mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
jit: Apply hasSetRounding at compile time.
Otherwise, the block will be executed with the wrong rounding mode the first time rounding is set. This could be important if it was set for a single operation. This is only a problem the first time it's set.
This commit is contained in:
parent
09e307b097
commit
ab809bd19e
13 changed files with 37 additions and 55 deletions
|
@ -123,20 +123,6 @@ void ArmJit::GenerateFixedCode() {
|
|||
POP(2, SCRATCHREG1, R_PC);
|
||||
}
|
||||
|
||||
// Must preserve SCRATCHREG1 (R0), destroys SCRATCHREG2 (LR)
|
||||
updateRoundingMode = AlignCode16(); {
|
||||
PUSH(2, SCRATCHREG1, R_LR);
|
||||
LDR(SCRATCHREG2, CTXREG, offsetof(MIPSState, fcr31));
|
||||
MOVI2R(SCRATCHREG1, 0x1000003);
|
||||
TST(SCRATCHREG2, SCRATCHREG1);
|
||||
FixupBranch skip = B_CC(CC_EQ); // zero
|
||||
MOVI2R(SCRATCHREG2, 1);
|
||||
MOVP2R(SCRATCHREG1, &js.hasSetRounding);
|
||||
STRB(SCRATCHREG2, SCRATCHREG1, 0);
|
||||
SetJumpTarget(skip);
|
||||
POP(2, SCRATCHREG1, R_PC);
|
||||
}
|
||||
|
||||
FlushLitPool();
|
||||
|
||||
enterDispatcher = AlignCode16();
|
||||
|
|
|
@ -416,8 +416,10 @@ void ArmJit::Comp_mxc1(MIPSOpcode op)
|
|||
// Must clear before setting, since ApplyRoundingMode() assumes it was cleared.
|
||||
RestoreRoundingMode();
|
||||
bool wasImm = gpr.IsImm(rt);
|
||||
u32 immVal = -1;
|
||||
if (wasImm) {
|
||||
gpr.SetImm(MIPS_REG_FPCOND, (gpr.GetImm(rt) >> 23) & 1);
|
||||
immVal = gpr.GetImm(rt);
|
||||
gpr.SetImm(MIPS_REG_FPCOND, (immVal >> 23) & 1);
|
||||
gpr.MapReg(rt);
|
||||
} else {
|
||||
gpr.MapDirtyIn(MIPS_REG_FPCOND, rt);
|
||||
|
@ -433,8 +435,10 @@ void ArmJit::Comp_mxc1(MIPSOpcode op)
|
|||
MOV(SCRATCHREG1, Operand2(gpr.R(rt), ST_LSR, 23));
|
||||
AND(gpr.R(MIPS_REG_FPCOND), SCRATCHREG1, Operand2(1));
|
||||
#endif
|
||||
UpdateRoundingMode();
|
||||
} else {
|
||||
UpdateRoundingMode(immVal);
|
||||
}
|
||||
UpdateRoundingMode();
|
||||
ApplyRoundingMode();
|
||||
} else {
|
||||
Comp_Generic(op);
|
||||
|
|
|
@ -640,8 +640,12 @@ void ArmJit::ApplyRoundingMode(bool force) {
|
|||
}
|
||||
|
||||
// Does (must!) not destroy R0 (SCRATCHREG1). Destroys R14 (SCRATCHREG2).
|
||||
void ArmJit::UpdateRoundingMode() {
|
||||
QuickCallFunction(R1, updateRoundingMode);
|
||||
void ArmJit::UpdateRoundingMode(u32 fcr31) {
|
||||
// We must set js.hasSetRounding at compile time, or this block will use the wrong rounding mode.
|
||||
// The fcr31 parameter is -1 when not known at compile time, so we just assume it was changed.
|
||||
if (fcr31 & 0x01000003) {
|
||||
js.hasSetRounding = true;
|
||||
}
|
||||
}
|
||||
|
||||
// IDEA - could have a WriteDualExit that takes two destinations and two condition flags,
|
||||
|
|
|
@ -203,7 +203,7 @@ private:
|
|||
void WriteDownCountR(ArmGen::ARMReg reg);
|
||||
void RestoreRoundingMode(bool force = false);
|
||||
void ApplyRoundingMode(bool force = false);
|
||||
void UpdateRoundingMode();
|
||||
void UpdateRoundingMode(u32 fcr31 = -1);
|
||||
void MovFromPC(ArmGen::ARMReg r);
|
||||
void MovToPC(ArmGen::ARMReg r);
|
||||
|
||||
|
@ -311,7 +311,6 @@ public:
|
|||
|
||||
const u8 *restoreRoundingMode;
|
||||
const u8 *applyRoundingMode;
|
||||
const u8 *updateRoundingMode;
|
||||
|
||||
const u8 *breakpointBailout;
|
||||
};
|
||||
|
|
|
@ -177,17 +177,6 @@ void Arm64Jit::GenerateFixedCode(const JitOptions &jo) {
|
|||
ADDI2R(SCRATCH2, SCRATCH2, 4);
|
||||
SetJumpTarget(skip);
|
||||
|
||||
// We need both SCRATCH1 and SCRATCH2 for updating hasSetRounding.
|
||||
PUSH(SCRATCH2);
|
||||
// We can only skip if the rounding mode is zero and flush is not set.
|
||||
CMPI2R(SCRATCH2, 0);
|
||||
FixupBranch skip2 = B(CC_EQ);
|
||||
MOVI2R(SCRATCH2, 1);
|
||||
MOVP2R(SCRATCH1_64, &js.hasSetRounding);
|
||||
STRB(INDEX_UNSIGNED, SCRATCH2, SCRATCH1_64, 0);
|
||||
SetJumpTarget(skip2);
|
||||
POP(SCRATCH2);
|
||||
|
||||
// Let's update js.currentRoundingFunc with the right convertS0ToSCRATCH1 func.
|
||||
MOVP2R(SCRATCH1_64, convertS0ToSCRATCH1);
|
||||
LSL(SCRATCH2, SCRATCH2, 3);
|
||||
|
|
|
@ -375,8 +375,10 @@ void Arm64Jit::Comp_mxc1(MIPSOpcode op)
|
|||
// Must clear before setting, since ApplyRoundingMode() assumes it was cleared.
|
||||
RestoreRoundingMode();
|
||||
bool wasImm = gpr.IsImm(rt);
|
||||
u32 immVal = -1;
|
||||
if (wasImm) {
|
||||
gpr.SetImm(MIPS_REG_FPCOND, (gpr.GetImm(rt) >> 23) & 1);
|
||||
immVal = gpr.GetImm(rt);
|
||||
gpr.SetImm(MIPS_REG_FPCOND, (immVal >> 23) & 1);
|
||||
gpr.MapReg(rt);
|
||||
} else {
|
||||
gpr.MapDirtyIn(MIPS_REG_FPCOND, rt);
|
||||
|
@ -387,9 +389,11 @@ void Arm64Jit::Comp_mxc1(MIPSOpcode op)
|
|||
STR(INDEX_UNSIGNED, gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31));
|
||||
if (!wasImm) {
|
||||
UBFX(gpr.R(MIPS_REG_FPCOND), gpr.R(rt), 23, 1);
|
||||
// TODO: We do have the fcr31 value in a register here, could use that in UpdateRoundingMode to avoid reloading it.
|
||||
UpdateRoundingMode();
|
||||
} else {
|
||||
UpdateRoundingMode(immVal);
|
||||
}
|
||||
// TODO: We do have the fcr31 value in a register here, could use that in UpdateRoundingMode to avoid reloading it.
|
||||
UpdateRoundingMode();
|
||||
ApplyRoundingMode();
|
||||
} else {
|
||||
Comp_Generic(op);
|
||||
|
|
|
@ -602,7 +602,12 @@ void Arm64Jit::ApplyRoundingMode(bool force) {
|
|||
}
|
||||
|
||||
// Destroys SCRATCH1 and SCRATCH2
|
||||
void Arm64Jit::UpdateRoundingMode() {
|
||||
void Arm64Jit::UpdateRoundingMode(u32 fcr31) {
|
||||
// We must set js.hasSetRounding at compile time, or this block will use the wrong rounding mode.
|
||||
// The fcr31 parameter is -1 when not known at compile time, so we just assume it was changed.
|
||||
if (fcr31 & 0x01000003) {
|
||||
js.hasSetRounding = true;
|
||||
}
|
||||
QuickCallFunction(SCRATCH2_64, updateRoundingMode);
|
||||
}
|
||||
|
||||
|
|
|
@ -202,7 +202,7 @@ private:
|
|||
void WriteDownCountR(Arm64Gen::ARM64Reg reg, bool updateFlags = true);
|
||||
void RestoreRoundingMode(bool force = false);
|
||||
void ApplyRoundingMode(bool force = false);
|
||||
void UpdateRoundingMode();
|
||||
void UpdateRoundingMode(u32 fcr31 = -1);
|
||||
void MovFromPC(Arm64Gen::ARM64Reg r);
|
||||
void MovToPC(Arm64Gen::ARM64Reg r);
|
||||
|
||||
|
|
|
@ -200,6 +200,8 @@ void IRFrontend::ApplyRoundingMode(bool force) {
|
|||
|
||||
// Destroys SCRATCH1 and SCRATCH2
|
||||
void IRFrontend::UpdateRoundingMode() {
|
||||
// We must set js.hasSetRounding at compile time, or this block will use the wrong rounding mode.
|
||||
js.hasSetRounding = true;
|
||||
ir.Write(IROp::UpdateRoundingMode);
|
||||
}
|
||||
|
||||
|
|
|
@ -109,18 +109,6 @@ void Jit::GenerateFixedCode(JitOptions &jo) {
|
|||
RET();
|
||||
}
|
||||
|
||||
updateRoundingMode = AlignCode16(); {
|
||||
// If it's only ever 0, we don't actually bother applying or restoring it.
|
||||
// This is the most common situation.
|
||||
TEST(32, MIPSSTATE_VAR(fcr31), Imm32(0x01000003));
|
||||
FixupBranch skip = J_CC(CC_Z);
|
||||
// TODO: Move the hasSetRounding flag somewhere we can reach it through the context pointer, or something.
|
||||
MOV(PTRBITS, R(RAX), ImmPtr(&js.hasSetRounding));
|
||||
MOV(8, MatR(RAX), Imm8(1));
|
||||
SetJumpTarget(skip);
|
||||
RET();
|
||||
}
|
||||
|
||||
enterDispatcher = AlignCode16();
|
||||
ABI_PushAllCalleeSavedRegsAndAdjustStack();
|
||||
#ifdef _M_X64
|
||||
|
|
|
@ -426,7 +426,7 @@ void Jit::Comp_mxc1(MIPSOpcode op) {
|
|||
if ((gpr.GetImm(rt) & 0x1000003) == 0) {
|
||||
// Default nearest / no-flush mode, just leave it cleared.
|
||||
} else {
|
||||
UpdateRoundingMode();
|
||||
UpdateRoundingMode(gpr.GetImm(rt));
|
||||
ApplyRoundingMode();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -198,8 +198,12 @@ void Jit::ApplyRoundingMode(bool force) {
|
|||
}
|
||||
}
|
||||
|
||||
void Jit::UpdateRoundingMode() {
|
||||
CALL(updateRoundingMode);
|
||||
void Jit::UpdateRoundingMode(u32 fcr31) {
|
||||
// We must set js.hasSetRounding at compile time, or this block will use the wrong rounding mode.
|
||||
// The fcr31 parameter is -1 when not known at compile time, so we just assume it was changed.
|
||||
if (fcr31 & 0x01000003) {
|
||||
js.hasSetRounding = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Jit::ClearCache()
|
||||
|
@ -418,8 +422,6 @@ void Jit::AddContinuedBlock(u32 dest) {
|
|||
bool Jit::DescribeCodePtr(const u8 *ptr, std::string &name) {
|
||||
if (ptr == applyRoundingMode)
|
||||
name = "applyRoundingMode";
|
||||
else if (ptr == updateRoundingMode)
|
||||
name = "updateRoundingMode";
|
||||
else if (ptr == dispatcher)
|
||||
name = "dispatcher";
|
||||
else if (ptr == dispatcherInEAXNoCheck)
|
||||
|
|
|
@ -155,7 +155,7 @@ public:
|
|||
|
||||
void RestoreRoundingMode(bool force = false);
|
||||
void ApplyRoundingMode(bool force = false);
|
||||
void UpdateRoundingMode();
|
||||
void UpdateRoundingMode(u32 fcr31 = -1);
|
||||
|
||||
JitBlockCache *GetBlockCache() override { return &blocks; }
|
||||
JitBlockCacheDebugInterface *GetBlockCacheDebugInterface() override { return &blocks; }
|
||||
|
@ -324,7 +324,6 @@ private:
|
|||
|
||||
const u8 *restoreRoundingMode;
|
||||
const u8 *applyRoundingMode;
|
||||
const u8 *updateRoundingMode;
|
||||
|
||||
const u8 *endOfPregeneratedCode;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue