diff --git a/Source/Core/Core/Src/PowerPC/JitArmIL/IR_Arm.cpp b/Source/Core/Core/Src/PowerPC/JitArmIL/IR_Arm.cpp index d1bdd157ad..d3a6786e78 100644 --- a/Source/Core/Core/Src/PowerPC/JitArmIL/IR_Arm.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArmIL/IR_Arm.cpp @@ -509,6 +509,21 @@ static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit) { Jit->BL(R14); break; } + case SystemCall: { + unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); + Jit->MOVI2R(R14, InstLoc + 4); + Jit->STR(R14, R9, PPCSTATE_OFF(pc)); + Jit->LDR(R14, R9, PPCSTATE_OFF(Exceptions)); + Jit->ORR(R14, R14, EXCEPTION_SYSCALL); + Jit->STR(R14, R9, PPCSTATE_OFF(Exceptions)); + Jit->WriteExceptionExit(); + break; + } + case InterpreterBranch: { + Jit->LDR(R14, R9, PPCSTATE_OFF(npc)); + Jit->WriteExitDestInReg(R14); + break; + } case RFIExit: { const u32 mask = 0x87C0FFFF; const u32 clearMSR13 = 0xFFFBFFFF; // Mask used to clear the bit MSR[13] diff --git a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.cpp index a4041c7244..788aad3f3a 100644 --- a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.cpp @@ -70,6 +70,11 @@ void JitArmIL::DoNothing(UGeckoInstruction _inst) { // Yup, just don't do anything. } +void JitArmIL::Break(UGeckoInstruction _inst) +{ + ibuild.EmitINT3(); +} + void JitArmIL::DoDownCount() { ARMReg rA = R14; @@ -105,7 +110,13 @@ void JitArmIL::WriteRfiExitDestInR(ARMReg Reg) MOVI2R(Reg, (u32)asm_routines.testExceptions); B(Reg); } +void JitArmIL::WriteExceptionExit() +{ + DoDownCount(); + MOVI2R(R14, (u32)asm_routines.testExceptions); + B(R14); +} void JitArmIL::WriteExit(u32 destination, int exit_num) { DoDownCount(); @@ -183,7 +194,6 @@ void STACKALIGN JitArmIL::Jit(u32 em_address) const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b) { - printf("Doing a JIT in JITARMIL. Scream and shout.\n"); int blockSize = code_buf->GetSize(); // Memory exception on instruction fetch bool memory_exception = false; @@ -318,7 +328,7 @@ const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB } if (!ops[i].skip) { - PrintDebug(ops[i].inst, 1); + PrintDebug(ops[i].inst, 0); if (js.memcheck && (opinfo->flags & FL_USE_FPU)) { // Don't do this yet @@ -349,7 +359,6 @@ const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB { } - printf("Done emitting block. size was 0x%08x\n", size); FlushIcache(); return start; diff --git a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.h b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.h index a6a6b8012f..e70007e35e 100644 --- a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.h +++ b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.h @@ -75,12 +75,14 @@ public: void WriteExit(u32 destination, int exit_num); void WriteExitDestInReg(ARMReg Reg); void WriteRfiExitDestInR(ARMReg Reg); + void WriteExceptionExit(); // OPCODES void unknown_instruction(UGeckoInstruction inst); void Default(UGeckoInstruction inst); void DoNothing(UGeckoInstruction inst); void HLEFunction(UGeckoInstruction inst); + void Break(UGeckoInstruction inst); void DynaRunTable4(UGeckoInstruction inst); void DynaRunTable19(UGeckoInstruction inst); @@ -94,10 +96,13 @@ public: void BIN_ADD(ARMReg reg, Operand2 op2); // Branches + void icbi(UGeckoInstruction inst); + void sc(UGeckoInstruction inst); void rfi(UGeckoInstruction inst); void bx(UGeckoInstruction inst); void bcx(UGeckoInstruction inst); void bclrx(UGeckoInstruction inst); + void bcctrx(UGeckoInstruction inst); // System Registers void mtmsr(UGeckoInstruction inst); }; diff --git a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Branch.cpp b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Branch.cpp index c6576e882d..4cf2c3fc25 100644 --- a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Branch.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Branch.cpp @@ -12,8 +12,17 @@ #include "../../HW/Memmap.h" -//#define NORMALBRANCH_START Default(inst); ibuild.EmitInterpreterBranch(); return; -#define NORMALBRANCH_START +#define NORMALBRANCH_START Default(inst); ibuild.EmitInterpreterBranch(); return; +//#define NORMALBRANCH_START +void JitArmIL::icbi(UGeckoInstruction inst) +{ + Default(inst); + ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4)); +} +void JitArmIL::sc(UGeckoInstruction inst) +{ + ibuild.EmitSystemCall(ibuild.EmitIntConst(js.compilerPC)); +} void JitArmIL::rfi(UGeckoInstruction inst) { @@ -143,3 +152,32 @@ void JitArmIL::bcx(UGeckoInstruction inst) ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4)); } +void JitArmIL::bcctrx(UGeckoInstruction inst) +{ + NORMALBRANCH_START + if ((inst.BO & 4) == 0) { + IREmitter::InstLoc c = ibuild.EmitLoadCTR(); + c = ibuild.EmitSub(c, ibuild.EmitIntConst(1)); + ibuild.EmitStoreCTR(c); + } + IREmitter::InstLoc test; + if ((inst.BO & 16) == 0) // Test a CR bit + { + IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2); + IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3)); + test = ibuild.EmitAnd(CRReg, CRCmp); + if (!(inst.BO & 8)) + test = ibuild.EmitXor(test, CRCmp); + } else { + test = ibuild.EmitIntConst(1); + } + test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0)); + ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4)); + + IREmitter::InstLoc destination = ibuild.EmitLoadCTR(); + destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4)); + if (inst.LK) + ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4)); + ibuild.EmitBranchUncond(destination); +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Tables.cpp b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Tables.cpp index 2072336188..31d7504d64 100644 --- a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Tables.cpp @@ -40,10 +40,10 @@ static GekkoOPTemplate primarytable[] = {16, &JitArmIL::bcx}, //"bcx", OPTYPE_SYSTEM, FL_ENDBLOCK}}, {18, &JitArmIL::bx}, //"bx", OPTYPE_SYSTEM, FL_ENDBLOCK}}, - {1, &JitArmIL::Default}, //"HLEFunction", OPTYPE_SYSTEM, FL_ENDBLOCK}}, + {1, &JitArmIL::HLEFunction}, //"HLEFunction", OPTYPE_SYSTEM, FL_ENDBLOCK}}, {2, &JitArmIL::Default}, //"DynaBlock", OPTYPE_SYSTEM, 0}}, - {3, &JitArmIL::Default}, //"twi", OPTYPE_SYSTEM, FL_ENDBLOCK}}, - {17, &JitArmIL::Default}, //"sc", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}}, + {3, &JitArmIL::Break}, //"twi", OPTYPE_SYSTEM, FL_ENDBLOCK}}, + {17, &JitArmIL::sc}, //"sc", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}}, {7, &JitArmIL::Default}, //"mulli", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_RC_BIT, 2}}, {8, &JitArmIL::Default}, //"subfic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}}, @@ -160,7 +160,7 @@ static GekkoOPTemplate table4_3[] = static GekkoOPTemplate table19[] = { - {528, &JitArmIL::Default}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}}, + {528, &JitArmIL::bcctrx}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}}, {16, &JitArmIL::bclrx}, //"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}}, {257, &JitArmIL::Default}, //"crand", OPTYPE_CR, FL_EVIL}}, {129, &JitArmIL::Default}, //"crandc", OPTYPE_CR, FL_EVIL}}, @@ -175,7 +175,7 @@ static GekkoOPTemplate table19[] = {0, &JitArmIL::Default}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}}, {50, &JitArmIL::rfi}, //"rfi", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS, 1}}, - {18, &JitArmIL::Default}, //"rfid", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS}} + {18, &JitArmIL::Break}, //"rfid", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS}} }; @@ -279,9 +279,9 @@ static GekkoOPTemplate table31[] = {595, &JitArmIL::Default}, //"mfsr", OPTYPE_SYSTEM, FL_OUT_D, 2}}, {659, &JitArmIL::Default}, //"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 2}}, - {4, &JitArmIL::Default}, //"tw", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}}, + {4, &JitArmIL::Break}, //"tw", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}}, {598, &JitArmIL::Default}, //"sync", OPTYPE_SYSTEM, 0, 2}}, - {982, &JitArmIL::Default}, //"icbi", OPTYPE_SYSTEM, FL_ENDBLOCK, 3}}, + {982, &JitArmIL::icbi}, //"icbi", OPTYPE_SYSTEM, FL_ENDBLOCK, 3}}, // Unused instructions on GC {310, &JitArmIL::Default}, //"eciwx", OPTYPE_INTEGER, FL_RC_BIT}},