MCPcopy Create free account
hub / github.com/N64Recomp/N64Recomp / analyze_instruction

Function analyze_instruction

src/analysis.cpp:59–265  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

57using RegId = rabbitizer::Registers::Cpu::GprO32;
58
59bool analyze_instruction(const rabbitizer::InstructionCpu& instr, const N64Recomp::Function& func, N64Recomp::FunctionStats& stats,
60 RegState reg_states[32], std::vector<RegState>& stack_states, bool is_got_addr_defined) {
61 // Temporary register state for tracking the register being operated on
62 RegState temp{};
63
64 int rd = (int)instr.GetO32_rd();
65 int rs = (int)instr.GetO32_rs();
66 int base = rs;
67 int rt = (int)instr.GetO32_rt();
68 int sa = (int)instr.Get_sa();
69
70 uint16_t imm = instr.Get_immediate();
71
72 auto check_move = [&]() {
73 if (rs == 0) {
74 // rs is zero so copy rt to rd
75 reg_states[rd] = reg_states[rt];
76 } else if (rt == 0) {
77 // rt is zero so copy rs to rd
78 reg_states[rd] = reg_states[rs];
79 } else {
80 // Not a move, invalidate rd
81 reg_states[rd].invalidate();
82 }
83 };
84
85 switch (instr.getUniqueId()) {
86 case InstrId::cpu_lui:
87 // rt has been completely overwritten, so invalidate it
88 reg_states[rt].invalidate();
89 reg_states[rt].prev_lui = (int16_t)imm << 16;
90 reg_states[rt].valid_lui = true;
91 break;
92 case InstrId::cpu_addiu:
93 // The target reg is a copy of the source reg plus an immediate, so copy the source reg's state
94 reg_states[rt] = reg_states[rs];
95 // Set the addiu state if and only if there hasn't been an addiu already
96 if (!reg_states[rt].valid_addiu) {
97 reg_states[rt].prev_addiu_vram = (int16_t)imm;
98 reg_states[rt].valid_addiu = true;
99 } else {
100 // Otherwise, there have been 2 or more consecutive addius so invalidate the whole register
101 reg_states[rt].invalidate();
102 }
103 break;
104 case InstrId::cpu_addu:
105 // rd has been completely overwritten, so invalidate it
106 temp.invalidate();
107 if (reg_states[rs].valid_got_offset != reg_states[rt].valid_got_offset) {
108 // Track which of the two registers has the valid GOT offset state and which is the addend
109 int valid_got_offset_reg = reg_states[rs].valid_got_offset ? rs : rt;
110 int addend_reg = reg_states[rs].valid_got_offset ? rt : rs;
111
112 // Copy the got offset reg's state into the destination reg, then set the destination reg's addend to the other operand
113 temp = reg_states[valid_got_offset_reg];
114 temp.valid_addend = true;
115 temp.prev_addend_reg = addend_reg;
116 temp.prev_addu_vram = instr.getVram();

Callers 1

analyze_functionMethod · 0.85

Calls 1

invalidateMethod · 0.80

Tested by

no test coverage detected