Merge pull request #444 from unknownbrackets/jit-minor

Don't muck with currentMIPS->r directly in the slowmem jit
This commit is contained in:
Henrik Rydgård 2013-01-20 01:58:48 -08:00
commit 2cb830510c
4 changed files with 179 additions and 179 deletions

View file

@ -178,6 +178,15 @@ void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1)
ABI_RestoreStack(1 * 4);
}
void XEmitter::ABI_CallFunctionAA(void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2)
{
ABI_AlignStack(2 * 4);
PUSH(32, arg2);
PUSH(32, arg1);
CALL(func);
ABI_RestoreStack(2 * 4);
}
void XEmitter::ABI_PushAllCalleeSavedRegsAndAdjustStack() {
// Note: 4 * 4 = 16 bytes, so alignment is preserved.
PUSH(EBP);
@ -445,6 +454,23 @@ void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1)
}
}
void XEmitter::ABI_CallFunctionAA(void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2)
{
if (!arg1.IsSimpleReg(ABI_PARAM1))
MOV(32, R(ABI_PARAM1), arg1);
if (!arg2.IsSimpleReg(ABI_PARAM2))
MOV(32, R(ABI_PARAM2), arg2);
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);
}
}
unsigned int XEmitter::ABI_GetAlignedFrameSize(unsigned int frameSize) {
return frameSize;
}

View file

@ -658,6 +658,7 @@ public:
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_CallFunctionAA(void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2);
// Pass a register as a paremeter.
void ABI_CallFunctionR(void *func, Gen::X64Reg reg1);

View file

