[ARM-JitArmIL] Enable a bunch of instructions.
This commit is contained in:
parent
f5e1b4659a
commit
bd79603c66
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}},
|
||||
|
|
Loading…
Reference in New Issue