jak-project/decompiler/Disasm/Register.h
water111 78cde74d5a
update readme and fix always playing str (#1139)
* update readme deps

* replace assert

* bump timeout

* fix memory corruption in kernel

* use unknown if level name is invalid
2022-02-08 19:02:47 -05:00

189 lines
4.6 KiB
C++

#pragma once
/*!
* @file Register.h
* Representation of an EE register.
*/
#include <cstdint>
#include <string>
#include "common/util/Assert.h"
namespace decompiler {
// Namespace for register name constants
// Note on registers:
// Registers are assigned a unique Register ID as an integer from 0 to 164 (not including 164).
// Don't change these enums without updating the indexing scheme.
// It is important that each register is a unique register ID, and that we don't have gaps.
namespace Reg {
enum RegisterKind {
GPR = 0, // EE General purpose registers, these have nicknames (32 regs)
FPR = 1, // EE Floating point registers, just called f0 - f31 (32 regs)
VF = 2, // VU0 Floating point vector registers from EE, just called vf0 - vf31 (32 regs)
VI = 3, // VU0 Integer registers from EE, the first 16 are vi00 - vi15, the rest are control
// regs. (32 regs)
COP0 = 4, // EE COP0 Control Registers: full of fancy names (there are 32 of them) (32 regs)
SPECIAL = 5, // COP2 Q, ACC accessed from macro mode instructions and PCR
MAX_KIND = 6
};
// nicknames for GPRs
enum Gpr {
R0 = 0, // hardcoded to zero
AT = 1, // temp, not used by GOAL compiler, but used by GOAL's kernel inline assembly (an other
// places?)
V0 = 2, // return, temp
V1 = 3, // temp
A0 = 4, // arg0, temp
A1 = 5, // arg1, temp
A2 = 6, // arg2, temp
A3 = 7, // arg3, temp
T0 = 8, // arg4, temp
T1 = 9, // arg5, temp
T2 = 10, // arg6, temp
T3 = 11, // arg7, temp
T4 = 12, // temp
T5 = 13, // temp
T6 = 14, // temp
T7 = 15, // temp
S0 = 16, // saved
S1 = 17, // saved
S2 = 18, // saved
S3 = 19, // saved
S4 = 20, // saved
S5 = 21, // saved
S6 = 22, // process pointer
S7 = 23, // symbol table
T8 = 24, // temp
T9 = 25, // function pointer
K0 = 26, // reserved
K1 = 27, // reserved
GP = 28, // saved (C code uses this a global pointer)
SP = 29, // stack pointer
FP = 30, // global pointer (address of current function)
RA = 31, // return address
MAX_GPR = 32
};
// nicknames for COP0 registers
enum Cop0 {
INDEX = 0,
RANDOM = 1,
ENTRYLO0 = 2,
ENTRYLO1 = 3,
CONTEXT = 4,
PAGEMASK = 5,
WIRED = 6,
INVALID7 = 7,
BADVADDR = 8,
COUNT = 9,
ENTRYHI = 10,
COMPARE = 11,
COP0_STATUS = 12,
CAUSE = 13,
EPC = 14,
PRID = 15,
CONFIG = 16,
INVALID17 = 17,
INVALID18 = 18,
INVALID19 = 19,
INVALID20 = 20,
INVALID21 = 21,
INVALID22 = 22,
BADPADDR = 23,
DEBUG = 24,
PERF = 25,
INVALID26 = 26,
INVALID27 = 27,
TAGLO = 28,
TAGHI = 29,
ERROREPC = 30,
INVALID31 = 31,
MAX_COP0 = 32
};
// nicknames for COP2 Integer (VI) registers
// the first 16 are vi0 - vi15, so they don't have nicknames
enum Vi {
COP2_STATUS = 16,
MAC = 17,
CLIPPING = 18,
COP2_INVALID3 = 19,
R = 20,
I = 21,
Q = 22,
COP2_INVALID7 = 23,
COP2_INVALID8 = 24,
COP2_INVALID9 = 25,
TPC = 26,
CMSAR0 = 27,
FBRST = 28,
VPUSTAT = 29,
COP2_INVALID14 = 30,
CMSAR1 = 31,
MAX_COP2 = 32
};
enum SpecialRegisters {
PCR0 = 0,
PCR1 = 1,
MACRO_Q = 2,
MACRO_ACC = 3,
MAX_SPECIAL = 4,
};
const extern bool allowed_local_gprs[Reg::MAX_GPR];
constexpr int MAX_REG_ID = 32 * 5 + MAX_SPECIAL;
constexpr int MAX_VAR_REG_ID = 32 * 2; // gprs/fprs.
} // namespace Reg
// Representation of a register. Uses a 16-bit integer internally.
class Register {
public:
Register() = default;
Register(Reg::RegisterKind kind, uint32_t num);
explicit Register(int reg_id) {
ASSERT(reg_id < Reg::MAX_REG_ID);
id = reg_id;
}
Register(const std::string& name);
static Register get_arg_reg(int idx) {
ASSERT(idx >= 0 && idx < 8);
return Register(Reg::GPR, Reg::A0 + idx);
}
uint16_t reg_id() const { return id; }
const char* to_charp() const;
std::string to_string() const;
Reg::RegisterKind get_kind() const;
bool is_vu_float() const {
return get_kind() == Reg::VF ||
(get_kind() == Reg::SPECIAL &&
(get_special() == Reg::MACRO_Q || get_special() == Reg::MACRO_ACC));
}
Reg::Gpr get_gpr() const;
uint32_t get_fpr() const;
uint32_t get_vf() const;
uint32_t get_vi() const;
Reg::Cop0 get_cop0() const;
uint32_t get_special() const;
bool allowed_local_gpr() const;
bool operator==(const Register& other) const;
bool operator!=(const Register& other) const;
bool operator<(const Register& other) const { return id < other.id; }
struct hash {
auto operator()(const Register& x) const { return std::hash<uint16_t>()(x.id); }
};
private:
uint16_t id = -1;
};
} // namespace decompiler