[ARM] ps_rsqrte implementation.
This commit is contained in:
parent
7d410ec95c
commit
a0a0c526ae
|
@ -67,7 +67,8 @@ private:
|
||||||
|
|
||||||
void PrintDebug(UGeckoInstruction inst, u32 level);
|
void PrintDebug(UGeckoInstruction inst, u32 level);
|
||||||
|
|
||||||
void Helper_UpdateCR1(ARMReg value);
|
void Helper_UpdateCR1(ARMReg value);
|
||||||
|
|
||||||
void SetFPException(ARMReg Reg, u32 Exception);
|
void SetFPException(ARMReg Reg, u32 Exception);
|
||||||
public:
|
public:
|
||||||
JitArm() : code_buffer(32000) {}
|
JitArm() : code_buffer(32000) {}
|
||||||
|
@ -238,6 +239,7 @@ public:
|
||||||
void ps_neg(UGeckoInstruction _inst);
|
void ps_neg(UGeckoInstruction _inst);
|
||||||
void ps_abs(UGeckoInstruction _inst);
|
void ps_abs(UGeckoInstruction _inst);
|
||||||
void ps_nabs(UGeckoInstruction _inst);
|
void ps_nabs(UGeckoInstruction _inst);
|
||||||
|
void ps_rsqrte(UGeckoInstruction _inst);
|
||||||
|
|
||||||
// LoadStore paired
|
// LoadStore paired
|
||||||
void psq_l(UGeckoInstruction _inst);
|
void psq_l(UGeckoInstruction _inst);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -25,64 +25,19 @@
|
||||||
#include "../PPCTables.h"
|
#include "../PPCTables.h"
|
||||||
#include "ArmEmitter.h"
|
#include "ArmEmitter.h"
|
||||||
#include "../../HW/Memmap.h"
|
#include "../../HW/Memmap.h"
|
||||||
#include "../Interpreter/Interpreter_FPUtils.h"
|
#include "JitArm_FPUtils.h"
|
||||||
|
|
||||||
#include "Jit.h"
|
#include "Jit.h"
|
||||||
#include "JitRegCache.h"
|
#include "JitRegCache.h"
|
||||||
#include "JitFPRCache.h"
|
#include "JitFPRCache.h"
|
||||||
#include "JitAsm.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)
|
void JitArm::Helper_UpdateCR1(ARMReg value)
|
||||||
{
|
{
|
||||||
// Should just update exception flags, not do any compares.
|
// Should just update exception flags, not do any compares.
|
||||||
PanicAlert("CR1");
|
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)
|
void JitArm::fctiwzx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
|
|
|
@ -22,11 +22,76 @@
|
||||||
#include "../../CoreTiming.h"
|
#include "../../CoreTiming.h"
|
||||||
#include "../PPCTables.h"
|
#include "../PPCTables.h"
|
||||||
#include "ArmEmitter.h"
|
#include "ArmEmitter.h"
|
||||||
|
#include "JitArm_FPUtils.h"
|
||||||
|
|
||||||
#include "Jit.h"
|
#include "Jit.h"
|
||||||
#include "JitRegCache.h"
|
#include "JitRegCache.h"
|
||||||
#include "JitAsm.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)
|
void JitArm::ps_add(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
|
|
|
@ -155,7 +155,7 @@ static GekkoOPTemplate table4_2[] =
|
||||||
{23, &JitArm::Default}, //"ps_sel", OPTYPE_PS, 0}},
|
{23, &JitArm::Default}, //"ps_sel", OPTYPE_PS, 0}},
|
||||||
{24, &JitArm::Default}, //"ps_res", OPTYPE_PS, 0}},
|
{24, &JitArm::Default}, //"ps_res", OPTYPE_PS, 0}},
|
||||||
{25, &JitArm::ps_mul}, //"ps_mul", 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}},
|
{28, &JitArm::ps_msub}, //"ps_msub", OPTYPE_PS, 0}},
|
||||||
{29, &JitArm::ps_madd}, //"ps_madd", OPTYPE_PS, 0}},
|
{29, &JitArm::ps_madd}, //"ps_madd", OPTYPE_PS, 0}},
|
||||||
{30, &JitArm::ps_nmsub}, //"ps_nmsub", OPTYPE_PS, 0}},
|
{30, &JitArm::ps_nmsub}, //"ps_nmsub", OPTYPE_PS, 0}},
|
||||||
|
|
Loading…
Reference in New Issue