1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 * Copyright (C) 2014-2021 Paul Cercueil <paul@crapouillou.net>
6 #ifndef __DISASSEMBLER_H__
7 #define __DISASSEMBLER_H__
11 #include "lightrec-config.h"
14 #define __packed __attribute__((packed))
17 #define BIT(x) (1ULL << (x))
19 /* Flags for all opcodes */
20 #define LIGHTREC_NO_DS BIT(0)
21 #define LIGHTREC_SYNC BIT(1)
23 /* Flags for LUI, ORI, ADDIU */
24 #define LIGHTREC_MOVI BIT(2)
26 /* Flags for load/store opcodes */
27 #define LIGHTREC_SMC BIT(2)
28 #define LIGHTREC_NO_INVALIDATE BIT(3)
29 #define LIGHTREC_NO_MASK BIT(4)
30 #define LIGHTREC_LOAD_DELAY BIT(5)
32 /* I/O mode for load/store opcodes */
33 #define LIGHTREC_IO_MODE_LSB 6
34 #define LIGHTREC_IO_MODE(x) ((x) << LIGHTREC_IO_MODE_LSB)
35 #define LIGHTREC_IO_UNKNOWN 0x0
36 #define LIGHTREC_IO_DIRECT 0x1
37 #define LIGHTREC_IO_HW 0x2
38 #define LIGHTREC_IO_RAM 0x3
39 #define LIGHTREC_IO_BIOS 0x4
40 #define LIGHTREC_IO_SCRATCH 0x5
41 #define LIGHTREC_IO_DIRECT_HW 0x6
42 #define LIGHTREC_IO_MASK LIGHTREC_IO_MODE(0x7)
43 #define LIGHTREC_FLAGS_GET_IO_MODE(x) \
44 (((x) & LIGHTREC_IO_MASK) >> LIGHTREC_IO_MODE_LSB)
46 /* Flags for branches */
47 #define LIGHTREC_EMULATE_BRANCH BIT(2)
48 #define LIGHTREC_LOCAL_BRANCH BIT(3)
50 /* Flags for div/mult opcodes */
51 #define LIGHTREC_NO_LO BIT(2)
52 #define LIGHTREC_NO_HI BIT(3)
53 #define LIGHTREC_NO_DIV_CHECK BIT(4)
55 #define LIGHTREC_REG_RS_LSB 26
56 #define LIGHTREC_REG_RS(x) ((x) << LIGHTREC_REG_RS_LSB)
57 #define LIGHTREC_REG_RS_MASK LIGHTREC_REG_RS(0x3)
58 #define LIGHTREC_FLAGS_GET_RS(x) \
59 (((x) & LIGHTREC_REG_RS_MASK) >> LIGHTREC_REG_RS_LSB)
61 #define LIGHTREC_REG_RT_LSB 28
62 #define LIGHTREC_REG_RT(x) ((x) << LIGHTREC_REG_RT_LSB)
63 #define LIGHTREC_REG_RT_MASK LIGHTREC_REG_RT(0x3)
64 #define LIGHTREC_FLAGS_GET_RT(x) \
65 (((x) & LIGHTREC_REG_RT_MASK) >> LIGHTREC_REG_RT_LSB)
67 #define LIGHTREC_REG_RD_LSB 30
68 #define LIGHTREC_REG_RD(x) ((x) << LIGHTREC_REG_RD_LSB)
69 #define LIGHTREC_REG_RD_MASK LIGHTREC_REG_RD(0x3)
70 #define LIGHTREC_FLAGS_GET_RD(x) \
71 (((x) & LIGHTREC_REG_RD_MASK) >> LIGHTREC_REG_RD_LSB)
73 #define LIGHTREC_REG_NOOP 0x0
74 #define LIGHTREC_REG_UNLOAD 0x1
75 #define LIGHTREC_REG_DISCARD 0x2
76 #define LIGHTREC_REG_CLEAN 0x3
80 enum standard_opcodes {
116 OP_META_MULT2 = 0x19,
117 OP_META_MULTU2 = 0x1a,
122 enum special_opcodes {
123 OP_SPECIAL_SLL = 0x00,
124 OP_SPECIAL_SRL = 0x02,
125 OP_SPECIAL_SRA = 0x03,
126 OP_SPECIAL_SLLV = 0x04,
127 OP_SPECIAL_SRLV = 0x06,
128 OP_SPECIAL_SRAV = 0x07,
129 OP_SPECIAL_JR = 0x08,
130 OP_SPECIAL_JALR = 0x09,
131 OP_SPECIAL_SYSCALL = 0x0c,
132 OP_SPECIAL_BREAK = 0x0d,
133 OP_SPECIAL_MFHI = 0x10,
134 OP_SPECIAL_MTHI = 0x11,
135 OP_SPECIAL_MFLO = 0x12,
136 OP_SPECIAL_MTLO = 0x13,
137 OP_SPECIAL_MULT = 0x18,
138 OP_SPECIAL_MULTU = 0x19,
139 OP_SPECIAL_DIV = 0x1a,
140 OP_SPECIAL_DIVU = 0x1b,
141 OP_SPECIAL_ADD = 0x20,
142 OP_SPECIAL_ADDU = 0x21,
143 OP_SPECIAL_SUB = 0x22,
144 OP_SPECIAL_SUBU = 0x23,
145 OP_SPECIAL_AND = 0x24,
146 OP_SPECIAL_OR = 0x25,
147 OP_SPECIAL_XOR = 0x26,
148 OP_SPECIAL_NOR = 0x27,
149 OP_SPECIAL_SLT = 0x2a,
150 OP_SPECIAL_SLTU = 0x2b,
153 enum regimm_opcodes {
154 OP_REGIMM_BLTZ = 0x00,
155 OP_REGIMM_BGEZ = 0x01,
156 OP_REGIMM_BLTZAL = 0x10,
157 OP_REGIMM_BGEZAL = 0x11,
194 enum cp2_basic_opcodes {
195 OP_CP2_BASIC_MFC2 = 0x00,
196 OP_CP2_BASIC_CFC2 = 0x02,
197 OP_CP2_BASIC_MTC2 = 0x04,
198 OP_CP2_BASIC_CTC2 = 0x06,
211 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
229 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
243 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
253 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
271 /* Keep in sync with struct opcode */
280 /* Keep this union at the first position */
284 /* Keep in sync with union code */
299 void lightrec_print_disassembly(const struct block *block, const u32 *code);
301 static inline _Bool op_flag_no_ds(u32 flags)
303 return OPT_SWITCH_DELAY_SLOTS && (flags & LIGHTREC_NO_DS);
306 static inline _Bool op_flag_sync(u32 flags)
308 return OPT_LOCAL_BRANCHES && (flags & LIGHTREC_SYNC);
311 static inline _Bool op_flag_smc(u32 flags)
313 return OPT_FLAG_IO && (flags & LIGHTREC_SMC);
316 static inline _Bool op_flag_no_invalidate(u32 flags)
318 return OPT_FLAG_IO && (flags & LIGHTREC_NO_INVALIDATE);
321 static inline _Bool op_flag_no_mask(u32 flags)
323 return OPT_FLAG_IO && (flags & LIGHTREC_NO_MASK);
326 static inline _Bool op_flag_load_delay(u32 flags)
328 return OPT_HANDLE_LOAD_DELAYS && (flags & LIGHTREC_LOAD_DELAY);
331 static inline _Bool op_flag_emulate_branch(u32 flags)
333 return OPT_DETECT_IMPOSSIBLE_BRANCHES &&
334 (flags & LIGHTREC_EMULATE_BRANCH);
337 static inline _Bool op_flag_local_branch(u32 flags)
339 return OPT_LOCAL_BRANCHES && (flags & LIGHTREC_LOCAL_BRANCH);
342 static inline _Bool op_flag_no_lo(u32 flags)
344 return OPT_FLAG_MULT_DIV && (flags & LIGHTREC_NO_LO);
347 static inline _Bool op_flag_no_hi(u32 flags)
349 return OPT_FLAG_MULT_DIV && (flags & LIGHTREC_NO_HI);
352 static inline _Bool op_flag_no_div_check(u32 flags)
354 return OPT_FLAG_MULT_DIV && (flags & LIGHTREC_NO_DIV_CHECK);
357 #endif /* __DISASSEMBLER_H__ */