JitIL: Implemented some instructions.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6111 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
nodchip 2010-08-20 05:05:11 +00:00
parent 7b9d0dbedc
commit 168136a219
3 changed files with 72 additions and 103 deletions

View File

@ -294,36 +294,45 @@ void JitIL::mullwx(UGeckoInstruction inst)
void JitIL::mulhwux(UGeckoInstruction inst) void JitIL::mulhwux(UGeckoInstruction inst)
{ {
Default(inst); return; INSTRUCTION_START
#if 0 JITDISABLE(Integer)
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
{Default(inst); return;} // turn off from debugger
INSTRUCTION_START; // Compute upper 32-bit of (a * b) using Karatsuba algorithm
int a = inst.RA, b = inst.RB, d = inst.RD; // Karatsuba algorithm reduces the number of multiplication 4 to 3
gpr.FlushLockX(EDX); // d = a * b
gpr.Lock(a, b, d); // = {a1 * (1 << 16) + a0} * {b1 * (1 << 16) + b0};
if (d != a && d != b) { // = d2 * (1 << 32) + d1 * (1 << 16) + d0
gpr.LoadToX64(d, false, true); // where
} else { // d2 = a1 * b1
gpr.LoadToX64(d, true, true); // d0 = a0 * b0
} // d1 = (a1 + a0) * (b1 * b0) - d2 - d0
if (gpr.RX(d) == EDX) // since
PanicAlert("mulhwux : WTF"); // d1 = (a1 + a0) * (b1 * b0) - d2 - d0
MOV(32, R(EAX), gpr.R(a)); // = a1 * b1 + a1 * b0 + a0 * b1 + a0 * b0 - a1 * b1 - a0 * b0
gpr.KillImmediate(b); // = a1 * b0 + a0 * b1
MUL(32, gpr.R(b)); // The result of mulhwux is
gpr.UnlockAll(); // d2' = (((d0 >> 16) + d1) >> 16) + d2
gpr.UnlockAllX(); //
if (inst.Rc) { // Though it is not so fast...
MOV(32, R(EAX), R(EDX)); IREmitter::InstLoc a = ibuild.EmitLoadGReg(inst.RA);
MOV(32, gpr.R(d), R(EDX)); IREmitter::InstLoc a0 = ibuild.EmitAnd(a, ibuild.EmitIntConst(0xFFFF));
// result is already in eax IREmitter::InstLoc a1 = ibuild.EmitShrl(a, ibuild.EmitIntConst(16));
CALL((u8*)asm_routines.computeRc); IREmitter::InstLoc b = ibuild.EmitLoadGReg(inst.RB);
} else { IREmitter::InstLoc b0 = ibuild.EmitAnd(b, ibuild.EmitIntConst(0xFFFF));
MOV(32, gpr.R(d), R(EDX)); IREmitter::InstLoc b1 = ibuild.EmitShrl(b, ibuild.EmitIntConst(16));
}
#endif IREmitter::InstLoc d2 = ibuild.EmitMul(a1, b1);
IREmitter::InstLoc d0 = ibuild.EmitMul(a0, b0);
IREmitter::InstLoc d1 = ibuild.EmitMul(ibuild.EmitAdd(a1, a0), ibuild.EmitAdd(b1, b0));
d1 = ibuild.EmitSub(d1, d2);
d1 = ibuild.EmitSub(d1, d0);
d1 = ibuild.EmitAdd(d1, ibuild.EmitShrl(d0, ibuild.EmitIntConst(16)));
d2 = ibuild.EmitAdd(d2, ibuild.EmitShrl(d1, ibuild.EmitIntConst(16)));
ibuild.EmitStoreGReg(d2, inst.RD);
if (inst.Rc)
ComputeRC(ibuild, d2);
} }
// skipped some of the special handling in here - if we get crashes, let the interpreter handle this op // skipped some of the special handling in here - if we get crashes, let the interpreter handle this op
@ -375,36 +384,28 @@ void JitIL::addzex(UGeckoInstruction inst)
if (inst.Rc) if (inst.Rc)
ComputeRC(ibuild, val); ComputeRC(ibuild, val);
} }
// This can be optimized
void JitIL::addex(UGeckoInstruction inst) void JitIL::addex(UGeckoInstruction inst)
{ {
Default(inst); return; INSTRUCTION_START
#if 0 JITDISABLE(Integer)
// USES_XER
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
{Default(inst); return;} // turn off from debugger
INSTRUCTION_START; IREmitter::InstLoc a = ibuild.EmitLoadGReg(inst.RA);
int a = inst.RA, b = inst.RB, d = inst.RD; IREmitter::InstLoc b = ibuild.EmitLoadGReg(inst.RB);
gpr.FlushLockX(ECX);
gpr.Lock(a, b, d); IREmitter::InstLoc ab = ibuild.EmitAdd(a, b);
if (d != a && d != b) IREmitter::InstLoc new_carry = ibuild.EmitICmpUlt(ab, a);
gpr.LoadToX64(d, false);
else IREmitter::InstLoc previous_carry = ibuild.EmitLoadCarry();
gpr.LoadToX64(d, true); IREmitter::InstLoc abc = ibuild.EmitAdd(ab, previous_carry);
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); new_carry = ibuild.EmitOr(new_carry, ibuild.EmitICmpUlt(abc, ab));
SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag
MOV(32, R(EAX), gpr.R(a)); ibuild.EmitStoreGReg(abc, inst.RD);
ADC(32, R(EAX), gpr.R(b)); ibuild.EmitStoreCarry(new_carry);
MOV(32, gpr.R(d), R(EAX));
//GenerateCarry(ECX); if (inst.OE) PanicAlert("OE: addex");
gpr.UnlockAll();
gpr.UnlockAllX();
if (inst.Rc) if (inst.Rc)
{ ComputeRC(ibuild, abc);
CALL((u8*)asm_routines.computeRc);
}
#endif
} }
void JitIL::rlwinmx(UGeckoInstruction inst) void JitIL::rlwinmx(UGeckoInstruction inst)

