mirror of https://github.com/PCSX2/pcsx2.git
x86emitter: Add several architecture dependant wrapper
* A nice object to create the stack frame * Various xStdCall/xFastCall to emulate standard & fast call
This commit is contained in:
parent
3cefa54789
commit
21445fe0d0
|
@ -85,7 +85,14 @@ namespace x86Emitter
|
||||||
|
|
||||||
extern const xImpl_BitScan xBSF, xBSR;
|
extern const xImpl_BitScan xBSF, xBSR;
|
||||||
|
|
||||||
extern const xImpl_JmpCall xJMP, xCALL;
|
extern const xImpl_JmpCall xJMP;
|
||||||
|
#ifdef __x86_64__
|
||||||
|
// 32 bits Call won't be compatible in 64 bits (different ABI)
|
||||||
|
// Just a reminder to port the code
|
||||||
|
[[deprecated]] extern const xImpl_JmpCall xCALL;
|
||||||
|
#else
|
||||||
|
extern const xImpl_JmpCall xCALL;
|
||||||
|
#endif
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
extern const xImpl_CMov
|
extern const xImpl_CMov
|
||||||
|
@ -171,6 +178,23 @@ namespace x86Emitter
|
||||||
extern void xINT( u8 imm );
|
extern void xINT( u8 imm );
|
||||||
extern void xINTO();
|
extern void xINTO();
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Helper function to handle the various functions ABI
|
||||||
|
extern void xFastCall(void* func, const xRegister32& a1 = xEmptyReg, const xRegister32& a2 = xEmptyReg);
|
||||||
|
extern void xFastCall(void* func, const xRegisterSSE& a1, const xRegisterSSE& a2);
|
||||||
|
extern void xFastCall(void* func, u32 a1, u32 a2);
|
||||||
|
extern void xFastCall(void* func, u32 a1);
|
||||||
|
|
||||||
|
extern void xStdCall(void* func, u32 a1);
|
||||||
|
|
||||||
|
class xScopedStackFrame
|
||||||
|
{
|
||||||
|
bool m_base_frame;
|
||||||
|
|
||||||
|
xScopedStackFrame(bool base_frame);
|
||||||
|
~xScopedStackFrame();
|
||||||
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// JMP / Jcc Instructions!
|
// JMP / Jcc Instructions!
|
||||||
|
|
||||||
|
|
|
@ -1022,4 +1022,135 @@ __emitinline void xRestoreReg( const xRegisterSSE& dest )
|
||||||
xMOVDQA( dest, ptr[&xmm_data[dest.Id*2]] );
|
xMOVDQA( dest, ptr[&xmm_data[dest.Id*2]] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Helper function to handle the various functions ABI
|
||||||
|
|
||||||
|
__emitinline void xFastCall(void *func, const xRegister32& a1, const xRegister32& a2)
|
||||||
|
{
|
||||||
|
#ifdef __x86_64__
|
||||||
|
// NEW ABI
|
||||||
|
pxAssert(0);
|
||||||
|
#else
|
||||||
|
if (!a1.IsEmpty())
|
||||||
|
xMOV(ecx, a1);
|
||||||
|
|
||||||
|
if (!a2.IsEmpty())
|
||||||
|
xMOV(edx, a2);
|
||||||
|
|
||||||
|
xCALL(func);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__emitinline void xFastCall(void *func, const xRegisterSSE& a1, const xRegisterSSE& a2)
|
||||||
|
{
|
||||||
|
#ifdef __x86_64__
|
||||||
|
// NEW ABI
|
||||||
|
pxAssert(0);
|
||||||
|
#else
|
||||||
|
xMOVD(ecx, a1);
|
||||||
|
xMOVD(edx, a2);
|
||||||
|
|
||||||
|
xCALL(func);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
__emitinline void xFastCall(void *func, u32 a1, u32 a2)
|
||||||
|
{
|
||||||
|
#ifdef __x86_64__
|
||||||
|
// NEW ABI
|
||||||
|
pxAssert(0);
|
||||||
|
#else
|
||||||
|
xMOV(ecx, a1);
|
||||||
|
xMOV(edx, a2);
|
||||||
|
|
||||||
|
xCALL(func);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
__emitinline void xFastCall(void *func, u32 a1)
|
||||||
|
{
|
||||||
|
#ifdef __x86_64__
|
||||||
|
// NEW ABI
|
||||||
|
pxAssert(0);
|
||||||
|
#else
|
||||||
|
xMOV(ecx, a1);
|
||||||
|
|
||||||
|
xCALL(func);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
__emitinline void xStdCall(void *func, u32 a1)
|
||||||
|
{
|
||||||
|
#ifdef __x86_64__
|
||||||
|
// NEW ABI
|
||||||
|
pxAssert(0);
|
||||||
|
#else
|
||||||
|
// GCC note: unlike C call, GCC doesn't requires
|
||||||
|
// strict 16B alignment on std call
|
||||||
|
xPUSH(a1);
|
||||||
|
xCALL(func);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Helper object to handle ABI frame
|
||||||
|
|
||||||
|
xScopedStackFrame::xScopedStackFrame(bool base_frame)
|
||||||
|
{
|
||||||
|
m_base_frame = base_frame;
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
// NEW ABI
|
||||||
|
pxAssert(0);
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Create a new frame
|
||||||
|
if (m_base_frame) {
|
||||||
|
xPUSH( ebp );
|
||||||
|
xMOV( ebp, esp );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the register context
|
||||||
|
xPUSH( edi );
|
||||||
|
xPUSH( esi );
|
||||||
|
xPUSH( ebx );
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
// Realign the stack to 16 byte
|
||||||
|
if (m_base_frame) {
|
||||||
|
xSUB( esp, 12);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
xScopedStackFrame::~xScopedStackFrame()
|
||||||
|
{
|
||||||
|
#ifdef __x86_64__
|
||||||
|
// NEW ABI
|
||||||
|
pxAssert(0);
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
// Restore the stack (due to the above alignment)
|
||||||
|
// Potentially it can be restored from ebp
|
||||||
|
if (m_base_frame) {
|
||||||
|
xADD( esp, 12);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Restore the register context
|
||||||
|
xPOP( ebx );
|
||||||
|
xPOP( esi );
|
||||||
|
xPOP( edi );
|
||||||
|
|
||||||
|
// Destroy the frame
|
||||||
|
if (m_base_frame) {
|
||||||
|
xLEAVE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace x86Emitter
|
||||||
|
|
Loading…
Reference in New Issue