From 4e43ecb28d4eaea565d3912f277159c84fa463c9 Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Sun, 22 Sep 2013 14:29:35 -0400 Subject: [PATCH] Fix crashes in Single Core mode on Dolphin Win64. Cherry-picked from 6209067daa51. --- Source/Core/Common/Src/x64ABI.cpp | 18 ++++++------- Source/Core/Common/Src/x64Emitter.h | 2 +- .../Src/PowerPC/JitCommon/JitAsmCommon.cpp | 26 +++++++++---------- .../Core/Src/PowerPC/JitCommon/Jit_Util.cpp | 8 +++--- .../Core/Src/PowerPC/JitCommon/Jit_Util.h | 2 +- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Source/Core/Common/Src/x64ABI.cpp b/Source/Core/Common/Src/x64ABI.cpp index b5726947fc..1b4fa0b5ff 100644 --- a/Source/Core/Common/Src/x64ABI.cpp +++ b/Source/Core/Common/Src/x64ABI.cpp @@ -15,9 +15,9 @@ unsigned int XEmitter::ABI_GetAlignedFrameSize(unsigned int frameSize, bool noPr // the stack pointer is 4/8 bytes less than a multiple of 16; however, the // function prolog immediately subtracts an appropriate amount to align // it, so no alignment is required around a call. - // In the functions generated by ThunkManager::ProtectFunction, we add the - // necessary subtraction (and 0x20 bytes shadow space for Win64) into this - // rather than having a separate prolog. + // In the functions generated by ThunkManager::ProtectFunction and some + // others, we add the necessary subtraction (and 0x20 bytes shadow space + // for Win64) into this rather than having a separate prolog. // On Windows 32-bit, the required alignment is only 4 bytes, so we just // ensure that the frame size isn't misaligned. #ifdef _M_X64 @@ -142,13 +142,13 @@ void XEmitter::ABI_CallFunctionR(void *func, X64Reg reg1) { } // Pass two registers as parameters. -void XEmitter::ABI_CallFunctionRR(void *func, Gen::X64Reg reg1, Gen::X64Reg reg2) +void XEmitter::ABI_CallFunctionRR(void *func, Gen::X64Reg reg1, Gen::X64Reg reg2, bool noProlog) { - ABI_AlignStack(2 * 4); + ABI_AlignStack(2 * 4, noProlog); PUSH(32, R(reg2)); PUSH(32, R(reg1)); CALL(func); - ABI_RestoreStack(2 * 4); + ABI_RestoreStack(2 * 4, noProlog); } void XEmitter::ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2) @@ -351,8 +351,8 @@ void XEmitter::ABI_CallFunctionR(void *func, X64Reg reg1) { } // Pass two registers as parameters. -void XEmitter::ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2) { - ABI_AlignStack(0); +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)); @@ -373,7 +373,7 @@ void XEmitter::ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2) { } else { CALL(func); } - ABI_RestoreStack(0); + ABI_RestoreStack(0, noProlog); } void XEmitter::ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2) diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h index c42c955ec4..27a735ab90 100644 --- a/Source/Core/Common/Src/x64Emitter.h +++ b/Source/Core/Common/Src/x64Emitter.h @@ -639,7 +639,7 @@ public: // Pass a register as a parameter. void ABI_CallFunctionR(void *func, Gen::X64Reg reg1); - void ABI_CallFunctionRR(void *func, Gen::X64Reg reg1, Gen::X64Reg reg2); + void ABI_CallFunctionRR(void *func, Gen::X64Reg reg1, Gen::X64Reg reg2, bool noProlog = false); // A function that doesn't have any control over what it will do to regs, // such as the dispatcher, should be surrounded by these. diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp index 5187ef1478..d80b0bb3f8 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp @@ -167,7 +167,7 @@ void CommonAsmRoutines::GenQuantizedStores() { MOV(64, MComplex(RBX, RCX, SCALE_1, 0), R(RAX)); FixupBranch skip_complex = J(); SetJumpTarget(too_complex); - ABI_CallFunctionRR(thunks.ProtectFunction((void *)&WriteDual32, 2), RAX, RCX); + ABI_CallFunctionRR(thunks.ProtectFunction((void *)&WriteDual32, 2), RAX, RCX, /* noProlog = */ true); SetJumpTarget(skip_complex); RET(); #else @@ -184,10 +184,10 @@ void CommonAsmRoutines::GenQuantizedStores() { FixupBranch arg2 = J(); SetJumpTarget(argh); MOV(32, R(EAX), M(((char*)&psTemp))); - ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U32, 2), EAX, ECX); + ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U32, 2), EAX, ECX, /* noProlog = */ true); MOV(32, R(EAX), M(((char*)&psTemp)+4)); ADD(32, R(ECX), Imm32(4)); - ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U32, 2), EAX, ECX); + ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U32, 2), EAX, ECX, /* noProlog = */ true); SetJumpTarget(arg2); RET(); #endif @@ -206,7 +206,7 @@ void CommonAsmRoutines::GenQuantizedStores() { PACKSSDW(XMM0, R(XMM0)); PACKUSWB(XMM0, R(XMM0)); MOVD_xmm(R(EAX), XMM0); - SafeWriteRegToReg(AX, ECX, 16, 0, false); + SafeWriteRegToReg(AX, ECX, 16, 0, false, true); RET(); @@ -225,7 +225,7 @@ void CommonAsmRoutines::GenQuantizedStores() { PACKSSWB(XMM0, R(XMM0)); MOVD_xmm(R(EAX), XMM0); - SafeWriteRegToReg(AX, ECX, 16, 0, false); + SafeWriteRegToReg(AX, ECX, 16, 0, false, true); RET(); @@ -251,7 +251,7 @@ void CommonAsmRoutines::GenQuantizedStores() { MOV(16, R(AX), M((char*)psTemp + 4)); BSWAP(32, EAX); - SafeWriteRegToReg(EAX, ECX, 32, 0, false); + SafeWriteRegToReg(EAX, ECX, 32, 0, false, true); RET(); @@ -271,7 +271,7 @@ void CommonAsmRoutines::GenQuantizedStores() { MOVD_xmm(R(EAX), XMM0); BSWAP(32, EAX); ROL(32, R(EAX), Imm8(16)); - SafeWriteRegToReg(EAX, ECX, 32, 0, false); + SafeWriteRegToReg(EAX, ECX, 32, 0, false, true); RET(); @@ -303,11 +303,11 @@ void CommonAsmRoutines::GenQuantizedSingleStores() { // TODO: SafeWriteFloat MOVSS(M(&psTemp[0]), XMM0); MOV(32, R(EAX), M(&psTemp[0])); - SafeWriteRegToReg(EAX, ECX, 32, 0, false); + SafeWriteRegToReg(EAX, ECX, 32, 0, false, true); } else { MOVSS(M(&psTemp[0]), XMM0); MOV(32, R(EAX), M(&psTemp[0])); - SafeWriteRegToReg(EAX, ECX, 32, 0, true); + SafeWriteRegToReg(EAX, ECX, 32, 0, true, true); }*/ const u8* storeSingleU8 = AlignCode4(); // Used by MKWii @@ -318,7 +318,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() { MAXSS(XMM0, R(XMM1)); MINSS(XMM0, M((void *)&m_255)); CVTTSS2SI(EAX, R(XMM0)); - SafeWriteRegToReg(AL, ECX, 8, 0, true); + SafeWriteRegToReg(AL, ECX, 8, 0, true, true); RET(); const u8* storeSingleS8 = AlignCode4(); @@ -328,7 +328,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() { MAXSS(XMM0, M((void *)&m_m128)); MINSS(XMM0, M((void *)&m_127)); CVTTSS2SI(EAX, R(XMM0)); - SafeWriteRegToReg(AL, ECX, 8, 0, true); + SafeWriteRegToReg(AL, ECX, 8, 0, true, true); RET(); const u8* storeSingleU16 = AlignCode4(); // Used by MKWii @@ -339,7 +339,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() { MAXSS(XMM0, R(XMM1)); MINSS(XMM0, M((void *)&m_65535)); CVTTSS2SI(EAX, R(XMM0)); - SafeWriteRegToReg(EAX, ECX, 16, 0, true); + SafeWriteRegToReg(EAX, ECX, 16, 0, true, true); RET(); const u8* storeSingleS16 = AlignCode4(); @@ -349,7 +349,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() { MAXSS(XMM0, M((void *)&m_m32768)); MINSS(XMM0, M((void *)&m_32767)); CVTTSS2SI(EAX, R(XMM0)); - SafeWriteRegToReg(EAX, ECX, 16, 0, true); + SafeWriteRegToReg(EAX, ECX, 16, 0, true, true); RET(); singleStoreQuantized = reinterpret_cast(const_cast(AlignCode16())); diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp index 18c8044385..637dff171b 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp @@ -223,7 +223,7 @@ void EmuCodeBlock::UnsafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int ac } // Destroys both arg registers -void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int accessSize, s32 offset, bool swap) +void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int accessSize, s32 offset, bool swap, bool noProlog) { if (offset) ADD(32, R(reg_addr), Imm32((u32)offset)); @@ -247,9 +247,9 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int acce MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write switch (accessSize) { - case 32: ABI_CallFunctionRR(thunks.ProtectFunction(swap ? ((void *)&Memory::Write_U32) : ((void *)&Memory::Write_U32_Swap), 2), reg_value, reg_addr); break; - case 16: ABI_CallFunctionRR(thunks.ProtectFunction(swap ? ((void *)&Memory::Write_U16) : ((void *)&Memory::Write_U16_Swap), 2), reg_value, reg_addr); break; - case 8: ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U8, 2), reg_value, reg_addr); break; + case 32: ABI_CallFunctionRR(thunks.ProtectFunction(swap ? ((void *)&Memory::Write_U32) : ((void *)&Memory::Write_U32_Swap), 2), reg_value, reg_addr, noProlog); break; + case 16: ABI_CallFunctionRR(thunks.ProtectFunction(swap ? ((void *)&Memory::Write_U16) : ((void *)&Memory::Write_U16_Swap), 2), reg_value, reg_addr, noProlog); break; + case 8: ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U8, 2), reg_value, reg_addr, noProlog); break; } FixupBranch exit = J(); SetJumpTarget(fast); diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.h b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.h index 7708ab8598..57dce19790 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.h @@ -16,7 +16,7 @@ public: void UnsafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset = 0, bool swap = true); void UnsafeLoadToEAX(const Gen::OpArg & opAddress, int accessSize, s32 offset, bool signExtend); void SafeLoadToEAX(const Gen::OpArg & opAddress, int accessSize, s32 offset, bool signExtend); - void SafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset, bool swap = true); + void SafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset, bool swap = true, bool noProlog = false); // Trashes both inputs and EAX. void SafeWriteFloatToReg(Gen::X64Reg xmm_value, Gen::X64Reg reg_addr);