mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #4518 from hrydgard/fpcond
ARMJIT: Cache fpcond in a register to avoid store/load between compare and branch
This commit is contained in:
commit
f4b5e8a4c1
5 changed files with 26 additions and 29 deletions
|
@ -287,8 +287,8 @@ void Jit::BranchFPFlag(MIPSOpcode op, ArmGen::CCFlags cc, bool likely)
|
|||
if (!likely && delaySlotIsNice)
|
||||
CompileDelaySlot(DELAYSLOT_NICE);
|
||||
|
||||
LDR(R0, CTXREG, offsetof(MIPSState, fpcond));
|
||||
TST(R0, Operand2(1, TYPE_IMM));
|
||||
gpr.MapReg(MIPS_REG_FPCOND, 0);
|
||||
TST(gpr.R(MIPS_REG_FPCOND), Operand2(1, TYPE_IMM));
|
||||
|
||||
ArmGen::FixupBranch ptr;
|
||||
if (!likely)
|
||||
|
|
|
@ -192,13 +192,13 @@ void Jit::Comp_FPUComp(MIPSOpcode op) {
|
|||
int opc = op & 0xF;
|
||||
if (opc >= 8) opc -= 8; // alias
|
||||
if (opc == 0) { // f, sf (signalling false)
|
||||
MOVI2R(R0, 0);
|
||||
STR(R0, CTXREG, offsetof(MIPSState, fpcond));
|
||||
gpr.SetImm(MIPS_REG_FPCOND, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
int fs = _FS;
|
||||
int ft = _FT;
|
||||
gpr.MapReg(MIPS_REG_FPCOND, MAP_DIRTY | MAP_NOINIT);
|
||||
fpr.MapInIn(fs, ft);
|
||||
VCMP(fpr.R(fs), fpr.R(ft));
|
||||
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
|
||||
|
@ -206,62 +206,58 @@ void Jit::Comp_FPUComp(MIPSOpcode op) {
|
|||
{
|
||||
case 1: // un, ngle (unordered)
|
||||
SetCC(CC_VS);
|
||||
MOVI2R(R0, 1);
|
||||
MOVI2R(gpr.R(MIPS_REG_FPCOND), 1);
|
||||
SetCC(CC_VC);
|
||||
break;
|
||||
case 2: // eq, seq (equal, ordered)
|
||||
SetCC(CC_EQ);
|
||||
MOVI2R(R0, 1);
|
||||
MOVI2R(gpr.R(MIPS_REG_FPCOND), 1);
|
||||
SetCC(CC_NEQ);
|
||||
break;
|
||||
case 3: // ueq, ngl (equal, unordered)
|
||||
SetCC(CC_EQ);
|
||||
MOVI2R(R0, 1);
|
||||
MOVI2R(gpr.R(MIPS_REG_FPCOND), 1);
|
||||
SetCC(CC_NEQ);
|
||||
MOVI2R(R0, 0);
|
||||
MOVI2R(gpr.R(MIPS_REG_FPCOND), 0);
|
||||
SetCC(CC_VS);
|
||||
MOVI2R(R0, 1);
|
||||
MOVI2R(gpr.R(MIPS_REG_FPCOND), 1);
|
||||
SetCC(CC_AL);
|
||||
STR(R0, CTXREG, offsetof(MIPSState, fpcond));
|
||||
return;
|
||||
case 4: // olt, lt (less than, ordered)
|
||||
SetCC(CC_LO);
|
||||
MOVI2R(R0, 1);
|
||||
MOVI2R(gpr.R(MIPS_REG_FPCOND), 1);
|
||||
SetCC(CC_HS);
|
||||
break;
|
||||
case 5: // ult, nge (less than, unordered)
|
||||
SetCC(CC_LT);
|
||||
MOVI2R(R0, 1);
|
||||
MOVI2R(gpr.R(MIPS_REG_FPCOND), 1);
|
||||
SetCC(CC_GE);
|
||||
break;
|
||||
case 6: // ole, le (less equal, ordered)
|
||||
SetCC(CC_LS);
|
||||
MOVI2R(R0, 1);
|
||||
MOVI2R(gpr.R(MIPS_REG_FPCOND), 1);
|
||||
SetCC(CC_HI);
|
||||
break;
|
||||
case 7: // ule, ngt (less equal, unordered)
|
||||
SetCC(CC_LE);
|
||||
MOVI2R(R0, 1);
|
||||
MOVI2R(gpr.R(MIPS_REG_FPCOND), 1);
|
||||
SetCC(CC_GT);
|
||||
break;
|
||||
default:
|
||||
Comp_Generic(op);
|
||||
return;
|
||||
}
|
||||
MOVI2R(R0, 0);
|
||||
MOVI2R(gpr.R(MIPS_REG_FPCOND), 0);
|
||||
SetCC(CC_AL);
|
||||
STR(R0, CTXREG, offsetof(MIPSState, fpcond));
|
||||
}
|
||||
|
||||
void Jit::Comp_FPU2op(MIPSOpcode op)
|
||||
{
|
||||
void Jit::Comp_FPU2op(MIPSOpcode op) {
|
||||
CONDITIONAL_DISABLE;
|
||||
|
||||
int fs = _FS;
|
||||
int fd = _FD;
|
||||
|
||||
switch (op & 0x3f)
|
||||
{
|
||||
switch (op & 0x3f) {
|
||||
case 4: //F(fd) = sqrtf(F(fs)); break; //sqrt
|
||||
fpr.MapDirtyIn(fd, fs);
|
||||
VSQRT(fpr.R(fd), fpr.R(fs));
|
||||
|
@ -345,13 +341,12 @@ void Jit::Comp_mxc1(MIPSOpcode op)
|
|||
case 2: //cfc1
|
||||
if (fs == 31)
|
||||
{
|
||||
gpr.MapReg(rt, MAP_DIRTY | MAP_NOINIT);
|
||||
LDR(R0, CTXREG, offsetof(MIPSState, fpcond));
|
||||
gpr.MapDirtyIn(rt, MIPS_REG_FPCOND);
|
||||
LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31));
|
||||
if (cpu_info.bArmV7) {
|
||||
BFI(gpr.R(rt), R0, 23, 1);
|
||||
BFI(gpr.R(rt), gpr.R(MIPS_REG_FPCOND), 23, 1);
|
||||
} else {
|
||||
AND(R0, R0, Operand2(1)); // Just in case
|
||||
AND(R0, gpr.R(MIPS_REG_FPCOND), Operand2(1)); // Just in case
|
||||
ANDI2R(gpr.R(rt), gpr.R(rt), ~(0x1 << 23), R1); // R1 won't be used, this turns into a simple BIC.
|
||||
ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, 23));
|
||||
}
|
||||
|
@ -372,7 +367,7 @@ void Jit::Comp_mxc1(MIPSOpcode op)
|
|||
case 6: //ctc1
|
||||
if (fs == 31)
|
||||
{
|
||||
gpr.MapReg(rt, 0);
|
||||
gpr.MapDirtyIn(MIPS_REG_FPCOND, rt);
|
||||
// Hardware rounding method.
|
||||
// Left here in case it is faster than conditional method.
|
||||
/*
|
||||
|
@ -393,12 +388,11 @@ void Jit::Comp_mxc1(MIPSOpcode op)
|
|||
// Update MIPS state
|
||||
STR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31));
|
||||
if (cpu_info.bArmV7) {
|
||||
UBFX(R0, gpr.R(rt), 23, 1);
|
||||
UBFX(gpr.R(MIPS_REG_FPCOND), gpr.R(rt), 23, 1);
|
||||
} else {
|
||||
MOV(R0, Operand2(gpr.R(rt), ST_LSR, 23));
|
||||
AND(R0, R0, Operand2(1));
|
||||
AND(gpr.R(MIPS_REG_FPCOND), R0, Operand2(1));
|
||||
}
|
||||
STR(R0, CTXREG, offsetof(MIPSState, fpcond));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -569,6 +569,8 @@ int ArmRegCache::GetMipsRegOffset(MIPSGPReg r) {
|
|||
return offsetof(MIPSState, hi);
|
||||
case MIPS_REG_LO:
|
||||
return offsetof(MIPSState, lo);
|
||||
case MIPS_REG_FPCOND:
|
||||
return offsetof(MIPSState, fpcond);
|
||||
default:
|
||||
ERROR_LOG_REPORT(JIT, "bad mips register %i", r);
|
||||
return 0; // or what?
|
||||
|
|
|
@ -31,7 +31,7 @@ using namespace ArmGen;
|
|||
// R11 = base pointer
|
||||
|
||||
enum {
|
||||
TOTAL_MAPPABLE_MIPSREGS = 34,
|
||||
TOTAL_MAPPABLE_MIPSREGS = 35,
|
||||
};
|
||||
|
||||
typedef int MIPSReg;
|
||||
|
|
|
@ -68,6 +68,7 @@ enum MIPSGPReg
|
|||
// Not real regs, just for convenience/jit mapping.
|
||||
MIPS_REG_HI = 32,
|
||||
MIPS_REG_LO = 33,
|
||||
MIPS_REG_FPCOND = 34,
|
||||
};
|
||||
|
||||
enum
|
||||
|
|
Loading…
Add table
Reference in a new issue