armjit: Replace MOVI2R with using the regcache.

So that it can optimize the value with existing imms.

Not actually optimizing yet.
This commit is contained in:
Unknown W. Brackets 2013-11-10 13:16:29 -08:00
parent d092f7dd2d
commit 7e46ee0b0f
8 changed files with 37 additions and 31 deletions

View File

@ -61,7 +61,7 @@ namespace MIPSComp
if (TryMakeOperand2(uimm, op2)) {
(this->*arith)(gpr.R(rt), gpr.R(rs), op2);
} else {
MOVI2R(R0, (u32)uimm);
gpr.SetRegImm(R0, (u32)uimm);
(this->*arith)(gpr.R(rt), gpr.R(rs), R0);
}
}

View File

@ -157,7 +157,7 @@ void Jit::BranchRSZeroComp(MIPSOpcode op, ArmGen::CCFlags cc, bool andLink, bool
// Take the branch
if (andLink)
{
MOVI2R(R0, js.compilerPC + 8);
gpr.SetRegImm(R0, js.compilerPC + 8);
STR(R0, CTXREG, MIPS_REG_RA * 4);
}
@ -356,7 +356,7 @@ void Jit::Comp_Jump(MIPSOpcode op)
case 3: //jal
gpr.MapReg(MIPS_REG_RA, MAP_NOINIT | MAP_DIRTY);
MOVI2R(gpr.R(MIPS_REG_RA), js.compilerPC + 8);
gpr.SetRegImm(gpr.R(MIPS_REG_RA), js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_NICE);
FlushAll();
WriteExit(targetAddr, js.nextExit++);
@ -419,7 +419,7 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
case 8: //jr
break;
case 9: //jalr
MOVI2R(R0, js.compilerPC + 8);
gpr.SetRegImm(R0, js.compilerPC + 8);
STR(R0, CTXREG, (int)rd * 4);
break;
default:
@ -446,12 +446,12 @@ void Jit::Comp_Syscall(MIPSOpcode op)
void *quickFunc = GetQuickSyscallFunc(op);
if (quickFunc)
{
MOVI2R(R0, (u32)(intptr_t)GetSyscallInfo(op));
gpr.SetRegImm(R0, (u32)(intptr_t)GetSyscallInfo(op));
QuickCallFunction(R1, quickFunc);
}
else
{
MOVI2R(R0, op.encoding);
gpr.SetRegImm(R0, op.encoding);
QuickCallFunction(R1, (void *)&CallSyscall);
}
RestoreDowncount();

View File

@ -108,7 +108,7 @@ void Jit::Comp_FPULS(MIPSOpcode op)
fpr.MapReg(ft, MAP_NOINIT | MAP_DIRTY);
if (gpr.IsImm(rs)) {
u32 addr = (offset + gpr.GetImm(rs)) & 0x3FFFFFFF;
MOVI2R(R0, addr + (u32)Memory::base);
gpr.SetRegImm(R0, addr + (u32)Memory::base);
} else {
gpr.MapReg(rs);
if (g_Config.bFastMemory) {
@ -152,7 +152,7 @@ void Jit::Comp_FPULS(MIPSOpcode op)
fpr.MapReg(ft);
if (gpr.IsImm(rs)) {
u32 addr = (offset + gpr.GetImm(rs)) & 0x3FFFFFFF;
MOVI2R(R0, addr + (u32)Memory::base);
gpr.SetRegImm(R0, addr + (u32)Memory::base);
} else {
gpr.MapReg(rs);
if (g_Config.bFastMemory) {

View File

@ -78,10 +78,10 @@ namespace MIPSComp
} else {
// Try to avoid using MOVT
if (offset < 0) {
MOVI2R(R0, (u32)(-offset));
gpr.SetRegImm(R0, (u32)(-offset));
SUB(R0, gpr.R(rs), R0);
} else {
MOVI2R(R0, (u32)offset);
gpr.SetRegImm(R0, (u32)offset);
ADD(R0, gpr.R(rs), R0);
}
}
@ -156,7 +156,7 @@ namespace MIPSComp
u32 addr = iaddr & 0x3FFFFFFF;
// Must be OK even if rs == rt since we have the value from imm already.
gpr.MapReg(rt, load ? MAP_NOINIT | MAP_DIRTY : 0);
MOVI2R(R0, addr & ~3);
gpr.SetRegImm(R0, addr & ~3);
u8 shift = (addr & 3) * 8;
@ -329,7 +329,7 @@ namespace MIPSComp
u32 addr = iaddr & 0x3FFFFFFF;
// Must be OK even if rs == rt since we have the value from imm already.
gpr.MapReg(rt, load ? MAP_NOINIT | MAP_DIRTY : 0);
MOVI2R(R0, addr);
gpr.SetRegImm(R0, addr);
} else {
_dbg_assert_msg_(JIT, !gpr.IsImm(rs), "Invalid immediate address? CPU bug?");
load ? gpr.MapDirtyIn(rt, rs) : gpr.MapInIn(rt, rs);

View File

@ -254,7 +254,7 @@ namespace MIPSComp
fpr.MapRegV(vt, MAP_DIRTY | MAP_NOINIT);
if (gpr.IsImm(rs)) {
u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF;
MOVI2R(R0, addr + (u32)Memory::base);
gpr.SetRegImm(R0, addr + (u32)Memory::base);
} else {
gpr.MapReg(rs);
if (g_Config.bFastMemory) {
@ -292,7 +292,7 @@ namespace MIPSComp
fpr.MapRegV(vt);
if (gpr.IsImm(rs)) {
u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF;
MOVI2R(R0, addr + (u32)Memory::base);
gpr.SetRegImm(R0, addr + (u32)Memory::base);
} else {
gpr.MapReg(rs);
if (g_Config.bFastMemory) {
@ -348,7 +348,7 @@ namespace MIPSComp
if (gpr.IsImm(rs)) {
u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF;
MOVI2R(R0, addr + (u32)Memory::base);
gpr.SetRegImm(R0, addr + (u32)Memory::base);
} else {
gpr.MapReg(rs);
if (g_Config.bFastMemory) {
@ -397,7 +397,7 @@ namespace MIPSComp
if (gpr.IsImm(rs)) {
u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF;
MOVI2R(R0, addr + (u32)Memory::base);
gpr.SetRegImm(R0, addr + (u32)Memory::base);
} else {
gpr.MapReg(rs);
if (g_Config.bFastMemory) {
@ -1588,7 +1588,7 @@ namespace MIPSComp
GetVectorRegsPrefixD(dregs, sz, _VD);
fpr.MapRegsAndSpillLockV(dregs, sz, MAP_NOINIT | MAP_DIRTY);
MOVI2R(R0, (u32)(void *)&cst_constants[conNum]);
gpr.SetRegImm(R0, (u32)(void *)&cst_constants[conNum]);
VLDR(S0, R0, 0);
for (int i = 0; i < n; ++i)
VMOV(fpr.V(dregs[i]), S0);
@ -1652,7 +1652,7 @@ namespace MIPSComp
// We should write a custom pure-asm function instead.
VMOV(R0, fpr.V(sreg));
QuickCallFunction(R1, negSin ? (void *)&SinCosNegSin : (void *)&SinCos);
MOVI2R(R0, (u32)(&sincostemp[0]));
gpr.SetRegImm(R0, (u32)(&sincostemp[0]));
VLDR(S0, R0, 0);
VLDR(S1, R0, 4);

View File

@ -109,19 +109,19 @@ void Jit::FlushAll()
void Jit::FlushPrefixV()
{
if ((js.prefixSFlag & JitState::PREFIX_DIRTY) != 0) {
MOVI2R(R0, js.prefixS);
gpr.SetRegImm(R0, js.prefixS);
STR(R0, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_SPREFIX]));
js.prefixSFlag = (JitState::PrefixState) (js.prefixSFlag & ~JitState::PREFIX_DIRTY);
}
if ((js.prefixTFlag & JitState::PREFIX_DIRTY) != 0) {
MOVI2R(R0, js.prefixT);
gpr.SetRegImm(R0, js.prefixT);
STR(R0, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_TPREFIX]));
js.prefixTFlag = (JitState::PrefixState) (js.prefixTFlag & ~JitState::PREFIX_DIRTY);
}
if ((js.prefixDFlag & JitState::PREFIX_DIRTY) != 0) {
MOVI2R(R0, js.prefixD);
gpr.SetRegImm(R0, js.prefixD);
STR(R0, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_DPREFIX]));
js.prefixDFlag = (JitState::PrefixState) (js.prefixDFlag & ~JitState::PREFIX_DIRTY);
}
@ -230,7 +230,7 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b)
// Not intrusive so keeping it around here to experiment with, may help on ARMv6 due to
// large/slow construction of 32-bit immediates?
JumpTarget backJump = GetCodePtr();
MOVI2R(R0, js.blockStart);
gpr.SetRegImm(R0, js.blockStart);
B((const void *)outerLoopPCInR0);
b->checkedEntry = GetCodePtr();
SetCC(CC_LT);
@ -244,7 +244,7 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b)
} else {
b->checkedEntry = GetCodePtr();
SetCC(CC_LT);
MOVI2R(R0, js.blockStart);
gpr.SetRegImm(R0, js.blockStart);
B((const void *)outerLoopPCInR0);
SetCC(CC_AL);
}
@ -283,7 +283,7 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b)
if (jo.useForwardJump) {
SetJumpTarget(bail);
MOVI2R(R0, js.blockStart);
gpr.SetRegImm(R0, js.blockStart);
B((const void *)outerLoopPCInR0);
}
@ -329,9 +329,9 @@ void Jit::Comp_Generic(MIPSOpcode op)
if (func)
{
SaveDowncount();
MOVI2R(R0, js.compilerPC);
gpr.SetRegImm(R0, js.compilerPC);
MovToPC(R0);
MOVI2R(R0, op.encoding);
gpr.SetRegImm(R0, op.encoding);
QuickCallFunction(R1, (void *)func);
RestoreDowncount();
}
@ -373,7 +373,7 @@ void Jit::WriteDownCount(int offset)
} else {
// Should be fine to use R2 here, flushed the regcache anyway.
// If js.downcountAmount can be expressed as an Imm8, we don't need this anyway.
MOVI2R(R2, theDowncount);
gpr.SetRegImm(R2, theDowncount);
SUBS(R7, R7, R2);
}
} else {
@ -386,7 +386,7 @@ void Jit::WriteDownCount(int offset)
} else {
// Should be fine to use R2 here, flushed the regcache anyway.
// If js.downcountAmount can be expressed as an Imm8, we don't need this anyway.
MOVI2R(R2, theDowncount);
gpr.SetRegImm(R2, theDowncount);
SUBS(R1, R1, R2);
STR(R1, CTXREG, offsetof(MIPSState, downcount));
}
@ -412,7 +412,7 @@ void Jit::WriteExit(u32 destination, int exit_num)
B(blocks.GetBlock(block)->checkedEntry);
b->linkStatus[exit_num] = true;
} else {
MOVI2R(R0, destination);
gpr.SetRegImm(R0, destination);
B((const void *)dispatcherPCInR0);
}
}

