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_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
|
||||
|
@ -171,6 +178,23 @@ namespace x86Emitter
|
|||
extern void xINT( u8 imm );
|
||||
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!
|
||||
|
||||
|
|
|
@ -1022,4 +1022,135 @@ __emitinline void xRestoreReg( const xRegisterSSE& dest )
|
|||
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