mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 21:27:52 -04:00
ddd60fca48
- fix issue described in https://github.com/open-goal/jak-project/issues/1939 - fix `text`, which was manually patched with the wrong offset (was reading the symbol value off by one byte) - clean up some random useless prints - make the offline tests keep trying if there's a comparison error, clean up the output a bit so the diffs are all at the end.
114 lines
3.5 KiB
C++
114 lines
3.5 KiB
C++
#pragma once
|
|
|
|
/*!
|
|
* @file Instruction.h
|
|
* An EE instruction, represented as an operation, plus a list of source/destination atoms.
|
|
* Can print itself (within the context of a LinkedObjectFile).
|
|
*/
|
|
|
|
#include <vector>
|
|
|
|
#include "OpcodeInfo.h"
|
|
#include "Register.h"
|
|
|
|
namespace decompiler {
|
|
struct DecompilerLabel;
|
|
|
|
constexpr int MAX_INSTRUCTION_SOURCE = 4;
|
|
constexpr int MAX_INTRUCTION_DEST = 1;
|
|
|
|
// An "atom", representing a single register, immediate, etc... for use in an Instruction.
|
|
struct InstructionAtom {
|
|
enum AtomKind {
|
|
REGISTER, // An EE Register
|
|
IMM, // An immediate value (stored as int32)
|
|
IMM_SYM, // An immediate value (a symbolic link)
|
|
IMM_SYM_VAL_PTR, // pointer to value of a symbol
|
|
LABEL, // A label in a LinkedObjectFile
|
|
VU_ACC, // The VU0 Accumulator
|
|
VU_Q, // The VU0 Q Register
|
|
VF_FIELD, // Field specifier
|
|
INVALID
|
|
} kind = INVALID;
|
|
|
|
void set_reg(Register r);
|
|
void set_imm(int32_t i);
|
|
void set_label(int id);
|
|
void set_vu_q();
|
|
void set_vu_acc();
|
|
void set_sym(const std::string& _sym);
|
|
void set_sym_val_ptr(const std::string& _sym);
|
|
void set_vf_field(uint32_t value);
|
|
|
|
Register get_reg() const;
|
|
int32_t get_imm() const;
|
|
int32_t get_vf_field() const;
|
|
int get_label() const;
|
|
std::string get_sym() const;
|
|
|
|
std::string to_string(const std::vector<DecompilerLabel>& labels) const;
|
|
|
|
bool is_reg() const { return kind == REGISTER; }
|
|
bool is_imm() const { return kind == IMM; }
|
|
bool is_label() const { return kind == LABEL; }
|
|
bool is_sym() const { return kind == IMM_SYM || kind == IMM_SYM_VAL_PTR; }
|
|
|
|
bool is_reg(Register r) const { return kind == REGISTER && reg == r; }
|
|
bool is_imm(int32_t i) const { return kind == IMM && imm == i; }
|
|
bool is_sym(const std::string& name) const { return is_sym() && name == sym; }
|
|
|
|
bool operator==(const InstructionAtom& other) const;
|
|
bool operator!=(const InstructionAtom& other) const { return !((*this) == other); }
|
|
|
|
private:
|
|
int32_t imm;
|
|
int label_id;
|
|
Register reg;
|
|
std::string sym;
|
|
};
|
|
|
|
// An "Instruction", consisting of a "kind" (the opcode), and the source/destination atoms it
|
|
// operates on.
|
|
class Instruction {
|
|
public:
|
|
InstructionKind kind = InstructionKind::UNKNOWN;
|
|
|
|
std::string op_name_to_string() const;
|
|
std::string to_string(const std::vector<DecompilerLabel>& labels) const;
|
|
bool is_valid() const;
|
|
|
|
void add_src(InstructionAtom& a);
|
|
void add_dst(InstructionAtom& a);
|
|
|
|
InstructionAtom& get_src(size_t idx);
|
|
InstructionAtom& get_dst(size_t idx);
|
|
const InstructionAtom& get_src(size_t idx) const;
|
|
const InstructionAtom& get_dst(size_t idx) const;
|
|
|
|
// source and destination atoms
|
|
uint8_t n_src = 0, n_dst = 0;
|
|
InstructionAtom src[MAX_INSTRUCTION_SOURCE];
|
|
InstructionAtom dst[MAX_INTRUCTION_DEST];
|
|
|
|
InstructionAtom& get_imm_src();
|
|
int32_t get_imm_src_int();
|
|
|
|
const OpcodeInfo& get_info() const;
|
|
|
|
int get_label_target() const;
|
|
|
|
bool operator==(const Instruction& other) const;
|
|
bool operator!=(const Instruction& other) const { return !((*this) == other); }
|
|
|
|
// extra fields for some COP2 instructions.
|
|
// this is stored like in the PS2 instruction, which is different from intel
|
|
uint8_t cop2_dest = 0xff; // 0xff indicates "don't print dest"
|
|
uint8_t cop2_bc = 0xff; // 0xff indicates "don't print bc"
|
|
uint8_t il = 0xff; // 0xff indicates "don't print il"
|
|
|
|
char cop2_bc_to_char() const;
|
|
std::string cop2_dest_to_char() const;
|
|
int cop2_dest_mask_intel() const;
|
|
};
|
|
} // namespace decompiler
|