mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
EE/IOP/VU: x86-64 recompiler support
This commit is contained in:
committed by
tellowkrinkle
parent
eeca29b6d3
commit
dc57270fb8
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
+132
-133
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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]]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user