diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h index 9b354b29d3..160a17bc2c 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h +++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h @@ -253,8 +253,9 @@ public: // LoadStore paired void psq_l(UGeckoInstruction _inst); + void psq_lx(UGeckoInstruction _inst); void psq_st(UGeckoInstruction _inst); - + void psq_stx(UGeckoInstruction _inst); }; #endif // _JIT64_H diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStorePaired.cpp index bae9042dd0..ab90f41655 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStorePaired.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStorePaired.cpp @@ -54,6 +54,54 @@ void JitArm::psq_l(UGeckoInstruction inst) MOVI2F(vD1, 1.0f, INVALID_REG); // No need for temp reg with 1.0f } +void JitArm::psq_lx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITLoadStorePairedOff) + + bool update = inst.SUBOP10 == 38; + // R12 contains scale + // R11 contains type + // R10 is the ADDR + if (js.memcheck || !Core::g_CoreStartupParameter.bFastmem) { Default(inst); return; } + + LDR(R11, R9, PPCSTATE_OFF(spr[SPR_GQR0 + inst.Ix])); + UBFX(R12, R11, 16, 3); // Type + LSL(R12, R12, 2); + UBFX(R11, R11, 24, 6); // Scale + LSL(R11, R11, 2); + + if (inst.RA || update) // Always uses the register on update + { + ADD(R10, gpr.R(inst.RB), gpr.R(inst.RA)); + } + else + MOV(R10, gpr.R(inst.RB)); + + if (update) + MOV(gpr.R(inst.RA), R10); + + MOVI2R(R14, (u32)asm_routines.pairedLoadQuantized); + ADD(R14, R14, R12); + LDR(R14, R14, inst.Wx ? 8 * 4 : 0); + + // Values returned in S0, S1 + BL(R14); // Jump to the quantizer Load + + ARMReg vD0 = fpr.R0(inst.RS, false); + ARMReg vD1 = fpr.R1(inst.RS, false); + LDR(R14, R9, PPCSTATE_OFF(Exceptions)); + CMP(R14, EXCEPTION_DSI); + SetCC(CC_NEQ); + + VCVT(vD0, S0, 0); + if (!inst.Wx) + VCVT(vD1, S1, 0); + else + MOVI2F(vD1, 1.0f, INVALID_REG); // No need for temp reg with 1.0f + SetCC(); +} + void JitArm::psq_st(UGeckoInstruction inst) { INSTRUCTION_START @@ -98,3 +146,47 @@ void JitArm::psq_st(UGeckoInstruction inst) // floats passed through D0 BL(R14); // Jump to the quantizer Store } + +void JitArm::psq_stx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITLoadStorePairedOff) + + bool update = inst.SUBOP10 == 39; + + // R12 contains scale + // R11 contains type + // R10 is the ADDR + if (js.memcheck || !Core::g_CoreStartupParameter.bFastmem) { Default(inst); return; } + + LDR(R11, R9, PPCSTATE_OFF(spr[SPR_GQR0 + inst.I])); + UBFX(R12, R11, 0, 3); // Type + LSL(R12, R12, 2); + UBFX(R11, R11, 8, 6); // Scale + LSL(R11, R11, 2); + + if (inst.RA || update) // Always uses the register on update + { + ADD(R10, gpr.R(inst.RA), gpr.R(inst.RB)); + } + else + MOV(R10, gpr.R(inst.RB)); + + if (update) + MOV(gpr.R(inst.RA), R10); + + MOVI2R(R14, (u32)asm_routines.pairedStoreQuantized); + ADD(R14, R14, R12); + LDR(R14, R14, inst.W ? 8 * 4 : 0); + + ARMReg vD0 = fpr.R0(inst.RS); + VCVT(S0, vD0, 0); + + if (!inst.W) + { + ARMReg vD1 = fpr.R1(inst.RS); + VCVT(S1, vD1, 0); + } + // floats passed through D0 + BL(R14); // Jump to the quantizer Store +} diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp index 4f37d72c5f..848f5338b5 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp @@ -165,10 +165,10 @@ static GekkoOPTemplate table4_2[] = static GekkoOPTemplate table4_3[] = { - {6, &JitArm::Default}, //"psq_lx", OPTYPE_PS, 0}}, - {7, &JitArm::Default}, //"psq_stx", OPTYPE_PS, 0}}, - {38, &JitArm::Default}, //"psq_lux", OPTYPE_PS, 0}}, - {39, &JitArm::Default}, //"psq_stux", OPTYPE_PS, 0}}, + {6, &JitArm::psq_lx}, //"psq_lx", OPTYPE_PS, 0}}, + {7, &JitArm::psq_stx}, //"psq_stx", OPTYPE_PS, 0}}, + {38, &JitArm::psq_lx}, //"psq_lux", OPTYPE_PS, 0}}, + {39, &JitArm::psq_stx}, //"psq_stux", OPTYPE_PS, 0}}, }; static GekkoOPTemplate table19[] =