jak-project/goalc/emitter/Register.h

155 lines
2.9 KiB
C
Raw Normal View History

2020-08-28 20:16:30 -04:00
/*!
* @file Register.h
* Representation of an x86-64 Register.
*/
#ifndef JAK_REGISTER_H
#define JAK_REGISTER_H
#include <cassert>
#include <functional>
#include <array>
#include "common/common_types.h"
namespace emitter {
// registers by name
enum X86_REG : u8 {
RAX, // return, temp
RCX, // arg 3
RDX, // arg 2
RBX, // X saved
2020-08-29 19:13:29 -04:00
RSP, // stack pointer !!!!
RBP, // saved !!!!
2020-08-28 20:16:30 -04:00
RSI, // arg 1
RDI, // arg 0
R8, // arg 4
R9, // arg 5, saved
R10, // arg 6, saved (arg in GOAL only)
R11, // arg 7, saved (arg in GOAL only)
2020-08-29 19:13:29 -04:00
R12, // X saved - pp register (like s6) !!
R13, // X saved - function call register (like t9) !!
2020-08-28 20:16:30 -04:00
R14, // X saved - offset (added in GOAL x86)
R15, // X saved - st (like s7)
XMM0,
XMM1,
XMM2,
XMM3,
XMM4,
XMM5,
XMM6,
XMM7,
XMM8,
XMM9,
XMM10,
XMM11,
XMM12,
XMM13,
XMM14,
XMM15
};
2020-08-29 19:13:29 -04:00
2020-08-28 20:16:30 -04:00
class Register {
public:
Register() = default;
// intentionally not explicit so we can use X86_REGs in place of Registers
Register(int id) : m_id(id) {}
2020-08-29 19:13:29 -04:00
bool is_xmm() const { return m_id >= XMM0 && m_id <= XMM15; }
2020-08-28 20:16:30 -04:00
2020-08-29 19:13:29 -04:00
bool is_gpr() const { return m_id >= RAX && m_id <= R15; }
2020-08-28 20:16:30 -04:00
2020-08-29 19:13:29 -04:00
int hw_id() const {
2020-08-28 20:16:30 -04:00
if (is_xmm()) {
return m_id - XMM0;
} else if (is_gpr()) {
return m_id - RAX;
} else {
assert(false);
}
return 0xff;
}
2020-08-29 19:13:29 -04:00
int id() const {
return m_id;
}
2020-08-28 20:16:30 -04:00
struct hash {
auto operator()(const Register& x) const { return std::hash<u8>()(x.m_id); }
};
2020-08-29 19:13:29 -04:00
bool operator==(const Register& x) const { return m_id == x.m_id; }
2020-08-28 20:16:30 -04:00
2020-08-29 19:13:29 -04:00
bool operator!=(const Register& x) const { return m_id != x.m_id; }
2020-08-28 20:16:30 -04:00
private:
u8 m_id = 0xff;
};
2020-08-29 19:13:29 -04:00
class RegisterInfo {
public:
static constexpr int N_ARGS = 8;
static constexpr int N_REGS = 32;
static constexpr int N_SAVED_GPRS = 5;
static constexpr int N_SAVED_XMMS = 8;
static_assert(N_REGS - 1 == XMM15, "bad register count");
2020-08-28 20:16:30 -04:00
2020-08-29 19:13:29 -04:00
static RegisterInfo make_register_info();
2020-08-28 20:16:30 -04:00
struct Info {
2020-08-29 19:13:29 -04:00
int argument_id = -1; // -1 if not argument
bool saved = false; // does the callee save it?
bool special = false; // is it a special GOAL register?
2020-08-28 20:16:30 -04:00
std::string name;
};
2020-08-29 19:13:29 -04:00
const Info& get_info(Register r) const {
return m_info.at(r.id());
}
Register get_arg_reg(int id) const {
return m_arg_regs.at(id);
}
Register get_saved_gpr(int id) const {
return m_saved_gprs.at(id);
}
2020-08-28 20:16:30 -04:00
2020-08-29 19:13:29 -04:00
Register get_saved_xmm(int id) const {
return m_saved_xmms.at(id);
}
2020-08-28 20:16:30 -04:00
2020-08-29 19:13:29 -04:00
Register get_process_reg() const {
return R13;
}
2020-08-28 20:16:30 -04:00
2020-08-29 19:13:29 -04:00
Register get_st_reg() const {
return R14;
}
2020-08-28 20:16:30 -04:00
2020-08-29 19:13:29 -04:00
Register get_offset_reg() const {
return R15;
}
Register get_ret_reg() const {
return RAX;
}
private:
RegisterInfo() = default;
std::array<Info, N_REGS> m_info;
std::array<Register, N_ARGS> m_arg_regs;
std::array<Register, N_SAVED_GPRS> m_saved_gprs;
std::array<Register, N_SAVED_XMMS> m_saved_xmms;
};
2020-08-28 20:16:30 -04:00
} // namespace emitter
#endif // JAK_REGISTER_H