diff --git a/src/emu/cpu/mips/mips3.h b/src/emu/cpu/mips/mips3.h index 2d2fce7ed03..5910669e6bc 100644 --- a/src/emu/cpu/mips/mips3.h +++ b/src/emu/cpu/mips/mips3.h @@ -544,20 +544,28 @@ private: void static_generate_tlb_mismatch(); void static_generate_exception(UINT8 exception, int recover, const char *name); void static_generate_memory_accessor(int mode, int size, int iswrite, int ismasked, const char *name, uml::code_handle **handleptr); + void generate_update_mode(drcuml_block *block); void generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, int allow_exception); void generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast); void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); void generate_delay_slot_and_branch(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT8 linkreg); + int generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); int generate_special(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); int generate_regimm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); int generate_idt(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); + int generate_set_cop0_reg(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT8 reg); int generate_get_cop0_reg(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT8 reg); int generate_cop0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); int generate_cop1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); int generate_cop1x(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); + + void check_cop0_access(drcuml_block *block); + void check_cop1_access(drcuml_block *block); + void generate_badcop(drcuml_block *block, const int cop); + void log_add_disasm_comment(drcuml_block *block, UINT32 pc, UINT32 op); const char *log_desc_flags_to_string(UINT32 flags); void log_register_list(drcuml_state *drcuml, const char *string, const UINT32 *reglist, const UINT32 *regnostarlist); @@ -743,12 +751,13 @@ private: /* fix me -- how do we make this work?? */ #define MIPS3DRC_STRICT_VERIFY 0x0001 /* verify all instructions */ -#define MIPS3DRC_STRICT_COP1 0x0002 /* validate all COP1 instructions */ -#define MIPS3DRC_STRICT_COP2 0x0004 /* validate all COP2 instructions */ -#define MIPS3DRC_FLUSH_PC 0x0008 /* flush the PC value before each memory access */ -#define MIPS3DRC_CHECK_OVERFLOWS 0x0010 /* actually check overflows on add/sub instructions */ +#define MIPS3DRC_STRICT_COP0 0x0002 /* validate all COP0 instructions */ +#define MIPS3DRC_STRICT_COP1 0x0004 /* validate all COP1 instructions */ +#define MIPS3DRC_STRICT_COP2 0x0008 /* validate all COP2 instructions */ +#define MIPS3DRC_FLUSH_PC 0x0010 /* flush the PC value before each memory access */ +#define MIPS3DRC_CHECK_OVERFLOWS 0x0020 /* actually check overflows on add/sub instructions */ -#define MIPS3DRC_COMPATIBLE_OPTIONS (MIPS3DRC_STRICT_VERIFY | MIPS3DRC_STRICT_COP1 | MIPS3DRC_STRICT_COP2 | MIPS3DRC_FLUSH_PC) +#define MIPS3DRC_COMPATIBLE_OPTIONS (MIPS3DRC_STRICT_VERIFY | MIPS3DRC_STRICT_COP1 | MIPS3DRC_STRICT_COP0 | MIPS3DRC_STRICT_COP2 | MIPS3DRC_FLUSH_PC) #define MIPS3DRC_FASTEST_OPTIONS (0) diff --git a/src/emu/cpu/mips/mips3drc.c b/src/emu/cpu/mips/mips3drc.c index 83a098da129..a91465dd494 100644 --- a/src/emu/cpu/mips/mips3drc.c +++ b/src/emu/cpu/mips/mips3drc.c @@ -1617,8 +1617,7 @@ int mips3_device::generate_opcode(drcuml_block *block, compiler_state *compiler, return TRUE; case 0x31: /* LWC1 - MIPS I */ - UML_TEST(block, CPR032(COP0_Status), SR_COP1); // test [Status],SR_COP1 - UML_EXHc(block, COND_Z, *m_exception[EXCEPTION_BADCOP], 1); // exh cop,1,Z + check_cop1_access(block); UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,,SIMMVAL UML_CALLH(block, *m_read32[m_core->mode >> 1]); // callh read32 UML_MOV(block, FPR32(RTREG), I0); // mov ,i0 @@ -1627,8 +1626,7 @@ int mips3_device::generate_opcode(drcuml_block *block, compiler_state *compiler, return TRUE; case 0x35: /* LDC1 - MIPS III */ - UML_TEST(block, CPR032(COP0_Status), SR_COP1); // test [Status],SR_COP1 - UML_EXHc(block, COND_Z, *m_exception[EXCEPTION_BADCOP], 1); // exh cop,1,Z + check_cop1_access(block); UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,,SIMMVAL UML_CALLH(block, *m_read64[m_core->mode >> 1]); // callh read64 UML_DMOV(block, FPR64(RTREG), I0); // dmov ,i0 @@ -1772,8 +1770,7 @@ int mips3_device::generate_opcode(drcuml_block *block, compiler_state *compiler, return TRUE; case 0x39: /* SWC1 - MIPS I */ - UML_TEST(block, CPR032(COP0_Status), SR_COP1); // test [Status],SR_COP1 - UML_EXHc(block, COND_Z, *m_exception[EXCEPTION_BADCOP], 1); // exh cop,1,Z + check_cop1_access(block); UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,,SIMMVAL UML_MOV(block, I1, FPR32(RTREG)); // mov i1, UML_CALLH(block, *m_write32[m_core->mode >> 1]); // callh write32 @@ -1782,8 +1779,7 @@ int mips3_device::generate_opcode(drcuml_block *block, compiler_state *compiler, return TRUE; case 0x3d: /* SDC1 - MIPS III */ - UML_TEST(block, CPR032(COP0_Status), SR_COP1); // test [Status],SR_COP1 - UML_EXHc(block, COND_Z, *m_exception[EXCEPTION_BADCOP], 1); // exh cop,1,Z + check_cop1_access(block); UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,,SIMMVAL UML_DMOV(block, I1, FPR64(RTREG)); // dmov i1, UML_CALLH(block, *m_write64[m_core->mode >> 1]); // callh write64 @@ -2480,6 +2476,28 @@ int mips3_device::generate_get_cop0_reg(drcuml_block *block, compiler_state *com } +/*------------------------------------------------------------------------- + generate_badcop - raise a BADCOP exception +-------------------------------------------------------------------------*/ + +void mips3_device::generate_badcop(drcuml_block *block, const int cop) +{ + UML_TEST(block, CPR032(COP0_Status), SR_COP0 << cop); // test [Status], SR_COP0 << cop + UML_EXHc(block, COND_Z, *m_exception[EXCEPTION_BADCOP], cop); // exh badcop,cop,Z +} + +/*------------------------------------------------------------------------- + check_cop0_access - raise a BADCOP exception if we're not in kernel mode +-------------------------------------------------------------------------*/ + +void mips3_device::check_cop0_access(drcuml_block *block) +{ + if ((m_core->mode >> 1) != MODE_KERNEL) + { + generate_badcop(block, 0); + } +} + /*------------------------------------------------- generate_cop0 - compile COP0 opcodes -------------------------------------------------*/ @@ -2606,6 +2624,18 @@ int mips3_device::generate_cop0(drcuml_block *block, compiler_state *compiler, c COP1 RECOMPILATION ***************************************************************************/ +/*------------------------------------------------------------------------- + check_cop1_access - raise a BADCOP exception if COP1 is not enabled +-------------------------------------------------------------------------*/ + +void mips3_device::check_cop1_access(drcuml_block *block) +{ + if (m_drcoptions & MIPS3DRC_STRICT_COP1) + { + generate_badcop(block, 1); + } +} + /*------------------------------------------------- generate_cop1 - compile COP1 opcodes -------------------------------------------------*/ @@ -2616,39 +2646,34 @@ int mips3_device::generate_cop1(drcuml_block *block, compiler_state *compiler, c code_label skip; condition_t condition; - /* generate an exception if COP1 is disabled */ - if (m_drcoptions & MIPS3DRC_STRICT_COP1) - { - UML_TEST(block, CPR032(COP0_Status), SR_COP1); // test [Status],SR_COP1 - UML_EXHc(block, COND_Z, *m_exception[EXCEPTION_BADCOP], 1);// exh cop,1,Z - } + check_cop1_access(block); switch (RSREG) { - case 0x00: /* MFCz - MIPS I */ + case 0x00: /* MFC1 - MIPS I */ if (RTREG != 0) UML_DSEXT(block, R64(RTREG), FPR32(RDREG), SIZE_DWORD); // dsext ,fpr[rdreg],dword return TRUE; - case 0x01: /* DMFCz - MIPS III */ + case 0x01: /* DMFC1 - MIPS III */ if (RTREG != 0) UML_DMOV(block, R64(RTREG), FPR64(RDREG)); // dmov ,fpr[rdreg] return TRUE; - case 0x02: /* CFCz - MIPS I */ + case 0x02: /* CFC1 - MIPS I */ if (RTREG != 0) UML_DSEXT(block, R64(RTREG), CCR132(RDREG), SIZE_DWORD); // dsext ,ccr132[rdreg],dword return TRUE; - case 0x04: /* MTCz - MIPS I */ + case 0x04: /* MTC1 - MIPS I */ UML_MOV(block, FPR32(RDREG), R32(RTREG)); // mov fpr[rdreg], return TRUE; - case 0x05: /* DMTCz - MIPS III */ + case 0x05: /* DMTC1 - MIPS III */ UML_DMOV(block, FPR64(RDREG), R64(RTREG)); // dmov fpr[rdreg], return TRUE; - case 0x06: /* CTCz - MIPS I */ + case 0x06: /* CTC1 - MIPS I */ if (RDREG != 31) UML_DSEXT(block, CCR164(RDREG), R32(RTREG), SIZE_DWORD); // dsext ccr1[rdreg],,dword else @@ -2991,11 +3016,7 @@ int mips3_device::generate_cop1x(drcuml_block *block, compiler_state *compiler, int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0); UINT32 op = desc->opptr.l[0]; - if (m_drcoptions & MIPS3DRC_STRICT_COP1) - { - UML_TEST(block, CPR032(COP0_Status), SR_COP1); // test [Status],SR_COP1 - UML_EXHc(block, COND_Z, *m_exception[EXCEPTION_BADCOP], 1);// exh cop,1,Z - } + check_cop1_access(block); switch (op & 0x3f) {