Merge pull request #440 from unknownbrackets/jit-minor

Micro optimizations to x86 jit mem when fastmem is off
This commit is contained in:
Henrik Rydgård 2013-01-19 02:04:34 -08:00
commit c20cef2399
3 changed files with 196 additions and 16 deletions

View File

@ -160,6 +160,16 @@ void XEmitter::ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2
ABI_RestoreStack(2 * 4); ABI_RestoreStack(2 * 4);
} }
void XEmitter::ABI_CallFunctionACC(void *func, const Gen::OpArg &arg1, u32 param2, u32 param3)
{
ABI_AlignStack(3 * 4);
PUSH(32, Imm32(param3));
PUSH(32, Imm32(param2));
PUSH(32, arg1);
CALL(func);
ABI_RestoreStack(3 * 4);
}
void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1) void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1)
{ {
ABI_AlignStack(1 * 4); ABI_AlignStack(1 * 4);
@ -404,6 +414,22 @@ void XEmitter::ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2
} }
} }
void XEmitter::ABI_CallFunctionACC(void *func, const Gen::OpArg &arg1, u32 param2, u32 param3)
{
MOV(32, R(ABI_PARAM1), arg1);
MOV(32, R(ABI_PARAM2), Imm32(param2));
MOV(64, R(ABI_PARAM3), Imm64(param3));
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
// Far call
MOV(64, R(RAX), Imm64((u64)func));
CALLptr(R(RAX));
} else {
CALL(func);
}
}
void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1) void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1)
{ {
if (!arg1.IsSimpleReg(ABI_PARAM1)) if (!arg1.IsSimpleReg(ABI_PARAM1))

View File

@ -656,6 +656,7 @@ public:
void ABI_CallFunctionCCCP(void *func, u32 param1, u32 param2,u32 param3, void *param4); void ABI_CallFunctionCCCP(void *func, u32 param1, u32 param2,u32 param3, void *param4);
void ABI_CallFunctionPPC(void *func, void *param1, void *param2,u32 param3); void ABI_CallFunctionPPC(void *func, void *param1, void *param2,u32 param3);
void ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2); void ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2);
void ABI_CallFunctionACC(void *func, const Gen::OpArg &arg1, u32 param2, u32 param3);
void ABI_CallFunctionA(void *func, const Gen::OpArg &arg1); void ABI_CallFunctionA(void *func, const Gen::OpArg &arg1);
// Pass a register as a paremeter. // Pass a register as a paremeter.

View File

