summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorRyan Houdek <Sonicadvance1@Gmail.com>2013-10-09 23:03:39 +0000
committerRyan Houdek <Sonicadvance1@Gmail.com>2013-10-09 23:03:39 +0000
commitbd79603c66b54e77ca5b627460b6bdfd1936b2f4 (patch)
treee4ca503866bec29946dbdd74f814e697ec950b32 /Source/Core
parentf5e1b4659a5785d3573ba2b278995f8aa5afe94d (diff)
[ARM-JitArmIL] Enable a bunch of instructions.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArmIL/IR_Arm.cpp150
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.h1
-rw-r--r--Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Tables.cpp56
3 files changed, 169 insertions, 38 deletions
diff --git a/Source/Core/Core/Src/PowerPC/JitArmIL/IR_Arm.cpp b/Source/Core/Core/Src/PowerPC/JitArmIL/IR_Arm.cpp
index f9aad96ba4..5215f00fb3 100644
--- a/Source/Core/Core/Src/PowerPC/JitArmIL/IR_Arm.cpp
+++ b/Source/Core/Core/Src/PowerPC/JitArmIL/IR_Arm.cpp
@@ -56,7 +56,6 @@ static void regClearInst(RegInfo& RI, InstLoc I) {
if (RI.regs[RegAllocOrder[i]] == I)
RI.regs[RegAllocOrder[i]] = 0;
}
-
static void regNormalRegClear(RegInfo& RI, InstLoc I) {
if (RI.IInfo[I - RI.FirstI] & 4)
regClearInst(RI, getOp1(I));
@@ -125,6 +124,25 @@ static ARMReg regLocForInst(RegInfo& RI, InstLoc I) {
RI.Jit->LDR(reg, R14, 0);
return reg;
}
+static ARMReg regBinLHSReg(RegInfo& RI, InstLoc I) {
+ ARMReg reg = regFindFreeReg(RI);
+ RI.Jit->MOV(reg, regLocForInst(RI, getOp1(I)));
+ return reg;
+}
+
+// If the lifetime of the register used by an operand ends at I,
+// return the register. Otherwise return a free register.
+static ARMReg regBinReg(RegInfo& RI, InstLoc I) {
+ // FIXME: When regLocForInst() is extracted as a local variable,
+ // "Retrieving unknown spill slot?!" is shown.
+ if (RI.IInfo[I - RI.FirstI] & 4)
+ return regLocForInst(RI, getOp1(I));
+ else if (RI.IInfo[I - RI.FirstI] & 8)
+ return regLocForInst(RI, getOp2(I));
+
+ return regFindFreeReg(RI);
+}
+
static void regSpillCallerSaved(RegInfo& RI) {
regSpill(RI, R0);
regSpill(RI, R1);
@@ -144,17 +162,28 @@ static void regWriteExit(RegInfo& RI, InstLoc dest) {
}
}
static void regStoreInstToPPCState(RegInfo& RI, unsigned width, InstLoc I, s32 offset) {
- if (width != 32) {
- PanicAlert("Not implemented!");
- return;
+ void (JitArmIL::*op)(ARMReg, ARMReg, Operand2, bool);
+ switch(width)
+ {
+ case 32:
+ op = &JitArmIL::STR;
+ break;
+ case 8:
+ op = &JitArmIL::STRB;
+ break;
+ default:
+ PanicAlert("Not implemented!");
+ return;
+ break;
}
+
if (isImm(*I)) {
RI.Jit->MOVI2R(R12, RI.Build->GetImmValue(I));
- RI.Jit->STR(R12, R9, offset);
+ (RI.Jit->*op)(R12, R9, offset, true);
return;
}
ARMReg reg = regEnsureInReg(RI, I);
- RI.Jit->STR(reg, R9, offset);
+ (RI.Jit->*op)(reg, R9, offset, true);
}
//
@@ -177,6 +206,10 @@ void JitArmIL::BIN_XOR(ARMReg reg, Operand2 op2)
{
EOR(reg, reg, op2);
}
+void JitArmIL::BIN_OR(ARMReg reg, Operand2 op2)
+{
+ ORR(reg, reg, op2);
+}
void JitArmIL::BIN_AND(ARMReg reg, Operand2 op2)
{
AND(reg, reg, op2);
@@ -185,6 +218,19 @@ void JitArmIL::BIN_ADD(ARMReg reg, Operand2 op2)
{
ADD(reg, reg, op2);
}
+static void regEmitShiftInst(RegInfo& RI, InstLoc I, void (JitArmIL::*op)(ARMReg, ARMReg, Operand2))
+{
+ ARMReg reg = regBinLHSReg(RI, I);
+ if (isImm(*getOp2(I))) {
+ unsigned RHS = RI.Build->GetImmValue(getOp2(I));
+ (RI.Jit->*op)(reg, reg, RHS);
+ RI.regs[reg] = I;
+ return;
+ }
+ (RI.Jit->*op)(reg, reg, regLocForInst(RI, getOp2(I)));
+ RI.regs[reg] = I;
+ regNormalRegClear(RI, I);
+}
static void regEmitBinInst(RegInfo& RI, InstLoc I,
void (JitArmIL::*op)(ARMReg, Operand2),
@@ -202,10 +248,13 @@ static void regEmitBinInst(RegInfo& RI, InstLoc I,
}
if (isImm(*getOp2(I))) {
unsigned RHS = RI.Build->GetImmValue(getOp2(I));
- if (RHS + 128 < 256) {
- (RI.Jit->*op)(reg, RHS);
- } else {
- (RI.Jit->*op)(reg, RHS);
+ Operand2 RHSop;
+ if (TryMakeOperand2(RHS, RHSop))
+ (RI.Jit->*op)(reg, RHSop);
+ else
+ {
+ RI.Jit->MOVI2R(R12, RHS);
+ (RI.Jit->*op)(reg, R12);
}
} else if (commuted) {
(RI.Jit->*op)(reg, regLocForInst(RI, getOp1(I)));
@@ -215,6 +264,22 @@ static void regEmitBinInst(RegInfo& RI, InstLoc I,
RI.regs[reg] = I;
regNormalRegClear(RI, I);
}
+static void regEmitCmp(RegInfo& RI, InstLoc I) {
+ if (isImm(*getOp2(I))) {
+ unsigned RHS = RI.Build->GetImmValue(getOp2(I));
+ Operand2 op;
+ if (TryMakeOperand2(RHS, op))
+ RI.Jit->CMP(regLocForInst(RI, getOp1(I)), op);
+ else
+ {
+ RI.Jit->MOVI2R(R12, RHS);
+ RI.Jit->CMP(regLocForInst(RI, getOp1(I)), R12);
+ }
+ } else {
+ ARMReg reg = regEnsureInReg(RI, getOp1(I));
+ RI.Jit->CMP(reg, regLocForInst(RI, getOp2(I)));
+ }
+}
static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit) {
RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts());
@@ -447,6 +512,18 @@ static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit) {
break;
}
+ case StoreGReg: {
+ unsigned ppcreg = *I >> 16;
+ regStoreInstToPPCState(RI, 32, getOp1(I), PPCSTATE_OFF(gpr[ppcreg]));
+ regNormalRegClear(RI, I);
+ break;
+ }
+ case StoreCR: {
+ unsigned ppcreg = *I >> 16;
+ regStoreInstToPPCState(RI, 8, getOp1(I), PPCSTATE_OFF(cr_fast[ppcreg]));
+ regNormalRegClear(RI, I);
+ break;
+ }
case StoreLink: {
regStoreInstToPPCState(RI, 32, getOp1(I), PPCSTATE_OFF(spr[SPR_LR]));
regNormalRegClear(RI, I);
@@ -565,11 +642,39 @@ static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit) {
Jit->WriteRfiExitDestInR(rA); // rA gets unlocked here
break;
}
+ case Shl: {
+ if (!thisUsed) break;
+ regEmitShiftInst(RI, I, &JitArmIL::LSL);
+ break;
+ }
+ case Shrl: {
+ if (!thisUsed) break;
+ regEmitShiftInst(RI, I, &JitArmIL::LSR);
+ break;
+ }
+ case Sarl: {
+ if (!thisUsed) break;
+ regEmitShiftInst(RI, I, &JitArmIL::ASR);
+ break;
+ }
case And: {
if (!thisUsed) break;
regEmitBinInst(RI, I, &JitArmIL::BIN_AND, true);
break;
}
+ case Not: {
+ if (!thisUsed) break;
+ ARMReg reg = regBinLHSReg(RI, I);
+ Jit->MVN(reg, reg);
+ RI.regs[reg] = I;
+ regNormalRegClear(RI, I);
+ break;
+ }
+ case Or: {
+ if (!thisUsed) break;
+ regEmitBinInst(RI, I, &JitArmIL::BIN_OR, true);
+ break;
+ }
case Xor: {
if (!thisUsed) break;
regEmitBinInst(RI, I, &JitArmIL::BIN_XOR, true);
@@ -580,6 +685,31 @@ static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit) {
regEmitBinInst(RI, I, &JitArmIL::BIN_ADD, true);
break;
}
+ case ICmpCRUnsigned: {
+ if (!thisUsed) break;
+ regEmitCmp(RI, I);
+ ARMReg reg = regBinReg(RI, I);
+ Jit->MOV(reg, 0x2); // Result == 0
+ Jit->SetCC(CC_LO); Jit->MOV(reg, 0x8); // Result < 0
+ Jit->SetCC(CC_HI); Jit->MOV(reg, 0x4); // Result > 0
+ Jit->SetCC();
+ RI.regs[reg] = I;
+ regNormalRegClear(RI, I);
+ break;
+ }
+
+ case ICmpCRSigned: {
+ if (!thisUsed) break;
+ regEmitCmp(RI, I);
+ ARMReg reg = regBinReg(RI, I);
+ Jit->MOV(reg, 0x2); // Result == 0
+ Jit->SetCC(CC_LT); Jit->MOV(reg, 0x8); // Result < 0
+ Jit->SetCC(CC_GT); Jit->MOV(reg, 0x4); // Result > 0
+ Jit->SetCC();
+ RI.regs[reg] = I;
+ regNormalRegClear(RI, I);
+ break;
+ }
case Int3:
Jit->BKPT(0x321);
break;
diff --git a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.h b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.h
index ccbf35bc28..e0462cf852 100644
--- a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.h
+++ b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.h
@@ -86,6 +86,7 @@ public:
// Binary ops
void BIN_AND(ARMReg reg, Operand2 op2);
void BIN_XOR(ARMReg reg, Operand2 op2);
+ void BIN_OR(ARMReg reg, Operand2 op2);
void BIN_ADD(ARMReg reg, Operand2 op2);
// Branches
diff --git a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Tables.cpp b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Tables.cpp
index 31d7504d64..2f6677c952 100644
--- a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Tables.cpp
+++ b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL_Tables.cpp
@@ -47,23 +47,23 @@ static GekkoOPTemplate primarytable[] =
{7, &JitArmIL::Default}, //"mulli", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_RC_BIT, 2}},
{8, &JitArmIL::Default}, //"subfic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},
- {10, &JitArmIL::Default}, //"cmpli", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
- {11, &JitArmIL::Default}, //"cmpi", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
+ {10, &JitArmIL::cmpXX}, //"cmpli", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
+ {11, &JitArmIL::cmpXX}, //"cmpi", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
{12, &JitArmIL::Default}, //"addic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},
{13, &JitArmIL::Default}, //"addic_rc", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CR0}},
- {14, &JitArmIL::Default}, //"addi", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
- {15, &JitArmIL::Default}, //"addis", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
+ {14, &JitArmIL::reg_imm}, //"addi", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
+ {15, &JitArmIL::reg_imm}, //"addis", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
{20, &JitArmIL::Default}, //"rlwimix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_A | FL_IN_S | FL_RC_BIT}},
{21, &JitArmIL::Default}, //"rlwinmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{23, &JitArmIL::Default}, //"rlwnmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_IN_B | FL_RC_BIT}},
- {24, &JitArmIL::Default}, //"ori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
- {25, &JitArmIL::Default}, //"oris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
- {26, &JitArmIL::Default}, //"xori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
- {27, &JitArmIL::Default}, //"xoris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
- {28, &JitArmIL::Default}, //"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
- {29, &JitArmIL::Default}, //"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
+ {24, &JitArmIL::reg_imm}, //"ori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
+ {25, &JitArmIL::reg_imm}, //"oris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
+ {26, &JitArmIL::reg_imm}, //"xori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
+ {27, &JitArmIL::reg_imm}, //"xoris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
+ {28, &JitArmIL::reg_imm}, //"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
+ {29, &JitArmIL::reg_imm}, //"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{32, &JitArmIL::Default}, //"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{33, &JitArmIL::Default}, //"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
@@ -162,14 +162,14 @@ static GekkoOPTemplate table19[] =
{
{528, &JitArmIL::bcctrx}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
{16, &JitArmIL::bclrx}, //"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
- {257, &JitArmIL::Default}, //"crand", OPTYPE_CR, FL_EVIL}},
- {129, &JitArmIL::Default}, //"crandc", OPTYPE_CR, FL_EVIL}},
- {289, &JitArmIL::Default}, //"creqv", OPTYPE_CR, FL_EVIL}},
- {225, &JitArmIL::Default}, //"crnand", OPTYPE_CR, FL_EVIL}},
- {33, &JitArmIL::Default}, //"crnor", OPTYPE_CR, FL_EVIL}},
- {449, &JitArmIL::Default}, //"cror", OPTYPE_CR, FL_EVIL}},
- {417, &JitArmIL::Default}, //"crorc", OPTYPE_CR, FL_EVIL}},
- {193, &JitArmIL::Default}, //"crxor", OPTYPE_CR, FL_EVIL}},
+ {257, &JitArmIL::crXX}, //"crand", OPTYPE_CR, FL_EVIL}},
+ {129, &JitArmIL::crXX}, //"crandc", OPTYPE_CR, FL_EVIL}},
+ {289, &JitArmIL::crXX}, //"creqv", OPTYPE_CR, FL_EVIL}},
+ {225, &JitArmIL::crXX}, //"crnand", OPTYPE_CR, FL_EVIL}},
+ {33, &JitArmIL::crXX}, //"crnor", OPTYPE_CR, FL_EVIL}},
+ {449, &JitArmIL::crXX}, //"cror", OPTYPE_CR, FL_EVIL}},
+ {417, &JitArmIL::crXX}, //"crorc", OPTYPE_CR, FL_EVIL}},
+ {193, &JitArmIL::crXX}, //"crxor", OPTYPE_CR, FL_EVIL}},
{150, &JitArmIL::Default}, //"isync", OPTYPE_ICACHE, FL_EVIL}},
{0, &JitArmIL::Default}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}},
@@ -181,16 +181,16 @@ static GekkoOPTemplate table19[] =
static GekkoOPTemplate table31[] =
{
- {28, &JitArmIL::Default}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
- {60, &JitArmIL::Default}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
- {444, &JitArmIL::Default}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
- {124, &JitArmIL::Default}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
- {316, &JitArmIL::Default}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
- {412, &JitArmIL::Default}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
- {476, &JitArmIL::Default}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
- {284, &JitArmIL::Default}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
- {0, &JitArmIL::Default}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
- {32, &JitArmIL::Default}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
+ {28, &JitArmIL::boolX}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {60, &JitArmIL::boolX}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {444, &JitArmIL::boolX}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {124, &JitArmIL::boolX}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {316, &JitArmIL::boolX}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {412, &JitArmIL::boolX}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {476, &JitArmIL::boolX}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {284, &JitArmIL::boolX}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
+ {0, &JitArmIL::cmpXX}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
+ {32, &JitArmIL::cmpXX}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
{26, &JitArmIL::Default}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{922, &JitArmIL::Default}, //"extshx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{954, &JitArmIL::Default}, //"extsbx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},