Align stack to 16-byte boundary when compiling in 32-bit mode with GCC. This is required to run anything on OS X and to support SSE instructions on Linux.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@439 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
f96d19a1fb
commit
722ea233a1
|
@ -10,42 +10,48 @@ using namespace Gen;
|
|||
// ====================================
|
||||
|
||||
void ABI_CallFunctionC(void *func, u32 param1) {
|
||||
ABI_AlignStack(1 * 4);
|
||||
PUSH(32, Imm32(param1));
|
||||
CALL(func);
|
||||
ADD(32, R(ESP), Imm8(4));
|
||||
ABI_RestoreStack(1 * 4);
|
||||
}
|
||||
|
||||
void ABI_CallFunctionCC(void *func, u32 param1, u32 param2) {
|
||||
ABI_AlignStack(2 * 4);
|
||||
PUSH(32, Imm32(param2));
|
||||
PUSH(32, Imm32(param1));
|
||||
CALL(func);
|
||||
ADD(32, R(ESP), Imm8(8));
|
||||
ABI_RestoreStack(2 * 4);
|
||||
}
|
||||
|
||||
// Pass a register as a paremeter.
|
||||
void ABI_CallFunctionR(void *func, X64Reg reg1) {
|
||||
ABI_AlignStack(1 * 4);
|
||||
PUSH(32, R(reg1));
|
||||
CALL(func);
|
||||
ADD(32, R(ESP), Imm8(4));
|
||||
ABI_RestoreStack(1 * 4);
|
||||
}
|
||||
|
||||
void ABI_CallFunctionRR(void *func, Gen::X64Reg reg1, Gen::X64Reg reg2)
|
||||
{
|
||||
ABI_AlignStack(2 * 4);
|
||||
PUSH(32, R(reg2));
|
||||
PUSH(32, R(reg1));
|
||||
CALL(func);
|
||||
ADD(32, R(ESP), Imm8(8));
|
||||
ABI_RestoreStack(2 * 4);
|
||||
}
|
||||
|
||||
void ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2)
|
||||
{
|
||||
ABI_AlignStack(2 * 4);
|
||||
PUSH(32, arg1);
|
||||
PUSH(32, Imm32(param2));
|
||||
CALL(func);
|
||||
ADD(32, R(ESP), Imm8(8));
|
||||
ABI_RestoreStack(2 * 4);
|
||||
}
|
||||
|
||||
void ABI_PushAllCalleeSavedRegsAndAdjustStack() {
|
||||
// Note: 4 * 4 = 16 bytes, so alignment is preserved.
|
||||
PUSH(EBP);
|
||||
PUSH(EBX);
|
||||
PUSH(ESI);
|
||||
|
@ -59,6 +65,38 @@ void ABI_PopAllCalleeSavedRegsAndAdjustStack() {
|
|||
POP(EBP);
|
||||
}
|
||||
|
||||
void ABI_AlignStack(unsigned int frameSize) {
|
||||
// Mac OS X requires the stack to be 16-byte aligned before every call.
|
||||
// Linux requires the stack to be 16-byte aligned before calls that put SSE
|
||||
// vectors on the stack, but since we do not keep track of which calls do that,
|
||||
// it is effectively every call as well.
|
||||
// Windows binaries compiled with MSVC do not have such a restriction, but I
|
||||
// expect that GCC on Windows acts the same as GCC on Linux in this respect.
|
||||
// It would be nice if someone could verify this.
|
||||
#ifdef __GNUC__
|
||||
frameSize += 4; // reserve space for return address
|
||||
unsigned int paddedSize = (frameSize + 15) & -16;
|
||||
unsigned int fillSize = paddedSize - frameSize;
|
||||
if (fillSize != 0) {
|
||||
SUB(32, R(ESP), Imm8(fillSize));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ABI_RestoreStack(unsigned int frameSize) {
|
||||
frameSize += 4; // reserve space for return address
|
||||
unsigned int paddedSize =
|
||||
#ifdef __GNUC__
|
||||
(frameSize + 15) & -16;
|
||||
#else
|
||||
frameSize;
|
||||
#endif
|
||||
paddedSize -= 4; // return address is already consumed
|
||||
if (paddedSize != 0) {
|
||||
ADD(32, R(ESP), Imm8(paddedSize));
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Shared code between Win64 and Unix64
|
||||
|
@ -99,6 +137,12 @@ void ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2)
|
|||
CALL(func);
|
||||
}
|
||||
|
||||
void ABI_AlignStack(unsigned int /*frameSize*/) {
|
||||
}
|
||||
|
||||
void ABI_RestoreStack(unsigned int /*frameSize*/) {
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// Win64 Specific Code
|
||||
|
|
|
@ -103,6 +103,9 @@ void ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
|||
void ABI_PushAllCallerSavedRegsAndAdjustStack();
|
||||
void ABI_PopAllCallerSavedRegsAndAdjustStack();
|
||||
|
||||
void ABI_AlignStack(unsigned int frameSize);
|
||||
void ABI_RestoreStack(unsigned int frameSize);
|
||||
|
||||
#ifdef _M_IX86
|
||||
inline int ABI_GetNumXMMRegs() { return 8; }
|
||||
#else
|
||||
|
|
|
@ -136,17 +136,17 @@ void *ProtectFunction(void *function, int num_params)
|
|||
// Since parameters are in the previous stack frame, not in registers, this takes some
|
||||
// trickery : we simply re-push the parameters. might not be optimal, but that doesn't really
|
||||
// matter.
|
||||
ABI_AlignStack(num_params * 4);
|
||||
for (int i = 0; i < num_params; i++) {
|
||||
// ESP is changing, so we do not need i
|
||||
PUSH(32, MDisp(ESP, (num_params) * 4));
|
||||
PUSH(32, MDisp(ESP, num_params * 4));
|
||||
}
|
||||
CALL(function);
|
||||
if (num_params)
|
||||
ADD(32, R(ESP), Imm8(num_params * 4));
|
||||
ABI_RestoreStack(num_params * 4);
|
||||
CALL((void*)load_regs);
|
||||
RET();
|
||||
#endif
|
||||
|
||||
thunks[function] = call_point;
|
||||
return (void *)call_point;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1317,6 +1317,7 @@ void CallCdeclFunction3(void* fnptr, u32 arg0, u32 arg1, u32 arg2)
|
|||
#endif
|
||||
|
||||
#else
|
||||
ABI_AlignStack(3 * 4);
|
||||
PUSH(32, Imm32(arg2));
|
||||
PUSH(32, Imm32(arg1));
|
||||
PUSH(32, Imm32(arg0));
|
||||
|
@ -1324,7 +1325,7 @@ void CallCdeclFunction3(void* fnptr, u32 arg0, u32 arg1, u32 arg2)
|
|||
#ifdef _WIN32
|
||||
// don't inc stack
|
||||
#else
|
||||
ADD(32, R(ESP), Imm8(3 * 4));
|
||||
ABI_RestoreStack(3 * 4);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
@ -1349,6 +1350,7 @@ void CallCdeclFunction4(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3)
|
|||
#endif
|
||||
|
||||
#else
|
||||
ABI_AlignStack(4 * 4);
|
||||
PUSH(32, Imm32(arg3));
|
||||
PUSH(32, Imm32(arg2));
|
||||
PUSH(32, Imm32(arg1));
|
||||
|
@ -1357,7 +1359,7 @@ void CallCdeclFunction4(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3)
|
|||
#ifdef _WIN32
|
||||
// don't inc stack
|
||||
#else
|
||||
ADD(32, R(ESP), Imm8(4 * 4));
|
||||
ABI_RestoreStack(4 * 4);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
@ -1384,6 +1386,7 @@ void CallCdeclFunction5(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32
|
|||
#endif
|
||||
|
||||
#else
|
||||
ABI_AlignStack(5 * 4);
|
||||
PUSH(32, Imm32(arg4));
|
||||
PUSH(32, Imm32(arg3));
|
||||
PUSH(32, Imm32(arg2));
|
||||
|
@ -1393,7 +1396,7 @@ void CallCdeclFunction5(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32
|
|||
#ifdef _WIN32
|
||||
// don't inc stack
|
||||
#else
|
||||
ADD(32, R(ESP), Imm8(5 * 4));
|
||||
ABI_RestoreStack(5 * 4);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
@ -1422,6 +1425,7 @@ void CallCdeclFunction6(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32
|
|||
#endif
|
||||
|
||||
#else
|
||||
ABI_AlignStack(6 * 4);
|
||||
PUSH(32, Imm32(arg5));
|
||||
PUSH(32, Imm32(arg4));
|
||||
PUSH(32, Imm32(arg3));
|
||||
|
@ -1432,7 +1436,7 @@ void CallCdeclFunction6(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32
|
|||
#ifdef _WIN32
|
||||
// don't inc stack
|
||||
#else
|
||||
ADD(32, R(ESP), Imm8(6 * 4));
|
||||
ABI_RestoreStack(6 * 4);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -137,9 +137,10 @@ void Generate()
|
|||
SetJumpTarget(notfound);
|
||||
|
||||
//Ok, no block, let's jit
|
||||
ABI_AlignStack(4);
|
||||
PUSH(32, M(&PowerPC::ppcState.pc));
|
||||
CALL(reinterpret_cast<void *>(&Jit));
|
||||
ADD(32, R(ESP), Imm8(4));
|
||||
ABI_RestoreStack(4);
|
||||
JMP(dispatcherNoCheck); // no point in special casing this
|
||||
|
||||
//FP blocks test for FPU available, jump here if false
|
||||
|
|
|
@ -342,9 +342,10 @@ void VertexLoader::Compile()
|
|||
|
||||
for (int i = 0; i < m_numPipelineStates; i++)
|
||||
{
|
||||
ABI_AlignStack(1 * 4);
|
||||
PUSH(32, Imm32((u32)&m_VtxAttr));
|
||||
CALL(m_PipelineStates[i]);
|
||||
ADD(32, R(ESP), Imm8(4));
|
||||
ABI_RestoreStack(1 * 4);
|
||||
}
|
||||
|
||||
ADD(32, M(&varray->count), Imm8(1));
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "Common.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
#include "Profiler.h"
|
||||
#include "StringUtil.h"
|
||||
|
||||
|
@ -536,21 +537,21 @@ void VertexLoader::ProcessFormat()
|
|||
|
||||
int id = GL_TEXTURE0+i;
|
||||
#ifdef _M_X64
|
||||
|
||||
#ifdef _MSC_VER
|
||||
MOV(32, R(RCX), Imm32(id));
|
||||
CALL((void *)glClientActiveTexture);
|
||||
#else
|
||||
MOV(32, R(RDI), Imm32(id));
|
||||
CALL((void *)glClientActiveTexture);
|
||||
#endif
|
||||
|
||||
#else
|
||||
ABI_AlignStack(1 * 4);
|
||||
PUSH(32, Imm32(id));
|
||||
#endif
|
||||
CALL((void *)glClientActiveTexture);
|
||||
// don't inc stack on windows, stdcall
|
||||
#ifndef _WIN32
|
||||
ADD(32, R(ESP), Imm8(4));
|
||||
#ifndef _M_X64
|
||||
#ifdef _WIN32
|
||||
// don't inc stack on windows, stdcall
|
||||
#else
|
||||
ABI_RestoreStack(1 * 4);
|
||||
#endif
|
||||
#endif
|
||||
if( m_components&(VB_HAS_TEXMTXIDX0<<i) ) {
|
||||
|
|
Loading…
Reference in New Issue