diff --git a/src/backend_x64/a32_emit_x64.cpp b/src/backend_x64/a32_emit_x64.cpp index 422cff7f..80ca023c 100644 --- a/src/backend_x64/a32_emit_x64.cpp +++ b/src/backend_x64/a32_emit_x64.cpp @@ -148,58 +148,58 @@ void A32EmitX64::InvalidateCacheRanges(const boost::icl::interval_set& rang void A32EmitX64::GenMemoryAccessors() { code.align(); read_memory_8 = code.getCurr(); - ABI_PushCallerSaveRegistersAndAdjustStack(code); + ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryRead8).EmitCall(code); - ABI_PopCallerSaveRegistersAndAdjustStack(code); + ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); code.ret(); code.align(); read_memory_16 = code.getCurr(); - ABI_PushCallerSaveRegistersAndAdjustStack(code); + ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryRead16).EmitCall(code); - ABI_PopCallerSaveRegistersAndAdjustStack(code); + ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); code.ret(); code.align(); read_memory_32 = code.getCurr(); - ABI_PushCallerSaveRegistersAndAdjustStack(code); + ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryRead32).EmitCall(code); - ABI_PopCallerSaveRegistersAndAdjustStack(code); + ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); code.ret(); code.align(); read_memory_64 = code.getCurr(); - ABI_PushCallerSaveRegistersAndAdjustStack(code); + ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryRead64).EmitCall(code); - ABI_PopCallerSaveRegistersAndAdjustStack(code); + ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); code.ret(); code.align(); write_memory_8 = code.getCurr(); - ABI_PushCallerSaveRegistersAndAdjustStack(code); + ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryWrite8).EmitCall(code); - ABI_PopCallerSaveRegistersAndAdjustStack(code); + ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); code.ret(); code.align(); write_memory_16 = code.getCurr(); - ABI_PushCallerSaveRegistersAndAdjustStack(code); + ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryWrite16).EmitCall(code); - ABI_PopCallerSaveRegistersAndAdjustStack(code); + ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); code.ret(); code.align(); write_memory_32 = code.getCurr(); - ABI_PushCallerSaveRegistersAndAdjustStack(code); + ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryWrite32).EmitCall(code); - ABI_PopCallerSaveRegistersAndAdjustStack(code); + ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); code.ret(); code.align(); write_memory_64 = code.getCurr(); - ABI_PushCallerSaveRegistersAndAdjustStack(code); + ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); DEVIRT(config.callbacks, &A32::UserCallbacks::MemoryWrite64).EmitCall(code); - ABI_PopCallerSaveRegistersAndAdjustStack(code); + ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, ABI_RETURN); code.ret(); } diff --git a/src/backend_x64/abi.cpp b/src/backend_x64/abi.cpp index a3889afd..c249f664 100644 --- a/src/backend_x64/abi.cpp +++ b/src/backend_x64/abi.cpp @@ -126,4 +126,16 @@ void ABI_PopCallerSaveRegistersAndAdjustStack(Xbyak::CodeGenerator& code, size_t ABI_PopRegistersAndAdjustStack(code, frame_size, ABI_ALL_CALLER_SAVE); } +void ABI_PushCallerSaveRegistersAndAdjustStackExcept(Xbyak::CodeGenerator& code, HostLoc exception) { + std::vector regs; + std::remove_copy(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end(), std::back_inserter(regs), exception); + ABI_PushRegistersAndAdjustStack(code, 0, regs); +} + +void ABI_PopCallerSaveRegistersAndAdjustStackExcept(Xbyak::CodeGenerator& code, HostLoc exception) { + std::vector regs; + std::remove_copy(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end(), std::back_inserter(regs), exception); + ABI_PopRegistersAndAdjustStack(code, 0, regs); +} + } // namespace Dynarmic::BackendX64 diff --git a/src/backend_x64/abi.h b/src/backend_x64/abi.h index b097efcb..1b13271c 100644 --- a/src/backend_x64/abi.h +++ b/src/backend_x64/abi.h @@ -20,7 +20,8 @@ constexpr HostLoc ABI_PARAM2 = HostLoc::RDX; constexpr HostLoc ABI_PARAM3 = HostLoc::R8; constexpr HostLoc ABI_PARAM4 = HostLoc::R9; -constexpr std::array ABI_ALL_CALLER_SAVE = { +constexpr std::array ABI_ALL_CALLER_SAVE = { + HostLoc::RAX, HostLoc::RCX, HostLoc::RDX, HostLoc::R8, @@ -67,7 +68,8 @@ constexpr HostLoc ABI_PARAM2 = HostLoc::RSI; constexpr HostLoc ABI_PARAM3 = HostLoc::RDX; constexpr HostLoc ABI_PARAM4 = HostLoc::RCX; -constexpr std::array ABI_ALL_CALLER_SAVE = { +constexpr std::array ABI_ALL_CALLER_SAVE = { + HostLoc::RAX, HostLoc::RCX, HostLoc::RDX, HostLoc::RDI, @@ -107,11 +109,14 @@ constexpr size_t ABI_SHADOW_SPACE = 0; // bytes #endif -static_assert(ABI_ALL_CALLER_SAVE.size() + ABI_ALL_CALLEE_SAVE.size() == 30, "Invalid total number of registers"); +static_assert(ABI_ALL_CALLER_SAVE.size() + ABI_ALL_CALLEE_SAVE.size() == 31, "Invalid total number of registers"); void ABI_PushCalleeSaveRegistersAndAdjustStack(Xbyak::CodeGenerator& code, size_t frame_size = 0); void ABI_PopCalleeSaveRegistersAndAdjustStack(Xbyak::CodeGenerator& code, size_t frame_size = 0); void ABI_PushCallerSaveRegistersAndAdjustStack(Xbyak::CodeGenerator& code, size_t frame_size = 0); void ABI_PopCallerSaveRegistersAndAdjustStack(Xbyak::CodeGenerator& code, size_t frame_size = 0); +void ABI_PushCallerSaveRegistersAndAdjustStackExcept(Xbyak::CodeGenerator& code, HostLoc exception); +void ABI_PopCallerSaveRegistersAndAdjustStackExcept(Xbyak::CodeGenerator& code, HostLoc exception); + } // namespace Dynarmic::BackendX64 diff --git a/src/backend_x64/reg_alloc.cpp b/src/backend_x64/reg_alloc.cpp index ac891d47..10ef9b17 100644 --- a/src/backend_x64/reg_alloc.cpp +++ b/src/backend_x64/reg_alloc.cpp @@ -351,6 +351,7 @@ void RegAlloc::HostCall(IR::Inst* result_def, boost::optional arg0, b static const std::vector other_caller_save = [args_hostloc]() { std::vector ret(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end()); + ret.erase(std::find(ret.begin(), ret.end(), ABI_RETURN)); for (auto hostloc : args_hostloc) ret.erase(std::find(ret.begin(), ret.end(), hostloc));