View File

@ -128,63 +128,31 @@ void JitIL::mftb(UGeckoInstruction inst)
void JitIL::mfcr(UGeckoInstruction inst) void JitIL::mfcr(UGeckoInstruction inst)
{ {
Default(inst); return;
#if 0
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITSystemRegistersOff)
{Default(inst); return;} // turn off from debugger
INSTRUCTION_START; INSTRUCTION_START;
// USES_CR JITDISABLE(SystemRegisters)
int d = inst.RD;
gpr.LoadToX64(d, false, true); IREmitter::InstLoc d = ibuild.EmitIntConst(0);
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[0])); for (int i = 0; i < 8; ++i)
SHL(32, R(EAX), Imm8(4)); {
for (int i = 1; i < 7; i++) { d = ibuild.EmitShl(d, ibuild.EmitIntConst(4));
OR(8, R(EAX), M(&PowerPC::ppcState.cr_fast[i])); d = ibuild.EmitOr(d, ibuild.EmitLoadCR(i));
SHL(32, R(EAX), Imm8(4));
} }
OR(8, R(EAX), M(&PowerPC::ppcState.cr_fast[7])); ibuild.EmitStoreGReg(d, inst.RD);
MOV(32, gpr.R(d), R(EAX));
#endif
} }
void JitIL::mtcrf(UGeckoInstruction inst) void JitIL::mtcrf(UGeckoInstruction inst)
{ {
Default(inst); return;
#if 0
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITSystemRegistersOff)
{Default(inst); return;} // turn off from debugger
INSTRUCTION_START; INSTRUCTION_START;
JITDISABLE(SystemRegisters)
// USES_CR IREmitter::InstLoc s = ibuild.EmitLoadGReg(inst.RS);
u32 mask = 0; for (int i = 0; i < 8; ++i)
u32 crm = inst.CRM; {
if (crm == 0xFF) { if (inst.CRM & (1 << i))
gpr.FlushLockX(ECX); {
MOV(32, R(EAX), gpr.R(inst.RS)); ibuild.EmitStoreCR(ibuild.EmitAnd(ibuild.EmitShrl(s, ibuild.EmitIntConst(28 - 4 * i)), ibuild.EmitIntConst(0xf)), i);
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));
} }
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);
} }
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));
}
#endif
} }
void JitIL::crXX(UGeckoInstruction inst) void JitIL::crXX(UGeckoInstruction inst)

View File

@ -186,7 +186,7 @@ static GekkoOPTemplate table19[] =
{193, &JitIL::crXX}, //"crxor", OPTYPE_CR, FL_EVIL}}, {193, &JitIL::crXX}, //"crxor", OPTYPE_CR, FL_EVIL}},
{150, &JitIL::DoNothing}, //"isync", OPTYPE_ICACHE, FL_EVIL}}, {150, &JitIL::DoNothing}, //"isync", OPTYPE_ICACHE, FL_EVIL}},
{0, &JitIL::Default}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}}, {0, &JitIL::mfcr}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}},
{50, &JitIL::rfi}, //"rfi", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS, 1}}, {50, &JitIL::rfi}, //"rfi", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS, 1}},
{18, &JitIL::Default}, //"rfid", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS}} {18, &JitIL::Default}, //"rfid", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS}}