diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h index 6fd886ea0c..75136ec155 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h +++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h @@ -201,7 +201,9 @@ public: void lfsu(UGeckoInstruction _inst); void lfsx(UGeckoInstruction _inst); void lfd(UGeckoInstruction _inst); + void lfdu(UGeckoInstruction _inst); void stfs(UGeckoInstruction _inst); + void stfsu(UGeckoInstruction _inst); // Paired Singles void ps_add(UGeckoInstruction _inst); diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp index 723430cc95..6bc9392978 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp @@ -183,6 +183,43 @@ void JitArm::lfd(UGeckoInstruction inst) SetJumpTarget(DoNotLoad); } +void JitArm::lfdu(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITLoadStoreFloatingOff) + + ARMReg RA = gpr.R(inst.RA); + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + + ARMReg v0 = fpr.R0(inst.FD); + + MOVI2R(rB, inst.SIMM_16); + ADD(rB, rB, RA); + + LDR(rA, R9, PPCSTATE_OFF(Exceptions)); + CMP(rA, EXCEPTION_DSI); + FixupBranch DoNotLoad = B_CC(CC_EQ); + + MOVI2R(rA, (u32)&Memory::Read_F64); + MOV(RA, rB); + + PUSH(4, R0, R1, R2, R3); + MOV(R0, rB); + BL(rA); + +#if !defined(__ARM_PCS_VFP) // SoftFP returns in R0 and R1 + VMOV(v0, R0); +#else + VMOV(v0, D0); +#endif + + POP(4, R0, R1, R2, R3); + + gpr.Unlock(rA, rB); + SetJumpTarget(DoNotLoad); +} + void JitArm::stfs(UGeckoInstruction inst) { INSTRUCTION_START @@ -215,3 +252,37 @@ void JitArm::stfs(UGeckoInstruction inst) gpr.Unlock(rA, rB); } +void JitArm::stfsu(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITLoadStoreFloatingOff) + + ARMReg RA = gpr.R(inst.RA); + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + ARMReg v0 = fpr.R0(inst.FS); + VCVT(S0, v0, 0); + + MOVI2R(rB, inst.SIMM_16); + ADD(rB, rB, RA); + + LDR(rA, R9, PPCSTATE_OFF(Exceptions)); + CMP(rA, EXCEPTION_DSI); + + SetCC(CC_NEQ); + MOV(RA, rB); + SetCC(); + + MOVI2R(rA, (u32)&Memory::Write_U32); + PUSH(4, R0, R1, R2, R3); + VMOV(R0, S0); + MOV(R1, rB); + + BL(rA); + + POP(4, R0, R1, R2, R3); + + gpr.Unlock(rA, rB); +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp index 6f649f2890..da6d6b9dc8 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp @@ -100,10 +100,10 @@ static GekkoOPTemplate primarytable[] = {48, &JitArm::lfs}, //"lfs", OPTYPE_LOADFP, FL_IN_A}}, {49, &JitArm::lfsu}, //"lfsu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}}, {50, &JitArm::lfd}, //"lfd", OPTYPE_LOADFP, FL_IN_A}}, - {51, &JitArm::Default}, //"lfdu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}}, + {51, &JitArm::lfdu}, //"lfdu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}}, {52, &JitArm::stfs}, //"stfs", OPTYPE_STOREFP, FL_IN_A}}, - {53, &JitArm::Default}, //"stfsu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}}, + {53, &JitArm::stfsu}, //"stfsu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}}, {54, &JitArm::Default}, //"stfd", OPTYPE_STOREFP, FL_IN_A}}, {55, &JitArm::Default}, //"stfdu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},