25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_sh.c,v 1.66 2007/04/13 07:06:31 debug Exp $ |
* $Id: cpu_sh.c,v 1.72 2007/04/28 09:44:35 debug Exp $ |
29 |
* |
* |
30 |
* Hitachi SuperH ("SH") CPU emulation. |
* Hitachi SuperH ("SH") CPU emulation. |
31 |
* |
* |
186 |
|
|
187 |
/* SH4-specific memory mapped registers, TLBs, caches, etc: */ |
/* SH4-specific memory mapped registers, TLBs, caches, etc: */ |
188 |
if (cpu->cd.sh.cpu_type.arch == 4) { |
if (cpu->cd.sh.cpu_type.arch == 4) { |
189 |
device_add(machine, "sh4"); |
cpu->cd.sh.pcic_pcibus = device_add(machine, "sh4"); |
190 |
|
|
191 |
/* |
/* |
192 |
* Interrupt Controller initial values, according to the |
* Interrupt Controller initial values, according to the |
274 |
void sh_cpu_interrupt_assert(struct interrupt *interrupt) |
void sh_cpu_interrupt_assert(struct interrupt *interrupt) |
275 |
{ |
{ |
276 |
struct cpu *cpu = interrupt->extra; |
struct cpu *cpu = interrupt->extra; |
277 |
int irq_nr = interrupt->line; |
unsigned int irq_nr = interrupt->line; |
278 |
int index = irq_nr / 0x20; |
unsigned int index = irq_nr / 0x20; |
279 |
int prio; |
unsigned int prio; |
280 |
|
|
281 |
/* Assert the interrupt, and check its priority level: */ |
/* Assert the interrupt, and check its priority level: */ |
282 |
cpu->cd.sh.int_prio_and_pending[index] |= SH_INT_ASSERTED; |
cpu->cd.sh.int_prio_and_pending[index] |= SH_INT_ASSERTED; |
465 |
|
|
466 |
if (coprocs & 1) { |
if (coprocs & 1) { |
467 |
/* Floating point: */ |
/* Floating point: */ |
468 |
debug("cpu%i: fpscr = 0x%08"PRIx32" fpul = 0x%08"PRIx32 |
debug("cpu%i: fpscr = 0x%08"PRIx32" (%s,%s,%s) fpul = 0x%08" |
469 |
"\n", x, cpu->cd.sh.fpscr, cpu->cd.sh.fpul); |
PRIx32"\n", x, cpu->cd.sh.fpscr, |
470 |
|
cpu->cd.sh.fpscr & SH_FPSCR_PR? "PR" : "!pr", |
471 |
|
cpu->cd.sh.fpscr & SH_FPSCR_SZ? "SZ" : "!sz", |
472 |
|
cpu->cd.sh.fpscr & SH_FPSCR_FR? "FR" : "!fr", |
473 |
|
cpu->cd.sh.fpul); |
474 |
|
|
475 |
for (i=0; i<SH_N_FPRS; i++) { |
for (i=0; i<SH_N_FPRS; i++) { |
476 |
if ((i % 4) == 0) |
if ((i % 4) == 0) |
733 |
int sh_cpu_disassemble_instr_compact(struct cpu *cpu, unsigned char *instr, |
int sh_cpu_disassemble_instr_compact(struct cpu *cpu, unsigned char *instr, |
734 |
int running, uint64_t dumpaddr) |
int running, uint64_t dumpaddr) |
735 |
{ |
{ |
736 |
uint64_t addr; |
char *symbol; |
737 |
|
uint64_t offset, addr; |
738 |
uint16_t iword; |
uint16_t iword; |
739 |
int hi4, lo4, lo8, r8, r4; |
int hi4, lo4, lo8, r8, r4; |
740 |
|
|
765 |
else if (lo4 == 0x6) |
else if (lo4 == 0x6) |
766 |
debug("mov.l\tr%i,@(r0,r%i)", r4, r8); |
debug("mov.l\tr%i,@(r0,r%i)", r4, r8); |
767 |
if (running) { |
if (running) { |
768 |
debug("\t; r0+r%i = 0x%08"PRIx32, r8, |
uint32_t addr = cpu->cd.sh.r[0] + |
769 |
cpu->cd.sh.r[0] + cpu->cd.sh.r[r8]); |
cpu->cd.sh.r[r8]; |
770 |
|
debug("\t; r0+r%i = ", r8); |
771 |
|
symbol = get_symbol_name( |
772 |
|
&cpu->machine->symbol_context, |
773 |
|
addr, &offset); |
774 |
|
if (symbol != NULL) |
775 |
|
debug("<%s>", symbol); |
776 |
|
else |
777 |
|
debug("0x%08"PRIx32, addr); |
778 |
} |
} |
779 |
debug("\n"); |
debug("\n"); |
780 |
} else if (lo4 == 0x7) |
} else if (lo4 == 0x7) |
795 |
else if (lo4 == 0xe) |
else if (lo4 == 0xe) |
796 |
debug("mov.l\t@(r0,r%i),r%i", r4, r8); |
debug("mov.l\t@(r0,r%i),r%i", r4, r8); |
797 |
if (running) { |
if (running) { |
798 |
debug("\t; r0+r%i = 0x%08"PRIx32, r4, |
uint32_t addr = cpu->cd.sh.r[0] + |
799 |
cpu->cd.sh.r[0] + cpu->cd.sh.r[r4]); |
cpu->cd.sh.r[r4]; |
800 |
|
debug("\t; r0+r%i = ", r4); |
801 |
|
symbol = get_symbol_name( |
802 |
|
&cpu->machine->symbol_context, |
803 |
|
addr, &offset); |
804 |
|
if (symbol != NULL) |
805 |
|
debug("<%s>", symbol); |
806 |
|
else |
807 |
|
debug("0x%08"PRIx32, addr); |
808 |
} |
} |
809 |
debug("\n"); |
debug("\n"); |
810 |
} else if (lo8 == 0x12) |
} else if (lo8 == 0x12) |
867 |
case 0x1: |
case 0x1: |
868 |
debug("mov.l\tr%i,@(%i,r%i)", r4, lo4 * 4, r8); |
debug("mov.l\tr%i,@(%i,r%i)", r4, lo4 * 4, r8); |
869 |
if (running) { |
if (running) { |
870 |
debug("\t; r%i+%i = 0x%08"PRIx32, r8, lo4 * 4, |
uint32_t addr = cpu->cd.sh.r[r8] + lo4 * 4; |
871 |
cpu->cd.sh.r[r8] + lo4 * 4); |
debug("\t; r%i+%i = ", r8, lo4 * 4); |
872 |
|
symbol = get_symbol_name(&cpu->machine->symbol_context, |
873 |
|
addr, &offset); |
874 |
|
if (symbol != NULL) |
875 |
|
debug("<%s>", symbol); |
876 |
|
else |
877 |
|
debug("0x%08"PRIx32, addr); |
878 |
} |
} |
879 |
debug("\n"); |
debug("\n"); |
880 |
break; |
break; |
1021 |
debug("shlr16\tr%i\n", r8); |
debug("shlr16\tr%i\n", r8); |
1022 |
else if (lo8 == 0x2a) |
else if (lo8 == 0x2a) |
1023 |
debug("lds\tr%i,pr\n", r8); |
debug("lds\tr%i,pr\n", r8); |
1024 |
else if (lo8 == 0x2b) |
else if (lo8 == 0x2b) { |
1025 |
debug("jmp\t@r%i\n", r8); |
debug("jmp\t@r%i", r8); |
1026 |
else if (lo8 == 0x2e) |
if (running) { |
1027 |
|
symbol = get_symbol_name( |
1028 |
|
&cpu->machine->symbol_context, |
1029 |
|
cpu->cd.sh.r[r8], &offset); |
1030 |
|
if (symbol != NULL) |
1031 |
|
debug("\t\t; <%s>", symbol); |
1032 |
|
} |
1033 |
|
debug("\n"); |
1034 |
|
} else if (lo8 == 0x2e) |
1035 |
debug("ldc\tr%i,vbr\n", r8); |
debug("ldc\tr%i,vbr\n", r8); |
1036 |
else if (lo8 == 0x33) |
else if (lo8 == 0x33) |
1037 |
debug("stc.l\tssr,@-r%i\n", r8); |
debug("stc.l\tssr,@-r%i\n", r8); |
1141 |
} else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) { |
} else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) { |
1142 |
addr = (int8_t)lo8; |
addr = (int8_t)lo8; |
1143 |
addr = dumpaddr + 4 + (addr << 1); |
addr = dumpaddr + 4 + (addr << 1); |
1144 |
debug("b%s%s\t0x%x\n", |
debug("b%s%s\t0x%x", |
1145 |
(r8 == 0x9 || r8 == 0xd)? "t" : "f", |
(r8 == 0x9 || r8 == 0xd)? "t" : "f", |
1146 |
(r8 == 0x9 || r8 == 0xb)? "" : "/s", (int)addr); |
(r8 == 0x9 || r8 == 0xb)? "" : "/s", (int)addr); |
1147 |
|
symbol = get_symbol_name(&cpu->machine->symbol_context, |
1148 |
|
addr, &offset); |
1149 |
|
if (symbol != NULL) |
1150 |
|
debug("\t; <%s>", symbol); |
1151 |
|
debug("\n"); |
1152 |
} else |
} else |
1153 |
debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8); |
debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8); |
1154 |
break; |
break; |
1156 |
case 0xd: |
case 0xd: |
1157 |
addr = lo8 * (hi4==9? 2 : 4); |
addr = lo8 * (hi4==9? 2 : 4); |
1158 |
addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4; |
addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4; |
1159 |
debug("mov.%s\t0x%x,r%i\n", hi4==9? "w":"l", (int)addr, r8); |
debug("mov.%s\t0x%x,r%i", hi4==9? "w":"l", (int)addr, r8); |
1160 |
|
symbol = get_symbol_name(&cpu->machine->symbol_context, |
1161 |
|
addr, &offset); |
1162 |
|
if (symbol != NULL) |
1163 |
|
debug("\t; <%s>", symbol); |
1164 |
|
debug("\n"); |
1165 |
break; |
break; |
1166 |
case 0xa: |
case 0xa: |
1167 |
case 0xb: |
case 0xb: |
1168 |
addr = (int32_t)(int16_t)((iword & 0xfff) << 4); |
addr = (int32_t)(int16_t)((iword & 0xfff) << 4); |
1169 |
addr = ((int32_t)addr >> 3); |
addr = ((int32_t)addr >> 3); |
1170 |
addr += dumpaddr + 4; |
addr += dumpaddr + 4; |
1171 |
debug("%s\t0x%x\n", hi4==0xa? "bra":"bsr", (int)addr); |
debug("%s\t0x%x", hi4==0xa? "bra":"bsr", (int)addr); |
1172 |
|
|
1173 |
|
symbol = get_symbol_name(&cpu->machine->symbol_context, |
1174 |
|
addr, &offset); |
1175 |
|
if (symbol != NULL) |
1176 |
|
debug("\t; <%s>", symbol); |
1177 |
|
debug("\n"); |
1178 |
break; |
break; |
1179 |
case 0xc: |
case 0xc: |
1180 |
if (r8 == 0x0) |
if (r8 == 0x0) |
1314 |
debug("fldi0\tfr%i\n", r8); |
debug("fldi0\tfr%i\n", r8); |
1315 |
else if (lo8 == 0x9d) |
else if (lo8 == 0x9d) |
1316 |
debug("fldi1\tfr%i\n", r8); |
debug("fldi1\tfr%i\n", r8); |
1317 |
|
else if (lo8 == 0xad) |
1318 |
|
debug("fcnvsd\tfpul,dr%i\n", r8); |
1319 |
|
else if (lo8 == 0xbd) |
1320 |
|
debug("fcnvds\tdr%i,fpul\n", r8); |
1321 |
else if ((iword & 0x01ff) == 0x00fd) |
else if ((iword & 0x01ff) == 0x00fd) |
1322 |
debug("fsca\tfpul,dr%i\n", r8); |
debug("fsca\tfpul,dr%i\n", r8); |
1323 |
else if (iword == 0xf3fd) |
else if (iword == 0xf3fd) |