Merge pull request #1728 from Sonicadvance1/AArch64_BindToRegister

[AArch64] Adds support for BindToRegister to the integer instructions.
This commit is contained in:
Ryan Houdek 2014-12-21 20:48:24 -06:00
commit 1da6995d5b
2 changed files with 80 additions and 41 deletions

View File

@ -16,13 +16,12 @@
#include "Core/PowerPC/JitArmCommon/BackPatch.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
#define PPCSTATE_OFF(elem) ((s64)&PowerPC::ppcState.elem - (s64)&PowerPC::ppcState)
#define PPCSTATE_OFF(elem) (offsetof(PowerPC::PowerPCState, elem))
// Some asserts to make sure we will be able to load everything
static_assert(PPCSTATE_OFF(spr[1023]) <= 16380, "LDR(32bit) can't reach the last SPR");
static_assert((PPCSTATE_OFF(ps[0][0]) % 8) == 0, "LDR(64bit VFP) requires FPRs to be 8 byte aligned");
using namespace Arm64Gen;
class JitArm64 : public JitBase, public Arm64Gen::ARM64CodeBlock
{
public:
@ -132,9 +131,10 @@ private:
FixupBranch JumpIfCRFieldBit(int field, int bit, bool jump_if_set);
void ComputeRC(u32 d);
void ComputeRC(Arm64Gen::ARM64Reg reg, int crf = 0);
void ComputeRC(u32 imm, int crf = 0);
typedef u32 (*Operation)(u32, u32);
void reg_imm(u32 d, u32 a, bool binary, u32 value, Operation do_op, void (ARM64XEmitter::*op)(ARM64Reg, ARM64Reg, ARM64Reg, ArithOption), bool Rc = false);
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);
};

View File

