--- trunk/src/cpus/cpu_dyntrans.c 2007/10/08 16:19:37 22 +++ trunk/src/cpus/cpu_dyntrans.c 2007/10/08 16:19:56 24 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: cpu_dyntrans.c,v 1.54 2006/02/09 22:55:20 debug Exp $ + * $Id: cpu_dyntrans.c,v 1.99 2006/06/23 20:43:44 debug Exp $ * * Common dyntrans routines. Included from cpu_*.c. */ @@ -100,10 +100,11 @@ if (array_16kpage_in_use[i]) { for (j=0; j<16384; j++) if (array[i*16384 + j] > 0) - fprintf(f, "%lli\t0x%016llx\n", - (long long)array[i*16384+j], - (long long)((i*16384+j) << - DYNTRANS_INSTR_ALIGNMENT_SHIFT)); + fprintf(f, "%lli\t" + "0x%016"PRIx64"\n", + (uint64_t)array[i*16384+j], + (uint64_t)((i*16384+j) << + DYNTRANS_INSTR_ALIGNMENT_SHIFT)); } fclose(f); printf("n=0x%08x\n", n); @@ -112,14 +113,62 @@ } #endif /* PC statistics */ + #define S gather_statistics(cpu) + #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic; \ cpu->cd.DYNTRANS_ARCH.next_ic += ic->arg[0]; \ ic->f(cpu, ic); #else -#define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); + +/* The normal instruction execution core: */ +#define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); + +/* For heavy debugging: */ +/* #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; \ + { \ + int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \ + (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \ + sizeof(struct DYNTRANS_IC); \ + printf("cur_ic_page=%p ic=%p (low_pc=0x%x)\n", \ + cpu->cd.DYNTRANS_ARCH.cur_ic_page, \ + ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \ + } \ + ic->f(cpu, ic); */ + +/* static long long nr_of_I_calls = 0; */ + +/* Temporary hack for finding NULL bugs: */ +/* #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; \ + nr_of_I_calls ++; \ + if (ic->f == NULL) { \ + int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \ + (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \ + sizeof(struct DYNTRANS_IC); \ + cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << \ + DYNTRANS_INSTR_ALIGNMENT_SHIFT); \ + cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT);\ + printf("Crash at %016"PRIx64"\n", cpu->pc); \ + printf("nr of I calls: %lli\n", nr_of_I_calls); \ + printf("Next ic = %p\n", cpu->cd. \ + DYNTRANS_ARCH.next_ic); \ + printf("cur ic page = %p\n", cpu->cd. \ + DYNTRANS_ARCH.cur_ic_page); \ + cpu->running = 0; \ + return 0; \ + } \ + ic->f(cpu, ic); */ + +/* Temporary hack for MIPS, to hunt for 32-bit/64-bit sign-extension bugs: */ +/* #define I { int k; for (k=1; k<=31; k++) \ + cpu->cd.mips.gpr[k] = (int32_t)cpu->cd.mips.gpr[k];\ + if (cpu->cd.mips.gpr[0] != 0) { \ + fatal("NOOOOOO\n"); exit(1); \ + } \ + ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); } +*/ #endif @@ -133,10 +182,15 @@ */ int DYNTRANS_CPU_RUN_INSTR(struct emul *emul, struct cpu *cpu) { -#ifdef MODE32 - uint32_t cached_pc; -#else + /* + * TODO: Statistics stuff! + */ + int show_opcode_statistics = 0; + +#ifdef DYNTRANS_DUALMODE_32 uint64_t cached_pc; +#else + uint32_t cached_pc; #endif int low_pc, n_instrs; @@ -152,11 +206,36 @@ * conversion; if the conversion caused an exception of some kind * then interrupts are probably disabled, and the exception will get * priority over device interrupts.) + * + * TODO: Turn this into a family-specific function somewhere... */ #ifdef DYNTRANS_ARM if (cpu->cd.arm.irq_asserted && !(cpu->cd.arm.cpsr & ARM_FLAG_I)) arm_exception(cpu, ARM_EXCEPTION_IRQ); #endif +#ifdef DYNTRANS_MIPS + { + int enabled, mask; + int status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS]; + if (cpu->cd.mips.cpu_type.exc_model == EXC3K) { + /* R3000: */ + enabled = status & MIPS_SR_INT_IE; + } else { + /* R4000 and others: */ + enabled = (status & STATUS_IE) + && !(status & STATUS_EXL) && !(status & STATUS_ERL); + /* Special case for R5900/C790/TX79: */ + if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 && + !(status & R5900_STATUS_EIE)) + enabled = 0; + } + mask = status & cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] + & STATUS_IM_MASK; + + if (enabled && mask) + mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0,0); + } +#endif #ifdef DYNTRANS_PPC if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) { ppc_exception(cpu, PPC_EXCEPTION_DEC); @@ -174,15 +253,16 @@ cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *) cpu->cd.DYNTRANS_ARCH.cur_ic_page; - if (single_step || cpu->machine->instruction_trace) { + if (single_step || cpu->machine->instruction_trace + || cpu->machine->register_dump) { /* * Single-step: */ - struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic -#ifndef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH - ++ -#endif - ; + struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic; + if (cpu->machine->register_dump) { + debug("\n"); + cpu_register_dump(cpu->machine, cpu, 1, 0x1); + } if (cpu->machine->instruction_trace) { #ifdef DYNTRANS_X86 unsigned char instr[17]; @@ -195,18 +275,34 @@ unsigned char instr[4]; /* General case... */ #endif #endif + if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0], sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) { fatal("XXX_cpu_run_instr(): could not read " "the instruction\n"); } else { cpu_disassemble_instr(cpu->machine, cpu, - instr, 1, 0, 0); -#ifdef DYNTRANS_MIPS -/* TODO: generalize, not just MIPS */ + instr, 1, 0); +#ifdef DYNTRANS_DELAYSLOT /* Show the instruction in the delay slot, if any: */ - fatal("TODO: check for delay slot!\n"); + if (cpu->instruction_has_delayslot == NULL) + fatal("WARNING: ihd func not yet" + " implemented?\n"); + else if (cpu->instruction_has_delayslot(cpu, + instr)) { + int saved_delayslot = cpu->delay_slot; + cpu->memory_rw(cpu, cpu->mem, cached_pc + + sizeof(instr), &instr[0], + sizeof(instr), MEM_READ, + CACHE_INSTRUCTION); + cpu->delay_slot = DELAYED; + cpu->pc += sizeof(instr); + cpu_disassemble_instr(cpu->machine, + cpu, instr, 1, 0); + cpu->delay_slot = saved_delayslot; + cpu->pc -= sizeof(instr); + } #endif } } @@ -215,17 +311,22 @@ be combined into one. This clears all translations: */ if (cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & COMBINATIONS) { int i; - for (i=0; icd.DYNTRANS_ARCH.cur_physpage->ics[i].f = #ifdef DYNTRANS_DUALMODE_32 cpu->is_32bit? instr32(to_be_translated) : #endif instr(to_be_translated); - fatal("[ Note: The translation of physical page 0x%llx" - " contained combinations of instructions; these " - "are now flushed because we are single-stepping." - " ]\n", (long long)cpu->cd.DYNTRANS_ARCH. +#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 | TRANSLATIONS); @@ -235,8 +336,31 @@ S; /* Execute just one instruction: */ - ic->f(cpu, ic); + I; + 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 (!cpu->running_translated || + n_instrs + cpu->n_translated_instrs >= + N_SAFE_DYNTRANS_LIMIT / 2) + break; + } } else if (show_opcode_statistics) { /* Gather statistics while executing multiple instructions: */ n_instrs = 0; @@ -251,7 +375,8 @@ n_instrs += 24; if (!cpu->running_translated || - n_instrs + cpu->n_translated_instrs >= 16384) + n_instrs + cpu->n_translated_instrs >= + N_SAFE_DYNTRANS_LIMIT / 2) break; } } else { @@ -271,7 +396,8 @@ n_instrs += 60; if (!cpu->running_translated || - n_instrs + cpu->n_translated_instrs >= 16384) + n_instrs + cpu->n_translated_instrs >= + N_SAFE_DYNTRANS_LIMIT / 2) break; } } @@ -300,6 +426,20 @@ DYNTRANS_INSTR_ALIGNMENT_SHIFT); } +#ifdef DYNTRANS_MIPS + /* Update the count register (on everything except EXC3K): */ + if (cpu->cd.mips.cpu_type.exc_model != EXC3K) { + uint32_t old = cpu->cd.mips.coproc[0]->reg[COP0_COUNT]; + int32_t diff1 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] - old; + int32_t diff2; + cpu->cd.mips.coproc[0]->reg[COP0_COUNT] = + (int32_t) (old + n_instrs); + diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] - + cpu->cd.mips.coproc[0]->reg[COP0_COUNT]; + if (cpu->cd.mips.compare_register_set && diff1>0 && diff2<=0) + cpu_interrupt(cpu, 7); + } +#endif #ifdef DYNTRANS_PPC /* Update the Decrementer and Time base registers: */ { @@ -336,7 +476,7 @@ char *symbol; uint64_t ot; int x, print_dots = 1, n_args_to_print = -#ifdef DYNTRANS_ALPHA +#if defined(DYNTRANS_ALPHA) || defined(DYNTRANS_SPARC) 6 #else #ifdef DYNTRANS_SH @@ -418,9 +558,9 @@ fatal("&%s", symbol); else { if (cpu->is_32bit) - fatal("0x%x", (int)d); + fatal("0x%"PRIx32, (uint32_t)d); else - fatal("0x%llx", (long long)d); + fatal("0x%"PRIx64, (uint64_t)d); } if (x < n_args_to_print - 1) @@ -470,19 +610,29 @@ ppp->physaddr = physaddr; /* TODO: Is this faster than copying an entire template page? */ - for (i=0; iics[i].f = #ifdef DYNTRANS_DUALMODE_32 cpu->is_32bit? instr32(to_be_translated) : #endif instr(to_be_translated); +#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH + ppp->ics[i].arg[0] = 0; +#endif + } + /* End-of-page: */ ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f = #ifdef DYNTRANS_DUALMODE_32 cpu->is_32bit? instr32(end_of_page) : #endif instr(end_of_page); +#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH + ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].arg[0] = 0; +#endif + + /* End-of-page-2, for delay-slot architectures: */ #ifdef DYNTRANS_DELAYSLOT ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f = #ifdef DYNTRANS_DUALMODE_32 @@ -514,33 +664,31 @@ #else uint64_t #endif - cached_pc, physaddr = 0; + cached_pc = cpu->pc, physaddr = 0; uint32_t physpage_ofs; int ok, pagenr, table_index; uint32_t *physpage_entryp; struct DYNTRANS_TC_PHYSPAGE *ppp; #ifdef MODE32 - int index; - cached_pc = cpu->pc; - index = DYNTRANS_ADDR_TO_PAGENR(cached_pc); + int index = DYNTRANS_ADDR_TO_PAGENR(cached_pc); #else -#ifdef DYNTRANS_ALPHA - uint32_t a, b; - int kernel = 0; - struct alpha_vph_page *vph_p; - cached_pc = cpu->pc; - a = (cached_pc >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1); - b = (cached_pc >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1); - if ((cached_pc >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) { - vph_p = cpu->cd.alpha.vph_table0_kernel[a]; - kernel = 1; - } else - vph_p = cpu->cd.alpha.vph_table0[a]; -#else - fatal("Neither alpha nor 32-bit? 3\n"); - exit(1); -#endif + const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1; + const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1; + const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1; + uint32_t x1, x2, x3; + struct DYNTRANS_L2_64_TABLE *l2; + struct DYNTRANS_L3_64_TABLE *l3; + + x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1; + x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2; + x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3; + /* fatal("X3: cached_pc=%016"PRIx64" x1=%x x2=%x x3=%x\n", + (uint64_t)cached_pc, (int)x1, (int)x2, (int)x3); */ + l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; + /* fatal(" l2 = %p\n", l2); */ + l3 = l2->l3[x2]; + /* fatal(" l3 = %p\n", l3); */ #endif /* Virtual to physical address translation: */ @@ -551,15 +699,10 @@ ok = 1; } #else -#ifdef DYNTRANS_ALPHA - if (vph_p->host_load[b] != NULL) { - physaddr = vph_p->phys_addr[b]; + if (l3->host_load[x3] != NULL) { + physaddr = l3->phys_addr[x3]; ok = 1; } -#else - fatal("Neither alpha nor 32-bit? 4\n"); - exit(1); -#endif #endif if (!ok) { @@ -572,16 +715,16 @@ ok = 1; } if (!ok) { - /* fatal("TODO: instruction vaddr=>paddr translation" - " failed. vaddr=0x%llx\n", (long long)cached_pc); - fatal("!! cpu->pc=0x%llx\n", (long long)cpu->pc); */ + /* fatal("TODO: instruction vaddr=>paddr translation " + "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc); + fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */ ok = cpu->translate_address(cpu, cpu->pc, &paddr, FLAG_INSTR); /* printf("EXCEPTION HANDLER: vaddr = 0x%x ==> " "paddr = 0x%x\n", (int)cpu->pc, (int)paddr); - fatal("!? cpu->pc=0x%llx\n", (long long)cpu->pc); */ + fatal("!? cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */ if (!ok) { fatal("FATAL: could not find physical" @@ -589,15 +732,28 @@ exit(1); } } + + /* If there was an exception, the PC can have changed. + Update cached_pc: */ cached_pc = cpu->pc; + #ifdef MODE32 index = DYNTRANS_ADDR_TO_PAGENR(cached_pc); +#else + x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1; + x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2; + x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) + & mask3; #endif + physaddr = paddr; } #ifdef MODE32 if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) { +#else + if (l3->host_load[x3] == NULL) { +#endif unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem, physaddr, MEM_READ); if (host_page != NULL) { @@ -606,9 +762,14 @@ ((1 << BITS_PER_MEMBLOCK) - 1) & ~q); cpu->update_translation_table(cpu, cached_pc & ~q, host_page, TLB_CODE, physaddr & ~q); +#ifndef MODE32 + /* Recalculate l2 and l3, since they might have + changed now: */ + l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; + l3 = l2->l3[x2]; +#endif } } -#endif if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) { debug("[ dyntrans: resetting the translation cache ]\n"); @@ -627,7 +788,7 @@ ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache + physpage_ofs); /* If we found the page in the cache, then we're done: */ - if (ppp->physaddr == physaddr) + if (DYNTRANS_ADDR_TO_PAGENR(ppp->physaddr) == pagenr) break; /* Try the next page in the chain: */ physpage_ofs = ppp->next_ofs; @@ -637,8 +798,8 @@ new "default" empty translation page. */ if (ppp == NULL) { - /* fatal("CREATING page %lli (physaddr 0x%llx), table index " - "%i\n", (long long)pagenr, (long long)physaddr, + /* fatal("CREATING page %lli (physaddr 0x%"PRIx64"), table " + "index %i\n", (long long)pagenr, (uint64_t)physaddr, (int)table_index); */ *physpage_entryp = physpage_ofs = cpu->translation_cache_cur_ofs; @@ -653,11 +814,9 @@ #ifdef MODE32 if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp; -#endif - -#ifdef DYNTRANS_ALPHA - if (vph_p->host_load[b] != NULL) - vph_p->phys_page[b] = ppp; +#else + if (l3->host_load[x3] != NULL) + l3->phys_page[x3] = ppp; #endif #ifdef MODE32 @@ -675,9 +834,9 @@ cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page + DYNTRANS_PC_TO_IC_ENTRY(cached_pc); - /* printf("cached_pc=0x%016llx pagenr=%lli table_index=%lli, " - "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr, - (long long)table_index, (long long)physpage_ofs); */ + /* printf("cached_pc=0x%016"PRIx64" pagenr=%lli table_index=%lli, " + "physpage_ofs=0x%016"PRIx64"\n", (uint64_t)cached_pc, (long long) + pagenr, (long long)table_index, (uint64_t)physpage_ofs); */ } @@ -711,50 +870,71 @@ if (ppp != NULL) goto have_it; #else -#ifdef DYNTRANS_ALPHA - uint32_t a, b; - int kernel = 0; - struct alpha_vph_page *vph_p; - a = (cached_pc >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1); - b = (cached_pc >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1); - if ((cached_pc >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) { - vph_p = cpu->cd.alpha.vph_table0_kernel[a]; - kernel = 1; - } else - vph_p = cpu->cd.alpha.vph_table0[a]; - if (vph_p != cpu->cd.alpha.vph_default_page) { - ppp = vph_p->phys_page[b]; - if (ppp != NULL) - goto have_it; - } -#else - fatal("X1: cached_pc=%016llx\n", (long long)cached_pc); - /* Temporary, to avoid a compiler warning: */ - ppp = NULL; - fatal("Neither alpha nor 32-bit? 1\n"); - exit(1); -#endif + const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1; + const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1; + const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1; + uint32_t x1, x2, x3; + struct DYNTRANS_L2_64_TABLE *l2; + struct DYNTRANS_L3_64_TABLE *l3; + + x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1; + x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2; + x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3; + l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; + l3 = l2->l3[x2]; + ppp = l3->phys_page[x3]; + if (ppp != NULL) + goto have_it; #endif DYNTRANS_PC_TO_POINTERS_GENERIC(cpu); return; /* Quick return path: */ -#if defined(MODE32) || defined(DYNTRANS_ALPHA) have_it: cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0]; cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page + DYNTRANS_PC_TO_IC_ENTRY(cached_pc); - /* printf("cached_pc=0x%016llx pagenr=%lli table_index=%lli, " - "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr, - (long long)table_index, (long long)physpage_ofs); */ -#endif + /* printf("cached_pc=0x%016"PRIx64" pagenr=%lli table_index=%lli, " + "physpage_ofs=0x%016"PRIx64"\n", (uint64_t)cached_pc, (long long) + pagenr, (long long)table_index, (uint64_t)physpage_ofs); */ } #endif /* DYNTRANS_PC_TO_POINTERS_FUNC */ +#ifdef DYNTRANS_INIT_64BIT_DUMMY_TABLES +/* + * XXX_init_64bit_dummy_tables(): + * + * Initializes 64-bit dummy tables and pointers. + */ +void DYNTRANS_INIT_64BIT_DUMMY_TABLES(struct cpu *cpu) +{ + struct DYNTRANS_L2_64_TABLE *dummy_l2; + struct DYNTRANS_L3_64_TABLE *dummy_l3; + int x1, x2; + + if (cpu->is_32bit) + return; + + dummy_l2 = zeroed_alloc(sizeof(struct DYNTRANS_L2_64_TABLE)); + dummy_l3 = zeroed_alloc(sizeof(struct DYNTRANS_L3_64_TABLE)); + + cpu->cd.DYNTRANS_ARCH.l2_64_dummy = dummy_l2; + cpu->cd.DYNTRANS_ARCH.l3_64_dummy = dummy_l3; + + for (x1 = 0; x1 < (1 << DYNTRANS_L1N); x1 ++) + cpu->cd.DYNTRANS_ARCH.l1_64[x1] = dummy_l2; + + for (x2 = 0; x2 < (1 << DYNTRANS_L2N); x2 ++) + dummy_l2->l3[x2] = dummy_l3; +} +#endif /* DYNTRANS_INIT_64BIT_DUMMY_TABLES */ + + + #ifdef DYNTRANS_INVAL_ENTRY /* * XXX_invalidate_tlb_entry(): @@ -785,58 +965,65 @@ (int)vaddr_page); */ cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL; } else { + int tlbi = cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index]; cpu->cd.DYNTRANS_ARCH.host_load[index] = NULL; cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL; cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0; cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL; + if (tlbi > 0) + cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[tlbi-1].valid = 0; cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0; } #else - /* 2-level: */ -#ifdef DYNTRANS_ALPHA - struct alpha_vph_page *vph_p; - uint32_t a, b; - int kernel = 0; - - a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1); - b = (vaddr_page >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1); - if ((vaddr_page >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) { - vph_p = cpu->cd.alpha.vph_table0_kernel[a]; - kernel = 1; - } else - vph_p = cpu->cd.alpha.vph_table0[a]; + const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1; + const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1; + const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1; + uint32_t x1, x2, x3; + struct DYNTRANS_L2_64_TABLE *l2; + struct DYNTRANS_L3_64_TABLE *l3; + + 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; - if (vph_p == cpu->cd.alpha.vph_default_page) { - fatal("alpha_invalidate_tlb_entry(): huh? Problem 1.\n"); - exit(1); - } + l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; + if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) + return; + + l3 = l2->l3[x2]; + if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) + return; if (flags & JUST_MARK_AS_NON_WRITABLE) { - vph_p->host_store[b] = NULL; + l3->host_store[x3] = NULL; return; } - vph_p->host_load[b] = NULL; - vph_p->host_store[b] = NULL; - vph_p->phys_addr[b] = 0; - vph_p->phys_page[b] = NULL; - vph_p->refcount --; - if (vph_p->refcount < 0) { - fatal("alpha_invalidate_tlb_entry(): huh? Problem 2.\n"); + l3->host_load[x3] = NULL; + l3->host_store[x3] = NULL; + l3->phys_addr[x3] = 0; + l3->phys_page[x3] = NULL; + l3->refcount --; + if (l3->refcount < 0) { + fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n"); exit(1); } - if (vph_p->refcount == 0) { - vph_p->next = cpu->cd.alpha.vph_next_free_page; - cpu->cd.alpha.vph_next_free_page = vph_p; - if (kernel) - cpu->cd.alpha.vph_table0_kernel[a] = - cpu->cd.alpha.vph_default_page; - else - cpu->cd.alpha.vph_table0[a] = - cpu->cd.alpha.vph_default_page; - } -#else /* !DYNTRANS_ALPHA */ - fatal("Not yet for non-1-level, non-Alpha\n"); -#endif /* !DYNTRANS_ALPHA */ + if (l3->refcount == 0) { + l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3; + cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3; + l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy; + + l2->refcount --; + if (l2->refcount < 0) { + fatal("xxx_invalidate_tlb_entry(): Refcount bug L2.\n"); + exit(1); + } + if (l2->refcount == 0) { + l2->next = cpu->cd.DYNTRANS_ARCH.next_free_l2; + cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2; + cpu->cd.DYNTRANS_ARCH.l1_64[x1] = + cpu->cd.DYNTRANS_ARCH.l2_64_dummy; + } + } #endif } #endif @@ -1058,27 +1245,21 @@ cpu->cd.DYNTRANS_ARCH.phystranslation[ index >> 5] &= ~ (1 << (index & 31)); #else - /* 2-level: */ -#ifdef DYNTRANS_ALPHA - struct alpha_vph_page *vph_p; - uint32_t a, b; - int kernel = 0; - - a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) - & (ALPHA_LEVEL0 - 1); - b = (vaddr_page >> ALPHA_LEVEL1_SHIFT) - & (ALPHA_LEVEL1 - 1); - if ((vaddr_page >> ALPHA_TOPSHIFT) == - ALPHA_TOP_KERNEL) { - vph_p = cpu->cd.alpha. - vph_table0_kernel[a]; - kernel = 1; - } else - vph_p = cpu->cd.alpha.vph_table0[a]; - vph_p->phys_page[b] = NULL; -#else /* !DYNTRANS_ALPHA */ - fatal("Not yet for non-1-level, non-Alpha\n"); -#endif /* !DYNTRANS_ALPHA */ + const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1; + const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1; + const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1; + uint32_t x1, x2, x3; + struct DYNTRANS_L2_64_TABLE *l2; + struct DYNTRANS_L3_64_TABLE *l3; + + 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; + l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; + l3 = l2->l3[x2]; + l3->phys_page[x3] = NULL; #endif } } @@ -1102,14 +1283,6 @@ #endif int found, r, lowest_index, start, end, useraccess = 0; -#ifdef DYNTRANS_ALPHA - uint32_t a, b; - struct alpha_vph_page *vph_p; - int kernel = 0; - /* fatal("update_translation_table(): v=0x%llx, h=%p w=%i" - " p=0x%llx\n", (long long)vaddr_page, host_page, writeflag, - (long long)paddr_page); */ -#else #ifdef MODE32 uint32_t index; vaddr_page &= 0xffffffffULL; @@ -1118,9 +1291,15 @@ " p=0x%x\n", (int)vaddr_page, host_page, writeflag, (int)paddr_page); */ #else /* !MODE32 */ - fatal("Neither 32-bit nor Alpha? 2\n"); - exit(1); -#endif + const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1; + const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1; + const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1; + uint32_t x1, x2, x3; + struct DYNTRANS_L2_64_TABLE *l2; + struct DYNTRANS_L3_64_TABLE *l3; + /* fatal("update_translation_table(): v=0x%"PRIx64", h=%p w=%i" + " p=0x%"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag, + (uint64_t)paddr_page); */ #endif if (writeflag & MEMORY_USER_ACCESS) { @@ -1201,42 +1380,6 @@ #endif /* Add the new translation to the table: */ -#ifdef DYNTRANS_ALPHA - a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1); - b = (vaddr_page >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1); - if ((vaddr_page >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) { - vph_p = cpu->cd.alpha.vph_table0_kernel[a]; - kernel = 1; - } else - vph_p = cpu->cd.alpha.vph_table0[a]; - if (vph_p == cpu->cd.alpha.vph_default_page) { - if (cpu->cd.alpha.vph_next_free_page != NULL) { - if (kernel) - vph_p = cpu->cd.alpha.vph_table0_kernel - [a] = cpu->cd.alpha. - vph_next_free_page; - else - vph_p = cpu->cd.alpha.vph_table0[a] = - cpu->cd.alpha.vph_next_free_page; - cpu->cd.alpha.vph_next_free_page = vph_p->next; - } else { - if (kernel) - vph_p = cpu->cd.alpha.vph_table0_kernel - [a] = malloc(sizeof(struct - alpha_vph_page)); - else - vph_p = cpu->cd.alpha.vph_table0[a] = - malloc(sizeof(struct - alpha_vph_page)); - memset(vph_p, 0, sizeof(struct alpha_vph_page)); - } - } - vph_p->refcount ++; - vph_p->host_load[b] = host_page; - vph_p->host_store[b] = writeflag? host_page : NULL; - vph_p->phys_addr[b] = paddr_page; - vph_p->phys_page[b] = NULL; -#else #ifdef MODE32 index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page); cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page; @@ -1250,8 +1393,45 @@ cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5] |= 1 << (index & 31); #endif -#endif /* 32 */ -#endif /* !ALPHA */ +#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; + l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; + if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) { + if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) { + l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] = + cpu->cd.DYNTRANS_ARCH.next_free_l2; + cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next; + } else { + int i; + l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] = + malloc(sizeof(struct DYNTRANS_L2_64_TABLE)); + for (i=0; i<(1 << DYNTRANS_L2N); i++) + l2->l3[i] = cpu->cd.DYNTRANS_ARCH. + l3_64_dummy; + } + } + l3 = l2->l3[x2]; + if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) { + if (cpu->cd.DYNTRANS_ARCH.next_free_l3 != NULL) { + l3 = l2->l3[x2] = + cpu->cd.DYNTRANS_ARCH.next_free_l3; + cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3->next; + } else { + l3 = l2->l3[x2] = zeroed_alloc(sizeof( + struct DYNTRANS_L3_64_TABLE)); + } + l2->refcount ++; + } + l3->host_load[x3] = host_page; + l3->host_store[x3] = writeflag? host_page : NULL; + l3->phys_addr[x3] = paddr_page; + l3->phys_page[x3] = NULL; + l3->vaddr_to_tlbindex[x3] = r + 1; + l3->refcount ++; +#endif /* !MODE32 */ } else { /* * The translation was already in the TLB. @@ -1267,27 +1447,6 @@ cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1; if (writeflag & MEM_DOWNGRADE) cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 0; -#ifdef DYNTRANS_ALPHA - a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1); - b = (vaddr_page >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1); - if ((vaddr_page >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) { - vph_p = cpu->cd.alpha.vph_table0_kernel[a]; - kernel = 1; - } else - vph_p = cpu->cd.alpha.vph_table0[a]; - vph_p->phys_page[b] = NULL; - if (vph_p->phys_addr[b] == paddr_page) { - if (writeflag & MEM_WRITE) - vph_p->host_store[b] = host_page; - if (writeflag & MEM_DOWNGRADE) - vph_p->host_store[b] = NULL; - } else { - /* Change the entire physical/host mapping: */ - vph_p->host_load[b] = host_page; - vph_p->host_store[b] = writeflag? host_page : NULL; - vph_p->phys_addr[b] = paddr_page; - } -#else #ifdef MODE32 index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page); cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL; @@ -1310,8 +1469,25 @@ writeflag? host_page : NULL; cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page; } -#endif /* 32 */ -#endif /* !ALPHA */ +#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; + l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; + l3 = l2->l3[x2]; + if (l3->phys_addr[x3] == paddr_page) { + if (writeflag & MEM_WRITE) + l3->host_store[x3] = host_page; + if (writeflag & MEM_DOWNGRADE) + l3->host_store[x3] = NULL; + } else { + /* Change the entire physical/host mapping: */ + l3->host_load[x3] = host_page; + l3->host_store[x3] = writeflag? host_page : NULL; + l3->phys_addr[x3] = paddr_page; + } +#endif /* !MODE32 */ } } #endif /* DYNTRANS_UPDATE_TRANSLATION_TABLE */ @@ -1325,30 +1501,22 @@ * Check for breakpoints. */ if (!single_step_breakpoint) { -#ifdef MODE32 - uint32_t curpc = cpu->pc; -#else - uint64_t curpc = cpu->pc; -#endif + MODE_uint_t curpc = cpu->pc; int i; for (i=0; imachine->n_breakpoints; i++) - if (curpc == -#ifdef MODE32 - (uint32_t) -#endif + if (curpc == (MODE_uint_t) cpu->machine->breakpoint_addr[i]) { if (!cpu->machine->instruction_trace) { int old_quiet_mode = quiet_mode; quiet_mode = 0; - DISASSEMBLE(cpu, ib, 1, 0, 0); + DISASSEMBLE(cpu, ib, 1, 0); quiet_mode = old_quiet_mode; } - fatal("BREAKPOINT: pc = 0x%llx\n(The " + fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The " "instruction has not yet executed.)\n", - (long long)cpu->pc); + (uint64_t)cpu->pc); #ifdef DYNTRANS_DELAYSLOT - if (cpu->cd.DYNTRANS_ARCH.delay_slot != - NOT_DELAYED) + if (cpu->delay_slot != NOT_DELAYED) fatal("ERROR! Breakpoint in a delay" " slot! Not yet supported.\n"); #endif @@ -1371,6 +1539,9 @@ * (Special case for 32-bit mode: set the corresponding bit in the * phystranslation[] array.) */ + /* Make sure cur_physpage is in synch: */ + cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *) + cpu->cd.DYNTRANS_ARCH.cur_ic_page; #ifdef MODE32 if (!(cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & TRANSLATIONS)) { uint32_t index = DYNTRANS_ADDR_TO_PAGENR((uint32_t)addr); @@ -1381,153 +1552,80 @@ cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= TRANSLATIONS; -#ifdef DYNTRANS_BACKEND - /* - * "Empty"/simple native dyntrans backend stuff: - * - * 1) If no translation is currently being done, but the translated - * instruction was simple enough, then let's start making a new - * native translation block. - * - * 2) If a native translation block is currently being constructed, - * but this instruction wasn't simple enough, then end the block - * (without including this instruction). - * - * 3) If a native translation block is currently being constructed, - * and this is a simple instruction, then add it. - */ - if (simple && cpu->translation_context.p == NULL && - dyntrans_backend_enable) { - size_t s = 0; - - if (cpu->translation_context.translation_buffer == NULL) { - cpu->translation_context.translation_buffer = - zeroed_alloc(DTB_TRANSLATION_SIZE_MAX + - DTB_TRANSLATION_SIZE_MARGIN); - } - - cpu->translation_context.p = - cpu->translation_context.translation_buffer; - - cpu->translation_context.ic_page = - cpu->cd.DYNTRANS_ARCH.cur_ic_page; - cpu->translation_context.start_instr_call_index = - ((size_t)ic - (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) - / (sizeof(*ic)); - - dtb_function_prologue(&cpu->translation_context, &s); - cpu->translation_context.p += s; - cpu->translation_context.n_simple = 0; - } - - /* If this is not a continuation of a simple translation, then - stop now! */ - if (cpu->translation_context.ic_page != cpu->cd.DYNTRANS_ARCH. - cur_ic_page || ic != &cpu->cd.DYNTRANS_ARCH.cur_ic_page[ - cpu->translation_context.start_instr_call_index + - cpu->translation_context.n_simple]) - simple = 0; - - if (cpu->translation_context.p != NULL && !simple) { - size_t s = 0, total; - - if (cpu->translation_context.n_simple > 1) { - dtb_generate_ptr_inc(cpu, &cpu->translation_context, - &s, &cpu->cd.DYNTRANS_ARCH.next_ic, - (cpu->translation_context.n_simple - 1) * - sizeof(*(cpu->cd.DYNTRANS_ARCH.next_ic))); - cpu->translation_context.p += s; - } - - dtb_function_epilogue(&cpu->translation_context, &s); - cpu->translation_context.p += s; - - cpu_dtb_do_fixups(cpu); -#if 0 -{ -int i; -unsigned char *addr = cpu->translation_context.translation_buffer; -printf("index = %i\n", cpu->translation_context.start_instr_call_index); -quiet_mode = 0; -for (i=0; i<4*32; i+=4) - alpha_cpu_disassemble_instr(cpu, (unsigned char *)addr + i, - 0, i, 0); -} -#endif - total = (size_t)cpu->translation_context.p - - (size_t)cpu->translation_context.translation_buffer; - - /* Copy the translated block to the translation cache: */ - /* Align first: */ - cpu->translation_cache_cur_ofs --; - cpu->translation_cache_cur_ofs |= 31; - cpu->translation_cache_cur_ofs ++; - - memcpy(cpu->translation_cache + cpu->translation_cache_cur_ofs, - cpu->translation_context.translation_buffer, total); - - /* Set the ic pointer: */ - ((struct DYNTRANS_IC *)cpu->translation_context.ic_page) - [cpu->translation_context.start_instr_call_index].f = - (void *) - (cpu->translation_cache + cpu->translation_cache_cur_ofs); - - /* Align cur_ofs afterwards as well, just to be safe. */ - cpu->translation_cache_cur_ofs += total; - cpu->translation_cache_cur_ofs --; - cpu->translation_cache_cur_ofs |= 31; - cpu->translation_cache_cur_ofs ++; - - /* Set the "combined instruction" flag for this page: */ - cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *) - cpu->cd.DYNTRANS_ARCH.cur_ic_page; - cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= COMBINATIONS; - - dtb_host_cacheinvalidate(0,0); /* p , size ... ); */ - - cpu->translation_context.p = NULL; - } - if (cpu->translation_context.p != NULL) { - size_t s = 0; - dtb_generate_fcall(cpu, &cpu->translation_context, - &s, (size_t)ic->f, (size_t)ic); - cpu->translation_context.p += s; - cpu->translation_context.n_simple ++; - } -#endif /* DYNTRANS_BACKEND */ - - /* * Now it is time to check for combinations of instructions that can * be converted into a single function call. * * Note: Single-stepping or instruction tracing doesn't work with - * instruction combination. + * instruction combination. For architectures with delay slots, + * we also ignore combinations if the delay slot is across a page + * boundary. */ - if (!single_step && !cpu->machine->instruction_trace) { + if (!single_step && !cpu->machine->instruction_trace +#ifdef DYNTRANS_DELAYSLOT + && !in_crosspage_delayslot +#endif + ) { if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL && cpu->machine->speed_tricks) cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic, addr & (DYNTRANS_PAGESIZE - 1)); - cpu->cd.DYNTRANS_ARCH.combination_check = NULL; + } + + cpu->cd.DYNTRANS_ARCH.combination_check = NULL; + + /* An additional check, to catch some bugs: */ + if (ic->f == ( +#ifdef DYNTRANS_DUALMODE_32 + cpu->is_32bit? instr32(to_be_translated) : +#endif + instr(to_be_translated))) { + fatal("INTERNAL ERROR: ic->f not set!\n"); + goto bad; + } + if (ic->f == NULL) { + fatal("INTERNAL ERROR: ic->f == NULL!\n"); + goto bad; } /* ... and finally execute the translated instruction: */ - if (single_step_breakpoint) { + if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED) +#ifdef DYNTRANS_DELAYSLOT + || in_crosspage_delayslot +#endif + ) { /* * Special case when single-stepping: Execute the translated * instruction, but then replace it with a "to be translated" * directly afterwards. */ single_step_breakpoint = 0; +#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH + cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0]; +#endif ic->f(cpu, ic); ic->f = #ifdef DYNTRANS_DUALMODE_32 cpu->is_32bit? instr32(to_be_translated) : #endif instr(to_be_translated); - } else +#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH + ic->arg[0] = 0; +#endif + } else { +#ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH + cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0]; + + /* Additional check, for variable length ISAs: */ + if (ic->arg[0] == 0) { + fatal("INTERNAL ERROR: instr len = 0!\n"); + goto bad; + } +#endif + + /* Finally finally :-), execute the instruction: */ ic->f(cpu, ic); + } return; @@ -1541,13 +1639,13 @@ if (cpu->machine->instruction_trace) #ifdef MODE32 - fatal(" at 0x%x\n", (int)cpu->pc); + fatal(" at 0x%"PRIx32"\n", (uint32_t)cpu->pc); #else - fatal(" at 0x%llx\n", (long long)cpu->pc); + fatal(" at 0x%"PRIx64"\n", (uint64_t)cpu->pc); #endif else { fatal(":\n"); - DISASSEMBLE(cpu, ib, 1, 0, 0); + DISASSEMBLE(cpu, ib, 1, 0); } cpu->running = 0;