Jit reg+reg compile time, and avoid flushing EDX.

This commit is contained in:
Unknown W. Brackets 2013-01-25 00:02:03 -08:00
parent ce5f393fb8
commit ab9bea068c
2 changed files with 54 additions and 16 deletions

View File

@ -142,23 +142,54 @@ namespace MIPSComp
}
//rd = rs X rt
void Jit::CompTriArith(u32 op, void (XEmitter::*arith)(int, const OpArg &, const OpArg &))
void Jit::CompTriArith(u32 op, void (XEmitter::*arith)(int, const OpArg &, const OpArg &), u32 (*doImm)(const u32, const u32))
{
int rt = _RT;
int rs = _RS;
int rd = _RD;
gpr.FlushLockX(EDX);
// Yes, this happens. Let's make it fast.
if (doImm && gpr.IsImmediate(rs) && gpr.IsImmediate(rt))
{
gpr.SetImmediate32(rd, doImm(gpr.GetImmediate32(rs), gpr.GetImmediate32(rt)));
return;
}
gpr.Lock(rt, rs, rd);
MOV(32, R(EAX), gpr.R(rs));
MOV(32, R(EDX), gpr.R(rt));
gpr.BindToRegister(rd, true, true);
(this->*arith)(32, R(EAX), R(EDX));
MOV(32, gpr.R(rd), R(EAX));
// Use EAX as a temporary if we'd overwrite it.
if (rd == rt)
MOV(32, R(EAX), gpr.R(rt));
gpr.BindToRegister(rd, rs == rd, true);
if (rs != rd)
MOV(32, gpr.R(rd), gpr.R(rs));
(this->*arith)(32, gpr.R(rd), rd == rt ? R(EAX) : gpr.R(rt));
gpr.UnlockAll();
gpr.UnlockAllX();
}
static u32 RType3_ImmAdd(const u32 a, const u32 b)
{
return a + b;
}
static u32 RType3_ImmSub(const u32 a, const u32 b)
{
return a - b;
}
static u32 RType3_ImmAnd(const u32 a, const u32 b)
{
return a & b;
}
static u32 RType3_ImmOr(const u32 a, const u32 b)
{
return a | b;
}
static u32 RType3_ImmXor(const u32 a, const u32 b)
{
return a ^ b;
}
void Jit::Comp_RType3(u32 op)
{
@ -168,6 +199,10 @@ namespace MIPSComp
int rs = _RS;
int rd = _RD;
// noop, won't write to ZERO.
if (rd == 0)
return;
switch (op & 63)
{
//case 10: if (!R(rt)) R(rd) = R(rs); break; //movz
@ -175,25 +210,28 @@ namespace MIPSComp
// case 32: //R(rd) = R(rs) + R(rt); break; //add
case 33: //R(rd) = R(rs) + R(rt); break; //addu
CompTriArith(op, &XEmitter::ADD);
CompTriArith(op, &XEmitter::ADD, &RType3_ImmAdd);
break;
case 34: //R(rd) = R(rs) - R(rt); break; //sub
case 35:
CompTriArith(op, &XEmitter::SUB);
CompTriArith(op, &XEmitter::SUB, &RType3_ImmSub);
break;
case 36: //R(rd) = R(rs) & R(rt); break; //and
CompTriArith(op, &XEmitter::AND);
CompTriArith(op, &XEmitter::AND, &RType3_ImmAnd);
break;
case 37: //R(rd) = R(rs) | R(rt); break; //or
CompTriArith(op, &XEmitter::OR);
CompTriArith(op, &XEmitter::OR, &RType3_ImmOr);
break;
case 38: //R(rd) = R(rs) ^ R(rt); break; //xor
CompTriArith(op, &XEmitter::XOR);
CompTriArith(op, &XEmitter::XOR, &RType3_ImmXor);
break;
case 39: // R(rd) = ~(R(rs) | R(rt)); //nor
CompTriArith(op, &XEmitter::OR);
NOT(32, gpr.R(rd));
CompTriArith(op, &XEmitter::OR, &RType3_ImmOr);
if (gpr.IsImmediate(rd))
gpr.SetImmediate32(rd, ~gpr.GetImmediate32(rd));
else
NOT(32, gpr.R(rd));
break;
case 42: //R(rd) = (int)R(rs) < (int)R(rt); break; //slt

View File

@ -121,7 +121,7 @@ private:
// Utilities to reduce duplicated code
void CompImmLogic(u32 op, void (XEmitter::*arith)(int, const OpArg &, const OpArg &));
void CompTriArith(u32 op, void (XEmitter::*arith)(int, const OpArg &, const OpArg &));
void CompTriArith(u32 op, void (XEmitter::*arith)(int, const OpArg &, const OpArg &), u32 (*doImm)(const u32, const u32));
void CompShiftImm(u32 op, void (XEmitter::*shift)(int, OpArg, OpArg));
void CompShiftVar(u32 op, void (XEmitter::*shift)(int, OpArg, OpArg));
void CompITypeMemRead(u32 op, u32 bits, void (XEmitter::*mov)(int, int, X64Reg, OpArg), void *safeFunc);