Merge pull request #2897 from degasus/arm
JitArm64: Implement subfex, subfcx, addex, subfic, divwux, srwx
This commit is contained in:
commit
8bc311ab3c
|
@ -98,7 +98,13 @@ public:
|
|||
void subfx(UGeckoInstruction inst);
|
||||
void addcx(UGeckoInstruction inst);
|
||||
void slwx(UGeckoInstruction inst);
|
||||
void srwx(UGeckoInstruction inst);
|
||||
void rlwimix(UGeckoInstruction inst);
|
||||
void subfex(UGeckoInstruction inst);
|
||||
void subfcx(UGeckoInstruction inst);
|
||||
void subfic(UGeckoInstruction inst);
|
||||
void addex(UGeckoInstruction inst);
|
||||
void divwux(UGeckoInstruction inst);
|
||||
|
||||
// System Registers
|
||||
void mtmsr(UGeckoInstruction inst);
|
||||
|
|
|
@ -724,6 +724,188 @@ void JitArm64::subfx(UGeckoInstruction inst)
|
|||
}
|
||||
}
|
||||
|
||||
void JitArm64::subfex(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITIntegerOff);
|
||||
FALLBACK_IF(inst.OE);
|
||||
|
||||
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||
|
||||
if (gpr.IsImm(a) && gpr.IsImm(b))
|
||||
{
|
||||
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, X29, PPCSTATE_OFF(xer_ca));
|
||||
ADD(gpr.R(d), gpr.R(d), WA);
|
||||
gpr.Unlock(WA);
|
||||
|
||||
bool must_have_carry = Interpreter::Helper_Carry(~i, j);
|
||||
bool might_have_carry = (~i + j) == 0xFFFFFFFF;
|
||||
|
||||
if (must_have_carry)
|
||||
{
|
||||
ComputeCarry(true);
|
||||
}
|
||||
else if (might_have_carry)
|
||||
{
|
||||
// carry stay as it is
|
||||
}
|
||||
else
|
||||
{
|
||||
ComputeCarry(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
gpr.BindToRegister(d, d == a || d == b);
|
||||
|
||||
// upload the carry state
|
||||
LDRB(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(xer_ca));
|
||||
CMP(WA, 1);
|
||||
|
||||
// d = ~a + b + carry;
|
||||
if (gpr.IsImm(a))
|
||||
MOVI2R(WA, ~gpr.GetImm(a));
|
||||
else
|
||||
MVN(WA, gpr.R(a));
|
||||
ADCS(gpr.R(d), WA, gpr.R(b));
|
||||
|
||||
gpr.Unlock(WA);
|
||||
|
||||
ComputeCarry();
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
ComputeRC(gpr.R(d), 0);
|
||||
}
|
||||
|
||||
void JitArm64::subfcx(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITIntegerOff);
|
||||
FALLBACK_IF(inst.OE);
|
||||
|
||||
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||
|
||||
if (gpr.IsImm(a) && gpr.IsImm(b))
|
||||
{
|
||||
u32 a_imm = gpr.GetImm(a), b_imm = gpr.GetImm(b);
|
||||
|
||||
gpr.SetImmediate(d, b_imm - a_imm);
|
||||
ComputeCarry(a_imm == 0 || Interpreter::Helper_Carry(b_imm, 0u - a_imm));
|
||||
|
||||
if (inst.Rc)
|
||||
ComputeRC(gpr.GetImm(d), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.BindToRegister(d, d == a || d == b);
|
||||
|
||||
// d = b - a
|
||||
SUBS(gpr.R(d), gpr.R(b), gpr.R(a));
|
||||
|
||||
ComputeCarry();
|
||||
|
||||
if (inst.Rc)
|
||||
ComputeRC(gpr.R(d), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void JitArm64::subfic(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITIntegerOff);
|
||||
|
||||
int a = inst.RA, d = inst.RD;
|
||||
s32 imm = inst.SIMM_16;
|
||||
|
||||
if (gpr.IsImm(a))
|
||||
{
|
||||
u32 a_imm = gpr.GetImm(a);
|
||||
|
||||
gpr.SetImmediate(d, imm - a_imm);
|
||||
ComputeCarry(a_imm == 0 || Interpreter::Helper_Carry(imm, 0u - a_imm));
|
||||
|
||||
if (inst.Rc)
|
||||
ComputeRC(gpr.GetImm(d), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.BindToRegister(d, d == a);
|
||||
|
||||
// d = imm - a
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
MOVI2R(WA, imm);
|
||||
SUBS(gpr.R(d), WA, gpr.R(a));
|
||||
gpr.Unlock(WA);
|
||||
|
||||
ComputeCarry();
|
||||
|
||||
if (inst.Rc)
|
||||
ComputeRC(gpr.R(d), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void JitArm64::addex(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITIntegerOff);
|
||||
FALLBACK_IF(inst.OE);
|
||||
|
||||
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||
|
||||
if (gpr.IsImm(a) && gpr.IsImm(b))
|
||||
{
|
||||
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, X29, PPCSTATE_OFF(xer_ca));
|
||||
ADD(gpr.R(d), gpr.R(d), WA);
|
||||
gpr.Unlock(WA);
|
||||
|
||||
bool must_have_carry = Interpreter::Helper_Carry(i, j);
|
||||
bool might_have_carry = (i + j) == 0xFFFFFFFF;
|
||||
|
||||
if (must_have_carry)
|
||||
{
|
||||
ComputeCarry(true);
|
||||
}
|
||||
else if (might_have_carry)
|
||||
{
|
||||
// carry stay as it is
|
||||
}
|
||||
else
|
||||
{
|
||||
ComputeCarry(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.BindToRegister(d, d == a || d == b);
|
||||
|
||||
// upload the carry state
|
||||
ARM64Reg WA = gpr.GetReg();
|
||||
LDRB(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(xer_ca));
|
||||
CMP(WA, 1);
|
||||
gpr.Unlock(WA);
|
||||
|
||||
// d = a + b + carry;
|
||||
ADCS(gpr.R(d), gpr.R(a), gpr.R(b));
|
||||
|
||||
ComputeCarry();
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
ComputeRC(gpr.R(d), 0);
|
||||
}
|
||||
|
||||
void JitArm64::addcx(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
|
@ -753,6 +935,34 @@ void JitArm64::addcx(UGeckoInstruction inst)
|
|||
}
|
||||
}
|
||||
|
||||
void JitArm64::divwux(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITIntegerOff);
|
||||
FALLBACK_IF(inst.OE);
|
||||
|
||||
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||
|
||||
if (gpr.IsImm(a) && gpr.IsImm(b))
|
||||
{
|
||||
u32 i = gpr.GetImm(a), j = gpr.GetImm(b);
|
||||
gpr.SetImmediate(d, j == 0 ? 0 : i / j);
|
||||
|
||||
if (inst.Rc)
|
||||
ComputeRC(gpr.GetImm(d), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.BindToRegister(d, d == a || d == b);
|
||||
|
||||
// d = a / b
|
||||
UDIV(gpr.R(d), gpr.R(a), gpr.R(b));
|
||||
|
||||
if (inst.Rc)
|
||||
ComputeRC(gpr.R(d), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void JitArm64::slwx(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
|
@ -801,6 +1011,52 @@ void JitArm64::slwx(UGeckoInstruction inst)
|
|||
}
|
||||
}
|
||||
|
||||
void JitArm64::srwx(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITIntegerOff);
|
||||
|
||||
int a = inst.RA, b = inst.RB, s = inst.RS;
|
||||
|
||||
if (gpr.IsImm(b) && gpr.IsImm(s))
|
||||
{
|
||||
u32 i = gpr.GetImm(s), amount = gpr.GetImm(b);
|
||||
gpr.SetImmediate(a, (amount & 0x20) ? 0 : i >> (amount & 0x1F));
|
||||
|
||||
if (inst.Rc)
|
||||
ComputeRC(gpr.GetImm(a), 0);
|
||||
}
|
||||
else if (gpr.IsImm(b))
|
||||
{
|
||||
u32 amount = gpr.GetImm(b);
|
||||
if (amount & 0x20)
|
||||
{
|
||||
gpr.SetImmediate(a, 0);
|
||||
if (inst.Rc)
|
||||
ComputeRC(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.BindToRegister(a, a == s);
|
||||
LSR(gpr.R(a), gpr.R(s), amount & 0x1F);
|
||||
if (inst.Rc)
|
||||
ComputeRC(gpr.R(a), 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.BindToRegister(a, a == b || a == s);
|
||||
|
||||
// wipe upper bits. TODO: get rid of it, but then no instruction is allowed to emit some higher bits.
|
||||
MOV(gpr.R(s), gpr.R(s));
|
||||
|
||||
LSRV(EncodeRegTo64(gpr.R(a)), EncodeRegTo64(gpr.R(s)), EncodeRegTo64(gpr.R(b)));
|
||||
|
||||
if (inst.Rc)
|
||||
ComputeRC(gpr.R(a), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void JitArm64::rlwimix(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
|
|
|
@ -44,7 +44,7 @@ static GekkoOPTemplate primarytable[] =
|
|||
{17, &JitArm64::sc}, // sc
|
||||
|
||||
{7, &JitArm64::mulli}, // mulli
|
||||
{8, &JitArm64::FallBackToInterpreter}, // subfic
|
||||
{8, &JitArm64::subfic}, // subfic
|
||||
{10, &JitArm64::cmpli}, // cmpli
|
||||
{11, &JitArm64::cmpi}, // cmpi
|
||||
{12, &JitArm64::addic}, // addic
|
||||
|
@ -174,16 +174,16 @@ static GekkoOPTemplate table31[] =
|
|||
{778, &JitArm64::addx}, // addox
|
||||
{10, &JitArm64::addcx}, // addcx
|
||||
{522, &JitArm64::addcx}, // addcox
|
||||
{138, &JitArm64::FallBackToInterpreter}, // addex
|
||||
{650, &JitArm64::FallBackToInterpreter}, // addeox
|
||||
{138, &JitArm64::addex}, // addex
|
||||
{650, &JitArm64::addex}, // addeox
|
||||
{234, &JitArm64::FallBackToInterpreter}, // addmex
|
||||
{746, &JitArm64::FallBackToInterpreter}, // addmeox
|
||||
{202, &JitArm64::addzex}, // addzex
|
||||
{714, &JitArm64::addzex}, // addzeox
|
||||
{491, &JitArm64::FallBackToInterpreter}, // divwx
|
||||
{1003, &JitArm64::FallBackToInterpreter}, // divwox
|
||||
{459, &JitArm64::FallBackToInterpreter}, // divwux
|
||||
{971, &JitArm64::FallBackToInterpreter}, // divwuox
|
||||
{459, &JitArm64::divwux}, // divwux
|
||||
{971, &JitArm64::divwux}, // divwuox
|
||||
{75, &JitArm64::FallBackToInterpreter}, // mulhwx
|
||||
{11, &JitArm64::FallBackToInterpreter}, // mulhwux
|
||||
{235, &JitArm64::mullwx}, // mullwx
|
||||
|
@ -192,10 +192,10 @@ static GekkoOPTemplate table31[] =
|
|||
{616, &JitArm64::negx}, // negox
|
||||
{40, &JitArm64::subfx}, // subfx
|
||||
{552, &JitArm64::subfx}, // subfox
|
||||
{8, &JitArm64::FallBackToInterpreter}, // subfcx
|
||||
{520, &JitArm64::FallBackToInterpreter}, // subfcox
|
||||
{136, &JitArm64::FallBackToInterpreter}, // subfex
|
||||
{648, &JitArm64::FallBackToInterpreter}, // subfeox
|
||||
{8, &JitArm64::subfcx}, // subfcx
|
||||
{520, &JitArm64::subfcx}, // subfcox
|
||||
{136, &JitArm64::subfex}, // subfex
|
||||
{648, &JitArm64::subfex}, // subfeox
|
||||
{232, &JitArm64::FallBackToInterpreter}, // subfmex
|
||||
{744, &JitArm64::FallBackToInterpreter}, // subfmeox
|
||||
{200, &JitArm64::FallBackToInterpreter}, // subfzex
|
||||
|
@ -214,7 +214,7 @@ static GekkoOPTemplate table31[] =
|
|||
{26, &JitArm64::cntlzwx}, // cntlzwx
|
||||
{922, &JitArm64::extsXx}, // extshx
|
||||
{954, &JitArm64::extsXx}, // extsbx
|
||||
{536, &JitArm64::FallBackToInterpreter}, // srwx
|
||||
{536, &JitArm64::srwx}, // srwx
|
||||
{792, &JitArm64::FallBackToInterpreter}, // srawx
|
||||
{824, &JitArm64::srawix}, // srawix
|
||||
{24, &JitArm64::slwx}, // slwx
|
||||
|
|
Loading…
Reference in New Issue