From 2645f5171340f2fc85a729fa4b28c5a12ebb8a97 Mon Sep 17 00:00:00 2001
From: SachinVin <sachinvinayak2000@gmail.com>
Date: Sat, 3 Aug 2019 10:27:02 +0530
Subject: [PATCH] backend/a64: Port ABI functions

---
 src/backend/A64/abi.cpp |  87 ++++++++++++++++++++++++++++++++
 src/backend/A64/abi.h   | 109 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 196 insertions(+)
 create mode 100644 src/backend/A64/abi.cpp
 create mode 100644 src/backend/A64/abi.h

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 <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
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 <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