25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_dyntrans.c,v 1.120 2006/08/12 11:43:12 debug Exp $ |
* $Id: cpu_dyntrans.c,v 1.132 2006/10/27 13:12:20 debug Exp $ |
29 |
* |
* |
30 |
* Common dyntrans routines. Included from cpu_*.c. |
* Common dyntrans routines. Included from cpu_*.c. |
31 |
*/ |
*/ |
45 |
int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t) |
int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t) |
46 |
cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC); |
cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC); |
47 |
|
|
48 |
|
if (cpu->machine->statistics_file == NULL) { |
49 |
|
fatal("statistics gathering with no filename set is" |
50 |
|
" meaningless\n"); |
51 |
|
return; |
52 |
|
} |
53 |
|
|
54 |
buf[0] = '\0'; |
buf[0] = '\0'; |
55 |
|
|
56 |
while ((ch = cpu->machine->statistics_fields[i]) != '\0') { |
while ((ch = cpu->machine->statistics_fields[i]) != '\0') { |
236 |
if (cpu->cd.ppc.irq_asserted && cpu->cd.ppc.msr & PPC_MSR_EE) |
if (cpu->cd.ppc.irq_asserted && cpu->cd.ppc.msr & PPC_MSR_EE) |
237 |
ppc_exception(cpu, PPC_EXCEPTION_EI); |
ppc_exception(cpu, PPC_EXCEPTION_EI); |
238 |
#endif |
#endif |
239 |
|
#ifdef DYNTRANS_SH |
240 |
|
if (cpu->cd.sh.int_to_assert > 0 && !(cpu->cd.sh.sr & SH_SR_BL) |
241 |
|
&& ((cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT) |
242 |
|
< cpu->cd.sh.int_level) |
243 |
|
sh_exception(cpu, 0, cpu->cd.sh.int_to_assert, 0); |
244 |
|
#endif |
245 |
|
|
246 |
cached_pc = cpu->pc; |
cached_pc = cpu->pc; |
247 |
|
|
261 |
cpu_register_dump(cpu->machine, cpu, 1, 0x1); |
cpu_register_dump(cpu->machine, cpu, 1, 0x1); |
262 |
} |
} |
263 |
if (cpu->machine->instruction_trace) { |
if (cpu->machine->instruction_trace) { |
264 |
|
/* TODO/Note: This must be large enough to hold |
265 |
|
any instruction for any ISA: */ |
266 |
|
unsigned char instr[1 << |
267 |
|
DYNTRANS_INSTR_ALIGNMENT_SHIFT]; |
268 |
#ifdef DYNTRANS_X86 |
#ifdef DYNTRANS_X86 |
|
unsigned char instr[17]; |
|
269 |
cpu->cd.x86.cursegment = X86_S_CS; |
cpu->cd.x86.cursegment = X86_S_CS; |
270 |
cpu->cd.x86.seg_override = 0; |
cpu->cd.x86.seg_override = 0; |
|
#else |
|
|
#ifdef DYNTRANS_M68K |
|
|
unsigned char instr[16]; /* TODO: 16? */ |
|
|
#else |
|
|
unsigned char instr[4]; /* General case... */ |
|
|
#endif |
|
271 |
#endif |
#endif |
|
|
|
272 |
if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0], |
if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0], |
273 |
sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) { |
sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) { |
274 |
fatal("XXX_run_instr(): could not read " |
fatal("XXX_run_instr(): could not read " |
275 |
"the instruction\n"); |
"the instruction\n"); |
276 |
} else { |
} else { |
277 |
cpu_disassemble_instr(cpu->machine, cpu, |
#ifdef DYNTRANS_DELAYSLOT |
278 |
instr, 1, 0); |
int len = |
279 |
|
#endif |
280 |
|
cpu_disassemble_instr( |
281 |
|
cpu->machine, cpu, instr, 1, 0); |
282 |
#ifdef DYNTRANS_DELAYSLOT |
#ifdef DYNTRANS_DELAYSLOT |
283 |
/* Show the instruction in the delay slot, |
/* Show the instruction in the delay slot, |
284 |
if any: */ |
if any: */ |
289 |
instr)) { |
instr)) { |
290 |
int saved_delayslot = cpu->delay_slot; |
int saved_delayslot = cpu->delay_slot; |
291 |
cpu->memory_rw(cpu, cpu->mem, cached_pc |
cpu->memory_rw(cpu, cpu->mem, cached_pc |
292 |
+ sizeof(instr), &instr[0], |
+ len, &instr[0], |
293 |
sizeof(instr), MEM_READ, |
sizeof(instr), MEM_READ, |
294 |
CACHE_INSTRUCTION); |
CACHE_INSTRUCTION); |
295 |
cpu->delay_slot = DELAYED; |
cpu->delay_slot = DELAYED; |
296 |
cpu->pc += sizeof(instr); |
cpu->pc += len; |
297 |
cpu_disassemble_instr(cpu->machine, |
cpu_disassemble_instr(cpu->machine, |
298 |
cpu, instr, 1, 0); |
cpu, instr, 1, 0); |
299 |
cpu->delay_slot = saved_delayslot; |
cpu->delay_slot = saved_delayslot; |
300 |
cpu->pc -= sizeof(instr); |
cpu->pc -= len; |
301 |
} |
} |
302 |
#endif |
#endif |
303 |
} |
} |
405 |
(int32_t) (old + n_instrs); |
(int32_t) (old + n_instrs); |
406 |
diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] - |
diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] - |
407 |
cpu->cd.mips.coproc[0]->reg[COP0_COUNT]; |
cpu->cd.mips.coproc[0]->reg[COP0_COUNT]; |
408 |
if (cpu->cd.mips.compare_register_set && diff1>0 && diff2<=0) |
|
409 |
cpu_interrupt(cpu, 7); |
if (cpu->cd.mips.compare_register_set) { |
410 |
|
#if 1 |
411 |
|
/* Not yet. TODO */ |
412 |
|
if (cpu->machine->emulated_hz > 0) { |
413 |
|
if (cpu->cd.mips.compare_interrupts_pending > 0) |
414 |
|
cpu_interrupt(cpu, 7); |
415 |
|
} else |
416 |
|
#endif |
417 |
|
{ |
418 |
|
if (diff1 > 0 && diff2 <= 0) |
419 |
|
cpu_interrupt(cpu, 7); |
420 |
|
} |
421 |
|
} |
422 |
} |
} |
423 |
#endif |
#endif |
424 |
#ifdef DYNTRANS_PPC |
#ifdef DYNTRANS_PPC |
461 |
6 |
6 |
462 |
#else |
#else |
463 |
#ifdef DYNTRANS_SH |
#ifdef DYNTRANS_SH |
464 |
8 |
8 /* Both for 32-bit and 64-bit SuperH */ |
465 |
#else |
#else |
466 |
4 /* Default value for most archs */ |
4 /* Default value for most archs */ |
467 |
#endif |
#endif |
502 |
they go downwards, ie. 22,23 and so on */ |
they go downwards, ie. 22,23 and so on */ |
503 |
r[24 |
r[24 |
504 |
#endif |
#endif |
505 |
|
#ifdef DYNTRANS_AVR32 |
506 |
|
r[0 /* TODO */ |
507 |
|
#endif |
508 |
#ifdef DYNTRANS_HPPA |
#ifdef DYNTRANS_HPPA |
509 |
r[0 /* TODO */ |
r[0 /* TODO */ |
510 |
#endif |
#endif |
523 |
#ifdef DYNTRANS_PPC |
#ifdef DYNTRANS_PPC |
524 |
gpr[3 |
gpr[3 |
525 |
#endif |
#endif |
526 |
|
#ifdef DYNTRANS_RCA180X |
527 |
|
r[0 /* TODO */ |
528 |
|
#endif |
529 |
#ifdef DYNTRANS_SH |
#ifdef DYNTRANS_SH |
530 |
r[2 |
r[4 /* NetBSD seems to use 4? But 2 seems |
531 |
|
to be used by other code? TODO */ |
532 |
#endif |
#endif |
533 |
#ifdef DYNTRANS_SPARC |
#ifdef DYNTRANS_SPARC |
534 |
r[24 |
r[8 /* o0..o5 */ |
535 |
#endif |
#endif |
536 |
+ x]; |
+ x]; |
537 |
#endif |
#endif |
1371 |
void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page, |
void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page, |
1372 |
unsigned char *host_page, int writeflag, uint64_t paddr_page) |
unsigned char *host_page, int writeflag, uint64_t paddr_page) |
1373 |
{ |
{ |
1374 |
int found, r, lowest_index, useraccess = 0; |
int found, r, useraccess = 0; |
1375 |
|
|
1376 |
#ifdef MODE32 |
#ifdef MODE32 |
1377 |
uint32_t index; |
uint32_t index; |
1402 |
} |
} |
1403 |
|
|
1404 |
/* Scan the current TLB entries: */ |
/* Scan the current TLB entries: */ |
|
lowest_index = 0; |
|
1405 |
|
|
1406 |
#ifdef MODE32 |
#ifdef MODE32 |
1407 |
/* |
/* |
1433 |
#endif |
#endif |
1434 |
|
|
1435 |
if (found < 0) { |
if (found < 0) { |
1436 |
|
/* Create the new TLB entry, overwriting a "random" entry: */ |
1437 |
static unsigned int x = 0; |
static unsigned int x = 0; |
1438 |
lowest_index = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES; |
r = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES; |
|
} |
|
1439 |
|
|
|
if (found < 0) { |
|
|
/* Create the new TLB entry, overwriting the oldest one: */ |
|
|
r = lowest_index; |
|
1440 |
if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) { |
if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) { |
1441 |
/* This one has to be invalidated first: */ |
/* This one has to be invalidated first: */ |
1442 |
DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, |
DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, |