Implemented more JIT instructions
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6008 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
87043879f8
commit
12be9952ab
|
@ -524,7 +524,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
||||||
js.compilerPC = ops[i].address;
|
js.compilerPC = ops[i].address;
|
||||||
js.op = &ops[i];
|
js.op = &ops[i];
|
||||||
js.instructionNumber = i;
|
js.instructionNumber = i;
|
||||||
const GekkoOPInfo *opinfo = GetOpInfo(ops[i].inst);
|
const GekkoOPInfo *opinfo = ops[i].opinfo;
|
||||||
js.downcountAmount += (opinfo->numCyclesMinusOne + 1);
|
js.downcountAmount += (opinfo->numCyclesMinusOne + 1);
|
||||||
|
|
||||||
if (i == (int)size - 1)
|
if (i == (int)size - 1)
|
||||||
|
|
|
@ -169,9 +169,15 @@ public:
|
||||||
void DynaRunTable63(UGeckoInstruction _inst);
|
void DynaRunTable63(UGeckoInstruction _inst);
|
||||||
|
|
||||||
void addx(UGeckoInstruction inst);
|
void addx(UGeckoInstruction inst);
|
||||||
|
void addcx(UGeckoInstruction inst);
|
||||||
void orx(UGeckoInstruction inst);
|
void orx(UGeckoInstruction inst);
|
||||||
|
void orcx(UGeckoInstruction inst);
|
||||||
|
void norx(UGeckoInstruction inst);
|
||||||
void xorx(UGeckoInstruction inst);
|
void xorx(UGeckoInstruction inst);
|
||||||
|
void eqvx(UGeckoInstruction inst);
|
||||||
void andx(UGeckoInstruction inst);
|
void andx(UGeckoInstruction inst);
|
||||||
|
void nandx(UGeckoInstruction inst);
|
||||||
|
void andcx(UGeckoInstruction inst);
|
||||||
void mulli(UGeckoInstruction inst);
|
void mulli(UGeckoInstruction inst);
|
||||||
void mulhwux(UGeckoInstruction inst);
|
void mulhwux(UGeckoInstruction inst);
|
||||||
void mullwx(UGeckoInstruction inst);
|
void mullwx(UGeckoInstruction inst);
|
||||||
|
@ -179,6 +185,8 @@ public:
|
||||||
void srawix(UGeckoInstruction inst);
|
void srawix(UGeckoInstruction inst);
|
||||||
void srawx(UGeckoInstruction inst);
|
void srawx(UGeckoInstruction inst);
|
||||||
void addex(UGeckoInstruction inst);
|
void addex(UGeckoInstruction inst);
|
||||||
|
void addmex(UGeckoInstruction inst);
|
||||||
|
void addzex(UGeckoInstruction inst);
|
||||||
|
|
||||||
void extsbx(UGeckoInstruction inst);
|
void extsbx(UGeckoInstruction inst);
|
||||||
void extshx(UGeckoInstruction inst);
|
void extshx(UGeckoInstruction inst);
|
||||||
|
@ -198,6 +206,17 @@ public:
|
||||||
void mftb(UGeckoInstruction inst);
|
void mftb(UGeckoInstruction inst);
|
||||||
void mtcrf(UGeckoInstruction inst);
|
void mtcrf(UGeckoInstruction inst);
|
||||||
void mfcr(UGeckoInstruction inst);
|
void mfcr(UGeckoInstruction inst);
|
||||||
|
void mcrf(UGeckoInstruction inst);
|
||||||
|
void mcrxr(UGeckoInstruction inst);
|
||||||
|
|
||||||
|
void crand(UGeckoInstruction inst);
|
||||||
|
void crandc(UGeckoInstruction inst);
|
||||||
|
void creqv(UGeckoInstruction inst);
|
||||||
|
void crnand(UGeckoInstruction inst);
|
||||||
|
void crnor(UGeckoInstruction inst);
|
||||||
|
void cror(UGeckoInstruction inst);
|
||||||
|
void crorc(UGeckoInstruction inst);
|
||||||
|
void crxor(UGeckoInstruction inst);
|
||||||
|
|
||||||
void reg_imm(UGeckoInstruction inst);
|
void reg_imm(UGeckoInstruction inst);
|
||||||
|
|
||||||
|
@ -247,6 +266,8 @@ public:
|
||||||
void subfcx(UGeckoInstruction inst);
|
void subfcx(UGeckoInstruction inst);
|
||||||
void subfx(UGeckoInstruction inst);
|
void subfx(UGeckoInstruction inst);
|
||||||
void subfex(UGeckoInstruction inst);
|
void subfex(UGeckoInstruction inst);
|
||||||
|
void subfmex(UGeckoInstruction inst);
|
||||||
|
void subfzex(UGeckoInstruction inst);
|
||||||
|
|
||||||
void lbzx(UGeckoInstruction inst);
|
void lbzx(UGeckoInstruction inst);
|
||||||
void lwzx(UGeckoInstruction inst);
|
void lwzx(UGeckoInstruction inst);
|
||||||
|
|
|
@ -174,17 +174,17 @@ static GekkoOPTemplate table19[] =
|
||||||
{
|
{
|
||||||
{528, &Jit64::bcctrx}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
|
{528, &Jit64::bcctrx}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
|
||||||
{16, &Jit64::bclrx}, //"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
|
{16, &Jit64::bclrx}, //"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
|
||||||
{257, &Jit64::Default}, //"crand", OPTYPE_CR, FL_EVIL}},
|
{257, &Jit64::crand}, //"crand", OPTYPE_CR, FL_EVIL}},
|
||||||
{129, &Jit64::Default}, //"crandc", OPTYPE_CR, FL_EVIL}},
|
{129, &Jit64::crandc}, //"crandc", OPTYPE_CR, FL_EVIL}},
|
||||||
{289, &Jit64::Default}, //"creqv", OPTYPE_CR, FL_EVIL}},
|
{289, &Jit64::creqv}, //"creqv", OPTYPE_CR, FL_EVIL}},
|
||||||
{225, &Jit64::Default}, //"crnand", OPTYPE_CR, FL_EVIL}},
|
{225, &Jit64::crnand}, //"crnand", OPTYPE_CR, FL_EVIL}},
|
||||||
{33, &Jit64::Default}, //"crnor", OPTYPE_CR, FL_EVIL}},
|
{33, &Jit64::crnor}, //"crnor", OPTYPE_CR, FL_EVIL}},
|
||||||
{449, &Jit64::Default}, //"cror", OPTYPE_CR, FL_EVIL}},
|
{449, &Jit64::cror}, //"cror", OPTYPE_CR, FL_EVIL}},
|
||||||
{417, &Jit64::Default}, //"crorc", OPTYPE_CR, FL_EVIL}},
|
{417, &Jit64::crorc}, //"crorc", OPTYPE_CR, FL_EVIL}},
|
||||||
{193, &Jit64::Default}, //"crxor", OPTYPE_CR, FL_EVIL}},
|
{193, &Jit64::crxor}, //"crxor", OPTYPE_CR, FL_EVIL}},
|
||||||
|
|
||||||
{150, &Jit64::DoNothing}, //"isync", OPTYPE_ICACHE, FL_EVIL}},
|
{150, &Jit64::DoNothing}, //"isync", OPTYPE_ICACHE, FL_EVIL}},
|
||||||
{0, &Jit64::Default}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}},
|
{0, &Jit64::mcrf}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}},
|
||||||
|
|
||||||
{50, &Jit64::rfi}, //"rfi", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS, 1}},
|
{50, &Jit64::rfi}, //"rfi", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS, 1}},
|
||||||
{18, &Jit64::Default}, //"rfid", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS}}
|
{18, &Jit64::Default}, //"rfid", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS}}
|
||||||
|
@ -194,13 +194,13 @@ static GekkoOPTemplate table19[] =
|
||||||
static GekkoOPTemplate table31[] =
|
static GekkoOPTemplate table31[] =
|
||||||
{
|
{
|
||||||
{28, &Jit64::andx}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
{28, &Jit64::andx}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||||
{60, &Jit64::Default}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
{60, &Jit64::andcx}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||||
{444, &Jit64::orx}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
{444, &Jit64::orx}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||||
{124, &Jit64::Default}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
{124, &Jit64::norx}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||||
{316, &Jit64::xorx}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
{316, &Jit64::xorx}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||||
{412, &Jit64::Default}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
{412, &Jit64::orcx}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||||
{476, &Jit64::Default}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
{476, &Jit64::nandx}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||||
{284, &Jit64::Default}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
{284, &Jit64::eqvx}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||||
{0, &Jit64::cmpXX}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
|
{0, &Jit64::cmpXX}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
|
||||||
{32, &Jit64::cmpXX}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
|
{32, &Jit64::cmpXX}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
|
||||||
{26, &Jit64::cntlzwx}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
|
{26, &Jit64::cntlzwx}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
|
||||||
|
@ -287,7 +287,7 @@ static GekkoOPTemplate table31[] =
|
||||||
{339, &Jit64::mfspr}, //"mfspr", OPTYPE_SPR, FL_OUT_D}},
|
{339, &Jit64::mfspr}, //"mfspr", OPTYPE_SPR, FL_OUT_D}},
|
||||||
{467, &Jit64::mtspr}, //"mtspr", OPTYPE_SPR, 0, 2}},
|
{467, &Jit64::mtspr}, //"mtspr", OPTYPE_SPR, 0, 2}},
|
||||||
{371, &Jit64::mftb}, //"mftb", OPTYPE_SYSTEM, FL_OUT_D | FL_TIMER}},
|
{371, &Jit64::mftb}, //"mftb", OPTYPE_SYSTEM, FL_OUT_D | FL_TIMER}},
|
||||||
{512, &Jit64::Default}, //"mcrxr", OPTYPE_SYSTEM, 0}},
|
{512, &Jit64::mcrxr}, //"mcrxr", OPTYPE_SYSTEM, 0}},
|
||||||
{595, &Jit64::Default}, //"mfsr", OPTYPE_SYSTEM, FL_OUT_D, 2}},
|
{595, &Jit64::Default}, //"mfsr", OPTYPE_SYSTEM, FL_OUT_D, 2}},
|
||||||
{659, &Jit64::Default}, //"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 2}},
|
{659, &Jit64::Default}, //"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 2}},
|
||||||
|
|
||||||
|
@ -307,10 +307,10 @@ static GekkoOPTemplate table31[] =
|
||||||
static GekkoOPTemplate table31_2[] =
|
static GekkoOPTemplate table31_2[] =
|
||||||
{
|
{
|
||||||
{266, &Jit64::addx}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
|
{266, &Jit64::addx}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
|
||||||
{10, &Jit64::Default}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
|
{10, &Jit64::addcx}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
|
||||||
{138, &Jit64::addex}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
{138, &Jit64::addex}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
||||||
{234, &Jit64::Default}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
{234, &Jit64::addmex}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
||||||
{202, &Jit64::Default}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
{202, &Jit64::addzex}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
||||||
{491, &Jit64::Default}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
|
{491, &Jit64::Default}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
|
||||||
{459, &Jit64::divwux}, //"divwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
|
{459, &Jit64::divwux}, //"divwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
|
||||||
{75, &Jit64::Default}, //"mulhwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
|
{75, &Jit64::Default}, //"mulhwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
|
||||||
|
@ -320,8 +320,8 @@ static GekkoOPTemplate table31_2[] =
|
||||||
{40, &Jit64::subfx}, //"subfx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
|
{40, &Jit64::subfx}, //"subfx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
|
||||||
{8, &Jit64::subfcx}, //"subfcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
|
{8, &Jit64::subfcx}, //"subfcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
|
||||||
{136, &Jit64::subfex}, //"subfex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
{136, &Jit64::subfex}, //"subfex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
||||||
{232, &Jit64::Default}, //"subfmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
{232, &Jit64::subfmex}, //"subfmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
||||||
{200, &Jit64::Default}, //"subfzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
{200, &Jit64::subfzex}, //"subfzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
||||||
};
|
};
|
||||||
|
|
||||||
static GekkoOPTemplate table59[] =
|
static GekkoOPTemplate table59[] =
|
||||||
|
|
|
@ -28,29 +28,42 @@
|
||||||
void Jit64::GenerateCarry() {
|
void Jit64::GenerateCarry() {
|
||||||
// USES_XER
|
// USES_XER
|
||||||
FixupBranch pNoCarry = J_CC(CC_NC);
|
FixupBranch pNoCarry = J_CC(CC_NC);
|
||||||
OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(1 << 29));
|
OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(XER_CA_MASK));
|
||||||
FixupBranch pContinue = J();
|
FixupBranch pContinue = J();
|
||||||
SetJumpTarget(pNoCarry);
|
SetJumpTarget(pNoCarry);
|
||||||
AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~(1 << 29)));
|
AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~(XER_CA_MASK)));
|
||||||
SetJumpTarget(pContinue);
|
SetJumpTarget(pContinue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::ComputeRC(const Gen::OpArg & arg) {
|
void Jit64::ComputeRC(const Gen::OpArg & arg) {
|
||||||
CMP(32, arg, Imm8(0));
|
if( arg.IsImm() )
|
||||||
FixupBranch pLesser = J_CC(CC_L);
|
{
|
||||||
FixupBranch pGreater = J_CC(CC_G);
|
s32 value = (s32)arg.offset;
|
||||||
MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x2)); // _x86Reg == 0
|
if( value < 0 )
|
||||||
FixupBranch continue1 = J();
|
MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x8));
|
||||||
|
else if( value > 0 )
|
||||||
|
MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x4));
|
||||||
|
else
|
||||||
|
MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CMP(32, arg, Imm8(0));
|
||||||
|
FixupBranch pLesser = J_CC(CC_L);
|
||||||
|
FixupBranch pGreater = J_CC(CC_G);
|
||||||
|
MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x2)); // _x86Reg == 0
|
||||||
|
FixupBranch continue1 = J();
|
||||||
|
|
||||||
SetJumpTarget(pGreater);
|
SetJumpTarget(pGreater);
|
||||||
MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x4)); // _x86Reg > 0
|
MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x4)); // _x86Reg > 0
|
||||||
FixupBranch continue2 = J();
|
FixupBranch continue2 = J();
|
||||||
|
|
||||||
SetJumpTarget(pLesser);
|
SetJumpTarget(pLesser);
|
||||||
MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x8)); // _x86Reg < 0
|
MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x8)); // _x86Reg < 0
|
||||||
|
|
||||||
SetJumpTarget(continue1);
|
SetJumpTarget(continue1);
|
||||||
SetJumpTarget(continue2);
|
SetJumpTarget(continue2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Add(u32 a, u32 b) {return a + b;}
|
u32 Add(u32 a, u32 b) {return a + b;}
|
||||||
|
@ -139,6 +152,7 @@ void Jit64::reg_imm(UGeckoInstruction inst)
|
||||||
// FIXME: Seems to be required on OS X (see r5799)
|
// FIXME: Seems to be required on OS X (see r5799)
|
||||||
gpr.StoreFromX64(d);
|
gpr.StoreFromX64(d);
|
||||||
#endif
|
#endif
|
||||||
|
js.downcountAmount++;
|
||||||
js.skipnext = true;
|
js.skipnext = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -148,6 +162,7 @@ void Jit64::reg_imm(UGeckoInstruction inst)
|
||||||
// FIXME: Seems to be required on OS X (see r5799)
|
// FIXME: Seems to be required on OS X (see r5799)
|
||||||
gpr.StoreFromX64(d);
|
gpr.StoreFromX64(d);
|
||||||
#endif
|
#endif
|
||||||
|
js.downcountAmount++;
|
||||||
js.skipnext = true;
|
js.skipnext = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -365,6 +380,67 @@ void Jit64::orx(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Jit64::orcx(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(Integer)
|
||||||
|
int a = inst.RA, s = inst.RS, b = inst.RB;
|
||||||
|
if (a != s && a != b) {
|
||||||
|
gpr.LoadToX64(a, false, true);
|
||||||
|
} else {
|
||||||
|
gpr.LoadToX64(a, true, true);
|
||||||
|
}
|
||||||
|
gpr.Lock(a, s, b);
|
||||||
|
MOV(32, R(EAX), gpr.R(b));
|
||||||
|
NOT(32, R(EAX));
|
||||||
|
OR(32, R(EAX), gpr.R(s));
|
||||||
|
MOV(32, gpr.R(a), R(EAX));
|
||||||
|
gpr.UnlockAll();
|
||||||
|
|
||||||
|
if (inst.Rc) {
|
||||||
|
// result is already in eax
|
||||||
|
ComputeRC(R(EAX));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::norx(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(Integer)
|
||||||
|
int a = inst.RA;
|
||||||
|
int s = inst.RS;
|
||||||
|
int b = inst.RB;
|
||||||
|
|
||||||
|
if (s == b && s != a)
|
||||||
|
{
|
||||||
|
gpr.Lock(a,s);
|
||||||
|
gpr.LoadToX64(a, false);
|
||||||
|
MOV(32, gpr.R(a), gpr.R(s));
|
||||||
|
NOT(32, gpr.R(a));
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gpr.Lock(a, s, b);
|
||||||
|
gpr.LoadToX64(a, (a == s || a == b), true);
|
||||||
|
if (a == s)
|
||||||
|
OR(32, gpr.R(a), gpr.R(b));
|
||||||
|
else if (a == b)
|
||||||
|
OR(32, gpr.R(a), gpr.R(s));
|
||||||
|
else {
|
||||||
|
MOV(32, gpr.R(a), gpr.R(b));
|
||||||
|
OR(32, gpr.R(a), gpr.R(s));
|
||||||
|
}
|
||||||
|
NOT(32, gpr.R(a));
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst.Rc)
|
||||||
|
{
|
||||||
|
ComputeRC(gpr.R(a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// m_GPR[_inst.RA] = m_GPR[_inst.RS] ^ m_GPR[_inst.RB];
|
// m_GPR[_inst.RA] = m_GPR[_inst.RS] ^ m_GPR[_inst.RB];
|
||||||
void Jit64::xorx(UGeckoInstruction inst)
|
void Jit64::xorx(UGeckoInstruction inst)
|
||||||
|
@ -394,6 +470,34 @@ void Jit64::xorx(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Jit64::eqvx(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(Integer)
|
||||||
|
int a = inst.RA;
|
||||||
|
int s = inst.RS;
|
||||||
|
int b = inst.RB;
|
||||||
|
|
||||||
|
if (s == b) {
|
||||||
|
gpr.SetImmediate32(a, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gpr.LoadToX64(a, a == s || a == b, true);
|
||||||
|
gpr.Lock(a, s, b);
|
||||||
|
MOV(32, R(EAX), gpr.R(s));
|
||||||
|
XOR(32, R(EAX), gpr.R(b));
|
||||||
|
NOT(32, R(EAX));
|
||||||
|
MOV(32, gpr.R(a), R(EAX));
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst.Rc)
|
||||||
|
{
|
||||||
|
ComputeRC(gpr.R(a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Jit64::andx(UGeckoInstruction inst)
|
void Jit64::andx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
|
@ -416,6 +520,52 @@ void Jit64::andx(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Jit64::nandx(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(Integer)
|
||||||
|
int a = inst.RA, s = inst.RS, b = inst.RB;
|
||||||
|
if (a != s && a != b) {
|
||||||
|
gpr.LoadToX64(a, false, true);
|
||||||
|
} else {
|
||||||
|
gpr.LoadToX64(a, true, true);
|
||||||
|
}
|
||||||
|
gpr.Lock(a, s, b);
|
||||||
|
MOV(32, R(EAX), gpr.R(s));
|
||||||
|
AND(32, R(EAX), gpr.R(b));
|
||||||
|
NOT(32, R(EAX));
|
||||||
|
MOV(32, gpr.R(a), R(EAX));
|
||||||
|
gpr.UnlockAll();
|
||||||
|
|
||||||
|
if (inst.Rc) {
|
||||||
|
// result is already in eax
|
||||||
|
ComputeRC(R(EAX));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::andcx(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(Integer)
|
||||||
|
int a = inst.RA, s = inst.RS, b = inst.RB;
|
||||||
|
if (a != s && a != b) {
|
||||||
|
gpr.LoadToX64(a, false, true);
|
||||||
|
} else {
|
||||||
|
gpr.LoadToX64(a, true, true);
|
||||||
|
}
|
||||||
|
gpr.Lock(a, s, b);
|
||||||
|
MOV(32, R(EAX), gpr.R(b));
|
||||||
|
NOT(32, R(EAX));
|
||||||
|
AND(32, R(EAX), gpr.R(s));
|
||||||
|
MOV(32, gpr.R(a), R(EAX));
|
||||||
|
gpr.UnlockAll();
|
||||||
|
|
||||||
|
if (inst.Rc) {
|
||||||
|
// result is already in eax
|
||||||
|
ComputeRC(R(EAX));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Jit64::extsbx(UGeckoInstruction inst)
|
void Jit64::extsbx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
|
@ -542,6 +692,80 @@ void Jit64::subfex(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Jit64::subfmex(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
// USES_XER
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(Integer)
|
||||||
|
int a = inst.RA, d = inst.RD;
|
||||||
|
|
||||||
|
if (d == a)
|
||||||
|
{
|
||||||
|
gpr.Lock(a, d);
|
||||||
|
gpr.LoadToX64(d, true);
|
||||||
|
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||||
|
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||||
|
NOT(32, gpr.R(d));
|
||||||
|
ADC(32, gpr.R(d), Imm32(0xFFFFFFFF));
|
||||||
|
GenerateCarry();
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gpr.Lock(a, d);
|
||||||
|
gpr.LoadToX64(d, false);
|
||||||
|
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||||
|
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||||
|
MOV(32, gpr.R(d), gpr.R(a));
|
||||||
|
NOT(32, gpr.R(d));
|
||||||
|
ADC(32, gpr.R(d), Imm32(0xFFFFFFFF));
|
||||||
|
GenerateCarry();
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst.Rc)
|
||||||
|
{
|
||||||
|
ComputeRC(gpr.R(d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::subfzex(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
// USES_XER
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(Integer)
|
||||||
|
int a = inst.RA, d = inst.RD;
|
||||||
|
|
||||||
|
if (d == a)
|
||||||
|
{
|
||||||
|
gpr.Lock(a, d);
|
||||||
|
gpr.LoadToX64(d, true);
|
||||||
|
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||||
|
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||||
|
NOT(32, gpr.R(d));
|
||||||
|
ADC(32, gpr.R(d), Imm8(0));
|
||||||
|
GenerateCarry();
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gpr.Lock(a, d);
|
||||||
|
gpr.LoadToX64(d, false);
|
||||||
|
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||||
|
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||||
|
MOV(32, gpr.R(d), gpr.R(a));
|
||||||
|
NOT(32, gpr.R(d));
|
||||||
|
ADC(32, gpr.R(d), Imm8(0));
|
||||||
|
GenerateCarry();
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst.Rc)
|
||||||
|
{
|
||||||
|
ComputeRC(gpr.R(d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Jit64::subfx(UGeckoInstruction inst)
|
void Jit64::subfx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
|
@ -655,103 +879,178 @@ void Jit64::divwux(UGeckoInstruction inst)
|
||||||
|
|
||||||
void Jit64::addx(UGeckoInstruction inst)
|
void Jit64::addx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
JITDISABLE(Integer)
|
JITDISABLE(Integer)
|
||||||
int a = inst.RA, b = inst.RB, d = inst.RD;
|
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||||
_assert_msg_(DYNA_REC, !inst.OE, "Add - OE enabled :(");
|
_assert_msg_(DYNA_REC, !inst.OE, "Add - OE enabled :(");
|
||||||
|
|
||||||
if (a != d && b != d && a != b)
|
if (gpr.R(a).IsSimpleReg() && gpr.R(b).IsSimpleReg())
|
||||||
{
|
{
|
||||||
gpr.Lock(a, b, d);
|
gpr.Lock(a, b, d);
|
||||||
gpr.LoadToX64(d, false);
|
gpr.LoadToX64(d, false);
|
||||||
if (gpr.R(a).IsSimpleReg() && gpr.R(b).IsSimpleReg()) {
|
LEA(32, gpr.RX(d), MComplex(gpr.RX(a), gpr.RX(b), 1, 0));
|
||||||
LEA(32, gpr.RX(d), MComplex(gpr.RX(a), gpr.RX(b), 1, 0));
|
|
||||||
} else {
|
|
||||||
MOV(32, gpr.R(d), gpr.R(a));
|
|
||||||
ADD(32, gpr.R(d), gpr.R(b));
|
|
||||||
}
|
|
||||||
if (inst.Rc)
|
|
||||||
{
|
|
||||||
ComputeRC(gpr.R(d));
|
|
||||||
}
|
|
||||||
gpr.UnlockAll();
|
gpr.UnlockAll();
|
||||||
}
|
}
|
||||||
else if (d == a && d != b)
|
else if ((d == a) || (d == b))
|
||||||
{
|
{
|
||||||
gpr.Lock(b, d);
|
int operand = ((d == a) ? b : a);
|
||||||
|
gpr.Lock(a, b, d);
|
||||||
gpr.LoadToX64(d, true);
|
gpr.LoadToX64(d, true);
|
||||||
ADD(32, gpr.R(d), gpr.R(b));
|
ADD(32, gpr.R(d), gpr.R(operand));
|
||||||
if (inst.Rc)
|
|
||||||
{
|
|
||||||
ComputeRC(gpr.R(d));
|
|
||||||
}
|
|
||||||
gpr.UnlockAll();
|
|
||||||
}
|
|
||||||
else if (d == b && d != a)
|
|
||||||
{
|
|
||||||
gpr.Lock(a, d);
|
|
||||||
gpr.LoadToX64(d, true);
|
|
||||||
ADD(32, gpr.R(d), gpr.R(a));
|
|
||||||
if (inst.Rc)
|
|
||||||
{
|
|
||||||
ComputeRC(gpr.R(d));
|
|
||||||
}
|
|
||||||
gpr.UnlockAll();
|
|
||||||
}
|
|
||||||
else if( a == b && b == d && a == d)
|
|
||||||
{
|
|
||||||
gpr.Lock(d);
|
|
||||||
gpr.LoadToX64(d, true);
|
|
||||||
ADD(32, gpr.R(d), gpr.R(d));
|
|
||||||
if (inst.Rc)
|
|
||||||
{
|
|
||||||
ComputeRC(gpr.R(d));
|
|
||||||
}
|
|
||||||
gpr.UnlockAll();
|
|
||||||
}
|
|
||||||
else if( a == b && b != d)
|
|
||||||
{
|
|
||||||
gpr.Lock(a, d);
|
|
||||||
gpr.LoadToX64(d, false);
|
|
||||||
MOV(32, gpr.R(d), gpr.R(a));
|
|
||||||
ADD(32, gpr.R(d), gpr.R(d));
|
|
||||||
if (inst.Rc)
|
|
||||||
{
|
|
||||||
ComputeRC(gpr.R(d));
|
|
||||||
}
|
|
||||||
gpr.UnlockAll();
|
gpr.UnlockAll();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Default(inst); return;
|
gpr.Lock(a, b, d);
|
||||||
|
gpr.LoadToX64(d, false);
|
||||||
|
MOV(32, gpr.R(d), gpr.R(a));
|
||||||
|
ADD(32, gpr.R(d), gpr.R(b));
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst.Rc)
|
||||||
|
{
|
||||||
|
ComputeRC(gpr.R(d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This can be optimized
|
|
||||||
void Jit64::addex(UGeckoInstruction inst)
|
void Jit64::addex(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
// USES_XER
|
// USES_XER
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
JITDISABLE(Integer)
|
JITDISABLE(Integer)
|
||||||
int a = inst.RA, b = inst.RB, d = inst.RD;
|
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||||
gpr.Lock(a, b, d);
|
|
||||||
if (d != a && d != b)
|
if ((d == a) || (d == b))
|
||||||
gpr.LoadToX64(d, false);
|
{
|
||||||
else
|
gpr.Lock(a, b, d);
|
||||||
gpr.LoadToX64(d, true);
|
gpr.LoadToX64(d, true);
|
||||||
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||||
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||||
MOV(32, R(EAX), gpr.R(a));
|
ADC(32, gpr.R(d), gpr.R((d == a) ? b : a));
|
||||||
ADC(32, R(EAX), gpr.R(b));
|
GenerateCarry();
|
||||||
MOV(32, gpr.R(d), R(EAX));
|
gpr.UnlockAll();
|
||||||
GenerateCarry();
|
}
|
||||||
gpr.UnlockAll();
|
else
|
||||||
|
{
|
||||||
|
gpr.Lock(a, b, d);
|
||||||
|
gpr.LoadToX64(d, false);
|
||||||
|
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||||
|
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||||
|
MOV(32, gpr.R(d), gpr.R(a));
|
||||||
|
ADC(32, gpr.R(d), gpr.R(b));
|
||||||
|
GenerateCarry();
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst.Rc)
|
||||||
|
{
|
||||||
|
ComputeRC(gpr.R(d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::addcx(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(Integer)
|
||||||
|
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||||
|
_assert_msg_(DYNA_REC, !inst.OE, "Add - OE enabled :(");
|
||||||
|
|
||||||
|
if ((d == a) || (d == b))
|
||||||
|
{
|
||||||
|
int operand = ((d == a) ? b : a);
|
||||||
|
gpr.Lock(a, b, d);
|
||||||
|
gpr.LoadToX64(d, true);
|
||||||
|
ADD(32, gpr.R(d), gpr.R(operand));
|
||||||
|
GenerateCarry();
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gpr.Lock(a, b, d);
|
||||||
|
gpr.LoadToX64(d, false);
|
||||||
|
MOV(32, gpr.R(d), gpr.R(a));
|
||||||
|
ADD(32, gpr.R(d), gpr.R(b));
|
||||||
|
GenerateCarry();
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
{
|
{
|
||||||
ComputeRC(R(EAX));
|
ComputeRC(gpr.R(d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Jit64::addmex(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
// USES_XER
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(Integer)
|
||||||
|
int a = inst.RA, d = inst.RD;
|
||||||
|
|
||||||
|
if (d == a)
|
||||||
|
{
|
||||||
|
gpr.Lock(a, d);
|
||||||
|
gpr.LoadToX64(d, true);
|
||||||
|
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||||
|
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||||
|
ADC(32, gpr.R(d), Imm32(0xFFFFFFFF));
|
||||||
|
GenerateCarry();
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gpr.Lock(a, d);
|
||||||
|
gpr.LoadToX64(d, false);
|
||||||
|
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||||
|
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||||
|
MOV(32, gpr.R(d), gpr.R(a));
|
||||||
|
ADC(32, gpr.R(d), Imm32(0xFFFFFFFF));
|
||||||
|
GenerateCarry();
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst.Rc)
|
||||||
|
{
|
||||||
|
ComputeRC(gpr.R(d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::addzex(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
// USES_XER
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(Integer)
|
||||||
|
int a = inst.RA, d = inst.RD;
|
||||||
|
|
||||||
|
if (d == a)
|
||||||
|
{
|
||||||
|
gpr.Lock(a, d);
|
||||||
|
gpr.LoadToX64(d, true);
|
||||||
|
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||||
|
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||||
|
ADC(32, gpr.R(d), Imm8(0));
|
||||||
|
GenerateCarry();
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gpr.Lock(a, d);
|
||||||
|
gpr.LoadToX64(d, false);
|
||||||
|
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||||
|
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
|
||||||
|
MOV(32, gpr.R(d), gpr.R(a));
|
||||||
|
ADC(32, gpr.R(d), Imm8(0));
|
||||||
|
GenerateCarry();
|
||||||
|
gpr.UnlockAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst.Rc)
|
||||||
|
{
|
||||||
|
ComputeRC(gpr.R(d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Jit64::rlwinmx(UGeckoInstruction inst)
|
void Jit64::rlwinmx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
|
|
|
@ -146,12 +146,10 @@ void Jit64::mfcr(UGeckoInstruction inst)
|
||||||
int d = inst.RD;
|
int d = inst.RD;
|
||||||
gpr.LoadToX64(d, false, true);
|
gpr.LoadToX64(d, false, true);
|
||||||
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[0]));
|
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[0]));
|
||||||
SHL(32, R(EAX), Imm8(4));
|
for (int i = 1; i < 8; i++) {
|
||||||
for (int i = 1; i < 7; i++) {
|
|
||||||
OR(8, R(EAX), M(&PowerPC::ppcState.cr_fast[i]));
|
|
||||||
SHL(32, R(EAX), Imm8(4));
|
SHL(32, R(EAX), Imm8(4));
|
||||||
|
OR(8, R(EAX), M(&PowerPC::ppcState.cr_fast[i]));
|
||||||
}
|
}
|
||||||
OR(8, R(EAX), M(&PowerPC::ppcState.cr_fast[7]));
|
|
||||||
MOV(32, gpr.R(d), R(EAX));
|
MOV(32, gpr.R(d), R(EAX));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,32 +159,347 @@ void Jit64::mtcrf(UGeckoInstruction inst)
|
||||||
JITDISABLE(SystemRegisters)
|
JITDISABLE(SystemRegisters)
|
||||||
|
|
||||||
// USES_CR
|
// USES_CR
|
||||||
u32 mask = 0;
|
|
||||||
u32 crm = inst.CRM;
|
u32 crm = inst.CRM;
|
||||||
if (crm == 0xFF) {
|
if (crm != 0)
|
||||||
gpr.FlushLockX(ECX);
|
{
|
||||||
MOV(32, R(EAX), gpr.R(inst.RS));
|
if (gpr.R(inst.RS).IsImm())
|
||||||
for (int i = 0; i < 8; i++) {
|
{
|
||||||
MOV(32, R(ECX), R(EAX));
|
for (int i = 0; i < 8; i++)
|
||||||
SHR(32, R(ECX), Imm8(28 - (i * 4)));
|
{
|
||||||
AND(32, R(ECX), Imm32(0xF));
|
if ((crm & (0x80 >> i)) != 0)
|
||||||
MOV(8, M(&PowerPC::ppcState.cr_fast[i]), R(ECX));
|
{
|
||||||
|
u8 newcr = (gpr.R(inst.RS).offset >> (28 - (i * 4))) & 0xF;
|
||||||
|
MOV(8, M(&PowerPC::ppcState.cr_fast[i]), Imm8(newcr));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
gpr.UnlockAllX();
|
else
|
||||||
} else {
|
{
|
||||||
Default(inst);
|
gpr.LoadToX64(inst.RS, true);
|
||||||
return;
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
// TODO: translate this to work in new CR model.
|
if ((crm & (0x80 >> i)) != 0)
|
||||||
for (int i = 0; i < 8; i++) {
|
{
|
||||||
if (crm & (1 << i))
|
MOV(32, R(EAX), gpr.R(inst.RS));
|
||||||
mask |= 0xF << (i*4);
|
SHR(32, R(EAX), Imm8(28 - (i * 4)));
|
||||||
|
AND(32, R(EAX), Imm32(0xF));
|
||||||
|
MOV(8, M(&PowerPC::ppcState.cr_fast[i]), R(EAX));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MOV(32, R(EAX), gpr.R(inst.RS));
|
|
||||||
MOV(32, R(ECX), M(&PowerPC::ppcState.cr));
|
|
||||||
AND(32, R(EAX), Imm32(mask));
|
|
||||||
AND(32, R(ECX), Imm32(~mask));
|
|
||||||
OR(32, R(EAX), R(ECX));
|
|
||||||
MOV(32, M(&PowerPC::ppcState.cr), R(EAX));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Jit64::mcrf(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(SystemRegisters)
|
||||||
|
|
||||||
|
// USES_CR
|
||||||
|
if (inst.CRFS != inst.CRFD)
|
||||||
|
{
|
||||||
|
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[inst.CRFS]));
|
||||||
|
MOV(8, M(&PowerPC::ppcState.cr_fast[inst.CRFD]), R(EAX));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::mcrxr(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(SystemRegisters)
|
||||||
|
|
||||||
|
// USES_CR
|
||||||
|
|
||||||
|
// Copy XER[0-3] into CR[inst.CRFD]
|
||||||
|
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
|
||||||
|
SHR(32, R(EAX), Imm8(28));
|
||||||
|
MOV(8, M(&PowerPC::ppcState.cr_fast[inst.CRFD]), R(EAX));
|
||||||
|
|
||||||
|
// Clear XER[0-3]
|
||||||
|
AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(0x0FFFFFFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::crand(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(SystemRegisters)
|
||||||
|
|
||||||
|
// USES_CR
|
||||||
|
|
||||||
|
// Get bit CRBA in EAX aligned with bit CRBD
|
||||||
|
int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3);
|
||||||
|
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[inst.CRBA >> 2]));
|
||||||
|
if (shiftA < 0)
|
||||||
|
SHL(8, R(EAX), Imm8(-shiftA));
|
||||||
|
else if (shiftA > 0)
|
||||||
|
SHR(8, R(EAX), Imm8(shiftA));
|
||||||
|
|
||||||
|
// Get bit CRBB in ECX aligned with bit CRBD
|
||||||
|
gpr.FlushLockX(ECX);
|
||||||
|
int shiftB = (inst.CRBD & 3) - (inst.CRBB & 3);
|
||||||
|
MOV(8, R(ECX), M(&PowerPC::ppcState.cr_fast[inst.CRBB >> 2]));
|
||||||
|
if (shiftB < 0)
|
||||||
|
SHL(8, R(ECX), Imm8(-shiftB));
|
||||||
|
else if (shiftB > 0)
|
||||||
|
SHR(8, R(ECX), Imm8(shiftB));
|
||||||
|
|
||||||
|
// Compute combined bit
|
||||||
|
AND(8, R(EAX), R(ECX));
|
||||||
|
|
||||||
|
// Store result bit in CRBD
|
||||||
|
AND(8, R(EAX), Imm8(0x8 >> (inst.CRBD & 3)));
|
||||||
|
AND(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), Imm8(~(0x8 >> (inst.CRBD & 3))));
|
||||||
|
OR(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), R(EAX));
|
||||||
|
|
||||||
|
gpr.UnlockAllX();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::crandc(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(SystemRegisters)
|
||||||
|
|
||||||
|
// USES_CR
|
||||||
|
|
||||||
|
// Get bit CRBA in EAX aligned with bit CRBD
|
||||||
|
int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3);
|
||||||
|
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[inst.CRBA >> 2]));
|
||||||
|
if (shiftA < 0)
|
||||||
|
SHL(8, R(EAX), Imm8(-shiftA));
|
||||||
|
else if (shiftA > 0)
|
||||||
|
SHR(8, R(EAX), Imm8(shiftA));
|
||||||
|
|
||||||
|
// Get bit CRBB in ECX aligned with bit CRBD
|
||||||
|
gpr.FlushLockX(ECX);
|
||||||
|
int shiftB = (inst.CRBD & 3) - (inst.CRBB & 3);
|
||||||
|
MOV(8, R(ECX), M(&PowerPC::ppcState.cr_fast[inst.CRBB >> 2]));
|
||||||
|
if (shiftB < 0)
|
||||||
|
SHL(8, R(ECX), Imm8(-shiftB));
|
||||||
|
else if (shiftB > 0)
|
||||||
|
SHR(8, R(ECX), Imm8(shiftB));
|
||||||
|
|
||||||
|
// Compute combined bit
|
||||||
|
NOT(8, R(ECX));
|
||||||
|
AND(8, R(EAX), R(ECX));
|
||||||
|
|
||||||
|
// Store result bit in CRBD
|
||||||
|
AND(8, R(EAX), Imm8(0x8 >> (inst.CRBD & 3)));
|
||||||
|
AND(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), Imm8(~(0x8 >> (inst.CRBD & 3))));
|
||||||
|
OR(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), R(EAX));
|
||||||
|
|
||||||
|
gpr.UnlockAllX();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::creqv(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(SystemRegisters)
|
||||||
|
|
||||||
|
// USES_CR
|
||||||
|
|
||||||
|
// Get bit CRBA in EAX aligned with bit CRBD
|
||||||
|
int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3);
|
||||||
|
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[inst.CRBA >> 2]));
|
||||||
|
if (shiftA < 0)
|
||||||
|
SHL(8, R(EAX), Imm8(-shiftA));
|
||||||
|
else if (shiftA > 0)
|
||||||
|
SHR(8, R(EAX), Imm8(shiftA));
|
||||||
|
|
||||||
|
// Get bit CRBB in ECX aligned with bit CRBD
|
||||||
|
gpr.FlushLockX(ECX);
|
||||||
|
int shiftB = (inst.CRBD & 3) - (inst.CRBB & 3);
|
||||||
|
MOV(8, R(ECX), M(&PowerPC::ppcState.cr_fast[inst.CRBB >> 2]));
|
||||||
|
if (shiftB < 0)
|
||||||
|
SHL(8, R(ECX), Imm8(-shiftB));
|
||||||
|
else if (shiftB > 0)
|
||||||
|
SHR(8, R(ECX), Imm8(shiftB));
|
||||||
|
|
||||||
|
// Compute combined bit
|
||||||
|
XOR(8, R(EAX), R(ECX));
|
||||||
|
NOT(8, R(EAX));
|
||||||
|
|
||||||
|
// Store result bit in CRBD
|
||||||
|
AND(8, R(EAX), Imm8(0x8 >> (inst.CRBD & 3)));
|
||||||
|
AND(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), Imm8(~(0x8 >> (inst.CRBD & 3))));
|
||||||
|
OR(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), R(EAX));
|
||||||
|
|
||||||
|
gpr.UnlockAllX();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::crnand(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(SystemRegisters)
|
||||||
|
|
||||||
|
// USES_CR
|
||||||
|
|
||||||
|
// Get bit CRBA in EAX aligned with bit CRBD
|
||||||
|
int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3);
|
||||||
|
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[inst.CRBA >> 2]));
|
||||||
|
if (shiftA < 0)
|
||||||
|
SHL(8, R(EAX), Imm8(-shiftA));
|
||||||
|
else if (shiftA > 0)
|
||||||
|
SHR(8, R(EAX), Imm8(shiftA));
|
||||||
|
|
||||||
|
// Get bit CRBB in ECX aligned with bit CRBD
|
||||||
|
gpr.FlushLockX(ECX);
|
||||||
|
int shiftB = (inst.CRBD & 3) - (inst.CRBB & 3);
|
||||||
|
MOV(8, R(ECX), M(&PowerPC::ppcState.cr_fast[inst.CRBB >> 2]));
|
||||||
|
if (shiftB < 0)
|
||||||
|
SHL(8, R(ECX), Imm8(-shiftB));
|
||||||
|
else if (shiftB > 0)
|
||||||
|
SHR(8, R(ECX), Imm8(shiftB));
|
||||||
|
|
||||||
|
// Compute combined bit
|
||||||
|
AND(8, R(EAX), R(ECX));
|
||||||
|
NOT(8, R(EAX));
|
||||||
|
|
||||||
|
// Store result bit in CRBD
|
||||||
|
AND(8, R(EAX), Imm8(0x8 >> (inst.CRBD & 3)));
|
||||||
|
AND(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), Imm8(~(0x8 >> (inst.CRBD & 3))));
|
||||||
|
OR(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), R(EAX));
|
||||||
|
|
||||||
|
gpr.UnlockAllX();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::crnor(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(SystemRegisters)
|
||||||
|
|
||||||
|
// USES_CR
|
||||||
|
|
||||||
|
// Get bit CRBA in EAX aligned with bit CRBD
|
||||||
|
int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3);
|
||||||
|
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[inst.CRBA >> 2]));
|
||||||
|
if (shiftA < 0)
|
||||||
|
SHL(8, R(EAX), Imm8(-shiftA));
|
||||||
|
else if (shiftA > 0)
|
||||||
|
SHR(8, R(EAX), Imm8(shiftA));
|
||||||
|
|
||||||
|
// Get bit CRBB in ECX aligned with bit CRBD
|
||||||
|
gpr.FlushLockX(ECX);
|
||||||
|
int shiftB = (inst.CRBD & 3) - (inst.CRBB & 3);
|
||||||
|
MOV(8, R(ECX), M(&PowerPC::ppcState.cr_fast[inst.CRBB >> 2]));
|
||||||
|
if (shiftB < 0)
|
||||||
|
SHL(8, R(ECX), Imm8(-shiftB));
|
||||||
|
else if (shiftB > 0)
|
||||||
|
SHR(8, R(ECX), Imm8(shiftB));
|
||||||
|
|
||||||
|
// Compute combined bit
|
||||||
|
OR(8, R(EAX), R(ECX));
|
||||||
|
NOT(8, R(EAX));
|
||||||
|
|
||||||
|
// Store result bit in CRBD
|
||||||
|
AND(8, R(EAX), Imm8(0x8 >> (inst.CRBD & 3)));
|
||||||
|
AND(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), Imm8(~(0x8 >> (inst.CRBD & 3))));
|
||||||
|
OR(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), R(EAX));
|
||||||
|
|
||||||
|
gpr.UnlockAllX();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::cror(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(SystemRegisters)
|
||||||
|
|
||||||
|
// USES_CR
|
||||||
|
|
||||||
|
// Get bit CRBA in EAX aligned with bit CRBD
|
||||||
|
int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3);
|
||||||
|
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[inst.CRBA >> 2]));
|
||||||
|
if (shiftA < 0)
|
||||||
|
SHL(8, R(EAX), Imm8(-shiftA));
|
||||||
|
else if (shiftA > 0)
|
||||||
|
SHR(8, R(EAX), Imm8(shiftA));
|
||||||
|
|
||||||
|
// Get bit CRBB in ECX aligned with bit CRBD
|
||||||
|
gpr.FlushLockX(ECX);
|
||||||
|
int shiftB = (inst.CRBD & 3) - (inst.CRBB & 3);
|
||||||
|
MOV(8, R(ECX), M(&PowerPC::ppcState.cr_fast[inst.CRBB >> 2]));
|
||||||
|
if (shiftB < 0)
|
||||||
|
SHL(8, R(ECX), Imm8(-shiftB));
|
||||||
|
else if (shiftB > 0)
|
||||||
|
SHR(8, R(ECX), Imm8(shiftB));
|
||||||
|
|
||||||
|
// Compute combined bit
|
||||||
|
OR(8, R(EAX), R(ECX));
|
||||||
|
|
||||||
|
// Store result bit in CRBD
|
||||||
|
AND(8, R(EAX), Imm8(0x8 >> (inst.CRBD & 3)));
|
||||||
|
AND(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), Imm8(~(0x8 >> (inst.CRBD & 3))));
|
||||||
|
OR(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), R(EAX));
|
||||||
|
|
||||||
|
gpr.UnlockAllX();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::crorc(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(SystemRegisters)
|
||||||
|
|
||||||
|
// USES_CR
|
||||||
|
|
||||||
|
// Get bit CRBA in EAX aligned with bit CRBD
|
||||||
|
int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3);
|
||||||
|
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[inst.CRBA >> 2]));
|
||||||
|
if (shiftA < 0)
|
||||||
|
SHL(8, R(EAX), Imm8(-shiftA));
|
||||||
|
else if (shiftA > 0)
|
||||||
|
SHR(8, R(EAX), Imm8(shiftA));
|
||||||
|
|
||||||
|
// Get bit CRBB in ECX aligned with bit CRBD
|
||||||
|
gpr.FlushLockX(ECX);
|
||||||
|
int shiftB = (inst.CRBD & 3) - (inst.CRBB & 3);
|
||||||
|
MOV(8, R(ECX), M(&PowerPC::ppcState.cr_fast[inst.CRBB >> 2]));
|
||||||
|
if (shiftB < 0)
|
||||||
|
SHL(8, R(ECX), Imm8(-shiftB));
|
||||||
|
else if (shiftB > 0)
|
||||||
|
SHR(8, R(ECX), Imm8(shiftB));
|
||||||
|
|
||||||
|
// Compute combined bit
|
||||||
|
NOT(8, R(ECX));
|
||||||
|
OR(8, R(EAX), R(ECX));
|
||||||
|
|
||||||
|
// Store result bit in CRBD
|
||||||
|
AND(8, R(EAX), Imm8(0x8 >> (inst.CRBD & 3)));
|
||||||
|
AND(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), Imm8(~(0x8 >> (inst.CRBD & 3))));
|
||||||
|
OR(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), R(EAX));
|
||||||
|
|
||||||
|
gpr.UnlockAllX();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::crxor(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(SystemRegisters)
|
||||||
|
|
||||||
|
// USES_CR
|
||||||
|
|
||||||
|
// Get bit CRBA in EAX aligned with bit CRBD
|
||||||
|
int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3);
|
||||||
|
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[inst.CRBA >> 2]));
|
||||||
|
if (shiftA < 0)
|
||||||
|
SHL(8, R(EAX), Imm8(-shiftA));
|
||||||
|
else if (shiftA > 0)
|
||||||
|
SHR(8, R(EAX), Imm8(shiftA));
|
||||||
|
|
||||||
|
// Get bit CRBB in ECX aligned with bit CRBD
|
||||||
|
gpr.FlushLockX(ECX);
|
||||||
|
int shiftB = (inst.CRBD & 3) - (inst.CRBB & 3);
|
||||||
|
MOV(8, R(ECX), M(&PowerPC::ppcState.cr_fast[inst.CRBB >> 2]));
|
||||||
|
if (shiftB < 0)
|
||||||
|
SHL(8, R(ECX), Imm8(-shiftB));
|
||||||
|
else if (shiftB > 0)
|
||||||
|
SHR(8, R(ECX), Imm8(shiftB));
|
||||||
|
|
||||||
|
// Compute combined bit
|
||||||
|
XOR(8, R(EAX), R(ECX));
|
||||||
|
|
||||||
|
// Store result bit in CRBD
|
||||||
|
AND(8, R(EAX), Imm8(0x8 >> (inst.CRBD & 3)));
|
||||||
|
AND(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), Imm8(~(0x8 >> (inst.CRBD & 3))));
|
||||||
|
OR(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), R(EAX));
|
||||||
|
|
||||||
|
gpr.UnlockAllX();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue