JitArm64_SystemRegisters: Use ScopedARM64Reg

This commit is contained in:
Sintendo 2024-06-23 23:21:07 +02:00
parent be2b466743
commit defb2d65a6
1 changed files with 155 additions and 190 deletions

View File

@ -48,17 +48,16 @@ void JitArm64::FixGTBeforeSettingCRFieldBit(Arm64Gen::ARM64Reg reg)
// if the internal representation either has bit 63 set or has all bits set to zero. // if the internal representation either has bit 63 set or has all bits set to zero.
// If all bits are zero and we set some bit that's unrelated to GT, we need to set bit 63 so GT // If all bits are zero and we set some bit that's unrelated to GT, we need to set bit 63 so GT
// doesn't accidentally become considered set. Gross but necessary; this can break actual games. // doesn't accidentally become considered set. Gross but necessary; this can break actual games.
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XA = EncodeRegTo64(WA);
ORR(XA, reg, LogicalImm(1ULL << 63, GPRSize::B64)); ORR(XA, reg, LogicalImm(1ULL << 63, GPRSize::B64));
CMP(reg, ARM64Reg::ZR); CMP(reg, ARM64Reg::ZR);
CSEL(reg, reg, XA, CC_NEQ); CSEL(reg, reg, XA, CC_NEQ);
gpr.Unlock(WA);
} }
void JitArm64::UpdateFPExceptionSummary(ARM64Reg fpscr) void JitArm64::UpdateFPExceptionSummary(ARM64Reg fpscr)
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
// fpscr.VX = (fpscr & FPSCR_VX_ANY) != 0 // fpscr.VX = (fpscr & FPSCR_VX_ANY) != 0
MOVI2R(WA, FPSCR_VX_ANY); MOVI2R(WA, FPSCR_VX_ANY);
@ -71,8 +70,6 @@ void JitArm64::UpdateFPExceptionSummary(ARM64Reg fpscr)
TST(WA, fpscr, ArithOption(fpscr, ShiftType::LSR, 22)); TST(WA, fpscr, ArithOption(fpscr, ShiftType::LSR, 22));
CSET(WA, CCFlags::CC_NEQ); CSET(WA, CCFlags::CC_NEQ);
BFI(fpscr, WA, MathUtil::IntLog2(FPSCR_FEX), 1); BFI(fpscr, WA, MathUtil::IntLog2(FPSCR_FEX), 1);
gpr.Unlock(WA);
} }
void JitArm64::UpdateRoundingMode() void JitArm64::UpdateRoundingMode()
@ -135,7 +132,7 @@ void JitArm64::mcrxr(UGeckoInstruction inst)
JITDISABLE(bJITSystemRegistersOff); JITDISABLE(bJITSystemRegistersOff);
gpr.BindCRToRegister(inst.CRFD, false); gpr.BindCRToRegister(inst.CRFD, false);
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XA = EncodeRegTo64(WA);
ARM64Reg XB = gpr.CR(inst.CRFD); ARM64Reg XB = gpr.CR(inst.CRFD);
ARM64Reg WB = EncodeRegTo32(XB); ARM64Reg WB = EncodeRegTo32(XB);
@ -155,8 +152,6 @@ void JitArm64::mcrxr(UGeckoInstruction inst)
// Clear XER[0-3] // Clear XER[0-3]
static_assert(PPCSTATE_OFF(xer_ca) + 1 == PPCSTATE_OFF(xer_so_ov)); static_assert(PPCSTATE_OFF(xer_ca) + 1 == PPCSTATE_OFF(xer_so_ov));
STRH(IndexType::Unsigned, ARM64Reg::WZR, PPC_REG, PPCSTATE_OFF(xer_ca)); STRH(IndexType::Unsigned, ARM64Reg::WZR, PPC_REG, PPCSTATE_OFF(xer_ca));
gpr.Unlock(WA);
} }
void JitArm64::mfsr(UGeckoInstruction inst) void JitArm64::mfsr(UGeckoInstruction inst)
@ -186,14 +181,12 @@ void JitArm64::mfsrin(UGeckoInstruction inst)
ARM64Reg RB = gpr.R(b); ARM64Reg RB = gpr.R(b);
ARM64Reg RD = gpr.R(d); ARM64Reg RD = gpr.R(d);
ARM64Reg index = gpr.GetReg(); auto index = gpr.GetScopedReg();
ARM64Reg addr = EncodeRegTo64(RD); ARM64Reg addr = EncodeRegTo64(RD);
UBFM(index, RB, 28, 31); UBFM(index, RB, 28, 31);
ADDI2R(addr, PPC_REG, PPCSTATE_OFF_SR(0), addr); ADDI2R(addr, PPC_REG, PPCSTATE_OFF_SR(0), addr);
LDR(RD, addr, ArithOption(EncodeRegTo64(index), true)); LDR(RD, addr, ArithOption(EncodeRegTo64(index), true));
gpr.Unlock(index);
} }
void JitArm64::mtsrin(UGeckoInstruction inst) void JitArm64::mtsrin(UGeckoInstruction inst)
@ -206,14 +199,12 @@ void JitArm64::mtsrin(UGeckoInstruction inst)
ARM64Reg RB = gpr.R(b); ARM64Reg RB = gpr.R(b);
ARM64Reg RD = gpr.R(d); ARM64Reg RD = gpr.R(d);
ARM64Reg index = gpr.GetReg(); auto index = gpr.GetScopedReg();
ARM64Reg addr = gpr.GetReg(); auto addr = gpr.GetScopedReg();
UBFM(index, RB, 28, 31); UBFM(index, RB, 28, 31);
ADDI2R(EncodeRegTo64(addr), PPC_REG, PPCSTATE_OFF_SR(0), EncodeRegTo64(addr)); ADDI2R(EncodeRegTo64(addr), PPC_REG, PPCSTATE_OFF_SR(0), EncodeRegTo64(addr));
STR(RD, EncodeRegTo64(addr), ArithOption(EncodeRegTo64(index), true)); STR(RD, EncodeRegTo64(addr), ArithOption(EncodeRegTo64(index), true));
gpr.Unlock(index, addr);
} }
void JitArm64::twx(UGeckoInstruction inst) void JitArm64::twx(UGeckoInstruction inst)
@ -223,7 +214,7 @@ void JitArm64::twx(UGeckoInstruction inst)
s32 a = inst.RA; s32 a = inst.RA;
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
if (inst.OPCD == 3) // twi if (inst.OPCD == 3) // twi
{ {
@ -278,8 +269,6 @@ void JitArm64::twx(UGeckoInstruction inst)
fpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG); fpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG);
WriteExit(js.compilerPC + 4); WriteExit(js.compilerPC + 4);
} }
gpr.Unlock(WA);
} }
void JitArm64::mfspr(UGeckoInstruction inst) void JitArm64::mfspr(UGeckoInstruction inst)
@ -294,19 +283,19 @@ void JitArm64::mfspr(UGeckoInstruction inst)
case SPR_TL: case SPR_TL:
case SPR_TU: case SPR_TU:
{ {
ARM64Reg Wg = gpr.GetReg(); auto Wg = gpr.GetScopedReg();
ARM64Reg Xg = EncodeRegTo64(Wg); ARM64Reg Xg = EncodeRegTo64(Wg);
ARM64Reg Wresult = gpr.GetReg(); auto Wresult = gpr.GetScopedReg();
ARM64Reg Xresult = EncodeRegTo64(Wresult); ARM64Reg Xresult = EncodeRegTo64(Wresult);
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ARM64Reg WB = gpr.GetReg(); auto WB = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XA = EncodeRegTo64(WA);
ARM64Reg XB = EncodeRegTo64(WB); ARM64Reg XB = EncodeRegTo64(WB);
ARM64Reg VC = fpr.GetReg(); auto VC = fpr.GetScopedReg();
ARM64Reg VD = fpr.GetReg(); auto VD = fpr.GetScopedReg();
ARM64Reg SC = EncodeRegToSingle(VC); ARM64Reg SC = EncodeRegToSingle(VC);
ARM64Reg SD = EncodeRegToSingle(VD); ARM64Reg SD = EncodeRegToSingle(VD);
@ -371,8 +360,6 @@ void JitArm64::mfspr(UGeckoInstruction inst)
else else
LSR(EncodeRegTo64(gpr.R(n)), Xresult, 32); LSR(EncodeRegTo64(gpr.R(n)), Xresult, 32);
gpr.Unlock(Wg, Wresult, WA, WB);
fpr.Unlock(VC, VD);
break; break;
} }
} }
@ -381,22 +368,18 @@ void JitArm64::mfspr(UGeckoInstruction inst)
LSR(EncodeRegTo64(gpr.R(d)), Xresult, 32); LSR(EncodeRegTo64(gpr.R(d)), Xresult, 32);
else else
MOV(gpr.R(d), Wresult); MOV(gpr.R(d), Wresult);
gpr.Unlock(Wg, Wresult, WA, WB);
fpr.Unlock(VC, VD);
} }
break; break;
case SPR_XER: case SPR_XER:
{ {
gpr.BindToRegister(d, false); gpr.BindToRegister(d, false);
ARM64Reg RD = gpr.R(d); ARM64Reg RD = gpr.R(d);
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
LDRH(IndexType::Unsigned, RD, PPC_REG, PPCSTATE_OFF(xer_stringctrl)); LDRH(IndexType::Unsigned, RD, PPC_REG, PPCSTATE_OFF(xer_stringctrl));
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
ORR(RD, RD, WA, ArithOption(WA, ShiftType::LSL, XER_CA_SHIFT)); ORR(RD, RD, WA, ArithOption(WA, ShiftType::LSL, XER_CA_SHIFT));
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_so_ov)); LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_so_ov));
ORR(RD, RD, WA, ArithOption(WA, ShiftType::LSL, XER_OV_SHIFT)); ORR(RD, RD, WA, ArithOption(WA, ShiftType::LSL, XER_OV_SHIFT));
gpr.Unlock(WA);
} }
break; break;
case SPR_WPAR: case SPR_WPAR:
@ -462,14 +445,13 @@ void JitArm64::mtspr(UGeckoInstruction inst)
case SPR_XER: case SPR_XER:
{ {
ARM64Reg RD = gpr.R(inst.RD); ARM64Reg RD = gpr.R(inst.RD);
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
AND(WA, RD, LogicalImm(0xFFFFFF7F, GPRSize::B32)); AND(WA, RD, LogicalImm(0xFFFFFF7F, GPRSize::B32));
STRH(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_stringctrl)); STRH(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_stringctrl));
UBFM(WA, RD, XER_CA_SHIFT, XER_CA_SHIFT + 1); UBFM(WA, RD, XER_CA_SHIFT, XER_CA_SHIFT + 1);
STRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); STRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
UBFM(WA, RD, XER_OV_SHIFT, 31); // Same as WA = RD >> XER_OV_SHIFT UBFM(WA, RD, XER_OV_SHIFT, 31); // Same as WA = RD >> XER_OV_SHIFT
STRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_so_ov)); STRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_so_ov));
gpr.Unlock(WA);
} }
break; break;
default: default:
@ -553,9 +535,10 @@ void JitArm64::crXXX(UGeckoInstruction inst)
return; return;
} }
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XA = EncodeRegTo64(WA);
ARM64Reg WB = gpr.GetReg(); {
auto WB = gpr.GetScopedReg();
ARM64Reg XB = EncodeRegTo64(WB); ARM64Reg XB = EncodeRegTo64(WB);
// creqv or crnand or crnor // creqv or crnand or crnor
@ -623,44 +606,41 @@ void JitArm64::crXXX(UGeckoInstruction inst)
ORR(XA, XA, XB); ORR(XA, XA, XB);
break; break;
} }
}
// Store result bit in CRBD // Store result bit in CRBD
int field = inst.CRBD >> 2; int field = inst.CRBD >> 2;
int bit = 3 - (inst.CRBD & 3); int bit = 3 - (inst.CRBD & 3);
gpr.Unlock(WB);
WB = ARM64Reg::INVALID_REG;
gpr.BindCRToRegister(field, true); gpr.BindCRToRegister(field, true);
XB = gpr.CR(field); ARM64Reg CR = gpr.CR(field);
if (bit != PowerPC::CR_GT_BIT) if (bit != PowerPC::CR_GT_BIT)
FixGTBeforeSettingCRFieldBit(XB); FixGTBeforeSettingCRFieldBit(CR);
switch (bit) switch (bit)
{ {
case PowerPC::CR_SO_BIT: // set bit 59 to input case PowerPC::CR_SO_BIT: // set bit 59 to input
BFI(XB, XA, PowerPC::CR_EMU_SO_BIT, 1); BFI(CR, XA, PowerPC::CR_EMU_SO_BIT, 1);
break; break;
case PowerPC::CR_EQ_BIT: // clear low 32 bits, set bit 0 to !input case PowerPC::CR_EQ_BIT: // clear low 32 bits, set bit 0 to !input
AND(XB, XB, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64)); AND(CR, CR, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64));
EOR(XA, XA, LogicalImm(1, GPRSize::B64)); EOR(XA, XA, LogicalImm(1, GPRSize::B64));
ORR(XB, XB, XA); ORR(CR, CR, XA);
break; break;
case PowerPC::CR_GT_BIT: // set bit 63 to !input case PowerPC::CR_GT_BIT: // set bit 63 to !input
EOR(XA, XA, LogicalImm(1, GPRSize::B64)); EOR(XA, XA, LogicalImm(1, GPRSize::B64));
BFI(XB, XA, 63, 1); BFI(CR, XA, 63, 1);
break; break;
case PowerPC::CR_LT_BIT: // set bit 62 to input case PowerPC::CR_LT_BIT: // set bit 62 to input
BFI(XB, XA, PowerPC::CR_EMU_LT_BIT, 1); BFI(CR, XA, PowerPC::CR_EMU_LT_BIT, 1);
break; break;
} }
ORR(XB, XB, LogicalImm(1ULL << 32, GPRSize::B64)); ORR(CR, CR, LogicalImm(1ULL << 32, GPRSize::B64));
gpr.Unlock(WA);
} }
void JitArm64::mfcr(UGeckoInstruction inst) void JitArm64::mfcr(UGeckoInstruction inst)
@ -670,8 +650,8 @@ void JitArm64::mfcr(UGeckoInstruction inst)
gpr.BindToRegister(inst.RD, false); gpr.BindToRegister(inst.RD, false);
ARM64Reg WA = gpr.R(inst.RD); ARM64Reg WA = gpr.R(inst.RD);
ARM64Reg WB = gpr.GetReg(); auto WB = gpr.GetScopedReg();
ARM64Reg WC = gpr.GetReg(); auto WC = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XA = EncodeRegTo64(WA);
ARM64Reg XB = EncodeRegTo64(WB); ARM64Reg XB = EncodeRegTo64(WB);
ARM64Reg XC = EncodeRegTo64(WC); ARM64Reg XC = EncodeRegTo64(WC);
@ -716,8 +696,6 @@ void JitArm64::mfcr(UGeckoInstruction inst)
else if (!js.op->crInUse[i]) else if (!js.op->crInUse[i])
gpr.StoreCRRegisters(BitSet8{i}, WC); gpr.StoreCRRegisters(BitSet8{i}, WC);
} }
gpr.Unlock(WB, WC);
} }
void JitArm64::mtcrf(UGeckoInstruction inst) void JitArm64::mtcrf(UGeckoInstruction inst)
@ -729,7 +707,7 @@ void JitArm64::mtcrf(UGeckoInstruction inst)
if (crm != 0) if (crm != 0)
{ {
ARM64Reg RS = gpr.R(inst.RS); ARM64Reg RS = gpr.R(inst.RS);
ARM64Reg WB = gpr.GetReg(); auto WB = gpr.GetScopedReg();
ARM64Reg XB = EncodeRegTo64(WB); ARM64Reg XB = EncodeRegTo64(WB);
MOVP2R(XB, PowerPC::ConditionRegister::s_crTable.data()); MOVP2R(XB, PowerPC::ConditionRegister::s_crTable.data());
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
@ -753,7 +731,6 @@ void JitArm64::mtcrf(UGeckoInstruction inst)
LDR(CR, XB, ArithOption(CR, true)); LDR(CR, XB, ArithOption(CR, true));
} }
} }
gpr.Unlock(WB);
} }
} }
@ -771,7 +748,7 @@ void JitArm64::mcrfs(UGeckoInstruction inst)
gpr.BindCRToRegister(field, false); gpr.BindCRToRegister(field, false);
ARM64Reg CR = gpr.CR(field); ARM64Reg CR = gpr.CR(field);
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ARM64Reg WCR = EncodeRegTo32(CR); ARM64Reg WCR = EncodeRegTo32(CR);
ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XA = EncodeRegTo64(WA);
@ -789,8 +766,6 @@ void JitArm64::mcrfs(UGeckoInstruction inst)
MOVP2R(XA, PowerPC::ConditionRegister::s_crTable.data()); MOVP2R(XA, PowerPC::ConditionRegister::s_crTable.data());
LDR(CR, XA, ArithOption(CR, true)); LDR(CR, XA, ArithOption(CR, true));
gpr.Unlock(WA);
} }
void JitArm64::mffsx(UGeckoInstruction inst) void JitArm64::mffsx(UGeckoInstruction inst)
@ -799,7 +774,7 @@ void JitArm64::mffsx(UGeckoInstruction inst)
JITDISABLE(bJITSystemRegistersOff); JITDISABLE(bJITSystemRegistersOff);
FALLBACK_IF(inst.Rc); FALLBACK_IF(inst.Rc);
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XA = EncodeRegTo64(WA);
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
@ -808,8 +783,6 @@ void JitArm64::mffsx(UGeckoInstruction inst)
ORR(XA, XA, LogicalImm(0xFFF8'0000'0000'0000, GPRSize::B64)); ORR(XA, XA, LogicalImm(0xFFF8'0000'0000'0000, GPRSize::B64));
m_float_emit.FMOV(EncodeRegToDouble(VD), XA); m_float_emit.FMOV(EncodeRegToDouble(VD), XA);
gpr.Unlock(WA);
} }
void JitArm64::mtfsb0x(UGeckoInstruction inst) void JitArm64::mtfsb0x(UGeckoInstruction inst)
@ -824,7 +797,8 @@ void JitArm64::mtfsb0x(UGeckoInstruction inst)
if (mask == FPSCR_FEX || mask == FPSCR_VX) if (mask == FPSCR_FEX || mask == FPSCR_VX)
return; return;
ARM64Reg WA = gpr.GetReg(); {
auto WA = gpr.GetScopedReg();
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
@ -833,8 +807,7 @@ void JitArm64::mtfsb0x(UGeckoInstruction inst)
if ((mask & (FPSCR_ANY_X | FPSCR_ANY_E)) != 0) if ((mask & (FPSCR_ANY_X | FPSCR_ANY_E)) != 0)
UpdateFPExceptionSummary(WA); UpdateFPExceptionSummary(WA);
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
}
gpr.Unlock(WA);
if (inst.CRBD >= 29) if (inst.CRBD >= 29)
UpdateRoundingMode(); UpdateRoundingMode();
@ -852,25 +825,24 @@ void JitArm64::mtfsb1x(UGeckoInstruction inst)
if (mask == FPSCR_FEX || mask == FPSCR_VX) if (mask == FPSCR_FEX || mask == FPSCR_VX)
return; return;
ARM64Reg WA = gpr.GetReg(); {
auto WA = gpr.GetScopedReg();
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
if ((mask & FPSCR_ANY_X) != 0) if ((mask & FPSCR_ANY_X) != 0)
{ {
ARM64Reg WB = gpr.GetReg(); auto WB = gpr.GetScopedReg();
TST(WA, LogicalImm(mask, GPRSize::B32)); TST(WA, LogicalImm(mask, GPRSize::B32));
ORR(WB, WA, LogicalImm(1 << 31, GPRSize::B32)); ORR(WB, WA, LogicalImm(1 << 31, GPRSize::B32));
CSEL(WA, WA, WB, CCFlags::CC_NEQ); CSEL(WA, WA, WB, CCFlags::CC_NEQ);
gpr.Unlock(WB);
} }
ORR(WA, WA, LogicalImm(mask, GPRSize::B32)); ORR(WA, WA, LogicalImm(mask, GPRSize::B32));
if ((mask & (FPSCR_ANY_X | FPSCR_ANY_E)) != 0) if ((mask & (FPSCR_ANY_X | FPSCR_ANY_E)) != 0)
UpdateFPExceptionSummary(WA); UpdateFPExceptionSummary(WA);
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
}
gpr.Unlock(WA);
if (inst.CRBD >= 29) if (inst.CRBD >= 29)
UpdateRoundingMode(); UpdateRoundingMode();
@ -887,7 +859,8 @@ void JitArm64::mtfsfix(UGeckoInstruction inst)
u8 shift = 28 - 4 * inst.CRFD; u8 shift = 28 - 4 * inst.CRFD;
u32 mask = 0xF << shift; u32 mask = 0xF << shift;
ARM64Reg WA = gpr.GetReg(); {
auto WA = gpr.GetScopedReg();
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
@ -902,17 +875,15 @@ void JitArm64::mtfsfix(UGeckoInstruction inst)
} }
else else
{ {
ARM64Reg WB = gpr.GetReg(); auto WB = gpr.GetScopedReg();
MOVZ(WB, imm); MOVZ(WB, imm);
BFI(WA, WB, shift, 4); BFI(WA, WB, shift, 4);
gpr.Unlock(WB);
} }
if ((mask & (FPSCR_FEX | FPSCR_VX | FPSCR_ANY_X | FPSCR_ANY_E)) != 0) if ((mask & (FPSCR_FEX | FPSCR_VX | FPSCR_ANY_X | FPSCR_ANY_E)) != 0)
UpdateFPExceptionSummary(WA); UpdateFPExceptionSummary(WA);
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
}
gpr.Unlock(WA);
// Field 7 contains NI and RN. // Field 7 contains NI and RN.
if (inst.CRFD == 7) if (inst.CRFD == 7)
@ -936,20 +907,19 @@ void JitArm64::mtfsfx(UGeckoInstruction inst)
if (mask == 0xFFFFFFFF) if (mask == 0xFFFFFFFF)
{ {
ARM64Reg VB = fpr.R(inst.FB, RegType::LowerPair); ARM64Reg VB = fpr.R(inst.FB, RegType::LowerPair);
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
m_float_emit.FMOV(WA, EncodeRegToSingle(VB)); m_float_emit.FMOV(WA, EncodeRegToSingle(VB));
UpdateFPExceptionSummary(WA); UpdateFPExceptionSummary(WA);
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
gpr.Unlock(WA);
} }
else if (mask != 0) else if (mask != 0)
{ {
ARM64Reg VB = fpr.R(inst.FB, RegType::LowerPair); ARM64Reg VB = fpr.R(inst.FB, RegType::LowerPair);
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ARM64Reg WB = gpr.GetReg(); {
auto WB = gpr.GetScopedReg();
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
m_float_emit.FMOV(WB, EncodeRegToSingle(VB)); m_float_emit.FMOV(WB, EncodeRegToSingle(VB));
@ -962,23 +932,18 @@ void JitArm64::mtfsfx(UGeckoInstruction inst)
} }
else else
{ {
ARM64Reg WC = gpr.GetReg(); auto WC = gpr.GetScopedReg();
MOVI2R(WC, mask); MOVI2R(WC, mask);
BIC(WA, WA, WC); BIC(WA, WA, WC);
AND(WB, WB, WC); AND(WB, WB, WC);
gpr.Unlock(WC);
} }
ORR(WA, WA, WB); ORR(WA, WA, WB);
}
gpr.Unlock(WB);
if ((mask & (FPSCR_FEX | FPSCR_VX | FPSCR_ANY_X | FPSCR_ANY_E)) != 0) if ((mask & (FPSCR_FEX | FPSCR_VX | FPSCR_ANY_X | FPSCR_ANY_E)) != 0)
UpdateFPExceptionSummary(WA); UpdateFPExceptionSummary(WA);
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
gpr.Unlock(WA);
} }
if (inst.FM & 1) if (inst.FM & 1)