mirror of
https://git.suyu.dev/suyu/dynarmic.git
synced 2026-01-04 05:34:42 +01:00
Port x64 backend to xbyak
This commit is contained in:
parent
611cffb612
commit
e32812cd00
25 changed files with 1638 additions and 5323 deletions
|
|
@ -11,93 +11,55 @@
|
|||
#include <vector>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <xbyak.h>
|
||||
|
||||
#include "backend_x64/block_of_code.h"
|
||||
#include "backend_x64/hostloc.h"
|
||||
#include "backend_x64/jitstate.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/x64/emitter.h"
|
||||
#include "frontend/ir/microinstruction.h"
|
||||
#include "frontend/ir/value.h"
|
||||
|
||||
namespace Dynarmic {
|
||||
namespace BackendX64 {
|
||||
|
||||
enum class HostLoc {
|
||||
// Ordering of the registers is intentional. See also: HostLocToX64.
|
||||
RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14,
|
||||
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
||||
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15,
|
||||
CF, PF, AF, ZF, SF, OF,
|
||||
FirstSpill,
|
||||
};
|
||||
struct OpArg {
|
||||
OpArg() : type(OPERAND), inner_operand() {}
|
||||
OpArg(const Xbyak::Address& address) : type(ADDRESS), inner_address(address) {}
|
||||
OpArg(const Xbyak::Operand& operand) : type(OPERAND), inner_operand(operand) {}
|
||||
|
||||
constexpr size_t HostLocCount = static_cast<size_t>(HostLoc::FirstSpill) + SpillCount;
|
||||
Xbyak::Operand& operator*() {
|
||||
switch (type) {
|
||||
case ADDRESS:
|
||||
return inner_address;
|
||||
case OPERAND:
|
||||
return inner_operand;
|
||||
}
|
||||
ASSERT_MSG(false, "Unreachable");
|
||||
}
|
||||
|
||||
enum class HostLocState {
|
||||
Idle, Def, Use, Scratch
|
||||
};
|
||||
void setBit(int bits) {
|
||||
switch (type) {
|
||||
case ADDRESS:
|
||||
inner_address.setBit(bits);
|
||||
return;
|
||||
case OPERAND:
|
||||
inner_operand.setBit(bits);
|
||||
return;
|
||||
}
|
||||
ASSERT_MSG(false, "Unreachable");
|
||||
}
|
||||
|
||||
inline bool HostLocIsGPR(HostLoc reg) {
|
||||
return reg >= HostLoc::RAX && reg <= HostLoc::R14;
|
||||
}
|
||||
private:
|
||||
enum {
|
||||
OPERAND,
|
||||
ADDRESS,
|
||||
} type;
|
||||
|
||||
inline bool HostLocIsXMM(HostLoc reg) {
|
||||
return reg >= HostLoc::XMM0 && reg <= HostLoc::XMM15;
|
||||
}
|
||||
|
||||
inline bool HostLocIsRegister(HostLoc reg) {
|
||||
return HostLocIsGPR(reg) || HostLocIsXMM(reg);
|
||||
}
|
||||
|
||||
inline bool HostLocIsFlag(HostLoc reg) {
|
||||
return reg >= HostLoc::CF && reg <= HostLoc::OF;
|
||||
}
|
||||
|
||||
inline HostLoc HostLocSpill(size_t i) {
|
||||
ASSERT_MSG(i < SpillCount, "Invalid spill");
|
||||
return static_cast<HostLoc>(static_cast<int>(HostLoc::FirstSpill) + i);
|
||||
}
|
||||
|
||||
inline bool HostLocIsSpill(HostLoc reg) {
|
||||
return reg >= HostLoc::FirstSpill && reg <= HostLocSpill(SpillCount - 1);
|
||||
}
|
||||
|
||||
using HostLocList = std::initializer_list<HostLoc>;
|
||||
|
||||
const HostLocList any_gpr = {
|
||||
HostLoc::RAX,
|
||||
HostLoc::RBX,
|
||||
HostLoc::RCX,
|
||||
HostLoc::RDX,
|
||||
HostLoc::RSI,
|
||||
HostLoc::RDI,
|
||||
HostLoc::RBP,
|
||||
HostLoc::R8,
|
||||
HostLoc::R9,
|
||||
HostLoc::R10,
|
||||
HostLoc::R11,
|
||||
HostLoc::R12,
|
||||
HostLoc::R13,
|
||||
HostLoc::R14,
|
||||
};
|
||||
|
||||
const HostLocList any_xmm = {
|
||||
HostLoc::XMM0,
|
||||
HostLoc::XMM1,
|
||||
HostLoc::XMM2,
|
||||
HostLoc::XMM3,
|
||||
HostLoc::XMM4,
|
||||
HostLoc::XMM5,
|
||||
HostLoc::XMM6,
|
||||
HostLoc::XMM7,
|
||||
HostLoc::XMM8,
|
||||
HostLoc::XMM9,
|
||||
HostLoc::XMM10,
|
||||
HostLoc::XMM11,
|
||||
HostLoc::XMM12,
|
||||
HostLoc::XMM13,
|
||||
HostLoc::XMM14,
|
||||
HostLoc::XMM15,
|
||||
union {
|
||||
Xbyak::Operand inner_operand;
|
||||
Xbyak::Address inner_address;
|
||||
};
|
||||
};
|
||||
|
||||
class RegAlloc final {
|
||||
|
|
@ -105,21 +67,54 @@ public:
|
|||
RegAlloc(BlockOfCode* code) : code(code) {}
|
||||
|
||||
/// Late-def
|
||||
Gen::X64Reg DefRegister(IR::Inst* def_inst, HostLocList desired_locations);
|
||||
Xbyak::Reg64 DefGpr(IR::Inst* def_inst, HostLocList desired_locations = any_gpr) {
|
||||
return HostLocToReg64(DefHostLocReg(def_inst, desired_locations));
|
||||
}
|
||||
Xbyak::Xmm DefXmm(IR::Inst* def_inst, HostLocList desired_locations = any_xmm) {
|
||||
return HostLocToXmm(DefHostLocReg(def_inst, desired_locations));
|
||||
}
|
||||
void RegisterAddDef(IR::Inst* def_inst, const IR::Value& use_inst);
|
||||
/// Early-use, Late-def
|
||||
Gen::X64Reg UseDefRegister(IR::Value use_value, IR::Inst* def_inst, HostLocList desired_locations);
|
||||
Gen::X64Reg UseDefRegister(IR::Inst* use_inst, IR::Inst* def_inst, HostLocList desired_locations);
|
||||
std::tuple<Gen::OpArg, Gen::X64Reg> UseDefOpArg(IR::Value use_value, IR::Inst* def_inst, HostLocList desired_locations);
|
||||
Xbyak::Reg64 UseDefGpr(IR::Value use_value, IR::Inst* def_inst, HostLocList desired_locations = any_gpr) {
|
||||
return HostLocToReg64(UseDefHostLocReg(use_value, def_inst, desired_locations));
|
||||
}
|
||||
Xbyak::Xmm UseDefXmm(IR::Value use_value, IR::Inst* def_inst, HostLocList desired_locations = any_xmm) {
|
||||
return HostLocToXmm(UseDefHostLocReg(use_value, def_inst, desired_locations));
|
||||
}
|
||||
std::tuple<OpArg, Xbyak::Reg64> UseDefOpArgGpr(IR::Value use_value, IR::Inst* def_inst, HostLocList desired_locations = any_gpr) {
|
||||
OpArg op;
|
||||
HostLoc host_loc;
|
||||
std::tie(op, host_loc) = UseDefOpArgHostLocReg(use_value, def_inst, desired_locations);
|
||||
return std::make_tuple(op, HostLocToReg64(host_loc));
|
||||
}
|
||||
std::tuple<OpArg, Xbyak::Xmm> UseDefOpArgXmm(IR::Value use_value, IR::Inst* def_inst, HostLocList desired_locations = any_gpr) {
|
||||
OpArg op;
|
||||
HostLoc host_loc;
|
||||
std::tie(op, host_loc) = UseDefOpArgHostLocReg(use_value, def_inst, desired_locations);
|
||||
return std::make_tuple(op, HostLocToXmm(host_loc));
|
||||
}
|
||||
/// Early-use
|
||||
Gen::X64Reg UseRegister(IR::Value use_value, HostLocList desired_locations);
|
||||
Gen::X64Reg UseRegister(IR::Inst* use_inst, HostLocList desired_locations);
|
||||
Gen::OpArg UseOpArg(IR::Value use_value, HostLocList desired_locations);
|
||||
Xbyak::Reg64 UseGpr(IR::Value use_value, HostLocList desired_locations = any_gpr) {
|
||||
return HostLocToReg64(UseHostLocReg(use_value, desired_locations));
|
||||
}
|
||||
Xbyak::Xmm UseXmm(IR::Value use_value, HostLocList desired_locations = any_xmm) {
|
||||
return HostLocToXmm(UseHostLocReg(use_value, desired_locations));
|
||||
}
|
||||
OpArg UseOpArg(IR::Value use_value, HostLocList desired_locations);
|
||||
/// Early-use, Destroyed
|
||||
Gen::X64Reg UseScratchRegister(IR::Value use_value, HostLocList desired_locations);
|
||||
Gen::X64Reg UseScratchRegister(IR::Inst* use_inst, HostLocList desired_locations);
|
||||
Xbyak::Reg64 UseScratchGpr(IR::Value use_value, HostLocList desired_locations = any_gpr) {
|
||||
return HostLocToReg64(UseScratchHostLocReg(use_value, desired_locations));
|
||||
}
|
||||
Xbyak::Xmm UseScratchXmm(IR::Value use_value, HostLocList desired_locations = any_xmm) {
|
||||
return HostLocToXmm(UseScratchHostLocReg(use_value, desired_locations));
|
||||
}
|
||||
/// Early-def, Late-use, single-use
|
||||
Gen::X64Reg ScratchRegister(HostLocList desired_locations);
|
||||
Xbyak::Reg64 ScratchGpr(HostLocList desired_locations = any_gpr) {
|
||||
return HostLocToReg64(ScratchHostLocReg(desired_locations));
|
||||
}
|
||||
Xbyak::Xmm ScratchXmm(HostLocList desired_locations = any_xmm) {
|
||||
return HostLocToXmm(ScratchHostLocReg(desired_locations));
|
||||
}
|
||||
|
||||
/// Late-def for result register, Early-use for all arguments, Each value is placed into registers according to host ABI.
|
||||
void HostCall(IR::Inst* result_def = nullptr, IR::Value arg0_use = {}, IR::Value arg1_use = {}, IR::Value arg2_use = {}, IR::Value arg3_use = {});
|
||||
|
|
@ -141,11 +136,20 @@ private:
|
|||
bool IsRegisterAllocated(HostLoc loc) const;
|
||||
bool IsLastUse(IR::Inst* inst) const;
|
||||
|
||||
HostLoc DefHostLocReg(IR::Inst* def_inst, HostLocList desired_locations);
|
||||
HostLoc UseDefHostLocReg(IR::Value use_value, IR::Inst* def_inst, HostLocList desired_locations);
|
||||
HostLoc UseDefHostLocReg(IR::Inst* use_inst, IR::Inst* def_inst, HostLocList desired_locations);
|
||||
std::tuple<OpArg, HostLoc> UseDefOpArgHostLocReg(IR::Value use_value, IR::Inst* def_inst, HostLocList desired_locations);
|
||||
HostLoc UseHostLocReg(IR::Value use_value, HostLocList desired_locations);
|
||||
HostLoc UseHostLocReg(IR::Inst* use_inst, HostLocList desired_locations);
|
||||
std::tuple<HostLoc, bool> UseHostLoc(IR::Inst* use_inst, HostLocList desired_locations);
|
||||
HostLoc UseScratchHostLocReg(IR::Value use_value, HostLocList desired_locations);
|
||||
HostLoc UseScratchHostLocReg(IR::Inst* use_inst, HostLocList desired_locations);
|
||||
HostLoc ScratchHostLocReg(HostLocList desired_locations);
|
||||
|
||||
void EmitMove(HostLoc to, HostLoc from);
|
||||
void EmitExchange(HostLoc a, HostLoc b);
|
||||
Gen::X64Reg LoadImmediateIntoRegister(IR::Value imm, Gen::X64Reg reg);
|
||||
HostLoc LoadImmediateIntoHostLocReg(IR::Value imm, HostLoc reg);
|
||||
|
||||
void SpillRegister(HostLoc loc);
|
||||
HostLoc FindFreeSpill() const;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue