1 |
/* |
/* |
2 |
* Copyright (C) 2005-2006 Anders Gavare. All rights reserved. |
* Copyright (C) 2005-2007 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_dyntrans.c,v 1.132 2006/10/27 13:12:20 debug Exp $ |
* $Id: cpu_dyntrans.c,v 1.165 2007/06/15 21:43:53 debug Exp $ |
29 |
* |
* |
30 |
* Common dyntrans routines. Included from cpu_*.c. |
* Common dyntrans routines. Included from cpu_*.c. |
31 |
*/ |
*/ |
51 |
return; |
return; |
52 |
} |
} |
53 |
|
|
54 |
|
/* low_pc must be within the page! */ |
55 |
|
if (low_pc < 0 || low_pc > DYNTRANS_IC_ENTRIES_PER_PAGE) |
56 |
|
return; |
57 |
|
|
58 |
buf[0] = '\0'; |
buf[0] = '\0'; |
59 |
|
|
60 |
while ((ch = cpu->machine->statistics_fields[i]) != '\0') { |
while ((ch = cpu->machine->statistics_fields[i]) != '\0') { |
68 |
break; |
break; |
69 |
case 'p': |
case 'p': |
70 |
/* Physical program counter address: */ |
/* Physical program counter address: */ |
|
/* (low_pc must be within the page!) */ |
|
|
if (low_pc < 0 || |
|
|
low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE) |
|
|
strlcat(buf, "-", sizeof(buf)); |
|
71 |
cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *) |
cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *) |
72 |
cpu->cd.DYNTRANS_ARCH.cur_ic_page; |
cpu->cd.DYNTRANS_ARCH.cur_ic_page; |
73 |
a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr; |
a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr; |
76 |
a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT; |
a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT; |
77 |
if (cpu->is_32bit) |
if (cpu->is_32bit) |
78 |
snprintf(buf + strlen(buf), sizeof(buf), |
snprintf(buf + strlen(buf), sizeof(buf), |
79 |
"0x%016"PRIx32, (uint32_t)a); |
"0x%08"PRIx32, (uint32_t)a); |
80 |
else |
else |
81 |
snprintf(buf + strlen(buf), sizeof(buf), |
snprintf(buf + strlen(buf), sizeof(buf), |
82 |
"0x%016"PRIx64, (uint64_t)a); |
"0x%016"PRIx64, (uint64_t)a); |
83 |
break; |
break; |
84 |
case 'v': |
case 'v': |
85 |
/* Virtual program counter address: */ |
/* Virtual program counter address: */ |
|
/* (low_pc inside the page, or in a delay slot) */ |
|
|
if (low_pc < 0 || |
|
|
low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE + 2) |
|
|
strlcat(buf, "-", sizeof(buf)); |
|
86 |
a = cpu->pc; |
a = cpu->pc; |
87 |
a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << |
a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << |
88 |
DYNTRANS_INSTR_ALIGNMENT_SHIFT); |
DYNTRANS_INSTR_ALIGNMENT_SHIFT); |
89 |
a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT; |
a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT; |
90 |
if (cpu->is_32bit) |
if (cpu->is_32bit) |
91 |
snprintf(buf + strlen(buf), sizeof(buf), |
snprintf(buf + strlen(buf), sizeof(buf), |
92 |
"0x%016"PRIx32, (uint32_t)a); |
"0x%08"PRIx32, (uint32_t)a); |
93 |
else |
else |
94 |
snprintf(buf + strlen(buf), sizeof(buf), |
snprintf(buf + strlen(buf), sizeof(buf), |
95 |
"0x%016"PRIx64, (uint64_t)a); |
"0x%016"PRIx64, (uint64_t)a); |
105 |
#define S gather_statistics(cpu) |
#define S gather_statistics(cpu) |
106 |
|
|
107 |
|
|
108 |
#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH |
#if 1 |
|
#define I ic = cpu->cd.DYNTRANS_ARCH.next_ic; \ |
|
|
cpu->cd.DYNTRANS_ARCH.next_ic += ic->arg[0]; \ |
|
|
ic->f(cpu, ic); |
|
|
#else |
|
109 |
|
|
110 |
/* The normal instruction execution core: */ |
/* The normal instruction execution core: */ |
111 |
#define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); |
#define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); |
112 |
|
|
113 |
|
#else |
114 |
|
|
115 |
/* For heavy debugging: */ |
/* For heavy debugging: */ |
116 |
/* #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; \ |
#define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; \ |
117 |
{ \ |
{ \ |
118 |
int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \ |
int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \ |
119 |
(size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \ |
(size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \ |
122 |
cpu->cd.DYNTRANS_ARCH.cur_ic_page, \ |
cpu->cd.DYNTRANS_ARCH.cur_ic_page, \ |
123 |
ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \ |
ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \ |
124 |
} \ |
} \ |
125 |
ic->f(cpu, ic); */ |
ic->f(cpu, ic); |
126 |
|
|
127 |
|
#endif |
128 |
|
|
129 |
/* static long long nr_of_I_calls = 0; */ |
/* static long long nr_of_I_calls = 0; */ |
130 |
|
|
157 |
} \ |
} \ |
158 |
ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); } |
ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); } |
159 |
*/ |
*/ |
|
#endif |
|
160 |
#endif /* STATIC STUFF */ |
#endif /* STATIC STUFF */ |
161 |
|
|
162 |
|
|
260 |
any instruction for any ISA: */ |
any instruction for any ISA: */ |
261 |
unsigned char instr[1 << |
unsigned char instr[1 << |
262 |
DYNTRANS_INSTR_ALIGNMENT_SHIFT]; |
DYNTRANS_INSTR_ALIGNMENT_SHIFT]; |
|
#ifdef DYNTRANS_X86 |
|
|
cpu->cd.x86.cursegment = X86_S_CS; |
|
|
cpu->cd.x86.seg_override = 0; |
|
|
#endif |
|
263 |
if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0], |
if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0], |
264 |
sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) { |
sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) { |
265 |
fatal("XXX_run_instr(): could not read " |
fatal("XXX_run_instr(): could not read " |
301 |
I; |
I; |
302 |
|
|
303 |
n_instrs = 1; |
n_instrs = 1; |
|
} else if (cpu->machine->cycle_accurate) { |
|
|
/* Executing multiple instructions, and call devices' |
|
|
tick functions: */ |
|
|
n_instrs = 0; |
|
|
for (;;) { |
|
|
struct DYNTRANS_IC *ic; |
|
|
/* TODO: continue here */ |
|
|
int64_t cycles = cpu->cd.avr.extra_cycles; |
|
|
I; |
|
|
n_instrs += 1; |
|
|
cycles = cpu->cd.avr.extra_cycles - cycles + 1; |
|
|
/* The instruction took 'cycles' cycles. */ |
|
|
/* printf("A\n"); */ |
|
|
while (cycles-- > 0) |
|
|
cpu->machine->tick_func[1](cpu, cpu->machine->tick_extra[1]); |
|
|
/* printf("B\n"); */ |
|
|
|
|
|
if (n_instrs + cpu->n_translated_instrs >= |
|
|
N_SAFE_DYNTRANS_LIMIT) |
|
|
break; |
|
|
} |
|
304 |
} else if (cpu->machine->statistics_enabled) { |
} else if (cpu->machine->statistics_enabled) { |
305 |
/* Gather statistics while executing multiple instructions: */ |
/* Gather statistics while executing multiple instructions: */ |
306 |
n_instrs = 0; |
n_instrs = 0; |
319 |
break; |
break; |
320 |
} |
} |
321 |
} else { |
} else { |
322 |
/* Execute multiple instructions: */ |
/* |
323 |
int n = 0; |
* Execute multiple instructions: |
324 |
|
* |
325 |
|
* (This is the core dyntrans loop.) |
326 |
|
*/ |
327 |
|
n_instrs = 0; |
328 |
|
cpu->sampling = 1; |
329 |
|
|
330 |
for (;;) { |
for (;;) { |
331 |
struct DYNTRANS_IC *ic; |
struct DYNTRANS_IC *ic; |
332 |
|
|
338 |
|
|
339 |
I; I; I; I; I; I; I; I; I; I; |
I; I; I; I; I; I; I; I; I; I; |
340 |
|
|
341 |
n += 60; |
I; I; I; I; I; I; I; I; I; I; |
342 |
|
I; I; I; I; I; I; I; I; I; I; |
343 |
|
I; I; I; I; I; I; I; I; I; I; |
344 |
|
I; I; I; I; I; I; I; I; I; I; |
345 |
|
I; I; I; I; I; I; I; I; I; I; |
346 |
|
|
347 |
if (n + cpu->n_translated_instrs >= |
I; I; I; I; I; I; I; I; I; I; |
348 |
N_SAFE_DYNTRANS_LIMIT) |
|
349 |
|
cpu->n_translated_instrs += 120; |
350 |
|
if (cpu->n_translated_instrs >= N_SAFE_DYNTRANS_LIMIT) |
351 |
break; |
break; |
352 |
} |
} |
353 |
n_instrs = n; |
|
354 |
|
cpu->sampling = 0; |
355 |
} |
} |
356 |
|
|
357 |
n_instrs += cpu->n_translated_instrs; |
n_instrs += cpu->n_translated_instrs; |
394 |
/* Not yet. TODO */ |
/* Not yet. TODO */ |
395 |
if (cpu->machine->emulated_hz > 0) { |
if (cpu->machine->emulated_hz > 0) { |
396 |
if (cpu->cd.mips.compare_interrupts_pending > 0) |
if (cpu->cd.mips.compare_interrupts_pending > 0) |
397 |
cpu_interrupt(cpu, 7); |
INTERRUPT_ASSERT( |
398 |
|
cpu->cd.mips.irq_compare); |
399 |
} else |
} else |
400 |
#endif |
#endif |
401 |
{ |
{ |
402 |
if (diff1 > 0 && diff2 <= 0) |
if (diff1 > 0 && diff2 <= 0) |
403 |
cpu_interrupt(cpu, 7); |
INTERRUPT_ASSERT( |
404 |
|
cpu->cd.mips.irq_compare); |
405 |
} |
} |
406 |
} |
} |
407 |
} |
} |
421 |
} |
} |
422 |
#endif |
#endif |
423 |
|
|
424 |
|
cpu->ninstrs += n_instrs; |
425 |
|
|
426 |
|
/* |
427 |
|
* Check if there are enough samples to decide whether or not to |
428 |
|
* perform native code generation: |
429 |
|
*/ |
430 |
|
if (cpu->sampling_curindex == N_PADDR_SAMPLES) { |
431 |
|
/* TODO: Check against known blocks, etc. */ |
432 |
|
|
433 |
|
cpu->sampling_curindex = 0; |
434 |
|
} |
435 |
|
|
436 |
/* Return the nr of instructions executed: */ |
/* Return the nr of instructions executed: */ |
437 |
return n_instrs; |
return n_instrs; |
438 |
} |
} |
450 |
*/ |
*/ |
451 |
void DYNTRANS_FUNCTION_TRACE(struct cpu *cpu, uint64_t f, int n_args) |
void DYNTRANS_FUNCTION_TRACE(struct cpu *cpu, uint64_t f, int n_args) |
452 |
{ |
{ |
453 |
|
int show_symbolic_function_name = 1; |
454 |
char strbuf[50]; |
char strbuf[50]; |
455 |
char *symbol; |
char *symbol; |
456 |
uint64_t ot; |
uint64_t ot; |
458 |
#if defined(DYNTRANS_ALPHA) || defined(DYNTRANS_SPARC) |
#if defined(DYNTRANS_ALPHA) || defined(DYNTRANS_SPARC) |
459 |
6 |
6 |
460 |
#else |
#else |
461 |
#ifdef DYNTRANS_SH |
#if defined(DYNTRANS_SH) || defined(DYNTRANS_M88K) |
462 |
8 /* Both for 32-bit and 64-bit SuperH */ |
8 /* Both for 32-bit and 64-bit SuperH, and M88K */ |
463 |
#else |
#else |
464 |
4 /* Default value for most archs */ |
4 /* Default value for most archs */ |
465 |
#endif |
#endif |
471 |
n_args_to_print = n_args; |
n_args_to_print = n_args; |
472 |
} |
} |
473 |
|
|
474 |
|
#ifdef DYNTRANS_M88K |
475 |
|
/* Special hack for M88K userspace: */ |
476 |
|
if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE)) |
477 |
|
show_symbolic_function_name = 0; |
478 |
|
#endif |
479 |
|
|
480 |
/* |
/* |
481 |
* TODO: The type of each argument should be taken from the symbol |
* TODO: The type of each argument should be taken from the symbol |
482 |
* table, in some way. |
* table, in some way. |
489 |
* than were passed in register. |
* than were passed in register. |
490 |
*/ |
*/ |
491 |
for (x=0; x<n_args_to_print; x++) { |
for (x=0; x<n_args_to_print; x++) { |
492 |
int64_t d; |
int64_t d = cpu->cd.DYNTRANS_ARCH. |
|
#if defined(DYNTRANS_X86) || defined(DYNTRANS_TRANSPUTER) |
|
|
d = 0; /* TODO */ |
|
|
#else |
|
|
/* Args in registers: */ |
|
|
d = cpu->cd.DYNTRANS_ARCH. |
|
493 |
#ifdef DYNTRANS_ALPHA |
#ifdef DYNTRANS_ALPHA |
494 |
r[ALPHA_A0 |
r[ALPHA_A0 |
495 |
#endif |
#endif |
501 |
they go downwards, ie. 22,23 and so on */ |
they go downwards, ie. 22,23 and so on */ |
502 |
r[24 |
r[24 |
503 |
#endif |
#endif |
|
#ifdef DYNTRANS_AVR32 |
|
|
r[0 /* TODO */ |
|
|
#endif |
|
|
#ifdef DYNTRANS_HPPA |
|
|
r[0 /* TODO */ |
|
|
#endif |
|
|
#ifdef DYNTRANS_I960 |
|
|
r[0 /* TODO */ |
|
|
#endif |
|
|
#ifdef DYNTRANS_IA64 |
|
|
r[0 /* TODO */ |
|
|
#endif |
|
|
#ifdef DYNTRANS_M68K |
|
|
d[0 /* TODO */ |
|
|
#endif |
|
504 |
#ifdef DYNTRANS_MIPS |
#ifdef DYNTRANS_MIPS |
505 |
gpr[MIPS_GPR_A0 |
gpr[MIPS_GPR_A0 |
506 |
#endif |
#endif |
507 |
|
#ifdef DYNTRANS_M88K |
508 |
|
r[2 /* r2..r9 */ |
509 |
|
#endif |
510 |
#ifdef DYNTRANS_PPC |
#ifdef DYNTRANS_PPC |
511 |
gpr[3 |
gpr[3 |
512 |
#endif |
#endif |
|
#ifdef DYNTRANS_RCA180X |
|
|
r[0 /* TODO */ |
|
|
#endif |
|
513 |
#ifdef DYNTRANS_SH |
#ifdef DYNTRANS_SH |
514 |
r[4 /* NetBSD seems to use 4? But 2 seems |
r[4 /* NetBSD seems to use 4? But 2 seems |
515 |
to be used by other code? TODO */ |
to be used by other code? TODO */ |
518 |
r[8 /* o0..o5 */ |
r[8 /* o0..o5 */ |
519 |
#endif |
#endif |
520 |
+ x]; |
+ x]; |
521 |
#endif |
|
522 |
symbol = get_symbol_name(&cpu->machine->symbol_context, d, &ot); |
symbol = get_symbol_name(&cpu->machine->symbol_context, d, &ot); |
523 |
|
|
524 |
if (d > -256 && d < 256) |
if (d > -256 && d < 256) |
526 |
else if (memory_points_to_string(cpu, cpu->mem, d, 1)) |
else if (memory_points_to_string(cpu, cpu->mem, d, 1)) |
527 |
fatal("\"%s\"", memory_conv_to_string(cpu, |
fatal("\"%s\"", memory_conv_to_string(cpu, |
528 |
cpu->mem, d, strbuf, sizeof(strbuf))); |
cpu->mem, d, strbuf, sizeof(strbuf))); |
529 |
else if (symbol != NULL && ot == 0) |
else if (symbol != NULL && ot == 0 && |
530 |
|
show_symbolic_function_name) |
531 |
fatal("&%s", symbol); |
fatal("&%s", symbol); |
532 |
else { |
else { |
533 |
if (cpu->is_32bit) |
if (cpu->is_32bit) |
547 |
|
|
548 |
|
|
549 |
|
|
550 |
|
#ifdef DYNTRANS_TIMER_SAMPLE_TICK |
551 |
|
/* |
552 |
|
* XXX_timer_sample_tick(): |
553 |
|
* |
554 |
|
* Gathers statistics about which translation blocks are being executed. |
555 |
|
* This can then be used to calculate if it is worth the effort to perform |
556 |
|
* native code generation (which is assumed to have a large overhead, but |
557 |
|
* will result in faster code). |
558 |
|
*/ |
559 |
|
void DYNTRANS_TIMER_SAMPLE_TICK(struct timer *timer, void *extra) |
560 |
|
{ |
561 |
|
struct cpu *cpu = extra; |
562 |
|
struct DYNTRANS_IC *next_ic; |
563 |
|
size_t low_pc; |
564 |
|
uint64_t paddr; |
565 |
|
|
566 |
|
/* |
567 |
|
* Don't sample if: |
568 |
|
* |
569 |
|
* 1) Sampling is not enabled. It should only be enabled during |
570 |
|
* the core dyntrans loop. |
571 |
|
* 2) Enough samples have already been gathered. |
572 |
|
*/ |
573 |
|
|
574 |
|
if (!cpu->sampling || cpu->sampling_curindex == N_PADDR_SAMPLES) |
575 |
|
return; |
576 |
|
|
577 |
|
/* Get the physical address of the program counter: */ |
578 |
|
|
579 |
|
next_ic = cpu->cd.DYNTRANS_ARCH.next_ic; |
580 |
|
low_pc = ((size_t)next_ic - (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) |
581 |
|
/ sizeof(struct DYNTRANS_IC); |
582 |
|
|
583 |
|
/* Not possible to represent as a physical address? Then abort. */ |
584 |
|
if (low_pc > DYNTRANS_IC_ENTRIES_PER_PAGE) |
585 |
|
return; |
586 |
|
|
587 |
|
cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *) |
588 |
|
cpu->cd.DYNTRANS_ARCH.cur_ic_page; |
589 |
|
paddr = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr; |
590 |
|
paddr &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << |
591 |
|
DYNTRANS_INSTR_ALIGNMENT_SHIFT); |
592 |
|
paddr += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT; |
593 |
|
|
594 |
|
/* ... and finally add the sample to the sampling array: */ |
595 |
|
cpu->sampling_paddr[cpu->sampling_curindex ++] = paddr; |
596 |
|
} |
597 |
|
#endif /* DYNTRANS_TIMER_SAMPLE_TICK */ |
598 |
|
|
599 |
|
|
600 |
|
|
601 |
#ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE |
#ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE |
602 |
/* |
/* |
603 |
* XXX_tc_allocate_default_page(): |
* XXX_tc_allocate_default_page(): |
721 |
} |
} |
722 |
#else |
#else |
723 |
x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1; |
x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1; |
724 |
x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2; |
x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) |
725 |
x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) |
& mask2; |
726 |
& mask3; |
x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N |
727 |
|
- DYNTRANS_L3N)) & mask3; |
728 |
l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; |
l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; |
729 |
l3 = l2->l3[x2]; |
l3 = l2->l3[x2]; |
730 |
if (l3->host_load[x3] != NULL) { |
if (l3->host_load[x3] != NULL) { |
768 |
} |
} |
769 |
} |
} |
770 |
|
|
771 |
if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) { |
if (cpu->translation_cache_cur_ofs >= dyntrans_cache_size) { |
772 |
#ifdef UNSTABLE_DEVEL |
#ifdef UNSTABLE_DEVEL |
773 |
fatal("[ dyntrans: resetting the translation cache ]\n"); |
fatal("[ dyntrans: resetting the translation cache ]\n"); |
774 |
#endif |
#endif |
795 |
physpage_ofs = ppp->next_ofs; |
physpage_ofs = ppp->next_ofs; |
796 |
} |
} |
797 |
|
|
798 |
/* If the offset is 0 (or ppp is NULL), then we need to create a |
/* |
799 |
new "default" empty translation page. */ |
* If the offset is 0, then no translation exists yet for this |
800 |
|
* physical address. Let's create a new page, and add it first in |
801 |
|
* the chain. |
802 |
|
*/ |
803 |
|
if (physpage_ofs == 0) { |
804 |
|
uint32_t previous_first_page_in_chain; |
805 |
|
|
|
if (ppp == NULL) { |
|
806 |
/* fatal("CREATING page %lli (physaddr 0x%"PRIx64"), table " |
/* fatal("CREATING page %lli (physaddr 0x%"PRIx64"), table " |
807 |
"index %i\n", (long long)pagenr, (uint64_t)physaddr, |
"index %i\n", (long long)pagenr, (uint64_t)physaddr, |
808 |
(int)table_index); */ |
(int)table_index); */ |
809 |
|
|
810 |
|
previous_first_page_in_chain = *physpage_entryp; |
811 |
|
|
812 |
|
/* Insert the new page first in the chain: */ |
813 |
*physpage_entryp = physpage_ofs = |
*physpage_entryp = physpage_ofs = |
814 |
cpu->translation_cache_cur_ofs; |
cpu->translation_cache_cur_ofs; |
815 |
|
|
818 |
|
|
819 |
ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache |
ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache |
820 |
+ physpage_ofs); |
+ physpage_ofs); |
821 |
|
|
822 |
|
/* Point to the other pages in the same chain: */ |
823 |
|
ppp->next_ofs = previous_first_page_in_chain; |
824 |
} |
} |
825 |
|
|
826 |
|
/* Here, ppp points to a valid physical page struct. */ |
827 |
|
|
828 |
#ifdef MODE32 |
#ifdef MODE32 |
829 |
if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) |
if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) |
830 |
cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp; |
cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp; |
949 |
int x1, x2; |
int x1, x2; |
950 |
#endif |
#endif |
951 |
int i; |
int i; |
952 |
struct DYNTRANS_TC_PHYSPAGE *ppp = malloc(sizeof( |
struct DYNTRANS_TC_PHYSPAGE *ppp; |
|
struct DYNTRANS_TC_PHYSPAGE)); |
|
953 |
|
|
954 |
if (ppp == NULL) { |
CHECK_ALLOCATION(ppp = malloc(sizeof(struct DYNTRANS_TC_PHYSPAGE))); |
|
fprintf(stderr, "out of memory\n"); |
|
|
exit(1); |
|
|
} |
|
955 |
|
|
956 |
ppp->next_ofs = 0; |
ppp->next_ofs = 0; |
957 |
ppp->translations = 0; |
ppp->translations = 0; |
963 |
cpu->is_32bit? instr32(to_be_translated) : |
cpu->is_32bit? instr32(to_be_translated) : |
964 |
#endif |
#endif |
965 |
instr(to_be_translated); |
instr(to_be_translated); |
|
#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH |
|
|
ppp->ics[i].arg[0] = 0; |
|
|
#endif |
|
966 |
} |
} |
967 |
|
|
968 |
/* End-of-page: */ |
/* End-of-page: */ |
972 |
#endif |
#endif |
973 |
instr(end_of_page); |
instr(end_of_page); |
974 |
|
|
|
#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH |
|
|
ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].arg[0] = 0; |
|
|
#endif |
|
|
|
|
975 |
/* End-of-page-2, for delay-slot architectures: */ |
/* End-of-page-2, for delay-slot architectures: */ |
976 |
#ifdef DYNTRANS_DELAYSLOT |
#ifdef DYNTRANS_DELAYSLOT |
977 |
ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f = |
ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f = |
1293 |
physpage_entryp = &(((uint32_t *)cpu-> |
physpage_entryp = &(((uint32_t *)cpu-> |
1294 |
translation_cache)[table_index]); |
translation_cache)[table_index]); |
1295 |
physpage_ofs = *physpage_entryp; |
physpage_ofs = *physpage_entryp; |
1296 |
|
|
1297 |
|
/* Return immediately if there is no code translation |
1298 |
|
for this page. */ |
1299 |
|
if (physpage_ofs == 0) |
1300 |
|
return; |
1301 |
|
|
1302 |
prev_ppp = ppp = NULL; |
prev_ppp = ppp = NULL; |
1303 |
|
|
1304 |
/* Traverse the physical page chain: */ |
/* Traverse the physical page chain: */ |
1316 |
physpage_ofs = ppp->next_ofs; |
physpage_ofs = ppp->next_ofs; |
1317 |
} |
} |
1318 |
|
|
1319 |
|
/* If there is no translation, there is no need to go |
1320 |
|
on and try to remove it from the vph_tlb_entry array: */ |
1321 |
if (physpage_ofs == 0) |
if (physpage_ofs == 0) |
1322 |
ppp = NULL; |
return; |
1323 |
|
|
1324 |
#if 0 |
#if 0 |
1325 |
/* |
/* |
1423 |
#ifdef MODE32 |
#ifdef MODE32 |
1424 |
uint32_t index; |
uint32_t index; |
1425 |
vaddr_page &= 0xffffffffULL; |
vaddr_page &= 0xffffffffULL; |
1426 |
paddr_page &= 0xffffffffULL; |
|
1427 |
|
if (paddr_page > 0xffffffffULL) { |
1428 |
|
fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i" |
1429 |
|
" p=0x%016"PRIx64"\n", vaddr_page, host_page, writeflag, |
1430 |
|
paddr_page); |
1431 |
|
exit(1); |
1432 |
|
} |
1433 |
|
|
1434 |
/* fatal("update_translation_table(): v=0x%x, h=%p w=%i" |
/* fatal("update_translation_table(): v=0x%x, h=%p w=%i" |
1435 |
" p=0x%x\n", (int)vaddr_page, host_page, writeflag, |
" p=0x%x\n", (int)vaddr_page, host_page, writeflag, |
1436 |
(int)paddr_page); */ |
(int)paddr_page); */ |
1455 |
useraccess = 1; |
useraccess = 1; |
1456 |
} |
} |
1457 |
|
|
1458 |
|
#ifdef DYNTRANS_M88K |
1459 |
|
/* TODO */ |
1460 |
|
if (useraccess) |
1461 |
|
return; |
1462 |
|
#endif |
1463 |
|
|
1464 |
/* Scan the current TLB entries: */ |
/* Scan the current TLB entries: */ |
1465 |
|
|
1466 |
#ifdef MODE32 |
#ifdef MODE32 |
1534 |
cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next; |
cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next; |
1535 |
} else { |
} else { |
1536 |
int i; |
int i; |
1537 |
l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] = |
CHECK_ALLOCATION(l2 = |
1538 |
malloc(sizeof(struct DYNTRANS_L2_64_TABLE)); |
cpu->cd.DYNTRANS_ARCH.l1_64[x1] = malloc( |
1539 |
|
sizeof(struct DYNTRANS_L2_64_TABLE))); |
1540 |
l2->refcount = 0; |
l2->refcount = 0; |
1541 |
for (i=0; i<(1 << DYNTRANS_L2N); i++) |
for (i=0; i<(1 << DYNTRANS_L2N); i++) |
1542 |
l2->l3[i] = cpu->cd.DYNTRANS_ARCH. |
l2->l3[i] = cpu->cd.DYNTRANS_ARCH. |
1696 |
/* |
/* |
1697 |
* Check for breakpoints. |
* Check for breakpoints. |
1698 |
*/ |
*/ |
1699 |
if (!single_step_breakpoint) { |
if (!single_step_breakpoint && !cpu->translation_readahead) { |
1700 |
MODE_uint_t curpc = cpu->pc; |
MODE_uint_t curpc = cpu->pc; |
1701 |
int i; |
int i; |
1702 |
for (i=0; i<cpu->machine->n_breakpoints; i++) |
for (i=0; i<cpu->machine->breakpoints.n; i++) |
1703 |
if (curpc == (MODE_uint_t) |
if (curpc == (MODE_uint_t) |
1704 |
cpu->machine->breakpoint_addr[i]) { |
cpu->machine->breakpoints.addr[i]) { |
1705 |
if (!cpu->machine->instruction_trace) { |
if (!cpu->machine->instruction_trace) { |
1706 |
int old_quiet_mode = quiet_mode; |
int old_quiet_mode = quiet_mode; |
1707 |
quiet_mode = 0; |
quiet_mode = 0; |
1708 |
DISASSEMBLE(cpu, ib, 1, 0); |
DISASSEMBLE(cpu, ib, 1, 0); |
1709 |
quiet_mode = old_quiet_mode; |
quiet_mode = old_quiet_mode; |
1710 |
} |
} |
1711 |
|
#ifdef MODE32 |
1712 |
|
fatal("BREAKPOINT: pc = 0x%"PRIx32"\n(The " |
1713 |
|
"instruction has not yet executed.)\n", |
1714 |
|
(uint32_t)cpu->pc); |
1715 |
|
#else |
1716 |
fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The " |
fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The " |
1717 |
"instruction has not yet executed.)\n", |
"instruction has not yet executed.)\n", |
1718 |
(uint64_t)cpu->pc); |
(uint64_t)cpu->pc); |
1719 |
|
#endif |
1720 |
#ifdef DYNTRANS_DELAYSLOT |
#ifdef DYNTRANS_DELAYSLOT |
1721 |
if (cpu->delay_slot != NOT_DELAYED) |
if (cpu->delay_slot != NOT_DELAYED) |
1722 |
fatal("ERROR! Breakpoint in a delay" |
fatal("ERROR! Breakpoint in a delay" |
1757 |
* be converted into a single function call. |
* be converted into a single function call. |
1758 |
* |
* |
1759 |
* Note: Single-stepping or instruction tracing doesn't work with |
* Note: Single-stepping or instruction tracing doesn't work with |
1760 |
* instruction combination. For architectures with delay slots, |
* instruction combinations. For architectures with delay slots, |
1761 |
* we also ignore combinations if the delay slot is across a page |
* we also ignore combinations if the delay slot is across a page |
1762 |
* boundary. |
* boundary. |
1763 |
*/ |
*/ |
1788 |
} |
} |
1789 |
|
|
1790 |
/* ... and finally execute the translated instruction: */ |
/* ... and finally execute the translated instruction: */ |
1791 |
|
|
1792 |
|
/* (Except when doing read-ahead!) */ |
1793 |
|
if (cpu->translation_readahead) |
1794 |
|
return; |
1795 |
|
|
1796 |
|
/* |
1797 |
|
* Special case when single-stepping: Execute the translated |
1798 |
|
* instruction, but then replace it with a "to be translated" |
1799 |
|
* directly afterwards. |
1800 |
|
*/ |
1801 |
if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED) |
if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED) |
1802 |
#ifdef DYNTRANS_DELAYSLOT |
#ifdef DYNTRANS_DELAYSLOT |
1803 |
|| in_crosspage_delayslot |
|| in_crosspage_delayslot |
1804 |
#endif |
#endif |
1805 |
) { |
) { |
|
/* |
|
|
* Special case when single-stepping: Execute the translated |
|
|
* instruction, but then replace it with a "to be translated" |
|
|
* directly afterwards. |
|
|
*/ |
|
1806 |
single_step_breakpoint = 0; |
single_step_breakpoint = 0; |
|
#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH |
|
|
cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0]; |
|
|
#endif |
|
1807 |
ic->f(cpu, ic); |
ic->f(cpu, ic); |
1808 |
ic->f = |
ic->f = |
1809 |
#ifdef DYNTRANS_DUALMODE_32 |
#ifdef DYNTRANS_DUALMODE_32 |
1810 |
cpu->is_32bit? instr32(to_be_translated) : |
cpu->is_32bit? instr32(to_be_translated) : |
1811 |
#endif |
#endif |
1812 |
instr(to_be_translated); |
instr(to_be_translated); |
1813 |
#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH |
|
1814 |
ic->arg[0] = 0; |
return; |
1815 |
|
} |
1816 |
|
|
1817 |
|
/* Translation read-ahead: */ |
1818 |
|
if (!single_step && !cpu->machine->instruction_trace) { |
1819 |
|
/* Do readahead: */ |
1820 |
|
int i = 1; |
1821 |
|
uint64_t pagenr = DYNTRANS_ADDR_TO_PAGENR(cpu->pc); |
1822 |
|
uint64_t baseaddr = cpu->pc; |
1823 |
|
|
1824 |
|
cpu->translation_readahead = MAX_DYNTRANS_READAHEAD; |
1825 |
|
|
1826 |
|
while (DYNTRANS_ADDR_TO_PAGENR(baseaddr + |
1827 |
|
(i << DYNTRANS_INSTR_ALIGNMENT_SHIFT)) == pagenr && |
1828 |
|
cpu->translation_readahead > 0) { |
1829 |
|
void (*old_f)(struct cpu *, |
1830 |
|
struct DYNTRANS_IC *) = ic[i].f; |
1831 |
|
|
1832 |
|
/* Already translated? Then abort: */ |
1833 |
|
if (old_f != ( |
1834 |
|
#ifdef DYNTRANS_DUALMODE_32 |
1835 |
|
cpu->is_32bit? instr32(to_be_translated) : |
1836 |
#endif |
#endif |
1837 |
} else { |
instr(to_be_translated))) |
1838 |
#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH |
break; |
|
cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0]; |
|
1839 |
|
|
1840 |
/* Additional check, for variable length ISAs: */ |
/* Translate the instruction: */ |
1841 |
if (ic->arg[0] == 0) { |
ic[i].f(cpu, ic+i); |
1842 |
fatal("INTERNAL ERROR: instr len = 0!\n"); |
|
1843 |
goto bad; |
/* Translation failed? Then abort. */ |
1844 |
|
if (ic[i].f == old_f) |
1845 |
|
break; |
1846 |
|
|
1847 |
|
cpu->translation_readahead --; |
1848 |
|
++i; |
1849 |
} |
} |
|
#endif |
|
1850 |
|
|
1851 |
/* Finally finally :-), execute the instruction: */ |
cpu->translation_readahead = 0; |
|
ic->f(cpu, ic); |
|
1852 |
} |
} |
1853 |
|
|
1854 |
|
|
1855 |
|
/* |
1856 |
|
* Finally finally :-), execute the instruction. |
1857 |
|
* |
1858 |
|
* Note: The instruction might have changed during read-ahead, if |
1859 |
|
* instruction combinations are used. |
1860 |
|
*/ |
1861 |
|
|
1862 |
|
ic->f(cpu, ic); |
1863 |
|
|
1864 |
return; |
return; |
1865 |
|
|
1866 |
|
|
1868 |
* Nothing was translated. (Unimplemented or illegal instruction.) |
* Nothing was translated. (Unimplemented or illegal instruction.) |
1869 |
*/ |
*/ |
1870 |
|
|
1871 |
|
/* Clear the translation, in case it was "half-way" done: */ |
1872 |
|
ic->f = |
1873 |
|
#ifdef DYNTRANS_DUALMODE_32 |
1874 |
|
cpu->is_32bit? instr32(to_be_translated) : |
1875 |
|
#endif |
1876 |
|
instr(to_be_translated); |
1877 |
|
|
1878 |
|
if (cpu->translation_readahead) |
1879 |
|
return; |
1880 |
|
|
1881 |
quiet_mode = 0; |
quiet_mode = 0; |
1882 |
fatal("to_be_translated(): TODO: unimplemented instruction"); |
fatal("to_be_translated(): TODO: unimplemented instruction"); |
1883 |
|
|
1902 |
ic = cpu->cd.DYNTRANS_ARCH.next_ic = ¬hing_call; |
ic = cpu->cd.DYNTRANS_ARCH.next_ic = ¬hing_call; |
1903 |
cpu->cd.DYNTRANS_ARCH.next_ic ++; |
cpu->cd.DYNTRANS_ARCH.next_ic ++; |
1904 |
|
|
1905 |
|
#ifdef DYNTRANS_DELAYSLOT |
1906 |
|
/* Special hack: If the bad instruction was in a delay slot, |
1907 |
|
make sure that execution does not continue anyway: */ |
1908 |
|
if (cpu->delay_slot) |
1909 |
|
cpu->delay_slot |= EXCEPTION_IN_DELAY_SLOT; |
1910 |
|
#endif |
1911 |
|
|
1912 |
/* Execute the "nothing" instruction: */ |
/* Execute the "nothing" instruction: */ |
1913 |
ic->f(cpu, ic); |
ic->f(cpu, ic); |
1914 |
|
|