git subrepo clone https://github.com/pcercuei/lightrec.git deps/lightrec
[pcsx_rearmed.git] / deps / lightrec / disassembler.h
1 /*
2  * Copyright (C) 2014 Paul Cercueil <paul@crapouillou.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  */
14
15 #ifndef __DISASSEMBLER_H__
16 #define __DISASSEMBLER_H__
17
18 #include "debug.h"
19 #include "lightrec.h"
20
21 #ifndef __packed
22 #define __packed __attribute__((packed))
23 #endif
24
25 #define LIGHTREC_DIRECT_IO      (1 << 0)
26 #define LIGHTREC_NO_INVALIDATE  (1 << 1)
27 #define LIGHTREC_NO_DS          (1 << 2)
28 #define LIGHTREC_SMC            (1 << 3)
29 #define LIGHTREC_EMULATE_BRANCH (1 << 4)
30 #define LIGHTREC_LOCAL_BRANCH   (1 << 5)
31 #define LIGHTREC_HW_IO          (1 << 6)
32 #define LIGHTREC_MULT32         (1 << 7)
33
34 struct block;
35
36 enum standard_opcodes {
37         OP_SPECIAL              = 0x00,
38         OP_REGIMM               = 0x01,
39         OP_J                    = 0x02,
40         OP_JAL                  = 0x03,
41         OP_BEQ                  = 0x04,
42         OP_BNE                  = 0x05,
43         OP_BLEZ                 = 0x06,
44         OP_BGTZ                 = 0x07,
45         OP_ADDI                 = 0x08,
46         OP_ADDIU                = 0x09,
47         OP_SLTI                 = 0x0a,
48         OP_SLTIU                = 0x0b,
49         OP_ANDI                 = 0x0c,
50         OP_ORI                  = 0x0d,
51         OP_XORI                 = 0x0e,
52         OP_LUI                  = 0x0f,
53         OP_CP0                  = 0x10,
54         OP_CP2                  = 0x12,
55         OP_LB                   = 0x20,
56         OP_LH                   = 0x21,
57         OP_LWL                  = 0x22,
58         OP_LW                   = 0x23,
59         OP_LBU                  = 0x24,
60         OP_LHU                  = 0x25,
61         OP_LWR                  = 0x26,
62         OP_SB                   = 0x28,
63         OP_SH                   = 0x29,
64         OP_SWL                  = 0x2a,
65         OP_SW                   = 0x2b,
66         OP_SWR                  = 0x2e,
67         OP_LWC2                 = 0x32,
68         OP_SWC2                 = 0x3a,
69
70         OP_META_REG_UNLOAD      = 0x11,
71
72         OP_META_BEQZ            = 0x14,
73         OP_META_BNEZ            = 0x15,
74
75         OP_META_MOV             = 0x16,
76         OP_META_SYNC            = 0x17,
77 };
78
79 enum special_opcodes {
80         OP_SPECIAL_SLL          = 0x00,
81         OP_SPECIAL_SRL          = 0x02,
82         OP_SPECIAL_SRA          = 0x03,
83         OP_SPECIAL_SLLV         = 0x04,
84         OP_SPECIAL_SRLV         = 0x06,
85         OP_SPECIAL_SRAV         = 0x07,
86         OP_SPECIAL_JR           = 0x08,
87         OP_SPECIAL_JALR         = 0x09,
88         OP_SPECIAL_SYSCALL      = 0x0c,
89         OP_SPECIAL_BREAK        = 0x0d,
90         OP_SPECIAL_MFHI         = 0x10,
91         OP_SPECIAL_MTHI         = 0x11,
92         OP_SPECIAL_MFLO         = 0x12,
93         OP_SPECIAL_MTLO         = 0x13,
94         OP_SPECIAL_MULT         = 0x18,
95         OP_SPECIAL_MULTU        = 0x19,
96         OP_SPECIAL_DIV          = 0x1a,
97         OP_SPECIAL_DIVU         = 0x1b,
98         OP_SPECIAL_ADD          = 0x20,
99         OP_SPECIAL_ADDU         = 0x21,
100         OP_SPECIAL_SUB          = 0x22,
101         OP_SPECIAL_SUBU         = 0x23,
102         OP_SPECIAL_AND          = 0x24,
103         OP_SPECIAL_OR           = 0x25,
104         OP_SPECIAL_XOR          = 0x26,
105         OP_SPECIAL_NOR          = 0x27,
106         OP_SPECIAL_SLT          = 0x2a,
107         OP_SPECIAL_SLTU         = 0x2b,
108 };
109
110 enum regimm_opcodes {
111         OP_REGIMM_BLTZ          = 0x00,
112         OP_REGIMM_BGEZ          = 0x01,
113         OP_REGIMM_BLTZAL        = 0x10,
114         OP_REGIMM_BGEZAL        = 0x11,
115 };
116
117 enum cp0_opcodes {
118         OP_CP0_MFC0             = 0x00,
119         OP_CP0_CFC0             = 0x02,
120         OP_CP0_MTC0             = 0x04,
121         OP_CP0_CTC0             = 0x06,
122         OP_CP0_RFE              = 0x10,
123 };
124
125 enum cp2_opcodes {
126         OP_CP2_BASIC            = 0x00,
127 };
128
129 enum cp2_basic_opcodes {
130         OP_CP2_BASIC_MFC2       = 0x00,
131         OP_CP2_BASIC_CFC2       = 0x02,
132         OP_CP2_BASIC_MTC2       = 0x04,
133         OP_CP2_BASIC_CTC2       = 0x06,
134 };
135
136 struct opcode_r {
137 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
138         u32 zero :6;
139         u32 rs   :5;
140         u32 rt   :5;
141         u32 rd   :5;
142         u32 imm  :5;
143         u32 op   :6;
144 #else
145         u32 op   :6;
146         u32 imm  :5;
147         u32 rd   :5;
148         u32 rt   :5;
149         u32 rs   :5;
150         u32 zero :6;
151 #endif
152 } __packed;
153
154 struct opcode_i {
155 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
156         u32 op  :6;
157         u32 rs  :5;
158         u32 rt  :5;
159         u32 imm :16;
160 #else
161         u32 imm :16;
162         u32 rt  :5;
163         u32 rs  :5;
164         u32 op  :6;
165 #endif
166 } __packed;
167
168 struct opcode_j {
169 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
170         u32 op  :6;
171         u32 imm :26;
172 #else
173         u32 imm :26;
174         u32 op  :6;
175 #endif
176 } __packed;
177
178 union code {
179         /* Keep in sync with struct opcode */
180         u32 opcode;
181         struct opcode_r r;
182         struct opcode_i i;
183         struct opcode_j j;
184 };
185
186 struct opcode {
187         /* Keep this union at the first position */
188         union {
189                 union code c;
190
191                 /* Keep in sync with union code */
192                 u32 opcode;
193                 struct opcode_r r;
194                 struct opcode_i i;
195                 struct opcode_j j;
196         };
197         u16 flags;
198         u16 offset;
199         struct opcode *next;
200 };
201
202 struct opcode * lightrec_disassemble(struct lightrec_state *state,
203                                      const u32 *src, unsigned int *len);
204 void lightrec_free_opcode_list(struct lightrec_state *state,
205                                struct opcode *list);
206
207 unsigned int lightrec_cycles_of_opcode(union code code);
208
209 void lightrec_print_disassembly(const struct block *block,
210                                 const u32 *code, unsigned int length);
211
212 #endif /* __DISASSEMBLER_H__ */