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:
Gregory Hainaut 2015-12-02 19:06:52 +01:00
parent 3cefa54789
commit 21445fe0d0
2 changed files with 156 additions and 1 deletions

View File

@ -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!

View File

@ -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