--- trunk/src/cpus/cpu_mips_instr.c 2007/10/08 16:21:06 33 +++ trunk/src/cpus/cpu_mips_instr.c 2007/10/08 16:21:17 34 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2006 Anders Gavare. All rights reserved. + * Copyright (C) 2005-2007 Anders Gavare. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: cpu_mips_instr.c,v 1.118 2006/10/29 05:10:27 debug Exp $ + * $Id: cpu_mips_instr.c,v 1.124 2007/02/03 10:00:52 debug Exp $ * * MIPS instructions. * @@ -2586,512 +2586,8 @@ #ifdef MODE32 -/* - * multi_sw_2, _3, _4: - * - * sw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2] - */ -X(multi_sw_2_le) -{ - uint32_t *page; - MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; - MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; - MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; - uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; - - page = (uint32_t *) cpu->cd.mips.host_store[index0]; - - /* Fallback: */ - if (cpu->delay_slot || - page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || - index0 != index1) { - /* Normal safe sw: */ - mips32_loadstore[8 + 2 * 2](cpu, ic); - return; - } - - addr0 = (addr0 >> 2) & 0x3ff; - addr1 = (addr1 >> 2) & 0x3ff; - - r1 = reg(ic[0].arg[0]); - r2 = reg(ic[1].arg[0]); - - r1 = LE32_TO_HOST(r1); - r2 = LE32_TO_HOST(r2); - - page[addr0] = r1; - page[addr1] = r2; - - cpu->n_translated_instrs ++; - cpu->cd.mips.next_ic ++; -} -X(multi_sw_2_be) -{ - uint32_t *page; - MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; - MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; - MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; - uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; - - page = (uint32_t *) cpu->cd.mips.host_store[index0]; - - /* Fallback: */ - if (cpu->delay_slot || - page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || - index0 != index1) { - /* Normal safe sw: */ - mips32_loadstore[16 + 8 + 2 * 2](cpu, ic); - return; - } - - addr0 = (addr0 >> 2) & 0x3ff; - addr1 = (addr1 >> 2) & 0x3ff; - - r1 = reg(ic[0].arg[0]); - r2 = reg(ic[1].arg[0]); - - r1 = BE32_TO_HOST(r1); - r2 = BE32_TO_HOST(r2); - - page[addr0] = r1; - page[addr1] = r2; - - cpu->n_translated_instrs ++; - cpu->cd.mips.next_ic ++; -} -X(multi_sw_3_le) -{ - uint32_t *page; - MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; - MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; - MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; - MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; - uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, - index2 = addr2 >> 12; - - page = (uint32_t *) cpu->cd.mips.host_store[index0]; - - /* Fallback: */ - if (cpu->delay_slot || - page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || - (addr2 & 3) != 0 || index0 != index1 || index0 != index2) { - /* Normal safe sw: */ - mips32_loadstore[8 + 2 * 2](cpu, ic); - return; - } - - addr0 = (addr0 >> 2) & 0x3ff; - addr1 = (addr1 >> 2) & 0x3ff; - addr2 = (addr2 >> 2) & 0x3ff; - - /* printf("addr0=%x 1=%x 2=%x\n", - (int)addr0, (int)addr1, (int)addr2); */ - - r1 = reg(ic[0].arg[0]); - r2 = reg(ic[1].arg[0]); - r3 = reg(ic[2].arg[0]); - - r1 = LE32_TO_HOST(r1); - r2 = LE32_TO_HOST(r2); - r3 = LE32_TO_HOST(r3); - - page[addr0] = r1; - page[addr1] = r2; - page[addr2] = r3; - - cpu->n_translated_instrs += 2; - cpu->cd.mips.next_ic += 2; -} -X(multi_sw_3_be) -{ - uint32_t *page; - MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; - MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; - MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; - MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; - uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, - index2 = addr2 >> 12; - - page = (uint32_t *) cpu->cd.mips.host_store[index0]; - - /* Fallback: */ - if (cpu->delay_slot || - page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || - (addr2 & 3) != 0 || index0 != index1 || index0 != index2) { - /* Normal safe sw: */ - mips32_loadstore[16 + 8 + 2 * 2](cpu, ic); - return; - } - - addr0 = (addr0 >> 2) & 0x3ff; - addr1 = (addr1 >> 2) & 0x3ff; - addr2 = (addr2 >> 2) & 0x3ff; - - /* printf("addr0=%x 1=%x 2=%x\n", - (int)addr0, (int)addr1, (int)addr2); */ - - r1 = reg(ic[0].arg[0]); - r2 = reg(ic[1].arg[0]); - r3 = reg(ic[2].arg[0]); - - r1 = BE32_TO_HOST(r1); - r2 = BE32_TO_HOST(r2); - r3 = BE32_TO_HOST(r3); - - page[addr0] = r1; - page[addr1] = r2; - page[addr2] = r3; - - cpu->n_translated_instrs += 2; - cpu->cd.mips.next_ic += 2; -} -X(multi_sw_4_le) -{ - uint32_t *page; - MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; - MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; - MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; - MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; - MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; - uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, - index2 = addr2 >> 12, index3 = addr3 >> 12; - - page = (uint32_t *) cpu->cd.mips.host_store[index0]; - - /* Fallback: */ - if (cpu->delay_slot || - page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || - (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 || - index0 != index2 || index0 != index3) { - /* Normal safe sw: */ - mips32_loadstore[8 + 2 * 2](cpu, ic); - return; - } - - addr0 = (addr0 >> 2) & 0x3ff; - addr1 = (addr1 >> 2) & 0x3ff; - addr2 = (addr2 >> 2) & 0x3ff; - addr3 = (addr3 >> 2) & 0x3ff; - - r1 = reg(ic[0].arg[0]); - r2 = reg(ic[1].arg[0]); - r3 = reg(ic[2].arg[0]); - r4 = reg(ic[3].arg[0]); - - r1 = LE32_TO_HOST(r1); - r2 = LE32_TO_HOST(r2); - r3 = LE32_TO_HOST(r3); - r4 = LE32_TO_HOST(r4); - - page[addr0] = r1; - page[addr1] = r2; - page[addr2] = r3; - page[addr3] = r4; - - cpu->n_translated_instrs += 3; - cpu->cd.mips.next_ic += 3; -} -X(multi_sw_4_be) -{ - uint32_t *page; - MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; - MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; - MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; - MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; - MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; - uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, - index2 = addr2 >> 12, index3 = addr3 >> 12; - - page = (uint32_t *) cpu->cd.mips.host_store[index0]; - - /* Fallback: */ - if (cpu->delay_slot || - page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || - (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 || - index0 != index2 || index0 != index3) { - /* Normal safe sw: */ - mips32_loadstore[16 + 8 + 2 * 2](cpu, ic); - return; - } - - addr0 = (addr0 >> 2) & 0x3ff; - addr1 = (addr1 >> 2) & 0x3ff; - addr2 = (addr2 >> 2) & 0x3ff; - addr3 = (addr3 >> 2) & 0x3ff; - - r1 = reg(ic[0].arg[0]); - r2 = reg(ic[1].arg[0]); - r3 = reg(ic[2].arg[0]); - r4 = reg(ic[3].arg[0]); - - r1 = BE32_TO_HOST(r1); - r2 = BE32_TO_HOST(r2); - r3 = BE32_TO_HOST(r3); - r4 = BE32_TO_HOST(r4); - - page[addr0] = r1; - page[addr1] = r2; - page[addr2] = r3; - page[addr3] = r4; - - cpu->n_translated_instrs += 3; - cpu->cd.mips.next_ic += 3; -} -#endif - - -#ifdef MODE32 -/* - * multi_lw_2, _3, _4: - * - * lw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2] - */ -X(multi_lw_2_le) -{ - uint32_t *page; - MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; - MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; - MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; - uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; - - page = (uint32_t *) cpu->cd.mips.host_load[index0]; - - /* Fallback: */ - if (cpu->delay_slot || - page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || - index0 != index1) { - /* Normal safe lw: */ - mips32_loadstore[2 * 2 + 1](cpu, ic); - return; - } - - addr0 = (addr0 >> 2) & 0x3ff; - addr1 = (addr1 >> 2) & 0x3ff; - - r1 = page[addr0]; - r2 = page[addr1]; - - r1 = LE32_TO_HOST(r1); - r2 = LE32_TO_HOST(r2); - - reg(ic[0].arg[0]) = r1; - reg(ic[1].arg[0]) = r2; - - cpu->n_translated_instrs ++; - cpu->cd.mips.next_ic ++; -} -X(multi_lw_2_be) -{ - uint32_t *page; - MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2; - MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; - MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; - uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12; - - page = (uint32_t *) cpu->cd.mips.host_load[index0]; - - /* Fallback: */ - if (cpu->delay_slot || - page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || - index0 != index1) { - /* Normal safe lw: */ - mips32_loadstore[16 + 2 * 2 + 1](cpu, ic); - return; - } - - addr0 = (addr0 >> 2) & 0x3ff; - addr1 = (addr1 >> 2) & 0x3ff; - - r1 = page[addr0]; - r2 = page[addr1]; - - r1 = BE32_TO_HOST(r1); - r2 = BE32_TO_HOST(r2); - - reg(ic[0].arg[0]) = r1; - reg(ic[1].arg[0]) = r2; - - cpu->n_translated_instrs ++; - cpu->cd.mips.next_ic ++; -} -X(multi_lw_3_le) -{ - uint32_t *page; - MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; - MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; - MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; - MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; - uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, - index2 = addr2 >> 12; - - page = (uint32_t *) cpu->cd.mips.host_load[index0]; - - /* Fallback: */ - if (cpu->delay_slot || - page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || - (addr2 & 3) != 0 || index0 != index1 || index0 != index2) { - /* Normal safe lw: */ - mips32_loadstore[2 * 2 + 1](cpu, ic); - return; - } - - addr0 = (addr0 >> 2) & 0x3ff; - addr1 = (addr1 >> 2) & 0x3ff; - addr2 = (addr2 >> 2) & 0x3ff; - - /* printf("addr0=%x 1=%x 2=%x\n", - (int)addr0, (int)addr1, (int)addr2); */ - - r1 = page[addr0]; - r2 = page[addr1]; - r3 = page[addr2]; - - r1 = LE32_TO_HOST(r1); - r2 = LE32_TO_HOST(r2); - r3 = LE32_TO_HOST(r3); - - reg(ic[0].arg[0]) = r1; - reg(ic[1].arg[0]) = r2; - reg(ic[2].arg[0]) = r3; - - cpu->n_translated_instrs += 2; - cpu->cd.mips.next_ic += 2; -} -X(multi_lw_3_be) -{ - uint32_t *page; - MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3; - MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; - MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; - MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; - uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, - index2 = addr2 >> 12; - - page = (uint32_t *) cpu->cd.mips.host_load[index0]; - - /* Fallback: */ - if (cpu->delay_slot || - page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || - (addr2 & 3) != 0 || index0 != index1 || index0 != index2) { - /* Normal safe lw: */ - mips32_loadstore[16 + 2 * 2 + 1](cpu, ic); - return; - } - - addr0 = (addr0 >> 2) & 0x3ff; - addr1 = (addr1 >> 2) & 0x3ff; - addr2 = (addr2 >> 2) & 0x3ff; - - /* printf("addr0=%x 1=%x 2=%x\n", - (int)addr0, (int)addr1, (int)addr2); */ - - r1 = page[addr0]; - r2 = page[addr1]; - r3 = page[addr2]; - - r1 = BE32_TO_HOST(r1); - r2 = BE32_TO_HOST(r2); - r3 = BE32_TO_HOST(r3); - - reg(ic[0].arg[0]) = r1; - reg(ic[1].arg[0]) = r2; - reg(ic[2].arg[0]) = r3; - - cpu->n_translated_instrs += 2; - cpu->cd.mips.next_ic += 2; -} -X(multi_lw_4_le) -{ - uint32_t *page; - MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; - MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; - MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; - MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; - MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; - uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, - index2 = addr2 >> 12, index3 = addr3 >> 12; - - page = (uint32_t *) cpu->cd.mips.host_load[index0]; - - /* Fallback: */ - if (cpu->delay_slot || - page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || - (addr2 & 3) != 0 || (addr3 & 3) != 0 || - index0 != index1 || index0 != index2 || index0 != index3) { - /* Normal safe lw: */ - mips32_loadstore[2 * 2 + 1](cpu, ic); - return; - } - - addr0 = (addr0 >> 2) & 0x3ff; - addr1 = (addr1 >> 2) & 0x3ff; - addr2 = (addr2 >> 2) & 0x3ff; - addr3 = (addr3 >> 2) & 0x3ff; - - r1 = page[addr0]; - r2 = page[addr1]; - r3 = page[addr2]; - r4 = page[addr3]; - - r1 = LE32_TO_HOST(r1); - r2 = LE32_TO_HOST(r2); - r3 = LE32_TO_HOST(r3); - r4 = LE32_TO_HOST(r4); - - reg(ic[0].arg[0]) = r1; - reg(ic[1].arg[0]) = r2; - reg(ic[2].arg[0]) = r3; - reg(ic[3].arg[0]) = r4; - - cpu->n_translated_instrs += 3; - cpu->cd.mips.next_ic += 3; -} -X(multi_lw_4_be) -{ - uint32_t *page; - MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4; - MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2]; - MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2]; - MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2]; - MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2]; - uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12, - index2 = addr2 >> 12, index3 = addr3 >> 12; - - page = (uint32_t *) cpu->cd.mips.host_load[index0]; - - /* Fallback: */ - if (cpu->delay_slot || - page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 || - (addr2 & 3) != 0 || (addr3 & 3) != 0 || - index0 != index1 || index0 != index2 || index0 != index3) { - /* Normal safe lw: */ - mips32_loadstore[16 + 2 * 2 + 1](cpu, ic); - return; - } - - addr0 = (addr0 >> 2) & 0x3ff; - addr1 = (addr1 >> 2) & 0x3ff; - addr2 = (addr2 >> 2) & 0x3ff; - addr3 = (addr3 >> 2) & 0x3ff; - - r1 = page[addr0]; - r2 = page[addr1]; - r3 = page[addr2]; - r4 = page[addr3]; - - r1 = BE32_TO_HOST(r1); - r2 = BE32_TO_HOST(r2); - r3 = BE32_TO_HOST(r3); - r4 = BE32_TO_HOST(r4); - - reg(ic[0].arg[0]) = r1; - reg(ic[1].arg[0]) = r2; - reg(ic[2].arg[0]) = r3; - reg(ic[3].arg[0]) = r4; - - cpu->n_translated_instrs += 3; - cpu->cd.mips.next_ic += 3; -} +/* multi_{l,s}w_2, _3, etc. */ +#include "tmp_mips_loadstore_multi.c" #endif @@ -3881,6 +3377,12 @@ int in_crosspage_delayslot = 0; void (*samepage_function)(struct cpu *, struct mips_instr_call *); int store, signedness, size; +#ifdef NATIVE_CODE_GENERATION + int native = 0; + + if (!cpu->currently_translating_to_native) + cpu->native_code_function_pointer = (void *) &ic->f; +#endif /* Figure out the (virtual) address of the instruction: */ low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) @@ -4030,6 +3532,13 @@ default:goto bad; } } + +#ifdef NATIVE_CODE_GENERATION + if (native_code_translation_enabled && + !cpu->delay_slot && ic->f == instr(nop)) + native = native_nop(cpu); +#endif + break; case SPECIAL_ADD: @@ -4164,6 +3673,7 @@ if (ic->f == instr(addu)) cpu->cd.mips.combination_check = COMBINE(addu); + break; case SPECIAL_JR: @@ -4355,6 +3865,14 @@ instruction combinations, to do lui + addiu, etc. */ if (rt == MIPS_GPR_ZERO) ic->f = instr(nop); +#ifdef NATIVE_CODE_GENERATION +#ifdef MODE32 + if (native_code_translation_enabled && !cpu->delay_slot + && (addr & 0xffc) >= 4) + native = native_set_u32_p32(cpu, + ic->arg[1], ®(&cpu->cd.mips.gpr[rt])); +#endif +#endif break; case HI6_J: @@ -4588,6 +4106,25 @@ goto bad; break; + case HI6_COP3: + /* Always cause a coprocessor unusable exception if + there is no coprocessor 3: */ + if (cpu->cd.mips.coproc[3] == NULL) { + ic->f = instr(cpu); + ic->arg[0] = 3; + break; + } + + if (iword == 0x4d00ffff) { + /* R2020 writeback thing, used by e.g. NetBSD/pmax + on MIPSMATE. */ + ic->f = instr(nop); + } else { + fatal("COP3 iword=0x%08x\n", iword); + goto bad; + } + break; + case HI6_SPECIAL2: if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) { /* R5900, TX79/C790, have MMI instead of SPECIAL2: */ @@ -5031,6 +4568,7 @@ default:goto bad; } + #ifdef MODE32 if (x64) { static int has_warned = 0; @@ -5043,6 +4581,18 @@ } #endif +#ifdef NATIVE_CODE_GENERATION + /* + * End the native code generation when an instruction is translated + * (or found in the following slow) which is not translatable. + */ + if (cpu->currently_translating_to_native && (!native || + (addr & 0xffc) == 0xffc || + cpu->cd.mips.next_ic->f != instr(to_be_translated))) { + native_commit(cpu); + } +#endif + #define DYNTRANS_TO_BE_TRANSLATED_TAIL #include "cpu_dyntrans.c"