diff --git a/src/backend_x64/abi.cpp b/src/backend_x64/abi.cpp index 21d4e161..99c9c968 100644 --- a/src/backend_x64/abi.cpp +++ b/src/backend_x64/abi.cpp @@ -55,15 +55,16 @@ static FrameInfo CalculateFrameInfo(size_t num_gprs, size_t num_xmms, size_t fra return frame_info; } -void ABI_PushCalleeSaveRegistersAndAdjustStack(Xbyak::CodeGenerator* code, size_t frame_size) { +template +void ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator* code, size_t frame_size, const RegisterArrayT& regs) { using namespace Xbyak::util; - const size_t num_gprs = std::count_if(ABI_ALL_CALLEE_SAVE.begin(), ABI_ALL_CALLEE_SAVE.end(), HostLocIsGPR); - const size_t num_xmms = std::count_if(ABI_ALL_CALLEE_SAVE.begin(), ABI_ALL_CALLEE_SAVE.end(), HostLocIsXMM); + const size_t num_gprs = std::count_if(regs.begin(), regs.end(), HostLocIsGPR); + const size_t num_xmms = std::count_if(regs.begin(), regs.end(), HostLocIsXMM); FrameInfo frame_info = CalculateFrameInfo(num_gprs, num_xmms, frame_size); - for (HostLoc gpr : ABI_ALL_CALLEE_SAVE) { + for (HostLoc gpr : regs) { if (HostLocIsGPR(gpr)) { code->push(HostLocToReg64(gpr)); } @@ -74,7 +75,7 @@ void ABI_PushCalleeSaveRegistersAndAdjustStack(Xbyak::CodeGenerator* code, size_ } size_t xmm_offset = frame_info.xmm_offset; - for (HostLoc xmm : ABI_ALL_CALLEE_SAVE) { + for (HostLoc xmm : regs) { if (HostLocIsXMM(xmm)) { code->movaps(code->xword[rsp + xmm_offset], HostLocToXmm(xmm)); xmm_offset += XMM_SIZE; @@ -82,16 +83,17 @@ void ABI_PushCalleeSaveRegistersAndAdjustStack(Xbyak::CodeGenerator* code, size_ } } -void ABI_PopCalleeSaveRegistersAndAdjustStack(Xbyak::CodeGenerator* code, size_t frame_size) { +template +void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator* code, size_t frame_size, const RegisterArrayT& regs) { using namespace Xbyak::util; - const size_t num_gprs = std::count_if(ABI_ALL_CALLEE_SAVE.begin(), ABI_ALL_CALLEE_SAVE.end(), HostLocIsGPR); - const size_t num_xmms = std::count_if(ABI_ALL_CALLEE_SAVE.begin(), ABI_ALL_CALLEE_SAVE.end(), HostLocIsXMM); + const size_t num_gprs = std::count_if(regs.begin(), regs.end(), HostLocIsGPR); + const size_t num_xmms = std::count_if(regs.begin(), regs.end(), HostLocIsXMM); FrameInfo frame_info = CalculateFrameInfo(num_gprs, num_xmms, frame_size); size_t xmm_offset = frame_info.xmm_offset; - for (HostLoc xmm : ABI_ALL_CALLEE_SAVE) { + for (HostLoc xmm : regs) { if (HostLocIsXMM(xmm)) { code->movaps(HostLocToXmm(xmm), code->xword[rsp + xmm_offset]); xmm_offset += XMM_SIZE; @@ -102,12 +104,28 @@ void ABI_PopCalleeSaveRegistersAndAdjustStack(Xbyak::CodeGenerator* code, size_t code->add(rsp, u32(frame_info.stack_subtraction)); } - for (HostLoc gpr : Common::Reverse(ABI_ALL_CALLEE_SAVE)) { + for (HostLoc gpr : Common::Reverse(regs)) { if (HostLocIsGPR(gpr)) { code->pop(HostLocToReg64(gpr)); } } } +void ABI_PushCalleeSaveRegistersAndAdjustStack(Xbyak::CodeGenerator* code, size_t frame_size) { + ABI_PushRegistersAndAdjustStack(code, frame_size, ABI_ALL_CALLEE_SAVE); +} + +void ABI_PopCalleeSaveRegistersAndAdjustStack(Xbyak::CodeGenerator* code, size_t frame_size) { + ABI_PopRegistersAndAdjustStack(code, frame_size, ABI_ALL_CALLEE_SAVE); +} + +void ABI_PushCallerSaveRegistersAndAdjustStack(Xbyak::CodeGenerator* code, size_t frame_size) { + ABI_PushRegistersAndAdjustStack(code, frame_size, ABI_ALL_CALLER_SAVE); +} + +void ABI_PopCallerSaveRegistersAndAdjustStack(Xbyak::CodeGenerator* code, size_t frame_size) { + ABI_PopRegistersAndAdjustStack(code, frame_size, ABI_ALL_CALLER_SAVE); +} + } // namespace BackendX64 } // namespace Dynarmic diff --git a/src/backend_x64/abi.h b/src/backend_x64/abi.h index 89912dff..09c079f5 100644 --- a/src/backend_x64/abi.h +++ b/src/backend_x64/abi.h @@ -21,8 +21,7 @@ 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 = { - HostLoc::RAX, +constexpr std::array ABI_ALL_CALLER_SAVE = { HostLoc::RCX, HostLoc::RDX, HostLoc::R8, @@ -69,8 +68,7 @@ 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 = { - HostLoc::RAX, +constexpr std::array ABI_ALL_CALLER_SAVE = { HostLoc::RCX, HostLoc::RDX, HostLoc::RDI, @@ -110,10 +108,12 @@ constexpr size_t ABI_SHADOW_SPACE = 0; // bytes #endif -static_assert(ABI_ALL_CALLER_SAVE.size() + ABI_ALL_CALLEE_SAVE.size() == 31, "Invalid total number of registers"); +static_assert(ABI_ALL_CALLER_SAVE.size() + ABI_ALL_CALLEE_SAVE.size() == 30, "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); } // namespace BackendX64 } // namespace Dynarmic diff --git a/src/backend_x64/reg_alloc.cpp b/src/backend_x64/reg_alloc.cpp index f7fed276..a56de6ca 100644 --- a/src/backend_x64/reg_alloc.cpp +++ b/src/backend_x64/reg_alloc.cpp @@ -278,10 +278,10 @@ void RegAlloc::HostCall(IR::Inst* result_def, IR::Value arg0_use, IR::Value arg1 constexpr std::array args_hostloc = { ABI_PARAM1, ABI_PARAM2, ABI_PARAM3, ABI_PARAM4 }; const std::array args = {&arg0_use, &arg1_use, &arg2_use, &arg3_use}; - const static std::vector other_caller_save = [](){ + const static std::vector other_caller_save = [args_hostloc](){ std::vector ret(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end()); - for (auto hostloc : {ABI_RETURN, ABI_PARAM1, ABI_PARAM2, ABI_PARAM3, ABI_PARAM4}) + for (auto hostloc : args_hostloc) ret.erase(std::find(ret.begin(), ret.end(), hostloc)); return ret;