dolphin/Source/Core/Common/Src/ABI.cpp

196 lines
3.7 KiB
C++

#include "Common.h"
#include "x64Emitter.h"
#include "ABI.h"
using namespace Gen;
#ifdef _M_IX86 // All32
// Shared code between Win32 and Unix32
// ====================================
void ABI_CallFunctionC(void *func, u32 param1) {
PUSH(32, Imm32(param1));
CALL(func);
ADD(32, R(ESP), Imm8(4));
}
void ABI_CallFunctionCC(void *func, u32 param1, u32 param2) {
PUSH(32, Imm32(param2));
PUSH(32, Imm32(param1));
CALL(func);
ADD(32, R(ESP), Imm8(8));
}
// Pass a register as a paremeter.
void ABI_CallFunctionR(void *func, X64Reg reg1) {
PUSH(32, R(reg1));
CALL(func);
ADD(32, R(ESP), Imm8(4));
}
void ABI_CallFunctionRR(void *func, Gen::X64Reg reg1, Gen::X64Reg reg2)
{
PUSH(32, R(reg2));
PUSH(32, R(reg1));
CALL(func);
ADD(32, R(ESP), Imm8(8));
}
void ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2)
{
PUSH(32, arg1);
PUSH(32, Imm32(param2));
CALL(func);
ADD(32, R(ESP), Imm8(8));
}
void ABI_PushAllCalleeSavedRegsAndAdjustStack() {
PUSH(EBP);
PUSH(EBX);
PUSH(ESI);
PUSH(EDI);
}
void ABI_PopAllCalleeSavedRegsAndAdjustStack() {
POP(EDI);
POP(ESI);
POP(EBX);
POP(EBP);
}
#else
// Shared code between Win64 and Unix64
// ====================================
void ABI_CallFunctionC(void *func, u32 param1) {
MOV(32, R(ABI_PARAM1), Imm32(param1));
CALL(func);
}
void ABI_CallFunctionCC(void *func, u32 param1, u32 param2) {
MOV(32, R(ABI_PARAM1), Imm32(param1));
MOV(32, R(ABI_PARAM2), Imm32(param2));
CALL(func);
}
// Pass a register as a paremeter.
void ABI_CallFunctionR(void *func, X64Reg reg1) {
if (reg1 != ABI_PARAM1)
MOV(32, R(ABI_PARAM1), R(reg1));
CALL(func);
}
// Pass a register as a paremeter.
void ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2) {
if (reg1 != ABI_PARAM1)
MOV(32, R(ABI_PARAM1), R(reg1));
if (reg2 != ABI_PARAM2)
MOV(32, R(ABI_PARAM2), R(reg2));
CALL(func);
}
void ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2)
{
if (!arg1.IsSimpleReg(ABI_PARAM1))
MOV(32, R(ABI_PARAM1), arg1);
MOV(32, R(ABI_PARAM2), Imm32(param2));
CALL(func);
}
#ifdef _WIN32
// Win64 Specific Code
// ====================================
void ABI_PushAllCalleeSavedRegsAndAdjustStack() {
//we only want to do this once
PUSH(RBX);
PUSH(RSI);
PUSH(RDI);
PUSH(RBP);
PUSH(R12);
PUSH(R13);
PUSH(R14);
PUSH(R15);
//TODO: Also preserve XMM0-3?
SUB(64, R(RSP), Imm8(0x28));
}
void ABI_PopAllCalleeSavedRegsAndAdjustStack() {
ADD(64, R(RSP), Imm8(0x28));
POP(R15);
POP(R14);
POP(R13);
POP(R12);
POP(RBP);
POP(RDI);
POP(RSI);
POP(RBX);
}
// Win64 Specific Code
// ====================================
void ABI_PushAllCallerSavedRegsAndAdjustStack() {
PUSH(RCX);
PUSH(RDX);
PUSH(RSI);
PUSH(RDI);
PUSH(R8);
PUSH(R9);
PUSH(R10);
PUSH(R11);
//TODO: Also preserve XMM0-15?
SUB(64, R(RSP), Imm8(0x28));
}
void ABI_PopAllCallerSavedRegsAndAdjustStack() {
ADD(64, R(RSP), Imm8(0x28));
POP(R11);
POP(R10);
POP(R9);
POP(R8);
POP(RDI);
POP(RSI);
POP(RDX);
POP(RCX);
}
#else
// Unix64 Specific Code
// ====================================
void ABI_PushAllCalleeSavedRegsAndAdjustStack() {
PUSH(RBX);
PUSH(RBP);
PUSH(R12);
PUSH(R13);
PUSH(R14);
PUSH(R15);
PUSH(R15); //just to align stack. duped push/pop doesn't hurt.
}
void ABI_PopAllCalleeSavedRegsAndAdjustStack() {
POP(R15);
POP(R15);
POP(R14);
POP(R13);
POP(R12);
POP(RBP);
POP(RBX);
}
void ABI_PushAllCallerSavedRegsAndAdjustStack() {
INT3();
//not yet supported
}
void ABI_PopAllCallerSavedRegsAndAdjustStack() {
INT3();
//not yet supported
}
#endif
#endif