backend/a64: Port ABI functions

This commit is contained in:
SachinVin 2019-08-03 10:27:02 +05:30
parent ab07872025
commit a37f9c4cc6
2 changed files with 196 additions and 0 deletions

87
src/backend/A64/abi.cpp Normal file
View File

@ -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 <algorithm>
#include <vector>
#include "backend/A64/abi.h"
#include "common/common_types.h"
#include "common/math_util.h"
#include "common/iterator_util.h"
namespace Dynarmic::BackendA64 {
template<typename RegisterArrayT>
void ABI_PushRegistersAndAdjustStack(BlockOfCode& code, const RegisterArrayT& regs) {
u32 gprs = 0 , fprs = 0;
for (HostLoc reg : regs) {
if (HostLocIsGPR(reg)) {
gprs |= 0x1 << static_cast<u32>(DecodeReg(HostLocToReg64(reg)));
} else if (HostLocIsFPR(reg)) {
fprs |= 0x1 << static_cast<u32>(DecodeReg(HostLocToFpr(reg)));
}
}
code.fp_emitter.ABI_PushRegisters(fprs);
code.ABI_PushRegisters(gprs);
}
template<typename RegisterArrayT>
void ABI_PopRegistersAndAdjustStack(BlockOfCode& code, const RegisterArrayT& regs) {
u32 gprs = 0, fprs = 0;
for (HostLoc reg : regs) {
if (HostLocIsGPR(reg)) {
gprs |= 0x1 << static_cast<u32>(DecodeReg(HostLocToReg64(reg)));
} else if (HostLocIsFPR(reg)) {
fprs |= 0x1 << static_cast<u32>(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<HostLoc> 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<HostLoc> 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

109
src/backend/A64/abi.h Normal file
View File

@ -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 <array>
#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<HostLoc, 36> 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<HostLoc, 27> 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