mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
JitArm64_SystemRegisters: Use ScopedARM64Reg
This commit is contained in:
parent
be2b466743
commit
defb2d65a6
@ -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,114 +535,112 @@ 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();
|
|
||||||
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;
|
auto WB = gpr.GetScopedReg();
|
||||||
int bit = i ? 3 - (inst.CRBB & 3) : 3 - (inst.CRBA & 3);
|
ARM64Reg XB = EncodeRegTo64(WB);
|
||||||
ARM64Reg out = i ? XB : XA;
|
|
||||||
bool negate = i ? negateB : negateA;
|
|
||||||
|
|
||||||
ARM64Reg XC = gpr.CR(field);
|
// creqv or crnand or crnor
|
||||||
ARM64Reg WC = EncodeRegTo32(XC);
|
bool negateA = inst.SUBOP10 == 289 || inst.SUBOP10 == 225 || inst.SUBOP10 == 33;
|
||||||
switch (bit)
|
// 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
|
int field = i ? inst.CRBB >> 2 : inst.CRBA >> 2;
|
||||||
UBFX(out, XC, PowerPC::CR_EMU_SO_BIT, 1);
|
int bit = i ? 3 - (inst.CRBB & 3) : 3 - (inst.CRBA & 3);
|
||||||
if (negate)
|
ARM64Reg out = i ? XB : XA;
|
||||||
EOR(out, out, LogicalImm(1, GPRSize::B64));
|
bool negate = i ? negateB : negateA;
|
||||||
break;
|
|
||||||
|
|
||||||
case PowerPC::CR_EQ_BIT: // check bits 31-0 == 0
|
ARM64Reg XC = gpr.CR(field);
|
||||||
CMP(WC, ARM64Reg::WZR);
|
ARM64Reg WC = EncodeRegTo32(XC);
|
||||||
CSET(out, negate ? CC_NEQ : CC_EQ);
|
switch (bit)
|
||||||
break;
|
{
|
||||||
|
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
|
case PowerPC::CR_EQ_BIT: // check bits 31-0 == 0
|
||||||
CMP(XC, ARM64Reg::ZR);
|
CMP(WC, ARM64Reg::WZR);
|
||||||
CSET(out, negate ? CC_LE : CC_GT);
|
CSET(out, negate ? CC_NEQ : CC_EQ);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PowerPC::CR_LT_BIT: // check bit 62 set
|
case PowerPC::CR_GT_BIT: // check val > 0
|
||||||
UBFX(out, XC, PowerPC::CR_EMU_LT_BIT, 1);
|
CMP(XC, ARM64Reg::ZR);
|
||||||
if (negate)
|
CSET(out, negate ? CC_LE : CC_GT);
|
||||||
EOR(out, out, LogicalImm(1, GPRSize::B64));
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
case PowerPC::CR_LT_BIT: // check bit 62 set
|
||||||
ASSERT_MSG(DYNA_REC, false, "Invalid CR bit");
|
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
|
// Compute combined bit
|
||||||
switch (inst.SUBOP10)
|
switch (inst.SUBOP10)
|
||||||
{
|
{
|
||||||
case 33: // crnor: ~(A || B) == (~A && ~B)
|
case 33: // crnor: ~(A || B) == (~A && ~B)
|
||||||
case 129: // crandc: A && ~B
|
case 129: // crandc: A && ~B
|
||||||
case 257: // crand: A && B
|
case 257: // crand: A && B
|
||||||
AND(XA, XA, XB);
|
AND(XA, XA, XB);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 193: // crxor: A ^ B
|
case 193: // crxor: A ^ B
|
||||||
case 289: // creqv: ~(A ^ B) = ~A ^ B
|
case 289: // creqv: ~(A ^ B) = ~A ^ B
|
||||||
EOR(XA, XA, XB);
|
EOR(XA, XA, XB);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 225: // crnand: ~(A && B) == (~A || ~B)
|
case 225: // crnand: ~(A && B) == (~A || ~B)
|
||||||
case 417: // crorc: A || ~B
|
case 417: // crorc: A || ~B
|
||||||
case 449: // cror: A || B
|
case 449: // cror: A || B
|
||||||
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,17 +797,17 @@ 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));
|
||||||
|
|
||||||
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)
|
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();
|
|
||||||
|
|
||||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
|
||||||
|
|
||||||
if ((mask & FPSCR_ANY_X) != 0)
|
|
||||||
{
|
{
|
||||||
ARM64Reg WB = gpr.GetReg();
|
auto WA = gpr.GetScopedReg();
|
||||||
TST(WA, LogicalImm(mask, GPRSize::B32));
|
|
||||||
ORR(WB, WA, LogicalImm(1 << 31, GPRSize::B32));
|
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||||
CSEL(WA, WA, WB, CCFlags::CC_NEQ);
|
|
||||||
gpr.Unlock(WB);
|
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)
|
if (inst.CRBD >= 29)
|
||||||
UpdateRoundingMode();
|
UpdateRoundingMode();
|
||||||
@ -887,32 +859,31 @@ 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();
|
|
||||||
|
|
||||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
|
||||||
|
|
||||||
if (imm == 0xF)
|
|
||||||
{
|
{
|
||||||
ORR(WA, WA, LogicalImm(mask, GPRSize::B32));
|
auto WA = gpr.GetScopedReg();
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mask & (FPSCR_FEX | FPSCR_VX | FPSCR_ANY_X | FPSCR_ANY_E)) != 0)
|
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr));
|
||||||
UpdateFPExceptionSummary(WA);
|
|
||||||
STR(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.
|
// Field 7 contains NI and RN.
|
||||||
if (inst.CRFD == 7)
|
if (inst.CRFD == 7)
|
||||||
@ -936,49 +907,43 @@ 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();
|
|
||||||
|
|
||||||
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;
|
auto WB = gpr.GetScopedReg();
|
||||||
AND(WA, WA, LogicalImm(inverted_mask, GPRSize::B32));
|
|
||||||
AND(WB, WB, imm);
|
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)
|
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user