diff --git a/pcsx2/DebugTools/DebugInterface.cpp b/pcsx2/DebugTools/DebugInterface.cpp index 8d40606792..5ff0ae186a 100644 --- a/pcsx2/DebugTools/DebugInterface.cpp +++ b/pcsx2/DebugTools/DebugInterface.cpp @@ -32,9 +32,6 @@ extern AppCoreThread CoreThread; R5900DebugInterface r5900Debug; R3000DebugInterface r3000Debug; -enum { EECAT_GPR, EECAT_CP0, EECAT_CP1, EECAT_CP2F, EECAT_CP2I, EECAT_COUNT }; -enum { IOPCAT_GPR, IOPCAT_COUNT }; - #ifdef WIN32 #define strcasecmp stricmp #endif @@ -281,12 +278,14 @@ const char* R5900DebugInterface::getRegisterCategoryName(int cat) return "GPR"; case EECAT_CP0: return "CP0"; - case EECAT_CP1: - return "CP1"; - case EECAT_CP2F: - return "CP2f"; - case EECAT_CP2I: - return "CP2i"; + case EECAT_FPR: + return "FPR"; + case EECAT_FCR: + return "FCR"; + case EECAT_VU0F: + return "VU0f"; + case EECAT_VU0I: + return "VU0i"; default: return "Invalid"; } @@ -297,11 +296,12 @@ int R5900DebugInterface::getRegisterSize(int cat) switch (cat) { case EECAT_GPR: - case EECAT_CP2F: + case EECAT_VU0F: return 128; case EECAT_CP0: - case EECAT_CP1: - case EECAT_CP2I: + case EECAT_FPR: + case EECAT_FCR: + case EECAT_VU0I: return 32; default: return 0; @@ -315,9 +315,10 @@ int R5900DebugInterface::getRegisterCount(int cat) case EECAT_GPR: return 35; // 32 + pc + hi + lo case EECAT_CP0: - case EECAT_CP1: - case EECAT_CP2F: - case EECAT_CP2I: + case EECAT_FPR: + case EECAT_FCR: + case EECAT_VU0F: + case EECAT_VU0I: return 32; default: return 0; @@ -330,11 +331,12 @@ DebugInterface::RegisterType R5900DebugInterface::getRegisterType(int cat) { case EECAT_GPR: case EECAT_CP0: - case EECAT_CP2F: - case EECAT_CP2I: + case EECAT_VU0F: + case EECAT_VU0I: + case EECAT_FCR: default: return NORMAL; - case EECAT_CP1: + case EECAT_FPR: return SPECIAL; } } @@ -357,11 +359,13 @@ const char* R5900DebugInterface::getRegisterName(int cat, int num) } case EECAT_CP0: return R5900::COP0_REG[num]; - case EECAT_CP1: + case EECAT_FPR: return R5900::COP1_REG_FP[num]; - case EECAT_CP2F: + case EECAT_FCR: + return R5900::COP1_REG_FCR[num]; + case EECAT_VU0F: return R5900::COP2_REG_FP[num]; - case EECAT_CP2I: + case EECAT_VU0I: return R5900::COP2_REG_CTL[num]; default: return "Invalid"; @@ -393,13 +397,16 @@ u128 R5900DebugInterface::getRegister(int cat, int num) case EECAT_CP0: result = u128::From32(cpuRegs.CP0.r[num]); break; - case EECAT_CP1: + case EECAT_FPR: result = u128::From32(fpuRegs.fpr[num].UL); break; - case EECAT_CP2F: + case EECAT_FCR: + result = u128::From32(fpuRegs.fprc[num]); + break; + case EECAT_VU0F: result = VU1.VF[num].UQ; break; - case EECAT_CP2I: + case EECAT_VU0I: result = u128::From32(VU1.VI[num].UL); break; default: @@ -416,8 +423,9 @@ wxString R5900DebugInterface::getRegisterString(int cat, int num) { case EECAT_GPR: case EECAT_CP0: + case EECAT_FCR: return getRegister(cat,num).ToString(); - case EECAT_CP1: + case EECAT_FPR: { char str[64]; sprintf(str,"%f",fpuRegs.fpr[num].f); @@ -473,13 +481,16 @@ void R5900DebugInterface::setRegister(int cat, int num, u128 newValue) case EECAT_CP0: cpuRegs.CP0.r[num] = newValue._u32[0]; break; - case EECAT_CP1: + case EECAT_FPR: fpuRegs.fpr[num].UL = newValue._u32[0]; break; - case EECAT_CP2F: + case EECAT_FCR: + fpuRegs.fprc[num] = newValue._u32[0]; + break; + case EECAT_VU0F: VU1.VF[num].UQ = newValue; break; - case EECAT_CP2I: + case EECAT_VU0I: VU1.VI[num].UL = newValue._u32[0]; break; default: diff --git a/pcsx2/DebugTools/DebugInterface.h b/pcsx2/DebugTools/DebugInterface.h index 28ffdd3d11..a8c4b3fd15 100644 --- a/pcsx2/DebugTools/DebugInterface.h +++ b/pcsx2/DebugTools/DebugInterface.h @@ -17,6 +17,9 @@ #include "MemoryTypes.h" #include "ExpressionParser.h" +enum { EECAT_GPR, EECAT_CP0, EECAT_FPR, EECAT_FCR, EECAT_VU0F, EECAT_VU0I, EECAT_COUNT }; +enum { IOPCAT_GPR, IOPCAT_COUNT }; + class DebugInterface { public: diff --git a/pcsx2/DebugTools/MIPSAnalyst.cpp b/pcsx2/DebugTools/MIPSAnalyst.cpp index 2da49cee1f..2a715f80a4 100644 --- a/pcsx2/DebugTools/MIPSAnalyst.cpp +++ b/pcsx2/DebugTools/MIPSAnalyst.cpp @@ -20,6 +20,7 @@ #include "SymbolMap.h" #include "DebugInterface.h" #include "../R5900.h" +#include "../R5900OpcodeTables.h" static std::vector functions; @@ -160,296 +161,182 @@ namespace MIPSAnalyst } } - - enum BranchType { NONE, JUMP, BRANCH }; - struct BranchInfo - { - BranchType type; - bool link; - bool likely; - bool toRegister; - }; - - bool getBranchInfo(MipsOpcodeInfo& info) - { - BranchType type = NONE; - bool link = false; - bool likely = false; - bool toRegister = false; - bool met = false; - - u32 op = info.encodedOpcode; - - u32 opNum = MIPS_GET_OP(op); - u32 rsNum = MIPS_GET_RS(op); - u32 rtNum = MIPS_GET_RT(op); - u32 rs = info.cpu->getRegister(0,rsNum); - u32 rt = info.cpu->getRegister(0,rtNum); - - switch (MIPS_GET_OP(op)) - { - case 0x00: // special - switch (MIPS_GET_FUNC(op)) - { - case 0x08: // jr - type = JUMP; - toRegister = true; - break; - case 0x09: // jalr - type = JUMP; - toRegister = true; - link = true; - break; - } - break; - case 0x01: // regimm - switch (MIPS_GET_RT(op)) - { - case 0x00: // bltz - case 0x02: // bltzl - case 0x10: // bltzal - case 0x12: // bltzall - type = BRANCH; - met = (((s32)rs) < 0); - likely = (rt & 2) != 0; - link = rt >= 0x10; - break; - - case 0x01: // bgez - case 0x03: // bgezl - case 0x11: // bgezal - case 0x13: // bgezall - type = BRANCH; - met = (((s32)rs) >= 0); - likely = (rt & 2) != 0; - link = rt >= 0x10; - break; - } - break; - case 0x02: // j - type = JUMP; - break; - case 0x03: // jal - type = JUMP; - link = true; - break; - - case 0x04: // beq - case 0x14: // beql - type = BRANCH; - met = (rt == rs); - if (MIPS_GET_RT(op) == MIPS_GET_RS(op)) // always true - info.isConditional = false; - likely = opNum >= 0x10; - break; - - case 0x05: // bne - case 0x15: // bnel - type = BRANCH; - met = (rt != rs); - if (MIPS_GET_RT(op) == MIPS_GET_RS(op)) // always false - info.isConditional = false; - likely = opNum >= 0x10; - break; - - case 0x06: // blez - case 0x16: // blezl - type = BRANCH; - met = (((s32)rs) <= 0); - likely = opNum >= 0x10; - break; - - case 0x07: // bgtz - case 0x17: // bgtzl - type = BRANCH; - met = (((s32)rs) > 0); - likely = opNum >= 0x10; - break; - } - - if (type == NONE) - return false; - - info.isBranch = true; - info.isLinkedBranch = link; - info.isLikelyBranch = true; - info.isBranchToRegister = toRegister; - info.isConditional = type == BRANCH; - info.conditionMet = met; - - switch (type) - { - case JUMP: - if (toRegister) - { - info.branchRegisterNum = (int)MIPS_GET_RS(op); - info.branchTarget = info.cpu->getRegister(0,info.branchRegisterNum)._u32[0]; - } else { - info.branchTarget = (info.opcodeAddress & 0xF0000000) | ((op&0x03FFFFFF) << 2); - } - break; - case BRANCH: - info.branchTarget = info.opcodeAddress + 4 + ((signed short)(op&0xFFFF)<<2); - break; - case NONE: - return false; - } - - return true; - } - - bool getDataAccessInfo(MipsOpcodeInfo& info) - { - int size = 0; - - u32 op = info.encodedOpcode; - int off = 0; - switch (MIPS_GET_OP(op)) - { - case 0x20: // lb - case 0x24: // lbu - case 0x28: // sb - size = 1; - break; - case 0x21: // lh - case 0x25: // lhu - case 0x29: // sh - size = 2; - break; - case 0x23: // lw - case 0x2B: // sw - size = 4; - break; - case 0x26: // lwr - case 0x2E: // swr - size = 4; - info.lrType = LOADSTORE_RIGHT; - break; - case 0x22: // lwl - case 0x2A: // swl - size = 4; - off = -3; - info.lrType = LOADSTORE_LEFT; - break; - case 0x37: // ld - case 0x3F: // sd - size = 8; - break; - case 0x1B: // ldr - case 0x2D: // sdr - size = 8; - info.lrType = LOADSTORE_RIGHT; - break; - case 0x1A: // ldl - case 0x2C: // sdl - size = 8; - off = -7; - info.lrType = LOADSTORE_LEFT; - break; - case 0x1E: // lq - case 0x1F: // sq - size = 16; - break; - } - - if (size == 0) - return false; - - info.isDataAccess = true; - info.dataSize = size; - - u32 rs = info.cpu->getRegister(0, (int)MIPS_GET_RS(op)); - s16 imm16 = op & 0xFFFF; - info.dataAddress = rs + imm16 + off; - - info.hasRelevantAddress = true; - info.releventAddress = info.dataAddress; - return true; - } - MipsOpcodeInfo GetOpcodeInfo(DebugInterface* cpu, u32 address) { MipsOpcodeInfo info; memset(&info, 0, sizeof(info)); - if (cpu->isValidAddress(address) == false) { + if (cpu->isValidAddress(address) == false) return info; - } info.cpu = cpu; info.opcodeAddress = address; info.encodedOpcode = cpu->read32(address); u32 op = info.encodedOpcode; + const R5900::OPCODE& opcode = R5900::GetInstruction(op); - if (getBranchInfo(info) == true) - return info; + // extract all the branch related information + info.isBranch = (opcode.flags & IS_BRANCH) != 0; + if (info.isBranch) + { + info.isLinkedBranch = (opcode.flags & IS_LINKED) != 0; + info.isLikelyBranch = (opcode.flags & IS_LIKELY) != 0; - if (getDataAccessInfo(info) == true) - return info; - - // gather relevant address for alu operations - // that's usually the value of the dest register - switch (MIPS_GET_OP(op)) { - case 0: // special - switch (MIPS_GET_FUNC(op)) { - case 0x0C: // syscall + u64 rs,rt; + u32 value; + switch (opcode.flags & BRANCHTYPE_MASK) + { + case BRANCHTYPE_JUMP: + info.isConditional = false; + info.branchTarget = (info.opcodeAddress & 0xF0000000) | ((op&0x03FFFFFF) << 2); + break; + case BRANCHTYPE_BRANCH: + info.isConditional = true; + info.branchTarget = info.opcodeAddress + 4 + ((s16)(op&0xFFFF)<<2); + + rs = info.cpu->getRegister(0,MIPS_GET_RS(op))._u64[0]; + rt = info.cpu->getRegister(0,MIPS_GET_RT(op))._u64[0]; + switch (opcode.flags & CONDTYPE_MASK) + { + case CONDTYPE_EQ: + info.conditionMet = (rt == rs); + if (MIPS_GET_RT(op) == MIPS_GET_RS(op)) // always true + info.isConditional = false; + break; + case CONDTYPE_NE: + info.conditionMet = (rt != rs); + if (MIPS_GET_RT(op) == MIPS_GET_RS(op)) // always false + info.isConditional = false; + break; + case CONDTYPE_LEZ: + info.conditionMet = (((s64)rs) <= 0); + break; + case CONDTYPE_GTZ: + info.conditionMet = (((s64)rs) > 0); + break; + case CONDTYPE_LTZ: + info.conditionMet = (((s64)rs) < 0); + break; + case CONDTYPE_GEZ: + info.conditionMet = (((s64)rs) >= 0); + break; + } + + break; + case BRANCHTYPE_REGISTER: + info.isConditional = false; + info.isBranchToRegister = true; + info.branchRegisterNum = (int)MIPS_GET_RS(op); + info.branchTarget = info.cpu->getRegister(0,info.branchRegisterNum)._u32[0]; + break; + case BRANCHTYPE_SYSCALL: + info.isConditional = false; info.isSyscall = true; info.branchTarget = 0x80000000+0x180; break; - case 0x20: // add - case 0x21: // addu - info.hasRelevantAddress = true; - info.releventAddress = cpu->getRegister(0,MIPS_GET_RS(op))._u32[0]+cpu->getRegister(0,MIPS_GET_RT(op))._u32[0]; - break; - case 0x22: // sub - case 0x23: // subu - info.hasRelevantAddress = true; - info.releventAddress = cpu->getRegister(0,MIPS_GET_RS(op))._u32[0]-cpu->getRegister(0,MIPS_GET_RT(op))._u32[0]; - break; - } - break; - case 0x08: // addi - case 0x09: // adiu - info.hasRelevantAddress = true; - info.releventAddress = cpu->getRegister(0,MIPS_GET_RS(op))._u32[0]+((s16)(op & 0xFFFF)); - break; - case 0x10: // cop0 - switch (MIPS_GET_RS(op)) - { - case 0x10: // tlb - switch (MIPS_GET_FUNC(op)) + case BRANCHTYPE_ERET: + info.isConditional = false; + // probably shouldn't be hard coded like this... + if (cpuRegs.CP0.n.Status.b.ERL) { - case 0x18: // eret - info.isBranch = true; - info.isConditional = false; + info.branchTarget = cpuRegs.CP0.n.ErrorEPC; + } else { + info.branchTarget = cpuRegs.CP0.n.EPC; + } + break; + case BRANCHTYPE_BC1: + info.isConditional = true; + value = info.cpu->getRegister(EECAT_FCR,31)._u32[0] & 0x00800000; + info.branchTarget = info.opcodeAddress + 4 + ((s16)(op&0xFFFF)<<2); - // probably shouldn't be hard coded like this... - if (cpuRegs.CP0.n.Status.b.ERL) { - info.branchTarget = cpuRegs.CP0.n.ErrorEPC; - } else { - info.branchTarget = cpuRegs.CP0.n.EPC; - } + switch (opcode.flags & CONDTYPE_MASK) + { + case CONDTYPE_EQ: + info.conditionMet = value == 0; + break; + case CONDTYPE_NE: + info.conditionMet = value != 0; break; } break; } - break; } - // TODO: rest -/* // movn, movz - if (opInfo & IS_CONDMOVE) { - info.isConditional = true; + // extract the accessed memory address + info.isDataAccess = opcode.flags & IS_MEMORY; + if (info.isDataAccess) + { + if (opcode.flags & IS_LEFT) + info.lrType = LOADSTORE_LEFT; + else if (opcode.flags & IS_RIGHT) + info.lrType = LOADSTORE_RIGHT; + + u32 rs = info.cpu->getRegister(0, (int)MIPS_GET_RS(op)); + s16 imm16 = op & 0xFFFF; + info.dataAddress = rs + imm16; - u32 rt = cpu->GetRegValue(0, (int)MIPS_GET_RT(op)); - switch (opInfo & CONDTYPE_MASK) { - case CONDTYPE_EQ: - info.conditionMet = (rt == 0); + switch (opcode.flags & MEMTYPE_MASK) + { + case MEMTYPE_BYTE: + info.dataSize = 1; break; - case CONDTYPE_NE: - info.conditionMet = (rt != 0); + case MEMTYPE_HALF: + info.dataSize = 2; + break; + case MEMTYPE_WORD: + info.dataSize = 4; + if (info.lrType == LOADSTORE_LEFT) + info.dataAddress -= 3; + break; + case MEMTYPE_DWORD: + info.dataSize = 8; + if (info.lrType == LOADSTORE_LEFT) + info.dataAddress -= 7; + break; + case MEMTYPE_QWORD: + info.dataSize = 16; break; } - }*/ + + info.hasRelevantAddress = true; + info.releventAddress = info.dataAddress; + } + + // gather relevant address for alu operations + if (opcode.flags & IS_ALU) + { + u64 rs,rt; + rs = info.cpu->getRegister(0,MIPS_GET_RS(op))._u64[0]; + rt = info.cpu->getRegister(0,MIPS_GET_RT(op))._u64[0]; + + switch (opcode.flags & ALUTYPE_MASK) + { + case ALUTYPE_ADDI: + info.hasRelevantAddress = true; + info.releventAddress = rs+((s16)(op & 0xFFFF)); + break; + case ALUTYPE_ADD: + info.hasRelevantAddress = true; + info.releventAddress = rs+rt; + break; + case ALUTYPE_SUB: + info.hasRelevantAddress = true; + info.releventAddress = rs-rt; + break; + case ALUTYPE_CONDMOVE: + info.isConditional = true; + + switch (opcode.flags & CONDTYPE_MASK) + { + case CONDTYPE_EQ: + info.conditionMet = (rt == 0); + break; + case CONDTYPE_NE: + info.conditionMet = (rt != 0); + break; + } + break; + } + } return info; } diff --git a/pcsx2/R5900OpcodeTables.cpp b/pcsx2/R5900OpcodeTables.cpp index d7f0ef4350..8a9e78b772 100644 --- a/pcsx2/R5900OpcodeTables.cpp +++ b/pcsx2/R5900OpcodeTables.cpp @@ -39,40 +39,44 @@ namespace R5900 { // Generates an entry for the given opcode name. // Assumes the default function naming schemes for interpreter and recompiler functions. - # define MakeOpcode( name, cycles ) \ + # define MakeOpcode( name, cycles, flags ) \ static const OPCODE name = { \ #name, \ cycles, \ + flags, \ NULL, \ ::R5900::Interpreter::OpcodeImpl::name, \ ::R5900::Dynarec::OpcodeImpl::rec##name, \ ::R5900::OpcodeDisasm::name \ } -# define MakeOpcodeM( name, cycles ) \ +# define MakeOpcodeM( name, cycles, flags ) \ static const OPCODE name = { \ #name, \ cycles, \ + flags, \ NULL, \ ::R5900::Interpreter::OpcodeImpl::MMI::name, \ ::R5900::Dynarec::OpcodeImpl::MMI::rec##name, \ ::R5900::OpcodeDisasm::name \ } -# define MakeOpcode0( name, cycles ) \ +# define MakeOpcode0( name, cycles, flags ) \ static const OPCODE name = { \ #name, \ cycles, \ + flags, \ NULL, \ ::R5900::Interpreter::OpcodeImpl::COP0::name, \ ::R5900::Dynarec::OpcodeImpl::COP0::rec##name, \ ::R5900::OpcodeDisasm::name \ } - # define MakeOpcode1( name, cycles ) \ + # define MakeOpcode1( name, cycles, flags ) \ static const OPCODE name = { \ #name, \ cycles, \ + flags, \ NULL, \ ::R5900::Interpreter::OpcodeImpl::COP1::name, \ ::R5900::Dynarec::OpcodeImpl::COP1::rec##name, \ @@ -83,6 +87,7 @@ namespace R5900 static const OPCODE name = { \ #name, \ 0, \ + 0, \ R5900::Opcodes::Class_##name, \ NULL, \ NULL, \ @@ -113,10 +118,10 @@ namespace R5900 using namespace Cycles; - MakeOpcode( Unknown, Default ); - MakeOpcode( MMI_Unknown, Default ); - MakeOpcode( COP0_Unknown, Default ); - MakeOpcode( COP1_Unknown, Default ); + MakeOpcode( Unknown, Default, 0 ); + MakeOpcode( MMI_Unknown, Default, 0 ); + MakeOpcode( COP0_Unknown, Default, 0 ); + MakeOpcode( COP1_Unknown, Default, 0 ); // Class Subset Opcodes // (not really opcodes, but rather entire subsets of other opcode classes) @@ -135,250 +140,250 @@ namespace R5900 // Misc Junk - MakeOpcode( COP2, Default ); + MakeOpcode( COP2, Default, 0 ); - MakeOpcode( CACHE, Default ); - MakeOpcode( PREF, Default ); - MakeOpcode( SYSCALL, Default ); - MakeOpcode( BREAK, Default ); - MakeOpcode( SYNC, Default ); + MakeOpcode( CACHE, Default, 0 ); + MakeOpcode( PREF, Default, 0 ); + MakeOpcode( SYSCALL, Default, IS_BRANCH|BRANCHTYPE_SYSCALL ); + MakeOpcode( BREAK, Default, 0 ); + MakeOpcode( SYNC, Default, 0 ); // Branch/Jump Opcodes - MakeOpcode( J , Default ); - MakeOpcode( JAL, Default ); - MakeOpcode( JR, Default ); - MakeOpcode( JALR, Default ); + MakeOpcode( J , Default, IS_BRANCH|BRANCHTYPE_JUMP ); + MakeOpcode( JAL, Default, IS_BRANCH|BRANCHTYPE_JUMP|IS_LINKED ); + MakeOpcode( JR, Default, IS_BRANCH|BRANCHTYPE_REGISTER ); + MakeOpcode( JALR, Default, IS_BRANCH|BRANCHTYPE_REGISTER|IS_LINKED ); - MakeOpcode( BEQ, Branch ); - MakeOpcode( BNE, Branch ); - MakeOpcode( BLEZ, Branch ); - MakeOpcode( BGTZ, Branch ); - MakeOpcode( BEQL, Branch ); - MakeOpcode( BNEL, Branch ); - MakeOpcode( BLEZL, Branch ); - MakeOpcode( BGTZL, Branch ); - MakeOpcode( BLTZ, Branch ); - MakeOpcode( BGEZ, Branch ); - MakeOpcode( BLTZL, Branch ); - MakeOpcode( BGEZL, Branch ); - MakeOpcode( BLTZAL, Branch ); - MakeOpcode( BGEZAL, Branch ); - MakeOpcode( BLTZALL, Branch ); - MakeOpcode( BGEZALL, Branch ); + MakeOpcode( BEQ, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_EQ ); + MakeOpcode( BNE, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_NE ); + MakeOpcode( BLEZ, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_LEZ ); + MakeOpcode( BGTZ, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_GTZ ); + MakeOpcode( BEQL, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_EQ|IS_LIKELY ); + MakeOpcode( BNEL, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_NE|IS_LIKELY ); + MakeOpcode( BLEZL, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_LEZ|IS_LIKELY ); + MakeOpcode( BGTZL, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_GTZ|IS_LIKELY ); + MakeOpcode( BLTZ, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_LTZ ); + MakeOpcode( BGEZ, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_GEZ ); + MakeOpcode( BLTZL, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_LTZ|IS_LIKELY ); + MakeOpcode( BGEZL, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_GEZ|IS_LIKELY ); + MakeOpcode( BLTZAL, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_LTZ|IS_LINKED ); + MakeOpcode( BGEZAL, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_GEZ|IS_LINKED ); + MakeOpcode( BLTZALL, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_LTZ|IS_LINKED|IS_LIKELY ); + MakeOpcode( BGEZALL, Branch, IS_BRANCH|BRANCHTYPE_BRANCH|CONDTYPE_GEZ|IS_LINKED|IS_LIKELY ); - MakeOpcode( TGEI, Branch ); - MakeOpcode( TGEIU, Branch ); - MakeOpcode( TLTI, Branch ); - MakeOpcode( TLTIU, Branch ); - MakeOpcode( TEQI, Branch ); - MakeOpcode( TNEI, Branch ); - MakeOpcode( TGE, Branch ); - MakeOpcode( TGEU, Branch ); - MakeOpcode( TLT, Branch ); - MakeOpcode( TLTU, Branch ); - MakeOpcode( TEQ, Branch ); - MakeOpcode( TNE, Branch ); + MakeOpcode( TGEI, Branch, 0 ); + MakeOpcode( TGEIU, Branch, 0 ); + MakeOpcode( TLTI, Branch, 0 ); + MakeOpcode( TLTIU, Branch, 0 ); + MakeOpcode( TEQI, Branch, 0 ); + MakeOpcode( TNEI, Branch, 0 ); + MakeOpcode( TGE, Branch, 0 ); + MakeOpcode( TGEU, Branch, 0 ); + MakeOpcode( TLT, Branch, 0 ); + MakeOpcode( TLTU, Branch, 0 ); + MakeOpcode( TEQ, Branch, 0 ); + MakeOpcode( TNE, Branch, 0 ); // Arithmetic - MakeOpcode( MULT, Mult ); - MakeOpcode( MULTU, Mult ); - MakeOpcode( MULT1, Mult ); - MakeOpcode( MULTU1, Mult ); - MakeOpcode( MADD, Mult ); - MakeOpcode( MADDU, Mult ); - MakeOpcode( MADD1, Mult ); - MakeOpcode( MADDU1, Mult ); - MakeOpcode( DIV, Div ); - MakeOpcode( DIVU, Div ); - MakeOpcode( DIV1, Div ); - MakeOpcode( DIVU1, Div ); + MakeOpcode( MULT, Mult, 0 ); + MakeOpcode( MULTU, Mult, 0 ); + MakeOpcode( MULT1, Mult, 0 ); + MakeOpcode( MULTU1, Mult, 0 ); + MakeOpcode( MADD, Mult, 0 ); + MakeOpcode( MADDU, Mult, 0 ); + MakeOpcode( MADD1, Mult, 0 ); + MakeOpcode( MADDU1, Mult, 0 ); + MakeOpcode( DIV, Div, 0 ); + MakeOpcode( DIVU, Div, 0 ); + MakeOpcode( DIV1, Div, 0 ); + MakeOpcode( DIVU1, Div, 0 ); - MakeOpcode( ADDI, Default ); - MakeOpcode( ADDIU, Default ); - MakeOpcode( DADDI, Default ); - MakeOpcode( DADDIU, Default ); - MakeOpcode( DADD, Default ); - MakeOpcode( DADDU, Default ); - MakeOpcode( DSUB, Default ); - MakeOpcode( DSUBU, Default ); - MakeOpcode( ADD, Default ); - MakeOpcode( ADDU, Default ); - MakeOpcode( SUB, Default ); - MakeOpcode( SUBU, Default ); + MakeOpcode( ADDI, Default, IS_ALU|ALUTYPE_ADDI ); + MakeOpcode( ADDIU, Default, IS_ALU|ALUTYPE_ADDI ); + MakeOpcode( DADDI, Default, IS_ALU|ALUTYPE_ADDI|IS_64BIT ); + MakeOpcode( DADDIU, Default, IS_ALU|ALUTYPE_ADDI|IS_64BIT ); + MakeOpcode( DADD, Default, IS_ALU|ALUTYPE_ADD|IS_64BIT ); + MakeOpcode( DADDU, Default, IS_ALU|ALUTYPE_ADD|IS_64BIT ); + MakeOpcode( DSUB, Default, IS_ALU|ALUTYPE_SUB|IS_64BIT ); + MakeOpcode( DSUBU, Default, IS_ALU|ALUTYPE_SUB|IS_64BIT ); + MakeOpcode( ADD, Default, IS_ALU|ALUTYPE_ADD ); + MakeOpcode( ADDU, Default, IS_ALU|ALUTYPE_ADD ); + MakeOpcode( SUB, Default, IS_ALU|ALUTYPE_SUB ); + MakeOpcode( SUBU, Default, IS_ALU|ALUTYPE_SUB ); - MakeOpcode( ANDI, Default ); - MakeOpcode( ORI, Default ); - MakeOpcode( XORI, Default ); - MakeOpcode( AND, Default ); - MakeOpcode( OR, Default ); - MakeOpcode( XOR, Default ); - MakeOpcode( NOR, Default ); - MakeOpcode( SLTI, Default ); - MakeOpcode( SLTIU, Default ); - MakeOpcode( SLT, Default ); - MakeOpcode( SLTU, Default ); - MakeOpcode( LUI, Default ); - MakeOpcode( SLL, Default ); - MakeOpcode( SRL, Default ); - MakeOpcode( SRA, Default ); - MakeOpcode( SLLV, Default ); - MakeOpcode( SRLV, Default ); - MakeOpcode( SRAV, Default ); - MakeOpcode( MOVZ, Default ); - MakeOpcode( MOVN, Default ); - MakeOpcode( DSLLV, Default ); - MakeOpcode( DSRLV, Default ); - MakeOpcode( DSRAV, Default ); - MakeOpcode( DSLL, Default ); - MakeOpcode( DSRL, Default ); - MakeOpcode( DSRA, Default ); - MakeOpcode( DSLL32, Default ); - MakeOpcode( DSRL32, Default ); - MakeOpcode( DSRA32, Default ); + MakeOpcode( ANDI, Default, 0 ); + MakeOpcode( ORI, Default, 0 ); + MakeOpcode( XORI, Default, 0 ); + MakeOpcode( AND, Default, 0 ); + MakeOpcode( OR, Default, 0 ); + MakeOpcode( XOR, Default, 0 ); + MakeOpcode( NOR, Default, 0 ); + MakeOpcode( SLTI, Default, 0 ); + MakeOpcode( SLTIU, Default, 0 ); + MakeOpcode( SLT, Default, 0 ); + MakeOpcode( SLTU, Default, 0 ); + MakeOpcode( LUI, Default, 0 ); + MakeOpcode( SLL, Default, 0 ); + MakeOpcode( SRL, Default, 0 ); + MakeOpcode( SRA, Default, 0 ); + MakeOpcode( SLLV, Default, 0 ); + MakeOpcode( SRLV, Default, 0 ); + MakeOpcode( SRAV, Default, 0 ); + MakeOpcode( MOVZ, Default, IS_ALU|ALUTYPE_CONDMOVE|CONDTYPE_EQ ); + MakeOpcode( MOVN, Default, IS_ALU|ALUTYPE_CONDMOVE|CONDTYPE_NE ); + MakeOpcode( DSLLV, Default, 0 ); + MakeOpcode( DSRLV, Default, 0 ); + MakeOpcode( DSRAV, Default, 0 ); + MakeOpcode( DSLL, Default, 0 ); + MakeOpcode( DSRL, Default, 0 ); + MakeOpcode( DSRA, Default, 0 ); + MakeOpcode( DSLL32, Default, 0 ); + MakeOpcode( DSRL32, Default, 0 ); + MakeOpcode( DSRA32, Default, 0 ); - MakeOpcode( MFHI, Default ); - MakeOpcode( MTHI, Default ); - MakeOpcode( MFLO, Default ); - MakeOpcode( MTLO, Default ); - MakeOpcode( MFSA, Default ); - MakeOpcode( MTSA, Default ); - MakeOpcode( MTSAB, Default ); - MakeOpcode( MTSAH, Default ); - MakeOpcode( MFHI1, Default ); - MakeOpcode( MTHI1, Default ); - MakeOpcode( MFLO1, Default ); - MakeOpcode( MTLO1, Default ); + MakeOpcode( MFHI, Default, 0 ); + MakeOpcode( MTHI, Default, 0 ); + MakeOpcode( MFLO, Default, 0 ); + MakeOpcode( MTLO, Default, 0 ); + MakeOpcode( MFSA, Default, 0 ); + MakeOpcode( MTSA, Default, 0 ); + MakeOpcode( MTSAB, Default, 0 ); + MakeOpcode( MTSAH, Default, 0 ); + MakeOpcode( MFHI1, Default, 0 ); + MakeOpcode( MTHI1, Default, 0 ); + MakeOpcode( MFLO1, Default, 0 ); + MakeOpcode( MTLO1, Default, 0 ); // Loads! - MakeOpcode( LDL, Load ); - MakeOpcode( LDR, Load ); - MakeOpcode( LQ, Load ); - MakeOpcode( LB, Load ); - MakeOpcode( LH, Load ); - MakeOpcode( LWL, Load ); - MakeOpcode( LW, Load ); - MakeOpcode( LBU, Load ); - MakeOpcode( LHU, Load ); - MakeOpcode( LWR, Load ); - MakeOpcode( LWU, Load ); - MakeOpcode( LWC1, Load ); - MakeOpcode( LQC2, Load ); - MakeOpcode( LD, Load ); + MakeOpcode( LDL, Load, IS_MEMORY|IS_LOAD|MEMTYPE_DWORD|IS_LEFT ); + MakeOpcode( LDR, Load, IS_MEMORY|IS_LOAD|MEMTYPE_DWORD|IS_RIGHT ); + MakeOpcode( LQ, Load, IS_MEMORY|IS_LOAD|MEMTYPE_QWORD ); + MakeOpcode( LB, Load, IS_MEMORY|IS_LOAD|MEMTYPE_BYTE ); + MakeOpcode( LH, Load, IS_MEMORY|IS_LOAD|MEMTYPE_HALF ); + MakeOpcode( LWL, Load, IS_MEMORY|IS_LOAD|MEMTYPE_WORD|IS_LEFT ); + MakeOpcode( LW, Load, IS_MEMORY|IS_LOAD|MEMTYPE_WORD ); + MakeOpcode( LBU, Load, IS_MEMORY|IS_LOAD|MEMTYPE_BYTE ); + MakeOpcode( LHU, Load, IS_MEMORY|IS_LOAD|MEMTYPE_HALF ); + MakeOpcode( LWR, Load, IS_MEMORY|IS_LOAD|MEMTYPE_WORD|IS_RIGHT ); + MakeOpcode( LWU, Load, IS_MEMORY|IS_LOAD|MEMTYPE_WORD ); + MakeOpcode( LWC1, Load, IS_MEMORY|IS_LOAD|MEMTYPE_WORD ); + MakeOpcode( LQC2, Load, IS_MEMORY|IS_LOAD|MEMTYPE_QWORD ); + MakeOpcode( LD, Load, IS_MEMORY|IS_LOAD|MEMTYPE_DWORD ); // Stores! - MakeOpcode( SQ, Store ); - MakeOpcode( SB, Store ); - MakeOpcode( SH, Store ); - MakeOpcode( SWL, Store ); - MakeOpcode( SW, Store ); - MakeOpcode( SDL, Store ); - MakeOpcode( SDR, Store ); - MakeOpcode( SWR, Store ); - MakeOpcode( SWC1, Store ); - MakeOpcode( SQC2, Store ); - MakeOpcode( SD, Store ); + MakeOpcode( SQ, Store, IS_MEMORY|IS_STORE|MEMTYPE_QWORD ); + MakeOpcode( SB, Store, IS_MEMORY|IS_STORE|MEMTYPE_BYTE ); + MakeOpcode( SH, Store, IS_MEMORY|IS_STORE|MEMTYPE_HALF ); + MakeOpcode( SWL, Store, IS_MEMORY|IS_STORE|MEMTYPE_WORD|IS_LEFT ); + MakeOpcode( SW, Store, IS_MEMORY|IS_STORE|MEMTYPE_WORD ); + MakeOpcode( SDL, Store, IS_MEMORY|IS_STORE|MEMTYPE_DWORD|IS_LEFT ); + MakeOpcode( SDR, Store, IS_MEMORY|IS_STORE|MEMTYPE_DWORD|IS_RIGHT ); + MakeOpcode( SWR, Store, IS_MEMORY|IS_STORE|MEMTYPE_WORD|IS_RIGHT ); + MakeOpcode( SWC1, Store, IS_MEMORY|IS_STORE|MEMTYPE_WORD ); + MakeOpcode( SQC2, Store, IS_MEMORY|IS_STORE|MEMTYPE_QWORD ); + MakeOpcode( SD, Store, IS_MEMORY|IS_STORE|MEMTYPE_DWORD ); // Multimedia Instructions! - MakeOpcodeM( PLZCW, MMI_Default ); - MakeOpcodeM( PMFHL, MMI_Default ); - MakeOpcodeM( PMTHL, MMI_Default ); - MakeOpcodeM( PSLLH, MMI_Default ); - MakeOpcodeM( PSRLH, MMI_Default ); - MakeOpcodeM( PSRAH, MMI_Default ); - MakeOpcodeM( PSLLW, MMI_Default ); - MakeOpcodeM( PSRLW, MMI_Default ); - MakeOpcodeM( PSRAW, MMI_Default ); + MakeOpcodeM( PLZCW, MMI_Default, 0 ); + MakeOpcodeM( PMFHL, MMI_Default, 0 ); + MakeOpcodeM( PMTHL, MMI_Default, 0 ); + MakeOpcodeM( PSLLH, MMI_Default, 0 ); + MakeOpcodeM( PSRLH, MMI_Default, 0 ); + MakeOpcodeM( PSRAH, MMI_Default, 0 ); + MakeOpcodeM( PSLLW, MMI_Default, 0 ); + MakeOpcodeM( PSRLW, MMI_Default, 0 ); + MakeOpcodeM( PSRAW, MMI_Default, 0 ); - MakeOpcodeM( PADDW, MMI_Default ); - MakeOpcodeM( PADDH, MMI_Default ); - MakeOpcodeM( PADDB, MMI_Default ); - MakeOpcodeM( PADDSW, MMI_Default ); - MakeOpcodeM( PADDSH, MMI_Default ); - MakeOpcodeM( PADDSB, MMI_Default ); - MakeOpcodeM( PADDUW, MMI_Default ); - MakeOpcodeM( PADDUH, MMI_Default ); - MakeOpcodeM( PADDUB, MMI_Default ); - MakeOpcodeM( PSUBW, MMI_Default ); - MakeOpcodeM( PSUBH, MMI_Default ); - MakeOpcodeM( PSUBB, MMI_Default ); - MakeOpcodeM( PSUBSW, MMI_Default ); - MakeOpcodeM( PSUBSH, MMI_Default ); - MakeOpcodeM( PSUBSB, MMI_Default ); - MakeOpcodeM( PSUBUW, MMI_Default ); - MakeOpcodeM( PSUBUH, MMI_Default ); - MakeOpcodeM( PSUBUB, MMI_Default ); + MakeOpcodeM( PADDW, MMI_Default, 0 ); + MakeOpcodeM( PADDH, MMI_Default, 0 ); + MakeOpcodeM( PADDB, MMI_Default, 0 ); + MakeOpcodeM( PADDSW, MMI_Default, 0 ); + MakeOpcodeM( PADDSH, MMI_Default, 0 ); + MakeOpcodeM( PADDSB, MMI_Default, 0 ); + MakeOpcodeM( PADDUW, MMI_Default, 0 ); + MakeOpcodeM( PADDUH, MMI_Default, 0 ); + MakeOpcodeM( PADDUB, MMI_Default, 0 ); + MakeOpcodeM( PSUBW, MMI_Default, 0 ); + MakeOpcodeM( PSUBH, MMI_Default, 0 ); + MakeOpcodeM( PSUBB, MMI_Default, 0 ); + MakeOpcodeM( PSUBSW, MMI_Default, 0 ); + MakeOpcodeM( PSUBSH, MMI_Default, 0 ); + MakeOpcodeM( PSUBSB, MMI_Default, 0 ); + MakeOpcodeM( PSUBUW, MMI_Default, 0 ); + MakeOpcodeM( PSUBUH, MMI_Default, 0 ); + MakeOpcodeM( PSUBUB, MMI_Default, 0 ); - MakeOpcodeM( PCGTW, MMI_Default ); - MakeOpcodeM( PMAXW, MMI_Default ); - MakeOpcodeM( PMAXH, MMI_Default ); - MakeOpcodeM( PCGTH, MMI_Default ); - MakeOpcodeM( PCGTB, MMI_Default ); - MakeOpcodeM( PEXTLW, MMI_Default ); - MakeOpcodeM( PEXTLH, MMI_Default ); - MakeOpcodeM( PEXTLB, MMI_Default ); - MakeOpcodeM( PEXT5, MMI_Default ); - MakeOpcodeM( PPACW, MMI_Default ); - MakeOpcodeM( PPACH, MMI_Default ); - MakeOpcodeM( PPACB, MMI_Default ); - MakeOpcodeM( PPAC5, MMI_Default ); + MakeOpcodeM( PCGTW, MMI_Default, 0 ); + MakeOpcodeM( PMAXW, MMI_Default, 0 ); + MakeOpcodeM( PMAXH, MMI_Default, 0 ); + MakeOpcodeM( PCGTH, MMI_Default, 0 ); + MakeOpcodeM( PCGTB, MMI_Default, 0 ); + MakeOpcodeM( PEXTLW, MMI_Default, 0 ); + MakeOpcodeM( PEXTLH, MMI_Default, 0 ); + MakeOpcodeM( PEXTLB, MMI_Default, 0 ); + MakeOpcodeM( PEXT5, MMI_Default, 0 ); + MakeOpcodeM( PPACW, MMI_Default, 0 ); + MakeOpcodeM( PPACH, MMI_Default, 0 ); + MakeOpcodeM( PPACB, MMI_Default, 0 ); + MakeOpcodeM( PPAC5, MMI_Default, 0 ); - MakeOpcodeM( PABSW, MMI_Default ); - MakeOpcodeM( PABSH, MMI_Default ); - MakeOpcodeM( PCEQW, MMI_Default ); - MakeOpcodeM( PMINW, MMI_Default ); - MakeOpcodeM( PMINH, MMI_Default ); - MakeOpcodeM( PADSBH, MMI_Default ); - MakeOpcodeM( PCEQH, MMI_Default ); - MakeOpcodeM( PCEQB, MMI_Default ); - MakeOpcodeM( PEXTUW, MMI_Default ); - MakeOpcodeM( PEXTUH, MMI_Default ); - MakeOpcodeM( PEXTUB, MMI_Default ); - MakeOpcodeM( PSLLVW, MMI_Default ); - MakeOpcodeM( PSRLVW, MMI_Default ); + MakeOpcodeM( PABSW, MMI_Default, 0 ); + MakeOpcodeM( PABSH, MMI_Default, 0 ); + MakeOpcodeM( PCEQW, MMI_Default, 0 ); + MakeOpcodeM( PMINW, MMI_Default, 0 ); + MakeOpcodeM( PMINH, MMI_Default, 0 ); + MakeOpcodeM( PADSBH, MMI_Default, 0 ); + MakeOpcodeM( PCEQH, MMI_Default, 0 ); + MakeOpcodeM( PCEQB, MMI_Default, 0 ); + MakeOpcodeM( PEXTUW, MMI_Default, 0 ); + MakeOpcodeM( PEXTUH, MMI_Default, 0 ); + MakeOpcodeM( PEXTUB, MMI_Default, 0 ); + MakeOpcodeM( PSLLVW, MMI_Default, 0 ); + MakeOpcodeM( PSRLVW, MMI_Default, 0 ); - MakeOpcodeM( QFSRV, MMI_Default ); + MakeOpcodeM( QFSRV, MMI_Default, 0 ); - MakeOpcodeM( PMADDH, MMI_Mult ); - MakeOpcodeM( PHMADH, MMI_Mult ); - MakeOpcodeM( PMSUBH, MMI_Mult ); - MakeOpcodeM( PHMSBH, MMI_Mult ); - MakeOpcodeM( PMULTH, MMI_Mult ); - MakeOpcodeM( PMADDW, MMI_Mult ); - MakeOpcodeM( PMSUBW, MMI_Mult ); - MakeOpcodeM( PMFHI, MMI_Mult ); - MakeOpcodeM( PMFLO, MMI_Mult ); - MakeOpcodeM( PMULTW, MMI_Mult ); - MakeOpcodeM( PMADDUW, MMI_Mult ); - MakeOpcodeM( PMULTUW, MMI_Mult ); - MakeOpcodeM( PDIVUW, MMI_Div ); - MakeOpcodeM( PDIVW, MMI_Div ); - MakeOpcodeM( PDIVBW, MMI_Div ); + MakeOpcodeM( PMADDH, MMI_Mult, 0 ); + MakeOpcodeM( PHMADH, MMI_Mult, 0 ); + MakeOpcodeM( PMSUBH, MMI_Mult, 0 ); + MakeOpcodeM( PHMSBH, MMI_Mult, 0 ); + MakeOpcodeM( PMULTH, MMI_Mult, 0 ); + MakeOpcodeM( PMADDW, MMI_Mult, 0 ); + MakeOpcodeM( PMSUBW, MMI_Mult, 0 ); + MakeOpcodeM( PMFHI, MMI_Mult, 0 ); + MakeOpcodeM( PMFLO, MMI_Mult, 0 ); + MakeOpcodeM( PMULTW, MMI_Mult, 0 ); + MakeOpcodeM( PMADDUW, MMI_Mult, 0 ); + MakeOpcodeM( PMULTUW, MMI_Mult, 0 ); + MakeOpcodeM( PDIVUW, MMI_Div, 0 ); + MakeOpcodeM( PDIVW, MMI_Div, 0 ); + MakeOpcodeM( PDIVBW, MMI_Div, 0 ); - MakeOpcodeM( PINTH, MMI_Default ); - MakeOpcodeM( PCPYLD, MMI_Default ); - MakeOpcodeM( PAND, MMI_Default ); - MakeOpcodeM( PXOR, MMI_Default ); - MakeOpcodeM( PEXEH, MMI_Default ); - MakeOpcodeM( PREVH, MMI_Default ); - MakeOpcodeM( PEXEW, MMI_Default ); - MakeOpcodeM( PROT3W, MMI_Default ); + MakeOpcodeM( PINTH, MMI_Default, 0 ); + MakeOpcodeM( PCPYLD, MMI_Default, 0 ); + MakeOpcodeM( PAND, MMI_Default, 0 ); + MakeOpcodeM( PXOR, MMI_Default, 0 ); + MakeOpcodeM( PEXEH, MMI_Default, 0 ); + MakeOpcodeM( PREVH, MMI_Default, 0 ); + MakeOpcodeM( PEXEW, MMI_Default, 0 ); + MakeOpcodeM( PROT3W, MMI_Default, 0 ); - MakeOpcodeM( PSRAVW, MMI_Default ); - MakeOpcodeM( PMTHI, MMI_Default ); - MakeOpcodeM( PMTLO, MMI_Default ); - MakeOpcodeM( PINTEH, MMI_Default ); - MakeOpcodeM( PCPYUD, MMI_Default ); - MakeOpcodeM( POR, MMI_Default ); - MakeOpcodeM( PNOR, MMI_Default ); - MakeOpcodeM( PEXCH, MMI_Default ); - MakeOpcodeM( PCPYH, MMI_Default ); - MakeOpcodeM( PEXCW, MMI_Default ); + MakeOpcodeM( PSRAVW, MMI_Default, 0 ); + MakeOpcodeM( PMTHI, MMI_Default, 0 ); + MakeOpcodeM( PMTLO, MMI_Default, 0 ); + MakeOpcodeM( PINTEH, MMI_Default, 0 ); + MakeOpcodeM( PCPYUD, MMI_Default, 0 ); + MakeOpcodeM( POR, MMI_Default, 0 ); + MakeOpcodeM( PNOR, MMI_Default, 0 ); + MakeOpcodeM( PEXCH, MMI_Default, 0 ); + MakeOpcodeM( PCPYH, MMI_Default, 0 ); + MakeOpcodeM( PEXCW, MMI_Default, 0 ); ////////////////////////////////////////////////////////// // COP0 Instructions @@ -386,21 +391,21 @@ namespace R5900 MakeOpcodeClass( COP0_C0 ); MakeOpcodeClass( COP0_BC0 ); - MakeOpcode0( MFC0, CopDefault ); - MakeOpcode0( MTC0, CopDefault ); + MakeOpcode0( MFC0, CopDefault, 0 ); + MakeOpcode0( MTC0, CopDefault, 0 ); - MakeOpcode0( BC0F, Branch ); - MakeOpcode0( BC0T, Branch ); - MakeOpcode0( BC0FL, Branch ); - MakeOpcode0( BC0TL, Branch ); + MakeOpcode0( BC0F, Branch, 0 ); + MakeOpcode0( BC0T, Branch, 0 ); + MakeOpcode0( BC0FL, Branch, 0 ); + MakeOpcode0( BC0TL, Branch, 0 ); - MakeOpcode0( TLBR, CopDefault ); - MakeOpcode0( TLBWI, CopDefault ); - MakeOpcode0( TLBWR, CopDefault ); - MakeOpcode0( TLBP, CopDefault ); - MakeOpcode0( ERET, CopDefault ); - MakeOpcode0( EI, CopDefault ); - MakeOpcode0( DI, CopDefault ); + MakeOpcode0( TLBR, CopDefault, 0 ); + MakeOpcode0( TLBWI, CopDefault, 0 ); + MakeOpcode0( TLBWR, CopDefault, 0 ); + MakeOpcode0( TLBP, CopDefault, 0 ); + MakeOpcode0( ERET, CopDefault, IS_BRANCH|BRANCHTYPE_ERET ); + MakeOpcode0( EI, CopDefault, 0 ); + MakeOpcode0( DI, CopDefault, 0 ); ////////////////////////////////////////////////////////// // COP1 Instructions! @@ -409,44 +414,44 @@ namespace R5900 MakeOpcodeClass( COP1_S ); MakeOpcodeClass( COP1_W ); // contains CVT_S instruction *only* - MakeOpcode1( MFC1, CopDefault ); - MakeOpcode1( CFC1, CopDefault ); - MakeOpcode1( MTC1, CopDefault ); - MakeOpcode1( CTC1, CopDefault ); + MakeOpcode1( MFC1, CopDefault, 0 ); + MakeOpcode1( CFC1, CopDefault, 0 ); + MakeOpcode1( MTC1, CopDefault, 0 ); + MakeOpcode1( CTC1, CopDefault, 0 ); - MakeOpcode1( BC1F, Branch ); - MakeOpcode1( BC1T, Branch ); - MakeOpcode1( BC1FL, Branch ); - MakeOpcode1( BC1TL, Branch ); + MakeOpcode1( BC1F, Branch, IS_BRANCH|BRANCHTYPE_BC1|CONDTYPE_EQ ); + MakeOpcode1( BC1T, Branch, IS_BRANCH|BRANCHTYPE_BC1|CONDTYPE_NE ); + MakeOpcode1( BC1FL, Branch, IS_BRANCH|BRANCHTYPE_BC1|CONDTYPE_EQ|IS_LIKELY ); + MakeOpcode1( BC1TL, Branch, IS_BRANCH|BRANCHTYPE_BC1|CONDTYPE_NE|IS_LIKELY ); - MakeOpcode1( ADD_S, CopDefault ); - MakeOpcode1( ADDA_S, CopDefault ); - MakeOpcode1( SUB_S, CopDefault ); - MakeOpcode1( SUBA_S, CopDefault ); + MakeOpcode1( ADD_S, CopDefault, 0 ); + MakeOpcode1( ADDA_S, CopDefault, 0 ); + MakeOpcode1( SUB_S, CopDefault, 0 ); + MakeOpcode1( SUBA_S, CopDefault, 0 ); - MakeOpcode1( ABS_S, CopDefault ); - MakeOpcode1( MOV_S, CopDefault ); - MakeOpcode1( NEG_S, CopDefault ); - MakeOpcode1( MAX_S, CopDefault ); - MakeOpcode1( MIN_S, CopDefault ); + MakeOpcode1( ABS_S, CopDefault, 0 ); + MakeOpcode1( MOV_S, CopDefault, 0 ); + MakeOpcode1( NEG_S, CopDefault, 0 ); + MakeOpcode1( MAX_S, CopDefault, 0 ); + MakeOpcode1( MIN_S, CopDefault, 0 ); - MakeOpcode1( MUL_S, FPU_Mult ); - MakeOpcode1( DIV_S, 6*8 ); - MakeOpcode1( SQRT_S, 6*8 ); - MakeOpcode1( RSQRT_S, 8*8 ); - MakeOpcode1( MULA_S, FPU_Mult ); - MakeOpcode1( MADD_S, FPU_Mult ); - MakeOpcode1( MSUB_S, FPU_Mult ); - MakeOpcode1( MADDA_S, FPU_Mult ); - MakeOpcode1( MSUBA_S, FPU_Mult ); + MakeOpcode1( MUL_S, FPU_Mult, 0 ); + MakeOpcode1( DIV_S, 6*8, 0 ); + MakeOpcode1( SQRT_S, 6*8, 0 ); + MakeOpcode1( RSQRT_S, 8*8, 0 ); + MakeOpcode1( MULA_S, FPU_Mult, 0 ); + MakeOpcode1( MADD_S, FPU_Mult, 0 ); + MakeOpcode1( MSUB_S, FPU_Mult, 0 ); + MakeOpcode1( MADDA_S, FPU_Mult, 0 ); + MakeOpcode1( MSUBA_S, FPU_Mult, 0 ); - MakeOpcode1( C_F, CopDefault ); - MakeOpcode1( C_EQ, CopDefault ); - MakeOpcode1( C_LT, CopDefault ); - MakeOpcode1( C_LE, CopDefault ); + MakeOpcode1( C_F, CopDefault, 0 ); + MakeOpcode1( C_EQ, CopDefault, 0 ); + MakeOpcode1( C_LT, CopDefault, 0 ); + MakeOpcode1( C_LE, CopDefault, 0 ); - MakeOpcode1( CVT_S, CopDefault ); - MakeOpcode1( CVT_W, CopDefault ); + MakeOpcode1( CVT_S, CopDefault, 0 ); + MakeOpcode1( CVT_W, CopDefault, 0 ); } namespace OpcodeTables diff --git a/pcsx2/R5900OpcodeTables.h b/pcsx2/R5900OpcodeTables.h index 385991a410..394fb8c4c1 100644 --- a/pcsx2/R5900OpcodeTables.h +++ b/pcsx2/R5900OpcodeTables.h @@ -28,6 +28,49 @@ void COP2_SPECIAL(); void COP2_SPECIAL2(); void COP2_Unknown(); +// reserve the lower 8 bits for opcode specific types +// which of these are actually used depends on the opcode +// flags further below +#define MEMTYPE_MASK (0x07 << 0) +#define MEMTYPE_BYTE (0x01 << 0) +#define MEMTYPE_HALF (0x02 << 0) +#define MEMTYPE_WORD (0x03 << 0) +#define MEMTYPE_DWORD (0x04 << 0) +#define MEMTYPE_QWORD (0x05 << 0) + +#define CONDTYPE_MASK (0x07 << 0) +#define CONDTYPE_EQ (0x01 << 0) +#define CONDTYPE_NE (0x02 << 0) +#define CONDTYPE_LEZ (0x03 << 0) +#define CONDTYPE_GTZ (0x04 << 0) +#define CONDTYPE_LTZ (0x05 << 0) +#define CONDTYPE_GEZ (0x06 << 0) + +#define BRANCHTYPE_MASK (0x07 << 3) +#define BRANCHTYPE_JUMP (0x01 << 3) +#define BRANCHTYPE_BRANCH (0x02 << 3) +#define BRANCHTYPE_SYSCALL (0x03 << 3) +#define BRANCHTYPE_ERET (0x04 << 3) +#define BRANCHTYPE_REGISTER (0x05 << 3) +#define BRANCHTYPE_BC1 (0x06 << 3) + +#define ALUTYPE_MASK (0x07 << 3) +#define ALUTYPE_ADD (0x01 << 3) +#define ALUTYPE_ADDI (0x02 << 3) +#define ALUTYPE_SUB (0x03 << 3) +#define ALUTYPE_CONDMOVE (0x04 << 3) + +#define IS_LOAD 0x00000100 +#define IS_STORE 0x00000200 +#define IS_BRANCH 0x00000400 +#define IS_LINKED 0x00001000 +#define IS_LIKELY 0x00002000 +#define IS_MEMORY 0x00004000 +#define IS_CONDMOVE 0x00010000 +#define IS_ALU 0x00020000 +#define IS_64BIT 0x00040000 +#define IS_LEFT 0x00080000 +#define IS_RIGHT 0x00100000 namespace R5900 { @@ -79,6 +122,9 @@ namespace R5900 // Number of cycles this instruction normally uses. u8 cycles; + // Information about the opcode + u32 flags; + const OPCODE& (*getsubclass)(u32 op); // Process the instruction using the interpreter. diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp index 50f9cd462d..a3edc40a54 100644 --- a/pcsx2/x86/ix86-32/iR5900-32.cpp +++ b/pcsx2/x86/ix86-32/iR5900-32.cpp @@ -1359,45 +1359,9 @@ void recMemcheck(u32 op, u32 bits, bool store) inline bool isBranchOrJump(u32 addr) { u32 op = memRead32(addr); + const OPCODE& opcode = GetInstruction(op); - switch (op >> 26) - { - case 0x02: // j - case 0x03: // jal - case 0x04: // beq - case 0x05: // bne - case 0x06: // blez - case 0x07: // bgtz - case 0x14: // beql - case 0x15: // bnel - case 0x16: // blezl - case 0x17: // bgtzl - return true; - case 0x00: // special - switch (op & 0x3F) - { - case 0x08: // jr - case 0x09: // jalr - return true; - } - break; - case 0x01: // regimm - switch ((op >> 16) & 0x1F) - { - case 0x00: // bltz - case 0x01: // bgez - case 0x02: // bltzl - case 0x03: // bgezl - case 0x10: // bltzal - case 0x11: // bgezal - case 0x12: // bltzall - case 0x13: // bgezall - return true; - } - break; - } - - return false; + return (opcode.flags & IS_BRANCH) != 0; } // The next two functions return 0 if no breakpoint is needed, @@ -1419,39 +1383,18 @@ int isMemcheckNeeded(u32 pc) { if (CBreakPoints::GetMemChecks().size() == 0) return 0; - + u32 addr = pc; if (isBranchOrJump(addr)) addr += 4; u32 op = memRead32(addr); + const OPCODE& opcode = GetInstruction(op); - switch (op >> 26) - { - case 0x20: // lb - case 0x21: // lh - case 0x22: // lwl - case 0x23: // lw - case 0x24: // lbu - case 0x25: // lhu - case 0x26: // lwr - case 0x28: // sb - case 0x29: // sh - case 0x2A: // swl - case 0x2B: // sw - case 0x2E: // swr - case 0x37: // ld - case 0x1B: // ldr - case 0x3F: // sd - case 0x3D: // sdr - case 0x1A: // ldl - case 0x2C: // sdl - case 0x1E: // lq - case 0x1F: // sq + if ((opcode.flags & IS_MEMORY) && (opcode.flags & MEMTYPE_MASK) != 0) return addr == pc ? 1 : 2; - default: - return 0; - } + + return 0; } void encodeBreakpoint() @@ -1470,50 +1413,27 @@ void encodeMemcheck() return; u32 op = memRead32(needed == 2 ? pc+4 : pc); - switch (cpuRegs.code >> 26) + const OPCODE& opcode = GetInstruction(op); + + bool store = (opcode.flags & IS_STORE) != 0; + switch (opcode.flags & MEMTYPE_MASK) { - case 0x20: // lb - case 0x24: // lbu - recMemcheck(op,8,false); + case MEMTYPE_BYTE: + recMemcheck(op,8,store); break; - case 0x28: // sb - recMemcheck(op,8,true); + case MEMTYPE_HALF: + recMemcheck(op,16,store); break; - case 0x21: // lh - case 0x25: // lhu - recMemcheck(op,16,false); + case MEMTYPE_WORD: + recMemcheck(op,32,store); break; - case 0x22: // lwl - case 0x23: // lw - case 0x26: // lwr - recMemcheck(op,32,false); + case MEMTYPE_DWORD: + recMemcheck(op,64,store); break; - case 0x29: // sh - recMemcheck(op,16,true); - break; - case 0x2A: // swl - case 0x2B: // sw - case 0x2E: // swr - recMemcheck(op,32,true); - break; - case 0x37: // ld - case 0x1B: // ldr - case 0x1A: // ldl - recMemcheck(op,64,false); - break; - case 0x3F: // sd - case 0x3D: // sdr - case 0x2C: // sdl - recMemcheck(op,64,true); - break; - case 0x1E: // lq - recMemcheck(op,128,false); - break; - case 0x1F: // sq - recMemcheck(op,128,true); + case MEMTYPE_QWORD: + recMemcheck(op,128,store); break; } - } void recompileNextInstruction(int delayslot)