diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index 8ffa1b84aa..df4ea4931a 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp @@ -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 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. - ARM64Reg WA = gpr.GetReg(); + auto WA = gpr.GetScopedReg(); ARM64Reg XA = EncodeRegTo64(WA); ORR(XA, reg, LogicalImm(1ULL << 63, GPRSize::B64)); CMP(reg, ARM64Reg::ZR); CSEL(reg, reg, XA, CC_NEQ); - gpr.Unlock(WA); } void JitArm64::UpdateFPExceptionSummary(ARM64Reg fpscr) { - ARM64Reg WA = gpr.GetReg(); + auto WA = gpr.GetScopedReg(); // fpscr.VX = (fpscr & FPSCR_VX_ANY) != 0 MOVI2R(WA, FPSCR_VX_ANY); @@ -71,8 +70,6 @@ void JitArm64::UpdateFPExceptionSummary(ARM64Reg fpscr) TST(WA, fpscr, ArithOption(fpscr, ShiftType::LSR, 22)); CSET(WA, CCFlags::CC_NEQ); BFI(fpscr, WA, MathUtil::IntLog2(FPSCR_FEX), 1); - - gpr.Unlock(WA); } void JitArm64::UpdateRoundingMode() @@ -135,7 +132,7 @@ void JitArm64::mcrxr(UGeckoInstruction inst) JITDISABLE(bJITSystemRegistersOff); gpr.BindCRToRegister(inst.CRFD, false); - ARM64Reg WA = gpr.GetReg(); + auto WA = gpr.GetScopedReg(); ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XB = gpr.CR(inst.CRFD); ARM64Reg WB = EncodeRegTo32(XB); @@ -155,8 +152,6 @@ void JitArm64::mcrxr(UGeckoInstruction inst) // Clear XER[0-3] static_assert(PPCSTATE_OFF(xer_ca) + 1 == PPCSTATE_OFF(xer_so_ov)); STRH(IndexType::Unsigned, ARM64Reg::WZR, PPC_REG, PPCSTATE_OFF(xer_ca)); - - gpr.Unlock(WA); } void JitArm64::mfsr(UGeckoInstruction inst) @@ -186,14 +181,12 @@ void JitArm64::mfsrin(UGeckoInstruction inst) ARM64Reg RB = gpr.R(b); ARM64Reg RD = gpr.R(d); - ARM64Reg index = gpr.GetReg(); + auto index = gpr.GetScopedReg(); ARM64Reg addr = EncodeRegTo64(RD); UBFM(index, RB, 28, 31); ADDI2R(addr, PPC_REG, PPCSTATE_OFF_SR(0), addr); LDR(RD, addr, ArithOption(EncodeRegTo64(index), true)); - - gpr.Unlock(index); } void JitArm64::mtsrin(UGeckoInstruction inst) @@ -206,14 +199,12 @@ void JitArm64::mtsrin(UGeckoInstruction inst) ARM64Reg RB = gpr.R(b); ARM64Reg RD = gpr.R(d); - ARM64Reg index = gpr.GetReg(); - ARM64Reg addr = gpr.GetReg(); + auto index = gpr.GetScopedReg(); + auto addr = gpr.GetScopedReg(); UBFM(index, RB, 28, 31); ADDI2R(EncodeRegTo64(addr), PPC_REG, PPCSTATE_OFF_SR(0), EncodeRegTo64(addr)); STR(RD, EncodeRegTo64(addr), ArithOption(EncodeRegTo64(index), true)); - - gpr.Unlock(index, addr); } void JitArm64::twx(UGeckoInstruction inst) @@ -223,7 +214,7 @@ void JitArm64::twx(UGeckoInstruction inst) s32 a = inst.RA; - ARM64Reg WA = gpr.GetReg(); + auto WA = gpr.GetScopedReg(); if (inst.OPCD == 3) // twi { @@ -278,8 +269,6 @@ void JitArm64::twx(UGeckoInstruction inst) fpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG); WriteExit(js.compilerPC + 4); } - - gpr.Unlock(WA); } void JitArm64::mfspr(UGeckoInstruction inst) @@ -294,19 +283,19 @@ void JitArm64::mfspr(UGeckoInstruction inst) case SPR_TL: case SPR_TU: { - ARM64Reg Wg = gpr.GetReg(); + auto Wg = gpr.GetScopedReg(); ARM64Reg Xg = EncodeRegTo64(Wg); - ARM64Reg Wresult = gpr.GetReg(); + auto Wresult = gpr.GetScopedReg(); ARM64Reg Xresult = EncodeRegTo64(Wresult); - ARM64Reg WA = gpr.GetReg(); - ARM64Reg WB = gpr.GetReg(); + auto WA = gpr.GetScopedReg(); + auto WB = gpr.GetScopedReg(); ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XB = EncodeRegTo64(WB); - ARM64Reg VC = fpr.GetReg(); - ARM64Reg VD = fpr.GetReg(); + auto VC = fpr.GetScopedReg(); + auto VD = fpr.GetScopedReg(); ARM64Reg SC = EncodeRegToSingle(VC); ARM64Reg SD = EncodeRegToSingle(VD); @@ -371,8 +360,6 @@ void JitArm64::mfspr(UGeckoInstruction inst) else LSR(EncodeRegTo64(gpr.R(n)), Xresult, 32); - gpr.Unlock(Wg, Wresult, WA, WB); - fpr.Unlock(VC, VD); break; } } @@ -381,22 +368,18 @@ void JitArm64::mfspr(UGeckoInstruction inst) LSR(EncodeRegTo64(gpr.R(d)), Xresult, 32); else MOV(gpr.R(d), Wresult); - - gpr.Unlock(Wg, Wresult, WA, WB); - fpr.Unlock(VC, VD); } break; case SPR_XER: { gpr.BindToRegister(d, false); ARM64Reg RD = gpr.R(d); - ARM64Reg WA = gpr.GetReg(); + auto WA = gpr.GetScopedReg(); LDRH(IndexType::Unsigned, RD, PPC_REG, PPCSTATE_OFF(xer_stringctrl)); LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); ORR(RD, RD, WA, ArithOption(WA, ShiftType::LSL, XER_CA_SHIFT)); LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_so_ov)); ORR(RD, RD, WA, ArithOption(WA, ShiftType::LSL, XER_OV_SHIFT)); - gpr.Unlock(WA); } break; case SPR_WPAR: @@ -462,14 +445,13 @@ void JitArm64::mtspr(UGeckoInstruction inst) case SPR_XER: { ARM64Reg RD = gpr.R(inst.RD); - ARM64Reg WA = gpr.GetReg(); + auto WA = gpr.GetScopedReg(); AND(WA, RD, LogicalImm(0xFFFFFF7F, GPRSize::B32)); STRH(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_stringctrl)); UBFM(WA, RD, XER_CA_SHIFT, XER_CA_SHIFT + 1); STRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); 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)); - gpr.Unlock(WA); } break; default: @@ -553,114 +535,112 @@ void JitArm64::crXXX(UGeckoInstruction inst) return; } - ARM64Reg WA = gpr.GetReg(); + auto WA = gpr.GetScopedReg(); ARM64Reg XA = EncodeRegTo64(WA); - ARM64Reg WB = gpr.GetReg(); - ARM64Reg XB = EncodeRegTo64(WB); - - // creqv or crnand or crnor - bool negateA = inst.SUBOP10 == 289 || inst.SUBOP10 == 225 || inst.SUBOP10 == 33; - // crandc or crorc or crnand or crnor - bool negateB = - inst.SUBOP10 == 129 || inst.SUBOP10 == 417 || inst.SUBOP10 == 225 || inst.SUBOP10 == 33; - - // GetCRFieldBit - for (int i = 0; i < 2; i++) { - int field = i ? inst.CRBB >> 2 : inst.CRBA >> 2; - int bit = i ? 3 - (inst.CRBB & 3) : 3 - (inst.CRBA & 3); - ARM64Reg out = i ? XB : XA; - bool negate = i ? negateB : negateA; + auto WB = gpr.GetScopedReg(); + ARM64Reg XB = EncodeRegTo64(WB); - ARM64Reg XC = gpr.CR(field); - ARM64Reg WC = EncodeRegTo32(XC); - switch (bit) + // creqv or crnand or crnor + bool negateA = inst.SUBOP10 == 289 || inst.SUBOP10 == 225 || inst.SUBOP10 == 33; + // crandc or crorc or crnand or crnor + bool negateB = + inst.SUBOP10 == 129 || inst.SUBOP10 == 417 || inst.SUBOP10 == 225 || inst.SUBOP10 == 33; + + // GetCRFieldBit + for (int i = 0; i < 2; i++) { - case PowerPC::CR_SO_BIT: // check bit 59 set - UBFX(out, XC, PowerPC::CR_EMU_SO_BIT, 1); - if (negate) - EOR(out, out, LogicalImm(1, GPRSize::B64)); - break; + int field = i ? inst.CRBB >> 2 : inst.CRBA >> 2; + int bit = i ? 3 - (inst.CRBB & 3) : 3 - (inst.CRBA & 3); + ARM64Reg out = i ? XB : XA; + bool negate = i ? negateB : negateA; - case PowerPC::CR_EQ_BIT: // check bits 31-0 == 0 - CMP(WC, ARM64Reg::WZR); - CSET(out, negate ? CC_NEQ : CC_EQ); - break; + ARM64Reg XC = gpr.CR(field); + ARM64Reg WC = EncodeRegTo32(XC); + switch (bit) + { + case PowerPC::CR_SO_BIT: // check bit 59 set + UBFX(out, XC, PowerPC::CR_EMU_SO_BIT, 1); + if (negate) + EOR(out, out, LogicalImm(1, GPRSize::B64)); + break; - case PowerPC::CR_GT_BIT: // check val > 0 - CMP(XC, ARM64Reg::ZR); - CSET(out, negate ? CC_LE : CC_GT); - break; + case PowerPC::CR_EQ_BIT: // check bits 31-0 == 0 + CMP(WC, ARM64Reg::WZR); + CSET(out, negate ? CC_NEQ : CC_EQ); + break; - case PowerPC::CR_LT_BIT: // check bit 62 set - UBFX(out, XC, PowerPC::CR_EMU_LT_BIT, 1); - if (negate) - EOR(out, out, LogicalImm(1, GPRSize::B64)); - break; + case PowerPC::CR_GT_BIT: // check val > 0 + CMP(XC, ARM64Reg::ZR); + CSET(out, negate ? CC_LE : CC_GT); + break; - default: - ASSERT_MSG(DYNA_REC, false, "Invalid CR bit"); + case PowerPC::CR_LT_BIT: // check bit 62 set + UBFX(out, XC, PowerPC::CR_EMU_LT_BIT, 1); + if (negate) + EOR(out, out, LogicalImm(1, GPRSize::B64)); + break; + + default: + ASSERT_MSG(DYNA_REC, false, "Invalid CR bit"); + } } - } - // Compute combined bit - switch (inst.SUBOP10) - { - case 33: // crnor: ~(A || B) == (~A && ~B) - case 129: // crandc: A && ~B - case 257: // crand: A && B - AND(XA, XA, XB); - break; + // Compute combined bit + switch (inst.SUBOP10) + { + case 33: // crnor: ~(A || B) == (~A && ~B) + case 129: // crandc: A && ~B + case 257: // crand: A && B + AND(XA, XA, XB); + break; - case 193: // crxor: A ^ B - case 289: // creqv: ~(A ^ B) = ~A ^ B - EOR(XA, XA, XB); - break; + case 193: // crxor: A ^ B + case 289: // creqv: ~(A ^ B) = ~A ^ B + EOR(XA, XA, XB); + break; - case 225: // crnand: ~(A && B) == (~A || ~B) - case 417: // crorc: A || ~B - case 449: // cror: A || B - ORR(XA, XA, XB); - break; + case 225: // crnand: ~(A && B) == (~A || ~B) + case 417: // crorc: A || ~B + case 449: // cror: A || B + ORR(XA, XA, XB); + break; + } } // Store result bit in CRBD int field = inst.CRBD >> 2; int bit = 3 - (inst.CRBD & 3); - gpr.Unlock(WB); - WB = ARM64Reg::INVALID_REG; gpr.BindCRToRegister(field, true); - XB = gpr.CR(field); + ARM64Reg CR = gpr.CR(field); if (bit != PowerPC::CR_GT_BIT) - FixGTBeforeSettingCRFieldBit(XB); + FixGTBeforeSettingCRFieldBit(CR); switch (bit) { 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; 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)); - ORR(XB, XB, XA); + ORR(CR, CR, XA); break; case PowerPC::CR_GT_BIT: // set bit 63 to !input EOR(XA, XA, LogicalImm(1, GPRSize::B64)); - BFI(XB, XA, 63, 1); + BFI(CR, XA, 63, 1); break; 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; } - ORR(XB, XB, LogicalImm(1ULL << 32, GPRSize::B64)); - - gpr.Unlock(WA); + ORR(CR, CR, LogicalImm(1ULL << 32, GPRSize::B64)); } void JitArm64::mfcr(UGeckoInstruction inst) @@ -670,8 +650,8 @@ void JitArm64::mfcr(UGeckoInstruction inst) gpr.BindToRegister(inst.RD, false); ARM64Reg WA = gpr.R(inst.RD); - ARM64Reg WB = gpr.GetReg(); - ARM64Reg WC = gpr.GetReg(); + auto WB = gpr.GetScopedReg(); + auto WC = gpr.GetScopedReg(); ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XB = EncodeRegTo64(WB); ARM64Reg XC = EncodeRegTo64(WC); @@ -716,8 +696,6 @@ void JitArm64::mfcr(UGeckoInstruction inst) else if (!js.op->crInUse[i]) gpr.StoreCRRegisters(BitSet8{i}, WC); } - - gpr.Unlock(WB, WC); } void JitArm64::mtcrf(UGeckoInstruction inst) @@ -729,7 +707,7 @@ void JitArm64::mtcrf(UGeckoInstruction inst) if (crm != 0) { ARM64Reg RS = gpr.R(inst.RS); - ARM64Reg WB = gpr.GetReg(); + auto WB = gpr.GetScopedReg(); ARM64Reg XB = EncodeRegTo64(WB); MOVP2R(XB, PowerPC::ConditionRegister::s_crTable.data()); for (int i = 0; i < 8; ++i) @@ -753,7 +731,6 @@ void JitArm64::mtcrf(UGeckoInstruction inst) LDR(CR, XB, ArithOption(CR, true)); } } - gpr.Unlock(WB); } } @@ -771,7 +748,7 @@ void JitArm64::mcrfs(UGeckoInstruction inst) gpr.BindCRToRegister(field, false); ARM64Reg CR = gpr.CR(field); - ARM64Reg WA = gpr.GetReg(); + auto WA = gpr.GetScopedReg(); ARM64Reg WCR = EncodeRegTo32(CR); ARM64Reg XA = EncodeRegTo64(WA); @@ -789,8 +766,6 @@ void JitArm64::mcrfs(UGeckoInstruction inst) MOVP2R(XA, PowerPC::ConditionRegister::s_crTable.data()); LDR(CR, XA, ArithOption(CR, true)); - - gpr.Unlock(WA); } void JitArm64::mffsx(UGeckoInstruction inst) @@ -799,7 +774,7 @@ void JitArm64::mffsx(UGeckoInstruction inst) JITDISABLE(bJITSystemRegistersOff); FALLBACK_IF(inst.Rc); - ARM64Reg WA = gpr.GetReg(); + auto WA = gpr.GetScopedReg(); ARM64Reg XA = EncodeRegTo64(WA); 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)); m_float_emit.FMOV(EncodeRegToDouble(VD), XA); - - gpr.Unlock(WA); } void JitArm64::mtfsb0x(UGeckoInstruction inst) @@ -824,17 +797,17 @@ void JitArm64::mtfsb0x(UGeckoInstruction inst) if (mask == FPSCR_FEX || mask == FPSCR_VX) 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)); - AND(WA, WA, LogicalImm(inverted_mask, GPRSize::B32)); + AND(WA, WA, LogicalImm(inverted_mask, GPRSize::B32)); - if ((mask & (FPSCR_ANY_X | FPSCR_ANY_E)) != 0) - UpdateFPExceptionSummary(WA); - STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); - - gpr.Unlock(WA); + if ((mask & (FPSCR_ANY_X | FPSCR_ANY_E)) != 0) + UpdateFPExceptionSummary(WA); + STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); + } if (inst.CRBD >= 29) UpdateRoundingMode(); @@ -852,25 +825,24 @@ void JitArm64::mtfsb1x(UGeckoInstruction inst) if (mask == FPSCR_FEX || mask == FPSCR_VX) return; - ARM64Reg WA = gpr.GetReg(); - - LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); - - if ((mask & FPSCR_ANY_X) != 0) { - ARM64Reg WB = gpr.GetReg(); - TST(WA, LogicalImm(mask, GPRSize::B32)); - ORR(WB, WA, LogicalImm(1 << 31, GPRSize::B32)); - CSEL(WA, WA, WB, CCFlags::CC_NEQ); - gpr.Unlock(WB); + auto WA = gpr.GetScopedReg(); + + LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); + + if ((mask & FPSCR_ANY_X) != 0) + { + auto WB = gpr.GetScopedReg(); + TST(WA, LogicalImm(mask, GPRSize::B32)); + ORR(WB, WA, LogicalImm(1 << 31, GPRSize::B32)); + CSEL(WA, WA, WB, CCFlags::CC_NEQ); + } + ORR(WA, WA, LogicalImm(mask, GPRSize::B32)); + + if ((mask & (FPSCR_ANY_X | FPSCR_ANY_E)) != 0) + UpdateFPExceptionSummary(WA); + STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); } - ORR(WA, WA, LogicalImm(mask, GPRSize::B32)); - - if ((mask & (FPSCR_ANY_X | FPSCR_ANY_E)) != 0) - UpdateFPExceptionSummary(WA); - STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); - - gpr.Unlock(WA); if (inst.CRBD >= 29) UpdateRoundingMode(); @@ -887,32 +859,31 @@ void JitArm64::mtfsfix(UGeckoInstruction inst) u8 shift = 28 - 4 * inst.CRFD; u32 mask = 0xF << shift; - ARM64Reg WA = gpr.GetReg(); - - LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); - - if (imm == 0xF) { - ORR(WA, WA, LogicalImm(mask, GPRSize::B32)); - } - else if (imm == 0x0) - { - const u32 inverted_mask = ~mask; - AND(WA, WA, LogicalImm(inverted_mask, GPRSize::B32)); - } - else - { - ARM64Reg WB = gpr.GetReg(); - MOVZ(WB, imm); - BFI(WA, WB, shift, 4); - gpr.Unlock(WB); - } + auto WA = gpr.GetScopedReg(); - if ((mask & (FPSCR_FEX | FPSCR_VX | FPSCR_ANY_X | FPSCR_ANY_E)) != 0) - UpdateFPExceptionSummary(WA); - STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); + LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); - gpr.Unlock(WA); + if (imm == 0xF) + { + ORR(WA, WA, LogicalImm(mask, GPRSize::B32)); + } + else if (imm == 0x0) + { + const u32 inverted_mask = ~mask; + AND(WA, WA, LogicalImm(inverted_mask, GPRSize::B32)); + } + else + { + auto WB = gpr.GetScopedReg(); + MOVZ(WB, imm); + BFI(WA, WB, shift, 4); + } + + if ((mask & (FPSCR_FEX | FPSCR_VX | FPSCR_ANY_X | FPSCR_ANY_E)) != 0) + UpdateFPExceptionSummary(WA); + STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); + } // Field 7 contains NI and RN. if (inst.CRFD == 7) @@ -936,49 +907,43 @@ void JitArm64::mtfsfx(UGeckoInstruction inst) if (mask == 0xFFFFFFFF) { ARM64Reg VB = fpr.R(inst.FB, RegType::LowerPair); - ARM64Reg WA = gpr.GetReg(); + auto WA = gpr.GetScopedReg(); m_float_emit.FMOV(WA, EncodeRegToSingle(VB)); UpdateFPExceptionSummary(WA); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); - - gpr.Unlock(WA); } else if (mask != 0) { ARM64Reg VB = fpr.R(inst.FB, RegType::LowerPair); - ARM64Reg WA = gpr.GetReg(); - ARM64Reg WB = gpr.GetReg(); - - LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); - m_float_emit.FMOV(WB, EncodeRegToSingle(VB)); - - if (LogicalImm imm = LogicalImm(mask, GPRSize::B32)) + auto WA = gpr.GetScopedReg(); { - const u32 inverted_mask = ~mask; - AND(WA, WA, LogicalImm(inverted_mask, GPRSize::B32)); - AND(WB, WB, imm); + auto WB = gpr.GetScopedReg(); + + LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); + m_float_emit.FMOV(WB, EncodeRegToSingle(VB)); + + if (LogicalImm imm = LogicalImm(mask, GPRSize::B32)) + { + const u32 inverted_mask = ~mask; + AND(WA, WA, LogicalImm(inverted_mask, GPRSize::B32)); + AND(WB, WB, imm); + } + else + { + auto WC = gpr.GetScopedReg(); + + MOVI2R(WC, mask); + BIC(WA, WA, WC); + AND(WB, WB, WC); + } + ORR(WA, WA, WB); } - else - { - ARM64Reg WC = gpr.GetReg(); - - MOVI2R(WC, mask); - BIC(WA, WA, WC); - AND(WB, WB, WC); - - gpr.Unlock(WC); - } - ORR(WA, WA, WB); - - gpr.Unlock(WB); if ((mask & (FPSCR_FEX | FPSCR_VX | FPSCR_ANY_X | FPSCR_ANY_E)) != 0) UpdateFPExceptionSummary(WA); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); - - gpr.Unlock(WA); } if (inst.FM & 1)