25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_dyntrans.c,v 1.113 2006/07/21 20:09:15 debug Exp $ |
* $Id: cpu_dyntrans.c,v 1.120 2006/08/12 11:43:12 debug Exp $ |
29 |
* |
* |
30 |
* Common dyntrans routines. Included from cpu_*.c. |
* Common dyntrans routines. Included from cpu_*.c. |
31 |
*/ |
*/ |
223 |
#endif |
#endif |
224 |
#ifdef DYNTRANS_PPC |
#ifdef DYNTRANS_PPC |
225 |
if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) { |
if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) { |
226 |
ppc_exception(cpu, PPC_EXCEPTION_DEC); |
if (!(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC)) |
227 |
|
ppc_exception(cpu, PPC_EXCEPTION_DEC); |
228 |
cpu->cd.ppc.dec_intr_pending = 0; |
cpu->cd.ppc.dec_intr_pending = 0; |
229 |
} |
} |
230 |
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) |
234 |
cached_pc = cpu->pc; |
cached_pc = cpu->pc; |
235 |
|
|
236 |
cpu->n_translated_instrs = 0; |
cpu->n_translated_instrs = 0; |
|
cpu->running_translated = 1; |
|
237 |
|
|
238 |
cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *) |
cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *) |
239 |
cpu->cd.DYNTRANS_ARCH.cur_ic_page; |
cpu->cd.DYNTRANS_ARCH.cur_ic_page; |
292 |
} |
} |
293 |
} |
} |
294 |
|
|
|
/* When single-stepping, multiple instruction calls cannot |
|
|
be combined into one. This clears all translations: */ |
|
|
if (cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & COMBINATIONS) { |
|
|
int i; |
|
|
for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) { |
|
|
cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i].f = |
|
|
#ifdef DYNTRANS_DUALMODE_32 |
|
|
cpu->is_32bit? |
|
|
instr32(to_be_translated) : |
|
|
#endif |
|
|
instr(to_be_translated); |
|
|
#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH |
|
|
cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i]. |
|
|
arg[0] = 0; |
|
|
#endif |
|
|
} |
|
|
|
|
|
fatal("[ Note: The translation of physical page 0x%" |
|
|
PRIx64" contained combinations of instructions; " |
|
|
"these are now flushed because we are single-" |
|
|
"stepping. ]\n", (long long)cpu->cd.DYNTRANS_ARCH. |
|
|
cur_physpage->physaddr); |
|
|
|
|
|
cpu->cd.DYNTRANS_ARCH.cur_physpage->flags &= |
|
|
~COMBINATIONS; |
|
|
cpu->cd.DYNTRANS_ARCH.cur_physpage->translations = 0; |
|
|
} |
|
|
|
|
295 |
if (cpu->machine->statistics_enabled) |
if (cpu->machine->statistics_enabled) |
296 |
S; |
S; |
297 |
|
|
316 |
cpu->machine->tick_func[1](cpu, cpu->machine->tick_extra[1]); |
cpu->machine->tick_func[1](cpu, cpu->machine->tick_extra[1]); |
317 |
/* printf("B\n"); */ |
/* printf("B\n"); */ |
318 |
|
|
319 |
if (!cpu->running_translated || |
if (n_instrs + cpu->n_translated_instrs >= |
|
n_instrs + cpu->n_translated_instrs >= |
|
320 |
N_SAFE_DYNTRANS_LIMIT) |
N_SAFE_DYNTRANS_LIMIT) |
321 |
break; |
break; |
322 |
} |
} |
333 |
|
|
334 |
n_instrs += 24; |
n_instrs += 24; |
335 |
|
|
336 |
if (!cpu->running_translated || |
if (n_instrs + cpu->n_translated_instrs >= |
|
n_instrs + cpu->n_translated_instrs >= |
|
337 |
N_SAFE_DYNTRANS_LIMIT) |
N_SAFE_DYNTRANS_LIMIT) |
338 |
break; |
break; |
339 |
} |
} |
340 |
} else { |
} else { |
341 |
/* Execute multiple instructions: */ |
/* Execute multiple instructions: */ |
342 |
n_instrs = 0; |
int n = 0; |
343 |
for (;;) { |
for (;;) { |
344 |
struct DYNTRANS_IC *ic; |
struct DYNTRANS_IC *ic; |
345 |
|
|
351 |
|
|
352 |
I; I; I; I; I; I; I; I; I; I; |
I; I; I; I; I; I; I; I; I; I; |
353 |
|
|
354 |
n_instrs += 60; |
n += 60; |
355 |
|
|
356 |
if (!cpu->running_translated || |
if (n + cpu->n_translated_instrs >= |
|
n_instrs + cpu->n_translated_instrs >= |
|
357 |
N_SAFE_DYNTRANS_LIMIT) |
N_SAFE_DYNTRANS_LIMIT) |
358 |
break; |
break; |
359 |
} |
} |
360 |
|
n_instrs = n; |
361 |
} |
} |
362 |
|
|
363 |
n_instrs += cpu->n_translated_instrs; |
n_instrs += cpu->n_translated_instrs; |
620 |
if (!ok) { |
if (!ok) { |
621 |
uint64_t paddr; |
uint64_t paddr; |
622 |
if (cpu->translate_v2p != NULL) { |
if (cpu->translate_v2p != NULL) { |
623 |
|
uint64_t vaddr = |
624 |
|
#if defined(MODE32) && defined(DYNTRANS_MIPS) |
625 |
|
/* 32-bit MIPS is _sign_ extend, not zero. */ |
626 |
|
(int32_t) |
627 |
|
#endif |
628 |
|
cached_pc; |
629 |
ok = cpu->translate_v2p( |
ok = cpu->translate_v2p( |
630 |
cpu, cached_pc, &paddr, FLAG_INSTR); |
cpu, vaddr, &paddr, FLAG_INSTR); |
631 |
} else { |
} else { |
632 |
paddr = cached_pc; |
paddr = cached_pc; |
633 |
ok = 1; |
ok = 1; |
878 |
} |
} |
879 |
|
|
880 |
ppp->next_ofs = 0; |
ppp->next_ofs = 0; |
|
ppp->flags = 0; |
|
881 |
ppp->translations = 0; |
ppp->translations = 0; |
882 |
/* ppp->physaddr is filled in by the page allocator */ |
/* ppp->physaddr is filled in by the page allocator */ |
883 |
|
|
1287 |
x >>= 1; |
x >>= 1; |
1288 |
} |
} |
1289 |
|
|
|
ppp->flags &= ~COMBINATIONS; |
|
1290 |
ppp->translations = 0; |
ppp->translations = 0; |
1291 |
} |
} |
1292 |
#endif |
#endif |
1341 |
void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page, |
void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page, |
1342 |
unsigned char *host_page, int writeflag, uint64_t paddr_page) |
unsigned char *host_page, int writeflag, uint64_t paddr_page) |
1343 |
{ |
{ |
|
#ifndef MODE32 |
|
|
int64_t lowest, highest = -1; |
|
|
#endif |
|
1344 |
int found, r, lowest_index, useraccess = 0; |
int found, r, lowest_index, useraccess = 0; |
1345 |
|
|
1346 |
#ifdef MODE32 |
#ifdef MODE32 |
1385 |
*/ |
*/ |
1386 |
found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[ |
found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[ |
1387 |
DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1; |
DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1; |
1388 |
|
#else |
1389 |
|
x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1; |
1390 |
|
x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2; |
1391 |
|
x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) |
1392 |
|
& mask3; |
1393 |
|
|
1394 |
|
l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; |
1395 |
|
if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) |
1396 |
|
found = -1; |
1397 |
|
else { |
1398 |
|
l3 = l2->l3[x2]; |
1399 |
|
if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) |
1400 |
|
found = -1; |
1401 |
|
else |
1402 |
|
found = (int)l3->vaddr_to_tlbindex[x3] - 1; |
1403 |
|
} |
1404 |
|
#endif |
1405 |
|
|
1406 |
if (found < 0) { |
if (found < 0) { |
1407 |
static unsigned int x = 0; |
static unsigned int x = 0; |
1408 |
lowest_index = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES; |
lowest_index = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES; |
1409 |
} |
} |
|
#else |
|
|
lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp; |
|
|
found = -1; |
|
|
for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) { |
|
|
if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) { |
|
|
lowest = cpu->cd.DYNTRANS_ARCH. |
|
|
vph_tlb_entry[r].timestamp; |
|
|
lowest_index = r; |
|
|
} |
|
|
if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp > highest) |
|
|
highest = cpu->cd.DYNTRANS_ARCH. |
|
|
vph_tlb_entry[r].timestamp; |
|
|
if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && |
|
|
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page == |
|
|
vaddr_page) { |
|
|
found = r; |
|
|
break; |
|
|
} |
|
|
} |
|
|
#endif |
|
1410 |
|
|
1411 |
if (found < 0) { |
if (found < 0) { |
1412 |
/* Create the new TLB entry, overwriting the oldest one: */ |
/* Create the new TLB entry, overwriting the oldest one: */ |
1424 |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page; |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page; |
1425 |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = |
1426 |
writeflag & MEM_WRITE; |
writeflag & MEM_WRITE; |
|
#ifndef MODE32 |
|
|
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1; |
|
|
#endif |
|
1427 |
|
|
1428 |
/* Add the new translation to the table: */ |
/* Add the new translation to the table: */ |
1429 |
#ifdef MODE32 |
#ifdef MODE32 |
1440 |
|= 1 << (index & 31); |
|= 1 << (index & 31); |
1441 |
#endif |
#endif |
1442 |
#else /* !MODE32 */ |
#else /* !MODE32 */ |
|
x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1; |
|
|
x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2; |
|
|
x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) |
|
|
& mask3; |
|
|
|
|
1443 |
l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; |
l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; |
1444 |
if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) { |
if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) { |
1445 |
if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) { |
if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) { |
1524 |
* Writeflag = MEM_DOWNGRADE: Downgrade to readonly. |
* Writeflag = MEM_DOWNGRADE: Downgrade to readonly. |
1525 |
*/ |
*/ |
1526 |
r = found; |
r = found; |
|
#ifndef MODE32 |
|
|
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1; |
|
|
#endif |
|
1527 |
if (writeflag & MEM_WRITE) |
if (writeflag & MEM_WRITE) |
1528 |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1; |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1; |
1529 |
if (writeflag & MEM_DOWNGRADE) |
if (writeflag & MEM_DOWNGRADE) |
1672 |
#ifdef DYNTRANS_DELAYSLOT |
#ifdef DYNTRANS_DELAYSLOT |
1673 |
&& !in_crosspage_delayslot |
&& !in_crosspage_delayslot |
1674 |
#endif |
#endif |
1675 |
) { |
&& cpu->cd.DYNTRANS_ARCH.combination_check != NULL |
1676 |
if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL && |
&& cpu->machine->allow_instruction_combinations) { |
1677 |
cpu->machine->allow_instruction_combinations) |
cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic, |
1678 |
cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic, |
addr & (DYNTRANS_PAGESIZE - 1)); |
|
addr & (DYNTRANS_PAGESIZE - 1)); |
|
1679 |
} |
} |
1680 |
|
|
1681 |
cpu->cd.DYNTRANS_ARCH.combination_check = NULL; |
cpu->cd.DYNTRANS_ARCH.combination_check = NULL; |
1755 |
} |
} |
1756 |
|
|
1757 |
cpu->running = 0; |
cpu->running = 0; |
1758 |
cpu->dead = 1; |
|
1759 |
|
/* Note: Single-stepping can jump here. */ |
1760 |
stop_running_translated: |
stop_running_translated: |
1761 |
|
|
1762 |
debugger_n_steps_left_before_interaction = 0; |
debugger_n_steps_left_before_interaction = 0; |
1763 |
cpu->running_translated = 0; |
|
1764 |
ic = cpu->cd.DYNTRANS_ARCH.next_ic = ¬hing_call; |
ic = cpu->cd.DYNTRANS_ARCH.next_ic = ¬hing_call; |
1765 |
cpu->cd.DYNTRANS_ARCH.next_ic ++; |
cpu->cd.DYNTRANS_ARCH.next_ic ++; |
1766 |
|
|
1767 |
/* Execute the "nothing" instruction: */ |
/* Execute the "nothing" instruction: */ |
1768 |
ic->f(cpu, ic); |
ic->f(cpu, ic); |
1769 |
|
|
1770 |
#endif /* DYNTRANS_TO_BE_TRANSLATED_TAIL */ |
#endif /* DYNTRANS_TO_BE_TRANSLATED_TAIL */ |
1771 |
|
|