@ -41,28 +41,148 @@
namespace MIPSComp
{
static void ReadMemSafe32(u32 addr, int preg, u32 offset)
void Jit::CompITypeMemRead(u32 op, u32 bits, void (XEmitter::*mov)(int, int, X64Reg, OpArg), void *safeFunc)
{
currentMIPS->r[preg] = Memory::Read_U32(addr + offset);
CONDITIONAL_DISABLE;
int offset = (signed short)(op&0xFFFF);
int rt = _RT;
int rs = _RS;
gpr.Lock(rt, rs);
gpr.BindToRegister(rt, rt == rs, true);
if (gpr.R(rs).IsImm())
{
void *data = Memory::GetPointer(gpr.R(rs).GetImmValue() + offset);
if (data)
{
#ifdef _M_IX86
(this->*mov)(32, bits, gpr.RX(rt), M(data));
#else
(this->*mov)(32, bits, gpr.RX(rt), MDisp(RBX, gpr.R(rs).GetImmValue() + offset));
#endif
}
else
MOV(32, gpr.R(rt), Imm32(0));
}
else if (!g_Config.bFastMemory)
{
MOV(32, R(EAX), gpr.R(rs));
// Is it in physical ram?
CMP(32, R(EAX), Imm32(0x08000000));
FixupBranch tooLow = J_CC(CC_L);
CMP(32, R(EAX), Imm32(0x0A000000));
FixupBranch tooHigh = J_CC(CC_GE);
const u8* safe = GetCodePtr();
#ifdef _M_IX86
(this->*mov)(32, bits, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset));
#else
(this->*mov)(32, bits, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset));
#endif
FixupBranch skip = J();
SetJumpTarget(tooLow);
SetJumpTarget(tooHigh);
// Might also be the scratchpad.
CMP(32, R(EAX), Imm32(0x00010000));
FixupBranch tooLow2 = J_CC(CC_L);
CMP(32, R(EAX), Imm32(0x00014000));
J_CC(CC_L, safe);
SetJumpTarget(tooLow2);
ADD(32, R(EAX), Imm32(offset));
ABI_CallFunctionA(thunks.ProtectFunction(safeFunc, 1), R(EAX));
(this->*mov)(32, bits, gpr.RX(rt), R(EAX));
SetJumpTarget(skip);
}
else
{
MOV(32, R(EAX), gpr.R(rs));
#ifdef _M_IX86
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
(this->*mov)(32, bits, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset));
#else
(this->*mov)(32, bits, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset));
#endif
}
gpr.UnlockAll();
}
static void ReadMemSafe16(u32 addr, int preg, u32 offset)
void Jit::CompITypeMemWrite(u32 op, u32 bits, void *safeFunc)
{
currentMIPS->r[preg] = Memory::Read_U16(addr + offset);
}
CONDITIONAL_DISABLE;
int offset = (signed short)(op&0xFFFF);
int rt = _RT;
int rs = _RS;
static void WriteMemSafe32(u32 addr, int preg, u32 offset)
{
Memory::Write_U32(currentMIPS->r[preg], addr + offset);
}
gpr.Lock(rt, rs);
gpr.BindToRegister(rt, true, false);
static void WriteMemSafe16(u32 addr, int preg, u32 offset)
{
Memory::Write_U16(currentMIPS->r[preg], addr + offset);
if (gpr.R(rs).IsImm())
{
void *data = Memory::GetPointer(gpr.R(rs).GetImmValue() + offset);
if (data)
{
#ifdef _M_IX86
MOV(bits, M(data), gpr.R(rt));
#else
MOV(bits, MDisp(RBX, gpr.R(rs).GetImmValue() + offset), gpr.R(rt));
#endif
}
}
else if (!g_Config.bFastMemory)
{
MOV(32, R(EAX), gpr.R(rs));
// Is it in physical ram?
CMP(32, R(EAX), Imm32(0x08000000));
FixupBranch tooLow = J_CC(CC_L);
CMP(32, R(EAX), Imm32(0x0A000000));
FixupBranch tooHigh = J_CC(CC_GE);
const u8* safe = GetCodePtr();
#ifdef _M_IX86
MOV(bits, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt));
#else
MOV(bits, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt));
#endif
FixupBranch skip = J();
SetJumpTarget(tooLow);
SetJumpTarget(tooHigh);
// Might also be the scratchpad.
CMP(32, R(EAX), Imm32(0x00010000));
FixupBranch tooLow2 = J_CC(CC_L);
CMP(32, R(EAX), Imm32(0x00014000));
J_CC(CC_L, safe);
SetJumpTarget(tooLow2);
ADD(32, R(EAX), Imm32(offset));
ABI_CallFunctionAA(thunks.ProtectFunction(safeFunc, 2), gpr.R(rt), R(EAX));
SetJumpTarget(skip);
}
else
{
MOV(32, R(EAX), gpr.R(rs));
#ifdef _M_IX86
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
MOV(bits, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt));
#else
MOV(bits, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt));
#endif
}
gpr.UnlockAll();
}
void Jit::Comp_ITypeMem(u32 op)
{
CONDITIONAL_DISABLE;
int offset = (signed short)(op&0xFFFF);
int rt = _RT;
int rs = _RS;
@ -75,186 +195,35 @@ namespace MIPSComp
switch (o)
{
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();
}
CompITypeMemRead(op, 16, &XEmitter::MOVZX, (void *) &Memory::Read_U16);
break;
case 36: //R(rt) = ReadMem8 (addr); break; //lbu
Comp_Generic(op);
return;
case 35: //R(rt) = ReadMem32(addr); break; //lw
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
MOV(32, gpr.R(rt), MDisp(EAX, (u32)Memory::base + offset));
#else
MOV(32, gpr.R(rt), MComplex(RBX, EAX, SCALE_1, offset));
#endif
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();
}
CompITypeMemRead(op, 8, &XEmitter::MOVZX, (void *) &Memory::Read_U8);
break;
case 35: //R(rt) = ReadMem32(addr); break; //lw
CompITypeMemRead(op, 32, &XEmitter::MOVZX, (void *) &Memory::Read_U16);
break;
case 32: //R(rt) = (u32)(s32)(s8) ReadMem8 (addr); break; //lb
CompITypeMemRead(op, 8, &XEmitter::MOVSX, (void *) &Memory::Read_U8);
break;
case 33: //R(rt) = (u32)(s32)(s16)ReadMem16(addr); break; //lh
CompITypeMemRead(op, 16, &XEmitter::MOVSX, (void *) &Memory::Read_U16);
break;
case 132: //R(rt) = (u32)(s32)(s8) ReadMem8 (addr); break; //lb
case 133: //R(rt) = (u32)(s32)(s16)ReadMem16(addr); break; //lh
case 136: //R(rt) = ReadMem8 (addr); break; //lbu
case 140: //WriteMem8 (addr, R(rt)); break; //sb
Comp_Generic(op);
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();
}
CompITypeMemWrite(op, 16, (void *) &Memory::Write_U16);
break;
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.BindToRegister(rt, true, false);
#ifdef _M_IX86
MOV(32, R(EAX), gpr.R(rs));
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
MOV(32, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt));
#else
MOV(32, R(EAX), gpr.R(rs));
MOV(32, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt));
#endif
gpr.UnlockAll();
}
CompITypeMemWrite(op, 32, (void *) &Memory::Write_U32);
break;
case 134: //lwl

View file

@ -18,6 +18,7 @@
#pragma once
#include "../../../Globals.h"
#include "../../../Common/Thunk.h"
#include "Asm.h"
#if defined(ARM)
@ -120,6 +121,8 @@ private:
void CompTriArith(u32 op, void (XEmitter::*arith)(int, const OpArg &, const OpArg &));
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);
void CompITypeMemWrite(u32 op, u32 bits, void *safeFunc);
void CompFPTriArith(u32 op, void (XEmitter::*arith)(X64Reg reg, OpArg), bool orderMatters);
@ -131,6 +134,7 @@ private:
FPURegCache fpr;
AsmRoutineManager asm_;
ThunkManager thunks;
MIPSState *mips_;
};