Skip to content

Commit

Permalink
Merge pull request #1113 from Sonicadvance1/AArch64-integer-ops
Browse files Browse the repository at this point in the history
[AArch64] Implement a bunch of integer instructions
  • Loading branch information
Sonicadvance1 committed Sep 19, 2014
2 parents 5671530 + bdca720 commit 235546b
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 29 deletions.
1 change: 1 addition & 0 deletions Source/Core/Core/CMakeLists.txt
Expand Up @@ -225,6 +225,7 @@ elseif(_M_ARM_64)
PowerPC/JitArm64/JitArm64Cache.cpp
PowerPC/JitArm64/JitArm64_RegCache.cpp
PowerPC/JitArm64/JitArm64_Branch.cpp
PowerPC/JitArm64/JitArm64_Integer.cpp
PowerPC/JitArm64/JitArm64_LoadStore.cpp
PowerPC/JitArm64/JitArm64_SystemRegisters.cpp
PowerPC/JitArm64/JitArm64_Tables.cpp)
Expand Down
26 changes: 13 additions & 13 deletions Source/Core/Core/PowerPC/JitArm64/Jit.cpp
Expand Up @@ -255,19 +255,19 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
}
if (!ops[i].skip)
{
if (js.memcheck && (opinfo->flags & FL_USE_FPU))
{
// Don't do this yet
BRK(0x7777);
}

JitArm64Tables::CompileInstruction(ops[i]);

if (js.memcheck && (opinfo->flags & FL_LOADSTORE))
{
// Don't do this yet
BRK(0x666);
}
if (js.memcheck && (opinfo->flags & FL_USE_FPU))
{
// Don't do this yet
BRK(0x7777);
}

JitArm64Tables::CompileInstruction(ops[i]);

if (js.memcheck && (opinfo->flags & FL_LOADSTORE))
{
// Don't do this yet
BRK(0x666);
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions Source/Core/Core/PowerPC/JitArm64/Jit.h
Expand Up @@ -77,6 +77,10 @@ class JitArm64 : public JitBase, public Arm64Gen::ARM64CodeBlock
void bcctrx(UGeckoInstruction inst);
void bclrx(UGeckoInstruction inst);

// Integer
void arith_imm(UGeckoInstruction inst);
void boolX(UGeckoInstruction inst);

// System Registers
void mtmsr(UGeckoInstruction inst);

Expand All @@ -102,5 +106,10 @@ class JitArm64 : public JitBase, public Arm64Gen::ARM64CodeBlock
void WriteExitDestInR(ARM64Reg dest);

FixupBranch JumpIfCRFieldBit(int field, int bit, bool jump_if_set);

void ComputeRC(u32 d);

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);
};

229 changes: 229 additions & 0 deletions Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp
@@ -0,0 +1,229 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#include "Common/Arm64Emitter.h"
#include "Common/Common.h"

#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/PPCTables.h"
#include "Core/PowerPC/JitArm64/Jit.h"
#include "Core/PowerPC/JitArm64/JitArm64_RegCache.h"
#include "Core/PowerPC/JitArm64/JitAsm.h"

using namespace Arm64Gen;

void JitArm64::ComputeRC(u32 d)
{
ARM64Reg WA = gpr.GetReg();
ARM64Reg XA = EncodeRegTo64(WA);

if (gpr.IsImm(d))
{
MOVI2R(XA, gpr.GetImm(d));
SXTW(XA, XA);
}
else
{
SXTW(XA, gpr.R(d));
}

STR(INDEX_UNSIGNED, XA, X29, PPCSTATE_OFF(cr_val[0]));
gpr.Unlock(WA);
}

// 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)
{
return a | b;
}

static u32 And(u32 a, u32 b)
{
return a & b;
}

static u32 Xor(u32 a, u32 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)
{
if (a || binary)
{
if (gpr.IsImm(a))
{
gpr.SetImmediate(d, do_op(gpr.GetImm(a), value));
}
else
{
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);
}
else if (do_op == Add)
{
// a == 0, implies zero register
gpr.SetImmediate(d, value);
if (Rc)
ComputeRC(d);
}
else
{
_assert_msg_(DYNA_REC, false, "Hit impossible condition in reg_imm!");
}
}

