EE/IOP/VU: x86-64 recompiler support

This commit is contained in:
Tellow Krinkle
2020-08-24 16:20:09 -05:00
committed by tellowkrinkle
parent eeca29b6d3
commit dc57270fb8
31 changed files with 680 additions and 493 deletions
@@ -66,6 +66,7 @@ struct xImpl_FastCall
void operator()(void *f, u32 a1, const xRegister32 &a2) const;
void operator()(void *f, const xIndirect32 &a1) const;
void operator()(void *f, u32 a1, u32 a2) const;
void operator()(void *f, void *a1) const;
#ifdef __M_X86_64
void operator()(void *f, const xRegisterLong &a1, const xRegisterLong &a2 = xEmptyReg) const;
+25 -2
View File
@@ -145,6 +145,8 @@ extern void xBSWAP(const xRegister32or64 &to);
extern void xLEA(xRegister64 to, const xIndirectVoid &src, bool preserve_flags = false);
extern void xLEA(xRegister32 to, const xIndirectVoid &src, bool preserve_flags = false);
extern void xLEA(xRegister16 to, const xIndirectVoid &src, bool preserve_flags = false);
/// LEA with a target that will be decided later, guarantees that no optimizations are performed that could change what needs to be written in
extern u32* xLEA_Writeback(xAddressReg to);
// ----- Push / Pop Instructions -----
// Note: pushad/popad implementations are intentionally left out. The instructions are
@@ -198,6 +200,27 @@ public:
~xScopedStackFrame();
};
//////////////////////////////////////////////////////////////////////////////////////////
/// Helper object to save some temporary registers before the call
class xScopedSavedRegisters
{
std::vector<std::reference_wrapper<const xAddressReg>> regs;
public:
xScopedSavedRegisters(std::initializer_list<std::reference_wrapper<const xAddressReg>> regs);
~xScopedSavedRegisters();
};
//////////////////////////////////////////////////////////////////////////////////////////
/// Helper function to calculate base+offset taking into account the limitations of x86-64's RIP-relative addressing
/// (Will either return `base+offset` or LEA `base` into `tmpRegister` and return `tmpRegister+offset`)
xAddressVoid xComplexAddress(const xAddressReg& tmpRegister, void *base, const xAddressVoid& offset);
//////////////////////////////////////////////////////////////////////////////////////////
/// Helper function to load addresses that may be far from the current instruction pointer
/// On i386, resolves to `mov dst, (sptr)addr`
/// On x86-64, resolves to either `mov dst, (sptr)addr` or `lea dst, [addr]` depending on the distance from RIP
void xLoadFarAddr(const xAddressReg& dst, void *addr);
//////////////////////////////////////////////////////////////////////////////////////////
// JMP / Jcc Instructions!
@@ -445,8 +468,8 @@ extern void xMOVNTDQA(const xIndirectVoid &to, const xRegisterSSE &from);
extern void xMOVNTPD(const xIndirectVoid &to, const xRegisterSSE &from);
extern void xMOVNTPS(const xIndirectVoid &to, const xRegisterSSE &from);
extern void xMOVMSKPS(const xRegister32or64 &to, const xRegisterSSE &from);
extern void xMOVMSKPD(const xRegister32or64 &to, const xRegisterSSE &from);
extern void xMOVMSKPS(const xRegister32 &to, const xRegisterSSE &from);
extern void xMOVMSKPD(const xRegister32 &to, const xRegisterSSE &from);
extern void xMASKMOV(const xRegisterSSE &to, const xRegisterSSE &from);
extern void xPMOVMSKB(const xRegister32or64 &to, const xRegisterSSE &from);
+3 -7
View File
@@ -489,6 +489,7 @@ public:
#else
#define xRegisterLong xRegister32
#endif
static const int wordsize = sizeof(sptr);
class xAddressReg : public xRegisterLong
{
@@ -648,14 +649,9 @@ extern const xAddressReg
r8, r9, r10, r11,
r12, r13, r14, r15;
extern const xAddressReg
eax, ebx, ecx, edx,
esi, edi, ebp, esp;
// Temporary registers to aid the move to x86-64
extern const xRegister32
eaxd, ebxd, ecxd, edxd,
esid, edid, ebpd, espd,
eax, ebx, ecx, edx,
esi, edi, ebp, esp,
r8d, r9d, r10d, r11d,
r12d, r13d, r14d, r15d;
+5
View File
@@ -104,6 +104,11 @@ void xImpl_FastCall::operator()(void *f, u32 a1, const xRegisterLong &a2) const
}
#endif
void xImpl_FastCall::operator()(void *f, void *a1) const {
xLEA(arg1reg, ptr[a1]);
(*this)(f, arg1reg, arg2reg);
}
void xImpl_FastCall::operator()(void *f, u32 a1, const xRegister32 &a2) const {
if (!a2.IsEmpty()) { xMOV(arg2regd, a2); }
xMOV(arg1regd, a1);
+2 -2
View File
@@ -711,8 +711,8 @@ __fi void xMOVNTPS(const xIndirectVoid &to, const xRegisterSSE &from) { xOpWrite
// ------------------------------------------------------------------------
__fi void xMOVMSKPS(const xRegister32or64 &to, const xRegisterSSE &from) { xOpWrite0F(0x50, to, from); }
__fi void xMOVMSKPD(const xRegister32or64 &to, const xRegisterSSE &from) { xOpWrite0F(0x66, 0x50, to, from, true); }
__fi void xMOVMSKPS(const xRegister32 &to, const xRegisterSSE &from) { xOpWrite0F(0x50, to, from); }
__fi void xMOVMSKPD(const xRegister32 &to, const xRegisterSSE &from) { xOpWrite0F(0x66, 0x50, to, from, true); }
// xMASKMOV:
// Selectively write bytes from mm1/xmm1 to memory location using the byte mask in mm2/xmm2.
+76 -20
View File
@@ -130,17 +130,11 @@ const xAddressReg
r12(12), r13(13),
r14(14), r15(15);
const xAddressReg
const xRegister32
eax(0), ebx(3),
ecx(1), edx(2),
esp(4), ebp(5),
esi(6), edi(7);
const xRegister32
eaxd(0), ebxd(3),
ecxd(1), edxd(2),
espd(4), ebpd(5),
esid(6), edid(7),
esi(6), edi(7),
r8d(8), r9d(9),
r10d(10), r11d(11),
r12d(12), r13d(13),
@@ -173,10 +167,10 @@ const xAddressReg
calleeSavedReg2 = rsi;
const xRegister32
arg1regd = ecxd,
arg2regd = edxd,
calleeSavedReg1d = edid,
calleeSavedReg2d = esid;
arg1regd = ecx,
arg2regd = edx,
calleeSavedReg1d = edi,
calleeSavedReg2d = esi;
#else
const xAddressReg
arg1reg = rdi,
@@ -187,8 +181,8 @@ const xAddressReg
calleeSavedReg2 = r13;
const xRegister32
arg1regd = edid,
arg2regd = esid,
arg1regd = edi,
arg2regd = esi,
calleeSavedReg1d = r12d,
calleeSavedReg2d = r13d;
#endif
@@ -367,7 +361,7 @@ void EmitSibMagic(uint regfield, const xIndirectVoid &info, int extraRIPOffset)
EmitSibMagic(regfield, (void *)info.Displacement, extraRIPOffset);
return;
} else {
if (info.Index == ebp && displacement_size == 0)
if (info.Index == rbp && displacement_size == 0)
displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]!
ModRM(displacement_size, regfield, info.Index.Id & 7);
@@ -385,7 +379,7 @@ void EmitSibMagic(uint regfield, const xIndirectVoid &info, int extraRIPOffset)
xWrite<s32>(info.Displacement);
return;
} else {
if (info.Base == ebp && displacement_size == 0)
if (info.Base == rbp && displacement_size == 0)
displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]!
ModRM(displacement_size, regfield, ModRm_UseSib);
@@ -896,7 +890,7 @@ static void EmitLeaMagic(const xRegisterInt &to, const xIndirectVoid &src, bool
} else {
if (src.Scale == 0) {
if (!preserve_flags) {
if (src.Index == esp) {
if (src.Index == rsp) {
// ESP is not encodable as an index (ix86 ignores it), thus:
_xMovRtoR(to, sizeMatchedBase); // will do the trick!
if (src.Displacement)
@@ -907,7 +901,7 @@ static void EmitLeaMagic(const xRegisterInt &to, const xIndirectVoid &src, bool
_g1_EmitOp(G1Type_ADD, to, sizeMatchedIndex);
return;
}
} else if ((src.Index == esp) && (src.Displacement == 0)) {
} else if ((src.Index == rsp) && (src.Displacement == 0)) {
// special case handling of ESP as Index, which is replaceable with
// a single MOV even when preserve_flags is set! :D
@@ -937,6 +931,17 @@ __emitinline void xLEA(xRegister16 to, const xIndirectVoid &src, bool preserve_f
EmitLeaMagic(to, src, preserve_flags);
}
__emitinline u32* xLEA_Writeback(xAddressReg to)
{
#ifdef __M_X86_64
xOpWrite(0, 0x8d, to, ptr[(void*)(0xdcdcdcd + (uptr)xGetPtr() + 7)]);
#else
xOpAccWrite(0, 0xb8 | to.Id, 0, to);
xWrite32(0xcdcdcdcd);
#endif
return (u32*)xGetPtr() - 1;
}
// =====================================================================================================
// TEST / INC / DEC
// =====================================================================================================
@@ -1145,6 +1150,14 @@ __emitinline void xRestoreReg(const xRegisterSSE &dest)
#endif
static void stackAlign(int offset, bool moveDown) {
int needed = (16 - (offset % 16)) % 16;
if (moveDown) {
needed = -needed;
}
ALIGN_STACK(needed);
}
xScopedStackFrame::xScopedStackFrame(bool base_frame, bool save_base_pointer, int offset)
{
m_base_frame = base_frame;
@@ -1188,12 +1201,12 @@ xScopedStackFrame::xScopedStackFrame(bool base_frame, bool save_base_pointer, in
#endif
ALIGN_STACK(-(16 - m_offset % 16));
stackAlign(m_offset, true);
}
xScopedStackFrame::~xScopedStackFrame()
{
ALIGN_STACK(16 - m_offset % 16);
stackAlign(m_offset, false);
#ifdef __M_X86_64
@@ -1226,4 +1239,47 @@ xScopedStackFrame::~xScopedStackFrame()
}
}
xScopedSavedRegisters::xScopedSavedRegisters(std::initializer_list<std::reference_wrapper<const xAddressReg>> regs)
: regs(regs)
{
for (auto reg : regs)
{
const xAddressReg& regRef = reg;
xPUSH(regRef);
}
stackAlign(regs.size() * wordsize, true);
}
xScopedSavedRegisters::~xScopedSavedRegisters() {
stackAlign(regs.size() * wordsize, false);
for (auto it = regs.rbegin(); it < regs.rend(); ++it) {
const xAddressReg& regRef = *it;
xPOP(regRef);
}
}
xAddressVoid xComplexAddress(const xAddressReg& tmpRegister, void *base, const xAddressVoid& offset) {
if ((sptr)base == (s32)(sptr)base) {
return offset + base;
} else {
xLEA(tmpRegister, ptr[base]);
return offset + tmpRegister;
}
}
void xLoadFarAddr(const xAddressReg& dst, void *addr) {
#ifdef __M_X86_64
sptr iaddr = (sptr)addr;
sptr rip = (sptr)xGetPtr() + 7; // LEA will be 7 bytes
sptr disp = iaddr - rip;
if (disp == (s32)disp) {
xLEA(dst, ptr[addr]);
} else {
xMOV64(dst, iaddr);
}
#else
xMOV(dst, (sptr)addr);
#endif
}
} // End namespace x86Emitter
+1 -1
View File
@@ -782,7 +782,7 @@ void vtlb_Term()
//nothing to do for now
}
constexpr size_t VMAP_SIZE = sizeof(sptr) * VTLB_VMAP_ITEMS;
constexpr size_t VMAP_SIZE = sizeof(VTLBVirtual) * VTLB_VMAP_ITEMS;
// Reserves the vtlb core allocation used by various emulation components!
// [TODO] basemem - request allocating memory at the specified virtual location, which can allow
+2 -2
View File
@@ -230,14 +230,14 @@ public:
#define PC_GETBLOCK_(x, reclut) ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (x)*(sizeof(BASEBLOCK)/4)))
static void recLUT_SetPage(uptr reclut[0x10000], uptr hwlut[0x10000],
static void recLUT_SetPage(uptr reclut[0x10000], u32 hwlut[0x10000],
BASEBLOCK *mapbase, uint pagebase, uint pageidx, uint mappage)
{
// this value is in 64k pages!
uint page = pagebase + pageidx;
pxAssert( page < 0x10000 );
reclut[page] = (uptr)&mapbase[(mappage - page) << 14];
reclut[page] = (uptr)&mapbase[((s32)mappage - (s32)page) << 14];
if (hwlut)
hwlut[page] = 0u - (pagebase << 16);
}
+5 -2
View File
@@ -118,12 +118,15 @@ extern _x86regs x86regs[iREGCNT_GPR], s_saveX86regs[iREGCNT_GPR];
uptr _x86GetAddr(int type, int reg);
void _initX86regs();
int _getFreeX86reg(int mode);
int _allocX86reg(x86Emitter::xRegisterLong x86reg, int type, int reg, int mode);
[[deprecated]] int _allocX86reg(x86Emitter::xRegister64 x86reg, int type, int reg, int mode);
int _allocX86reg(x86Emitter::xRegister32 x86reg, int type, int reg, int mode);
// To resolve ambiguity between 32 and 64, delete once everything's on 32
int _allocX86reg(x86Emitter::xRegisterEmpty x86reg, int type, int reg, int mode);
void _deleteX86reg(int type, int reg, int flush);
int _checkX86reg(int type, int reg, int mode);
void _addNeededX86reg(int type, int reg);
void _clearNeededX86regs();
void _freeX86reg(const x86Emitter::xRegisterLong& x86reg);
void _freeX86reg(const x86Emitter::xRegister32& x86reg);
void _freeX86reg(int x86reg);
void _freeX86regs();
void _flushCachedRegs();
+3 -3
View File
@@ -397,9 +397,9 @@ void FPU_MUL(int info, int regd, int sreg, int treg, bool acc)
if (CHECK_FPUMULHACK)
{
xMOVD(ecx, xRegisterSSE(sreg));
xMOVD(edx, xRegisterSSE(treg));
xFastCall((void*)(uptr)&FPU_MUL_HACK, ecx, edx); //returns the hacked result or 0
xMOVD(arg1regd, xRegisterSSE(sreg));
xMOVD(arg2regd, xRegisterSSE(treg));
xFastCall((void*)(uptr)&FPU_MUL_HACK, arg1regd, arg2regd); //returns the hacked result or 0
xTEST(eax, eax);
noHack = JZ8(0);
xMOVDZX(xRegisterSSE(regd), eax);
+6 -4
View File
@@ -1500,16 +1500,18 @@ void recQFSRV()
int info = eeRecompileCodeXMM(XMMINFO_WRITED);
xMOV(eax, ptr32[&cpuRegs.sa]);
xMOVDQU(xRegisterSSE(EEREC_D), ptr32[eax + &cpuRegs.GPR.r[_Rt_]]);
xLEA(rcx, ptr[&cpuRegs.GPR.r[_Rt_]]);
xMOVDQU(xRegisterSSE(EEREC_D), ptr32[rax + rcx]);
return;
}
int info = eeRecompileCodeXMM( XMMINFO_READS | XMMINFO_READT | XMMINFO_WRITED );
xMOV(eax, ptr32[&cpuRegs.sa]);
xMOVDQA(ptr32[&tempqw[0]], xRegisterSSE(EEREC_T));
xMOVDQA(ptr32[&tempqw[4]], xRegisterSSE(EEREC_S));
xMOVDQU(xRegisterSSE(EEREC_D), ptr32[eax + &tempqw]);
xLEA(rcx, ptr[tempqw]);
xMOVDQA(ptr32[rcx], xRegisterSSE(EEREC_T));
xMOVDQA(ptr32[rcx+16], xRegisterSSE(EEREC_S));
xMOVDQU(xRegisterSSE(EEREC_D), ptr32[rax + rcx]);
_clearNeededXMMregs();
}
+16 -16
View File
@@ -46,7 +46,7 @@ u32 g_psxMaxRecMem = 0;
u32 s_psxrecblocks[] = {0};
uptr psxRecLUT[0x10000];
uptr psxhwLUT[0x10000];
u32 psxhwLUT[0x10000];
static __fi u32 HWADDR(u32 mem) { return psxhwLUT[mem >> 16] + mem; }
@@ -126,13 +126,13 @@ static DynGenFunc* _DynGen_JITCompile()
u8* retval = xGetPtr();
xFastCall((void*)iopRecRecompile, ptr[&psxRegs.pc] );
xFastCall((void*)iopRecRecompile, ptr32[&psxRegs.pc] );
xMOV( eax, ptr[&psxRegs.pc] );
xMOV( ebx, eax );
xSHR( eax, 16 );
xMOV( ecx, ptr[psxRecLUT + (eax*4)] );
xJMP( ptr32[ecx+ebx] );
xMOV( rcx, ptrNative[xComplexAddress(rcx, psxRecLUT, rax*wordsize)] );
xJMP( ptrNative[rbx*(wordsize/4) + rcx] );
return (DynGenFunc*)retval;
}
@@ -152,8 +152,8 @@ static DynGenFunc* _DynGen_DispatcherReg()
xMOV( eax, ptr[&psxRegs.pc] );
xMOV( ebx, eax );
xSHR( eax, 16 );
xMOV( ecx, ptr[psxRecLUT + (eax*4)] );
xJMP( ptr32[ecx+ebx] );
xMOV( rcx, ptrNative[xComplexAddress(rcx, psxRecLUT, rax*wordsize)] );
xJMP( ptrNative[rbx*(wordsize/4) + rcx] );
return (DynGenFunc*)retval;
}
@@ -391,7 +391,7 @@ void _psxDeleteReg(int reg, int flush)
_deleteX86reg(X86TYPE_PSX, reg, flush ? 0 : 2);
}
void _psxMoveGPRtoR(const xRegisterLong& to, int fromgpr)
void _psxMoveGPRtoR(const xRegister32& to, int fromgpr)
{
if( PSX_IS_CONST1(fromgpr) )
xMOV(to, g_psxConstRegs[fromgpr] );
@@ -863,22 +863,22 @@ void psxSetBranchReg(u32 reg)
psxbranch = 1;
if( reg != 0xffffffff ) {
_allocX86reg(esi, X86TYPE_PCWRITEBACK, 0, MODE_WRITE);
_psxMoveGPRtoR(esi, reg);
_allocX86reg(calleeSavedReg2d, X86TYPE_PCWRITEBACK, 0, MODE_WRITE);
_psxMoveGPRtoR(calleeSavedReg2d, reg);
psxRecompileNextInstruction(1);
if( x86regs[esi.GetId()].inuse ) {
pxAssert( x86regs[esi.GetId()].type == X86TYPE_PCWRITEBACK );
xMOV(ptr[&psxRegs.pc], esi);
x86regs[esi.GetId()].inuse = 0;
if( x86regs[calleeSavedReg2d.GetId()].inuse ) {
pxAssert( x86regs[calleeSavedReg2d.GetId()].type == X86TYPE_PCWRITEBACK );
xMOV(ptr32[&psxRegs.pc], calleeSavedReg2d);
x86regs[calleeSavedReg2d.GetId()].inuse = 0;
#ifdef PCSX2_DEBUG
xOR( esi, esi );
xOR( calleeSavedReg2d, calleeSavedReg2d );
#endif
}
else {
xMOV(eax, ptr[&g_recWriteback]);
xMOV(ptr[&psxRegs.pc], eax);
xMOV(eax, ptr32[&g_recWriteback]);
xMOV(ptr32[&psxRegs.pc], eax);
#ifdef PCSX2_DEBUG
xOR( eax, eax );
+1 -1
View File
@@ -48,7 +48,7 @@ void _psxFlushCall(int flushtype);
void _psxOnWriteReg(int reg);
void _psxMoveGPRtoR(const x86Emitter::xRegisterLong& to, int fromgpr);
void _psxMoveGPRtoR(const x86Emitter::xRegister32& to, int fromgpr);
#if 0
void _psxMoveGPRtoM(uptr to, int fromgpr);
void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr);
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -104,7 +104,7 @@ extern u32 g_cpuHasConstReg, g_cpuFlushedConstReg;
u32* _eeGetConstReg(int reg);
// finds where the GPR is stored and moves lower 32 bits to EAX
void _eeMoveGPRtoR(const x86Emitter::xRegisterLong& to, int fromgpr);
void _eeMoveGPRtoR(const x86Emitter::xRegister32& to, int fromgpr);
void _eeMoveGPRtoM(uptr to, int fromgpr);
void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr);
void eeSignExtendTo(int gpr, bool onlyupper=false);
+13 -3
View File
@@ -239,7 +239,17 @@ void _flushConstRegs()
}
}
int _allocX86reg(xRegisterLong x86reg, int type, int reg, int mode)
int _allocX86reg(xRegisterEmpty x86reg, int type, int reg, int mode)
{
return _allocX86reg(xRegister32(x86reg), type, reg, mode);
}
int _allocX86reg(xRegister64 x86reg, int type, int reg, int mode)
{
return _allocX86reg(xRegister32(x86reg.Id), type, reg, mode);
}
int _allocX86reg(xRegister32 x86reg, int type, int reg, int mode)
{
uint i;
pxAssertDev( reg >= 0 && reg < 32, "Register index out of bounds." );
@@ -313,7 +323,7 @@ int _allocX86reg(xRegisterLong x86reg, int type, int reg, int mode)
}
if (x86reg.IsEmpty())
x86reg = xRegisterLong(_getFreeX86reg(oldmode));
x86reg = xRegister32(_getFreeX86reg(oldmode));
else
_freeX86reg(x86reg);
@@ -440,7 +450,7 @@ void _deleteX86reg(int type, int reg, int flush)
}
// Temporary solution to support eax/ebx... type
void _freeX86reg(const x86Emitter::xRegisterLong& x86reg)
void _freeX86reg(const x86Emitter::xRegister32& x86reg)
{
_freeX86reg(x86reg.GetId());
}
+29 -21
View File
@@ -51,7 +51,7 @@ using namespace R5900;
u32 maxrecmem = 0;
static __aligned16 uptr recLUT[_64kb];
static __aligned16 uptr hwLUT[_64kb];
static __aligned16 u32 hwLUT[_64kb];
static __fi u32 HWADDR(u32 mem) { return hwLUT[mem >> 16] + mem; }
@@ -75,7 +75,7 @@ static const int RECCONSTBUF_SIZE = 16384 * 2; // 64 bit consts in 32 bit units
static RecompiledCodeReserve* recMem = NULL;
static u8* recRAMCopy = NULL;
static u8* recLutReserve_RAM = NULL;
static const size_t recLutSize = Ps2MemSize::MainRam + Ps2MemSize::Rom + Ps2MemSize::Rom1 + Ps2MemSize::Rom2;
static const size_t recLutSize = (Ps2MemSize::MainRam + Ps2MemSize::Rom + Ps2MemSize::Rom1 + Ps2MemSize::Rom2) * wordsize / 4;
static uptr m_ConfiguredCacheReserve = 64;
@@ -153,7 +153,7 @@ u32* _eeGetConstReg(int reg)
return &cpuRegs.GPR.r[ reg ].UL[0];
}
void _eeMoveGPRtoR(const xRegisterLong& to, int fromgpr)
void _eeMoveGPRtoR(const xRegister32& to, int fromgpr)
{
if( fromgpr == 0 )
xXOR(to, to); // zero register should use xor, thanks --air
@@ -346,13 +346,17 @@ static DynGenFunc* _DynGen_JITCompile()
u8* retval = xGetAlignedCallTarget();
xFastCall((void*)recRecompile, ptr[&cpuRegs.pc] );
xFastCall((void*)recRecompile, ptr32[&cpuRegs.pc] );
// C equivalent:
// u32 addr = cpuRegs.pc;
// void(**base)() = (void(**)())recLUT[addr >> 16];
// base[addr >> 2]();
xMOV( eax, ptr[&cpuRegs.pc] );
xMOV( ebx, eax );
xSHR( eax, 16 );
xMOV( ecx, ptr[recLUT + (eax*4)] );
xJMP( ptr32[ecx+ebx] );
xMOV( rcx, ptrNative[xComplexAddress(rcx, recLUT, rax*wordsize)] );
xJMP( ptrNative[rbx*(wordsize/4) + rcx] );
return (DynGenFunc*)retval;
}
@@ -369,11 +373,15 @@ static DynGenFunc* _DynGen_DispatcherReg()
{
u8* retval = xGetPtr(); // fallthrough target, can't align it!
// C equivalent:
// u32 addr = cpuRegs.pc;
// void(**base)() = (void(**)())recLUT[addr >> 16];
// base[addr >> 2]();
xMOV( eax, ptr[&cpuRegs.pc] );
xMOV( ebx, eax );
xSHR( eax, 16 );
xMOV( ecx, ptr[recLUT + (eax*4)] );
xJMP( ptr32[ecx+ebx] );
xMOV( rcx, ptrNative[xComplexAddress(rcx, recLUT, rax*wordsize)] );
xJMP( ptrNative[rbx*(wordsize/4) + rcx] );
return (DynGenFunc*)retval;
}
@@ -461,7 +469,7 @@ static void _DynGen_Dispatchers()
static __ri void ClearRecLUT(BASEBLOCK* base, int memsize)
{
for (int i = 0; i < memsize/4; i++)
for (int i = 0; i < memsize/(int)sizeof(uptr); i++)
base[i].SetFnptr((uptr)JITCompile);
}
@@ -521,7 +529,7 @@ static void recAlloc()
for (int i = 0; i < 0x10000; i++)
recLUT_SetPage(recLUT, 0, 0, 0, i, 0);
for ( int i = 0x0000; i < Ps2MemSize::MainRam / 0x10000; i++ )
for ( int i = 0x0000; i < (int)(Ps2MemSize::MainRam / 0x10000); i++ )
{
recLUT_SetPage(recLUT, hwLUT, recRAM, 0x0000, i, i);
recLUT_SetPage(recLUT, hwLUT, recRAM, 0x2000, i, i);
@@ -864,21 +872,21 @@ void SetBranchReg( u32 reg )
// xMOV(ptr[&cpuRegs.pc], eax);
// }
// }
_allocX86reg(esi, X86TYPE_PCWRITEBACK, 0, MODE_WRITE);
_eeMoveGPRtoR(esi, reg);
_allocX86reg(calleeSavedReg2d, X86TYPE_PCWRITEBACK, 0, MODE_WRITE);
_eeMoveGPRtoR(calleeSavedReg2d, reg);
if (EmuConfig.Gamefixes.GoemonTlbHack) {
xMOV(ecx, esi);
xMOV(ecx, calleeSavedReg2d);
vtlb_DynV2P();
xMOV(esi, eax);
xMOV(calleeSavedReg2d, eax);
}
recompileNextInstruction(1);
if( x86regs[esi.GetId()].inuse ) {
pxAssert( x86regs[esi.GetId()].type == X86TYPE_PCWRITEBACK );
xMOV(ptr[&cpuRegs.pc], esi);
x86regs[esi.GetId()].inuse = 0;
if( x86regs[calleeSavedReg2d.GetId()].inuse ) {
pxAssert( x86regs[calleeSavedReg2d.GetId()].type == X86TYPE_PCWRITEBACK );
xMOV(ptr[&cpuRegs.pc], calleeSavedReg2d);
x86regs[calleeSavedReg2d.GetId()].inuse = 0;
}
else {
xMOV(eax, ptr[&g_recWriteback]);
@@ -1525,8 +1533,8 @@ static void memory_protect_recompiled_code(u32 startpc, u32 size)
break;
case ProtMode_Manual:
xMOV( ecx, inpage_ptr );
xMOV( edx, inpage_sz / 4 );
xMOV( arg1regd, inpage_ptr );
xMOV( arg2regd, inpage_sz / 4 );
//xMOV( eax, startpc ); // uncomment this to access startpc (as eax) in dyna_block_discard
u32 lpc = inpage_ptr;
@@ -1737,7 +1745,7 @@ static void __fastcall recRecompile( const u32 startpc )
// Game will unmap some virtual addresses. If a constant address were hardcoded in the block, we would be in a bad situation.
eeRecNeedsReset = true;
// 0x3563b8 is the start address of the function that invalidate entry in TLB cache
xFastCall((void*)GoemonUnloadTlb, ptr[&cpuRegs.GPR.n.a0.UL[0]]);
xFastCall((void*)GoemonUnloadTlb, ptr32[&cpuRegs.GPR.n.a0.UL[0]]);
}
}
+2 -2
View File
@@ -148,7 +148,7 @@ void recSLTIU_(int info)
x86SetJ8(j8Ptr[0]);
x86SetJ8(j8Ptr[1]);
xMOV(ptr[&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]], eax);
xMOV(ptr32[&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]], eax);
xMOV(ptr32[&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]], 0 );
}
@@ -178,7 +178,7 @@ void recSLTI_(int info)
x86SetJ8(j8Ptr[0]);
x86SetJ8(j8Ptr[1]);
xMOV(ptr[&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]], eax);
xMOV(ptr32[&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]], eax);
xMOV(ptr32[&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]], 0 );
}
+8 -8
View File
@@ -103,13 +103,13 @@ void recJALR()
EE::Profiler.EmitOp(eeOpcode::JALR);
int newpc = pc + 4;
_allocX86reg(esi, X86TYPE_PCWRITEBACK, 0, MODE_WRITE);
_eeMoveGPRtoR(esi, _Rs_);
_allocX86reg(calleeSavedReg2d, X86TYPE_PCWRITEBACK, 0, MODE_WRITE);
_eeMoveGPRtoR(calleeSavedReg2d, _Rs_);
if (EmuConfig.Gamefixes.GoemonTlbHack) {
xMOV(ecx, esi);
xMOV(ecx, calleeSavedReg2d);
vtlb_DynV2P();
xMOV(esi, eax);
xMOV(calleeSavedReg2d, eax);
}
// uncomment when there are NO instructions that need to call interpreter
// int mmreg;
@@ -147,10 +147,10 @@ void recJALR()
_clearNeededXMMregs();
recompileNextInstruction(1);
if( x86regs[esi.GetId()].inuse ) {
pxAssert( x86regs[esi.GetId()].type == X86TYPE_PCWRITEBACK );
xMOV(ptr[&cpuRegs.pc], esi);
x86regs[esi.GetId()].inuse = 0;
if( x86regs[calleeSavedReg2d.GetId()].inuse ) {
pxAssert( x86regs[calleeSavedReg2d.GetId()].type == X86TYPE_PCWRITEBACK );
xMOV(ptr[&cpuRegs.pc], calleeSavedReg2d);
x86regs[calleeSavedReg2d.GetId()].inuse = 0;
}
else {
xMOV(eax, ptr[&g_recWriteback]);
+77 -77
View File
@@ -99,13 +99,13 @@ void recLoad64( u32 bits, bool sign )
{
pxAssume( bits == 64 || bits == 128 );
// Load EDX with the destination.
// Load arg2 with the destination.
// 64/128 bit modes load the result directly into the cpuRegs.GPR struct.
if (_Rt_)
xMOV(edx, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]);
xLEA(arg2reg, ptr[&cpuRegs.GPR.r[_Rt_].UL[0]]);
else
xMOV(edx, (uptr)&dummyValue[0]);
xLEA(arg2reg, ptr[&dummyValue[0]]);
if (GPR_IS_CONST1(_Rs_))
{
@@ -121,11 +121,11 @@ void recLoad64( u32 bits, bool sign )
else
{
// Load ECX with the source memory address that we're reading from.
_eeMoveGPRtoR(ecx, _Rs_);
_eeMoveGPRtoR(arg1regd, _Rs_);
if (_Imm_ != 0)
xADD(ecx, _Imm_);
xADD(arg1regd, _Imm_);
if (bits == 128) // force 16 byte alignment on 128 bit reads
xAND(ecx, ~0x0F);
xAND(arg1regd, ~0x0F);
_eeOnLoadWrite(_Rt_);
_deleteEEreg(_Rt_, 0);
@@ -154,10 +154,10 @@ void recLoad32( u32 bits, bool sign )
}
else
{
// Load ECX with the source memory address that we're reading from.
_eeMoveGPRtoR(ecx, _Rs_);
// Load arg1 with the source memory address that we're reading from.
_eeMoveGPRtoR(arg1regd, _Rs_);
if (_Imm_ != 0)
xADD(ecx, _Imm_ );
xADD(arg1regd, _Imm_ );
_eeOnLoadWrite(_Rt_);
_deleteEEreg(_Rt_, 0);
@@ -194,12 +194,12 @@ void recStore(u32 bits)
if (bits < 64)
{
_eeMoveGPRtoR(edx, _Rt_);
_eeMoveGPRtoR(arg2regd, _Rt_);
}
else if (bits == 128 || bits == 64)
{
_flushEEreg(_Rt_); // flush register to mem
xMOV(edx, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]);
xLEA(arg2reg, ptr[&cpuRegs.GPR.r[_Rt_].UL[0]]);
}
// Load ECX with the destination address, or issue a direct optimized write
@@ -215,11 +215,11 @@ void recStore(u32 bits)
}
else
{
_eeMoveGPRtoR(ecx, _Rs_);
_eeMoveGPRtoR(arg1regd, _Rs_);
if (_Imm_ != 0)
xADD(ecx, _Imm_);
xADD(arg1regd, _Imm_);
if (bits == 128)
xAND(ecx, ~0x0F);
xAND(arg1regd, ~0x0F);
iFlushCall(FLUSH_FULLVTLB);
@@ -253,30 +253,30 @@ void recLWL()
iFlushCall(FLUSH_FULLVTLB);
_deleteEEreg(_Rt_, 1);
_eeMoveGPRtoR(ecx, _Rs_);
_eeMoveGPRtoR(arg1regd, _Rs_);
if (_Imm_ != 0)
xADD(ecx, _Imm_);
xADD(arg1regd, _Imm_);
// edi = bit offset in word
xMOV(edi, ecx);
xAND(edi, 3);
xSHL(edi, 3);
// calleeSavedReg1 = bit offset in word
xMOV(calleeSavedReg1d, arg1regd);
xAND(calleeSavedReg1d, 3);
xSHL(calleeSavedReg1d, 3);
xAND(ecx, ~3);
xAND(arg1regd, ~3);
vtlb_DynGenRead32(32, false);
if (!_Rt_)
return;
// mask off bytes loaded
xMOV(ecx, edi);
xMOV(ecx, calleeSavedReg1d);
xMOV(edx, 0xffffff);
xSHR(edx, cl);
xAND(ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]], edx);
// OR in bytes loaded
xMOV(ecx, 24);
xSUB(ecx, edi);
xNEG(ecx);
xADD(ecx, 24);
xSHL(eax, cl);
xOR(ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]], eax);
@@ -301,16 +301,16 @@ void recLWR()
iFlushCall(FLUSH_FULLVTLB);
_deleteEEreg(_Rt_, 1);
_eeMoveGPRtoR(ecx, _Rs_);
_eeMoveGPRtoR(arg1regd, _Rs_);
if (_Imm_ != 0)
xADD(ecx, _Imm_);
xADD(arg1regd, _Imm_);
// edi = bit offset in word
xMOV(edi, ecx);
xAND(edi, 3);
xSHL(edi, 3);
xMOV(calleeSavedReg1d, arg1regd);
xAND(calleeSavedReg1d, 3);
xSHL(calleeSavedReg1d, 3);
xAND(ecx, ~3);
xAND(arg1regd, ~3);
vtlb_DynGenRead32(32, false);
if (!_Rt_)
@@ -318,17 +318,17 @@ void recLWR()
// mask off bytes loaded
xMOV(ecx, 24);
xSUB(ecx, edi);
xSUB(ecx, calleeSavedReg1d);
xMOV(edx, 0xffffff00);
xSHL(edx, cl);
xAND(ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]], edx);
// OR in bytes loaded
xMOV(ecx, edi);
xMOV(ecx, calleeSavedReg1d);
xSHR(eax, cl);
xOR(ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]], eax);
xCMP(edi, 0);
xCMP(ecx, 0);
xForwardJump8 nosignextend(Jcc_NotEqual);
// if ((addr & 3) == 0)
xCDQ();
@@ -351,38 +351,38 @@ void recSWL()
#ifdef REC_STORES
iFlushCall(FLUSH_FULLVTLB);
_eeMoveGPRtoR(ecx, _Rs_);
_eeMoveGPRtoR(arg1regd, _Rs_);
if (_Imm_ != 0)
xADD(ecx, _Imm_);
xADD(arg1regd, _Imm_);
// edi = bit offset in word
xMOV(edi, ecx);
xAND(edi, 3);
xSHL(edi, 3);
xMOV(calleeSavedReg1d, arg1regd);
xAND(calleeSavedReg1d, 3);
xSHL(calleeSavedReg1d, 3);
xAND(ecx, ~3);
xAND(arg1regd, ~3);
vtlb_DynGenRead32(32, false);
// mask read -> edx
xMOV(ecx, edi);
xMOV(edx, 0xffffff00);
xSHL(edx, cl);
xAND(edx, eax);
// mask read -> arg2
xMOV(ecx, calleeSavedReg1d);
xMOV(arg2regd, 0xffffff00);
xSHL(arg2regd, cl);
xAND(arg2regd, eax);
if (_Rt_)
{
// mask write and OR -> edx
xMOV(ecx, 24);
xSUB(ecx, edi);
xNEG(ecx);
xADD(ecx, 24);
_eeMoveGPRtoR(eax, _Rt_);
xSHR(eax, cl);
xOR(edx, eax);
xOR(arg2regd, eax);
}
_eeMoveGPRtoR(ecx, _Rs_);
_eeMoveGPRtoR(arg1regd, _Rs_);
if (_Imm_ != 0)
xADD(ecx, _Imm_);
xAND(ecx, ~3);
xADD(arg1regd, _Imm_);
xAND(arg1regd, ~3);
vtlb_DynGenWrite(32);
#else
@@ -401,38 +401,38 @@ void recSWR()
#ifdef REC_STORES
iFlushCall(FLUSH_FULLVTLB);
_eeMoveGPRtoR(ecx, _Rs_);
_eeMoveGPRtoR(arg1regd, _Rs_);
if (_Imm_ != 0)
xADD(ecx, _Imm_);
xADD(arg1regd, _Imm_);
// edi = bit offset in word
xMOV(edi, ecx);
xAND(edi, 3);
xSHL(edi, 3);
xMOV(calleeSavedReg1d, arg1regd);
xAND(calleeSavedReg1d, 3);
xSHL(calleeSavedReg1d, 3);
xAND(ecx, ~3);
xAND(arg1regd, ~3);
vtlb_DynGenRead32(32, false);
// mask read -> edx
xMOV(ecx, 24);
xSUB(ecx, edi);
xMOV(edx, 0xffffff);
xSHR(edx, cl);
xAND(edx, eax);
xSUB(ecx, calleeSavedReg1d);
xMOV(arg2regd, 0xffffff);
xSHR(arg2regd, cl);
xAND(arg2regd, eax);
if (_Rt_)
{
// mask write and OR -> edx
xMOV(ecx, edi);
xMOV(ecx, calleeSavedReg1d);
_eeMoveGPRtoR(eax, _Rt_);
xSHL(eax, cl);
xOR(edx, eax);
xOR(arg2regd, eax);
}
_eeMoveGPRtoR(ecx, _Rs_);
_eeMoveGPRtoR(arg1regd, _Rs_);
if (_Imm_ != 0)
xADD(ecx, _Imm_);
xAND(ecx, ~3);
xADD(arg1regd, _Imm_);
xAND(arg1regd, ~3);
vtlb_DynGenWrite(32);
#else
@@ -512,9 +512,9 @@ void recLWC1()
}
else
{
_eeMoveGPRtoR(ecx, _Rs_);
_eeMoveGPRtoR(arg1regd, _Rs_);
if (_Imm_ != 0)
xADD(ecx, _Imm_);
xADD(arg1regd, _Imm_);
iFlushCall(FLUSH_FULLVTLB);
@@ -536,7 +536,7 @@ void recSWC1()
#else
_deleteFPtoXMMreg(_Rt_, 1);
xMOV(edx, ptr32[&fpuRegs.fpr[_Rt_].UL] );
xMOV(arg2regd, ptr32[&fpuRegs.fpr[_Rt_].UL] );
if( GPR_IS_CONST1( _Rs_ ) )
{
@@ -545,9 +545,9 @@ void recSWC1()
}
else
{
_eeMoveGPRtoR(ecx, _Rs_);
_eeMoveGPRtoR(arg1regd, _Rs_);
if (_Imm_ != 0)
xADD(ecx, _Imm_);
xADD(arg1regd, _Imm_);
iFlushCall(FLUSH_FULLVTLB);
@@ -574,9 +574,9 @@ void recSWC1()
void recLQC2()
{
if (_Rt_)
xMOV(edx, (uptr)&VU0.VF[_Ft_].UD[0]);
xLEA(arg2reg, ptr[&VU0.VF[_Ft_].UD[0]]);
else
xMOV(edx, (uptr)&dummyValue[0]);
xLEA(arg2reg, ptr[&dummyValue[0]]);
if (GPR_IS_CONST1(_Rs_))
{
@@ -586,9 +586,9 @@ void recLQC2()
}
else
{
_eeMoveGPRtoR(ecx, _Rs_);
_eeMoveGPRtoR(arg1regd, _Rs_);
if (_Imm_ != 0)
xADD(ecx, _Imm_);
xADD(arg1regd, _Imm_);
iFlushCall(FLUSH_FULLVTLB);
@@ -602,7 +602,7 @@ void recLQC2()
void recSQC2()
{
xMOV(edx, (uptr)&VU0.VF[_Ft_].UD[0]);
xLEA(arg2reg, ptr[&VU0.VF[_Ft_].UD[0]]);
if (GPR_IS_CONST1(_Rs_))
{
@@ -611,9 +611,9 @@ void recSQC2()
}
else
{
_eeMoveGPRtoR(ecx, _Rs_);
_eeMoveGPRtoR(arg1regd, _Rs_);
if (_Imm_ != 0)
xADD(ecx, _Imm_);
xADD(arg1regd, _Imm_);
iFlushCall(FLUSH_FULLVTLB);

Some files were not shown because too many files have changed in this diff Show More