Fix stack misalignment issues.

- Call ABI_AlignStack even on x86-64.

- Have ABI_AlignStack respect the difference in current alignment
  between the root JIT function, which has a prolog, and
  ProtectFunction thunks, which do not.  This was causing many games
  to crash on start on OS X.  Since this might otherwise mean changing
  the stack pointer before every call...

- Have one prolog/epilog function rather than two (one of which
  definitely did not do what it was thought to do), and make it
  actually work like a normal one, so that the stack frame shows up
  properly in the debugger.  There should be no performance impact.
This commit is contained in:
comex
2013-09-19 21:10:32 -04:00
parent 95aac4ff68
commit d334a9bc23
5 changed files with 116 additions and 164 deletions

View File

@ -91,35 +91,27 @@ void *ThunkManager::ProtectFunction(void *function, int num_params)
PanicAlert("Trying to protect functions before the emu is started. Bad bad bad.");
const u8 *call_point = GetCodePtr();
// Make sure to align stack.
#ifdef _M_X64
#ifdef _WIN32
SUB(64, R(ESP), Imm8(0x28));
#else
SUB(64, R(ESP), Imm8(0x8));
#endif
// Make sure to align stack.
ABI_AlignStack(0, true);
CALL((void*)save_regs);
CALL((void*)function);
CALL((void*)load_regs);
#ifdef _WIN32
ADD(64, R(ESP), Imm8(0x28));
#else
ADD(64, R(ESP), Imm8(0x8));
#endif
ABI_RestoreStack(0, true);
RET();
#else
CALL((void*)save_regs);
// 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);
ABI_AlignStack(num_params * 4, true);
unsigned int alignedSize = ABI_GetAlignedFrameSize(num_params * 4);
for (int i = 0; i < num_params; i++) {
// ESP is changing, so we do not need i
PUSH(32, MDisp(ESP, alignedSize - 4));
PUSH(32, MDisp(ESP, alignedSize));
}
CALL(function);
ABI_RestoreStack(num_params * 4);
ABI_RestoreStack(num_params * 4, true);
CALL((void*)load_regs);
RET();
#endif