void JitArm64::arith_imm(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITIntegerOff);
u32 d = inst.RD, a = inst.RA, s = inst.RS;

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
if (a == 0 && s == 0 && inst.UIMM == 0 && !inst.Rc) //check for nop
{
// NOP
return;
}
reg_imm(a, s, true, inst.UIMM, Or, &ARM64XEmitter::ORR);
break;
case 25: // oris
reg_imm(a, s, true, inst.UIMM << 16, Or, &ARM64XEmitter::ORR);
break;
case 28: // andi
reg_imm(a, s, true, inst.UIMM, And, &ARM64XEmitter::AND, true);
break;
case 29: // andis
reg_imm(a, s, true, inst.UIMM << 16, And, &ARM64XEmitter::AND, true);
break;
case 26: // xori
reg_imm(a, s, true, inst.UIMM, Xor, &ARM64XEmitter::EOR);
break;
case 27: // xoris
reg_imm(a, s, true, inst.UIMM << 16, Xor, &ARM64XEmitter::EOR);
break;
}
}

void JitArm64::boolX(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITIntegerOff);
int a = inst.RA, s = inst.RS, b = inst.RB;

if (gpr.IsImm(s) && gpr.IsImm(b))
{
if (inst.SUBOP10 == 28) // andx
gpr.SetImmediate(a, (u32)gpr.GetImm(s) & (u32)gpr.GetImm(b));
else if (inst.SUBOP10 == 476) // nandx
gpr.SetImmediate(a, ~((u32)gpr.GetImm(s) & (u32)gpr.GetImm(b)));
else if (inst.SUBOP10 == 60) // andcx
gpr.SetImmediate(a, (u32)gpr.GetImm(s) & (~(u32)gpr.GetImm(b)));
else if (inst.SUBOP10 == 444) // orx
gpr.SetImmediate(a, (u32)gpr.GetImm(s) | (u32)gpr.GetImm(b));
else if (inst.SUBOP10 == 124) // norx
gpr.SetImmediate(a, ~((u32)gpr.GetImm(s) | (u32)gpr.GetImm(b)));
else if (inst.SUBOP10 == 412) // orcx
gpr.SetImmediate(a, (u32)gpr.GetImm(s) | (~(u32)gpr.GetImm(b)));
else if (inst.SUBOP10 == 316) // xorx
gpr.SetImmediate(a, (u32)gpr.GetImm(s) ^ (u32)gpr.GetImm(b));
else if (inst.SUBOP10 == 284) // eqvx
gpr.SetImmediate(a, ~((u32)gpr.GetImm(s) ^ (u32)gpr.GetImm(b)));

if (inst.Rc)
ComputeRC(a);
}
else if (s == b)
{
if ((inst.SUBOP10 == 28 /* andx */) || (inst.SUBOP10 == 444 /* orx */))
{
if (a != s)
{
MOV(gpr.R(a), gpr.R(s));
}
}
else if ((inst.SUBOP10 == 476 /* nandx */) || (inst.SUBOP10 == 124 /* norx */))
{
MVN(gpr.R(a), gpr.R(s));
}
else if ((inst.SUBOP10 == 412 /* orcx */) || (inst.SUBOP10 == 284 /* eqvx */))
{
gpr.SetImmediate(a, 0xFFFFFFFF);
}
else if ((inst.SUBOP10 == 60 /* andcx */) || (inst.SUBOP10 == 316 /* xorx */))
{
gpr.SetImmediate(a, 0);
}
else
{
PanicAlert("WTF!");
}
if (inst.Rc)
ComputeRC(a);
}
else
{
if (inst.SUBOP10 == 28) // andx
{
AND(gpr.R(a), gpr.R(s), gpr.R(b), ArithOption(gpr.R(a), ST_LSL, 0));
}
else if (inst.SUBOP10 == 476) // nandx
{
AND(gpr.R(a), gpr.R(s), gpr.R(b), ArithOption(gpr.R(a), ST_LSL, 0));
MVN(gpr.R(a), gpr.R(a));
}
else if (inst.SUBOP10 == 60) // andcx
{
BIC(gpr.R(a), gpr.R(s), gpr.R(b), ArithOption(gpr.R(a), ST_LSL, 0));
}
else if (inst.SUBOP10 == 444) // orx
{
ORR(gpr.R(a), gpr.R(s), gpr.R(b), ArithOption(gpr.R(a), ST_LSL, 0));
}
else if (inst.SUBOP10 == 124) // norx
{
ORR(gpr.R(a), gpr.R(s), gpr.R(b), ArithOption(gpr.R(a), ST_LSL, 0));
MVN(gpr.R(a), gpr.R(a));
}
else if (inst.SUBOP10 == 412) // orcx
{
ORN(gpr.R(a), gpr.R(s), gpr.R(b), ArithOption(gpr.R(a), ST_LSL, 0));
}
else if (inst.SUBOP10 == 316) // xorx
{
EOR(gpr.R(a), gpr.R(s), gpr.R(b), ArithOption(gpr.R(a), ST_LSL, 0));
}
else if (inst.SUBOP10 == 284) // eqvx
{
EON(gpr.R(a), gpr.R(b), gpr.R(s), ArithOption(gpr.R(a), ST_LSL, 0));
}
else
{
PanicAlert("WTF!");
}
if (inst.Rc)
ComputeRC(a);
}
}
32 changes: 16 additions & 16 deletions Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp
Expand Up @@ -51,19 +51,19 @@ static GekkoOPTemplate primarytable[] =
{11, &JitArm64::FallBackToInterpreter}, //"cmpi", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
{12, &JitArm64::FallBackToInterpreter}, //"addic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},
{13, &JitArm64::FallBackToInterpreter}, //"addic_rc", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CR0}},
{14, &JitArm64::FallBackToInterpreter}, //"addi", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
{15, &JitArm64::FallBackToInterpreter}, //"addis", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
{14, &JitArm64::arith_imm}, //"addi", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
{15, &JitArm64::arith_imm}, //"addis", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},

