From c9b2c36ef7ad4e684ee69f0e2fa0924402cfa4f1 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 19 Aug 2020 12:52:37 -0700 Subject: [PATCH] Removes usage of vixl's MacroAssembler This gives us two more volatile registers to play with --- .../Source/Interface/Core/JIT/Arm64/JIT.cpp | 103 +++++++++++++++--- .../Interface/Core/JIT/Arm64/JITClass.h | 20 ++-- 2 files changed, 101 insertions(+), 22 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp index 6f59aa9d0..fb23c86bd 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp @@ -281,7 +281,7 @@ bool JITCore::HandleSIGBUS(int Signal, void *info, void *ucontext) { } JITCore::JITCore(FEXCore::Context::Context *ctx, FEXCore::Core::InternalThreadState *Thread, CodeBuffer Buffer) - : vixl::aarch64::MacroAssembler(Buffer.Ptr, Buffer.Size, vixl::aarch64::PositionDependentCode) + : vixl::aarch64::Assembler(Buffer.Ptr, Buffer.Size, vixl::aarch64::PositionDependentCode) , CTX {ctx} , State {Thread} , InitialCodeBuffer {Buffer} @@ -593,7 +593,89 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const return reinterpret_cast(Entry); } +void JITCore::PushCalleeSavedRegisters() { + // We need to save pairs of registers + // We save r19-r30 + MemOperand PairOffset(sp, -16, PreIndex); + const std::array, 6> CalleeSaved = {{ + {x19, x20}, + {x21, x22}, + {x23, x24}, + {x25, x26}, + {x27, x28}, + {x29, x30}, + }}; + + for (auto &RegPair : CalleeSaved) { + stp(RegPair.first, RegPair.second, PairOffset); + } + + // Additionally we need to store the lower 64bits of v8-v15 + // Here's a fun thing, we can use two ST4 instructions to store everything + // We just need a single sub to sp before that + const std::array< + std::tuple, 2> FPRs = {{ + {v8, v9, v10, v11}, + {v12, v13, v14, v15}, + }}; + + uint32_t VectorSaveSize = sizeof(uint64_t) * 8; + sub(sp, sp, VectorSaveSize); + // SP supporting move + // We just saved x19 so it is safe + add(x19, sp, 0); + + MemOperand QuadOffset(x19, 32, PostIndex); + for (auto &RegQuad : FPRs) { + st4(std::get<0>(RegQuad).D(), + std::get<1>(RegQuad).D(), + std::get<2>(RegQuad).D(), + std::get<3>(RegQuad).D(), + 0, + QuadOffset); + } +} + +void JITCore::PopCalleeSavedRegisters() { + const std::array< + std::tuple, 2> FPRs = {{ + {v12, v13, v14, v15}, + {v8, v9, v10, v11}, + }}; + + MemOperand QuadOffset(sp, 32, PostIndex); + for (auto &RegQuad : FPRs) { + ld4(std::get<0>(RegQuad).D(), + std::get<1>(RegQuad).D(), + std::get<2>(RegQuad).D(), + std::get<3>(RegQuad).D(), + 0, + QuadOffset); + } + + MemOperand PairOffset(sp, 16, PostIndex); + const std::array, 6> CalleeSaved = {{ + {x29, x30}, + {x27, x28}, + {x25, x26}, + {x23, x24}, + {x21, x22}, + {x19, x20}, + }}; + + for (auto &RegPair : CalleeSaved) { + ldp(RegPair.first, RegPair.second, PairOffset); + } +} + void JITCore::CreateCustomDispatch(FEXCore::Core::InternalThreadState *Thread) { + auto OriginalBuffer = *GetBuffer(); // Dispatcher lives outside of traditional space-time @@ -603,7 +685,6 @@ void JITCore::CreateCustomDispatch(FEXCore::Core::InternalThreadState *Thread) { auto Buffer = GetBuffer(); DispatchPtr = Buffer->GetOffsetAddress(GetCursorOffset()); - EmissionCheckScope(this, 0); // while (!Thread->State.RunningEvents.ShouldStop.load()) { // Ptr = FindBlock(RIP) @@ -762,22 +843,22 @@ void JITCore::CreateCustomDispatch(FEXCore::Core::InternalThreadState *Thread) { b(&ExitCheck); } - FinalizeCode(); - CPU.EnsureIAndDCacheCoherency(reinterpret_cast(DispatchPtr), Buffer->GetOffsetAddress(GetCursorOffset()) - reinterpret_cast(DispatchPtr)); - // Disabling will be useful for debugging ThreadState CustomDispatchGenerated = true; GenerateDispatchHelpers(); + + FinalizeCode(); + uint64_t CodeEnd = Buffer->GetOffsetAddress(GetCursorOffset()); + CPU.EnsureIAndDCacheCoherency(reinterpret_cast(DispatchPtr), CodeEnd - reinterpret_cast(DispatchPtr)); + *GetBuffer() = OriginalBuffer; } void JITCore::GenerateDispatchHelpers() { auto Buffer = GetBuffer(); - auto HelperStart = Buffer->GetOffsetAddress(GetCursorOffset()); - { Label RestoreContextStateHelperLabel{}; - Bind(&RestoreContextStateHelperLabel); + bind(&RestoreContextStateHelperLabel); SignalReturnInstruction = Buffer->GetOffsetAddress(GetCursorOffset()); // Now to get back to our old location we need to do a fault dance @@ -787,7 +868,7 @@ void JITCore::GenerateDispatchHelpers() { { Label InterpreterFallback{}; - Bind(&InterpreterFallback); + bind(&InterpreterFallback); InterpreterFallbackHelperAddress = Buffer->GetOffsetAddress(GetCursorOffset()); mov(x0, STATE); LoadConstant(x1, reinterpret_cast(State->IntBackend->CompileCode(nullptr, nullptr))); @@ -795,10 +876,6 @@ void JITCore::GenerateDispatchHelpers() { // We will return to the dispatcher at this point br(x1); } - - auto HelperEnd = Buffer->GetOffsetAddress(GetCursorOffset()); - FinalizeCode(); - CPU.EnsureIAndDCacheCoherency(HelperStart, HelperEnd - reinterpret_cast(HelperStart)); } FEXCore::CPU::CPUBackend *CreateJITCore(FEXCore::Context::Context *ctx, FEXCore::Core::InternalThreadState *Thread) { diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h index e184256e9..efb88f447 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h @@ -6,7 +6,7 @@ #include "aarch64/assembler-aarch64.h" #include "aarch64/cpu-aarch64.h" #include "aarch64/disasm-aarch64.h" -#include "aarch64/macro-assembler-aarch64.h" +#include "aarch64/assembler-aarch64.h" #include #include @@ -26,21 +26,21 @@ namespace FEXCore::CPU { using namespace vixl; using namespace vixl::aarch64; -const std::array RA64 = { +const std::array RA64 = { x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, - /*x16, x17,*/ // We can't use these until we move away from the MacroAssembler + x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27}; -const std::array, 11> RA64Pair = {{ +const std::array, 12> RA64Pair = {{ {x4, x5}, {x6, x7}, {x8, x9}, {x10, x11}, {x12, x13}, {x14, x15}, - /* {x16, x17}, */ + {x16, x17}, {x18, x19}, {x20, x21}, {x22, x23}, @@ -48,14 +48,14 @@ const std::array, 11> RA64Pair = {x26, x27}, }}; -const std::array, 11> RA32Pair = {{ +const std::array, 12> RA32Pair = {{ {w4, w5}, {w6, w7}, {w8, w9}, {w10, w11}, {w12, w13}, {w14, w15}, - /* {w16, w17}, */ + {w16, w17}, {w18, w19}, {w20, w21}, {w22, w23}, @@ -70,8 +70,7 @@ const std::array RAFPR = { v23, v24, v25, v26, v27, v28, v29, v30, v31}; -// XXX: Switch from MacroAssembler to Assembler once we drop the simulator -class JITCore final : public CPUBackend, public vixl::aarch64::MacroAssembler { +class JITCore final : public CPUBackend, public vixl::aarch64::Assembler { public: struct CodeBuffer { uint8_t *Ptr; @@ -79,6 +78,7 @@ public: }; explicit JITCore(FEXCore::Context::Context *ctx, FEXCore::Core::InternalThreadState *Thread, CodeBuffer Buffer); + ~JITCore() override; std::string GetName() override { return "JIT"; } void *CompileCode(FEXCore::IR::IRListView const *IR, FEXCore::Core::DebugData *DebugData) override; @@ -194,6 +194,8 @@ private: void CreateCustomDispatch(FEXCore::Core::InternalThreadState *Thread); void GenerateDispatchHelpers(); + void PushCalleeSavedRegisters(); + void PopCalleeSavedRegisters(); /** * @name Dispatch Helper functions