psxmem: Add support for Lightrec's custom mem init sequence
[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_SMC            BIT(5)
27 #define LIGHTREC_NO_INVALIDATE  BIT(6)
28 #define LIGHTREC_NO_MASK        BIT(7)
29
30 /* I/O mode for load/store opcodes */
31 #define LIGHTREC_IO_MODE_LSB    8
32 #define LIGHTREC_IO_MODE(x)     ((x) << LIGHTREC_IO_MODE_LSB)
33 #define LIGHTREC_IO_UNKNOWN     0x0
34 #define LIGHTREC_IO_DIRECT      0x1
35 #define LIGHTREC_IO_HW          0x2
36 #define LIGHTREC_IO_RAM         0x3
37 #define LIGHTREC_IO_BIOS        0x4
38 #define LIGHTREC_IO_SCRATCH     0x5
39 #define LIGHTREC_IO_MASK        LIGHTREC_IO_MODE(0x7)
40 #define LIGHTREC_FLAGS_GET_IO_MODE(x) \
41         (((x) & LIGHTREC_IO_MASK) >> LIGHTREC_IO_MODE_LSB)
42
43 /* Flags for branches */
44 #define LIGHTREC_EMULATE_BRANCH BIT(5)
45 #define LIGHTREC_LOCAL_BRANCH   BIT(6)
46
47 /* Flags for div/mult opcodes */
48 #define LIGHTREC_NO_LO          BIT(5)
49 #define LIGHTREC_NO_HI          BIT(6)
50 #define LIGHTREC_NO_DIV_CHECK   BIT(7)
51
52 struct block;
53
54 enum standard_opcodes {
55         OP_SPECIAL              = 0x00,
56         OP_REGIMM               = 0x01,
57         OP_J                    = 0x02,
58         OP_JAL                  = 0x03,
59         OP_BEQ                  = 0x04,
60         OP_BNE                  = 0x05,
61         OP_BLEZ                 = 0x06,
62         OP_BGTZ                 = 0x07,
63         OP_ADDI                 = 0x08,
64         OP_ADDIU                = 0x09,
65         OP_SLTI                 = 0x0a,
66         OP_SLTIU                = 0x0b,
67         OP_ANDI                 = 0x0c,
68         OP_ORI                  = 0x0d,
69         OP_XORI                 = 0x0e,
70         OP_LUI                  = 0x0f,
71         OP_CP0                  = 0x10,
72         OP_CP2                  = 0x12,
73         OP_LB                   = 0x20,
74         OP_LH                   = 0x21,
75         OP_LWL                  = 0x22,
76         OP_LW                   = 0x23,
77         OP_LBU                  = 0x24,
78         OP_LHU                  = 0x25,
79         OP_LWR                  = 0x26,
80         OP_SB                   = 0x28,
81         OP_SH                   = 0x29,
82         OP_SWL                  = 0x2a,
83         OP_SW                   = 0x2b,
84         OP_SWR                  = 0x2e,
85         OP_LWC2                 = 0x32,
86         OP_SWC2                 = 0x3a,
87
88         OP_META_MOV             = 0x16,
89
90         OP_META_EXTC            = 0x17,
91         OP_META_EXTS            = 0x18,
92 };
93
94 enum special_opcodes {
95         OP_SPECIAL_SLL          = 0x00,
96         OP_SPECIAL_SRL          = 0x02,
97         OP_SPECIAL_SRA          = 0x03,
98         OP_SPECIAL_SLLV         = 0x04,
99         OP_SPECIAL_SRLV         = 0x06,
100         OP_SPECIAL_SRAV         = 0x07,
101         OP_SPECIAL_JR           = 0x08,
102         OP_SPECIAL_JALR         = 0x09,
103         OP_SPECIAL_SYSCALL      = 0x0c,
104         OP_SPECIAL_BREAK        = 0x0d,
105         OP_SPECIAL_MFHI         = 0x10,
106         OP_SPECIAL_MTHI         = 0x11,
107         OP_SPECIAL_MFLO         = 0x12,
108         OP_SPECIAL_MTLO         = 0x13,
109         OP_SPECIAL_MULT         = 0x18,
110         OP_SPECIAL_MULTU        = 0x19,
111         OP_SPECIAL_DIV          = 0x1a,
112         OP_SPECIAL_DIVU         = 0x1b,
113         OP_SPECIAL_ADD          = 0x20,
114         OP_SPECIAL_ADDU         = 0x21,
115         OP_SPECIAL_SUB          = 0x22,
116         OP_SPECIAL_SUBU         = 0x23,
117         OP_SPECIAL_AND          = 0x24,
118         OP_SPECIAL_OR           = 0x25,
119         OP_SPECIAL_XOR          = 0x26,
120         OP_SPECIAL_NOR          = 0x27,
121         OP_SPECIAL_SLT          = 0x2a,
122         OP_SPECIAL_SLTU         = 0x2b,
123 };
124
125 enum regimm_opcodes {
126         OP_REGIMM_BLTZ          = 0x00,
127         OP_REGIMM_BGEZ          = 0x01,
128         OP_REGIMM_BLTZAL        = 0x10,
129         OP_REGIMM_BGEZAL        = 0x11,
130 };
131
132 enum cp0_opcodes {
133         OP_CP0_MFC0             = 0x00,
134         OP_CP0_CFC0             = 0x02,
135         OP_CP0_MTC0             = 0x04,
136         OP_CP0_CTC0             = 0x06,
137         OP_CP0_RFE              = 0x10,
138 };
139
140 enum cp2_opcodes {
141         OP_CP2_BASIC            = 0x00,
142 };
143
144 enum cp2_basic_opcodes {
145         OP_CP2_BASIC_MFC2       = 0x00,
146         OP_CP2_BASIC_CFC2       = 0x02,
147         OP_CP2_BASIC_MTC2       = 0x04,
148         OP_CP2_BASIC_CTC2       = 0x06,
149 };
150
151 struct opcode_r {
152 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
153         u32 zero :6;
154         u32 rs   :5;
155         u32 rt   :5;
156         u32 rd   :5;
157         u32 imm  :5;
158         u32 op   :6;
159 #else
160         u32 op   :6;
161         u32 imm  :5;
162         u32 rd   :5;
163         u32 rt   :5;
164         u32 rs   :5;
165         u32 zero :6;
166 #endif
167 } __packed;
168
169 struct opcode_i {
170 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
171         u32 op  :6;
172         u32 rs  :5;
173         u32 rt  :5;
174         u32 imm :16;
175 #else
176         u32 imm :16;
177         u32 rt  :5;
178         u32 rs  :5;
179         u32 op  :6;
180 #endif
181 } __packed;
182
183 struct opcode_j {
184 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
185         u32 op  :6;
186         u32 imm :26;
187 #else
188         u32 imm :26;
189         u32 op  :6;
190 #endif
191 } __packed;
192
193 union code {
194         /* Keep in sync with struct opcode */
195         u32 opcode;
196         struct opcode_r r;
197         struct opcode_i i;
198         struct opcode_j j;
199 };
200
201 struct opcode {
202         /* Keep this union at the first position */
203         union {
204                 union code c;
205
206                 /* Keep in sync with union code */
207                 u32 opcode;
208                 struct opcode_r r;
209                 struct opcode_i i;
210                 struct opcode_j j;
211         };
212         u16 flags;
213 };
214
215 void lightrec_print_disassembly(const struct block *block, const u32 *code);
216
217 #endif /* __DISASSEMBLER_H__ */