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:
dok.slade
2010-07-30 21:28:20 +00:00
parent 87043879f8
commit 12be9952ab
5 changed files with 771 additions and 138 deletions
+1 -1
View File
@@ -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)
+21
View File
@@ -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[] =
File diff suppressed because it is too large Load Diff
@@ -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]));
SHL(32, R(EAX), Imm8(4));
for (int i = 1; i < 7; i++) {
OR(8, R(EAX), M(&PowerPC::ppcState.cr_fast[i]));
for (int i = 1; i < 8; i++) {
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));
}
@@ -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));
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();
}