JitArm64_Integer: Use ScopedARM64Reg

This commit is contained in:
Sintendo 2024-06-16 17:25:40 +02:00
parent 62e1d7ad99
commit c0a0746d65

View File

@ -86,10 +86,9 @@ void JitArm64::LoadCarry()
{ {
case CarryFlag::InPPCState: case CarryFlag::InPPCState:
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
CMP(WA, 1); CMP(WA, 1);
gpr.Unlock(WA);
break; break;
} }
case CarryFlag::InHostCarry: case CarryFlag::InHostCarry:
@ -119,18 +118,16 @@ void JitArm64::FlushCarry()
} }
case CarryFlag::InHostCarry: case CarryFlag::InHostCarry:
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
CSET(WA, CC_CS); CSET(WA, CC_CS);
STRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); STRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
gpr.Unlock(WA);
break; break;
} }
case CarryFlag::ConstantTrue: case CarryFlag::ConstantTrue:
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
MOVI2R(WA, 1); MOVI2R(WA, 1);
STRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); STRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
gpr.Unlock(WA);
break; break;
} }
case CarryFlag::ConstantFalse: case CarryFlag::ConstantFalse:
@ -155,9 +152,10 @@ void JitArm64::reg_imm(u32 d, u32 a, u32 value, u32 (*do_op)(u32, u32),
else else
{ {
gpr.BindToRegister(d, d == a); gpr.BindToRegister(d, d == a);
ARM64Reg WA = gpr.GetReg(); {
(this->*op)(gpr.R(d), gpr.R(a), value, WA); auto WA = gpr.GetScopedReg();
gpr.Unlock(WA); (this->*op)(gpr.R(d), gpr.R(a), value, WA);
}
if (Rc) if (Rc)
ComputeRC0(gpr.R(d)); ComputeRC0(gpr.R(d));
@ -245,9 +243,8 @@ void JitArm64::addix(UGeckoInstruction inst)
{ {
gpr.BindToRegister(d, d == a); gpr.BindToRegister(d, d == a);
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ADDI2R(gpr.R(d), gpr.R(a), imm, WA); ADDI2R(gpr.R(d), gpr.R(a), imm, WA);
gpr.Unlock(WA);
} }
} }
else else
@ -544,9 +541,10 @@ void JitArm64::addx(UGeckoInstruction inst)
int imm_value = gpr.GetImm(imm_reg); int imm_value = gpr.GetImm(imm_reg);
gpr.BindToRegister(d, d == in_reg); gpr.BindToRegister(d, d == in_reg);
ARM64Reg WA = gpr.GetReg(); {
ADDI2R(gpr.R(d), gpr.R(in_reg), imm_value, WA); auto WA = gpr.GetScopedReg();
gpr.Unlock(WA); ADDI2R(gpr.R(d), gpr.R(in_reg), imm_value, WA);
}
if (inst.Rc) if (inst.Rc)
ComputeRC0(gpr.R(d)); ComputeRC0(gpr.R(d));
} }
@ -722,9 +720,8 @@ void JitArm64::cmpi(UGeckoInstruction inst)
if (B != 0) if (B != 0)
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
SUBI2R(CR, CR, B, EncodeRegTo64(WA)); SUBI2R(CR, CR, B, EncodeRegTo64(WA));
gpr.Unlock(WA);
} }
} }
@ -796,10 +793,9 @@ void JitArm64::rlwinmx_internal(UGeckoInstruction inst, u32 sh)
} }
else else
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
MOVI2R(WA, mask); MOVI2R(WA, mask);
AND(gpr.R(a), WA, gpr.R(s), ArithOption(gpr.R(s), ShiftType::ROR, 32 - sh)); AND(gpr.R(a), WA, gpr.R(s), ArithOption(gpr.R(s), ShiftType::ROR, 32 - sh));
gpr.Unlock(WA);
} }
if (inst.Rc) if (inst.Rc)
@ -829,11 +825,12 @@ void JitArm64::rlwnmx(UGeckoInstruction inst)
const u32 mask = MakeRotationMask(inst.MB, inst.ME); const u32 mask = MakeRotationMask(inst.MB, inst.ME);
gpr.BindToRegister(a, a == s || a == b); gpr.BindToRegister(a, a == s || a == b);
ARM64Reg WA = gpr.GetReg(); {
NEG(WA, gpr.R(b)); auto WA = gpr.GetScopedReg();
RORV(gpr.R(a), gpr.R(s), WA); NEG(WA, gpr.R(b));
ANDI2R(gpr.R(a), gpr.R(a), mask, WA); RORV(gpr.R(a), gpr.R(s), WA);
gpr.Unlock(WA); ANDI2R(gpr.R(a), gpr.R(a), mask, WA);
}
if (inst.Rc) if (inst.Rc)
ComputeRC0(gpr.R(a)); ComputeRC0(gpr.R(a));
@ -878,8 +875,8 @@ void JitArm64::srawix(UGeckoInstruction inst)
if (js.op->wantsCA) if (js.op->wantsCA)
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ARM64Reg dest = inplace_carry ? WA : ARM64Reg::WSP; ARM64Reg dest = inplace_carry ? ARM64Reg(WA) : ARM64Reg::WSP;
if (a != s) if (a != s)
{ {
ASR(RA, RS, amount); ASR(RA, RS, amount);
@ -901,7 +898,6 @@ void JitArm64::srawix(UGeckoInstruction inst)
CSINC(WA, ARM64Reg::WSP, ARM64Reg::WSP, CC_EQ); CSINC(WA, ARM64Reg::WSP, ARM64Reg::WSP, CC_EQ);
ComputeCarry(WA); ComputeCarry(WA);
} }
gpr.Unlock(WA);
} }
else else
{ {
@ -936,9 +932,10 @@ void JitArm64::addic(UGeckoInstruction inst)
else else
{ {
gpr.BindToRegister(d, d == a); gpr.BindToRegister(d, d == a);
ARM64Reg WA = gpr.GetReg(); {
CARRY_IF_NEEDED(ADDI2R, ADDSI2R, gpr.R(d), gpr.R(a), simm, WA); auto WA = gpr.GetScopedReg();
gpr.Unlock(WA); CARRY_IF_NEEDED(ADDI2R, ADDSI2R, gpr.R(d), gpr.R(a), simm, WA);
}
ComputeCarry(); ComputeCarry();
if (rc) if (rc)
@ -1037,12 +1034,10 @@ void JitArm64::mulli(UGeckoInstruction inst)
gpr.BindToRegister(d, allocate_reg); gpr.BindToRegister(d, allocate_reg);
// Reuse d to hold the immediate if possible, allocate a register otherwise. // Reuse d to hold the immediate if possible, allocate a register otherwise.
ARM64Reg WA = allocate_reg ? gpr.GetReg() : gpr.R(d); auto WA = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(gpr.R(d));
MOVI2R(WA, (u32)(s32)inst.SIMM_16); MOVI2R(WA, (u32)(s32)inst.SIMM_16);
MUL(gpr.R(d), gpr.R(a), WA); MUL(gpr.R(d), gpr.R(a), WA);
if (allocate_reg)
gpr.Unlock(WA);
} }
} }
@ -1137,16 +1132,16 @@ void JitArm64::addzex(UGeckoInstruction inst)
{ {
case CarryFlag::InPPCState: case CarryFlag::InPPCState:
{ {
gpr.BindToRegister(d, d == a); const bool allocate_reg = d == a;
ARM64Reg WA = d == a ? gpr.GetReg() : gpr.R(d); gpr.BindToRegister(d, allocate_reg);
{
auto WA = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(gpr.R(d));
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), WA);
}
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), WA);
ComputeCarry(); ComputeCarry();
if (d == a)
gpr.Unlock(WA);
break; break;
} }
case CarryFlag::InHostCarry: case CarryFlag::InHostCarry:
@ -1229,18 +1224,16 @@ void JitArm64::subfex(UGeckoInstruction inst)
{ {
case CarryFlag::InPPCState: case CarryFlag::InPPCState:
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
ADDI2R(gpr.R(d), WA, ~i + j, gpr.R(d)); ADDI2R(gpr.R(d), WA, ~i + j, gpr.R(d));
gpr.Unlock(WA);
break; break;
} }
case CarryFlag::InHostCarry: case CarryFlag::InHostCarry:
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
MOVI2R(WA, ~i + j); MOVI2R(WA, ~i + j);
ADC(gpr.R(d), WA, ARM64Reg::WZR); ADC(gpr.R(d), WA, ARM64Reg::WZR);
gpr.Unlock(WA);
break; break;
} }
case CarryFlag::ConstantTrue: case CarryFlag::ConstantTrue:
@ -1274,23 +1267,30 @@ void JitArm64::subfex(UGeckoInstruction inst)
else else
{ {
gpr.BindToRegister(d, d == a || d == b); gpr.BindToRegister(d, d == a || d == b);
ARM64Reg RB = mex ? gpr.GetReg() : gpr.R(b); {
if (mex) Arm64GPRCache::ScopedARM64Reg RB;
MOVI2R(RB, -1); if (mex)
{
RB = gpr.GetScopedReg();
MOVI2R(RB, -1);
}
else
{
RB = gpr.R(b);
}
if (js.carryFlag == CarryFlag::ConstantTrue) if (js.carryFlag == CarryFlag::ConstantTrue)
{ {
CARRY_IF_NEEDED(SUB, SUBS, gpr.R(d), RB, gpr.R(a)); CARRY_IF_NEEDED(SUB, SUBS, gpr.R(d), RB, gpr.R(a));
} }
else else
{ {
LoadCarry(); LoadCarry();
CARRY_IF_NEEDED(SBC, SBCS, gpr.R(d), RB, gpr.R(a)); CARRY_IF_NEEDED(SBC, SBCS, gpr.R(d), RB, gpr.R(a));
}
} }
ComputeCarry(); ComputeCarry();
if (mex)
gpr.Unlock(RB);
} }
if (inst.Rc) if (inst.Rc)
@ -1343,12 +1343,13 @@ void JitArm64::subfzex(UGeckoInstruction inst)
{ {
case CarryFlag::InPPCState: case CarryFlag::InPPCState:
{ {
ARM64Reg WA = gpr.GetReg(); {
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); auto WA = gpr.GetScopedReg();
MVN(gpr.R(d), gpr.R(a)); LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(d), WA); MVN(gpr.R(d), gpr.R(a));
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(d), WA);
}
ComputeCarry(); ComputeCarry();
gpr.Unlock(WA);
break; break;
} }
case CarryFlag::InHostCarry: case CarryFlag::InHostCarry:
@ -1394,21 +1395,20 @@ void JitArm64::subfic(UGeckoInstruction inst)
{ {
const bool will_read = d == a; const bool will_read = d == a;
const bool is_zero = imm == 0; const bool is_zero = imm == 0;
const bool allocate_reg = will_read && !is_zero;
gpr.BindToRegister(d, will_read); gpr.BindToRegister(d, will_read);
// d = imm - a // d = imm - a
ARM64Reg RD = gpr.R(d); ARM64Reg RD = gpr.R(d);
ARM64Reg WA = ARM64Reg::WZR;
if (!is_zero)
{ {
WA = will_read ? gpr.GetReg() : RD; Arm64GPRCache::ScopedARM64Reg WA(ARM64Reg::WZR);
MOVI2R(WA, imm); if (!is_zero)
} {
CARRY_IF_NEEDED(SUB, SUBS, RD, WA, gpr.R(a)); WA = will_read ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RD);
MOVI2R(WA, imm);
}
if (allocate_reg) CARRY_IF_NEEDED(SUB, SUBS, RD, WA, gpr.R(a));
gpr.Unlock(WA); }
ComputeCarry(); ComputeCarry();
} }
@ -1433,10 +1433,9 @@ void JitArm64::addex(UGeckoInstruction inst)
{ {
case CarryFlag::InPPCState: case CarryFlag::InPPCState:
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
ADDI2R(gpr.R(d), WA, i + j, gpr.R(d)); ADDI2R(gpr.R(d), WA, i + j, gpr.R(d));
gpr.Unlock(WA);
break; break;
} }
case CarryFlag::InHostCarry: case CarryFlag::InHostCarry:
@ -1477,23 +1476,30 @@ void JitArm64::addex(UGeckoInstruction inst)
else else
{ {
gpr.BindToRegister(d, d == a || d == b); gpr.BindToRegister(d, d == a || d == b);
ARM64Reg RB = mex ? gpr.GetReg() : gpr.R(b); {
if (mex) Arm64GPRCache::ScopedARM64Reg RB;
MOVI2R(RB, -1); if (mex)
{
RB = gpr.GetScopedReg();
MOVI2R(RB, -1);
}
else
{
RB = gpr.R(b);
}
if (js.carryFlag == CarryFlag::ConstantFalse) if (js.carryFlag == CarryFlag::ConstantFalse)
{ {
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), RB); CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), RB);
} }
else else
{ {
LoadCarry(); LoadCarry();
CARRY_IF_NEEDED(ADC, ADCS, gpr.R(d), gpr.R(a), RB); CARRY_IF_NEEDED(ADC, ADCS, gpr.R(d), gpr.R(a), RB);
}
} }
ComputeCarry(); ComputeCarry();
if (mex)
gpr.Unlock(RB);
} }
if (inst.Rc) if (inst.Rc)
@ -1575,7 +1581,7 @@ void JitArm64::divwux(UGeckoInstruction inst)
{ {
UnsignedMagic m = UnsignedDivisionConstants(divisor); UnsignedMagic m = UnsignedDivisionConstants(divisor);
ARM64Reg WI = allocate_reg ? gpr.GetReg() : RD; auto WI = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RD);
ARM64Reg XD = EncodeRegTo64(RD); ARM64Reg XD = EncodeRegTo64(RD);
MOVI2R(WI, m.multiplier); MOVI2R(WI, m.multiplier);
@ -1590,9 +1596,6 @@ void JitArm64::divwux(UGeckoInstruction inst)
} }
LSR(XD, XD, 32 + m.shift); LSR(XD, XD, 32 + m.shift);
if (allocate_reg)
gpr.Unlock(WI);
} }
if (inst.Rc) if (inst.Rc)
@ -1719,7 +1722,7 @@ void JitArm64::divwx(UGeckoInstruction inst)
ARM64Reg RA = gpr.R(a); ARM64Reg RA = gpr.R(a);
ARM64Reg RD = gpr.R(d); ARM64Reg RD = gpr.R(d);
ARM64Reg WA = allocate_reg ? gpr.GetReg() : RD; auto WA = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RD);
TST(RA, RA); TST(RA, RA);
ADDI2R(WA, RA, abs_val - 1, WA); ADDI2R(WA, RA, abs_val - 1, WA);
@ -1729,9 +1732,6 @@ void JitArm64::divwx(UGeckoInstruction inst)
NEG(RD, WA, ArithOption(WA, ShiftType::ASR, MathUtil::IntLog2(abs_val))); NEG(RD, WA, ArithOption(WA, ShiftType::ASR, MathUtil::IntLog2(abs_val)));
else else
ASR(RD, WA, MathUtil::IntLog2(abs_val)); ASR(RD, WA, MathUtil::IntLog2(abs_val));
if (allocate_reg)
gpr.Unlock(WA);
} }
else else
{ {
@ -1739,8 +1739,8 @@ void JitArm64::divwx(UGeckoInstruction inst)
SignedMagic m = SignedDivisionConstants(divisor); SignedMagic m = SignedDivisionConstants(divisor);
ARM64Reg RD = gpr.R(d); ARM64Reg RD = gpr.R(d);
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ARM64Reg WB = allocate_reg ? gpr.GetReg() : RD; auto WB = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RD);
ARM64Reg XD = EncodeRegTo64(RD); ARM64Reg XD = EncodeRegTo64(RD);
ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XA = EncodeRegTo64(WA);
@ -1776,10 +1776,6 @@ void JitArm64::divwx(UGeckoInstruction inst)
ASR(XD, XD, 32 + m.shift); ASR(XD, XD, 32 + m.shift);
ADD(RD, WA, RD); ADD(RD, WA, RD);
} }
gpr.Unlock(WA);
if (allocate_reg)
gpr.Unlock(WB);
} }
if (inst.Rc) if (inst.Rc)
@ -1982,8 +1978,7 @@ void JitArm64::srawx(UGeckoInstruction inst)
else else
{ {
gpr.BindToRegister(a, a == s); gpr.BindToRegister(a, a == s);
auto WA = gpr.GetScopedReg();
ARM64Reg WA = gpr.GetReg();
if (a != s) if (a != s)
{ {
@ -2009,8 +2004,6 @@ void JitArm64::srawx(UGeckoInstruction inst)
CSET(WA, CC_NEQ); CSET(WA, CC_NEQ);
ComputeCarry(WA); ComputeCarry(WA);
gpr.Unlock(WA);
} }
} }
else else
@ -2018,8 +2011,8 @@ void JitArm64::srawx(UGeckoInstruction inst)
const bool will_read = a == b || a == s; const bool will_read = a == b || a == s;
gpr.BindToRegister(a, will_read); gpr.BindToRegister(a, will_read);
const bool allocate_reg = will_read || js.op->wantsCA; auto WA =
ARM64Reg WA = allocate_reg ? gpr.GetReg() : gpr.R(a); will_read || js.op->wantsCA ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(gpr.R(a));
LSL(EncodeRegTo64(WA), EncodeRegTo64(gpr.R(s)), 32); LSL(EncodeRegTo64(WA), EncodeRegTo64(gpr.R(s)), 32);
ASRV(EncodeRegTo64(WA), EncodeRegTo64(WA), EncodeRegTo64(gpr.R(b))); ASRV(EncodeRegTo64(WA), EncodeRegTo64(WA), EncodeRegTo64(gpr.R(b)));
@ -2031,9 +2024,6 @@ void JitArm64::srawx(UGeckoInstruction inst)
CSET(WA, CC_NEQ); CSET(WA, CC_NEQ);
ComputeCarry(WA); ComputeCarry(WA);
} }
if (allocate_reg)
gpr.Unlock(WA);
} }
if (inst.Rc) if (inst.Rc)
@ -2088,10 +2078,9 @@ void JitArm64::rlwimix(UGeckoInstruction inst)
// No rotation // No rotation
// No mask inversion // No mask inversion
gpr.BindToRegister(a, true); gpr.BindToRegister(a, true);
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
UBFX(WA, gpr.R(s), lsb, width); UBFX(WA, gpr.R(s), lsb, width);
BFI(gpr.R(a), WA, lsb, width); BFI(gpr.R(a), WA, lsb, width);
gpr.Unlock(WA);
} }
else if (inst.SH && inst.MB <= inst.ME) else if (inst.SH && inst.MB <= inst.ME)
{ {
@ -2103,28 +2092,22 @@ void JitArm64::rlwimix(UGeckoInstruction inst)
} }
else else
{ {
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ROR(WA, gpr.R(s), (rot_dist + lsb) % 32); ROR(WA, gpr.R(s), (rot_dist + lsb) % 32);
BFI(gpr.R(a), WA, lsb, width); BFI(gpr.R(a), WA, lsb, width);
gpr.Unlock(WA);
} }
} }
else else
{ {
gpr.BindToRegister(a, true); gpr.BindToRegister(a, true);
const bool allocate_reg = a == s;
ARM64Reg RA = gpr.R(a); ARM64Reg RA = gpr.R(a);
ARM64Reg WA = gpr.GetReg(); auto WA = gpr.GetScopedReg();
ARM64Reg WB = allocate_reg ? gpr.GetReg() : RA; auto WB = a == s ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RA);
MOVI2R(WA, mask); MOVI2R(WA, mask);
BIC(WB, RA, WA); BIC(WB, RA, WA);
AND(WA, WA, gpr.R(s), ArithOption(gpr.R(s), ShiftType::ROR, rot_dist)); AND(WA, WA, gpr.R(s), ArithOption(gpr.R(s), ShiftType::ROR, rot_dist));
ORR(RA, WB, WA); ORR(RA, WB, WA);
gpr.Unlock(WA);
if (allocate_reg)
gpr.Unlock(WB);
} }
if (inst.Rc) if (inst.Rc)