View File

@ -100,6 +100,10 @@ bool ArmRegCache::IsMappedAsPointer(MIPSGPReg mipsReg) {
return mr[mipsReg].loc == ML_ARMREG_AS_PTR;
}
void ArmRegCache::SetRegImm(ARMReg reg, u32 imm) {
emit_->MOVI2R(reg, imm);
}
void ArmRegCache::MapRegTo(ARMReg reg, MIPSGPReg mipsReg, int mapFlags) {
ar[reg].isDirty = (mapFlags & MAP_DIRTY) ? true : false;
if (!(mapFlags & MAP_NOINIT)) {
@ -119,7 +123,7 @@ void ArmRegCache::MapRegTo(ARMReg reg, MIPSGPReg mipsReg, int mapFlags) {
mr[mipsReg].loc = ML_ARMREG;
break;
case ML_IMM:
emit_->MOVI2R(reg, mr[mipsReg].imm);
SetRegImm(reg, mr[mipsReg].imm);
ar[reg].isDirty = true; // IMM is always dirty.
// If we are mapping dirty, it means we're gonna overwrite.
@ -311,7 +315,7 @@ void ArmRegCache::FlushR(MIPSGPReg r) {
case ML_IMM:
// IMM is always "dirty".
if (r != MIPS_REG_ZERO) {
emit_->MOVI2R(R0, mr[r].imm);
SetRegImm(R0, mr[r].imm);
emit_->STR(R0, CTXREG, GetMipsRegOffset(r));
}
break;

View File

@ -90,6 +90,8 @@ public:
void SetImm(MIPSGPReg reg, u32 immVal);
bool IsImm(MIPSGPReg reg) const;
u32 GetImm(MIPSGPReg reg) const;
// Optimally set a register to an imm value (possibly using another register.)
void SetRegImm(ARMReg reg, u32 imm);
// Returns an ARM register containing the requested MIPS register.
ARMReg MapReg(MIPSGPReg reg, int mapFlags = 0);