backend/x64: Move spill from JitState onto the stack
This commit is contained in:
parent
f8d8ea0deb
commit
ddbc50cee0
11 changed files with 52 additions and 40 deletions
|
@ -293,6 +293,7 @@ if (ARCHITECTURE STREQUAL "x86_64")
|
|||
backend/x64/perf_map.h
|
||||
backend/x64/reg_alloc.cpp
|
||||
backend/x64/reg_alloc.h
|
||||
backend/x64/stack_layout.h
|
||||
)
|
||||
|
||||
if ("A32" IN_LIST DYNARMIC_FRONTENDS)
|
||||
|
|
|
@ -109,7 +109,7 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
|
|||
return gprs;
|
||||
}();
|
||||
|
||||
RegAlloc reg_alloc{code, A32JitState::SpillCount, SpillToOpArg<A32JitState>, gpr_order, any_xmm};
|
||||
RegAlloc reg_alloc{code, gpr_order, any_xmm};
|
||||
A32EmitContext ctx{conf, reg_alloc, block};
|
||||
|
||||
// Start emitting.
|
||||
|
|
|
@ -39,13 +39,6 @@ struct A32JitState {
|
|||
|
||||
alignas(16) std::array<u32, 64> ExtReg{}; // Extension registers.
|
||||
|
||||
static constexpr size_t SpillCount = 64;
|
||||
alignas(16) std::array<std::array<u64, 2>, SpillCount> spill{}; // Spill.
|
||||
static Xbyak::Address GetSpillLocationFromIndex(size_t i) {
|
||||
using namespace Xbyak::util;
|
||||
return xword[r15 + offsetof(A32JitState, spill) + i * sizeof(u64) * 2];
|
||||
}
|
||||
|
||||
// For internal use (See: BlockOfCode::RunCode)
|
||||
u32 guest_MXCSR = 0x00001f80;
|
||||
u32 asimd_MXCSR = 0x00009fc0;
|
||||
|
|
|
@ -75,7 +75,7 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) {
|
|||
return gprs;
|
||||
}();
|
||||
|
||||
RegAlloc reg_alloc{code, A64JitState::SpillCount, SpillToOpArg<A64JitState>, gpr_order, any_xmm};
|
||||
RegAlloc reg_alloc{code, gpr_order, any_xmm};
|
||||
A64EmitContext ctx{conf, reg_alloc, block};
|
||||
|
||||
// Start emitting.
|
||||
|
|
|
@ -42,13 +42,6 @@ struct A64JitState {
|
|||
|
||||
alignas(16) std::array<u64, 64> vec{}; // Extension registers.
|
||||
|
||||
static constexpr size_t SpillCount = 64;
|
||||
alignas(16) std::array<std::array<u64, 2>, SpillCount> spill{}; // Spill.
|
||||
static Xbyak::Address GetSpillLocationFromIndex(size_t i) {
|
||||
using namespace Xbyak::util;
|
||||
return xword[r15 + offsetof(A64JitState, spill) + i * sizeof(u64) * 2];
|
||||
}
|
||||
|
||||
// For internal use (See: BlockOfCode::RunCode)
|
||||
u32 guest_MXCSR = 0x00001f80;
|
||||
u32 asimd_MXCSR = 0x00009fc0;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "backend/x64/block_of_code.h"
|
||||
#include "backend/x64/hostloc.h"
|
||||
#include "backend/x64/perf_map.h"
|
||||
#include "backend/x64/stack_layout.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/bit_util.h"
|
||||
|
||||
|
@ -155,7 +156,7 @@ void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
|
|||
// 1. It saves all the registers we as a callee need to save.
|
||||
// 2. It aligns the stack so that the code the JIT emits can assume
|
||||
// that the stack is appropriately aligned for CALLs.
|
||||
ABI_PushCalleeSaveRegistersAndAdjustStack(*this);
|
||||
ABI_PushCalleeSaveRegistersAndAdjustStack(*this, sizeof(StackLayout));
|
||||
|
||||
mov(r15, ABI_PARAM1);
|
||||
mov(rbx, ABI_PARAM2); // save temporarily in non-volatile register
|
||||
|
@ -172,7 +173,7 @@ void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
|
|||
align();
|
||||
step_code = getCurr<RunCodeFuncType>();
|
||||
|
||||
ABI_PushCalleeSaveRegistersAndAdjustStack(*this);
|
||||
ABI_PushCalleeSaveRegistersAndAdjustStack(*this, sizeof(StackLayout));
|
||||
|
||||
mov(r15, ABI_PARAM1);
|
||||
|
||||
|
@ -222,7 +223,7 @@ void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
|
|||
sub(param[0], qword[r15 + jsi.offsetof_cycles_remaining]);
|
||||
});
|
||||
|
||||
ABI_PopCalleeSaveRegistersAndAdjustStack(*this);
|
||||
ABI_PopCalleeSaveRegistersAndAdjustStack(*this, sizeof(StackLayout));
|
||||
ret();
|
||||
|
||||
PerfMapRegister(run_code, getCurr(), "dynarmic_dispatcher");
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
|
||||
#include <xbyak.h>
|
||||
|
||||
#include "backend/x64/abi.h"
|
||||
#include "backend/x64/hostloc.h"
|
||||
#include "backend/x64/stack_layout.h"
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
|
@ -19,4 +21,14 @@ Xbyak::Xmm HostLocToXmm(HostLoc loc) {
|
|||
return Xbyak::Xmm(static_cast<int>(loc) - static_cast<int>(HostLoc::XMM0));
|
||||
}
|
||||
|
||||
Xbyak::Address SpillToOpArg(HostLoc loc) {
|
||||
ASSERT(HostLocIsSpill(loc));
|
||||
|
||||
size_t i = static_cast<size_t>(loc) - static_cast<size_t>(HostLoc::FirstSpill);
|
||||
ASSERT_MSG(i < SpillCount, "Spill index greater than number of available spill locations");
|
||||
|
||||
using namespace Xbyak::util;
|
||||
return xword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, spill) + i * sizeof(u64) * 2];
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::Backend::X64
|
||||
|
|
|
@ -110,15 +110,6 @@ const HostLocList any_xmm = {
|
|||
|
||||
Xbyak::Reg64 HostLocToReg64(HostLoc loc);
|
||||
Xbyak::Xmm HostLocToXmm(HostLoc loc);
|
||||
|
||||
template <typename JitStateType>
|
||||
Xbyak::Address SpillToOpArg(HostLoc loc) {
|
||||
ASSERT(HostLocIsSpill(loc));
|
||||
|
||||
size_t i = static_cast<size_t>(loc) - static_cast<size_t>(HostLoc::FirstSpill);
|
||||
ASSERT_MSG(i < JitStateType::SpillCount, "Spill index greater than number of available spill locations");
|
||||
|
||||
return JitStateType::GetSpillLocationFromIndex(i);
|
||||
}
|
||||
Xbyak::Address SpillToOpArg(HostLoc loc);
|
||||
|
||||
} // namespace Dynarmic::Backend::X64
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "backend/x64/abi.h"
|
||||
#include "backend/x64/reg_alloc.h"
|
||||
#include "backend/x64/stack_layout.h"
|
||||
#include "common/assert.h"
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
@ -223,12 +224,11 @@ bool Argument::IsInMemory() const {
|
|||
return HostLocIsSpill(*reg_alloc.ValueLocation(value.GetInst()));
|
||||
}
|
||||
|
||||
RegAlloc::RegAlloc(BlockOfCode& code, size_t num_spills, std::function<Xbyak::Address(HostLoc)> spill_to_addr, std::vector<HostLoc> gpr_order, std::vector<HostLoc> xmm_order)
|
||||
RegAlloc::RegAlloc(BlockOfCode& code, std::vector<HostLoc> gpr_order, std::vector<HostLoc> xmm_order)
|
||||
: gpr_order(gpr_order)
|
||||
, xmm_order(xmm_order)
|
||||
, hostloc_info(NonSpillHostLocCount + num_spills)
|
||||
, hostloc_info(NonSpillHostLocCount + SpillCount)
|
||||
, code(code)
|
||||
, spill_to_addr(std::move(spill_to_addr))
|
||||
{}
|
||||
|
||||
RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) {
|
||||
|
@ -629,7 +629,7 @@ void RegAlloc::EmitMove(size_t bit_width, HostLoc to, HostLoc from) {
|
|||
MAYBE_AVX(movd, HostLocToReg64(to).cvt32(), HostLocToXmm(from));
|
||||
}
|
||||
} else if (HostLocIsXMM(to) && HostLocIsSpill(from)) {
|
||||
const Xbyak::Address spill_addr = spill_to_addr(from);
|
||||
const Xbyak::Address spill_addr = SpillToOpArg(from);
|
||||
ASSERT(spill_addr.getBit() >= bit_width);
|
||||
switch (bit_width) {
|
||||
case 128:
|
||||
|
@ -647,7 +647,7 @@ void RegAlloc::EmitMove(size_t bit_width, HostLoc to, HostLoc from) {
|
|||
UNREACHABLE();
|
||||
}
|
||||
} else if (HostLocIsSpill(to) && HostLocIsXMM(from)) {
|
||||
const Xbyak::Address spill_addr = spill_to_addr(to);
|
||||
const Xbyak::Address spill_addr = SpillToOpArg(to);
|
||||
ASSERT(spill_addr.getBit() >= bit_width);
|
||||
switch (bit_width) {
|
||||
case 128:
|
||||
|
@ -667,16 +667,16 @@ void RegAlloc::EmitMove(size_t bit_width, HostLoc to, HostLoc from) {
|
|||
} else if (HostLocIsGPR(to) && HostLocIsSpill(from)) {
|
||||
ASSERT(bit_width != 128);
|
||||
if (bit_width == 64) {
|
||||
code.mov(HostLocToReg64(to), spill_to_addr(from));
|
||||
code.mov(HostLocToReg64(to), SpillToOpArg(from));
|
||||
} else {
|
||||
code.mov(HostLocToReg64(to).cvt32(), spill_to_addr(from));
|
||||
code.mov(HostLocToReg64(to).cvt32(), SpillToOpArg(from));
|
||||
}
|
||||
} else if (HostLocIsSpill(to) && HostLocIsGPR(from)) {
|
||||
ASSERT(bit_width != 128);
|
||||
if (bit_width == 64) {
|
||||
code.mov(spill_to_addr(to), HostLocToReg64(from));
|
||||
code.mov(SpillToOpArg(to), HostLocToReg64(from));
|
||||
} else {
|
||||
code.mov(spill_to_addr(to), HostLocToReg64(from).cvt32());
|
||||
code.mov(SpillToOpArg(to), HostLocToReg64(from).cvt32());
|
||||
}
|
||||
} else {
|
||||
ASSERT_FALSE("Invalid RegAlloc::EmitMove");
|
||||
|
|
|
@ -96,7 +96,7 @@ class RegAlloc final {
|
|||
public:
|
||||
using ArgumentInfo = std::array<Argument, IR::max_arg_count>;
|
||||
|
||||
explicit RegAlloc(BlockOfCode& code, size_t num_spills, std::function<Xbyak::Address(HostLoc)> spill_to_addr, std::vector<HostLoc> gpr_order, std::vector<HostLoc> xmm_order);
|
||||
explicit RegAlloc(BlockOfCode& code, std::vector<HostLoc> gpr_order, std::vector<HostLoc> xmm_order);
|
||||
|
||||
ArgumentInfo GetArgumentInfo(IR::Inst* inst);
|
||||
|
||||
|
@ -160,7 +160,6 @@ private:
|
|||
const HostLocInfo& LocInfo(HostLoc loc) const;
|
||||
|
||||
BlockOfCode& code;
|
||||
std::function<Xbyak::Address(HostLoc)> spill_to_addr;
|
||||
void EmitMove(size_t bit_width, HostLoc to, HostLoc from);
|
||||
void EmitExchange(HostLoc a, HostLoc b);
|
||||
};
|
||||
|
|
22
src/backend/x64/stack_layout.h
Normal file
22
src/backend/x64/stack_layout.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2016 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
constexpr size_t SpillCount = 64;
|
||||
|
||||
struct alignas(16) StackLayout {
|
||||
std::array<std::array<u64, 2>, SpillCount> spill;
|
||||
};
|
||||
|
||||
static_assert(sizeof(StackLayout) % 16 == 0);
|
||||
|
||||
} // namespace Dynarmic::Backend::X64
|
Loading…
Reference in a new issue