Merge pull request #4392 from degasus/master

JitArm64: Get rid of MOVI2R as much as possible
This commit is contained in:
Markus Wick 2016-10-28 08:35:17 +02:00 committed by GitHub
commit a56e39a3a9
9 changed files with 167 additions and 345 deletions

View File

@ -2055,6 +2055,28 @@ void ARM64XEmitter::MOVI2R(ARM64Reg Rd, u64 imm, bool optimize)
}
}
bool ARM64XEmitter::MOVI2R2(ARM64Reg Rd, u64 imm1, u64 imm2)
{
// TODO: Also optimize for performance, not just for code size.
u8* start_pointer = GetWritableCodePtr();
MOVI2R(Rd, imm1);
int size1 = GetCodePtr() - start_pointer;
SetCodePtrUnsafe(start_pointer);
MOVI2R(Rd, imm2);
int size2 = GetCodePtr() - start_pointer;
SetCodePtrUnsafe(start_pointer);
bool element = size1 > size2;
MOVI2R(Rd, element ? imm2 : imm1);
return element;
}
void ARM64XEmitter::ABI_PushRegisters(BitSet32 registers)
{
int num_regs = registers.Count();
@ -4127,58 +4149,115 @@ void ARM64XEmitter::ANDSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
}
}
void ARM64XEmitter::ADDI2R_internal(ARM64Reg Rd, ARM64Reg Rn, u64 imm, bool negative, bool flags,
ARM64Reg scratch)
{
auto addi = [this](ARM64Reg Rd, ARM64Reg Rn, u64 imm, bool shift, bool negative, bool flags) {
switch ((negative << 1) | flags)
{
case 0:
ADD(Rd, Rn, imm, shift);
break;
case 1:
ADDS(Rd, Rn, imm, shift);
break;
case 2:
SUB(Rd, Rn, imm, shift);
break;
case 3:
SUBS(Rd, Rn, imm, shift);
break;
}
};
bool has_scratch = scratch != INVALID_REG;
u64 imm_neg = Is64Bit(Rd) ? -imm : -imm & 0xFFFFFFFFuLL;
bool neg_neg = negative ? false : true;
// Fast paths, aarch64 immediate instructions
// Try them all first
if (imm <= 0xFFF)
{
addi(Rd, Rn, imm, false, negative, flags);
return;
}
if (imm <= 0xFFFFFF && (imm & 0xFFF) == 0)
{
addi(Rd, Rn, imm >> 12, true, negative, flags);
return;
}
if (imm_neg <= 0xFFF)
{
addi(Rd, Rn, imm_neg, false, neg_neg, flags);
return;
}
if (imm_neg <= 0xFFFFFF && (imm_neg & 0xFFF) == 0)
{
addi(Rd, Rn, imm_neg >> 12, true, neg_neg, flags);
return;
}
// ADD+ADD is slower than MOVK+ADD, but inplace.
// But it supports a few more bits, so use it to avoid MOVK+MOVK+ADD.
// As this splits the addition in two parts, this must not be done on setting flags.
if (!flags && (imm >= 0x10000u || !has_scratch) && imm < 0x1000000u)
{
addi(Rd, Rn, imm & 0xFFF, false, negative, false);
addi(Rd, Rd, imm >> 12, true, negative, false);
return;
}
if (!flags && (imm_neg >= 0x10000u || !has_scratch) && imm_neg < 0x1000000u)
{
addi(Rd, Rn, imm_neg & 0xFFF, false, neg_neg, false);
addi(Rd, Rd, imm_neg >> 12, true, neg_neg, false);
return;
}
_assert_msg_(DYNA_REC, has_scratch,
"ADDI2R - failed to construct arithmetic immediate value from %08x, need scratch",
(u32)imm);
negative ^= MOVI2R2(scratch, imm, imm_neg);
switch ((negative << 1) | flags)
{
case 0:
ADD(Rd, Rn, scratch);
break;
case 1:
ADDS(Rd, Rn, scratch);
break;
case 2:
SUB(Rd, Rn, scratch);
break;
case 3:
SUBS(Rd, Rn, scratch);
break;
}
}
void ARM64XEmitter::ADDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
{
u32 val;
bool shift;
if (IsImmArithmetic(imm, &val, &shift))
{
ADD(Rd, Rn, val, shift);
}
else
{
_assert_msg_(DYNA_REC, scratch != INVALID_REG,
"ADDI2R - failed to construct arithmetic immediate value from %08x, need scratch",
(u32)imm);
MOVI2R(scratch, imm);
ADD(Rd, Rn, scratch);
}
ADDI2R_internal(Rd, Rn, imm, false, false, scratch);
}
void ARM64XEmitter::ADDSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
{
ADDI2R_internal(Rd, Rn, imm, false, true, scratch);
}
void ARM64XEmitter::SUBI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
{
u32 val;
bool shift;
if (IsImmArithmetic(imm, &val, &shift))
{
SUB(Rd, Rn, val, shift);
}
else
{
_assert_msg_(DYNA_REC, scratch != INVALID_REG,
"SUBI2R - failed to construct arithmetic immediate value from %08x, need scratch",
(u32)imm);
MOVI2R(scratch, imm);
SUB(Rd, Rn, scratch);
}
ADDI2R_internal(Rd, Rn, imm, true, false, scratch);
}
void ARM64XEmitter::SUBSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
{
ADDI2R_internal(Rd, Rn, imm, true, true, scratch);
}
void ARM64XEmitter::CMPI2R(ARM64Reg Rn, u64 imm, ARM64Reg scratch)
{
u32 val;
bool shift;
if (IsImmArithmetic(imm, &val, &shift))
{
CMP(Rn, val, shift);
}
else
{
_assert_msg_(DYNA_REC, scratch != INVALID_REG,
"CMPI2R - failed to construct arithmetic immediate value from %08x, need scratch",
(u32)imm);
MOVI2R(scratch, imm);
CMP(Rn, scratch);
}
ADDI2R_internal(Is64Bit(Rn) ? ZR : WZR, Rn, imm, true, true, scratch);
}
bool ARM64XEmitter::TryADDI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm)
@ -4320,21 +4399,4 @@ void ARM64FloatEmitter::MOVI2FDUP(ARM64Reg Rd, float value, ARM64Reg scratch)
DUP(32, Rd, Rd, 0);
}
void ARM64XEmitter::SUBSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
{
u32 val;
bool shift;
if (IsImmArithmetic(imm, &val, &shift))
{
SUBS(Rd, Rn, val, shift);
}
else
{
_assert_msg_(DYNA_REC, scratch != INVALID_REG,
"ANDSI2R - failed to construct immediate value from %08x, need scratch", (u32)imm);
MOVI2R(scratch, imm);
SUBS(Rd, Rn, scratch);
}
}
} // namespace

