[ARM] fcmpo/fcmpu implementations.

This commit is contained in:
Ryan Houdek 2013-09-16 08:57:51 +00:00
parent c56ecce840
commit 0bcc20ca5b
3 changed files with 145 additions and 5 deletions

View File

@ -200,7 +200,9 @@ public:
void fmrx(UGeckoInstruction _inst);
void fmaddsx(UGeckoInstruction _inst);
void fmaddx(UGeckoInstruction _inst);
void fctiwzx(UGeckoInstruction inst);
void fctiwzx(UGeckoInstruction _inst);
void fcmpo(UGeckoInstruction _inst);
void fcmpu(UGeckoInstruction _inst);
// Floating point loadStore
void lfs(UGeckoInstruction _inst);

View File

@ -38,10 +38,12 @@ 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.
@ -59,6 +61,12 @@ void JitArm::SetFPException(ARMReg Reg, u32 Exception)
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;
@ -155,6 +163,136 @@ void JitArm::fctiwzx(UGeckoInstruction inst)
fpr.Unlock(V2);
}
void JitArm::fcmpo(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITFloatingPointOff)
u32 a = inst.FA, b = inst.FB;
int cr = inst.CRFD;
ARMReg vA = fpr.R0(a);
ARMReg vB = fpr.R0(b);
ARMReg fpscrReg = gpr.GetReg();
ARMReg crReg = gpr.GetReg();
Operand2 FPRFMask(0x1F, 0xA); // 0x1F000
Operand2 LessThan(0x8, 0xA); // 0x8000
Operand2 GreaterThan(0x4, 0xA); // 0x4000
Operand2 EqualTo(0x2, 0xA); // 0x2000
Operand2 NANRes(0x1, 0xA); // 0x1000
FixupBranch Done1, Done2, Done3;
LDR(fpscrReg, R9, PPCSTATE_OFF(fpscr));
BIC(fpscrReg, fpscrReg, FPRFMask);
VCMPE(vA, vB);
VMRS(_PC);
SetCC(CC_LT);
ORR(fpscrReg, fpscrReg, LessThan);
MOV(crReg, 8);
Done1 = B();
SetCC(CC_GT);
ORR(fpscrReg, fpscrReg, GreaterThan);
MOV(crReg, 4);
Done2 = B();
SetCC(CC_EQ);
ORR(fpscrReg, fpscrReg, EqualTo);
MOV(crReg, 2);
Done3 = B();
SetCC();
ORR(fpscrReg, fpscrReg, NANRes);
MOV(crReg, 1);
VCMPE(vA, vA);
VMRS(_PC);
FixupBranch NanA = B_CC(CC_NEQ);
VCMPE(vB, vB);
VMRS(_PC);
FixupBranch NanB = B_CC(CC_NEQ);
SetFPException(fpscrReg, FPSCR_VXVC);
FixupBranch Done4 = B();
SetJumpTarget(NanA);
SetJumpTarget(NanB);
SetFPException(fpscrReg, FPSCR_VXSNAN);
TST(fpscrReg, VEMask);
FixupBranch noVXVC = B_CC(CC_NEQ);
SetFPException(fpscrReg, FPSCR_VXVC);
SetJumpTarget(noVXVC);
SetJumpTarget(Done1);
SetJumpTarget(Done2);
SetJumpTarget(Done3);
SetJumpTarget(Done4);
STRB(crReg, R9, PPCSTATE_OFF(cr_fast) + cr);
STR(fpscrReg, R9, PPCSTATE_OFF(fpscr));
gpr.Unlock(fpscrReg, crReg);
}
void JitArm::fcmpu(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITFloatingPointOff)
u32 a = inst.FA, b = inst.FB;
int cr = inst.CRFD;
ARMReg vA = fpr.R0(a);
ARMReg vB = fpr.R0(b);
ARMReg fpscrReg = gpr.GetReg();
ARMReg crReg = gpr.GetReg();
Operand2 FPRFMask(0x1F, 0xA); // 0x1F000
Operand2 LessThan(0x8, 0xA); // 0x8000
Operand2 GreaterThan(0x4, 0xA); // 0x4000
Operand2 EqualTo(0x2, 0xA); // 0x2000
Operand2 NANRes(0x1, 0xA); // 0x1000
FixupBranch Done1, Done2, Done3;
LDR(fpscrReg, R9, PPCSTATE_OFF(fpscr));
BIC(fpscrReg, fpscrReg, FPRFMask);
VCMPE(vA, vB);
VMRS(_PC);
SetCC(CC_LT);
ORR(fpscrReg, fpscrReg, LessThan);
MOV(crReg, 8);
Done1 = B();
SetCC(CC_GT);
ORR(fpscrReg, fpscrReg, GreaterThan);
MOV(crReg, 4);
Done2 = B();
SetCC(CC_EQ);
ORR(fpscrReg, fpscrReg, EqualTo);
MOV(crReg, 2);
Done3 = B();
SetCC();
ORR(fpscrReg, fpscrReg, NANRes);
MOV(crReg, 1);
VCMPE(vA, vA);
VMRS(_PC);
FixupBranch NanA = B_CC(CC_NEQ);
VCMPE(vB, vB);
VMRS(_PC);
FixupBranch NanB = B_CC(CC_NEQ);
FixupBranch Done4 = B();
SetJumpTarget(NanA);
SetJumpTarget(NanB);
SetFPException(fpscrReg, FPSCR_VXSNAN);
SetJumpTarget(Done1);
SetJumpTarget(Done2);
SetJumpTarget(Done3);
SetJumpTarget(Done4);
STRB(crReg, R9, PPCSTATE_OFF(cr_fast) + cr);
STR(fpscrReg, R9, PPCSTATE_OFF(fpscr));
gpr.Unlock(fpscrReg, crReg);
}
void JitArm::fabsx(UGeckoInstruction inst)
{
INSTRUCTION_START

View File

@ -347,8 +347,8 @@ static GekkoOPTemplate table59[] =
static GekkoOPTemplate table63[] =
{
{264, &JitArm::fabsx}, //"fabsx", OPTYPE_FPU, FL_RC_BIT_F}},
{32, &JitArm::Default}, //"fcmpo", OPTYPE_FPU, FL_RC_BIT_F}},
{0, &JitArm::Default}, //"fcmpu", OPTYPE_FPU, FL_RC_BIT_F}},
{32, &JitArm::fcmpo}, //"fcmpo", OPTYPE_FPU, FL_RC_BIT_F}},
{0, &JitArm::fcmpu}, //"fcmpu", OPTYPE_FPU, FL_RC_BIT_F}},
{14, &JitArm::Default}, //"fctiwx", OPTYPE_FPU, FL_RC_BIT_F}},
{15, &JitArm::fctiwzx}, //"fctiwzx", OPTYPE_FPU, FL_RC_BIT_F}},
{72, &JitArm::fmrx}, //"fmrx", OPTYPE_FPU, FL_RC_BIT_F}},