ae2af7eafaf99c1f5fafe951581bd00c535abc04
[pcsx_rearmed.git] / deps / lightrec / disassembler.h
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /*
3  * Copyright (C) 2014-2021 Paul Cercueil <paul@crapouillou.net>
4  */
5
6 #ifndef __DISASSEMBLER_H__
7 #define __DISASSEMBLER_H__
8
9 #include "debug.h"
10 #include "lightrec.h"
11
12 #ifndef __packed
13 #define __packed __attribute__((packed))
14 #endif
15
16 #define BIT(x) (1ULL << (x))
17
18 /* Flags for all opcodes */
19 #define LIGHTREC_NO_DS          BIT(0)
20 #define LIGHTREC_UNLOAD_RS      BIT(1)
21 #define LIGHTREC_UNLOAD_RT      BIT(2)
22 #define LIGHTREC_UNLOAD_RD      BIT(3)
23 #define LIGHTREC_SYNC           BIT(4)
24
25 /* Flags for load/store opcodes */
26 #define LIGHTREC_DIRECT_IO      BIT(5)
27 #define LIGHTREC_HW_IO          BIT(6)
28 #define LIGHTREC_SMC            BIT(7)
29 #define LIGHTREC_NO_INVALIDATE  BIT(8)
30
31 /* Flags for branches */
32 #define LIGHTREC_EMULATE_BRANCH BIT(5)
33 #define LIGHTREC_LOCAL_BRANCH   BIT(6)
34
35 /* Flags for div/mult opcodes */
36 #define LIGHTREC_NO_LO          BIT(5)
37 #define LIGHTREC_NO_HI          BIT(6)
38 #define LIGHTREC_NO_DIV_CHECK   BIT(7)
39
40 struct block;
41
42 enum standard_opcodes {
43         OP_SPECIAL              = 0x00,
44         OP_REGIMM               = 0x01,
45         OP_J                    = 0x02,
46         OP_JAL                  = 0x03,
47         OP_BEQ                  = 0x04,
48         OP_BNE                  = 0x05,
49         OP_BLEZ                 = 0x06,
50         OP_BGTZ                 = 0x07,
51         OP_ADDI                 = 0x08,
52         OP_ADDIU                = 0x09,
53         OP_SLTI                 = 0x0a,
54         OP_SLTIU                = 0x0b,
55         OP_ANDI                 = 0x0c,
56         OP_ORI                  = 0x0d,
57         OP_XORI                 = 0x0e,
58         OP_LUI                  = 0x0f,
59         OP_CP0                  = 0x10,
60         OP_CP2                  = 0x12,
61         OP_LB                   = 0x20,
62         OP_LH                   = 0x21,
63         OP_LWL                  = 0x22,
64         OP_LW                   = 0x23,
65         OP_LBU                  = 0x24,
66         OP_LHU                  = 0x25,
67         OP_LWR                  = 0x26,
68         OP_SB                   = 0x28,
69         OP_SH                   = 0x29,
70         OP_SWL                  = 0x2a,
71         OP_SW                   = 0x2b,
72         OP_SWR                  = 0x2e,
73         OP_LWC2                 = 0x32,
74         OP_SWC2                 = 0x3a,
75
76         OP_META_MOV             = 0x16,
77
78         OP_META_EXTC            = 0x17,
79         OP_META_EXTS            = 0x18,
80 };
81
82 enum special_opcodes {
83         OP_SPECIAL_SLL          = 0x00,
84         OP_SPECIAL_SRL          = 0x02,
85         OP_SPECIAL_SRA          = 0x03,
86         OP_SPECIAL_SLLV         = 0x04,
87         OP_SPECIAL_SRLV         = 0x06,
88         OP_SPECIAL_SRAV         = 0x07,
89         OP_SPECIAL_JR           = 0x08,
90         OP_SPECIAL_JALR         = 0x09,
91         OP_SPECIAL_SYSCALL      = 0x0c,
92         OP_SPECIAL_BREAK        = 0x0d,
93         OP_SPECIAL_MFHI         = 0x10,
94         OP_SPECIAL_MTHI         = 0x11,
95         OP_SPECIAL_MFLO         = 0x12,
96         OP_SPECIAL_MTLO         = 0x13,
97         OP_SPECIAL_MULT         = 0x18,
98         OP_SPECIAL_MULTU        = 0x19,
99         OP_SPECIAL_DIV          = 0x1a,
100         OP_SPECIAL_DIVU         = 0x1b,
101         OP_SPECIAL_ADD          = 0x20,
102         OP_SPECIAL_ADDU         = 0x21,
103         OP_SPECIAL_SUB          = 0x22,
104         OP_SPECIAL_SUBU         = 0x23,
105         OP_SPECIAL_AND          = 0x24,
106         OP_SPECIAL_OR           = 0x25,
107         OP_SPECIAL_XOR          = 0x26,
108         OP_SPECIAL_NOR          = 0x27,
109         OP_SPECIAL_SLT          = 0x2a,
110         OP_SPECIAL_SLTU         = 0x2b,
111 };
112
113 enum regimm_opcodes {
114         OP_REGIMM_BLTZ          = 0x00,
115         OP_REGIMM_BGEZ          = 0x01,
116         OP_REGIMM_BLTZAL        = 0x10,
117         OP_REGIMM_BGEZAL        = 0x11,
118 };
119
120 enum cp0_opcodes {
121         OP_CP0_MFC0             = 0x00,
122         OP_CP0_CFC0             = 0x02,
123         OP_CP0_MTC0             = 0x04,
124         OP_CP0_CTC0             = 0x06,
125         OP_CP0_RFE              = 0x10,
126 };
127
128 enum cp2_opcodes {
129         OP_CP2_BASIC            = 0x00,
130 };
131
132 enum cp2_basic_opcodes {
133         OP_CP2_BASIC_MFC2       = 0x00,
134         OP_CP2_BASIC_CFC2       = 0x02,
135         OP_CP2_BASIC_MTC2       = 0x04,
136         OP_CP2_BASIC_CTC2       = 0x06,
137 };
138
139 struct opcode_r {
140 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
141         u32 zero :6;
142         u32 rs   :5;
143         u32 rt   :5;
144         u32 rd   :5;
145         u32 imm  :5;
146         u32 op   :6;
147 #else
148         u32 op   :6;
149         u32 imm  :5;
150         u32 rd   :5;
151         u32 rt   :5;
152         u32 rs   :5;
153         u32 zero :6;
154 #endif
155 } __packed;
156
157 struct opcode_i {
158 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
159         u32 op  :6;
160         u32 rs  :5;
161         u32 rt  :5;
162         u32 imm :16;
163 #else
164         u32 imm :16;
165         u32 rt  :5;
166         u32 rs  :5;
167         u32 op  :6;
168 #endif
169 } __packed;
170
171 struct opcode_j {
172 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
173         u32 op  :6;
174         u32 imm :26;
175 #else
176         u32 imm :26;
177         u32 op  :6;
178 #endif
179 } __packed;
180
181 union code {
182         /* Keep in sync with struct opcode */
183         u32 opcode;
184         struct opcode_r r;
185         struct opcode_i i;
186         struct opcode_j j;
187 };
188
189 struct opcode {
190         /* Keep this union at the first position */
191         union {
192                 union code c;
193
194                 /* Keep in sync with union code */
195                 u32 opcode;
196                 struct opcode_r r;
197                 struct opcode_i i;
198                 struct opcode_j j;
199         };
200         u16 flags;
201 };
202
203 void lightrec_print_disassembly(const struct block *block, const u32 *code);
204
205 #endif /* __DISASSEMBLER_H__ */