mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
x86jit: Cache fpcond in a register.
Mostly to match armjit.
This commit is contained in:
parent
d2f43889a0
commit
acad2e1763
5 changed files with 103 additions and 21 deletions
|
@ -341,15 +341,25 @@ void Jit::Comp_mxc1(MIPSOpcode op)
|
||||||
|
|
||||||
case 2: //cfc1
|
case 2: //cfc1
|
||||||
if (fs == 31) {
|
if (fs == 31) {
|
||||||
gpr.MapDirtyIn(rt, MIPS_REG_FPCOND);
|
if (gpr.IsImm(MIPS_REG_FPCOND)) {
|
||||||
LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31));
|
gpr.MapReg(rt, MAP_DIRTY | MAP_NOINIT);
|
||||||
|
LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31));
|
||||||
|
if (gpr.GetImm(MIPS_REG_FPCOND) & 1) {
|
||||||
|
ORI2R(gpr.R(rt), gpr.R(rt), 0x1 << 23, SCRATCHREG2);
|
||||||
|
} else {
|
||||||
|
ANDI2R(gpr.R(rt), gpr.R(rt), ~(0x1 << 23), SCRATCHREG2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gpr.MapDirtyIn(rt, MIPS_REG_FPCOND);
|
||||||
|
LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31));
|
||||||
#ifdef HAVE_ARMV7
|
#ifdef HAVE_ARMV7
|
||||||
BFI(gpr.R(rt), gpr.R(MIPS_REG_FPCOND), 23, 1);
|
BFI(gpr.R(rt), gpr.R(MIPS_REG_FPCOND), 23, 1);
|
||||||
#else
|
#else
|
||||||
AND(SCRATCHREG1, gpr.R(MIPS_REG_FPCOND), Operand2(1)); // Just in case
|
AND(SCRATCHREG1, gpr.R(MIPS_REG_FPCOND), Operand2(1)); // Just in case
|
||||||
ANDI2R(gpr.R(rt), gpr.R(rt), ~(0x1 << 23), SCRATCHREG2); // SCRATCHREG2 won't be used, this turns into a simple BIC.
|
ANDI2R(gpr.R(rt), gpr.R(rt), ~(0x1 << 23), SCRATCHREG2); // SCRATCHREG2 won't be used, this turns into a simple BIC.
|
||||||
ORR(gpr.R(rt), gpr.R(rt), Operand2(SCRATCHREG1, ST_LSL, 23));
|
ORR(gpr.R(rt), gpr.R(rt), Operand2(SCRATCHREG1, ST_LSL, 23));
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
} else if (fs == 0) {
|
} else if (fs == 0) {
|
||||||
gpr.SetImm(rt, MIPSState::FCR0_VALUE);
|
gpr.SetImm(rt, MIPSState::FCR0_VALUE);
|
||||||
} else {
|
} else {
|
||||||
|
@ -365,9 +375,14 @@ void Jit::Comp_mxc1(MIPSOpcode op)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 6: //ctc1
|
case 6: //ctc1
|
||||||
if (fs == 31)
|
if (fs == 31) {
|
||||||
{
|
bool wasImm = gpr.IsImm(rt);
|
||||||
gpr.MapDirtyIn(MIPS_REG_FPCOND, rt);
|
if (wasImm) {
|
||||||
|
gpr.SetImm(MIPS_REG_FPCOND, (gpr.GetImm(rt) >> 23) & 1);
|
||||||
|
gpr.MapReg(rt);
|
||||||
|
} else {
|
||||||
|
gpr.MapDirtyIn(MIPS_REG_FPCOND, rt);
|
||||||
|
}
|
||||||
// Hardware rounding method.
|
// Hardware rounding method.
|
||||||
// Left here in case it is faster than conditional method.
|
// Left here in case it is faster than conditional method.
|
||||||
/*
|
/*
|
||||||
|
@ -388,12 +403,16 @@ void Jit::Comp_mxc1(MIPSOpcode op)
|
||||||
// Update MIPS state
|
// Update MIPS state
|
||||||
// TODO: Technically, should mask by 0x0181FFFF. Maybe just put all of FCR31 in the reg?
|
// TODO: Technically, should mask by 0x0181FFFF. Maybe just put all of FCR31 in the reg?
|
||||||
STR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31));
|
STR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31));
|
||||||
|
if (!wasImm) {
|
||||||
#ifdef HAVE_ARMV7
|
#ifdef HAVE_ARMV7
|
||||||
UBFX(gpr.R(MIPS_REG_FPCOND), gpr.R(rt), 23, 1);
|
UBFX(gpr.R(MIPS_REG_FPCOND), gpr.R(rt), 23, 1);
|
||||||
#else
|
#else
|
||||||
MOV(SCRATCHREG1, Operand2(gpr.R(rt), ST_LSR, 23));
|
MOV(SCRATCHREG1, Operand2(gpr.R(rt), ST_LSR, 23));
|
||||||
AND(gpr.R(MIPS_REG_FPCOND), SCRATCHREG1, Operand2(1));
|
AND(gpr.R(MIPS_REG_FPCOND), SCRATCHREG1, Operand2(1));
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Comp_Generic(op);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,7 +446,8 @@ void Jit::BranchFPFlag(MIPSOpcode op, Gen::CCFlags cc, bool likely)
|
||||||
if (!likely && delaySlotIsNice)
|
if (!likely && delaySlotIsNice)
|
||||||
CompileDelaySlot(DELAYSLOT_NICE);
|
CompileDelaySlot(DELAYSLOT_NICE);
|
||||||
|
|
||||||
TEST(32, M(&(mips_->fpcond)), Imm32(1));
|
gpr.KillImmediate(MIPS_REG_FPCOND, true, false);
|
||||||
|
TEST(32, gpr.R(MIPS_REG_FPCOND), Imm32(1));
|
||||||
|
|
||||||
CompBranchExits(cc, targetAddr, js.compilerPC + 8, delaySlotIsNice, likely, false);
|
CompBranchExits(cc, targetAddr, js.compilerPC + 8, delaySlotIsNice, likely, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,9 +154,10 @@ static const u64 MEMORY_ALIGNED16(ssNoSignMask[2]) = {0x7FFFFFFF7FFFFFFFULL, 0x7
|
||||||
|
|
||||||
void Jit::CompFPComp(int lhs, int rhs, u8 compare, bool allowNaN)
|
void Jit::CompFPComp(int lhs, int rhs, u8 compare, bool allowNaN)
|
||||||
{
|
{
|
||||||
|
gpr.MapReg(MIPS_REG_FPCOND, false, true);
|
||||||
MOVSS(XMM0, fpr.R(lhs));
|
MOVSS(XMM0, fpr.R(lhs));
|
||||||
CMPSS(XMM0, fpr.R(rhs), compare);
|
CMPSS(XMM0, fpr.R(rhs), compare);
|
||||||
MOVSS(M(¤tMIPS->fpcond), XMM0);
|
MOVD_xmm(gpr.R(MIPS_REG_FPCOND), XMM0);
|
||||||
|
|
||||||
// This means that NaN also means true, e.g. !<> or !>, etc.
|
// This means that NaN also means true, e.g. !<> or !>, etc.
|
||||||
if (allowNaN)
|
if (allowNaN)
|
||||||
|
@ -165,7 +166,7 @@ void Jit::CompFPComp(int lhs, int rhs, u8 compare, bool allowNaN)
|
||||||
CMPUNORDSS(XMM0, fpr.R(rhs));
|
CMPUNORDSS(XMM0, fpr.R(rhs));
|
||||||
|
|
||||||
MOVD_xmm(R(EAX), XMM0);
|
MOVD_xmm(R(EAX), XMM0);
|
||||||
OR(32, M(¤tMIPS->fpcond), R(EAX));
|
OR(32, gpr.R(MIPS_REG_FPCOND), R(EAX));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +181,7 @@ void Jit::Comp_FPUComp(MIPSOpcode op)
|
||||||
{
|
{
|
||||||
case 0: //f
|
case 0: //f
|
||||||
case 8: //sf
|
case 8: //sf
|
||||||
MOV(32, M(¤tMIPS->fpcond), Imm32(0));
|
gpr.SetImm(MIPS_REG_FPCOND, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: //un
|
case 1: //un
|
||||||
|
@ -319,7 +320,33 @@ void Jit::Comp_mxc1(MIPSOpcode op)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // R(rt) = currentMIPS->ReadFCR(fs); break; //cfc1
|
case 2: // R(rt) = currentMIPS->ReadFCR(fs); break; //cfc1
|
||||||
Comp_Generic(op);
|
if (fs == 31) {
|
||||||
|
bool wasImm = gpr.IsImm(MIPS_REG_FPCOND);
|
||||||
|
if (!wasImm) {
|
||||||
|
gpr.Lock(rt, MIPS_REG_FPCOND);
|
||||||
|
gpr.MapReg(MIPS_REG_FPCOND, true, false);
|
||||||
|
}
|
||||||
|
gpr.MapReg(rt, false, true);
|
||||||
|
MOV(32, gpr.R(rt), M(&mips_->fcr31));
|
||||||
|
if (wasImm) {
|
||||||
|
if (gpr.GetImm(MIPS_REG_FPCOND) & 1) {
|
||||||
|
OR(32, gpr.R(rt), Imm32(1 << 23));
|
||||||
|
} else {
|
||||||
|
AND(32, gpr.R(rt), Imm32(~(1 << 23)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AND(32, gpr.R(rt), Imm32(~(1 << 23)));
|
||||||
|
MOV(32, R(EAX), gpr.R(MIPS_REG_FPCOND));
|
||||||
|
AND(32, R(EAX), Imm32(1));
|
||||||
|
SHL(32, R(EAX), Imm8(23));
|
||||||
|
OR(32, gpr.R(rt), R(EAX));
|
||||||
|
}
|
||||||
|
gpr.UnlockAll();
|
||||||
|
} else if (fs == 0) {
|
||||||
|
gpr.SetImm(rt, MIPSState::FCR0_VALUE);
|
||||||
|
} else {
|
||||||
|
Comp_Generic(op);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 4: //FI(fs) = R(rt); break; //mtc1
|
case 4: //FI(fs) = R(rt); break; //mtc1
|
||||||
|
@ -329,7 +356,24 @@ void Jit::Comp_mxc1(MIPSOpcode op)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 6: //currentMIPS->WriteFCR(fs, R(rt)); break; //ctc1
|
case 6: //currentMIPS->WriteFCR(fs, R(rt)); break; //ctc1
|
||||||
Comp_Generic(op);
|
if (fs == 31) {
|
||||||
|
if (gpr.IsImm(rt)) {
|
||||||
|
gpr.SetImm(MIPS_REG_FPCOND, (gpr.GetImm(rt) >> 23) & 1);
|
||||||
|
MOV(32, M(&mips_->fcr31), Imm32(gpr.GetImm(rt) & 0x0181FFFF));
|
||||||
|
} else {
|
||||||
|
gpr.Lock(rt, MIPS_REG_FPCOND);
|
||||||
|
gpr.MapReg(rt, true, false);
|
||||||
|
gpr.MapReg(MIPS_REG_FPCOND, false, true);
|
||||||
|
MOV(32, gpr.R(MIPS_REG_FPCOND), gpr.R(rt));
|
||||||
|
SHR(32, gpr.R(MIPS_REG_FPCOND), Imm8(23));
|
||||||
|
AND(32, gpr.R(MIPS_REG_FPCOND), Imm32(1));
|
||||||
|
MOV(32, M(&mips_->fcr31), gpr.R(rt));
|
||||||
|
AND(32, M(&mips_->fcr31), Imm32(0x0181FFFF));
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Comp_Generic(op);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "Core/Reporting.h"
|
||||||
#include "Core/MIPS/MIPS.h"
|
#include "Core/MIPS/MIPS.h"
|
||||||
#include "Core/MIPS/MIPSTables.h"
|
#include "Core/MIPS/MIPSTables.h"
|
||||||
#include "Core/MIPS/MIPSAnalyst.h"
|
#include "Core/MIPS/MIPSAnalyst.h"
|
||||||
|
@ -60,10 +61,13 @@ void GPRRegCache::Start(MIPSState *mips, MIPSAnalyst::AnalysisResults &stats) {
|
||||||
}
|
}
|
||||||
memset(regs, 0, sizeof(regs));
|
memset(regs, 0, sizeof(regs));
|
||||||
OpArg base = GetDefaultLocation(MIPS_REG_ZERO);
|
OpArg base = GetDefaultLocation(MIPS_REG_ZERO);
|
||||||
for (int i = 0; i < NUM_MIPS_GPRS; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
regs[i].location = base;
|
regs[i].location = base;
|
||||||
base.IncreaseOffset(sizeof(u32));
|
base.IncreaseOffset(sizeof(u32));
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < NUM_MIPS_GPRS; i++) {
|
||||||
|
regs[i].location = GetDefaultLocation(MIPSGPReg(i));
|
||||||
|
}
|
||||||
|
|
||||||
// todo: sort to find the most popular regs
|
// todo: sort to find the most popular regs
|
||||||
/*
|
/*
|
||||||
|
@ -214,7 +218,21 @@ const int *GPRRegCache::GetAllocationOrder(int &count) {
|
||||||
|
|
||||||
|
|
||||||
OpArg GPRRegCache::GetDefaultLocation(MIPSGPReg reg) const {
|
OpArg GPRRegCache::GetDefaultLocation(MIPSGPReg reg) const {
|
||||||
return M(&mips->r[reg]);
|
if (reg < 32)
|
||||||
|
return M(&mips->r[reg]);
|
||||||
|
switch (reg) {
|
||||||
|
case MIPS_REG_HI:
|
||||||
|
return M(&mips->hi);
|
||||||
|
case MIPS_REG_LO:
|
||||||
|
return M(&mips->lo);
|
||||||
|
case MIPS_REG_FPCOND:
|
||||||
|
return M(&mips->fpcond);
|
||||||
|
case MIPS_REG_VFPUCC:
|
||||||
|
return M(&mips->vfpuCtrl[VFPU_CTRL_CC]);
|
||||||
|
default:
|
||||||
|
ERROR_LOG_REPORT(JIT, "bad mips register %i", reg);
|
||||||
|
return M(&mips->r[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ using namespace Gen;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: Add more cachable regs, like HI, LO
|
// TODO: Add more cachable regs, like HI, LO
|
||||||
#define NUM_MIPS_GPRS 32
|
#define NUM_MIPS_GPRS 36
|
||||||
|
|
||||||
struct MIPSCachedReg {
|
struct MIPSCachedReg {
|
||||||
OpArg location;
|
OpArg location;
|
||||||
|
|
Loading…
Add table
Reference in a new issue