This commit is contained in:
water
2021-06-19 13:05:48 -04:00
parent 387a394be9
commit 57b2f5d72f
9 changed files with 410 additions and 143 deletions
-122
View File
@@ -94,45 +94,6 @@ const char* special_to_charp(uint32_t special) {
}
} // namespace
/////////////////////////////
// Register Class
/////////////////////////////
// A register is stored as a 16-bit integer, with the top 8 bits indicating the "kind" and the lower
// 8 bits representing the register id within that kind. If the integer is -1, it is a special
// "invalid" register used to represent an uninitialized Register.
// Note: VI / COP2 are separate "kinds" of registers, each with 16 registers.
// It might make sense to make this a single "kind" instead?
namespace {
constexpr int REG_CATEGORY_SHIFT = 5;
constexpr int REG_IDX_MASK = 0b11111;
} // namespace
/*!
* Create a register. The kind and num must both be valid.
*/
Register::Register(Reg::RegisterKind kind, uint32_t num) {
// 32 regs/category at most.
id = (kind << REG_CATEGORY_SHIFT) | num;
// check range:
switch (kind) {
case Reg::GPR:
case Reg::FPR:
case Reg::VF:
case Reg::COP0:
case Reg::VI:
assert(num < 32);
break;
case Reg::SPECIAL:
assert(num < Reg::MAX_SPECIAL);
break;
default:
assert(false);
}
}
Register::Register(const std::string& name) {
// first try gprs,
for (int i = 0; i < Reg::MAX_GPR; i++) {
@@ -182,87 +143,4 @@ std::string Register::to_string() const {
return {to_charp()};
}
/*!
* Get the register kind.
*/
Reg::RegisterKind Register::get_kind() const {
uint16_t kind = id >> REG_CATEGORY_SHIFT;
assert(kind < Reg::MAX_KIND);
return (Reg::RegisterKind)kind;
}
/*!
* Get the GPR number. Must be a GPR.
*/
Reg::Gpr Register::get_gpr() const {
assert(get_kind() == Reg::GPR);
uint16_t kind = id & REG_IDX_MASK;
assert(kind < Reg::MAX_GPR);
return (Reg::Gpr)(kind);
}
/*!
* Get the FPR number. Must be an FPR.
*/
uint32_t Register::get_fpr() const {
assert(get_kind() == Reg::FPR);
uint16_t kind = id & REG_IDX_MASK;
assert(kind < 32);
return kind;
}
/*!
* Get the VF number. Must be a VF.
*/
uint32_t Register::get_vf() const {
assert(get_kind() == Reg::VF);
uint16_t kind = id & REG_IDX_MASK;
assert(kind < 32);
return kind;
}
/*!
* Get the VI number. Must be a VI.
*/
uint32_t Register::get_vi() const {
assert(get_kind() == Reg::VI);
uint16_t kind = id & REG_IDX_MASK;
assert(kind < 32);
return kind;
}
/*!
* Get the COP0 number. Must be a COP0.
*/
Reg::Cop0 Register::get_cop0() const {
assert(get_kind() == Reg::COP0);
uint16_t kind = id & REG_IDX_MASK;
assert(kind < Reg::MAX_COP0);
return (Reg::Cop0)(kind);
}
/*!
* Get the PCR number. Must be a PCR.
*/
uint32_t Register::get_special() const {
assert(get_kind() == Reg::SPECIAL);
uint16_t kind = id & REG_IDX_MASK;
assert(kind < Reg::MAX_SPECIAL);
return kind;
}
bool Register::operator==(const Register& other) const {
return id == other.id;
}
bool Register::operator!=(const Register& other) const {
return id != other.id;
}
bool Register::allowed_local_gpr() const {
if (get_kind() != Reg::GPR) {
return false;
}
return Reg::allowed_local_gprs[get_gpr()];
}
} // namespace decompiler