{20, &JitArm64::FallBackToInterpreter}, //"rlwimix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_A | FL_IN_S | FL_RC_BIT}},
{21, &JitArm64::FallBackToInterpreter}, //"rlwinmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{23, &JitArm64::FallBackToInterpreter}, //"rlwnmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_IN_B | FL_RC_BIT}},

{24, &JitArm64::FallBackToInterpreter}, //"ori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{25, &JitArm64::FallBackToInterpreter}, //"oris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{26, &JitArm64::FallBackToInterpreter}, //"xori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{27, &JitArm64::FallBackToInterpreter}, //"xoris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{28, &JitArm64::FallBackToInterpreter}, //"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{29, &JitArm64::FallBackToInterpreter}, //"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{24, &JitArm64::arith_imm}, //"ori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{25, &JitArm64::arith_imm}, //"oris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{26, &JitArm64::arith_imm}, //"xori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{27, &JitArm64::arith_imm}, //"xoris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{28, &JitArm64::arith_imm}, //"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{29, &JitArm64::arith_imm}, //"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},

{32, &JitArm64::FallBackToInterpreter}, //"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{33, &JitArm64::FallBackToInterpreter}, //"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
Expand Down Expand Up @@ -181,14 +181,14 @@ static GekkoOPTemplate table19[] =

static GekkoOPTemplate table31[] =
{
{28, &JitArm64::FallBackToInterpreter}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{60, &JitArm64::FallBackToInterpreter}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{444, &JitArm64::FallBackToInterpreter}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{124, &JitArm64::FallBackToInterpreter}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{316, &JitArm64::FallBackToInterpreter}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{412, &JitArm64::FallBackToInterpreter}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{476, &JitArm64::FallBackToInterpreter}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{284, &JitArm64::FallBackToInterpreter}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{28, &JitArm64::boolX}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{60, &JitArm64::boolX}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{444, &JitArm64::boolX}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{124, &JitArm64::boolX}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{316, &JitArm64::boolX}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{412, &JitArm64::boolX}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{476, &JitArm64::boolX}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{284, &JitArm64::boolX}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{0, &JitArm64::FallBackToInterpreter}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
{32, &JitArm64::FallBackToInterpreter}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
{26, &JitArm64::FallBackToInterpreter}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
Expand Down

0 comments on commit 235546b

Please sign in to comment.