--- trunk/src/bintrans.c 2007/10/08 16:18:00 4 +++ trunk/src/bintrans.c 2007/10/08 16:18:38 12 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: bintrans.c,v 1.165 2005/04/27 16:37:34 debug Exp $ + * $Id: bintrans.c,v 1.177 2005/08/14 15:47:36 debug Exp $ * * Dynamic binary translation. * @@ -81,9 +81,6 @@ * * o) Load/stores: TODO: Comment. * - * Testing: Running regression tests with and without the binary translator - * enabled should obviously result in the exact same results, or something is - * wrong. * * The general idea is something like this: * @@ -142,10 +139,12 @@ static void bintrans_write_pc_inc(unsigned char **addrp); static void bintrans_write_quickjump(struct memory *mem, unsigned char *quickjump_code, uint32_t chunkoffset); -static int bintrans_write_instruction__addiu_etc(unsigned char **addrp, int rt, - int rs, int imm, int instruction_type); -static int bintrans_write_instruction__addu_etc(unsigned char **addrp, int rd, - int rs, int rt, int sa, int instruction_type); +static int bintrans_write_instruction__addiu_etc(struct memory *mem, + unsigned char **addrp, int rt, int rs, int imm, + int instruction_type); +static int bintrans_write_instruction__addu_etc(struct memory *mem, + unsigned char **addrp, int rd, int rs, int rt, int sa, + int instruction_type); static int bintrans_write_instruction__branch(unsigned char **addrp, int instruction_type, int regimm_type, int rt, int rs, int imm); static int bintrans_write_instruction__jr(unsigned char **addrp, int rs, @@ -157,7 +156,7 @@ int only_care_about_chunk_p, int p, int forward); static int bintrans_write_instruction__loadstore(struct memory *mem, unsigned char **addrp, int rt, int imm, int rs, int instruction_type, - int bigendian); + int bigendian, int do_alignment_check); static int bintrans_write_instruction__lui(unsigned char **addrp, int rt, int imm); static int bintrans_write_instruction__mfmthilo(unsigned char **addrp, int rd, @@ -202,17 +201,7 @@ #define BACKEND_NAME "i386" #include "bintrans_i386.c" #else -#ifdef MIPS -#define BACKEND_NAME "MIPS" -#include "bintrans_mips.c" -#else -#ifdef SPARCV9 -#define BACKEND_NAME "UltraSPARC" -#include "bintrans_sparcv9.c" -#else #error Unsupported host architecture for bintrans. -#endif /* SPARCV9 */ -#endif /* MIPS */ #endif /* I386 */ #endif /* ALPHA */ @@ -287,13 +276,16 @@ { int i, n = 1 << BINTRANS_CACHE_N_INDEX_BITS; + if (cpu->machine->arch != ARCH_MIPS) + return; + for (i=0; imem->translation_page_entry_array[i] = NULL; cpu->mem->translation_code_chunk_space_head = 0; cpu->mem->n_quick_jumps = 0; - /* debug("bintrans: Starting over!\n"); */ + debug("[ bintrans: Starting over! ]\n"); clear_all_chunks_from_all_tables(cpu); } @@ -312,7 +304,7 @@ a = (vaddr >> 22) & 0x3ff; b = (vaddr >> 12) & 0x3ff; tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a]; - if (tbl1->haddr_entry[b] != NULL) + if (tbl1->haddr_entry[b*2] != NULL) tbl1->bintrans_chunks[b] = chunk0; break; default: @@ -348,7 +340,7 @@ int rs,rt,rd,sa,imm; uint32_t *potential_chunk_p; /* for branches */ int byte_order_cached_bigendian; - int delayed_branch, stop_after_delayed_branch; + int delayed_branch, stop_after_delayed_branch, return_code_written; uint64_t delayed_branch_new_p; int prev_p; @@ -420,8 +412,7 @@ /* ... and align again: */ cpu->mem->translation_code_chunk_space_head = - ((cpu->mem->translation_code_chunk_space_head - 1) | 63) - + 1; + ((cpu->mem->translation_code_chunk_space_head - 1) | 31)+1; /* Add the entry to the array: */ memset(tep, 0, sizeof(struct translation_page_entry)); @@ -453,6 +444,7 @@ try_to_translate = 1; n_translated = 0; res = 0; + return_code_written = 0; delayed_branch = 0; stop_after_delayed_branch = 0; delayed_branch_new_p = 0; @@ -503,6 +495,7 @@ bintrans_write_chunkreturn_fail(&ca); tep->flags[prev_p >> 3] |= mask; try_to_translate = 0; + return_code_written = 1; } else { translated = bintrans_write_instruction__tlb_rfe_etc(&ca, special6 == SPECIAL_BREAK? CALL_BREAK : CALL_SYSCALL); @@ -544,7 +537,7 @@ rd = rt = rs = sa = 0; special6 = SPECIAL_SLL; } - translated = try_to_translate = bintrans_write_instruction__addu_etc(&ca, rd, rs, rt, sa, special6); + translated = try_to_translate = bintrans_write_instruction__addu_etc(cpu->mem, &ca, rd, rs, rt, sa, special6); n_translated += translated; break; case SPECIAL_MFHI: @@ -566,6 +559,7 @@ tep->flags[prev_p >> 3] |= mask; } try_to_translate = 0; + return_code_written = 1; } break; @@ -584,7 +578,6 @@ delayed_branch_new_p = p + 4 + 4*imm; break; default: - try_to_translate = 0; /* Untranslatable: */ /* TODO: this code should only be in one place */ bintrans_write_chunkreturn_fail(&ca); @@ -593,6 +586,7 @@ tep->flags[prev_p >> 3] |= mask; } try_to_translate = 0; + return_code_written = 1; } break; @@ -637,8 +631,8 @@ case HI6_DADDI: case HI6_DADDIU: translated = try_to_translate = - bintrans_write_instruction__addiu_etc(&ca, - instr[2] & 31, + bintrans_write_instruction__addiu_etc(cpu->mem, + &ca, instr[2] & 31, ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7), (instr[1] << 8) + instr[0], hi6); n_translated += translated; @@ -680,8 +674,17 @@ translated = try_to_translate = bintrans_write_instruction__mfc_mtc(cpu->mem, &ca, 0, 1, rt, rd, 1); n_translated += translated; } - } else + } else { + /* Untranslatable: */ + /* TODO: this code should only be in one place */ + bintrans_write_chunkreturn_fail(&ca); + { + int mask = 1 << (prev_p & 7); + tep->flags[prev_p >> 3] |= mask; + } try_to_translate = 0; + return_code_written = 1; + } break; case 0x42: if (instr[2] == 0x00 && instr[1] == 0x00 && instr[0] == 0x10) { @@ -712,16 +715,32 @@ n_translated += translated; } else if (instr[2] == 0 && instr[1] == 0 && (instr[0] == 0x21 || instr[0] == 0x22)) { /* standby and suspend on VR41xx etc ==> NOP */ - translated = try_to_translate = bintrans_write_instruction__addu_etc(&ca, 0, 0, 0, 0, SPECIAL_SLL); + translated = try_to_translate = bintrans_write_instruction__addu_etc(cpu->mem, &ca, 0, 0, 0, 0, SPECIAL_SLL); n_translated += translated; - } else + } else { + /* Untranslatable: */ + /* TODO: this code should only be in one place */ + bintrans_write_chunkreturn_fail(&ca); + { + int mask = 1 << (prev_p & 7); + tep->flags[prev_p >> 3] |= mask; + } try_to_translate = 0; + return_code_written = 1; + } break; default: + /* Untranslatable: */ + /* TODO: this code should only be in one place */ + bintrans_write_chunkreturn_fail(&ca); + { + int mask = 1 << (prev_p & 7); + tep->flags[prev_p >> 3] |= mask; + } try_to_translate = 0; + return_code_written = 1; } break; - #if 0 case HI6_LQ_MDMX: #endif @@ -748,12 +767,14 @@ imm = (instr[1] << 8) + instr[0]; if (imm >= 32768) imm -= 65536; - translated = try_to_translate = bintrans_write_instruction__loadstore(cpu->mem, &ca, rt, imm, rs, hi6, byte_order_cached_bigendian); + translated = try_to_translate = bintrans_write_instruction__loadstore(cpu->mem, &ca, rt, imm, rs, hi6, + byte_order_cached_bigendian, + cpu->machine->dyntrans_alignment_check); n_translated += translated; break; case HI6_CACHE: - translated = try_to_translate = bintrans_write_instruction__addu_etc(&ca, 0, 0, 0, 0, SPECIAL_SLL); + translated = try_to_translate = bintrans_write_instruction__addu_etc(cpu->mem, &ca, 0, 0, 0, 0, SPECIAL_SLL); n_translated += translated; break; @@ -766,6 +787,7 @@ tep->flags[prev_p >> 3] |= mask; } try_to_translate = 0; + return_code_written = 1; } if (translated && delayed_branch) { @@ -791,10 +813,9 @@ cpu->mem, &ca, potential_chunk_p, &tep->chunk[0], 0, delayed_branch_new_p & 0xfff, forward); -#if 0 + if (stop_after_delayed_branch) try_to_translate = 0; -#endif } } @@ -821,7 +842,8 @@ if (tep->flags[(prev_p+1) >> 3] & mask && !delayed_branch) { bintrans_write_chunkreturn_fail(&ca); - /* try_to_translate = 0; */ + try_to_translate = 0; + return_code_written = 1; break; } @@ -830,14 +852,17 @@ if (tep->chunk[prev_p+1] != 0 && !delayed_branch) { bintrans_write_instruction__delayedbranch(cpu->mem, &ca, &tep->chunk[prev_p+1], NULL, 1, p+4, 1); + try_to_translate = 0; + return_code_written = 1; /* try_to_translate = 0; */ break; } - if (n_translated > 80 && !delayed_branch) { + if (n_translated > 120 && !delayed_branch) { bintrans_write_instruction__delayedbranch(cpu->mem, &ca, &tep->chunk[prev_p+1], NULL, 1, p+4, 1); - /* try_to_translate = 0; */ + try_to_translate = 0; + return_code_written = 1; break; } } @@ -864,7 +889,8 @@ cpu->mem->translation_code_chunk_space_head; /* Add return code: */ - bintrans_write_chunkreturn(&ca); + if (!return_code_written) + bintrans_write_chunkreturn(&ca); /* chunk_len = nr of bytes occupied by the new code chunk */ chunk_len = (size_t)ca - (size_t)ca2; @@ -876,7 +902,7 @@ /* Align the code chunk space: */ cpu->mem->translation_code_chunk_space_head = - ((cpu->mem->translation_code_chunk_space_head - 1) | 63) + 1; + ((cpu->mem->translation_code_chunk_space_head - 1) | 31) + 1; /* RUN the code chunk: */ @@ -918,7 +944,7 @@ /* tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a]; */ tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0[a]; - if (tbl1->haddr_entry[b] != NULL) { + if (tbl1->haddr_entry[b*2] != NULL) { paddr = tbl1->paddr_entry[b] | (cpu->pc & 0xfff); ok = 1; } @@ -963,7 +989,7 @@ #if 1 /* We have no translation. */ - if ((cpu->pc & 0xfff00000) == 0xbfc00000 && + if ((cpu->pc & 0xdff00000) == 0x9fc00000 && cpu->machine->prom_emulation) return cpu->cd.mips.bintrans_instructions_executed; @@ -981,11 +1007,10 @@ cpu->cd.mips.vaddr_to_hostaddr_table0_kernel) ok = 0; tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a]; - if (ok && tbl1->haddr_entry[b] != NULL) { + if (ok && tbl1->haddr_entry[b*2] != NULL) { cpu->cd.mips.pc_last_virtual_page = cpu->pc & ~0xfff; cpu->cd.mips.pc_last_physical_page = paddr & ~0xfff; - cpu->cd.mips.pc_last_host_4k_page = (unsigned char *) - (((size_t)tbl1->haddr_entry[b]) & ~1); + cpu->cd.mips.pc_last_host_4k_page = (unsigned char *)tbl1->haddr_entry[b*2]; cpu->cd.mips.pc_bintrans_host_4kpage = cpu->cd.mips.pc_last_host_4k_page; cpu->cd.mips.pc_bintrans_paddr = paddr; @@ -1041,7 +1066,8 @@ int i, offset; cpu->cd.mips.chunk_base_address = cpu->mem->translation_code_chunk_space; - cpu->cd.mips.bintrans_loadstore_32bit = bintrans_loadstore_32bit; + cpu->cd.mips.bintrans_load_32bit = bintrans_load_32bit; + cpu->cd.mips.bintrans_store_32bit = bintrans_store_32bit; cpu->cd.mips.bintrans_jump_to_32bit_pc = bintrans_jump_to_32bit_pc; cpu->cd.mips.bintrans_fast_tlbwri = coproc_tlbwri; cpu->cd.mips.bintrans_fast_tlbpr = coproc_tlbpr; @@ -1059,19 +1085,42 @@ cpu->cd.mips.vaddr_to_hostaddr_r2k3k_dcachetable = zeroed_alloc(sizeof(struct vth32_table)); for (i=0; i<1024; i++) { - cpu->cd.mips.vaddr_to_hostaddr_r2k3k_dcachetable->haddr_entry[i] = - (void *)(((size_t)cpu->cd.mips.cache[0]+offset) | 1); + cpu->cd.mips.vaddr_to_hostaddr_r2k3k_dcachetable-> + haddr_entry[i*2] = (void *)((size_t)cpu->cd.mips.cache[0]+offset); + cpu->cd.mips.vaddr_to_hostaddr_r2k3k_dcachetable-> + haddr_entry[i*2+1] = (void *)((size_t)cpu->cd.mips.cache[0]+offset); offset = (offset + 4096) % cpu->cd.mips.cache_size[0]; } cpu->cd.mips.vaddr_to_hostaddr_r2k3k_dcachetable->refcount = 1024; + /* 1M entry cache stuff for R2K/3K: */ + if (cpu->cd.mips.cpu_type.isa_level == 1) { + cpu->cd.mips.huge_r2k3k_cache_table = + zeroed_alloc(1048576 * sizeof(unsigned char *)); +#if 1 + for (i=0; i<1048576; i++) { + unsigned char *ptr = NULL; + if (i < (0xa0000000ULL >> 12) || + i >= (0xc0000000ULL >> 12)) + ptr = cpu->cd.mips. + vaddr_to_hostaddr_r2k3k_dcachetable + ->haddr_entry[(i & 1023) * 2]; + cpu->cd.mips.huge_r2k3k_cache_table[i] = ptr; + } +#endif + } + /* Instruction cache: */ offset = 0; cpu->cd.mips.vaddr_to_hostaddr_r2k3k_icachetable = zeroed_alloc(sizeof(struct vth32_table)); for (i=0; i<1024; i++) { - cpu->cd.mips.vaddr_to_hostaddr_r2k3k_icachetable->haddr_entry[i] = - (void *)(((size_t)cpu->cd.mips.cache[1]+offset) | 1); + cpu->cd.mips.vaddr_to_hostaddr_r2k3k_icachetable-> + haddr_entry[i*2] = + (void *)((size_t)cpu->cd.mips.cache[1]+offset); + cpu->cd.mips.vaddr_to_hostaddr_r2k3k_icachetable-> + haddr_entry[i*2+1] = + (void *)((size_t)cpu->cd.mips.cache[1]+offset); offset = (offset + 4096) % cpu->cd.mips.cache_size[1]; } cpu->cd.mips.vaddr_to_hostaddr_r2k3k_icachetable->refcount = 1024;