[ARM] ps_rsqrte implementation.

This commit is contained in:
Ryan Houdek 2013-09-16 12:59:34 +00:00
parent 7d410ec95c
commit a0a0c526ae
5 changed files with 136 additions and 48 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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}},