mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 21:27:52 -04:00
78cde74d5a
* update readme deps * replace assert * bump timeout * fix memory corruption in kernel * use unknown if level name is invalid
189 lines
4.6 KiB
C++
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
|