Update lightrec 20220716 (#672)
[pcsx_rearmed.git] / deps / lightrec / disassembler.h
CommitLineData
98fa08a5 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
d16005f8 2/*
98fa08a5 3 * Copyright (C) 2014-2021 Paul Cercueil <paul@crapouillou.net>
d16005f8
PC
4 */
5
6#ifndef __DISASSEMBLER_H__
7#define __DISASSEMBLER_H__
8
9#include "debug.h"
10#include "lightrec.h"
03535202 11#include "lightrec-config.h"
d16005f8
PC
12
13#ifndef __packed
14#define __packed __attribute__((packed))
15#endif
16
98fa08a5
PC
17#define BIT(x) (1ULL << (x))
18
19/* Flags for all opcodes */
20#define LIGHTREC_NO_DS BIT(0)
03535202 21#define LIGHTREC_SYNC BIT(1)
98fa08a5
PC
22
23/* Flags for load/store opcodes */
03535202
PC
24#define LIGHTREC_SMC BIT(2)
25#define LIGHTREC_NO_INVALIDATE BIT(3)
26#define LIGHTREC_NO_MASK BIT(4)
22eee2ac
PC
27
28/* I/O mode for load/store opcodes */
03535202 29#define LIGHTREC_IO_MODE_LSB 5
22eee2ac
PC
30#define LIGHTREC_IO_MODE(x) ((x) << LIGHTREC_IO_MODE_LSB)
31#define LIGHTREC_IO_UNKNOWN 0x0
32#define LIGHTREC_IO_DIRECT 0x1
33#define LIGHTREC_IO_HW 0x2
34#define LIGHTREC_IO_RAM 0x3
35#define LIGHTREC_IO_BIOS 0x4
36#define LIGHTREC_IO_SCRATCH 0x5
37#define LIGHTREC_IO_MASK LIGHTREC_IO_MODE(0x7)
38#define LIGHTREC_FLAGS_GET_IO_MODE(x) \
39 (((x) & LIGHTREC_IO_MASK) >> LIGHTREC_IO_MODE_LSB)
98fa08a5
PC
40
41/* Flags for branches */
03535202
PC
42#define LIGHTREC_EMULATE_BRANCH BIT(2)
43#define LIGHTREC_LOCAL_BRANCH BIT(3)
98fa08a5
PC
44
45/* Flags for div/mult opcodes */
03535202
PC
46#define LIGHTREC_NO_LO BIT(2)
47#define LIGHTREC_NO_HI BIT(3)
48#define LIGHTREC_NO_DIV_CHECK BIT(4)
49
50#define LIGHTREC_REG_RS_LSB 26
51#define LIGHTREC_REG_RS(x) ((x) << LIGHTREC_REG_RS_LSB)
52#define LIGHTREC_REG_RS_MASK LIGHTREC_REG_RS(0x3)
53#define LIGHTREC_FLAGS_GET_RS(x) \
54 (((x) & LIGHTREC_REG_RS_MASK) >> LIGHTREC_REG_RS_LSB)
55
56#define LIGHTREC_REG_RT_LSB 28
57#define LIGHTREC_REG_RT(x) ((x) << LIGHTREC_REG_RT_LSB)
58#define LIGHTREC_REG_RT_MASK LIGHTREC_REG_RT(0x3)
59#define LIGHTREC_FLAGS_GET_RT(x) \
60 (((x) & LIGHTREC_REG_RT_MASK) >> LIGHTREC_REG_RT_LSB)
61
62#define LIGHTREC_REG_RD_LSB 30
63#define LIGHTREC_REG_RD(x) ((x) << LIGHTREC_REG_RD_LSB)
64#define LIGHTREC_REG_RD_MASK LIGHTREC_REG_RD(0x3)
65#define LIGHTREC_FLAGS_GET_RD(x) \
66 (((x) & LIGHTREC_REG_RD_MASK) >> LIGHTREC_REG_RD_LSB)
67
68#define LIGHTREC_REG_NOOP 0x0
69#define LIGHTREC_REG_UNLOAD 0x1
70#define LIGHTREC_REG_DISCARD 0x2
71#define LIGHTREC_REG_CLEAN 0x3
d16005f8
PC
72
73struct block;
74
75enum standard_opcodes {
76 OP_SPECIAL = 0x00,
77 OP_REGIMM = 0x01,
78 OP_J = 0x02,
79 OP_JAL = 0x03,
80 OP_BEQ = 0x04,
81 OP_BNE = 0x05,
82 OP_BLEZ = 0x06,
83 OP_BGTZ = 0x07,
84 OP_ADDI = 0x08,
85 OP_ADDIU = 0x09,
86 OP_SLTI = 0x0a,
87 OP_SLTIU = 0x0b,
88 OP_ANDI = 0x0c,
89 OP_ORI = 0x0d,
90 OP_XORI = 0x0e,
91 OP_LUI = 0x0f,
92 OP_CP0 = 0x10,
93 OP_CP2 = 0x12,
94 OP_LB = 0x20,
95 OP_LH = 0x21,
96 OP_LWL = 0x22,
97 OP_LW = 0x23,
98 OP_LBU = 0x24,
99 OP_LHU = 0x25,
100 OP_LWR = 0x26,
101 OP_SB = 0x28,
102 OP_SH = 0x29,
103 OP_SWL = 0x2a,
104 OP_SW = 0x2b,
105 OP_SWR = 0x2e,
106 OP_LWC2 = 0x32,
107 OP_SWC2 = 0x3a,
108
d16005f8 109 OP_META_MOV = 0x16,
98fa08a5
PC
110
111 OP_META_EXTC = 0x17,
112 OP_META_EXTS = 0x18,
d16005f8
PC
113};
114
115enum special_opcodes {
116 OP_SPECIAL_SLL = 0x00,
117 OP_SPECIAL_SRL = 0x02,
118 OP_SPECIAL_SRA = 0x03,
119 OP_SPECIAL_SLLV = 0x04,
120 OP_SPECIAL_SRLV = 0x06,
121 OP_SPECIAL_SRAV = 0x07,
122 OP_SPECIAL_JR = 0x08,
123 OP_SPECIAL_JALR = 0x09,
124 OP_SPECIAL_SYSCALL = 0x0c,
125 OP_SPECIAL_BREAK = 0x0d,
126 OP_SPECIAL_MFHI = 0x10,
127 OP_SPECIAL_MTHI = 0x11,
128 OP_SPECIAL_MFLO = 0x12,
129 OP_SPECIAL_MTLO = 0x13,
130 OP_SPECIAL_MULT = 0x18,
131 OP_SPECIAL_MULTU = 0x19,
132 OP_SPECIAL_DIV = 0x1a,
133 OP_SPECIAL_DIVU = 0x1b,
134 OP_SPECIAL_ADD = 0x20,
135 OP_SPECIAL_ADDU = 0x21,
136 OP_SPECIAL_SUB = 0x22,
137 OP_SPECIAL_SUBU = 0x23,
138 OP_SPECIAL_AND = 0x24,
139 OP_SPECIAL_OR = 0x25,
140 OP_SPECIAL_XOR = 0x26,
141 OP_SPECIAL_NOR = 0x27,
142 OP_SPECIAL_SLT = 0x2a,
143 OP_SPECIAL_SLTU = 0x2b,
144};
145
146enum regimm_opcodes {
147 OP_REGIMM_BLTZ = 0x00,
148 OP_REGIMM_BGEZ = 0x01,
149 OP_REGIMM_BLTZAL = 0x10,
150 OP_REGIMM_BGEZAL = 0x11,
151};
152
153enum cp0_opcodes {
154 OP_CP0_MFC0 = 0x00,
155 OP_CP0_CFC0 = 0x02,
156 OP_CP0_MTC0 = 0x04,
157 OP_CP0_CTC0 = 0x06,
158 OP_CP0_RFE = 0x10,
159};
160
161enum cp2_opcodes {
162 OP_CP2_BASIC = 0x00,
163};
164
165enum cp2_basic_opcodes {
166 OP_CP2_BASIC_MFC2 = 0x00,
167 OP_CP2_BASIC_CFC2 = 0x02,
168 OP_CP2_BASIC_MTC2 = 0x04,
169 OP_CP2_BASIC_CTC2 = 0x06,
170};
171
172struct opcode_r {
173#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
174 u32 zero :6;
175 u32 rs :5;
176 u32 rt :5;
177 u32 rd :5;
178 u32 imm :5;
179 u32 op :6;
180#else
181 u32 op :6;
182 u32 imm :5;
183 u32 rd :5;
184 u32 rt :5;
185 u32 rs :5;
186 u32 zero :6;
187#endif
188} __packed;
189
190struct opcode_i {
191#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
192 u32 op :6;
193 u32 rs :5;
194 u32 rt :5;
195 u32 imm :16;
196#else
197 u32 imm :16;
198 u32 rt :5;
199 u32 rs :5;
200 u32 op :6;
201#endif
202} __packed;
203
204struct opcode_j {
205#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
206 u32 op :6;
207 u32 imm :26;
208#else
209 u32 imm :26;
210 u32 op :6;
211#endif
212} __packed;
213
214union code {
215 /* Keep in sync with struct opcode */
216 u32 opcode;
217 struct opcode_r r;
218 struct opcode_i i;
219 struct opcode_j j;
220};
221
222struct opcode {
223 /* Keep this union at the first position */
224 union {
225 union code c;
226
227 /* Keep in sync with union code */
228 u32 opcode;
229 struct opcode_r r;
230 struct opcode_i i;
231 struct opcode_j j;
232 };
03535202 233 u32 flags;
d16005f8
PC
234};
235
98fa08a5 236void lightrec_print_disassembly(const struct block *block, const u32 *code);
d16005f8 237
03535202
PC
238static inline _Bool op_flag_no_ds(u32 flags)
239{
240 return OPT_SWITCH_DELAY_SLOTS && (flags & LIGHTREC_NO_DS);
241}
242
243static inline _Bool op_flag_sync(u32 flags)
244{
245 return OPT_LOCAL_BRANCHES && (flags & LIGHTREC_SYNC);
246}
247
248static inline _Bool op_flag_smc(u32 flags)
249{
250 return OPT_FLAG_STORES && (flags & LIGHTREC_SMC);
251}
252
253static inline _Bool op_flag_no_invalidate(u32 flags)
254{
255 return (OPT_FLAG_IO || OPT_FLAG_STORES) &&
256 (flags & LIGHTREC_NO_INVALIDATE);
257}
258
259static inline _Bool op_flag_no_mask(u32 flags)
260{
261 return OPT_FLAG_IO && (flags & LIGHTREC_NO_MASK);
262}
263
264static inline _Bool op_flag_emulate_branch(u32 flags)
265{
266 return OPT_DETECT_IMPOSSIBLE_BRANCHES &&
267 (flags & LIGHTREC_EMULATE_BRANCH);
268}
269
270static inline _Bool op_flag_local_branch(u32 flags)
271{
272 return OPT_LOCAL_BRANCHES && (flags & LIGHTREC_LOCAL_BRANCH);
273}
274
275static inline _Bool op_flag_no_lo(u32 flags)
276{
277 return OPT_FLAG_MULT_DIV && (flags & LIGHTREC_NO_LO);
278}
279
280static inline _Bool op_flag_no_hi(u32 flags)
281{
282 return OPT_FLAG_MULT_DIV && (flags & LIGHTREC_NO_HI);
283}
284
285static inline _Bool op_flag_no_div_check(u32 flags)
286{
287 return OPT_FLAG_MULT_DIV && (flags & LIGHTREC_NO_DIV_CHECK);
288}
289
d16005f8 290#endif /* __DISASSEMBLER_H__ */