diff --git a/src/backend/A64/abi.cpp b/src/backend/A64/abi.cpp new file mode 100644 index 00000000..24fc1cb8 --- /dev/null +++ b/src/backend/A64/abi.cpp @@ -0,0 +1,87 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// 20th Sep 2018: This code was modified for Dynarmic. + +#include +#include + +#include "backend/A64/abi.h" +#include "common/common_types.h" +#include "common/math_util.h" +#include "common/iterator_util.h" + +namespace Dynarmic::BackendA64 { + +template +void ABI_PushRegistersAndAdjustStack(BlockOfCode& code, const RegisterArrayT& regs) { + u32 gprs = 0 , fprs = 0; + + for (HostLoc reg : regs) { + if (HostLocIsGPR(reg)) { + gprs |= 0x1 << static_cast(DecodeReg(HostLocToReg64(reg))); + } else if (HostLocIsFPR(reg)) { + fprs |= 0x1 << static_cast(DecodeReg(HostLocToFpr(reg))); + } + } + + code.fp_emitter.ABI_PushRegisters(fprs); + code.ABI_PushRegisters(gprs); +} + +template +void ABI_PopRegistersAndAdjustStack(BlockOfCode& code, const RegisterArrayT& regs) { + u32 gprs = 0, fprs = 0; + + for (HostLoc reg : regs) { + if (HostLocIsGPR(reg)) { + gprs |= 0x1 << static_cast(DecodeReg(HostLocToReg64(reg))); + } else if (HostLocIsFPR(reg)) { + fprs |= 0x1 << static_cast(DecodeReg(HostLocToFpr(reg))); + } + } + + code.ABI_PopRegisters(gprs); + code.fp_emitter.ABI_PopRegisters(fprs); +} + +void ABI_PushCalleeSaveRegistersAndAdjustStack(BlockOfCode& code) { + ABI_PushRegistersAndAdjustStack(code, ABI_ALL_CALLEE_SAVE); +} + +void ABI_PopCalleeSaveRegistersAndAdjustStack(BlockOfCode& code) { + ABI_PopRegistersAndAdjustStack(code, ABI_ALL_CALLEE_SAVE); +} + +void ABI_PushCallerSaveRegistersAndAdjustStack(BlockOfCode& code) { + ABI_PushRegistersAndAdjustStack(code, ABI_ALL_CALLER_SAVE); +} + +void ABI_PopCallerSaveRegistersAndAdjustStack(BlockOfCode& code) { + ABI_PopRegistersAndAdjustStack(code, ABI_ALL_CALLER_SAVE); +} + +void ABI_PushCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& 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, regs); +} + +void ABI_PopCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& 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, regs); +} + +} // namespace Dynarmic::BackendX64 diff --git a/src/backend/A64/abi.h b/src/backend/A64/abi.h new file mode 100644 index 00000000..141291d6 --- /dev/null +++ b/src/backend/A64/abi.h @@ -0,0 +1,109 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ +#pragma once + +#include + +#include "backend/A64/block_of_code.h" +#include "backend/A64/hostloc.h" + +namespace Dynarmic::BackendA64 { + +constexpr HostLoc ABI_RETURN = HostLoc::X0; + +constexpr HostLoc ABI_PARAM1 = HostLoc::X0; +constexpr HostLoc ABI_PARAM2 = HostLoc::X1; +constexpr HostLoc ABI_PARAM3 = HostLoc::X2; +constexpr HostLoc ABI_PARAM4 = HostLoc::X3; +constexpr HostLoc ABI_PARAM5 = HostLoc::X4; +constexpr HostLoc ABI_PARAM6 = HostLoc::X5; +constexpr HostLoc ABI_PARAM7 = HostLoc::X6; +constexpr HostLoc ABI_PARAM8 = HostLoc::X7; + +constexpr std::array ABI_ALL_CALLER_SAVE = { + HostLoc::X0, + HostLoc::X1, + HostLoc::X2, + HostLoc::X3, + HostLoc::X4, + HostLoc::X5, + HostLoc::X6, + HostLoc::X7, + HostLoc::X8, + HostLoc::X9, + HostLoc::X10, + HostLoc::X11, + HostLoc::X12, + HostLoc::X13, + HostLoc::X14, + HostLoc::X15, + HostLoc::X16, + HostLoc::X17, + HostLoc::X18, + + HostLoc::Q0, + HostLoc::Q1, + HostLoc::Q2, + HostLoc::Q3, + HostLoc::Q4, + HostLoc::Q5, + HostLoc::Q6, + HostLoc::Q7, + HostLoc::Q8, + HostLoc::Q9, + HostLoc::Q10, + HostLoc::Q11, + HostLoc::Q12, + HostLoc::Q13, + HostLoc::Q14, + HostLoc::Q15, + HostLoc::Q16, +}; + +constexpr std::array ABI_ALL_CALLEE_SAVE = { + HostLoc::X19, + HostLoc::X20, + HostLoc::X21, + HostLoc::X22, + HostLoc::X23, + HostLoc::X24, + HostLoc::X25, + HostLoc::X26, + HostLoc::X27, + HostLoc::X28, + HostLoc::X29, + HostLoc::X30, + + HostLoc::Q17, + HostLoc::Q18, + HostLoc::Q19, + HostLoc::Q20, + HostLoc::Q21, + HostLoc::Q22, + HostLoc::Q23, + HostLoc::Q24, + HostLoc::Q25, + HostLoc::Q26, + HostLoc::Q27, + HostLoc::Q28, + HostLoc::Q29, + HostLoc::Q30, + HostLoc::Q31, +}; + +constexpr size_t ABI_SHADOW_SPACE = 0; // bytes + +static_assert(ABI_ALL_CALLER_SAVE.size() + ABI_ALL_CALLEE_SAVE.size() == 63, "Invalid total number of registers"); + +void ABI_PushCalleeSaveRegistersAndAdjustStack(BlockOfCode& code); +void ABI_PopCalleeSaveRegistersAndAdjustStack(BlockOfCode& code); +void ABI_PushCallerSaveRegistersAndAdjustStack(BlockOfCode& code); +void ABI_PopCallerSaveRegistersAndAdjustStack(BlockOfCode& code); + +void ABI_PushCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& code, HostLoc exception); +void ABI_PopCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& code, HostLoc exception); + +} // namespace Dynarmic::BackendX64