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.op = &ops[i];
|
||||
js.instructionNumber = i;
|
||||
const GekkoOPInfo *opinfo = GetOpInfo(ops[i].inst);
|
||||
const GekkoOPInfo *opinfo = ops[i].opinfo;
|
||||
js.downcountAmount += (opinfo->numCyclesMinusOne + 1);
|
||||
|
||||
if (i == (int)size - 1)
|
||||
|
|
|
@ -169,9 +169,15 @@ public:
|
|||
void DynaRunTable63(UGeckoInstruction _inst);
|
||||
|
||||
void addx(UGeckoInstruction inst);
|
||||
void addcx(UGeckoInstruction inst);
|
||||
void orx(UGeckoInstruction inst);
|
||||
void orcx(UGeckoInstruction inst);
|
||||
void norx(UGeckoInstruction inst);
|
||||
void xorx(UGeckoInstruction inst);
|
||||
void eqvx(UGeckoInstruction inst);
|
||||
void andx(UGeckoInstruction inst);
|
||||
void nandx(UGeckoInstruction inst);
|
||||
void andcx(UGeckoInstruction inst);
|
||||
void mulli(UGeckoInstruction inst);
|
||||
void mulhwux(UGeckoInstruction inst);
|
||||
void mullwx(UGeckoInstruction inst);
|
||||
|
@ -179,6 +185,8 @@ public:
|
|||
void srawix(UGeckoInstruction inst);
|
||||
void srawx(UGeckoInstruction inst);
|
||||
void addex(UGeckoInstruction inst);
|
||||
void addmex(UGeckoInstruction inst);
|
||||
void addzex(UGeckoInstruction inst);
|
||||
|
||||
void extsbx(UGeckoInstruction inst);
|
||||
void extshx(UGeckoInstruction inst);
|
||||
|
@ -198,6 +206,17 @@ public:
|
|||
void mftb(UGeckoInstruction inst);
|
||||
void mtcrf(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);
|
||||
|
||||
|
@ -247,6 +266,8 @@ public:
|
|||
void subfcx(UGeckoInstruction inst);
|
||||
void subfx(UGeckoInstruction inst);
|
||||
void subfex(UGeckoInstruction inst);
|
||||
void subfmex(UGeckoInstruction inst);
|
||||
void subfzex(UGeckoInstruction inst);
|
||||
|
||||
void lbzx(UGeckoInstruction inst);
|
||||
void lwzx(UGeckoInstruction inst);
|
||||
|
|
|
@ -174,17 +174,17 @@ static GekkoOPTemplate table19[] =
|
|||
{
|
||||
{528, &Jit64::bcctrx}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
|
||||
{16, &Jit64::bclrx}, //"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
|
||||
{257, &Jit64::Default}, //"crand", OPTYPE_CR, FL_EVIL}},
|
||||
{129, &Jit64::Default}, //"crandc", OPTYPE_CR, FL_EVIL}},
|
||||
{289, &Jit64::Default}, //"creqv", OPTYPE_CR, FL_EVIL}},
|
||||
{225, &Jit64::Default}, //"crnand", OPTYPE_CR, FL_EVIL}},
|
||||
{33, &Jit64::Default}, //"crnor", OPTYPE_CR, FL_EVIL}},
|
||||
{449, &Jit64::Default}, //"cror", OPTYPE_CR, FL_EVIL}},
|
||||
{417, &Jit64::Default}, //"crorc", OPTYPE_CR, FL_EVIL}},
|
||||
{193, &Jit64::Default}, //"crxor", OPTYPE_CR, FL_EVIL}},
|
||||
{257, &Jit64::crand}, //"crand", OPTYPE_CR, FL_EVIL}},
|
||||
{129, &Jit64::crandc}, //"crandc", OPTYPE_CR, FL_EVIL}},
|
||||
{289, &Jit64::creqv}, //"creqv", OPTYPE_CR, FL_EVIL}},
|
||||
{225, &Jit64::crnand}, //"crnand", OPTYPE_CR, FL_EVIL}},
|
||||
{33, &Jit64::crnor}, //"crnor", OPTYPE_CR, FL_EVIL}},
|
||||
{449, &Jit64::cror}, //"cror", OPTYPE_CR, FL_EVIL}},
|
||||
{417, &Jit64::crorc}, //"crorc", OPTYPE_CR, FL_EVIL}},
|
||||
{193, &Jit64::crxor}, //"crxor", OPTYPE_CR, 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}},
|
||||
{18, &Jit64::Default}, //"rfid", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS}}
|
||||
|
@ -194,13 +194,13 @@ static GekkoOPTemplate table19[] =
|
|||
static GekkoOPTemplate table31[] =
|
||||
{
|
||||
{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}},
|
||||
{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}},
|
||||
{412, &Jit64::Default}, //"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}},
|
||||
{284, &Jit64::Default}, //"eqvx", 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::nandx}, //"nandx", 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}},
|
||||
{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}},
|
||||
|
@ -287,7 +287,7 @@ static GekkoOPTemplate table31[] =
|
|||
{339, &Jit64::mfspr}, //"mfspr", OPTYPE_SPR, FL_OUT_D}},
|
||||
{467, &Jit64::mtspr}, //"mtspr", OPTYPE_SPR, 0, 2}},
|
||||
{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}},
|
||||
{659, &Jit64::Default}, //"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 2}},
|
||||
|
||||
|
@ -307,10 +307,10 @@ static GekkoOPTemplate table31[] =
|
|||
static GekkoOPTemplate table31_2[] =
|
||||
{
|
||||
{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}},
|
||||
{234, &Jit64::Default}, //"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}},
|
||||
{234, &Jit64::addmex}, //"addmex", 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}},
|
||||
{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}},
|
||||
|
@ -320,8 +320,8 @@ static GekkoOPTemplate table31_2[] =
|
|||
{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}},
|
||||
{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}},
|
||||
{200, &Jit64::Default}, //"subfzex", 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::subfzex}, //"subfzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
|
||||
};
|
||||
|
||||
static GekkoOPTemplate table59[] =
|
||||
|
|
|
@ -28,14 +28,26 @@
|
|||
void Jit64::GenerateCarry() {
|
||||
// USES_XER
|
||||
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();
|
||||
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);
|
||||
}
|
||||
|
||||
void Jit64::ComputeRC(const Gen::OpArg & arg) {
|
||||
if( arg.IsImm() )
|
||||
{
|
||||
s32 value = (s32)arg.offset;
|
||||
if( value < 0 )
|
||||
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);
|
||||
|
@ -51,6 +63,7 @@ void Jit64::ComputeRC(const Gen::OpArg & arg) {
|
|||
|
||||
SetJumpTarget(continue1);
|
||||
SetJumpTarget(continue2);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
gpr.StoreFromX64(d);
|
||||
#endif
|
||||
js.downcountAmount++;
|
||||
js.skipnext = true;
|
||||
break;
|
||||
}
|
||||
|
@ -148,6 +162,7 @@ void Jit64::reg_imm(UGeckoInstruction inst)
|
|||
// FIXME: Seems to be required on OS X (see r5799)
|
||||
gpr.StoreFromX64(d);
|
||||
#endif
|
||||
js.downcountAmount++;
|
||||
js.skipnext = true;
|
||||
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];
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
|
@ -660,95 +884,170 @@ void Jit64::addx(UGeckoInstruction inst)
|
|||
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||
_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.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));
|
||||
} 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();
|
||||
}
|
||||
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);
|
||||
ADD(32, gpr.R(d), gpr.R(b));
|
||||
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));
|
||||
}
|
||||
ADD(32, gpr.R(d), gpr.R(operand));
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
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)
|
||||
{
|
||||
// USES_XER
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(Integer)
|
||||
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||
|
||||
if ((d == a) || (d == b))
|
||||
{
|
||||
gpr.Lock(a, b, d);
|
||||
if (d != a && d != b)
|
||||
gpr.LoadToX64(d, false);
|
||||
else
|
||||
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
|
||||
MOV(32, R(EAX), gpr.R(a));
|
||||
ADC(32, R(EAX), gpr.R(b));
|
||||
MOV(32, gpr.R(d), R(EAX));
|
||||
ADC(32, gpr.R(d), gpr.R((d == a) ? b : a));
|
||||
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(R(EAX));
|
||||
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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -146,12 +146,10 @@ void Jit64::mfcr(UGeckoInstruction inst)
|
|||
int d = inst.RD;
|
||||
gpr.LoadToX64(d, false, true);
|
||||
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[0]));
|
||||
for (int i = 1; i < 8; i++) {
|
||||
SHL(32, R(EAX), Imm8(4));
|
||||
for (int i = 1; i < 7; i++) {
|
||||
OR(8, R(EAX), M(&PowerPC::ppcState.cr_fast[i]));
|
||||
SHL(32, R(EAX), Imm8(4));
|
||||
}
|
||||
OR(8, R(EAX), M(&PowerPC::ppcState.cr_fast[7]));
|
||||
MOV(32, gpr.R(d), R(EAX));
|
||||
}
|
||||
|
||||
|
@ -161,32 +159,347 @@ void Jit64::mtcrf(UGeckoInstruction inst)
|
|||
JITDISABLE(SystemRegisters)
|
||||
|
||||
// USES_CR
|
||||
u32 mask = 0;
|
||||
u32 crm = inst.CRM;
|
||||
if (crm == 0xFF) {
|
||||
gpr.FlushLockX(ECX);
|
||||
MOV(32, R(EAX), gpr.R(inst.RS));
|
||||
for (int i = 0; i < 8; i++) {
|
||||
MOV(32, R(ECX), R(EAX));
|
||||
SHR(32, R(ECX), Imm8(28 - (i * 4)));
|
||||
AND(32, R(ECX), Imm32(0xF));
|
||||
MOV(8, M(&PowerPC::ppcState.cr_fast[i]), R(ECX));
|
||||
if (crm != 0)
|
||||
{
|
||||
if (gpr.R(inst.RS).IsImm())
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if ((crm & (0x80 >> i)) != 0)
|
||||
{
|
||||
u8 newcr = (gpr.R(inst.RS).offset >> (28 - (i * 4))) & 0xF;
|
||||
MOV(8, M(&PowerPC::ppcState.cr_fast[i]), Imm8(newcr));
|
||||
}
|
||||
gpr.UnlockAllX();
|
||||
} else {
|
||||
Default(inst);
|
||||
return;
|
||||
|
||||
// TODO: translate this to work in new CR model.
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (crm & (1 << i))
|
||||
mask |= 0xF << (i*4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gpr.LoadToX64(inst.RS, true);
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if ((crm & (0x80 >> i)) != 0)
|
||||
{
|
||||
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));
|
||||
SHR(32, R(EAX), Imm8(28 - (i * 4)));
|
||||
AND(32, R(EAX), Imm32(0xF));
|
||||
MOV(8, M(&PowerPC::ppcState.cr_fast[i]), 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