shader_jit_a64: Compact host executable memory (#230)

* common/aarch64: Allow generic code generator types

Use the templated `BasicCodeGenerator` type rather than the specialized
`CodeGenerator` type.
Allows `VectorCodeGenerator` to work with these functions.

* common/aarch64: Add `VectorCodeGenerator` to `CallFarFunction`

`VectorCodeGenerator` will always do far-calls since we cannot resolve any absolute addresses here.

* shader_jit_a64: Implement position-independent VectorCodeGenerator

Generates more position-independent assembly to allow for code to be
generated within a resizable vector before copying into executable
memory, allowing for more compact memory allocations and usage rather
than a statically defined worst-case for all-cases.

`VectorCodeGenerator` will need to generate position-independent code
rather than use absolute addresses. Assumes all far function calls in the
case of `VectorCodeGenerator` to use absolute addresses rather than
potentially use a relative `BL` branch after memory relocation.
This commit is contained in:
Wunk
2024-09-01 03:24:13 -07:00
committed by PabloMK7
parent 1ef86db597
commit bb1301b98e
4 changed files with 74 additions and 41 deletions

View File

@@ -78,7 +78,8 @@ inline ABIFrameInfo ABI_CalculateFrameSize(std::bitset<64> regs, std::size_t fra
return ABIFrameInfo{static_cast<u32>(total_size), static_cast<u32>(fprs_base_subtraction)};
}
inline void ABI_PushRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
template <typename Policy>
inline void ABI_PushRegisters(oaknut::BasicCodeGenerator<Policy>& code, std::bitset<64> regs,
std::size_t frame_size = 0) {
using namespace oaknut;
using namespace oaknut::util;
@@ -137,7 +138,8 @@ inline void ABI_PushRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
}
}
inline void ABI_PopRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
template <typename Policy>
inline void ABI_PopRegisters(oaknut::BasicCodeGenerator<Policy>& code, std::bitset<64> regs,
std::size_t frame_size = 0) {
using namespace oaknut;
using namespace oaknut::util;

View File

@@ -38,6 +38,16 @@ inline void CallFarFunction(oaknut::CodeGenerator& code, const T f) {
}
}
template <typename T>
inline void CallFarFunction(oaknut::VectorCodeGenerator& code, const T f) {
static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer.");
// X16(IP0) and X17(IP1) is the standard veneer register
// LR is also available as an intermediate register
// https://developer.arm.com/documentation/102374/0101/Procedure-Call-Standard
code.MOVP2R(oaknut::util::X16, reinterpret_cast<const void*>(f));
code.BLR(oaknut::util::X16);
}
} // namespace Common::A64
#endif // CITRA_ARCH(arm64)