mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-25 15:19:42 -06:00
Factor code from ABI_CallFunctionRR and GetWriteTrampoline into a helper, and fix a special case.
The special case is where the registers are actually to be swapped (i.e. func(ABI_PARAM2, ABI_PARAM1); this was previously impossible but would be ugly not to handle anyway.
This commit is contained in:
@ -353,20 +353,7 @@ void XEmitter::ABI_CallFunctionR(void *func, X64Reg reg1)
|
|||||||
void XEmitter::ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2, bool noProlog)
|
void XEmitter::ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2, bool noProlog)
|
||||||
{
|
{
|
||||||
ABI_AlignStack(0, noProlog);
|
ABI_AlignStack(0, noProlog);
|
||||||
if (reg2 != ABI_PARAM1)
|
MOVTwo(64, ABI_PARAM1, reg1, ABI_PARAM2, reg2, ABI_PARAM3);
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
u64 distance = u64(func) - (u64(code) + 5);
|
u64 distance = u64(func) - (u64(code) + 5);
|
||||||
if (distance >= 0x0000000080000000ULL &&
|
if (distance >= 0x0000000080000000ULL &&
|
||||||
distance < 0xFFFFFFFF80000000ULL)
|
distance < 0xFFFFFFFF80000000ULL)
|
||||||
@ -382,6 +369,30 @@ void XEmitter::ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2, bool noP
|
|||||||
ABI_RestoreStack(0, noProlog);
|
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)
|
void XEmitter::ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2)
|
||||||
{
|
{
|
||||||
ABI_AlignStack(0);
|
ABI_AlignStack(0);
|
||||||
|
@ -753,6 +753,9 @@ public:
|
|||||||
void ABI_CallFunctionR(void *func, X64Reg reg1);
|
void ABI_CallFunctionR(void *func, X64Reg reg1);
|
||||||
void ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2, bool noProlog = false);
|
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,
|
// A function that doesn't have any control over what it will do to regs,
|
||||||
// such as the dispatcher, should be surrounded by these.
|
// such as the dispatcher, should be surrounded by these.
|
||||||
void ABI_PushAllCalleeSavedRegsAndAdjustStack();
|
void ABI_PushAllCalleeSavedRegsAndAdjustStack();
|
||||||
|
@ -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
|
// PC is used by memory watchpoints (if enabled) or to print accurate PC locations in debug logs
|
||||||
MOV(32, PPCSTATE(pc), Imm32(pc));
|
MOV(32, PPCSTATE(pc), Imm32(pc));
|
||||||
|
|
||||||
if (dataReg == ABI_PARAM2)
|
MOVTwo(64, ABI_PARAM1, dataReg, ABI_PARAM2, addrReg, ABI_PARAM3);
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.displacement)
|
if (info.displacement)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user