Get rid of the ForceFlushToZero hidden config option

This commit is contained in:
Henrik Rydgard 2015-10-08 10:29:35 +02:00
parent 42ce836ba5
commit 6dd86cd843
5 changed files with 63 additions and 108 deletions

View file

@ -326,14 +326,6 @@ static ConfigSetting generalSettings[] = {
ConfigSetting(false),
};
static bool DefaultForceFlushToZero() {
#ifdef ARM
return true;
#else
return false;
#endif
}
static ConfigSetting cpuSettings[] = {
ReportedConfigSetting("Jit", &g_Config.bJit, &DefaultJit, true, true),
ReportedConfigSetting("SeparateCPUThread", &g_Config.bSeparateCPUThread, false, true, true),
@ -343,7 +335,6 @@ static ConfigSetting cpuSettings[] = {
ReportedConfigSetting("FuncReplacements", &g_Config.bFuncReplacements, true, true, true),
ReportedConfigSetting("CPUSpeed", &g_Config.iLockedCPUSpeed, 0, true, true),
ReportedConfigSetting("SetRoundingMode", &g_Config.bSetRoundingMode, true, true, true),
ReportedConfigSetting("ForceFlushToZero", &g_Config.bForceFlushToZero, &DefaultForceFlushToZero, true, true),
ConfigSetting(false),
};

View file

@ -117,7 +117,6 @@ public:
bool bForceLagSync;
bool bFuncReplacements;
bool bSetRoundingMode;
bool bForceFlushToZero;
// Definitely cannot be changed while game is running.
bool bSeparateCPUThread;

View file

@ -587,14 +587,10 @@ void ArmJit::WriteDownCountR(ARMReg reg) {
void ArmJit::RestoreRoundingMode(bool force) {
// If the game has never set an interesting rounding mode, we can safely skip this.
if (g_Config.bSetRoundingMode && (force || !g_Config.bForceFlushToZero || js.hasSetRounding)) {
if (g_Config.bSetRoundingMode && (force || js.hasSetRounding)) {
VMRS(SCRATCHREG2);
// Assume we're always in round-to-nearest mode beforehand.
// Also on ARM, we're always in flush-to-zero in C++, so stay that way.
if (!g_Config.bForceFlushToZero) {
ORR(SCRATCHREG2, SCRATCHREG2, AssumeMakeOperand2(4 << 22));
}
BIC(SCRATCHREG2, SCRATCHREG2, AssumeMakeOperand2(3 << 22));
// Assume we're always in round-to-nearest mode beforehand. Flush-to-zero is off.
BIC(SCRATCHREG2, SCRATCHREG2, AssumeMakeOperand2((3 | 4) << 22));
VMSR(SCRATCHREG2);
}
}
@ -602,19 +598,17 @@ void ArmJit::RestoreRoundingMode(bool force) {
void ArmJit::ApplyRoundingMode(bool force) {
// NOTE: Must not destroy R0.
// If the game has never set an interesting rounding mode, we can safely skip this.
if (g_Config.bSetRoundingMode && (force || !g_Config.bForceFlushToZero || js.hasSetRounding)) {
if (g_Config.bSetRoundingMode && (force || js.hasSetRounding)) {
LDR(SCRATCHREG2, CTXREG, offsetof(MIPSState, fcr31));
if (!g_Config.bForceFlushToZero) {
TST(SCRATCHREG2, AssumeMakeOperand2(1 << 24));
AND(SCRATCHREG2, SCRATCHREG2, Operand2(3));
SetCC(CC_NEQ);
ADD(SCRATCHREG2, SCRATCHREG2, Operand2(4));
SetCC(CC_AL);
// We can only skip if the rounding mode is zero and flush is set.
CMP(SCRATCHREG2, Operand2(4));
} else {
ANDS(SCRATCHREG2, SCRATCHREG2, Operand2(3));
}
TST(SCRATCHREG2, AssumeMakeOperand2(1 << 24));
AND(SCRATCHREG2, SCRATCHREG2, Operand2(3));
SetCC(CC_NEQ);
ADD(SCRATCHREG2, SCRATCHREG2, Operand2(4));
SetCC(CC_AL);
// We can only skip if the rounding mode is zero and flush is not set.
CMP(SCRATCHREG2, Operand2(3));
// At this point, if it was zero, we can skip the rest.
FixupBranch skip = B_CC(CC_EQ);
PUSH(1, SCRATCHREG1);
@ -624,12 +618,8 @@ void ArmJit::ApplyRoundingMode(bool force) {
// 1: Round to zero 3
// 2: Round up (ceil) 1
// 3: Round down (floor) 2
if (!g_Config.bForceFlushToZero) {
AND(SCRATCHREG1, SCRATCHREG2, Operand2(3));
CMP(SCRATCHREG1, Operand2(1));
} else {
CMP(SCRATCHREG2, Operand2(1));
}
AND(SCRATCHREG1, SCRATCHREG2, Operand2(3));
CMP(SCRATCHREG1, Operand2(1));
SetCC(CC_EQ); ADD(SCRATCHREG2, SCRATCHREG2, Operand2(2));
SetCC(CC_GT); SUB(SCRATCHREG2, SCRATCHREG2, Operand2(1));
@ -637,10 +627,8 @@ void ArmJit::ApplyRoundingMode(bool force) {
VMRS(SCRATCHREG1);
// Assume we're always in round-to-nearest mode beforehand.
if (!g_Config.bForceFlushToZero) {
// But we need to clear flush to zero in this case anyway.
BIC(SCRATCHREG1, SCRATCHREG1, AssumeMakeOperand2(7 << 22));
}
// But we need to clear flush to zero in this case anyway.
BIC(SCRATCHREG1, SCRATCHREG1, AssumeMakeOperand2((3 | 4) << 22));
ORR(SCRATCHREG1, SCRATCHREG1, Operand2(SCRATCHREG2, ST_LSL, 22));
VMSR(SCRATCHREG1);
@ -650,20 +638,17 @@ void ArmJit::ApplyRoundingMode(bool force) {
}
void ArmJit::UpdateRoundingMode() {
// NOTE: Must not destory R0.
// NOTE: Must not destroy R0.
if (g_Config.bSetRoundingMode) {
LDR(SCRATCHREG2, CTXREG, offsetof(MIPSState, fcr31));
if (!g_Config.bForceFlushToZero) {
TST(SCRATCHREG2, AssumeMakeOperand2(1 << 24));
AND(SCRATCHREG2, SCRATCHREG2, Operand2(3));
SetCC(CC_NEQ);
ADD(SCRATCHREG2, SCRATCHREG2, Operand2(4));
SetCC(CC_AL);
// We can only skip if the rounding mode is zero and flush is set.
CMP(SCRATCHREG2, Operand2(4));
} else {
ANDS(SCRATCHREG2, SCRATCHREG2, Operand2(3));
}
TST(SCRATCHREG2, AssumeMakeOperand2(1 << 24));
AND(SCRATCHREG2, SCRATCHREG2, Operand2(3));
SetCC(CC_NEQ);
ADD(SCRATCHREG2, SCRATCHREG2, Operand2(4));
SetCC(CC_AL);
// We can only skip if the rounding mode is zero and flush is not set.
CMP(SCRATCHREG2, Operand2(3));
FixupBranch skip = B_CC(CC_EQ);
PUSH(1, SCRATCHREG1);

View file

@ -526,14 +526,13 @@ void Arm64Jit::WriteDownCountR(ARM64Reg reg, bool updateFlags) {
void Arm64Jit::RestoreRoundingMode(bool force) {
// If the game has never set an interesting rounding mode, we can safely skip this.
if (g_Config.bSetRoundingMode && (force || !g_Config.bForceFlushToZero || js.hasSetRounding)) {
if (g_Config.bSetRoundingMode && (force || js.hasSetRounding)) {
MRS(SCRATCH2_64, FIELD_FPCR);
// We are not in flush-to-zero mode outside the JIT, so let's turn it off.
uint32_t mask = ~(4 << 22);
// Assume we're always in round-to-nearest mode beforehand.
// Also on ARM, we're always in flush-to-zero in C++, so stay that way.
if (!g_Config.bForceFlushToZero) {
ORRI2R(SCRATCH2, SCRATCH2, 4 << 22);
}
ANDI2R(SCRATCH2, SCRATCH2, ~(3 << 22));
mask &= ~(3 << 22);
ANDI2R(SCRATCH2, SCRATCH2, mask);
_MSR(FIELD_FPCR, SCRATCH2_64);
}
}
@ -541,19 +540,15 @@ void Arm64Jit::RestoreRoundingMode(bool force) {
void Arm64Jit::ApplyRoundingMode(bool force) {
// NOTE: Must not destroy SCRATCH1.
// If the game has never set an interesting rounding mode, we can safely skip this.
if (g_Config.bSetRoundingMode && (force || !g_Config.bForceFlushToZero || js.hasSetRounding)) {
if (g_Config.bSetRoundingMode && (force || js.hasSetRounding)) {
LDR(INDEX_UNSIGNED, SCRATCH2, CTXREG, offsetof(MIPSState, fcr31));
if (!g_Config.bForceFlushToZero) {
TSTI2R(SCRATCH2, 1 << 24);
ANDI2R(SCRATCH2, SCRATCH2, 3);
FixupBranch skip1 = B(CC_EQ);
ADDI2R(SCRATCH2, SCRATCH2, 4);
SetJumpTarget(skip1);
// We can only skip if the rounding mode is zero and flush is set.
CMPI2R(SCRATCH2, 4);
} else {
ANDSI2R(SCRATCH2, SCRATCH2, 3);
}
TSTI2R(SCRATCH2, 1 << 24);
ANDI2R(SCRATCH2, SCRATCH2, 3);
FixupBranch skip1 = B(CC_EQ);
ADDI2R(SCRATCH2, SCRATCH2, 4);
SetJumpTarget(skip1);
// We can only skip if the rounding mode is zero and flush is set.
CMPI2R(SCRATCH2, 4);
// At this point, if it was zero, we can skip the rest.
FixupBranch skip = B(CC_EQ);
PUSH(SCRATCH1);
@ -563,12 +558,8 @@ void Arm64Jit::ApplyRoundingMode(bool force) {
// 1: Round to zero 3
// 2: Round up (ceil) 1
// 3: Round down (floor) 2
if (!g_Config.bForceFlushToZero) {
ANDI2R(SCRATCH1, SCRATCH2, 3);
CMPI2R(SCRATCH1, 1);
} else {
CMPI2R(SCRATCH2, 1);
}
ANDI2R(SCRATCH1, SCRATCH2, 3);
CMPI2R(SCRATCH1, 1);
FixupBranch skipadd = B(CC_NEQ);
ADDI2R(SCRATCH2, SCRATCH2, 2);
@ -578,11 +569,10 @@ void Arm64Jit::ApplyRoundingMode(bool force) {
SetJumpTarget(skipsub);
MRS(SCRATCH1_64, FIELD_FPCR);
// Assume we're always in round-to-nearest mode beforehand.
if (!g_Config.bForceFlushToZero) {
// But we need to clear flush to zero in this case anyway.
ANDI2R(SCRATCH1, SCRATCH1, ~(7 << 22));
}
// Clear both flush-to-zero and rounding before re-setting them.
ANDI2R(SCRATCH1, SCRATCH1, ~((4 | 3) << 22));
ORR(SCRATCH1, SCRATCH1, SCRATCH2, ArithOption(SCRATCH2, ST_LSL, 22));
_MSR(FIELD_FPCR, SCRATCH1_64);
@ -603,25 +593,23 @@ void Arm64Jit::UpdateRoundingMode() {
// NOTE: Must not destroy SCRATCH1.
if (g_Config.bSetRoundingMode) {
LDR(INDEX_UNSIGNED, SCRATCH2, CTXREG, offsetof(MIPSState, fcr31));
if (!g_Config.bForceFlushToZero) {
TSTI2R(SCRATCH2, 1 << 24);
ANDI2R(SCRATCH2, SCRATCH2, 3);
FixupBranch skip = B(CC_EQ);
ADDI2R(SCRATCH2, SCRATCH2, 4);
SetJumpTarget(skip);
// We can only skip if the rounding mode is zero and flush is set.
CMPI2R(SCRATCH2, 4);
} else {
ANDSI2R(SCRATCH2, SCRATCH2, 3);
}
TSTI2R(SCRATCH2, 1 << 24);
ANDI2R(SCRATCH2, SCRATCH2, 3);
FixupBranch skip = B(CC_EQ);
ADDI2R(SCRATCH2, SCRATCH2, 4);
SetJumpTarget(skip);
// We can only skip if the rounding mode is zero and flush is not set.
CMPI2R(SCRATCH2, 3);
FixupBranch skip2 = B(CC_EQ);
PUSH(SCRATCH1_64);
MOVI2R(SCRATCH2, 1);
MOVP2R(SCRATCH1_64, &js.hasSetRounding);
STRB(INDEX_UNSIGNED, SCRATCH2, SCRATCH1_64, 0);
POP(SCRATCH1_64);
SetJumpTarget(skip);
SetJumpTarget(skip2);
}
}

View file

@ -223,7 +223,7 @@ void Jit::WriteDowncount(int offset)
void Jit::RestoreRoundingMode(bool force, XEmitter *emitter)
{
// If the game has never set an interesting rounding mode, we can safely skip this.
if (g_Config.bSetRoundingMode && (force || g_Config.bForceFlushToZero || js.hasSetRounding))
if (g_Config.bSetRoundingMode && (force || js.hasSetRounding))
{
if (emitter == NULL)
emitter = this;
@ -237,7 +237,7 @@ void Jit::RestoreRoundingMode(bool force, XEmitter *emitter)
void Jit::ApplyRoundingMode(bool force, XEmitter *emitter)
{
// If the game has never set an interesting rounding mode, we can safely skip this.
if (g_Config.bSetRoundingMode && (force || g_Config.bForceFlushToZero || js.hasSetRounding))
if (g_Config.bSetRoundingMode && (force || js.hasSetRounding))
{
if (emitter == NULL)
emitter = this;
@ -247,9 +247,7 @@ void Jit::ApplyRoundingMode(bool force, XEmitter *emitter)
// If it's 0, we don't actually bother setting. This is the most common.
// We always use nearest as the default rounding mode with
// flush-to-zero disabled.
FixupBranch skip;
if (!g_Config.bForceFlushToZero)
skip = emitter->J_CC(CC_Z);
FixupBranch skip = emitter->J_CC(CC_Z);
emitter->STMXCSR(M(&mips_->temp));
@ -263,19 +261,13 @@ void Jit::ApplyRoundingMode(bool force, XEmitter *emitter)
emitter->SHL(32, R(EAX), Imm8(13));
emitter->OR(32, M(&mips_->temp), R(EAX));
if (g_Config.bForceFlushToZero) {
emitter->OR(32, M(&mips_->temp), Imm32(1 << 15));
} else {
emitter->TEST(32, M(&mips_->fcr31), Imm32(1 << 24));
FixupBranch skip3 = emitter->J_CC(CC_Z);
emitter->OR(32, M(&mips_->temp), Imm32(1 << 15));
emitter->SetJumpTarget(skip3);
}
emitter->TEST(32, M(&mips_->fcr31), Imm32(1 << 24));
FixupBranch skip3 = emitter->J_CC(CC_Z);
emitter->OR(32, M(&mips_->temp), Imm32(1 << 15));
emitter->SetJumpTarget(skip3);
emitter->LDMXCSR(M(&mips_->temp));
if (!g_Config.bForceFlushToZero)
emitter->SetJumpTarget(skip);
emitter->SetJumpTarget(skip);
}
}