diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp index 33fd8b917..435c8c137 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp @@ -783,10 +783,12 @@ void *Arm64JITCore::CompileCode(uint64_t Entry, SpillSlots = RAData->SpillSlots(); if (SpillSlots) { - if (IsImmAddSub(SpillSlots * 16)) { - sub(sp, sp, SpillSlots * 16); + const auto TotalSpillSlotsSize = SpillSlots * MaxSpillSlotSize; + + if (IsImmAddSub(TotalSpillSlotsSize)) { + sub(sp, sp, TotalSpillSlotsSize); } else { - LoadConstant(x0, SpillSlots * 16); + LoadConstant(x0, TotalSpillSlotsSize); sub(sp, sp, x0); } } @@ -854,14 +856,17 @@ void *Arm64JITCore::CompileCode(uint64_t Entry, } void Arm64JITCore::ResetStack() { - if (SpillSlots == 0) + if (SpillSlots == 0) { return; + } - if (IsImmAddSub(SpillSlots * 16)) { - add(sp, sp, SpillSlots * 16); + const auto TotalSpillSlotsSize = SpillSlots * MaxSpillSlotSize; + + if (IsImmAddSub(TotalSpillSlotsSize)) { + add(sp, sp, TotalSpillSlotsSize); } else { // Too big to fit in a 12bit immediate - LoadConstant(x0, SpillSlots * 16); + LoadConstant(x0, TotalSpillSlotsSize); add(sp, sp, x0); } } diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp index 323a77e47..a8b0ad1f3 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/MemoryOps.cpp @@ -446,9 +446,9 @@ DEF_OP(StoreContextIndexed) { } DEF_OP(SpillRegister) { - auto Op = IROp->C(); + const auto Op = IROp->C(); const uint8_t OpSize = IROp->Size; - const uint32_t SlotOffset = Op->Slot * 16; + const uint32_t SlotOffset = Op->Slot * MaxSpillSlotSize; if (Op->Class == FEXCore::IR::GPRClass) { switch (OpSize) { @@ -492,9 +492,9 @@ DEF_OP(SpillRegister) { } DEF_OP(FillRegister) { - auto Op = IROp->C(); - uint8_t OpSize = IROp->Size; - uint32_t SlotOffset = Op->Slot * 16; + const auto Op = IROp->C(); + const uint8_t OpSize = IROp->Size; + const uint32_t SlotOffset = Op->Slot * MaxSpillSlotSize; if (Op->Class == FEXCore::IR::GPRClass) { switch (OpSize) { diff --git a/External/FEXCore/Source/Interface/Core/JIT/x86_64/BranchOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/x86_64/BranchOps.cpp index 7b20aeeb0..3c89ba53b 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/x86_64/BranchOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/x86_64/BranchOps.cpp @@ -33,7 +33,7 @@ namespace FEXCore::CPU { DEF_OP(SignalReturn) { // Adjust the stack first for a regular return if (SpillSlots) { - add(rsp, SpillSlots * 16); // + 8 to consume return address + add(rsp, SpillSlots * MaxSpillSlotSize); // + 8 to consume return address } jmp(qword [STATE + offsetof(FEXCore::Core::CpuStateFrame, Pointers.Common.SignalReturnHandler)]); @@ -42,7 +42,7 @@ DEF_OP(SignalReturn) { DEF_OP(CallbackReturn) { // Adjust the stack first for a regular return if (SpillSlots) { - add(rsp, SpillSlots * 16); // + 8 to consume return address + add(rsp, SpillSlots * MaxSpillSlotSize); // + 8 to consume return address } // Make sure to adjust the refcounter so we don't clear the cache now @@ -71,7 +71,7 @@ DEF_OP(ExitFunction) { if (SpillSlots) { - add(rsp, SpillSlots * 16); + add(rsp, SpillSlots * MaxSpillSlotSize); } uint64_t NewRIP; diff --git a/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp b/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp index 1f8b8e06b..a8276a243 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp @@ -599,7 +599,7 @@ void *X86JITCore::CompileCode(uint64_t Entry, [[maybe_unused]] FEXCore::IR::IRLi SpillSlots = RAData->SpillSlots(); if (SpillSlots) { - sub(rsp, SpillSlots * 16); + sub(rsp, SpillSlots * MaxSpillSlotSize); } #ifdef BLOCKSTATS diff --git a/External/FEXCore/Source/Interface/Core/JIT/x86_64/MemoryOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/x86_64/MemoryOps.cpp index a51c8bcb2..07e7e6398 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/x86_64/MemoryOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/x86_64/MemoryOps.cpp @@ -333,10 +333,10 @@ DEF_OP(StoreContextIndexed) { } DEF_OP(SpillRegister) { - auto Op = IROp->C(); - uint8_t OpSize = IROp->Size; + const auto Op = IROp->C(); + const uint8_t OpSize = IROp->Size; + const uint32_t SlotOffset = Op->Slot * MaxSpillSlotSize; - uint32_t SlotOffset = Op->Slot * 16; if (Op->Class == FEXCore::IR::GPRClass) { switch (OpSize) { case 1: { @@ -381,10 +381,10 @@ DEF_OP(SpillRegister) { } DEF_OP(FillRegister) { - auto Op = IROp->C(); - uint8_t OpSize = IROp->Size; + const auto Op = IROp->C(); + const uint8_t OpSize = IROp->Size; + const uint32_t SlotOffset = Op->Slot * MaxSpillSlotSize; - uint32_t SlotOffset = Op->Slot * 16; if (Op->Class == FEXCore::IR::GPRClass) { switch (OpSize) { case 1: { diff --git a/External/FEXCore/Source/Interface/Core/JIT/x86_64/MiscOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/x86_64/MiscOps.cpp index 42d3d43f8..54909fcc6 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/x86_64/MiscOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/x86_64/MiscOps.cpp @@ -47,7 +47,7 @@ DEF_OP(Break) { auto Op = IROp->C(); if (SpillSlots) { - add(rsp, SpillSlots * 16); + add(rsp, SpillSlots * MaxSpillSlotSize); } mov(byte [STATE + offsetof(FEXCore::Core::CpuStateFrame, SynchronousFaultData.FaultToTopAndGeneratedException)], 1); diff --git a/External/FEXCore/include/FEXCore/Core/CPUBackend.h b/External/FEXCore/include/FEXCore/Core/CPUBackend.h index 067dc32db..0949422cd 100644 --- a/External/FEXCore/include/FEXCore/Core/CPUBackend.h +++ b/External/FEXCore/include/FEXCore/Core/CPUBackend.h @@ -122,6 +122,10 @@ namespace CPU { bool IsAddressInCodeBuffer(uintptr_t Address) const; protected: + // Max spill slot size in bytes. We need at most 32 bytes + // to be able to handle a 256-bit vector store to a slot. + constexpr static uint32_t MaxSpillSlotSize = 32; + FEXCore::Core::InternalThreadState *ThreadState; size_t InitialCodeSize, MaxCodeSize;