dynarmic/src/backend_x64/reg_alloc.h

160 lines
4.4 KiB
C
Raw Normal View History

2016-07-01 14:01:06 +01:00
/* This file is part of the dynarmic project.
* Copyright (c) 2016 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
#include <array>
#include <vector>
#include <boost/optional.hpp>
2016-08-24 20:07:08 +01:00
#include <xbyak.h>
2016-07-01 14:01:06 +01:00
#include "backend_x64/block_of_code.h"
2016-08-24 20:07:08 +01:00
#include "backend_x64/hostloc.h"
2017-02-21 23:38:36 +00:00
#include "backend_x64/oparg.h"
2016-07-01 14:01:06 +01:00
#include "common/common_types.h"
#include "frontend/ir/microinstruction.h"
#include "frontend/ir/value.h"
2016-07-01 14:01:06 +01:00
namespace Dynarmic {
namespace BackendX64 {
class RegAlloc;
struct HostLocInfo {
public:
bool IsLocked() const {
return is_being_used;
}
bool IsEmpty() const {
return !is_being_used && values.empty();
}
2017-02-24 20:14:02 +00:00
bool IsLastUse() const {
return !is_being_used && std::all_of(values.begin(), values.end(), [](const auto& inst) { return !inst->HasUses(); });
}
bool ContainsValue(const IR::Inst* inst) const {
return std::find(values.begin(), values.end(), inst) != values.end();
}
void ReadLock() {
ASSERT(!is_scratch);
is_being_used = true;
}
void WriteLock() {
ASSERT(!is_being_used);
is_being_used = true;
is_scratch = true;
}
void AddValue(IR::Inst* inst) {
values.push_back(inst);
}
void EndOfAllocScope() {
const auto to_erase = std::remove_if(values.begin(), values.end(), [](const auto& inst){ return !inst->HasUses(); });
values.erase(to_erase, values.end());
is_being_used = false;
is_scratch = false;
}
private:
std::vector<IR::Inst*> values;
bool is_being_used = false;
bool is_scratch = false;
};
struct Argument {
public:
IR::Type GetType() const {
return value.GetType();
}
bool IsImmediate() const {
return value.IsImmediate();
}
bool GetImmediateU1() const;
u8 GetImmediateU8() const;
u16 GetImmediateU16() const;
u32 GetImmediateU32() const;
u64 GetImmediateU64() const;
/// Is this value currently in a GPR?
bool IsInGpr() const;
/// Is this value currently in a XMM?
bool IsInXmm() const;
/// Is this value currently in memory?
bool IsInMemory() const;
private:
friend class RegAlloc;
Argument(RegAlloc& reg_alloc) : reg_alloc(reg_alloc) {}
bool allocated = false;
RegAlloc& reg_alloc;
IR::Value value;
};
2016-07-01 14:01:06 +01:00
class RegAlloc final {
public:
2016-09-07 12:08:48 +01:00
explicit RegAlloc(BlockOfCode* code) : code(code) {}
2016-07-01 14:01:06 +01:00
std::array<Argument, 3> GetArgumentInfo(IR::Inst* inst);
2017-02-26 22:28:32 +00:00
Xbyak::Reg64 UseGpr(Argument& arg);
Xbyak::Xmm UseXmm(Argument& arg);
OpArg UseOpArg(Argument& arg);
void Use(Argument& arg, HostLoc host_loc);
2017-02-26 22:28:32 +00:00
Xbyak::Reg64 UseScratchGpr(Argument& arg);
Xbyak::Xmm UseScratchXmm(Argument& arg);
void UseScratch(Argument& arg, HostLoc host_loc);
2017-02-26 22:28:32 +00:00
void DefineValue(IR::Inst* inst, const Xbyak::Reg& reg);
void DefineValue(IR::Inst* inst, Argument& arg);
2017-02-26 22:28:32 +00:00
Xbyak::Reg64 ScratchGpr(HostLocList desired_locations = any_gpr);
Xbyak::Xmm ScratchXmm(HostLocList desired_locations = any_xmm);
2016-07-01 14:01:06 +01:00
2017-02-26 22:28:32 +00:00
void HostCall(IR::Inst* result_def = nullptr, boost::optional<Argument&> arg0 = {}, boost::optional<Argument&> arg1 = {}, boost::optional<Argument&> arg2 = {}, boost::optional<Argument&> arg3 = {});
2016-07-01 14:01:06 +01:00
// TODO: Values in host flags
void EndOfAllocScope();
void AssertNoMoreUses();
2016-07-01 14:01:06 +01:00
private:
friend struct Argument;
HostLoc SelectARegister(HostLocList desired_locations) const;
boost::optional<HostLoc> ValueLocation(const IR::Inst* value) const;
2017-02-26 22:28:32 +00:00
HostLoc UseImpl(IR::Value use_value, HostLocList desired_locations);
HostLoc UseScratchImpl(IR::Value use_value, HostLocList desired_locations);
HostLoc ScratchImpl(HostLocList desired_locations);
void DefineValueImpl(IR::Inst* def_inst, HostLoc host_loc);
void DefineValueImpl(IR::Inst* def_inst, const IR::Value& use_inst);
2017-02-26 22:28:32 +00:00
BlockOfCode* code = nullptr;
2017-02-26 22:28:32 +00:00
HostLoc LoadImmediate(IR::Value imm, HostLoc reg);
2017-02-24 19:42:36 +00:00
void Move(HostLoc to, HostLoc from);
void CopyToScratch(HostLoc to, HostLoc from);
2017-02-24 19:42:36 +00:00
void Exchange(HostLoc a, HostLoc b);
void MoveOutOfTheWay(HostLoc reg);
2016-07-01 14:01:06 +01:00
void SpillRegister(HostLoc loc);
HostLoc FindFreeSpill() const;
std::array<HostLocInfo, HostLocCount> hostloc_info;
2017-02-26 22:28:32 +00:00
HostLocInfo& LocInfo(HostLoc loc);
const HostLocInfo& LocInfo(HostLoc loc) const;
2016-07-01 14:01:06 +01:00
};
} // namespace BackendX64
} // namespace Dynarmic