@ -41,13 +41,28 @@
namespace MIPSComp namespace MIPSComp
{ {
static void ReadMemSafe32(u32 addr, int preg, u32 offset)
{
currentMIPS->r[preg] = Memory::Read_U32(addr + offset);
}
static void ReadMemSafe16(u32 addr, int preg, u32 offset)
{
currentMIPS->r[preg] = Memory::Read_U16(addr + offset);
}
static void WriteMemSafe32(u32 addr, int preg, u32 offset)
{
Memory::Write_U32(currentMIPS->r[preg], addr + offset);
}
static void WriteMemSafe16(u32 addr, int preg, u32 offset)
{
Memory::Write_U16(currentMIPS->r[preg], addr + offset);
}
void Jit::Comp_ITypeMem(u32 op) void Jit::Comp_ITypeMem(u32 op)
{ {
if (!g_Config.bFastMemory)
{
DISABLE;
}
int offset = (signed short)(op&0xFFFF); int offset = (signed short)(op&0xFFFF);
int rt = _RT; int rt = _RT;
int rs = _RS; int rs = _RS;
@ -60,35 +75,173 @@ namespace MIPSComp
switch (o) switch (o)
{ {
case 37: //R(rt) = ReadMem16(addr); break; //lhu case 37: //R(rt) = ReadMem16(addr); break; //lhu
if (!g_Config.bFastMemory)
{
FlushAll();
gpr.Lock(rt, rs);
gpr.BindToRegister(rt, rt == rs, true);
MOV(32, R(EAX), gpr.R(rs));
CMP(32, R(EAX), Imm32(0x08000000));
FixupBranch tooLow = J_CC(CC_L);
CMP(32, R(EAX), Imm32(0x0A000000));
FixupBranch tooHigh = J_CC(CC_GE);
#ifdef _M_IX86
MOVZX(32, 16, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset));
#else
MOVZX(32, 16, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset));
#endif
gpr.UnlockAll();
FlushAll();
FixupBranch skip = J();
SetJumpTarget(tooLow);
SetJumpTarget(tooHigh);
ABI_CallFunctionACC((void *) &ReadMemSafe16, gpr.R(rs), rt, offset);
SetJumpTarget(skip);
}
else
{
gpr.Lock(rt, rs);
gpr.BindToRegister(rt, rt == rs, true);
#ifdef _M_IX86
MOV(32, R(EAX), gpr.R(rs));
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
MOVZX(32, 16, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset));
#else
MOV(32, R(EAX), gpr.R(rs));
MOVZX(32, 16, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset));
#endif
gpr.UnlockAll();
}
break;
case 36: //R(rt) = ReadMem8 (addr); break; //lbu case 36: //R(rt) = ReadMem8 (addr); break; //lbu
Comp_Generic(op); Comp_Generic(op);
return; return;
case 35: //R(rt) = ReadMem32(addr); break; //lw case 35: //R(rt) = ReadMem32(addr); break; //lw
gpr.Lock(rt, rs); if (!g_Config.bFastMemory)
gpr.BindToRegister(rt, rt == rs, true); {
FlushAll();
gpr.Lock(rt, rs);
gpr.BindToRegister(rt, rt == rs, true);
MOV(32, R(EAX), gpr.R(rs));
CMP(32, R(EAX), Imm32(0x08000000));
FixupBranch tooLow = J_CC(CC_L);
CMP(32, R(EAX), Imm32(0x0A000000));
FixupBranch tooHigh = J_CC(CC_GE);
#ifdef _M_IX86 #ifdef _M_IX86
MOV(32, R(EAX), gpr.R(rs)); MOV(32, gpr.R(rt), MDisp(EAX, (u32)Memory::base + offset));
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
MOV(32, gpr.R(rt), MDisp(EAX, (u32)Memory::base + offset));
#else #else
MOV(32, R(EAX), gpr.R(rs)); MOV(32, gpr.R(rt), MComplex(RBX, EAX, SCALE_1, offset));
MOV(32, gpr.R(rt), MComplex(RBX, EAX, SCALE_1, offset));
#endif #endif
gpr.UnlockAll(); gpr.UnlockAll();
FlushAll();
FixupBranch skip = J();
SetJumpTarget(tooLow);
SetJumpTarget(tooHigh);
ABI_CallFunctionACC((void *) &ReadMemSafe32, gpr.R(rs), rt, offset);
SetJumpTarget(skip);
}
else
{
gpr.Lock(rt, rs);
gpr.BindToRegister(rt, rt == rs, true);
#ifdef _M_IX86
MOV(32, R(EAX), gpr.R(rs));
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
MOV(32, gpr.R(rt), MDisp(EAX, (u32)Memory::base + offset));
#else
MOV(32, R(EAX), gpr.R(rs));
MOV(32, gpr.R(rt), MComplex(RBX, EAX, SCALE_1, offset));
#endif
gpr.UnlockAll();
}
break; break;
case 132: //R(rt) = (u32)(s32)(s8) ReadMem8 (addr); break; //lb case 132: //R(rt) = (u32)(s32)(s8) ReadMem8 (addr); break; //lb
case 133: //R(rt) = (u32)(s32)(s16)ReadMem16(addr); break; //lh case 133: //R(rt) = (u32)(s32)(s16)ReadMem16(addr); break; //lh
case 136: //R(rt) = ReadMem8 (addr); break; //lbu case 136: //R(rt) = ReadMem8 (addr); break; //lbu
case 140: //WriteMem8 (addr, R(rt)); break; //sb case 140: //WriteMem8 (addr, R(rt)); break; //sb
case 40:
case 41: //WriteMem16(addr, R(rt)); break; //sh
Comp_Generic(op); Comp_Generic(op);
return; return;
case 41: //WriteMem16(addr, R(rt)); break; //sh
if (!g_Config.bFastMemory)
{
FlushAll();
gpr.Lock(rt, rs);
gpr.BindToRegister(rt, true, true);
MOV(32, R(EAX), gpr.R(rs));
CMP(32, R(EAX), Imm32(0x08000000));
FixupBranch tooLow = J_CC(CC_L);
CMP(32, R(EAX), Imm32(0x0A000000));
FixupBranch tooHigh = J_CC(CC_GE);
#ifdef _M_IX86
MOV(16, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt));
#else
MOV(16, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt));
#endif
gpr.UnlockAll();
FlushAll();
FixupBranch skip = J();
SetJumpTarget(tooLow);
SetJumpTarget(tooHigh);
ABI_CallFunctionACC((void *) &WriteMemSafe16, gpr.R(rs), rt, offset);
SetJumpTarget(skip);
}
else
{
gpr.Lock(rt, rs);
gpr.BindToRegister(rt, true, false);
#ifdef _M_IX86
MOV(32, R(EAX), gpr.R(rs));
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
MOV(16, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt));
#else
MOV(32, R(EAX), gpr.R(rs));
MOV(16, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt));
#endif
gpr.UnlockAll();
}
break;
case 43: //WriteMem32(addr, R(rt)); break; //sw case 43: //WriteMem32(addr, R(rt)); break; //sw
if (!g_Config.bFastMemory)
{
FlushAll();
gpr.Lock(rt, rs);
gpr.BindToRegister(rt, true, true);
MOV(32, R(EAX), gpr.R(rs));
CMP(32, R(EAX), Imm32(0x08000000));
FixupBranch tooLow = J_CC(CC_L);
CMP(32, R(EAX), Imm32(0x0A000000));
FixupBranch tooHigh = J_CC(CC_GE);
#ifdef _M_IX86
MOV(32, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt));
#else
MOV(32, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt));
#endif
gpr.UnlockAll();
FlushAll();
FixupBranch skip = J();
SetJumpTarget(tooLow);
SetJumpTarget(tooHigh);
ABI_CallFunctionACC((void *) &WriteMemSafe32, gpr.R(rs), rt, offset);
SetJumpTarget(skip);
}
else
{ {
gpr.Lock(rt, rs); gpr.Lock(rt, rs);
gpr.BindToRegister(rt, true, false); gpr.BindToRegister(rt, true, false);