JitArm64: Split addi from arith_imm.

They ARM assembly has different immediate versions for logic and additions, so there is no use in merging those instructions.
This commit is contained in:
degasus 2016-02-28 10:35:47 +01:00
parent 961901daae
commit 4478146c80
3 changed files with 57 additions and 47 deletions

View File

@ -83,6 +83,7 @@ public:
void arith_imm(UGeckoInstruction inst); void arith_imm(UGeckoInstruction inst);
void boolX(UGeckoInstruction inst); void boolX(UGeckoInstruction inst);
void addx(UGeckoInstruction inst); void addx(UGeckoInstruction inst);
void addix(UGeckoInstruction inst);
void extsXx(UGeckoInstruction inst); void extsXx(UGeckoInstruction inst);
void cntlzwx(UGeckoInstruction inst); void cntlzwx(UGeckoInstruction inst);
void negx(UGeckoInstruction inst); void negx(UGeckoInstruction inst);
@ -249,6 +250,6 @@ private:
void ComputeCarry(); void ComputeCarry();
typedef u32 (*Operation)(u32, u32); typedef u32 (*Operation)(u32, u32);
void reg_imm(u32 d, u32 a, bool binary, u32 value, Operation do_op, void (ARM64XEmitter::*op)(Arm64Gen::ARM64Reg, Arm64Gen::ARM64Reg, Arm64Gen::ARM64Reg, ArithOption), bool Rc = false); void reg_imm(u32 d, u32 a, u32 value, Operation do_op, void (ARM64XEmitter::*op)(Arm64Gen::ARM64Reg, Arm64Gen::ARM64Reg, Arm64Gen::ARM64Reg, ArithOption), bool Rc = false);
}; };

View File

