mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-26 01:40:24 +00:00
Merge pull request #6470 from unknownbrackets/armjit-minor
Use the ARM rounding mode flag for conversions
This commit is contained in:
commit
7c54a3e8b6
@ -821,6 +821,14 @@ public:
|
|||||||
MOVI2R(reg, (u32)(intptr_t)(void *)val);
|
MOVI2R(reg, (u32)(intptr_t)(void *)val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MOVIU2F(ARMReg dest, u32 val, ARMReg tempReg, bool negate = false) {
|
||||||
|
union {
|
||||||
|
u32 u;
|
||||||
|
float f;
|
||||||
|
} v = {val};
|
||||||
|
MOVI2F(dest, v.f, tempReg, negate);
|
||||||
|
}
|
||||||
|
|
||||||
void ADDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
|
void ADDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
|
||||||
bool TryADDI2R(ARMReg rd, ARMReg rs, u32 val);
|
bool TryADDI2R(ARMReg rd, ARMReg rs, u32 val);
|
||||||
void SUBI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
|
void SUBI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
|
||||||
|
@ -284,38 +284,45 @@ void Jit::Comp_FPU2op(MIPSOpcode op) {
|
|||||||
break;
|
break;
|
||||||
case 13: //FsI(fd) = Rto0(F(fs))); break; //trunc.w.s
|
case 13: //FsI(fd) = Rto0(F(fs))); break; //trunc.w.s
|
||||||
fpr.MapDirtyIn(fd, fs);
|
fpr.MapDirtyIn(fd, fs);
|
||||||
|
VCMP(fpr.R(fs), fpr.R(fs));
|
||||||
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED | ROUND_TO_ZERO);
|
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED | ROUND_TO_ZERO);
|
||||||
|
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
|
||||||
|
SetCC(CC_VS);
|
||||||
|
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
|
||||||
|
SetCC(CC_AL);
|
||||||
break;
|
break;
|
||||||
case 14: //FsI(fd) = (int)ceilf (F(fs)); break; //ceil.w.s
|
case 14: //FsI(fd) = (int)ceilf (F(fs)); break; //ceil.w.s
|
||||||
{
|
{
|
||||||
fpr.MapDirtyIn(fd, fs);
|
fpr.MapDirtyIn(fd, fs);
|
||||||
VCVT(S0, fpr.R(fs), TO_INT | IS_SIGNED | ROUND_TO_ZERO);
|
VMRS(SCRATCHREG2);
|
||||||
VCVT(S1, S0, TO_FLOAT | IS_SIGNED);
|
// Assume we're always in round-to-zero mode.
|
||||||
// For a positive value, we may have gotten a smaller value, in which case we need to increment.
|
ORR(SCRATCHREG1, SCRATCHREG2, AssumeMakeOperand2(1 << 22));
|
||||||
VCMP(S1, fpr.R(fs));
|
VMSR(SCRATCHREG1);
|
||||||
VMOV(fpr.R(fd), S0);
|
VCMP(fpr.R(fs), fpr.R(fs));
|
||||||
|
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED);
|
||||||
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
|
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
|
||||||
FixupBranch skip = B_CC(CC_GE);
|
SetCC(CC_VS);
|
||||||
MOVI2F(S0, 1.0f, SCRATCHREG1);
|
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
|
||||||
VADD(S1, S1, S0);
|
SetCC(CC_AL);
|
||||||
VCVT(fpr.R(fd), S1, TO_INT | IS_SIGNED | ROUND_TO_ZERO);
|
// Set the rounding mode back. TODO: Keep it? Dirty?
|
||||||
SetJumpTarget(skip);
|
VMSR(SCRATCHREG2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 15: //FsI(fd) = (int)floorf(F(fs)); break; //floor.w.s
|
case 15: //FsI(fd) = (int)floorf(F(fs)); break; //floor.w.s
|
||||||
{
|
{
|
||||||
fpr.MapDirtyIn(fd, fs);
|
fpr.MapDirtyIn(fd, fs);
|
||||||
VCVT(S0, fpr.R(fs), TO_INT | IS_SIGNED | ROUND_TO_ZERO);
|
VMRS(SCRATCHREG2);
|
||||||
VCVT(S1, S0, TO_FLOAT | IS_SIGNED);
|
// Assume we're always in round-to-zero mode.
|
||||||
// For a negative value, we may have gotten a larger value, in which case we need to decrement.
|
ORR(SCRATCHREG1, SCRATCHREG2, AssumeMakeOperand2(2 << 22));
|
||||||
VCMP(S1, fpr.R(fs));
|
VMSR(SCRATCHREG1);
|
||||||
VMOV(fpr.R(fd), S0);
|
VCMP(fpr.R(fs), fpr.R(fs));
|
||||||
|
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED);
|
||||||
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
|
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
|
||||||
FixupBranch skip = B_CC(CC_LS);
|
SetCC(CC_VS);
|
||||||
MOVI2F(S0, 1.0f, SCRATCHREG1);
|
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
|
||||||
VSUB(S1, S1, S0);
|
SetCC(CC_AL);
|
||||||
VCVT(fpr.R(fd), S1, TO_INT | IS_SIGNED | ROUND_TO_ZERO);
|
// Set the rounding mode back. TODO: Keep it? Dirty?
|
||||||
SetJumpTarget(skip);
|
VMSR(SCRATCHREG2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 32: //F(fd) = (float)FsI(fs); break; //cvt.s.w
|
case 32: //F(fd) = (float)FsI(fs); break; //cvt.s.w
|
||||||
@ -323,61 +330,32 @@ void Jit::Comp_FPU2op(MIPSOpcode op) {
|
|||||||
VCVT(fpr.R(fd), fpr.R(fs), TO_FLOAT | IS_SIGNED);
|
VCVT(fpr.R(fd), fpr.R(fs), TO_FLOAT | IS_SIGNED);
|
||||||
break;
|
break;
|
||||||
case 36: //FsI(fd) = (int) F(fs); break; //cvt.w.s
|
case 36: //FsI(fd) = (int) F(fs); break; //cvt.w.s
|
||||||
{
|
|
||||||
// TODO: This is a monster. Try setting the ARM rounding mode instead?
|
|
||||||
fpr.MapDirtyIn(fd, fs);
|
fpr.MapDirtyIn(fd, fs);
|
||||||
LDR(SCRATCHREG1, CTXREG, offsetof(MIPSState, fcr31));
|
LDR(SCRATCHREG1, CTXREG, offsetof(MIPSState, fcr31));
|
||||||
AND(SCRATCHREG1, SCRATCHREG1, Operand2(3));
|
AND(SCRATCHREG1, SCRATCHREG1, Operand2(3));
|
||||||
// MIPS Rounding Mode:
|
// MIPS Rounding Mode: ARM Rounding Mode
|
||||||
// 0: Round nearest
|
// 0: Round nearest 0
|
||||||
// 1: Round to zero
|
// 1: Round to zero 3
|
||||||
// 2: Round up (ceil)
|
// 2: Round up (ceil) 1
|
||||||
// 3: Round down (floor)
|
// 3: Round down (floor) 2
|
||||||
CMP(SCRATCHREG1, Operand2(1));
|
CMP(SCRATCHREG1, Operand2(1));
|
||||||
// Let's hope 0/1 are the most common. Seems likely.
|
SetCC(CC_EQ); ADD(SCRATCHREG1, SCRATCHREG1, Operand2(2));
|
||||||
FixupBranch skipCeilFloor = B_CC(CC_LE);
|
SetCC(CC_GT); SUB(SCRATCHREG1, SCRATCHREG1, Operand2(1));
|
||||||
|
|
||||||
// Okay, here we are in ceil or floor mode only.
|
|
||||||
VCVT(S0, fpr.R(fs), TO_INT | IS_SIGNED | ROUND_TO_ZERO);
|
|
||||||
VCVT(S1, S0, TO_FLOAT | IS_SIGNED);
|
|
||||||
// Compare now, we'll VMRS_APSR a bit later for the ceil/floor case.
|
|
||||||
VCMP(S1, fpr.R(fs));
|
|
||||||
VMOV(fpr.R(fd), S0);
|
|
||||||
|
|
||||||
CMP(SCRATCHREG1, Operand2(2));
|
|
||||||
FixupBranch useFloor = B_CC(CC_GT);
|
|
||||||
|
|
||||||
// This is the ceil case specifically. We add one if we ended up lower.
|
|
||||||
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
|
|
||||||
FixupBranch finishCeil1 = B_CC(CC_GE);
|
|
||||||
MOVI2F(S0, 1.0f, SCRATCHREG1);
|
|
||||||
VADD(S1, S1, S0);
|
|
||||||
VCVT(fpr.R(fd), S1, TO_INT | IS_SIGNED | ROUND_TO_ZERO);
|
|
||||||
FixupBranch finishCeil2 = B();
|
|
||||||
|
|
||||||
// For floor, we subtract one if we ended up higher.
|
|
||||||
SetJumpTarget(useFloor);
|
|
||||||
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
|
|
||||||
FixupBranch finishFloor1 = B_CC(CC_LS);
|
|
||||||
MOVI2F(S0, 1.0f, SCRATCHREG1);
|
|
||||||
VSUB(S1, S1, S0);
|
|
||||||
VCVT(fpr.R(fd), S1, TO_INT | IS_SIGNED | ROUND_TO_ZERO);
|
|
||||||
FixupBranch finishFloor2 = B();
|
|
||||||
|
|
||||||
SetJumpTarget(skipCeilFloor);
|
|
||||||
// LT 1 means 0, nearest. EQ means 1, round to zero.
|
|
||||||
SetCC(CC_LT);
|
|
||||||
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED);
|
|
||||||
SetCC(CC_EQ);
|
|
||||||
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED | ROUND_TO_ZERO);
|
|
||||||
SetCC(CC_AL);
|
SetCC(CC_AL);
|
||||||
|
|
||||||
SetJumpTarget(finishCeil1);
|
VMRS(SCRATCHREG2);
|
||||||
SetJumpTarget(finishCeil2);
|
// Assume we're always in round-to-zero mode beforehand.
|
||||||
SetJumpTarget(finishFloor1);
|
ORR(SCRATCHREG1, SCRATCHREG2, Operand2(SCRATCHREG1, ST_LSL, 22));
|
||||||
SetJumpTarget(finishFloor2);
|
VMSR(SCRATCHREG1);
|
||||||
|
VCMP(fpr.R(fs), fpr.R(fs));
|
||||||
|
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED);
|
||||||
|
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
|
||||||
|
SetCC(CC_VS);
|
||||||
|
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
|
||||||
|
SetCC(CC_AL);
|
||||||
|
// Set the rounding mode back. TODO: Keep it? Dirty?
|
||||||
|
VMSR(SCRATCHREG2);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
DISABLE;
|
DISABLE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user