diff --git a/Source/Core/Common/x64ABI.cpp b/Source/Core/Common/x64ABI.cpp index c86c8f8b24..45465619bd 100644 --- a/Source/Core/Common/x64ABI.cpp +++ b/Source/Core/Common/x64ABI.cpp @@ -353,20 +353,7 @@ void XEmitter::ABI_CallFunctionR(void *func, X64Reg reg1) void XEmitter::ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2, bool noProlog) { ABI_AlignStack(0, noProlog); - if (reg2 != ABI_PARAM1) - { - if (reg1 != ABI_PARAM1) - MOV(64, R(ABI_PARAM1), R(reg1)); - if (reg2 != ABI_PARAM2) - MOV(64, R(ABI_PARAM2), R(reg2)); - } - else - { - if (reg2 != ABI_PARAM2) - MOV(64, R(ABI_PARAM2), R(reg2)); - if (reg1 != ABI_PARAM1) - MOV(64, R(ABI_PARAM1), R(reg1)); - } + MOVTwo(64, ABI_PARAM1, reg1, ABI_PARAM2, reg2, ABI_PARAM3); u64 distance = u64(func) - (u64(code) + 5); if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) @@ -382,6 +369,30 @@ void XEmitter::ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2, bool noP ABI_RestoreStack(0, noProlog); } +void XEmitter::MOVTwo(int bits, Gen::X64Reg dst1, Gen::X64Reg src1, Gen::X64Reg dst2, Gen::X64Reg src2, X64Reg temp) +{ + if (dst1 == src2 && dst2 == src1) + { + // need a temporary + MOV(bits, R(temp), R(src1)); + src1 = temp; + } + if (src2 != dst1) + { + if (dst1 != src1) + MOV(bits, R(dst1), R(src1)); + if (dst2 != src2) + MOV(bits, R(dst2), R(src2)); + } + else + { + if (dst2 != src2) + MOV(bits, R(dst2), R(src2)); + if (dst1 != src1) + MOV(bits, R(dst1), R(src1)); + } +} + void XEmitter::ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2) { ABI_AlignStack(0); diff --git a/Source/Core/Common/x64Emitter.h b/Source/Core/Common/x64Emitter.h index 558af41767..d6f0699e84 100644 --- a/Source/Core/Common/x64Emitter.h +++ b/Source/Core/Common/x64Emitter.h @@ -753,6 +753,9 @@ public: void ABI_CallFunctionR(void *func, X64Reg reg1); void ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2, bool noProlog = false); + // Helper method for the above, or can be used separately. + void MOVTwo(int bits, Gen::X64Reg dst1, Gen::X64Reg src1, Gen::X64Reg dst2, Gen::X64Reg src2, Gen::X64Reg temp); + // A function that doesn't have any control over what it will do to regs, // such as the dispatcher, should be surrounded by these. void ABI_PushAllCalleeSavedRegsAndAdjustStack(); diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp b/Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp index 1fe88f9e28..a51aac6480 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp @@ -115,22 +115,7 @@ const u8 *TrampolineCache::GetWriteTrampoline(const InstructionInfo &info, u32 r // PC is used by memory watchpoints (if enabled) or to print accurate PC locations in debug logs MOV(32, PPCSTATE(pc), Imm32(pc)); - if (dataReg == ABI_PARAM2) - PanicAlert("Incorrect use of SafeWriteRegToReg"); - if (addrReg != ABI_PARAM1) - { - if (ABI_PARAM1 != dataReg) - MOV(64, R(ABI_PARAM1), R((X64Reg)dataReg)); - if (ABI_PARAM2 != addrReg) - MOV(64, R(ABI_PARAM2), R((X64Reg)addrReg)); - } - else - { - if (ABI_PARAM2 != addrReg) - MOV(64, R(ABI_PARAM2), R((X64Reg)addrReg)); - if (ABI_PARAM1 != dataReg) - MOV(64, R(ABI_PARAM1), R((X64Reg)dataReg)); - } + MOVTwo(64, ABI_PARAM1, dataReg, ABI_PARAM2, addrReg, ABI_PARAM3); if (info.displacement) {