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/JitArmCommon/BackPatch.h"
#include "Core/PowerPC/JitCommon/JitBase.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 // 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(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"); 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 class JitArm64 : public JitBase, public Arm64Gen::ARM64CodeBlock
{ {
public: public:
@ -132,9 +131,10 @@ private:
FixupBranch JumpIfCRFieldBit(int field, int bit, bool jump_if_set); 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); 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; using namespace Arm64Gen;
void JitArm64::ComputeRC(u32 d) void JitArm64::ComputeRC(ARM64Reg reg, int crf)
{ {
ARM64Reg WA = gpr.GetReg(); ARM64Reg WA = gpr.GetReg();
ARM64Reg XA = EncodeRegTo64(WA); ARM64Reg XA = EncodeRegTo64(WA);
if (gpr.IsImm(d)) SXTW(XA, reg);
{
MOVI2R(WA, gpr.GetImm(d));
SXTW(XA, WA);
}
else
{
SXTW(XA, gpr.R(d));
}
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); 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)) 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 else
{ {
gpr.BindToRegister(d, d == a);
ARM64Reg WA = gpr.GetReg(); ARM64Reg WA = gpr.GetReg();
MOVI2R(WA, value); MOVI2R(WA, value);
(this->*op)(gpr.R(d), gpr.R(a), WA, ArithOption(WA, ST_LSL, 0)); (this->*op)(gpr.R(d), gpr.R(a), WA, ArithOption(WA, ST_LSL, 0));
gpr.Unlock(WA); gpr.Unlock(WA);
}
if (Rc) if (Rc)
ComputeRC(d); ComputeRC(gpr.R(d), 0);
}
} }
else if (do_op == Add) else if (do_op == Add)
{ {
// a == 0, implies zero register // a == 0, implies zero register
gpr.SetImmediate(d, value); gpr.SetImmediate(d, value);
if (Rc) if (Rc)
ComputeRC(d); ComputeRC(value, 0);
} }
else else
{ {
@ -153,7 +161,7 @@ void JitArm64::boolX(UGeckoInstruction inst)
gpr.SetImmediate(a, ~((u32)gpr.GetImm(s) ^ (u32)gpr.GetImm(b))); gpr.SetImmediate(a, ~((u32)gpr.GetImm(s) ^ (u32)gpr.GetImm(b)));
if (inst.Rc) if (inst.Rc)
ComputeRC(a); ComputeRC(gpr.GetImm(a), 0);
} }
else if (s == b) else if (s == b)
{ {
@ -161,30 +169,39 @@ void JitArm64::boolX(UGeckoInstruction inst)
{ {
if (a != s) if (a != s)
{ {
gpr.BindToRegister(a, false);
MOV(gpr.R(a), gpr.R(s)); MOV(gpr.R(a), gpr.R(s));
} }
if (inst.Rc)
ComputeRC(gpr.R(a));
} }
else if ((inst.SUBOP10 == 476 /* nandx */) || (inst.SUBOP10 == 124 /* norx */)) else if ((inst.SUBOP10 == 476 /* nandx */) || (inst.SUBOP10 == 124 /* norx */))
{ {
gpr.BindToRegister(a, a == s);
MVN(gpr.R(a), gpr.R(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 */)) else if ((inst.SUBOP10 == 412 /* orcx */) || (inst.SUBOP10 == 284 /* eqvx */))
{ {
gpr.SetImmediate(a, 0xFFFFFFFF); gpr.SetImmediate(a, 0xFFFFFFFF);
if (inst.Rc)
ComputeRC(gpr.GetImm(a), 0);
} }
else if ((inst.SUBOP10 == 60 /* andcx */) || (inst.SUBOP10 == 316 /* xorx */)) else if ((inst.SUBOP10 == 60 /* andcx */) || (inst.SUBOP10 == 316 /* xorx */))
{ {
gpr.SetImmediate(a, 0); gpr.SetImmediate(a, 0);
if (inst.Rc)
ComputeRC(gpr.GetImm(a), 0);
} }
else else
{ {
PanicAlert("WTF!"); PanicAlert("WTF!");
} }
if (inst.Rc)
ComputeRC(a);
} }
else else
{ {
gpr.BindToRegister(a, (a == s) || (a == b));
if (inst.SUBOP10 == 28) // andx if (inst.SUBOP10 == 28) // andx
{ {
AND(gpr.R(a), gpr.R(s), gpr.R(b), ArithOption(gpr.R(a), ST_LSL, 0)); 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!"); PanicAlert("WTF!");
} }
if (inst.Rc) 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 a = inst.RA, s = inst.RS;
int size = inst.SUBOP10 == 922 ? 16 : 8; int size = inst.SUBOP10 == 922 ? 16 : 8;
if (gpr.IsImm(s)) gpr.BindToRegister(a, a == s);
gpr.SetImmediate(a, (u32)(s32)(size == 16 ? (s16)gpr.GetImm(s) : (s8)gpr.GetImm(s)));
else if (gpr.IsImm(s))
SBFM(gpr.R(a), gpr.R(s), 0, size - 1); {
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) void JitArm64::cntlzwx(UGeckoInstruction inst)
@ -251,13 +276,20 @@ void JitArm64::cntlzwx(UGeckoInstruction inst)
int a = inst.RA; int a = inst.RA;
int s = inst.RS; int s = inst.RS;
if (gpr.IsImm(s)) gpr.BindToRegister(a, a == s);
gpr.SetImmediate(a, __builtin_clz(gpr.GetImm(s)));
else
CLZ(gpr.R(a), gpr.R(s));
if (inst.Rc) if (gpr.IsImm(s))
ComputeRC(a); {
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) void JitArm64::negx(UGeckoInstruction inst)
@ -269,11 +301,18 @@ void JitArm64::negx(UGeckoInstruction inst)
FALLBACK_IF(inst.OE); FALLBACK_IF(inst.OE);
if (gpr.IsImm(a)) gpr.BindToRegister(d, d == 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));
if (inst.Rc) if (gpr.IsImm(a))
ComputeRC(d); {
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);
}
} }