some tiny A64 optimisations

This commit is contained in:
RSDuck
2021-06-30 00:41:04 +02:00
parent aa430608e7
commit 5a071c4c29
3 changed files with 67 additions and 39 deletions

View File

@ -323,6 +323,8 @@ void Compiler::Comp_Arithmetic(int op, bool S, ARM64Reg rd, ARM64Reg rn, Op2 op2
case 0x5: // ADC case 0x5: // ADC
UBFX(W2, RCPSR, 29, 1); UBFX(W2, RCPSR, 29, 1);
if (S) if (S)
{
if (op2.IsImm)
{ {
CVInGPR = true; CVInGPR = true;
ADDS(W1, rn, W2); ADDS(W1, rn, W2);
@ -336,6 +338,17 @@ void Compiler::Comp_Arithmetic(int op, bool S, ARM64Reg rd, ARM64Reg rn, Op2 op2
CSINC(W3, W3, WZR, CC_VC); CSINC(W3, W3, WZR, CC_VC);
} }
else else
{
if (op2.Reg.ShiftAmount > 0)
{
MOV(W0, op2.Reg.Rm, op2.ToArithOption());
op2 = Op2(W0, ST_LSL, 0);
}
CMP(W2, 1);
ADCS(rd, rn, op2.Reg.Rm);
}
}
else
{ {
ADD(W1, rn, W2); ADD(W1, rn, W2);
if (op2.IsImm) if (op2.IsImm)
@ -346,6 +359,18 @@ void Compiler::Comp_Arithmetic(int op, bool S, ARM64Reg rd, ARM64Reg rn, Op2 op2
break; break;
case 0x6: // SBC case 0x6: // SBC
UBFX(W2, RCPSR, 29, 1); UBFX(W2, RCPSR, 29, 1);
if (S && !op2.IsImm)
{
if (op2.Reg.ShiftAmount > 0)
{
MOV(W0, op2.Reg.Rm, op2.ToArithOption());
op2 = Op2(W0, ST_LSL, 0);
}
CMP(W2, 1);
SBCS(rd, rn, op2.Reg.Rm);
}
else
{
// W1 = -op2 - 1 // W1 = -op2 - 1
if (op2.IsImm) if (op2.IsImm)
MOVI2R(W1, ~op2.Imm); MOVI2R(W1, ~op2.Imm);
@ -366,6 +391,7 @@ void Compiler::Comp_Arithmetic(int op, bool S, ARM64Reg rd, ARM64Reg rn, Op2 op2
ADD(W1, W2, W1); ADD(W1, W2, W1);
ADD(rd, rn, W1); ADD(rd, rn, W1);
} }
}
break; break;
case 0x7: // RSC case 0x7: // RSC
UBFX(W2, RCPSR, 29, 1); UBFX(W2, RCPSR, 29, 1);
@ -532,24 +558,10 @@ void Compiler::A_Comp_ALUMovOp()
MOVI2R(rd, op2.Imm); MOVI2R(rd, op2.Imm);
} }
else else
{
// ORR with shifted operand has cycles latency
if (op2.Reg.ShiftAmount > 0)
{
switch (op2.Reg.ShiftType)
{
case ST_LSL: LSL(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break;
case ST_LSR: LSR(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break;
case ST_ASR: ASR(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break;
case ST_ROR: ROR(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break;
}
}
else
{ {
MOV(rd, op2.Reg.Rm, op2.ToArithOption()); MOV(rd, op2.Reg.Rm, op2.ToArithOption());
} }
} }
}
if (S) if (S)
{ {

View File

@ -1607,7 +1607,21 @@ void ARM64XEmitter::BICS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Shif
void ARM64XEmitter::MOV(ARM64Reg Rd, ARM64Reg Rm, ArithOption Shift) void ARM64XEmitter::MOV(ARM64Reg Rd, ARM64Reg Rm, ArithOption Shift)
{ {
if (Shift.GetType() == ArithOption::TYPE_SHIFTEDREG)
{
switch (Shift.GetShiftType())
{
case ST_LSL: LSL(Rd, Rm, Shift.GetShiftAmount()); break;
case ST_LSR: LSR(Rd, Rm, Shift.GetShiftAmount()); break;
case ST_ASR: ASR(Rd, Rm, Shift.GetShiftAmount()); break;
case ST_ROR: ROR(Rd, Rm, Shift.GetShiftAmount()); break;
default: ASSERT_MSG(DYNA_REC, false, "Invalid shift type"); break;
}
}
else
{
ORR(Rd, Is64Bit(Rd) ? ZR : WZR, Rm, Shift); ORR(Rd, Is64Bit(Rd) ? ZR : WZR, Rm, Shift);
}
} }
void ARM64XEmitter::MOV(ARM64Reg Rd, ARM64Reg Rm) void ARM64XEmitter::MOV(ARM64Reg Rd, ARM64Reg Rm)

View File

@ -469,6 +469,8 @@ public:
} }
TypeSpecifier GetType() const { return m_type; } TypeSpecifier GetType() const { return m_type; }
ARM64Reg GetReg() const { return m_destReg; } ARM64Reg GetReg() const { return m_destReg; }
ShiftType GetShiftType() const { return m_shifttype; }
u32 GetShiftAmount() const { return m_shift; }
u32 GetData() const u32 GetData() const
{ {
switch (m_type) switch (m_type)