diff --git a/Source/Core/Common/x64ABI.cpp b/Source/Core/Common/x64ABI.cpp index 6f423eaa6a..0116212485 100644 --- a/Source/Core/Common/x64ABI.cpp +++ b/Source/Core/Common/x64ABI.cpp @@ -176,6 +176,14 @@ void XEmitter::ABI_CallFunctionCC(void *func, u32 param1, u32 param2) { ABI_RestoreStack(2 * 4); } +void XEmitter::ABI_CallFunctionCP(void *func, u32 param1, void *param2) { + ABI_AlignStack(2 * 4); + PUSH(32, Imm32((u32)param2)); + PUSH(32, Imm32(param1)); + CALL(func); + ABI_RestoreStack(2 * 4); +} + void XEmitter::ABI_CallFunctionCCC(void *func, u32 param1, u32 param2, u32 param3) { ABI_AlignStack(3 * 4); PUSH(32, Imm32(param3)); @@ -204,6 +212,14 @@ void XEmitter::ABI_CallFunctionCCCP(void *func, u32 param1, u32 param2,u32 param ABI_RestoreStack(4 * 4); } +void XEmitter::ABI_CallFunctionPC(void *func, void *param1, u32 param2) { + ABI_AlignStack(3 * 4); + PUSH(32, Imm32(param2)); + PUSH(32, Imm32((u32)param1)); + CALL(func); + ABI_RestoreStack(3 * 4); +} + void XEmitter::ABI_CallFunctionPPC(void *func, void *param1, void *param2,u32 param3) { ABI_AlignStack(3 * 4); PUSH(32, Imm32(param3)); @@ -344,6 +360,22 @@ void XEmitter::ABI_CallFunctionCC(void *func, u32 param1, u32 param2) { ABI_RestoreStack(0); } +void XEmitter::ABI_CallFunctionCP(void *func, u32 param1, void *param2) { + ABI_AlignStack(0); + MOV(32, R(ABI_PARAM1), Imm32(param1)); + MOV(64, R(ABI_PARAM2), Imm64((u64)param2)); + u64 distance = u64(func) - (u64(code) + 5); + if (distance >= 0x0000000080000000ULL + && distance < 0xFFFFFFFF80000000ULL) { + // Far call + MOV(64, R(RAX), Imm64((u64)func)); + CALLptr(R(RAX)); + } else { + CALL(func); + } + ABI_RestoreStack(0); +} + void XEmitter::ABI_CallFunctionCCC(void *func, u32 param1, u32 param2, u32 param3) { ABI_AlignStack(0); MOV(32, R(ABI_PARAM1), Imm32(param1)); @@ -396,6 +428,22 @@ void XEmitter::ABI_CallFunctionCCCP(void *func, u32 param1, u32 param2, u32 para ABI_RestoreStack(0); } +void XEmitter::ABI_CallFunctionPC(void *func, void *param1, u32 param2) { + ABI_AlignStack(0); + MOV(64, R(ABI_PARAM1), Imm64((u64)param1)); + MOV(32, R(ABI_PARAM2), Imm32(param2)); + u64 distance = u64(func) - (u64(code) + 5); + if (distance >= 0x0000000080000000ULL + && distance < 0xFFFFFFFF80000000ULL) { + // Far call + MOV(64, R(RAX), Imm64((u64)func)); + CALLptr(R(RAX)); + } else { + CALL(func); + } + ABI_RestoreStack(0); +} + void XEmitter::ABI_CallFunctionPPC(void *func, void *param1, void *param2, u32 param3) { ABI_AlignStack(0); MOV(64, R(ABI_PARAM1), Imm64((u64)param1)); diff --git a/Source/Core/Common/x64Emitter.h b/Source/Core/Common/x64Emitter.h index ced0456377..5b30833b21 100644 --- a/Source/Core/Common/x64Emitter.h +++ b/Source/Core/Common/x64Emitter.h @@ -671,9 +671,11 @@ public: // These will destroy the 1 or 2 first "parameter regs". void ABI_CallFunctionC(void *func, u32 param1); void ABI_CallFunctionCC(void *func, u32 param1, u32 param2); + void ABI_CallFunctionCP(void *func, u32 param1, void *param2); void ABI_CallFunctionCCC(void *func, u32 param1, u32 param2, u32 param3); void ABI_CallFunctionCCP(void *func, u32 param1, u32 param2, void *param3); void ABI_CallFunctionCCCP(void *func, u32 param1, u32 param2,u32 param3, void *param4); + void ABI_CallFunctionPC(void *func, void *param1, u32 param2); void ABI_CallFunctionPPC(void *func, void *param1, void *param2,u32 param3); void ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2); void ABI_CallFunctionA(void *func, const Gen::OpArg &arg1);