View File

@ -835,6 +835,7 @@ public:
// Wrapper around MOVZ+MOVK
void MOVI2R(ARM64Reg Rd, u64 imm, bool optimize = true);
bool MOVI2R2(ARM64Reg Rd, u64 imm1, u64 imm2);
template <class P>
void MOVP2R(ARM64Reg Rd, P* ptr)
{
@ -854,7 +855,10 @@ public:
void EORI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch = INVALID_REG);
void CMPI2R(ARM64Reg Rn, u64 imm, ARM64Reg scratch = INVALID_REG);
void ADDI2R_internal(ARM64Reg Rd, ARM64Reg Rn, u64 imm, bool negative, bool flags,
ARM64Reg scratch);
void ADDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch = INVALID_REG);
void ADDSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch = INVALID_REG);
void SUBI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch = INVALID_REG);
void SUBSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch = INVALID_REG);

View File

@ -183,20 +183,10 @@ void JitArm64::DoDownCount()
{
ARM64Reg WA = gpr.GetReg();
LDR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(downcount));
if (js.downcountAmount < 4096) // We can enlarge this if we used rotations
{
SUBS(WA, WA, js.downcountAmount);
STR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(downcount));
}
else
{
ARM64Reg WB = gpr.GetReg();
MOVI2R(WB, js.downcountAmount);
SUBS(WA, WA, WB);
STR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(downcount));
gpr.Unlock(WB);
}
gpr.Unlock(WA);
ARM64Reg WB = gpr.GetReg();
SUBSI2R(WA, WA, js.downcountAmount, WB);
STR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(downcount));
gpr.Unlock(WA, WB);
}
// Exits

