armjit: Use our I2R funcs on reg/reg math too.

When one is a known immediate.  This should catch more cases, like:

ori v0, $0, 0xFFFF
and v1, v1, v0
This commit is contained in:
Unknown W. Brackets 2014-03-14 19:13:17 -07:00
parent 8e979da0f9
commit e783627947
4 changed files with 32 additions and 17 deletions

View File

@ -204,6 +204,20 @@ bool ARMXEmitter::TryADDI2R(ARMReg rd, ARMReg rs, u32 val)
}
}
void ARMXEmitter::SUBI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch)
{
if (!TrySUBI2R(rd, rs, val)) {
MOVI2R(scratch, val);
SUB(rd, rs, scratch);
}
}
bool ARMXEmitter::TrySUBI2R(ARMReg rd, ARMReg rs, u32 val)
{
// Just add a negative.
return TryADDI2R(rd, rs, (u32)-(s32)val);
}
void ARMXEmitter::ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch)
{
if (!TryANDI2R(rd, rs, val)) {

View File

@ -796,6 +796,8 @@ public:
void ADDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
bool TryADDI2R(ARMReg rd, ARMReg rs, u32 val);
void SUBI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
bool TrySUBI2R(ARMReg rd, ARMReg rs, u32 val);
void ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
bool TryANDI2R(ARMReg rd, ARMReg rs, u32 val);
void CMPI2R(ARMReg rs, u32 val, ARMReg scratch);

View File

@ -183,7 +183,7 @@ namespace MIPSComp
}
}
void Jit::CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, void (ARMXEmitter::*arith)(ARMReg dst, ARMReg rm, Operand2 rn), u32 (*eval)(u32 a, u32 b), bool symmetric, bool useMOV)
void Jit::CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, void (ARMXEmitter::*arith)(ARMReg dst, ARMReg rm, Operand2 rn), bool (ARMXEmitter::*tryArithI2R)(ARMReg dst, ARMReg rm, u32 val), u32 (*eval)(u32 a, u32 b), bool symmetric)
{
if (gpr.IsImm(rs) && gpr.IsImm(rt)) {
gpr.SetImm(rd, (*eval)(gpr.GetImm(rs), gpr.GetImm(rt)));
@ -192,18 +192,17 @@ namespace MIPSComp
if (gpr.IsImm(rt) || (gpr.IsImm(rs) && symmetric)) {
MIPSGPReg lhs = gpr.IsImm(rs) ? rt : rs;
u32 rhsImm = gpr.IsImm(rs) ? gpr.GetImm(rs) : gpr.GetImm(rt);
Operand2 op2;
// TODO: AND could be reversed, OR/EOR could use multiple ops (maybe still cheaper.)
if (TryMakeOperand2(rhsImm, op2)) {
gpr.MapDirtyIn(rd, lhs);
// MOV can avoid the ALU so might be faster?
if (!useMOV || rhsImm != 0)
(this->*arith)(gpr.R(rd), gpr.R(lhs), op2);
else if (rd != lhs)
MOV(gpr.R(rd), gpr.R(lhs));
MIPSGPReg rhs = gpr.IsImm(rs) ? rs : rt;
u32 rhsImm = gpr.GetImm(rhs);
gpr.MapDirtyIn(rd, lhs);
if ((this->*tryArithI2R)(gpr.R(rd), gpr.R(lhs), rhsImm)) {
return;
}
// If rd is rhs, we may have lost it in the MapDirtyIn(). lhs was kept.
if (rd == rhs) {
// Luckily, it was just an imm.
gpr.SetImm(rhs, rhsImm);
}
} else if (gpr.IsImm(rs) && !symmetric) {
Operand2 op2;
// For SUB, we can use RSB as a reverse operation.
@ -288,21 +287,21 @@ namespace MIPSComp
case 32: //R(rd) = R(rs) + R(rt); break; //add
case 33: //R(rd) = R(rs) + R(rt); break; //addu
// We optimize out 0 as an operand2 ADD.
CompType3(rd, rs, rt, &ARMXEmitter::ADD, &EvalAdd, true, true);
CompType3(rd, rs, rt, &ARMXEmitter::ADD, &ARMXEmitter::TryADDI2R, &EvalAdd, true);
break;
case 34: //R(rd) = R(rs) - R(rt); break; //sub
case 35: //R(rd) = R(rs) - R(rt); break; //subu
CompType3(rd, rs, rt, &ARMXEmitter::SUB, &EvalSub, false, false);
CompType3(rd, rs, rt, &ARMXEmitter::SUB, &ARMXEmitter::TrySUBI2R, &EvalSub, false);
break;
case 36: //R(rd) = R(rs) & R(rt); break; //and
CompType3(rd, rs, rt, &ARMXEmitter::AND, &EvalAnd, true, false);
CompType3(rd, rs, rt, &ARMXEmitter::AND, &ARMXEmitter::TryANDI2R, &EvalAnd, true);
break;
case 37: //R(rd) = R(rs) | R(rt); break; //or
CompType3(rd, rs, rt, &ARMXEmitter::ORR, &EvalOr, true, true);
CompType3(rd, rs, rt, &ARMXEmitter::ORR, &ARMXEmitter::TryORI2R, &EvalOr, true);
break;
case 38: //R(rd) = R(rs) ^ R(rt); break; //xor/eor
CompType3(rd, rs, rt, &ARMXEmitter::EOR, &EvalEor, true, true);
CompType3(rd, rs, rt, &ARMXEmitter::EOR, &ARMXEmitter::TryEORI2R, &EvalEor, true);
break;
case 39: // R(rd) = ~(R(rs) | R(rt)); break; //nor

View File

@ -209,7 +209,7 @@ private:
// Utilities to reduce duplicated code
void CompImmLogic(MIPSGPReg rs, MIPSGPReg rt, u32 uimm, void (ARMXEmitter::*arith)(ARMReg dst, ARMReg src, Operand2 op2), bool (ARMXEmitter::*tryArithI2R)(ARMReg dst, ARMReg src, u32 val), u32 (*eval)(u32 a, u32 b));
void CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, void (ARMXEmitter::*arithOp2)(ARMReg dst, ARMReg rm, Operand2 rn), u32 (*eval)(u32 a, u32 b), bool symmetric = false, bool useMOV = false);
void CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, void (ARMXEmitter::*arithOp2)(ARMReg dst, ARMReg rm, Operand2 rn), bool (ARMXEmitter::*tryArithI2R)(ARMReg dst, ARMReg rm, u32 val), u32 (*eval)(u32 a, u32 b), bool symmetric = false);
void CompShiftImm(MIPSOpcode op, ArmGen::ShiftType shiftType, int sa);
void CompShiftVar(MIPSOpcode op, ArmGen::ShiftType shiftType);