25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_mips.c,v 1.46 2005/06/26 22:23:42 debug Exp $ |
* $Id: cpu_mips.c,v 1.61 2005/08/07 19:12:12 debug Exp $ |
29 |
* |
* |
30 |
* MIPS core CPU emulation. |
* MIPS core CPU emulation. |
31 |
*/ |
*/ |
95 |
static char *regnames[] = MIPS_REGISTER_NAMES; |
static char *regnames[] = MIPS_REGISTER_NAMES; |
96 |
static char *cop0_names[] = COP0_NAMES; |
static char *cop0_names[] = COP0_NAMES; |
97 |
|
|
|
|
|
98 |
#include "cpu_mips16.c" |
#include "cpu_mips16.c" |
99 |
|
|
100 |
|
|
156 |
cpu->cd.mips.cpu_type = cpu_type_defs[found]; |
cpu->cd.mips.cpu_type = cpu_type_defs[found]; |
157 |
cpu->name = cpu->cd.mips.cpu_type.name; |
cpu->name = cpu->cd.mips.cpu_type.name; |
158 |
cpu->byte_order = EMUL_LITTLE_ENDIAN; |
cpu->byte_order = EMUL_LITTLE_ENDIAN; |
159 |
cpu->cd.mips.gpr[MIPS_GPR_SP] = INITIAL_STACK_POINTER; |
cpu->cd.mips.gpr[MIPS_GPR_SP] = INITIAL_STACK_POINTER; |
160 |
|
cpu->update_translation_table = mips_update_translation_table; |
161 |
|
cpu->invalidate_translation_caches_paddr = |
162 |
|
mips_invalidate_translation_caches_paddr; |
163 |
|
|
164 |
|
if (cpu->cd.mips.cpu_type.isa_level <= 2 || |
165 |
|
cpu->cd.mips.cpu_type.isa_level == 32) |
166 |
|
cpu->is_32bit = 1; |
167 |
|
|
168 |
if (cpu_id == 0) |
if (cpu_id == 0) |
169 |
debug("%s", cpu->cd.mips.cpu_type.name); |
debug("%s", cpu->cd.mips.cpu_type.name); |
181 |
*/ |
*/ |
182 |
|
|
183 |
x = DEFAULT_PCACHE_SIZE; |
x = DEFAULT_PCACHE_SIZE; |
184 |
if (cpu->cd.mips.cpu_type.default_pdcache) |
if (cpu->cd.mips.cpu_type.pdcache) |
185 |
x = cpu->cd.mips.cpu_type.default_pdcache; |
x = cpu->cd.mips.cpu_type.pdcache; |
186 |
if (machine->cache_pdcache == 0) |
if (machine->cache_pdcache == 0) |
187 |
machine->cache_pdcache = x; |
machine->cache_pdcache = x; |
188 |
|
|
189 |
x = DEFAULT_PCACHE_SIZE; |
x = DEFAULT_PCACHE_SIZE; |
190 |
if (cpu->cd.mips.cpu_type.default_picache) |
if (cpu->cd.mips.cpu_type.picache) |
191 |
x = cpu->cd.mips.cpu_type.default_picache; |
x = cpu->cd.mips.cpu_type.picache; |
192 |
if (machine->cache_picache == 0) |
if (machine->cache_picache == 0) |
193 |
machine->cache_picache = x; |
machine->cache_picache = x; |
194 |
|
|
195 |
if (machine->cache_secondary == 0) |
if (machine->cache_secondary == 0) |
196 |
machine->cache_secondary = cpu->cd.mips.cpu_type.default_scache; |
machine->cache_secondary = cpu->cd.mips.cpu_type.scache; |
197 |
|
|
198 |
linesize = DEFAULT_PCACHE_LINESIZE; |
linesize = DEFAULT_PCACHE_LINESIZE; |
199 |
if (cpu->cd.mips.cpu_type.default_pdlinesize) |
if (cpu->cd.mips.cpu_type.pdlinesize) |
200 |
linesize = cpu->cd.mips.cpu_type.default_pdlinesize; |
linesize = cpu->cd.mips.cpu_type.pdlinesize; |
201 |
if (machine->cache_pdcache_linesize == 0) |
if (machine->cache_pdcache_linesize == 0) |
202 |
machine->cache_pdcache_linesize = linesize; |
machine->cache_pdcache_linesize = linesize; |
203 |
|
|
204 |
linesize = DEFAULT_PCACHE_LINESIZE; |
linesize = DEFAULT_PCACHE_LINESIZE; |
205 |
if (cpu->cd.mips.cpu_type.default_pilinesize) |
if (cpu->cd.mips.cpu_type.pilinesize) |
206 |
linesize = cpu->cd.mips.cpu_type.default_pilinesize; |
linesize = cpu->cd.mips.cpu_type.pilinesize; |
207 |
if (machine->cache_picache_linesize == 0) |
if (machine->cache_picache_linesize == 0) |
208 |
machine->cache_picache_linesize = linesize; |
machine->cache_picache_linesize = linesize; |
209 |
|
|
210 |
linesize = 0; |
linesize = 0; |
211 |
if (cpu->cd.mips.cpu_type.default_slinesize) |
if (cpu->cd.mips.cpu_type.slinesize) |
212 |
linesize = cpu->cd.mips.cpu_type.default_slinesize; |
linesize = cpu->cd.mips.cpu_type.slinesize; |
213 |
if (machine->cache_secondary_linesize == 0) |
if (machine->cache_secondary_linesize == 0) |
214 |
machine->cache_secondary_linesize = linesize; |
machine->cache_secondary_linesize = linesize; |
215 |
|
|
335 |
cpu->translate_address = translate_address_generic; |
cpu->translate_address = translate_address_generic; |
336 |
} |
} |
337 |
|
|
338 |
|
/* Testing: */ |
339 |
|
cpu->cd.mips.host_load = zeroed_alloc(1048576 * |
340 |
|
sizeof(unsigned char *)); |
341 |
|
cpu->cd.mips.host_store = zeroed_alloc(1048576 * |
342 |
|
sizeof(unsigned char *)); |
343 |
|
cpu->cd.mips.host_load_orig = cpu->cd.mips.host_load; |
344 |
|
cpu->cd.mips.host_store_orig = cpu->cd.mips.host_store; |
345 |
|
|
346 |
return 1; |
return 1; |
347 |
} |
} |
348 |
|
|
487 |
printf("\n"); |
printf("\n"); |
488 |
break; |
break; |
489 |
default: |
default: |
490 |
/* TODO: MIPS32 doesn't need 0x16llx */ |
switch (m->cpus[i]->cd.mips.cpu_type.mmu_model) { |
491 |
if (m->cpus[i]->cd.mips.cpu_type.mmu_model == MMU10K) |
case MMU10K: |
492 |
printf("vaddr=0x%1x..%011llx ", |
printf("vaddr=0x%1x..%011llx ", |
493 |
(int) (hi >> 60), |
(int) (hi >> 60), |
494 |
(long long) (hi&ENTRYHI_VPN2_MASK_R10K)); |
(long long) (hi&ENTRYHI_VPN2_MASK_R10K)); |
495 |
else |
break; |
496 |
|
case MMU32: |
497 |
|
printf("vaddr=0x%08x ", (int)(hi&ENTRYHI_VPN2_MASK)); |
498 |
|
break; |
499 |
|
default:/* R4000 etc. */ |
500 |
printf("vaddr=0x%1x..%010llx ", |
printf("vaddr=0x%1x..%010llx ", |
501 |
(int) (hi >> 60), |
(int) (hi >> 60), |
502 |
(long long) (hi&ENTRYHI_VPN2_MASK)); |
(long long) (hi&ENTRYHI_VPN2_MASK)); |
503 |
|
} |
504 |
if (hi & TLB_G) |
if (hi & TLB_G) |
505 |
printf("(global): "); |
printf("(global): "); |
506 |
else |
else |
552 |
/* Print index, random, and wired: */ |
/* Print index, random, and wired: */ |
553 |
printf("cpu%i: (", i); |
printf("cpu%i: (", i); |
554 |
|
|
555 |
if (m->cpus[i]->cd.mips.cpu_type.isa_level < 3 || |
if (m->cpus[i]->is_32bit) |
|
m->cpus[i]->cd.mips.cpu_type.isa_level == 32) |
|
556 |
printf("index=0x%08x random=0x%08x", |
printf("index=0x%08x random=0x%08x", |
557 |
(int)m->cpus[i]->cd.mips.coproc[0]->reg[COP0_INDEX], |
(int)m->cpus[i]->cd.mips.coproc[0]->reg[COP0_INDEX], |
558 |
(int)m->cpus[i]->cd.mips.coproc[0]->reg[COP0_RANDOM]); |
(int)m->cpus[i]->cd.mips.coproc[0]->reg[COP0_RANDOM]); |
574 |
j, |
j, |
575 |
(int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi, |
(int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi, |
576 |
(int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0); |
(int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0); |
577 |
else if (m->cpus[i]->cd.mips.cpu_type.isa_level < 3 || |
else if (m->cpus[i]->is_32bit) |
|
m->cpus[i]->cd.mips.cpu_type.isa_level == 32) |
|
578 |
printf("%3i: hi=0x%08x mask=0x%08x " |
printf("%3i: hi=0x%08x mask=0x%08x " |
579 |
"lo0=0x%08x lo1=0x%08x\n", j, |
"lo0=0x%08x lo1=0x%08x\n", j, |
580 |
(int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi, |
(int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi, |
744 |
if (cpu->machine->ncpus > 1 && running) |
if (cpu->machine->ncpus > 1 && running) |
745 |
debug("cpu%i: ", cpu->cpu_id); |
debug("cpu%i: ", cpu->cpu_id); |
746 |
|
|
747 |
if (cpu->cd.mips.cpu_type.isa_level < 3 || |
if (cpu->is_32bit) |
|
cpu->cd.mips.cpu_type.isa_level == 32) |
|
748 |
debug("%08x", (int)dumpaddr); |
debug("%08x", (int)dumpaddr); |
749 |
else |
else |
750 |
debug("%016llx", (long long)dumpaddr); |
debug("%016llx", (long long)dumpaddr); |
944 |
debug("syscall"); |
debug("syscall"); |
945 |
break; |
break; |
946 |
case SPECIAL_BREAK: |
case SPECIAL_BREAK: |
947 |
/* TODO: imm, as in 'syscall'? */ |
imm = (((instr[3] << 24) + (instr[2] << 16) + |
948 |
debug("break"); |
(instr[1] << 8) + instr[0]) >> 6) & 0xfffff; |
949 |
|
if (imm != 0) |
950 |
|
debug("break\t0x%05x", imm); |
951 |
|
else |
952 |
|
debug("break"); |
953 |
break; |
break; |
954 |
case SPECIAL_MFSA: |
case SPECIAL_MFSA: |
955 |
rd = (instr[1] >> 3) & 31; |
rd = (instr[1] >> 3) & 31; |
989 |
|
|
990 |
debug("%s,", regname(cpu->machine, rs)); |
debug("%s,", regname(cpu->machine, rs)); |
991 |
|
|
992 |
if (cpu->cd.mips.cpu_type.isa_level < 3 || |
if (cpu->is_32bit) |
|
cpu->cd.mips.cpu_type.isa_level == 32) |
|
993 |
debug("0x%08x", (int)addr); |
debug("0x%08x", (int)addr); |
994 |
else |
else |
995 |
debug("0x%016llx", (long long)addr); |
debug("0x%016llx", (long long)addr); |
1069 |
cpu->cd.mips.gpr[rs] + imm, &offset); |
cpu->cd.mips.gpr[rs] + imm, &offset); |
1070 |
|
|
1071 |
/* LWC3 is PREF in the newer ISA levels: */ |
/* LWC3 is PREF in the newer ISA levels: */ |
1072 |
/* TODO: Which ISAs? cpu->cd.mips.cpu_type.isa_level >= 4? */ |
/* TODO: Which ISAs? IV? V? 32? 64? */ |
1073 |
if (hi6 == HI6_LWC3) { |
if (cpu->cd.mips.cpu_type.isa_level >= 4 && hi6 == HI6_LWC3) { |
1074 |
debug("pref\t0x%x,%i(%s)", |
debug("pref\t0x%x,%i(%s)", |
1075 |
rt, imm, regname(cpu->machine, rs)); |
rt, imm, regname(cpu->machine, rs)); |
1076 |
|
|
1099 |
if (running) { |
if (running) { |
1100 |
debug("\t["); |
debug("\t["); |
1101 |
|
|
1102 |
if (cpu->cd.mips.cpu_type.isa_level < 3 || |
if (cpu->is_32bit) |
|
cpu->cd.mips.cpu_type.isa_level == 32) |
|
1103 |
debug("0x%08x", (int)(cpu->cd.mips.gpr[rs] + imm)); |
debug("0x%08x", (int)(cpu->cd.mips.gpr[rs] + imm)); |
1104 |
else |
else |
1105 |
debug("0x%016llx", |
debug("0x%016llx", |
1123 |
symbol = get_symbol_name(&cpu->machine->symbol_context, |
symbol = get_symbol_name(&cpu->machine->symbol_context, |
1124 |
addr, &offset); |
addr, &offset); |
1125 |
debug("%s\t0x", hi6_names[hi6]); |
debug("%s\t0x", hi6_names[hi6]); |
1126 |
if (cpu->cd.mips.cpu_type.isa_level < 3 || |
if (cpu->is_32bit) |
|
cpu->cd.mips.cpu_type.isa_level == 32) |
|
1127 |
debug("%08x", (int)addr); |
debug("%08x", (int)addr); |
1128 |
else |
else |
1129 |
debug("%016llx", (long long)addr); |
debug("%016llx", (long long)addr); |
1251 |
|
|
1252 |
addr = (dumpaddr + 4) + (imm << 2); |
addr = (dumpaddr + 4) + (imm << 2); |
1253 |
|
|
1254 |
if (cpu->cd.mips.cpu_type.isa_level < 3 || |
if (cpu->is_32bit) |
|
cpu->cd.mips.cpu_type.isa_level == 32) |
|
1255 |
debug("0x%08x", (int)addr); |
debug("0x%08x", (int)addr); |
1256 |
else |
else |
1257 |
debug("0x%016llx", (long long)addr); |
debug("0x%016llx", (long long)addr); |
1284 |
uint64_t offset; |
uint64_t offset; |
1285 |
char *symbol; |
char *symbol; |
1286 |
|
|
1287 |
bits32 = (cpu->cd.mips.cpu_type.isa_level < 3 || |
bits32 = cpu->is_32bit; |
|
cpu->cd.mips.cpu_type.isa_level == 32)? 1 : 0; |
|
1288 |
|
|
1289 |
if (gprs) { |
if (gprs) { |
1290 |
/* Special registers (pc, hi/lo) first: */ |
/* Special registers (pc, hi/lo) first: */ |
1294 |
if (bits32) |
if (bits32) |
1295 |
debug("cpu%i: pc = %08x", cpu->cpu_id, (int)cpu->pc); |
debug("cpu%i: pc = %08x", cpu->cpu_id, (int)cpu->pc); |
1296 |
else |
else |
1297 |
debug("cpu%i: pc = %016llx", |
debug("cpu%i: pc = 0x%016llx", |
1298 |
cpu->cpu_id, (long long)cpu->pc); |
cpu->cpu_id, (long long)cpu->pc); |
1299 |
|
|
1300 |
debug(" <%s>\n", symbol != NULL? symbol : |
debug(" <%s>\n", symbol != NULL? symbol : |
1304 |
debug("cpu%i: hi = %08x lo = %08x\n", |
debug("cpu%i: hi = %08x lo = %08x\n", |
1305 |
cpu->cpu_id, (int)cpu->cd.mips.hi, (int)cpu->cd.mips.lo); |
cpu->cpu_id, (int)cpu->cd.mips.hi, (int)cpu->cd.mips.lo); |
1306 |
else |
else |
1307 |
debug("cpu%i: hi = %016llx lo = %016llx\n", |
debug("cpu%i: hi = 0x%016llx lo = 0x%016llx\n", |
1308 |
cpu->cpu_id, (long long)cpu->cd.mips.hi, |
cpu->cpu_id, (long long)cpu->cd.mips.hi, |
1309 |
(long long)cpu->cd.mips.lo); |
(long long)cpu->cd.mips.lo); |
1310 |
|
|
1326 |
for (i=0; i<32; i++) { |
for (i=0; i<32; i++) { |
1327 |
if ((i & 3) == 0) |
if ((i & 3) == 0) |
1328 |
debug("cpu%i:", cpu->cpu_id); |
debug("cpu%i:", cpu->cpu_id); |
1329 |
debug(" %3s = %08x", regname(cpu->machine, i), |
if (i == MIPS_GPR_ZERO) |
1330 |
(int)cpu->cd.mips.gpr[i]); |
debug(" "); |
1331 |
|
else |
1332 |
|
debug(" %3s = %08x", regname(cpu->machine, i), (int)cpu->cd.mips.gpr[i]); |
1333 |
if ((i & 3) == 3) |
if ((i & 3) == 3) |
1334 |
debug("\n"); |
debug("\n"); |
1335 |
} |
} |
1336 |
} else { |
} else { |
1337 |
/* 64-bit: */ |
/* 64-bit: */ |
1338 |
for (i=0; i<32; i++) { |
for (i=0; i<32; i++) { |
1339 |
|
int r = (i >> 1) + ((i & 1) << 4); |
1340 |
if ((i & 1) == 0) |
if ((i & 1) == 0) |
1341 |
debug("cpu%i:", cpu->cpu_id); |
debug("cpu%i:", cpu->cpu_id); |
1342 |
debug(" %3s = %016llx", |
if (r == MIPS_GPR_ZERO) |
1343 |
regname(cpu->machine, i), |
debug(" "); |
1344 |
(long long)cpu->cd.mips.gpr[i]); |
else |
1345 |
|
debug(" %3s = 0x%016llx", regname(cpu->machine, r), (long long)cpu->cd.mips.gpr[r]); |
1346 |
if ((i & 1) == 1) |
if ((i & 1) == 1) |
1347 |
debug("\n"); |
debug("\n"); |
1348 |
} |
} |
1378 |
|
|
1379 |
if (bits32) |
if (bits32) |
1380 |
debug("=%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]); |
debug("=%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]); |
1381 |
else |
else { |
1382 |
debug(" = 0x%016llx", (long long) |
if (coprocnr == 0 && (i == COP0_COUNT |
1383 |
cpu->cd.mips.coproc[coprocnr]->reg[i]); |
|| i == COP0_COMPARE || i == COP0_INDEX |
1384 |
|
|| i == COP0_RANDOM || i == COP0_WIRED)) |
1385 |
|
debug(" = 0x%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]); |
1386 |
|
else |
1387 |
|
debug(" = 0x%016llx", (long long) |
1388 |
|
cpu->cd.mips.coproc[coprocnr]->reg[i]); |
1389 |
|
} |
1390 |
|
|
1391 |
if ((i & nm1) == nm1) |
if ((i & nm1) == nm1) |
1392 |
debug("\n"); |
debug("\n"); |
1397 |
i = 31; |
i = 31; |
1398 |
} |
} |
1399 |
|
|
1400 |
|
if (coprocnr == 0 && cpu->cd.mips.cpu_type.isa_level >= 32) { |
1401 |
|
debug("cpu%i: ", cpu->cpu_id); |
1402 |
|
debug("config_select1 = 0x"); |
1403 |
|
if (cpu->is_32bit) |
1404 |
|
debug("%08x", (int)cpu->cd.mips.cop0_config_select1); |
1405 |
|
else |
1406 |
|
debug("%016llx", (long long)cpu->cd.mips.cop0_config_select1); |
1407 |
|
debug("\n"); |
1408 |
|
} |
1409 |
|
|
1410 |
/* Floating point control registers: */ |
/* Floating point control registers: */ |
1411 |
if (coprocnr == 1) { |
if (coprocnr == 1) { |
1412 |
for (i=0; i<32; i++) |
for (i=0; i<32; i++) |
1426 |
} |
} |
1427 |
|
|
1428 |
|
|
1429 |
/* |
#define DYNTRANS_FUNCTION_TRACE mips_cpu_functioncall_trace |
1430 |
* show_trace(): |
#define DYNTRANS_MIPS |
1431 |
* |
#define DYNTRANS_ARCH mips |
1432 |
* Show trace tree. This function should be called every time |
#include "cpu_dyntrans.c" |
1433 |
* a function is called. cpu->cd.mips.trace_tree_depth is increased here |
#undef DYNTRANS_MIPS |
1434 |
* and should not be increased by the caller. |
#undef DYNTRANS_ARCH |
1435 |
* |
#undef DYNTRANS_FUNCTION_TRACE |
|
* Note: This function should not be called if show_trace_tree == 0. |
|
|
*/ |
|
|
static void show_trace(struct cpu *cpu, uint64_t addr) |
|
|
{ |
|
|
uint64_t offset; |
|
|
int x, n_args_to_print; |
|
|
char strbuf[50]; |
|
|
char *symbol; |
|
|
|
|
|
cpu->cd.mips.trace_tree_depth ++; |
|
|
|
|
|
if (cpu->machine->ncpus > 1) |
|
|
debug("cpu%i:", cpu->cpu_id); |
|
|
|
|
|
symbol = get_symbol_name(&cpu->machine->symbol_context, addr, &offset); |
|
|
|
|
|
for (x=0; x<cpu->cd.mips.trace_tree_depth; x++) |
|
|
debug(" "); |
|
|
|
|
|
/* debug("<%s>\n", symbol!=NULL? symbol : "no symbol"); */ |
|
|
|
|
|
if (symbol != NULL) |
|
|
debug("<%s(", symbol); |
|
|
else { |
|
|
debug("<0x"); |
|
|
if (cpu->cd.mips.cpu_type.isa_level < 3 || |
|
|
cpu->cd.mips.cpu_type.isa_level == 32) |
|
|
debug("%08x", (int)addr); |
|
|
else |
|
|
debug("%016llx", (long long)addr); |
|
|
debug("("); |
|
|
} |
|
|
|
|
|
/* |
|
|
* TODO: The number of arguments and the symbol type of each |
|
|
* argument should be taken from the symbol table, in some way. |
|
|
* |
|
|
* The MIPS binary calling convention is that the first 4 |
|
|
* arguments are in registers a0..a3. |
|
|
* |
|
|
* Choose a value greater than 4 (eg 5) to print all values in |
|
|
* the A0..A3 registers and then add a ".." to indicate that |
|
|
* there might be more arguments. |
|
|
*/ |
|
|
n_args_to_print = 5; |
|
|
|
|
|
for (x=0; x<n_args_to_print; x++) { |
|
|
int64_t d = cpu->cd.mips.gpr[x + MIPS_GPR_A0]; |
|
|
|
|
|
if (d > -256 && d < 256) |
|
|
debug("%i", (int)d); |
|
|
else if (memory_points_to_string(cpu, cpu->mem, d, 1)) |
|
|
debug("\"%s\"", memory_conv_to_string(cpu, |
|
|
cpu->mem, d, strbuf, sizeof(strbuf))); |
|
|
else { |
|
|
if (cpu->cd.mips.cpu_type.isa_level < 3 || |
|
|
cpu->cd.mips.cpu_type.isa_level == 32) |
|
|
debug("0x%x", (int)d); |
|
|
else |
|
|
debug("0x%llx", (long long)d); |
|
|
} |
|
|
|
|
|
if (x < n_args_to_print - 1) |
|
|
debug(","); |
|
|
|
|
|
/* Cannot go beyound MIPS_GPR_A3: */ |
|
|
if (x == 3) |
|
|
break; |
|
|
} |
|
|
|
|
|
if (n_args_to_print > 4) |
|
|
debug(".."); |
|
|
|
|
|
debug(")>\n"); |
|
|
} |
|
1436 |
|
|
1437 |
|
|
1438 |
/* |
/* |
1517 |
if (!quiet_mode) { |
if (!quiet_mode) { |
1518 |
uint64_t offset; |
uint64_t offset; |
1519 |
int x; |
int x; |
1520 |
char *symbol = get_symbol_name( |
char *symbol = get_symbol_name(&cpu->machine->symbol_context, |
1521 |
&cpu->machine->symbol_context, cpu->cd.mips.pc_last, &offset); |
cpu->cd.mips.pc_last, &offset); |
1522 |
|
|
1523 |
debug("[ "); |
debug("[ "); |
1524 |
if (cpu->machine->ncpus > 1) |
if (cpu->machine->ncpus > 1) |
1546 |
} |
} |
1547 |
break; |
break; |
1548 |
default: |
default: |
1549 |
debug(" vaddr=0x%016llx", (long long)vaddr); |
if (cpu->is_32bit) |
1550 |
|
debug(" vaddr=0x%08x", (int)vaddr); |
1551 |
|
else |
1552 |
|
debug(" vaddr=0x%016llx", (long long)vaddr); |
1553 |
} |
} |
1554 |
|
|
1555 |
debug(" pc=%08llx ", (long long)cpu->cd.mips.pc_last); |
if (cpu->is_32bit) |
1556 |
|
debug(" pc=0x%08x ", (int)cpu->cd.mips.pc_last); |
1557 |
|
else |
1558 |
|
debug(" pc=0x%016llx ", (long long)cpu->cd.mips.pc_last); |
1559 |
|
|
1560 |
if (symbol != NULL) |
if (symbol != NULL) |
1561 |
debug("<%s> ]\n", symbol); |
debug("<%s> ]\n", symbol); |
1570 |
fatal("[ "); |
fatal("[ "); |
1571 |
if (cpu->machine->ncpus > 1) |
if (cpu->machine->ncpus > 1) |
1572 |
fatal("cpu%i: ", cpu->cpu_id); |
fatal("cpu%i: ", cpu->cpu_id); |
1573 |
fatal("warning: LOW reference vaddr=0x%08llx, exception %s, " |
fatal("warning: LOW reference: vaddr="); |
1574 |
"pc=%08llx <%s> ]\n", (long long)vaddr, |
if (cpu->is_32bit) |
1575 |
exception_names[exccode], (long long)cpu->cd.mips.pc_last, |
fatal("0x%08x", (int)vaddr); |
1576 |
symbol? symbol : "(no symbol)"); |
else |
1577 |
|
fatal("0x%016llx", (long long)vaddr); |
1578 |
|
fatal(", exception %s, pc=", exception_names[exccode]); |
1579 |
|
if (cpu->is_32bit) |
1580 |
|
fatal("0x%08x", (int)cpu->cd.mips.pc_last); |
1581 |
|
else |
1582 |
|
fatal("0x%016llx", (long long)cpu->cd.mips.pc_last); |
1583 |
|
fatal(" <%s> ]\n", symbol? symbol : "(no symbol)"); |
1584 |
|
|
1585 |
#ifdef TRACE_NULL_CRASHES |
#ifdef TRACE_NULL_CRASHES |
1586 |
/* This can be useful for debugging kernel bugs: */ |
/* This can be useful for debugging kernel bugs: */ |
1599 |
} |
} |
1600 |
|
|
1601 |
/* Clear the exception code bits of the cause register... */ |
/* Clear the exception code bits of the cause register... */ |
1602 |
if (exc_model == EXC3K) { |
if (exc_model == EXC3K) |
1603 |
reg[COP0_CAUSE] &= ~R2K3K_CAUSE_EXCCODE_MASK; |
reg[COP0_CAUSE] &= ~R2K3K_CAUSE_EXCCODE_MASK; |
1604 |
#if 0 |
else |
|
if (exccode >= 16) { |
|
|
fatal("exccode = %i (there are only 16 exceptions on R3000 and lower)\n", exccode); |
|
|
cpu->running = 0; |
|
|
return; |
|
|
} |
|
|
#endif |
|
|
} else |
|
1605 |
reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK; |
reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK; |
1606 |
|
|
1607 |
/* ... and OR in the exception code: */ |
/* ... and OR in the exception code: */ |
1611 |
reg[COP0_CAUSE] &= ~CAUSE_CE_MASK; |
reg[COP0_CAUSE] &= ~CAUSE_CE_MASK; |
1612 |
reg[COP0_CAUSE] |= (coproc_nr << CAUSE_CE_SHIFT); |
reg[COP0_CAUSE] |= (coproc_nr << CAUSE_CE_SHIFT); |
1613 |
|
|
|
/* TODO: On R4000, vaddr should NOT be set on bus errors!!! */ |
|
|
#if 0 |
|
|
if (exccode == EXCEPTION_DBE) { |
|
|
reg[COP0_BADVADDR] = vaddr; |
|
|
/* sign-extend vaddr, if it is 32-bit */ |
|
|
if ((vaddr >> 32) == 0 && (vaddr & 0x80000000ULL)) |
|
|
reg[COP0_BADVADDR] |= |
|
|
0xffffffff00000000ULL; |
|
|
} |
|
|
#endif |
|
|
|
|
1614 |
if (tlb || (exccode >= EXCEPTION_MOD && exccode <= EXCEPTION_ADES) || |
if (tlb || (exccode >= EXCEPTION_MOD && exccode <= EXCEPTION_ADES) || |
1615 |
exccode == EXCEPTION_VCEI || exccode == EXCEPTION_VCED) { |
exccode == EXCEPTION_VCEI || exccode == EXCEPTION_VCED) { |
1616 |
reg[COP0_BADVADDR] = vaddr; |
reg[COP0_BADVADDR] = vaddr; |
1874 |
for (i=0; i<cpu->machine->n_breakpoints; i++) |
for (i=0; i<cpu->machine->n_breakpoints; i++) |
1875 |
if (cached_pc == cpu->machine->breakpoint_addr[i]) { |
if (cached_pc == cpu->machine->breakpoint_addr[i]) { |
1876 |
fatal("Breakpoint reached, pc=0x"); |
fatal("Breakpoint reached, pc=0x"); |
1877 |
if (cpu->cd.mips.cpu_type.isa_level < 3 || |
if (cpu->is_32bit) |
|
cpu->cd.mips.cpu_type.isa_level == 32) |
|
1878 |
fatal("%08x", (int)cached_pc); |
fatal("%08x", (int)cached_pc); |
1879 |
else |
else |
1880 |
fatal("%016llx", (long long)cached_pc); |
fatal("%016llx", (long long)cached_pc); |
1976 |
/* no need to update cached_pc, as we're returning */ |
/* no need to update cached_pc, as we're returning */ |
1977 |
cpu->cd.mips.delay_slot = NOT_DELAYED; |
cpu->cd.mips.delay_slot = NOT_DELAYED; |
1978 |
|
|
1979 |
if (!quiet_mode_cached && |
if (cpu->machine->show_trace_tree) |
1980 |
cpu->machine->show_trace_tree) |
cpu_functioncall_trace_return(cpu); |
|
cpu->cd.mips.trace_tree_depth --; |
|
1981 |
|
|
1982 |
/* TODO: how many instrs should this count as? */ |
/* TODO: how many instrs should this count as? */ |
1983 |
return 10; |
return 10; |
1990 |
* registers are sign-extended: (Slow, but might be useful |
* registers are sign-extended: (Slow, but might be useful |
1991 |
* to detect bugs that have to do with sign-extension.) |
* to detect bugs that have to do with sign-extension.) |
1992 |
*/ |
*/ |
1993 |
if (cpu->cd.mips.cpu_type.isa_level < 3 || cpu->cd.mips.cpu_type.isa_level == 32) { |
if (cpu->is_32bit) |
1994 |
int warning = 0; |
int warning = 0; |
1995 |
uint64_t x; |
uint64_t x; |
1996 |
|
|
2083 |
} |
} |
2084 |
#endif |
#endif |
2085 |
|
|
|
|
|
|
|
|
2086 |
#ifdef BINTRANS |
#ifdef BINTRANS |
2087 |
if ((single_step || instruction_trace_cached) |
if ((single_step || instruction_trace_cached) |
2088 |
&& cpu->machine->bintrans_enable) |
&& cpu->machine->bintrans_enable) |
2089 |
cpu->cd.mips.dont_run_next_bintrans = 1; |
cpu->cd.mips.dont_run_next_bintrans = 1; |
2090 |
#endif |
#endif |
2091 |
|
|
|
|
|
2092 |
if (!quiet_mode_cached) { |
if (!quiet_mode_cached) { |
2093 |
/* Dump CPU registers for debugging: */ |
/* Dump CPU registers for debugging: */ |
2094 |
if (cpu->machine->register_dump) { |
if (cpu->machine->register_dump) { |
2095 |
debug("\n"); |
debug("\n"); |
2096 |
mips_cpu_register_dump(cpu, 1, 0x1); |
mips_cpu_register_dump(cpu, 1, 0x1); |
2097 |
} |
} |
2098 |
|
} |
2099 |
|
|
2100 |
/* Trace tree: */ |
/* Trace tree: */ |
2101 |
if (cpu->machine->show_trace_tree && cpu->cd.mips.show_trace_delay > 0) { |
if (cpu->machine->show_trace_tree && cpu->cd.mips.show_trace_delay > 0) { |
2102 |
cpu->cd.mips.show_trace_delay --; |
cpu->cd.mips.show_trace_delay --; |
2103 |
if (cpu->cd.mips.show_trace_delay == 0) |
if (cpu->cd.mips.show_trace_delay == 0) |
2104 |
show_trace(cpu, cpu->cd.mips.show_trace_addr); |
cpu_functioncall_trace(cpu, cpu->cd.mips.show_trace_addr); |
|
} |
|
2105 |
} |
} |
2106 |
|
|
2107 |
#ifdef MFHILO_DELAY |
#ifdef MFHILO_DELAY |
2198 |
/* NOTE: This only works on the host if offset is |
/* NOTE: This only works on the host if offset is |
2199 |
aligned correctly! (TODO) */ |
aligned correctly! (TODO) */ |
2200 |
*(uint32_t *)instr = *(uint32_t *) |
*(uint32_t *)instr = *(uint32_t *) |
2201 |
(cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xfff)); |
(cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xffc)); |
2202 |
#ifdef BINTRANS |
#ifdef BINTRANS |
2203 |
cpu->cd.mips.pc_bintrans_paddr_valid = 1; |
cpu->cd.mips.pc_bintrans_paddr_valid = 1; |
2204 |
cpu->cd.mips.pc_bintrans_paddr = |
cpu->cd.mips.pc_bintrans_paddr = |
2268 |
* swap if necessary: |
* swap if necessary: |
2269 |
*/ |
*/ |
2270 |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
if (cpu->byte_order == EMUL_BIG_ENDIAN) { |
2271 |
instrword = instr[0]; instr[0] = instr[3]; |
int tmp = instr[0]; instr[0] = instr[3]; instr[3] = tmp; |
2272 |
instr[3] = instrword; |
tmp = instr[1]; instr[1] = instr[2]; instr[2] = tmp; |
|
instrword = instr[1]; instr[1] = instr[2]; |
|
|
instr[2] = instrword; |
|
2273 |
} |
} |
2274 |
} |
} |
2275 |
|
|
2475 |
cpu->cd.mips.delay_slot = TO_BE_DELAYED; |
cpu->cd.mips.delay_slot = TO_BE_DELAYED; |
2476 |
cpu->cd.mips.delay_jmpaddr = cpu->cd.mips.gpr[rs]; |
cpu->cd.mips.delay_jmpaddr = cpu->cd.mips.gpr[rs]; |
2477 |
|
|
2478 |
if (!quiet_mode_cached && cpu->machine->show_trace_tree |
if (cpu->machine->show_trace_tree && rs == 31) |
2479 |
&& rs == 31) { |
cpu_functioncall_trace_return(cpu); |
|
cpu->cd.mips.trace_tree_depth --; |
|
|
} |
|
2480 |
|
|
2481 |
return 1; |
return 1; |
2482 |
case SPECIAL_JALR: |
case SPECIAL_JALR: |
2493 |
cpu->cd.mips.gpr[rd] = cached_pc + 4; |
cpu->cd.mips.gpr[rd] = cached_pc + 4; |
2494 |
/* already increased by 4 earlier */ |
/* already increased by 4 earlier */ |
2495 |
|
|
2496 |
if (!quiet_mode_cached && cpu->machine->show_trace_tree |
if (cpu->machine->show_trace_tree && rd == 31) { |
|
&& rd == 31) { |
|
2497 |
cpu->cd.mips.show_trace_delay = 2; |
cpu->cd.mips.show_trace_delay = 2; |
2498 |
cpu->cd.mips.show_trace_addr = tmpvalue; |
cpu->cd.mips.show_trace_addr = tmpvalue; |
2499 |
} |
} |
2714 |
cpu->cd.mips.hi |= 0xffffffff00000000ULL; |
cpu->cd.mips.hi |= 0xffffffff00000000ULL; |
2715 |
break; |
break; |
2716 |
} |
} |
2717 |
/* |
if (special6 == SPECIAL_DMULT) { |
2718 |
* TODO: I'm too tired to think now. DMULT is probably |
/* 64x64 = 128 bit multiplication, signed. */ |
2719 |
* correct, but is DMULTU? (Unsigned 64x64 multiply.) |
uint64_t s1 = cpu->cd.mips.gpr[rt]; |
2720 |
* Or, hm, perhaps it is dmult which is incorrect. |
uint64_t s2 = cpu->cd.mips.gpr[rs]; |
2721 |
*/ |
int n_negative = 0; |
2722 |
if (special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU) { |
int i; |
2723 |
/* 64x64 = 128 bit multiplication: SLOW!!! TODO */ |
|
2724 |
uint64_t i, low_add, high_add; |
if ((int64_t)s1 < 0) { |
2725 |
|
s1 = -(int64_t)s1; |
2726 |
|
n_negative ++; |
2727 |
|
} |
2728 |
|
if ((int64_t)s2 < 0) { |
2729 |
|
s2 = -(int64_t)s2; |
2730 |
|
n_negative ++; |
2731 |
|
} |
2732 |
|
|
2733 |
cpu->cd.mips.lo = cpu->cd.mips.hi = 0; |
cpu->cd.mips.lo = cpu->cd.mips.hi = 0; |
2734 |
|
|
2735 |
for (i=0; i<64; i++) { |
for (i=0; i<64; i++) { |
2736 |
uint64_t bit = cpu->cd.mips.gpr[rt] & ((uint64_t)1 << i); |
int bit = (s1 & 0x8000000000000000ULL)? 1 : 0; |
2737 |
|
s1 <<= 1; |
2738 |
|
/* If bit in s1 set, then add s2 to hi/lo: */ |
2739 |
if (bit) { |
if (bit) { |
2740 |
/* Add cpu->cd.mips.gpr[rs] to hi and lo: */ |
uint64_t old_lo = cpu->cd.mips.lo; |
2741 |
low_add = (cpu->cd.mips.gpr[rs] << i); |
cpu->cd.mips.lo += s2; |
2742 |
high_add = (cpu->cd.mips.gpr[rs] >> (64-i)); |
if (cpu->cd.mips.lo < old_lo) |
|
if (i==0) /* WEIRD BUG in the compiler? Or maybe I'm just stupid */ |
|
|
high_add = 0; /* these lines are necessary, a >> 64 doesn't seem to do anything */ |
|
|
if (cpu->cd.mips.lo + low_add < cpu->cd.mips.lo) |
|
2743 |
cpu->cd.mips.hi ++; |
cpu->cd.mips.hi ++; |
2744 |
cpu->cd.mips.lo += low_add; |
} |
2745 |
cpu->cd.mips.hi += high_add; |
if (i != 63) { |
2746 |
|
cpu->cd.mips.hi <<= 1; |
2747 |
|
cpu->cd.mips.hi += |
2748 |
|
(cpu->cd.mips.lo & 0x8000000000000000ULL) ? 1 : 0; |
2749 |
|
cpu->cd.mips.lo <<= 1; |
2750 |
|
} |
2751 |
|
} |
2752 |
|
|
2753 |
|
if (n_negative == 1) { |
2754 |
|
cpu->cd.mips.hi = -(int64_t)cpu->cd.mips.hi; |
2755 |
|
cpu->cd.mips.lo = -(int64_t)cpu->cd.mips.lo; |
2756 |
|
if ((int64_t)cpu->cd.mips.lo < 0) |
2757 |
|
cpu->cd.mips.hi --; |
2758 |
|
} |
2759 |
|
break; |
2760 |
|
} |
2761 |
|
if (special6 == SPECIAL_DMULTU) { |
2762 |
|
/* 64x64 = 128 bit multiplication, unsigned. */ |
2763 |
|
uint64_t s1 = cpu->cd.mips.gpr[rt]; |
2764 |
|
uint64_t s2 = cpu->cd.mips.gpr[rs]; |
2765 |
|
int i; |
2766 |
|
|
2767 |
|
cpu->cd.mips.lo = cpu->cd.mips.hi = 0; |
2768 |
|
|
2769 |
|
for (i=0; i<64; i++) { |
2770 |
|
int bit = (s1 & 0x8000000000000000ULL)? 1 : 0; |
2771 |
|
s1 <<= 1; |
2772 |
|
/* If bit in s1 set, then add s2 to hi/lo: */ |
2773 |
|
if (bit) { |
2774 |
|
uint64_t old_lo = cpu->cd.mips.lo; |
2775 |
|
cpu->cd.mips.lo += s2; |
2776 |
|
if (cpu->cd.mips.lo < old_lo) |
2777 |
|
cpu->cd.mips.hi ++; |
2778 |
|
} |
2779 |
|
if (i != 63) { |
2780 |
|
cpu->cd.mips.hi <<= 1; |
2781 |
|
cpu->cd.mips.hi += |
2782 |
|
(cpu->cd.mips.lo & 0x8000000000000000ULL) ? 1 : 0; |
2783 |
|
cpu->cd.mips.lo <<= 1; |
2784 |
} |
} |
2785 |
} |
} |
2786 |
break; |
break; |
2910 |
} |
} |
2911 |
return 1; |
return 1; |
2912 |
case SPECIAL_SYNC: |
case SPECIAL_SYNC: |
2913 |
imm = ((instr[1] & 7) << 2) + (instr[0] >> 6); |
/* imm = ((instr[1] & 7) << 2) + (instr[0] >> 6); */ |
2914 |
/* TODO: actually sync */ |
/* TODO: actually sync */ |
2915 |
|
|
2916 |
/* Clear the LLbit (at least on R10000): */ |
/* Clear the LLbit (at least on R10000): */ |
2931 |
mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0); |
mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0); |
2932 |
return 1; |
return 1; |
2933 |
case SPECIAL_MFSA: |
case SPECIAL_MFSA: |
2934 |
/* R5900? What on earth does this thing do? */ |
/* R5900? Move from shift amount register? */ |
2935 |
rd = (instr[1] >> 3) & 31; |
/* rd = (instr[1] >> 3) & 31; */ |
2936 |
/* TODO */ |
/* TODO */ |
2937 |
return 1; |
return 1; |
2938 |
case SPECIAL_MTSA: |
case SPECIAL_MTSA: |
2939 |
/* R5900? What on earth does this thing do? */ |
/* R5900? Move to shift amount register? */ |
2940 |
rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7); |
/* rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7); */ |
2941 |
/* TODO */ |
/* TODO */ |
2942 |
return 1; |
return 1; |
2943 |
default: |
default: |
2944 |
if (!instruction_trace_cached) { |
if (!instruction_trace_cached) { |
2945 |
fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t", |
fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t", |
2946 |
cpu->cpu_id, cpu->cd.mips.pc_last, |
cpu->cpu_id, (long long)cpu->cd.mips.pc_last, |
2947 |
instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu)); |
instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu)); |
2948 |
} |
} |
2949 |
fatal("unimplemented special6 = 0x%02x\n", special6); |
fatal("unimplemented special6 = 0x%02x\n", special6); |
3766 |
default: |
default: |
3767 |
if (!instruction_trace_cached) { |
if (!instruction_trace_cached) { |
3768 |
fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t", |
fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t", |
3769 |
cpu->cpu_id, cpu->cd.mips.pc_last, |
cpu->cpu_id, (long long)cpu->cd.mips.pc_last, |
3770 |
instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu)); |
instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu)); |
3771 |
} |
} |
3772 |
fatal("unimplemented regimm5 = 0x%02x\n", regimm5); |
fatal("unimplemented regimm5 = 0x%02x\n", regimm5); |
3793 |
cpu->cd.mips.delay_slot = TO_BE_DELAYED; |
cpu->cd.mips.delay_slot = TO_BE_DELAYED; |
3794 |
cpu->cd.mips.delay_jmpaddr = addr; |
cpu->cd.mips.delay_jmpaddr = addr; |
3795 |
|
|
3796 |
if (!quiet_mode_cached && cpu->machine->show_trace_tree && |
if (cpu->machine->show_trace_tree && hi6 == HI6_JAL) { |
|
hi6 == HI6_JAL) { |
|
3797 |
cpu->cd.mips.show_trace_delay = 2; |
cpu->cd.mips.show_trace_delay = 2; |
3798 |
cpu->cd.mips.show_trace_addr = addr; |
cpu->cd.mips.show_trace_addr = addr; |
3799 |
} |
} |
3870 |
|
|
3871 |
/* |
/* |
3872 |
* TODO: The cache instruction is implementation dependant. |
* TODO: The cache instruction is implementation dependant. |
|
* This is really ugly. |
|
3873 |
*/ |
*/ |
3874 |
|
|
|
#if 0 |
|
|
Remove this... |
|
|
|
|
|
/* if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) { */ |
|
|
/* printf("taghi=%08lx taglo=%08lx\n", |
|
|
(long)cp0->reg[COP0_TAGDATA_HI], |
|
|
(long)cp0->reg[COP0_TAGDATA_LO]); |
|
|
*/ |
|
|
if (cp0->reg[COP0_TAGDATA_HI] == 0 && |
|
|
cp0->reg[COP0_TAGDATA_LO] == 0) { |
|
|
/* Normal cache operation: */ |
|
|
cpu->r10k_cache_disable_TODO = 0; |
|
|
} else { |
|
|
/* Dislocate the cache: */ |
|
|
cpu->r10k_cache_disable_TODO = 1; |
|
|
} |
|
|
/* } */ |
|
|
#endif |
|
|
|
|
3875 |
/* |
/* |
3876 |
* Clear the LLbit (at least on R10000): |
* Clear the LLbit (at least on R10000): |
3877 |
* TODO: How about R4000? |
* TODO: How about R4000? |
4016 |
} else { |
} else { |
4017 |
if (!instruction_trace_cached) { |
if (!instruction_trace_cached) { |
4018 |
fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t", |
fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t", |
4019 |
cpu->cpu_id, cpu->cd.mips.pc_last, |
cpu->cpu_id, (long long)cpu->cd.mips.pc_last, |
4020 |
instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu)); |
instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu)); |
4021 |
} |
} |
4022 |
fatal("unimplemented special_2 = 0x%02x, rs=0x%02x rt=0x%02x rd=0x%02x\n", |
fatal("unimplemented special_2 = 0x%02x, rs=0x%02x rt=0x%02x rd=0x%02x\n", |
4028 |
default: |
default: |
4029 |
if (!instruction_trace_cached) { |
if (!instruction_trace_cached) { |
4030 |
fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t", |
fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t", |
4031 |
cpu->cpu_id, cpu->cd.mips.pc_last, |
cpu->cpu_id, (long long)cpu->cd.mips.pc_last, |
4032 |
instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu)); |
instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu)); |
4033 |
} |
} |
4034 |
fatal("unimplemented hi6 = 0x%02x\n", hi6); |
fatal("unimplemented hi6 = 0x%02x\n", hi6); |
4056 |
*/ |
*/ |
4057 |
void mips_cpu_dumpinfo(struct cpu *cpu) |
void mips_cpu_dumpinfo(struct cpu *cpu) |
4058 |
{ |
{ |
4059 |
|
int iadd = 4; |
4060 |
struct mips_cpu_type_def *ct = &cpu->cd.mips.cpu_type; |
struct mips_cpu_type_def *ct = &cpu->cd.mips.cpu_type; |
4061 |
|
|
4062 |
debug(" (%i-bit ", (ct->isa_level < 3 || |
debug_indentation(iadd); |
4063 |
ct->isa_level == 32)? 32 : 64); |
|
4064 |
|
debug("\n%i-bit %s (MIPS", |
4065 |
|
cpu->is_32bit? 32 : 64, |
4066 |
|
cpu->byte_order == EMUL_BIG_ENDIAN? "BE" : "LE"); |
4067 |
|
|
4068 |
|
switch (ct->isa_level) { |
4069 |
|
case 1: debug(" ISA I"); break; |
4070 |
|
case 2: debug(" ISA II"); break; |
4071 |
|
case 3: debug(" ISA III"); break; |
4072 |
|
case 4: debug(" ISA IV"); break; |
4073 |
|
case 5: debug(" ISA V"); break; |
4074 |
|
case 32: |
4075 |
|
case 64:debug("%i", ct->isa_level); break; |
4076 |
|
default:debug(" ISA level %i", ct->isa_level); |
4077 |
|
} |
4078 |
|
|
4079 |
debug("%s, ", cpu->byte_order == EMUL_BIG_ENDIAN? "BE" : "LE"); |
debug("), "); |
4080 |
|
if (ct->nr_of_tlb_entries) |
4081 |
|
debug("%i TLB entries", ct->nr_of_tlb_entries); |
4082 |
|
else |
4083 |
|
debug("no TLB"); |
4084 |
|
debug("\n"); |
4085 |
|
|
4086 |
debug("nTLB=%i", ct->nr_of_tlb_entries); |
if (ct->picache) { |
4087 |
|
debug("L1 I-cache: %i KB", (1 << ct->picache) / 1024); |
4088 |
|
if (ct->pilinesize) |
4089 |
|
debug(", %i bytes per line", 1 << ct->pilinesize); |
4090 |
|
if (ct->piways > 1) |
4091 |
|
debug(", %i-way", ct->piways); |
4092 |
|
else |
4093 |
|
debug(", direct-mapped"); |
4094 |
|
debug("\n"); |
4095 |
|
} |
4096 |
|
|
4097 |
if (ct->default_picache || ct->default_pdcache) |
if (ct->pdcache) { |
4098 |
debug(", I+D = %i+%i KB", |
debug("L1 D-cache: %i KB", (1 << ct->pdcache) / 1024); |
4099 |
(1 << ct->default_picache) / 1024, |
if (ct->pdlinesize) |
4100 |
(1 << ct->default_pdcache) / 1024); |
debug(", %i bytes per line", 1 << ct->pdlinesize); |
4101 |
|
if (ct->pdways > 1) |
4102 |
|
debug(", %i-way", ct->pdways); |
4103 |
|
else |
4104 |
|
debug(", direct-mapped"); |
4105 |
|
debug("\n"); |
4106 |
|
} |
4107 |
|
|
4108 |
if (ct->default_scache) { |
if (ct->scache) { |
4109 |
int kb = (1 << ct->default_scache) / 1024; |
int kb = (1 << ct->scache) / 1024; |
4110 |
debug(", L2 = %i %cB", |
debug("L2 cache: %i %s", |
4111 |
kb >= 1024? kb / 1024 : kb, |
kb >= 1024? kb / 1024 : kb, kb >= 1024? "MB":"KB"); |
4112 |
kb >= 1024? 'M' : 'K'); |
if (ct->slinesize) |
4113 |
|
debug(", %i bytes per line", 1 << ct->slinesize); |
4114 |
|
if (ct->sways > 1) |
4115 |
|
debug(", %i-way", ct->sways); |
4116 |
|
else |
4117 |
|
debug(", direct-mapped"); |
4118 |
|
debug("\n"); |
4119 |
} |
} |
4120 |
|
|
4121 |
debug(")\n"); |
debug_indentation(-iadd); |
4122 |
} |
} |
4123 |
|
|
4124 |
|
|
4144 |
} |
} |
4145 |
|
|
4146 |
|
|
4147 |
/* |
CPU_FAMILY_INIT(mips,"MIPS") |
|
* mips_cpu_family_init(): |
|
|
* |
|
|
* Fill in the cpu_family struct for MIPS. |
|
|
*/ |
|
|
int mips_cpu_family_init(struct cpu_family *fp) |
|
|
{ |
|
|
fp->name = "MIPS"; |
|
|
fp->cpu_new = mips_cpu_new; |
|
|
fp->list_available_types = mips_cpu_list_available_types; |
|
|
fp->register_match = mips_cpu_register_match; |
|
|
fp->disassemble_instr = mips_cpu_disassemble_instr; |
|
|
fp->register_dump = mips_cpu_register_dump; |
|
|
fp->run = mips_cpu_run; |
|
|
fp->dumpinfo = mips_cpu_dumpinfo; |
|
|
fp->show_full_statistics = mips_cpu_show_full_statistics; |
|
|
fp->tlbdump = mips_cpu_tlbdump; |
|
|
fp->interrupt = mips_cpu_interrupt; |
|
|
fp->interrupt_ack = mips_cpu_interrupt_ack; |
|
|
return 1; |
|
|
} |
|
4148 |
|
|
4149 |
|
|
4150 |
#endif /* ENABLE_MIPS */ |
#endif /* ENABLE_MIPS */ |