@ -15,22 +15,27 @@
using namespace Arm64Gen;
void JitArm64::ComputeRC(u32 d)
void JitArm64::ComputeRC(ARM64Reg reg, int crf)
{
ARM64Reg WA = gpr.GetReg();
ARM64Reg XA = EncodeRegTo64(WA);
if (gpr.IsImm(d))
{
MOVI2R(WA, gpr.GetImm(d));
SXTW(XA, WA);
}
else
{
SXTW(XA, gpr.R(d));
}
SXTW(XA, reg);
STR(INDEX_UNSIGNED, XA, X29, PPCSTATE_OFF(cr_val[0]));
STR(INDEX_UNSIGNED, XA, X29, PPCSTATE_OFF(cr_val[crf]));
gpr.Unlock(WA);
}
void JitArm64::ComputeRC(u32 imm, int crf)
{
ARM64Reg WA = gpr.GetReg();
ARM64Reg XA = EncodeRegTo64(WA);
MOVI2R(WA, imm);
if (!(imm & 0x80000000))
SXTW(XA, WA);
STR(INDEX_UNSIGNED, XA, X29, PPCSTATE_OFF(cr_val[crf]));
gpr.Unlock(WA);
}
@ -62,24 +67,27 @@ void JitArm64::reg_imm(u32 d, u32 a, bool binary, u32 value, Operation do_op, vo
if (gpr.IsImm(a))
{
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(d);
if (Rc)
ComputeRC(gpr.R(d), 0);
}
}
else if (do_op == Add)
{
// a == 0, implies zero register
gpr.SetImmediate(d, value);
if (Rc)
ComputeRC(d);
ComputeRC(value, 0);
}
else
{
@ -153,7 +161,7 @@ void JitArm64::boolX(UGeckoInstruction inst)
gpr.SetImmediate(a, ~((u32)gpr.GetImm(s) ^ (u32)gpr.GetImm(b)));
if (inst.Rc)
ComputeRC(a);
ComputeRC(gpr.GetImm(a), 0);
}
else if (s == b)
{
@ -161,30 +169,39 @@ void JitArm64::boolX(UGeckoInstruction inst)
{
if (a != s)
{
gpr.BindToRegister(a, false);
MOV(gpr.R(a), gpr.R(s));
}
if (inst.Rc)
ComputeRC(gpr.R(a));
}
else if ((inst.SUBOP10 == 476 /* nandx */) || (inst.SUBOP10 == 124 /* norx */))
{
gpr.BindToRegister(a, a == s);
MVN(gpr.R(a), gpr.R(s));
if (inst.Rc)
ComputeRC(gpr.R(a));
}
else if ((inst.SUBOP10 == 412 /* orcx */) || (inst.SUBOP10 == 284 /* eqvx */))
{
gpr.SetImmediate(a, 0xFFFFFFFF);
if (inst.Rc)
ComputeRC(gpr.GetImm(a), 0);
}
else if ((inst.SUBOP10 == 60 /* andcx */) || (inst.SUBOP10 == 316 /* xorx */))
{
gpr.SetImmediate(a, 0);
if (inst.Rc)
ComputeRC(gpr.GetImm(a), 0);
}
else
{
PanicAlert("WTF!");
}
if (inst.Rc)
ComputeRC(a);
}
else
{
gpr.BindToRegister(a, (a == s) || (a == b));
if (inst.SUBOP10 == 28) // andx
{
AND(gpr.R(a), gpr.R(s), gpr.R(b), ArithOption(gpr.R(a), ST_LSL, 0));
@ -224,7 +241,7 @@ void JitArm64::boolX(UGeckoInstruction inst)
PanicAlert("WTF!");
}
if (inst.Rc)
ComputeRC(a);
ComputeRC(gpr.R(a), 0);
}
}
@ -235,13 +252,21 @@ void JitArm64::extsXx(UGeckoInstruction inst)
int a = inst.RA, s = inst.RS;
int size = inst.SUBOP10 == 922 ? 16 : 8;
if (gpr.IsImm(s))
gpr.SetImmediate(a, (u32)(s32)(size == 16 ? (s16)gpr.GetImm(s) : (s8)gpr.GetImm(s)));
else
SBFM(gpr.R(a), gpr.R(s), 0, size - 1);
gpr.BindToRegister(a, a == s);
if (gpr.IsImm(s))
{
gpr.SetImmediate(a, (u32)(s32)(size == 16 ? (s16)gpr.GetImm(s) : (s8)gpr.GetImm(s)));
if (inst.Rc)
ComputeRC(gpr.GetImm(a), 0);
}
else
{
SBFM(gpr.R(a), gpr.R(s), 0, size - 1);
if (inst.Rc)
ComputeRC(gpr.R(a), 0);
}
if (inst.Rc)
ComputeRC(a);
}
void JitArm64::cntlzwx(UGeckoInstruction inst)
@ -251,13 +276,20 @@ void JitArm64::cntlzwx(UGeckoInstruction inst)
int a = inst.RA;
int s = inst.RS;
if (gpr.IsImm(s))
gpr.SetImmediate(a, __builtin_clz(gpr.GetImm(s)));
else
CLZ(gpr.R(a), gpr.R(s));
gpr.BindToRegister(a, a == s);
if (inst.Rc)
ComputeRC(a);
if (gpr.IsImm(s))
{
gpr.SetImmediate(a, __builtin_clz(gpr.GetImm(s)));
if (inst.Rc)
ComputeRC(gpr.GetImm(a), 0);
}
else
{
CLZ(gpr.R(a), gpr.R(s));
if (inst.Rc)
ComputeRC(gpr.R(a), 0);
}
}
void JitArm64::negx(UGeckoInstruction inst)
@ -269,11 +301,18 @@ void JitArm64::negx(UGeckoInstruction inst)
FALLBACK_IF(inst.OE);
if (gpr.IsImm(a))
gpr.SetImmediate(d, ~((u32)gpr.GetImm(a)) + 1);
else
SUB(gpr.R(d), WSP, gpr.R(a), ArithOption(gpr.R(a), ST_LSL, 0));
gpr.BindToRegister(d, d == a);
if (inst.Rc)
ComputeRC(d);
if (gpr.IsImm(a))
{
gpr.SetImmediate(d, ~((u32)gpr.GetImm(a)) + 1);
if (inst.Rc)
ComputeRC(gpr.GetImm(d), 0);
}
else
{
SUB(gpr.R(d), WSP, gpr.R(a), ArithOption(gpr.R(a), ST_LSL, 0));
if (inst.Rc)
ComputeRC(gpr.R(d), 0);
}
}