@ -77,11 +77,6 @@ void JitArm64::ComputeCarry()
} }
// Following static functions are used in conjunction with reg_imm // Following static functions are used in conjunction with reg_imm
static u32 Add(u32 a, u32 b)
{
return a + b;
}
static u32 Or(u32 a, u32 b) static u32 Or(u32 a, u32 b)
{ {
return a | b; return a | b;
@ -97,38 +92,24 @@ static u32 Xor(u32 a, u32 b)
return a ^ b; return a ^ b;
} }
void JitArm64::reg_imm(u32 d, u32 a, bool binary, u32 value, Operation do_op, void (ARM64XEmitter::*op)(ARM64Reg, ARM64Reg, ARM64Reg, ArithOption), bool Rc) void JitArm64::reg_imm(u32 d, u32 a, u32 value, Operation do_op, void (ARM64XEmitter::*op)(ARM64Reg, ARM64Reg, ARM64Reg, ArithOption), bool Rc)
{ {
if (a || binary) if (gpr.IsImm(a))
{ {
if (gpr.IsImm(a)) gpr.SetImmediate(d, do_op(gpr.GetImm(a), value));
{
gpr.SetImmediate(d, do_op(gpr.GetImm(a), value));
if (Rc)
ComputeRC(gpr.GetImm(d));
}
else
{
gpr.BindToRegister(d, d == a);
ARM64Reg WA = gpr.GetReg();
MOVI2R(WA, value);
(this->*op)(gpr.R(d), gpr.R(a), WA, ArithOption(WA, ST_LSL, 0));
gpr.Unlock(WA);
if (Rc)
ComputeRC(gpr.R(d), 0);
}
}
else if (do_op == Add)
{
// a == 0, implies zero register
gpr.SetImmediate(d, value);
if (Rc) if (Rc)
ComputeRC(value, 0); ComputeRC(gpr.GetImm(d));
} }
else else
{ {
_assert_msg_(DYNA_REC, false, "Hit impossible condition in reg_imm!"); gpr.BindToRegister(d, d == a);
ARM64Reg WA = gpr.GetReg();
MOVI2R(WA, value);
(this->*op)(gpr.R(d), gpr.R(a), WA, ArithOption(WA, ST_LSL, 0));
gpr.Unlock(WA);
if (Rc)
ComputeRC(gpr.R(d), 0);
} }
} }
@ -136,42 +117,70 @@ void JitArm64::arith_imm(UGeckoInstruction inst)
{ {
INSTRUCTION_START INSTRUCTION_START
JITDISABLE(bJITIntegerOff); JITDISABLE(bJITIntegerOff);
u32 d = inst.RD, a = inst.RA, s = inst.RS; u32 a = inst.RA, s = inst.RS;
switch (inst.OPCD) switch (inst.OPCD)
{ {
case 14: // addi
reg_imm(d, a, false, (u32)(s32)inst.SIMM_16, Add, &ARM64XEmitter::ADD);
break;
case 15: // addis
reg_imm(d, a, false, (u32)inst.SIMM_16 << 16, Add, &ARM64XEmitter::ADD);
break;
case 24: // ori case 24: // ori
if (a == 0 && s == 0 && inst.UIMM == 0 && !inst.Rc) //check for nop if (a == 0 && s == 0 && inst.UIMM == 0 && !inst.Rc) //check for nop
{ {
// NOP // NOP
return; return;
} }
reg_imm(a, s, true, inst.UIMM, Or, &ARM64XEmitter::ORR); reg_imm(a, s, inst.UIMM, Or, &ARM64XEmitter::ORR);
break; break;
case 25: // oris case 25: // oris
reg_imm(a, s, true, inst.UIMM << 16, Or, &ARM64XEmitter::ORR); reg_imm(a, s, inst.UIMM << 16, Or, &ARM64XEmitter::ORR);
break; break;
case 28: // andi case 28: // andi
reg_imm(a, s, true, inst.UIMM, And, &ARM64XEmitter::AND, true); reg_imm(a, s, inst.UIMM, And, &ARM64XEmitter::AND, true);
break; break;
case 29: // andis case 29: // andis
reg_imm(a, s, true, inst.UIMM << 16, And, &ARM64XEmitter::AND, true); reg_imm(a, s, inst.UIMM << 16, And, &ARM64XEmitter::AND, true);
break; break;
case 26: // xori case 26: // xori
reg_imm(a, s, true, inst.UIMM, Xor, &ARM64XEmitter::EOR); reg_imm(a, s, inst.UIMM, Xor, &ARM64XEmitter::EOR);
break; break;
case 27: // xoris case 27: // xoris
reg_imm(a, s, true, inst.UIMM << 16, Xor, &ARM64XEmitter::EOR); reg_imm(a, s, inst.UIMM << 16, Xor, &ARM64XEmitter::EOR);
break; break;
} }
} }
void JitArm64::addix(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITIntegerOff);
u32 d = inst.RD, a = inst.RA;
u32 value = (u32)(s32)inst.SIMM_16;
if (inst.OPCD == 15)
value <<= 16;
if (a)
{
if (gpr.IsImm(a))
{
gpr.SetImmediate(d, gpr.GetImm(a) + value);
}
else
{
gpr.BindToRegister(d, d == a);
ARM64Reg WA = gpr.GetReg();
MOVI2R(WA, value);
ADD(gpr.R(d), gpr.R(a), WA);
gpr.Unlock(WA);
}
}
else
{
// a == 0, implies zero register
gpr.SetImmediate(d, value);
}
}
void JitArm64::boolX(UGeckoInstruction inst) void JitArm64::boolX(UGeckoInstruction inst)
{ {
INSTRUCTION_START INSTRUCTION_START

View File

@ -49,8 +49,8 @@ static GekkoOPTemplate primarytable[] =
{11, &JitArm64::cmpi}, // cmpi {11, &JitArm64::cmpi}, // cmpi
{12, &JitArm64::addic}, // addic {12, &JitArm64::addic}, // addic
{13, &JitArm64::addic}, // addic_rc {13, &JitArm64::addic}, // addic_rc
{14, &JitArm64::arith_imm}, // addi {14, &JitArm64::addix}, // addi
{15, &JitArm64::arith_imm}, // addis {15, &JitArm64::addix}, // addis
{20, &JitArm64::rlwimix}, // rlwimix {20, &JitArm64::rlwimix}, // rlwimix
{21, &JitArm64::rlwinmx}, // rlwinmx {21, &JitArm64::rlwinmx}, // rlwinmx