diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h index 37ea9459f1..d1280eaddf 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h +++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h @@ -67,7 +67,8 @@ private: void PrintDebug(UGeckoInstruction inst, u32 level); - void Helper_UpdateCR1(ARMReg value); + void Helper_UpdateCR1(ARMReg value); + void SetFPException(ARMReg Reg, u32 Exception); public: JitArm() : code_buffer(32000) {} @@ -238,6 +239,7 @@ public: void ps_neg(UGeckoInstruction _inst); void ps_abs(UGeckoInstruction _inst); void ps_nabs(UGeckoInstruction _inst); + void ps_rsqrte(UGeckoInstruction _inst); // LoadStore paired void psq_l(UGeckoInstruction _inst); diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FPUtils.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FPUtils.h new file mode 100644 index 0000000000..c186ae9696 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FPUtils.h @@ -0,0 +1,66 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. +#include "../Interpreter/Interpreter_FPUtils.h" + +#include "Jit.h" +#include "JitRegCache.h" +#include "JitFPRCache.h" +#include "JitAsm.h" + +static const double minmaxFloat[2] = {-(double)0x80000000, (double)0x7FFFFFFF}; +static const double doublenum = 0xfff8000000000000ull; + +// Exception masks +static Operand2 FRFIMask(5, 0x8); // 0x60000 +static Operand2 FIMask(2, 8); // 0x20000 +static Operand2 FRMask(4, 8); // 0x40000 +static Operand2 FXMask(2, 1); // 0x80000000 +static Operand2 VEMask(0x40, 0); // 0x40 + +static Operand2 XXException(2, 4); // 0x2000000 +static Operand2 CVIException(1, 0xC); // 0x100 +static Operand2 NANException(1, 4); // 0x1000000 +static Operand2 VXVCException(8, 8); // 0x80000 +static Operand2 ZXException(1, 3); // 0x4000000 +static Operand2 VXSQRTException(2, 5); // 0x200 + +inline void JitArm::SetFPException(ARMReg Reg, u32 Exception) +{ + Operand2 *ExceptionMask; + switch(Exception) + { + case FPSCR_VXCVI: + ExceptionMask = &CVIException; + break; + case FPSCR_XX: + ExceptionMask = &XXException; + break; + case FPSCR_VXSNAN: + ExceptionMask = &NANException; + break; + case FPSCR_VXVC: + ExceptionMask = &VXVCException; + break; + case FPSCR_ZX: + ExceptionMask = &ZXException; + break; + case FPSCR_VXSQRT: + ExceptionMask = &VXSQRTException; + break; + default: + _assert_msg_(DYNA_REC, false, "Passed unsupported FPexception: 0x%08x", Exception); + return; + break; + } + ARMReg rB = gpr.GetReg(); + MOV(rB, Reg); + ORR(Reg, Reg, *ExceptionMask); + CMP(rB, Reg); + SetCC(CC_NEQ); + ORR(Reg, Reg, FXMask); // If exception is set, set exception bit + SetCC(); + BIC(Reg, Reg, FRFIMask); + gpr.Unlock(rB); +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp index 9f5c2ce96a..c3e46b83f2 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp @@ -25,64 +25,19 @@ #include "../PPCTables.h" #include "ArmEmitter.h" #include "../../HW/Memmap.h" -#include "../Interpreter/Interpreter_FPUtils.h" +#include "JitArm_FPUtils.h" #include "Jit.h" #include "JitRegCache.h" #include "JitFPRCache.h" #include "JitAsm.h" -static const double minmaxFloat[2] = {-(double)0x80000000, (double)0x7FFFFFFF}; -static const double doublenum = 0xfff8000000000000ull; -static Operand2 FRFIMask(5, 0x8); // 0x60000 -static Operand2 FIMask(2, 8); // 0x20000 -static Operand2 FRMask(4, 8); // 0x40000 -static Operand2 FXMask(2, 1); // 0x80000000 -static Operand2 VEMask(0x40, 0); // 0x40 - -static Operand2 XXException(2, 4); // 0x2000000 -static Operand2 CVIException(1, 0xC); // 0x100 -static Operand2 NANException(1, 4); // 0x1000000 -static Operand2 VXVCException(8, 8); // 0x80000 void JitArm::Helper_UpdateCR1(ARMReg value) { // Should just update exception flags, not do any compares. PanicAlert("CR1"); } -void JitArm::SetFPException(ARMReg Reg, u32 Exception) -{ - Operand2 *ExceptionMask; - switch(Exception) - { - case FPSCR_VXCVI: - ExceptionMask = &CVIException; - break; - case FPSCR_XX: - ExceptionMask = &XXException; - break; - case FPSCR_VXSNAN: - ExceptionMask = &NANException; - break; - case FPSCR_VXVC: - ExceptionMask = &VXVCException; - break; - default: - _assert_msg_(DYNA_REC, false, "Passed unsupported FPexception: 0x%08x", Exception); - return; - break; - } - ARMReg rB = gpr.GetReg(); - MOV(rB, Reg); - ORR(Reg, Reg, *ExceptionMask); - CMP(rB, Reg); - SetCC(CC_NEQ); - ORR(Reg, Reg, FXMask); // If exception is set, set exception bit - SetCC(); - BIC(Reg, Reg, FRFIMask); - gpr.Unlock(rB); -} - void JitArm::fctiwzx(UGeckoInstruction inst) { INSTRUCTION_START diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Paired.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Paired.cpp index 175fc9e31e..ff9d85da63 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Paired.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Paired.cpp @@ -22,11 +22,76 @@ #include "../../CoreTiming.h" #include "../PPCTables.h" #include "ArmEmitter.h" +#include "JitArm_FPUtils.h" #include "Jit.h" #include "JitRegCache.h" #include "JitAsm.h" +void JitArm::ps_rsqrte(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITPairedOff) + + u32 b = inst.FB, d = inst.FD; + if (inst.Rc){ + Default(inst); return; + } + ARMReg vB0 = fpr.R0(b); + ARMReg vB1 = fpr.R1(b); + ARMReg vD0 = fpr.R0(d, false); + ARMReg vD1 = fpr.R1(d, false); + ARMReg fpscrReg = gpr.GetReg(); + ARMReg V0 = D1; + ARMReg rA = gpr.GetReg(); + + MOVI2R(fpscrReg, (u32)&PPC_NAN); + VLDR(V0, fpscrReg, 0); + LDR(fpscrReg, R9, PPCSTATE_OFF(fpscr)); + + VCMP(vB0); + VMRS(_PC); + FixupBranch Less0 = B_CC(CC_LT); + VMOV(vD0, V0); + SetFPException(fpscrReg, FPSCR_VXSQRT); + FixupBranch SkipOrr0 = B(); + SetJumpTarget(Less0); + SetCC(CC_EQ); + ORR(rA, rA, 1); + SetCC(); + SetJumpTarget(SkipOrr0); + + VCMP(vB1); + VMRS(_PC); + FixupBranch Less1 = B_CC(CC_LT); + VMOV(vD1, V0); + SetFPException(fpscrReg, FPSCR_VXSQRT); + FixupBranch SkipOrr1 = B(); + SetJumpTarget(Less1); + SetCC(CC_EQ); + ORR(rA, rA, 2); + SetCC(); + SetJumpTarget(SkipOrr1); + + CMP(rA, 0); + FixupBranch noException = B_CC(CC_EQ); + SetFPException(fpscrReg, FPSCR_ZX); + SetJumpTarget(noException); + + VCVT(S0, vB0, 0); + VCVT(S1, vB1, 0); + + NEONXEmitter nemit(this); + nemit.VRSQRTE(F_32, D0, D0); + VCVT(vD0, S0, 0); + VCVT(vD1, S1, 0); + BKPT(1); + + STR(fpscrReg, R9, PPCSTATE_OFF(fpscr)); + gpr.Unlock(fpscrReg, rA); + fpr.Unlock(V0); +} + void JitArm::ps_add(UGeckoInstruction inst) { INSTRUCTION_START diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp index cd67098ae3..01bda52b92 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp @@ -155,7 +155,7 @@ static GekkoOPTemplate table4_2[] = {23, &JitArm::Default}, //"ps_sel", OPTYPE_PS, 0}}, {24, &JitArm::Default}, //"ps_res", OPTYPE_PS, 0}}, {25, &JitArm::ps_mul}, //"ps_mul", OPTYPE_PS, 0}}, - {26, &JitArm::Default}, //"ps_rsqrte", OPTYPE_PS, 0, 1}}, + {26, &JitArm::ps_rsqrte}, //"ps_rsqrte", OPTYPE_PS, 0, 1}}, {28, &JitArm::ps_msub}, //"ps_msub", OPTYPE_PS, 0}}, {29, &JitArm::ps_madd}, //"ps_madd", OPTYPE_PS, 0}}, {30, &JitArm::ps_nmsub}, //"ps_nmsub", OPTYPE_PS, 0}},