25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_dyntrans.c,v 1.27 2005/10/27 14:01:13 debug Exp $ |
* $Id: cpu_dyntrans.c,v 1.41 2005/11/23 22:03:31 debug Exp $ |
29 |
* |
* |
30 |
* Common dyntrans routines. Included from cpu_*.c. |
* Common dyntrans routines. Included from cpu_*.c. |
31 |
*/ |
*/ |
40 |
if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE) |
if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE) |
41 |
return; |
return; |
42 |
|
|
43 |
#if 1 |
#if 0 |
44 |
/* Use the physical address: */ |
/* Use the physical address: */ |
45 |
cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *) |
cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *) |
46 |
cpu->cd.DYNTRANS_ARCH.cur_ic_page; |
cpu->cd.DYNTRANS_ARCH.cur_ic_page; |
94 |
#define S gather_statistics(cpu) |
#define S gather_statistics(cpu) |
95 |
|
|
96 |
#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH |
#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH |
97 |
#define I ic = cpu->cd.DYNTRANS_ARCH.next_ic; ic->f(cpu, ic); |
#define I ic = cpu->cd.DYNTRANS_ARCH.next_ic; \ |
98 |
|
cpu->cd.DYNTRANS_ARCH.next_ic += ic->len; \ |
99 |
|
ic->f(cpu, ic); |
100 |
#else |
#else |
101 |
#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); |
102 |
#endif |
#endif |
136 |
if (cpu->cd.arm.irq_asserted && !(cpu->cd.arm.cpsr & ARM_FLAG_I)) |
if (cpu->cd.arm.irq_asserted && !(cpu->cd.arm.cpsr & ARM_FLAG_I)) |
137 |
arm_exception(cpu, ARM_EXCEPTION_IRQ); |
arm_exception(cpu, ARM_EXCEPTION_IRQ); |
138 |
#endif |
#endif |
139 |
|
#ifdef DYNTRANS_PPC |
140 |
|
if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) { |
141 |
|
ppc_exception(cpu, PPC_EXCEPTION_DEC); |
142 |
|
cpu->cd.ppc.dec_intr_pending = 0; |
143 |
|
} |
144 |
|
if (cpu->cd.ppc.irq_asserted && cpu->cd.ppc.msr & PPC_MSR_EE) |
145 |
|
ppc_exception(cpu, PPC_EXCEPTION_EI); |
146 |
|
#endif |
147 |
|
|
148 |
cached_pc = cpu->pc; |
cached_pc = cpu->pc; |
149 |
|
|
248 |
} |
} |
249 |
} |
} |
250 |
|
|
251 |
|
n_instrs += cpu->n_translated_instrs; |
252 |
|
|
253 |
/* |
/* Synchronize the program counter: */ |
|
* Update the program counter and return the correct number of |
|
|
* executed instructions: |
|
|
*/ |
|
254 |
low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t) |
low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t) |
255 |
cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC); |
cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC); |
|
|
|
256 |
if (low_pc >= 0 && low_pc < DYNTRANS_IC_ENTRIES_PER_PAGE) { |
if (low_pc >= 0 && low_pc < DYNTRANS_IC_ENTRIES_PER_PAGE) { |
|
#ifdef DYNTRANS_ARM |
|
|
cpu->cd.arm.r[ARM_PC] &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1)<<2); |
|
|
cpu->cd.arm.r[ARM_PC] += (low_pc << 2); |
|
|
cpu->pc = cpu->cd.arm.r[ARM_PC]; |
|
|
#else |
|
257 |
cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << |
cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << |
258 |
DYNTRANS_INSTR_ALIGNMENT_SHIFT); |
DYNTRANS_INSTR_ALIGNMENT_SHIFT); |
259 |
cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); |
cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); |
|
#endif |
|
260 |
} else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE) { |
} else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE) { |
261 |
/* Switch to next page: */ |
/* Switch to next page: */ |
|
#ifdef DYNTRANS_ARM |
|
|
cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2); |
|
|
cpu->cd.arm.r[ARM_PC] += (ARM_IC_ENTRIES_PER_PAGE << 2); |
|
|
cpu->pc = cpu->cd.arm.r[ARM_PC]; |
|
|
#else |
|
262 |
cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << |
cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << |
263 |
DYNTRANS_INSTR_ALIGNMENT_SHIFT); |
DYNTRANS_INSTR_ALIGNMENT_SHIFT); |
264 |
cpu->pc += (DYNTRANS_IC_ENTRIES_PER_PAGE << |
cpu->pc += (DYNTRANS_IC_ENTRIES_PER_PAGE << |
265 |
DYNTRANS_INSTR_ALIGNMENT_SHIFT); |
DYNTRANS_INSTR_ALIGNMENT_SHIFT); |
|
#endif |
|
|
} else { |
|
|
/* debug("debug: Outside a page (This is actually ok)\n"); */ |
|
266 |
} |
} |
267 |
|
|
268 |
return n_instrs + cpu->n_translated_instrs; |
#ifdef DYNTRANS_PPC |
269 |
|
/* Update the Decrementer and Time base registers: */ |
270 |
|
{ |
271 |
|
uint32_t old = cpu->cd.ppc.spr[SPR_DEC]; |
272 |
|
cpu->cd.ppc.spr[SPR_DEC] = (uint32_t) (old - n_instrs); |
273 |
|
if ((old >> 31) == 0 && (cpu->cd.ppc.spr[SPR_DEC] >> 31) == 1) |
274 |
|
cpu->cd.ppc.dec_intr_pending = 1; |
275 |
|
|
276 |
|
old = cpu->cd.ppc.spr[SPR_TBL]; |
277 |
|
cpu->cd.ppc.spr[SPR_TBL] += n_instrs; |
278 |
|
if ((old >> 31) == 1 && (cpu->cd.ppc.spr[SPR_TBL] >> 31) == 0) |
279 |
|
cpu->cd.ppc.spr[SPR_TBU] ++; |
280 |
|
} |
281 |
|
#endif |
282 |
|
|
283 |
|
/* Return the nr of instructions executed: */ |
284 |
|
return n_instrs; |
285 |
} |
} |
286 |
#endif /* DYNTRANS_CPU_RUN_INSTR */ |
#endif /* DYNTRANS_CPU_RUN_INSTR */ |
287 |
|
|
361 |
#ifdef DYNTRANS_MIPS |
#ifdef DYNTRANS_MIPS |
362 |
gpr[MIPS_GPR_A0 |
gpr[MIPS_GPR_A0 |
363 |
#endif |
#endif |
364 |
|
#ifdef DYNTRANS_NEWMIPS |
365 |
|
r[0 /* TODO */ |
366 |
|
#endif |
367 |
#ifdef DYNTRANS_PPC |
#ifdef DYNTRANS_PPC |
368 |
gpr[3 |
gpr[3 |
369 |
#endif |
#endif |
465 |
#else |
#else |
466 |
uint64_t |
uint64_t |
467 |
#endif |
#endif |
468 |
cached_pc, physaddr; |
cached_pc, physaddr = 0; |
469 |
uint32_t physpage_ofs; |
uint32_t physpage_ofs; |
470 |
int ok, pagenr, table_index; |
int ok, pagenr, table_index; |
471 |
uint32_t *physpage_entryp; |
uint32_t *physpage_entryp; |
531 |
ok = 1; |
ok = 1; |
532 |
} |
} |
533 |
if (!ok) { |
if (!ok) { |
534 |
/* |
/* fatal("TODO: instruction vaddr=>paddr translation" |
|
fatal("TODO: instruction vaddr=>paddr translation" |
|
535 |
" failed. vaddr=0x%llx\n", (long long)cached_pc); |
" failed. vaddr=0x%llx\n", (long long)cached_pc); |
536 |
fatal("!! cpu->pc=0x%llx arm_pc=0x%x\n", (long long)cpu->pc, |
fatal("!! cpu->pc=0x%llx\n", (long long)cpu->pc); */ |
537 |
cpu->cd.arm.r[ARM_PC]); |
|
|
*/ |
|
538 |
ok = cpu->translate_address(cpu, cpu->pc, &paddr, |
ok = cpu->translate_address(cpu, cpu->pc, &paddr, |
539 |
FLAG_INSTR); |
FLAG_INSTR); |
540 |
/* |
|
541 |
printf("EXCEPTION HANDLER: vaddr = 0x%x ==> paddr = 0x%x\n", |
/* printf("EXCEPTION HANDLER: vaddr = 0x%x ==> " |
542 |
(int)cpu->pc, (int)paddr); |
"paddr = 0x%x\n", (int)cpu->pc, (int)paddr); |
543 |
fatal("!? cpu->pc=0x%llx arm_pc=0x%x\n", (long long)cpu->pc, |
fatal("!? cpu->pc=0x%llx\n", (long long)cpu->pc); */ |
544 |
cpu->cd.arm.r[ARM_PC]); |
|
|
*/ |
|
545 |
if (!ok) { |
if (!ok) { |
546 |
fatal("FATAL: could not find physical" |
fatal("FATAL: could not find physical" |
547 |
" address of the exception handler?"); |
" address of the exception handler?"); |
570 |
#endif |
#endif |
571 |
|
|
572 |
if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) { |
if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) { |
573 |
fatal("[ dyntrans: resetting the translation cache ]\n"); |
debug("[ dyntrans: resetting the translation cache ]\n"); |
574 |
cpu_create_or_reset_tc(cpu); |
cpu_create_or_reset_tc(cpu); |
575 |
} |
} |
576 |
|
|
619 |
vph_p->phys_page[b] = ppp; |
vph_p->phys_page[b] = ppp; |
620 |
#endif |
#endif |
621 |
|
|
622 |
|
#ifdef MODE32 |
623 |
|
/* Small optimization: only mark the physical page as non-writable |
624 |
|
if it did not contain translations. (Because if it does contain |
625 |
|
translations, it is already non-writable.) */ |
626 |
|
if (!cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] & |
627 |
|
(1 << (pagenr & 31))) |
628 |
|
#endif |
629 |
cpu->invalidate_translation_caches(cpu, physaddr, |
cpu->invalidate_translation_caches(cpu, physaddr, |
630 |
JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR); |
JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR); |
631 |
|
|
|
/* cpu->cd.DYNTRANS_ARCH.cur_physpage = ppp; */ |
|
632 |
cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0]; |
cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0]; |
633 |
|
|
634 |
cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page + |
cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page + |
689 |
goto have_it; |
goto have_it; |
690 |
} |
} |
691 |
#else |
#else |
692 |
|
/* Temporary, to avoid a compiler warning: */ |
693 |
|
cached_pc = 0; |
694 |
|
ppp = NULL; |
695 |
#ifdef DYNTRANS_IA64 |
#ifdef DYNTRANS_IA64 |
696 |
fatal("IA64 todo\n"); |
fatal("IA64 todo\n"); |
697 |
#else |
#else |
698 |
fatal("Neither alpha, ia64, nor 32-bit? 1\n"); |
fatal("Neither alpha, ia64, nor 32-bit? 1\n"); |
|
{ char *p = (char *) 0; *p = 0; } |
|
699 |
exit(1); |
exit(1); |
700 |
#endif |
#endif |
701 |
#endif |
#endif |
705 |
return; |
return; |
706 |
|
|
707 |
/* Quick return path: */ |
/* Quick return path: */ |
708 |
|
#if defined(MODE32) || defined(DYNTRANS_ALPHA) |
709 |
have_it: |
have_it: |
|
/* cpu->cd.DYNTRANS_ARCH.cur_physpage = ppp; */ |
|
710 |
cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0]; |
cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0]; |
711 |
cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page + |
cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page + |
712 |
DYNTRANS_PC_TO_IC_ENTRY(cached_pc); |
DYNTRANS_PC_TO_IC_ENTRY(cached_pc); |
714 |
/* printf("cached_pc=0x%016llx pagenr=%lli table_index=%lli, " |
/* printf("cached_pc=0x%016llx pagenr=%lli table_index=%lli, " |
715 |
"physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr, |
"physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr, |
716 |
(long long)table_index, (long long)physpage_ofs); */ |
(long long)table_index, (long long)physpage_ofs); */ |
717 |
|
#endif |
718 |
} |
} |
719 |
#endif /* DYNTRANS_PC_TO_POINTERS_FUNC */ |
#endif /* DYNTRANS_PC_TO_POINTERS_FUNC */ |
720 |
|
|
742 |
uint32_t index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page); |
uint32_t index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page); |
743 |
|
|
744 |
#ifdef DYNTRANS_ARM |
#ifdef DYNTRANS_ARM |
745 |
cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 3] &= ~(1 << (index & 7)); |
cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5] &= ~(1 << (index & 31)); |
746 |
#endif |
#endif |
747 |
|
|
748 |
if (flags & JUST_MARK_AS_NON_WRITABLE) { |
if (flags & JUST_MARK_AS_NON_WRITABLE) { |
838 |
#endif |
#endif |
839 |
addr_page = paddr & ~(DYNTRANS_PAGESIZE - 1); |
addr_page = paddr & ~(DYNTRANS_PAGESIZE - 1); |
840 |
|
|
841 |
|
/* fatal("invalidate(): "); */ |
842 |
|
|
843 |
/* Quick case for virtual addresses: see note above. */ |
/* Quick case for virtual addresses: see note above. */ |
844 |
if (flags & INVALIDATE_VADDR) { |
if (flags & INVALIDATE_VADDR) { |
845 |
|
/* fatal("vaddr 0x%08x\n", (int)addr_page); */ |
846 |
DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags); |
DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags); |
847 |
return; |
return; |
848 |
} |
} |
849 |
|
|
850 |
|
if (flags & INVALIDATE_ALL) { |
851 |
|
/* fatal("all\n"); */ |
852 |
|
for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) { |
853 |
|
if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) { |
854 |
|
DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, cpu->cd. |
855 |
|
DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page, |
856 |
|
0); |
857 |
|
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid=0; |
858 |
|
} |
859 |
|
} |
860 |
|
return; |
861 |
|
} |
862 |
|
|
863 |
|
/* fatal("paddr 0x%08x\n", (int)addr_page); */ |
864 |
|
|
865 |
for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) { |
for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) { |
866 |
if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && ( |
if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && ( |
867 |
(cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page == |
(cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page == |
1047 |
void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page, |
void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page, |
1048 |
unsigned char *host_page, int writeflag, uint64_t paddr_page) |
unsigned char *host_page, int writeflag, uint64_t paddr_page) |
1049 |
{ |
{ |
1050 |
|
#ifndef MODE32 |
1051 |
int64_t lowest, highest = -1; |
int64_t lowest, highest = -1; |
1052 |
|
#endif |
1053 |
int found, r, lowest_index, start, end, useraccess = 0; |
int found, r, lowest_index, start, end, useraccess = 0; |
1054 |
|
|
1055 |
#ifdef DYNTRANS_ALPHA |
#ifdef DYNTRANS_ALPHA |
1095 |
#endif |
#endif |
1096 |
|
|
1097 |
/* Scan the current TLB entries: */ |
/* Scan the current TLB entries: */ |
1098 |
found = -1; lowest_index = start; |
lowest_index = start; |
|
lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp; |
|
1099 |
|
|
1100 |
#ifdef MODE32 |
#ifdef MODE32 |
1101 |
/* NOTE: vaddr_to_tlbindex is one more than the index, so that |
/* |
1102 |
0 becomes -1, which means a miss. */ |
* NOTE 1: vaddr_to_tlbindex is one more than the index, so that |
1103 |
found = cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[ |
* 0 becomes -1, which means a miss. |
1104 |
|
* |
1105 |
|
* NOTE 2: When a miss occurs, instead of scanning the entire tlb |
1106 |
|
* for the entry with the lowest time stamp, just choosing |
1107 |
|
* one at random will work as well. |
1108 |
|
*/ |
1109 |
|
found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[ |
1110 |
DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1; |
DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1; |
1111 |
if (found < 0) |
if (found < 0) { |
1112 |
lowest_index = (random() % (end-start)) + start; |
static unsigned int x = 0; |
1113 |
if (0) |
lowest_index = (x % (end-start)) + start; |
1114 |
#endif |
x ++; |
1115 |
|
} |
1116 |
|
#else |
1117 |
|
lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp; |
1118 |
|
found = -1; |
1119 |
for (r=start; r<end; r++) { |
for (r=start; r<end; r++) { |
1120 |
if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) { |
if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) { |
1121 |
lowest = cpu->cd.DYNTRANS_ARCH. |
lowest = cpu->cd.DYNTRANS_ARCH. |
1132 |
break; |
break; |
1133 |
} |
} |
1134 |
} |
} |
1135 |
|
#endif |
1136 |
|
|
1137 |
if (found < 0) { |
if (found < 0) { |
1138 |
/* Create the new TLB entry, overwriting the oldest one: */ |
/* Create the new TLB entry, overwriting the oldest one: */ |
1148 |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].host_page = host_page; |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].host_page = host_page; |
1149 |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page = paddr_page; |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page = paddr_page; |
1150 |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page; |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page; |
1151 |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = writeflag; |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = |
1152 |
|
writeflag & MEM_WRITE; |
1153 |
|
#ifndef MODE32 |
1154 |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1; |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1; |
1155 |
|
#endif |
1156 |
|
|
1157 |
/* Add the new translation to the table: */ |
/* Add the new translation to the table: */ |
1158 |
#ifdef DYNTRANS_ALPHA |
#ifdef DYNTRANS_ALPHA |
1201 |
cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = r + 1; |
cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = r + 1; |
1202 |
#ifdef DYNTRANS_ARM |
#ifdef DYNTRANS_ARM |
1203 |
if (useraccess) |
if (useraccess) |
1204 |
cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 3] |
cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5] |
1205 |
|= 1 << (index & 7); |
|= 1 << (index & 31); |
1206 |
#endif |
#endif |
1207 |
#endif /* 32 */ |
#endif /* 32 */ |
1208 |
#endif /* !ALPHA */ |
#endif /* !ALPHA */ |
1211 |
* The translation was already in the TLB. |
* The translation was already in the TLB. |
1212 |
* Writeflag = 0: Do nothing. |
* Writeflag = 0: Do nothing. |
1213 |
* Writeflag = 1: Make sure the page is writable. |
* Writeflag = 1: Make sure the page is writable. |
1214 |
* Writeflag = -1: Downgrade to readonly. |
* Writeflag = MEM_DOWNGRADE: Downgrade to readonly. |
1215 |
*/ |
*/ |
1216 |
r = found; |
r = found; |
1217 |
|
#ifndef MODE32 |
1218 |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1; |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1; |
1219 |
if (writeflag == 1) |
#endif |
1220 |
|
if (writeflag & MEM_WRITE) |
1221 |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1; |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1; |
1222 |
if (writeflag == -1) |
if (writeflag & MEM_DOWNGRADE) |
1223 |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 0; |
cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 0; |
1224 |
#ifdef DYNTRANS_ALPHA |
#ifdef DYNTRANS_ALPHA |
1225 |
a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1); |
a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1); |
1231 |
vph_p = cpu->cd.alpha.vph_table0[a]; |
vph_p = cpu->cd.alpha.vph_table0[a]; |
1232 |
vph_p->phys_page[b] = NULL; |
vph_p->phys_page[b] = NULL; |
1233 |
if (vph_p->phys_addr[b] == paddr_page) { |
if (vph_p->phys_addr[b] == paddr_page) { |
1234 |
if (writeflag == 1) |
if (writeflag & MEM_WRITE) |
1235 |
vph_p->host_store[b] = host_page; |
vph_p->host_store[b] = host_page; |
1236 |
if (writeflag == -1) |
if (writeflag & MEM_DOWNGRADE) |
1237 |
vph_p->host_store[b] = NULL; |
vph_p->host_store[b] = NULL; |
1238 |
} else { |
} else { |
1239 |
/* Change the entire physical/host mapping: */ |
/* Change the entire physical/host mapping: */ |
1246 |
index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page); |
index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page); |
1247 |
cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL; |
cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL; |
1248 |
#ifdef DYNTRANS_ARM |
#ifdef DYNTRANS_ARM |
1249 |
cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 3]&=~(1<<(index&7)); |
cpu->cd.DYNTRANS_ARCH.is_userpage[index>>5] &= ~(1<<(index&31)); |
1250 |
if (useraccess) |
if (useraccess) |
1251 |
cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 3] |
cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5] |
1252 |
|= 1 << (index & 7); |
|= 1 << (index & 31); |
1253 |
#endif |
#endif |
1254 |
if (cpu->cd.DYNTRANS_ARCH.phys_addr[index] == paddr_page) { |
if (cpu->cd.DYNTRANS_ARCH.phys_addr[index] == paddr_page) { |
1255 |
if (writeflag == 1) |
if (writeflag & MEM_WRITE) |
1256 |
cpu->cd.DYNTRANS_ARCH.host_store[index] = |
cpu->cd.DYNTRANS_ARCH.host_store[index] = |
1257 |
host_page; |
host_page; |
1258 |
if (writeflag == -1) |
if (writeflag & MEM_DOWNGRADE) |
1259 |
cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL; |
cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL; |
1260 |
} else { |
} else { |
1261 |
/* Change the entire physical/host mapping: */ |
/* Change the entire physical/host mapping: */ |
1337 |
* instruction combination. |
* instruction combination. |
1338 |
*/ |
*/ |
1339 |
if (!single_step && !cpu->machine->instruction_trace) { |
if (!single_step && !cpu->machine->instruction_trace) { |
1340 |
if (cpu->combination_check != NULL && |
if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL && |
1341 |
cpu->machine->speed_tricks) |
cpu->machine->speed_tricks) |
1342 |
cpu->combination_check(cpu, ic, |
cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic, |
1343 |
addr & (DYNTRANS_PAGESIZE - 1)); |
addr & (DYNTRANS_PAGESIZE - 1)); |
1344 |
cpu->combination_check = NULL; |
cpu->cd.DYNTRANS_ARCH.combination_check = NULL; |
1345 |
} |
} |
1346 |
|
|
1347 |
/* ... and finally execute the translated instruction: */ |
/* ... and finally execute the translated instruction: */ |