View File

@ -54,17 +54,14 @@ void JitArm64::rfi(UGeckoInstruction inst)
ARM64Reg WB = gpr.GetReg();
ARM64Reg WC = gpr.GetReg();
MOVI2R(WA, (~mask) & clearMSR13);
MOVI2R(WB, mask & clearMSR13);
LDR(INDEX_UNSIGNED, WC, PPC_REG, PPCSTATE_OFF(msr));
AND(WC, WC, WA); // rD = Masked MSR
ANDI2R(WC, WC, (~mask) & clearMSR13, WA); // rD = Masked MSR
LDR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(spr[SPR_SRR1])); // rB contains SRR1 here
AND(WA, WA, WB); // rB contains masked SRR1 here
ORR(WA, WA, WC); // rB = Masked MSR OR masked SRR1
ANDI2R(WA, WA, mask & clearMSR13, WB); // rB contains masked SRR1 here
ORR(WA, WA, WC); // rB = Masked MSR OR masked SRR1
STR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(msr)); // STR rB in to rA

View File

@ -154,29 +154,9 @@ void JitArm64::addix(UGeckoInstruction inst)
{
gpr.BindToRegister(d, d == a);
if (imm < 4096)
{
ADD(gpr.R(d), gpr.R(a), imm);
}
else if (imm % 4096 == 0 && imm < 4096 * 4096)
{
ADD(gpr.R(d), gpr.R(a), imm / 4096, true);
}
else if (imm_neg < 4096)
{
SUB(gpr.R(d), gpr.R(a), imm_neg);
}
else if (imm_neg % 4096 == 0 && imm_neg < 4096 * 4096)
{
SUB(gpr.R(d), gpr.R(a), imm_neg / 4096, true);
}
else
{
ARM64Reg WA = gpr.GetReg();
MOVI2R(WA, imm);
ADD(gpr.R(d), gpr.R(a), WA);
gpr.Unlock(WA);
}
ARM64Reg WA = gpr.GetReg();
ADDI2R(gpr.R(d), gpr.R(a), imm, WA);
gpr.Unlock(WA);
}
}
else
@ -316,17 +296,9 @@ void JitArm64::addx(UGeckoInstruction inst)
int imm_reg = gpr.IsImm(a) ? a : b;
int in_reg = gpr.IsImm(a) ? b : a;
gpr.BindToRegister(d, d == in_reg);
if (gpr.GetImm(imm_reg) < 4096)
{
ADD(gpr.R(d), gpr.R(in_reg), gpr.GetImm(imm_reg));
}
else
{
ARM64Reg WA = gpr.GetReg();
MOVI2R(WA, gpr.GetImm(imm_reg));
ADD(gpr.R(d), gpr.R(in_reg), WA);
gpr.Unlock(WA);
}
ARM64Reg WA = gpr.GetReg();
ADDI2R(gpr.R(d), gpr.R(in_reg), gpr.GetImm(imm_reg), WA);
gpr.Unlock(WA);
if (inst.Rc)
ComputeRC(gpr.R(d), 0);
}
@ -479,15 +451,7 @@ void JitArm64::cmpi(UGeckoInstruction inst)
ARM64Reg WA = gpr.GetReg();
if (inst.SIMM_16 >= 0 && inst.SIMM_16 < 4096)
{
SUB(WA, gpr.R(a), inst.SIMM_16);
}
else
{
MOVI2R(WA, inst.SIMM_16);
SUB(WA, gpr.R(a), WA);
}
SUBI2R(WA, gpr.R(a), inst.SIMM_16, WA);
ComputeRC(WA, crf);
@ -516,15 +480,7 @@ void JitArm64::cmpli(UGeckoInstruction inst)
ARM64Reg WA = gpr.GetReg();
ARM64Reg XA = EncodeRegTo64(WA);
if (inst.UIMM < 4096)
{
SUB(XA, EncodeRegTo64(gpr.R(a)), inst.UIMM);
}
else
{
MOVI2R(WA, inst.UIMM);
SUB(XA, EncodeRegTo64(gpr.R(a)), XA);
}
SUBI2R(XA, EncodeRegTo64(gpr.R(a)), inst.UIMM, XA);
STR(INDEX_UNSIGNED, XA, PPC_REG,
PPCSTATE_OFF(cr_val[0]) + (sizeof(PowerPC::ppcState.cr_val[0]) * crf));
@ -626,7 +582,7 @@ void JitArm64::srawix(UGeckoInstruction inst)
if (inst.Rc)
ComputeRC(RA, 0);
ANDS(WSP, WA, RA, ArithOption(RA, ST_LSL, 0));
ANDS(WSP, WA, RA);
CSINC(WA, WSP, WSP, CC_EQ);
STRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
gpr.Unlock(WA);
@ -664,24 +620,9 @@ void JitArm64::addic(UGeckoInstruction inst)
else
{
gpr.BindToRegister(d, d == a);
if (imm < 4096)
{
ADDS(gpr.R(d), gpr.R(a), imm);
}
else if (simm > -4096 && simm < 0)
{
SUBS(gpr.R(d), gpr.R(a), std::abs(simm));
}
else
{
ARM64Reg WA = gpr.GetReg();
MOVI2R(WA, std::abs(simm));
if (simm < 0)
SUBS(gpr.R(d), gpr.R(a), WA);
else
ADDS(gpr.R(d), gpr.R(a), WA);
gpr.Unlock(WA);
}
ARM64Reg WA = gpr.GetReg();
ADDSI2R(gpr.R(d), gpr.R(a), simm, WA);
gpr.Unlock(WA);
ComputeCarry();
if (rc)
@ -850,10 +791,9 @@ void JitArm64::subfex(UGeckoInstruction inst)
u32 i = gpr.GetImm(a), j = gpr.GetImm(b);
gpr.BindToRegister(d, false);
MOVI2R(gpr.R(d), ~i + j);
ARM64Reg WA = gpr.GetReg();
LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
ADD(gpr.R(d), gpr.R(d), WA);
ADDI2R(gpr.R(d), WA, ~i + j, gpr.R(d));
gpr.Unlock(WA);
bool must_have_carry = Interpreter::Helper_Carry(~i, j);
@ -971,10 +911,9 @@ void JitArm64::addex(UGeckoInstruction inst)
u32 i = gpr.GetImm(a), j = gpr.GetImm(b);
gpr.BindToRegister(d, false);
MOVI2R(gpr.R(d), i + j);
ARM64Reg WA = gpr.GetReg();
LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
ADD(gpr.R(d), gpr.R(d), WA);
ADDI2R(gpr.R(d), WA, i + j, gpr.R(d));
gpr.Unlock(WA);
bool must_have_carry = Interpreter::Helper_Carry(i, j);

View File

@ -58,19 +58,7 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
}
else
{
if (offset >= 0 && offset < 4096)
{
ADD(addr_reg, up_reg, offset);
}
else if (offset < 0 && offset > -4096)
{
SUB(addr_reg, up_reg, std::abs(offset));
}
else
{
MOVI2R(addr_reg, offset);
ADD(addr_reg, addr_reg, up_reg);
}
ADDI2R(addr_reg, up_reg, offset, addr_reg);
}
}
else
@ -91,28 +79,12 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
else if (gpr.IsImm(addr) && !gpr.IsImm(offsetReg))
{
u32 reg_offset = gpr.GetImm(addr);
if (reg_offset < 4096)
{
ADD(addr_reg, off_reg, reg_offset);
}
else
{
MOVI2R(addr_reg, gpr.GetImm(addr));
ADD(addr_reg, addr_reg, off_reg);
}
ADDI2R(addr_reg, off_reg, reg_offset, addr_reg);
}
else if (!gpr.IsImm(addr) && gpr.IsImm(offsetReg))
{
u32 reg_offset = gpr.GetImm(offsetReg);
if (reg_offset < 4096)
{
ADD(addr_reg, up_reg, reg_offset);
}
else
{
MOVI2R(addr_reg, gpr.GetImm(offsetReg));
ADD(addr_reg, addr_reg, up_reg);
}
ADDI2R(addr_reg, up_reg, reg_offset, addr_reg);
}
else
{
@ -202,19 +174,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
}
else
{
if (offset >= 0 && offset < 4096)
{
ADD(addr_reg, reg_dest, offset);
}
else if (offset < 0 && offset > -4096)
{
SUB(addr_reg, reg_dest, std::abs(offset));
}
else
{
MOVI2R(addr_reg, offset);
ADD(addr_reg, addr_reg, reg_dest);
}
ADDI2R(addr_reg, reg_dest, offset, addr_reg);
}
}
else
@ -235,28 +195,12 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
else if (gpr.IsImm(dest) && !gpr.IsImm(regOffset))
{
u32 reg_offset = gpr.GetImm(dest);
if (reg_offset < 4096)
{
ADD(addr_reg, reg_off, reg_offset);
}
else
{
MOVI2R(addr_reg, reg_offset);
ADD(addr_reg, addr_reg, reg_off);
}
ADDI2R(addr_reg, reg_off, reg_offset, addr_reg);
}
else if (!gpr.IsImm(dest) && gpr.IsImm(regOffset))
{
u32 reg_offset = gpr.GetImm(regOffset);
if (reg_offset < 4096)
{
ADD(addr_reg, reg_dest, reg_offset);
}
else
{
MOVI2R(addr_reg, gpr.GetImm(regOffset));
ADD(addr_reg, addr_reg, reg_dest);
}
ADDI2R(addr_reg, reg_dest, reg_offset, addr_reg);
}
else
{
@ -526,8 +470,7 @@ void JitArm64::stX(UGeckoInstruction inst)
RB = gpr.R(regOffset);
if (regOffset == -1)
{
MOVI2R(WA, offset);
ADD(RA, RA, WA);
ADDI2R(RA, RA, offset, WA);
}
else
{
@ -549,37 +492,14 @@ void JitArm64::lmw(UGeckoInstruction inst)
ARM64Reg XA = EncodeRegTo64(WA);
if (a)
{
bool add = inst.SIMM_16 >= 0;
u16 off = std::abs(inst.SIMM_16);
if (off < 4096)
{
if (add)
ADD(WA, gpr.R(a), off);
else
SUB(WA, gpr.R(a), off);
}
else
{
u16 remaining = off >> 12;
if (add)
{
ADD(WA, gpr.R(a), off & 0xFFF);
ADD(WA, WA, remaining, true);
}
else
{
SUB(WA, gpr.R(a), off & 0xFFF);
SUB(WA, WA, remaining, true);
}
}
ADDI2R(WA, gpr.R(a), inst.SIMM_16, WA);
ADD(XA, XA, MEM_REG);
}
else
{
MOVI2R(WA, (u32)(s32)(s16)inst.SIMM_16);
ADDI2R(XA, MEM_REG, (u32)(s32)(s16)inst.SIMM_16, XA);
}
ADD(XA, XA, MEM_REG);
for (int i = inst.RD; i < 32; i++)
{
int remaining = 32 - i;
@ -637,37 +557,14 @@ void JitArm64::stmw(UGeckoInstruction inst)
if (a)
{
bool add = inst.SIMM_16 >= 0;
u16 off = std::abs(inst.SIMM_16);
if (off < 4096)
{
if (add)
ADD(WA, gpr.R(a), off);
else
SUB(WA, gpr.R(a), off);
}
else
{
u16 remaining = off >> 12;
if (add)
{
ADD(WA, gpr.R(a), off & 0xFFF);
ADD(WA, WA, remaining, true);
}
else
{
SUB(WA, gpr.R(a), off & 0xFFF);
SUB(WA, WA, remaining, true);
}
}
ADDI2R(WA, gpr.R(a), inst.SIMM_16, WA);
ADD(XA, XA, MEM_REG);
}
else
{
MOVI2R(WA, (u32)(s32)(s16)inst.SIMM_16);
ADDI2R(XA, MEM_REG, (u32)(s32)(s16)inst.SIMM_16, XA);
}
ADD(XA, XA, MEM_REG);
for (int i = inst.RD; i < 32; i++)
{
ARM64Reg RX = gpr.R(i);
@ -782,15 +679,7 @@ void JitArm64::dcbz(UGeckoInstruction inst)
// Only one register is an immediate
ARM64Reg base = is_imm_a ? gpr.R(b) : gpr.R(a);
u32 imm_offset = is_imm_a ? gpr.GetImm(a) : gpr.GetImm(b);
if (imm_offset < 4096)
{
ADD(addr_reg, base, imm_offset);
}
else
{
MOVI2R(addr_reg, imm_offset);
ADD(addr_reg, addr_reg, base);
}
ADDI2R(addr_reg, base, imm_offset, addr_reg);
}
else
{

View File

@ -101,19 +101,7 @@ void JitArm64::lfXX(UGeckoInstruction inst)
{
if (offset_reg == -1)
{
if (offset >= 0 && offset < 4096)
{
ADD(addr_reg, gpr.R(a), offset);
}
else if (offset < 0 && offset > -4096)
{
SUB(addr_reg, gpr.R(a), std::abs(offset));
}
else
{
MOVI2R(addr_reg, offset);
ADD(addr_reg, addr_reg, gpr.R(a));
}
ADDI2R(addr_reg, gpr.R(a), offset, addr_reg);
}
else
{
@ -132,19 +120,7 @@ void JitArm64::lfXX(UGeckoInstruction inst)
}
else if (a)
{
if (offset >= 0 && offset < 4096)
{
ADD(addr_reg, gpr.R(a), offset);
}
else if (offset < 0 && offset > -4096)
{
SUB(addr_reg, gpr.R(a), std::abs(offset));
}
else
{
MOVI2R(addr_reg, offset);
ADD(addr_reg, addr_reg, gpr.R(a));
}
ADDI2R(addr_reg, gpr.R(a), offset, addr_reg);
}
else
{
@ -298,19 +274,7 @@ void JitArm64::stfXX(UGeckoInstruction inst)
{
if (offset_reg == -1)
{
if (offset >= 0 && offset < 4096)
{
ADD(addr_reg, gpr.R(a), offset);
}
else if (offset < 0 && offset > -4096)
{
SUB(addr_reg, gpr.R(a), std::abs(offset));
}
else
{
MOVI2R(addr_reg, offset);
ADD(addr_reg, addr_reg, gpr.R(a));
}
ADDI2R(addr_reg, gpr.R(a), offset, addr_reg);
}
else
{
@ -329,19 +293,7 @@ void JitArm64::stfXX(UGeckoInstruction inst)
}
else if (a)
{
if (offset >= 0 && offset < 4096)
{
ADD(addr_reg, gpr.R(a), offset);
}
else if (offset < 0 && offset > -4096)
{
SUB(addr_reg, gpr.R(a), std::abs(offset));
}
else
{
MOVI2R(addr_reg, offset);
ADD(addr_reg, addr_reg, gpr.R(a));
}
ADDI2R(addr_reg, gpr.R(a), offset, addr_reg);
}
else
{

View File

@ -151,16 +151,7 @@ void JitArm64::twx(UGeckoInstruction inst)
if (inst.OPCD == 3) // twi
{
if (inst.SIMM_16 >= 0 && inst.SIMM_16 < 4096)
{
// Can fit in immediate in to the instruction encoding
CMP(gpr.R(a), inst.SIMM_16);
}
else
{
MOVI2R(WA, (s32)(s16)inst.SIMM_16);
CMP(gpr.R(a), WA);
}
CMPI2R(gpr.R(a), (s32)(s16)inst.SIMM_16, WA);
}
else // tw
{

View File

@ -64,8 +64,7 @@ private:
}
else
{
m_emit->MOVI2R(W1, mask);
m_emit->AND(W1, m_src_reg, W1, ArithOption(W1, ST_LSL, 0));
m_emit->ANDI2R(W1, m_src_reg, mask, W1);
StoreFromRegister(sbits, W1);
}
}
@ -159,8 +158,7 @@ private:
else
{
LoadToRegister(sbits, true);
m_emit->MOVI2R(W0, mask);
m_emit->AND(m_dst_reg, m_dst_reg, W0, ArithOption(W0, ST_LSL, 0));
m_emit->ANDI2R(m_dst_reg, m_dst_reg, mask, W0);
if (m_sign_extend)
m_emit->SBFM(m_dst_reg, m_dst_reg, 0, sbits - 1);
}