[ARM-JitArmIL] Enable a bunch of instructions.

This commit is contained in:
Ryan Houdek 2013-10-09 23:03:39 +00:00
parent f5e1b4659a
commit bd79603c66
3 changed files with 169 additions and 38 deletions

View File

@ -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;

View File

@ -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

View File

@ -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}},