1use core::str;
2use std::fmt::Display;
3
4use serde::{Deserialize, Serialize};
5
6use crate::errors::DisassemblerError;
7
8#[repr(u8)]
9#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
10pub enum OpCode {
11 Lddw = 0x18,
12 Ldxb = 0x71,
13 Ldxh = 0x69,
14 Ldxw = 0x61,
15 Ldxdw = 0x79,
16 Stb = 0x72,
17 Sth = 0x6a,
18 Stw = 0x62,
19 Stdw = 0x7a,
20 Stxb = 0x73,
21 Stxh = 0x6b,
22 Stxw = 0x63,
23 Stxdw = 0x7b,
24 Add32Imm = 0x04,
25 Add32Reg = 0x0c,
26 Sub32Imm = 0x14,
27 Sub32Reg = 0x1c,
28 Mul32Imm = 0x24,
29 Mul32Reg = 0x2c,
30 Div32Imm = 0x34,
31 Div32Reg = 0x3c,
32 Or32Imm = 0x44,
33 Or32Reg = 0x4c,
34 And32Imm = 0x54,
35 And32Reg = 0x5c,
36 Lsh32Imm = 0x64,
37 Lsh32Reg = 0x6c,
38 Rsh32Imm = 0x74,
39 Rsh32Reg = 0x7c,
40 Neg32 = 0x84,
41 Mod32Imm = 0x94,
42 Mod32Reg = 0x9c,
43 Xor32Imm = 0xa4,
44 Xor32Reg = 0xac,
45 Mov32Imm = 0xb4,
46 Mov32Reg = 0xbc,
47 Arsh32Imm = 0xc4,
48 Arsh32Reg = 0xcc,
49 Lmul32Imm = 0x86,
50 Lmul32Reg = 0x8e,
51 Udiv32Imm = 0x46,
52 Udiv32Reg = 0x4e,
53 Urem32Imm = 0x66,
54 Urem32Reg = 0x6e,
55 Sdiv32Imm = 0xc6,
56 Sdiv32Reg = 0xce,
57 Srem32Imm = 0xe6,
58 Srem32Reg = 0xee,
59 Le = 0xd4,
60 Be = 0xdc,
61 Add64Imm = 0x07,
62 Add64Reg = 0x0f,
63 Sub64Imm = 0x17,
64 Sub64Reg = 0x1f,
65 Mul64Imm = 0x27,
66 Mul64Reg = 0x2f,
67 Div64Imm = 0x37,
68 Div64Reg = 0x3f,
69 Or64Imm = 0x47,
70 Or64Reg = 0x4f,
71 And64Imm = 0x57,
72 And64Reg = 0x5f,
73 Lsh64Imm = 0x67,
74 Lsh64Reg = 0x6f,
75 Rsh64Imm = 0x77,
76 Rsh64Reg = 0x7f,
77 Neg64 = 0x87,
78 Mod64Imm = 0x97,
79 Mod64Reg = 0x9f,
80 Xor64Imm = 0xa7,
81 Xor64Reg = 0xaf,
82 Mov64Imm = 0xb7,
83 Mov64Reg = 0xbf,
84 Arsh64Imm = 0xc7,
85 Arsh64Reg = 0xcf,
86 Hor64Imm = 0xf7,
87 Lmul64Imm = 0x96,
88 Lmul64Reg = 0x9e,
89 Uhmul64Imm = 0x36,
90 Uhmul64Reg = 0x3e,
91 Udiv64Imm = 0x56,
92 Udiv64Reg = 0x5e,
93 Urem64Imm = 0x76,
94 Urem64Reg = 0x7e,
95 Shmul64Imm = 0xb6,
96 Shmul64Reg = 0xbe,
97 Sdiv64Imm = 0xd6,
98 Sdiv64Reg = 0xde,
99 Srem64Imm = 0xf6,
100 Srem64Reg = 0xfe,
101 Ja = 0x05,
102 JeqImm = 0x15,
103 JeqReg = 0x1d,
104 JgtImm = 0x25,
105 JgtReg = 0x2d,
106 JgeImm = 0x35,
107 JgeReg = 0x3d,
108 JltImm = 0xa5,
109 JltReg = 0xad,
110 JleImm = 0xb5,
111 JleReg = 0xbd,
112 JsetImm = 0x45,
113 JsetReg = 0x4d,
114 JneImm = 0x55,
115 JneReg = 0x5d,
116 JsgtImm = 0x65,
117 JsgtReg = 0x6d,
118 JsgeImm = 0x75,
119 JsgeReg = 0x7d,
120 JsltImm = 0xc5,
121 JsltReg = 0xcd,
122 JsleImm = 0xd5,
123 JsleReg = 0xdd,
124 Call = 0x85,
125 Callx = 0x8d,
126 Exit = 0x95,
127}
128
129impl Display for OpCode {
130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131 f.write_str(Into::<&str>::into(self.clone()))
132 }
133}
134
135impl TryFrom<u8> for OpCode {
136 type Error = DisassemblerError;
137
138 fn try_from(value: u8) -> Result<Self, Self::Error> {
139 Ok(match value {
140 0x18 => OpCode::Lddw,
141 0x71 => OpCode::Ldxb,
142 0x69 => OpCode::Ldxh,
143 0x61 => OpCode::Ldxw,
144 0x79 => OpCode::Ldxdw,
145 0x72 => OpCode::Stb,
146 0x6a => OpCode::Sth,
147 0x62 => OpCode::Stw,
148 0x7a => OpCode::Stdw,
149 0x73 => OpCode::Stxb,
150 0x6b => OpCode::Stxh,
151 0x63 => OpCode::Stxw,
152 0x7b => OpCode::Stxdw,
153 0x04 => OpCode::Add32Imm,
154 0x0c => OpCode::Add32Reg,
155 0x14 => OpCode::Sub32Imm,
156 0x1c => OpCode::Sub32Reg,
157 0x24 => OpCode::Mul32Imm,
158 0x2c => OpCode::Mul32Reg,
159 0x34 => OpCode::Div32Imm,
160 0x3c => OpCode::Div32Reg,
161 0x44 => OpCode::Or32Imm,
162 0x4c => OpCode::Or32Reg,
163 0x54 => OpCode::And32Imm,
164 0x5c => OpCode::And32Reg,
165 0x64 => OpCode::Lsh32Imm,
166 0x6c => OpCode::Lsh32Reg,
167 0x74 => OpCode::Rsh32Imm,
168 0x7c => OpCode::Rsh32Reg,
169 0x84 => OpCode::Neg32,
170 0x94 => OpCode::Mod32Imm,
171 0x9c => OpCode::Mod32Reg,
172 0xa4 => OpCode::Xor32Imm,
173 0xac => OpCode::Xor32Reg,
174 0xb4 => OpCode::Mov32Imm,
175 0xbc => OpCode::Mov32Reg,
176 0xc4 => OpCode::Arsh32Imm,
177 0xcc => OpCode::Arsh32Reg,
178 0x86 => OpCode::Lmul32Imm,
179 0x8e => OpCode::Lmul32Reg,
180 0x46 => OpCode::Udiv32Imm,
181 0x4e => OpCode::Udiv32Reg,
182 0x66 => OpCode::Urem32Imm,
183 0x6e => OpCode::Urem32Reg,
184 0xc6 => OpCode::Sdiv32Imm,
185 0xce => OpCode::Sdiv32Reg,
186 0xe6 => OpCode::Srem32Imm,
187 0xee => OpCode::Srem32Reg,
188 0xd4 => OpCode::Le,
189 0xdc => OpCode::Be,
190 0x07 => OpCode::Add64Imm,
191 0x0f => OpCode::Add64Reg,
192 0x17 => OpCode::Sub64Imm,
193 0x1f => OpCode::Sub64Reg,
194 0x27 => OpCode::Mul64Imm,
195 0x2f => OpCode::Mul64Reg,
196 0x37 => OpCode::Div64Imm,
197 0x3f => OpCode::Div64Reg,
198 0x47 => OpCode::Or64Imm,
199 0x4f => OpCode::Or64Reg,
200 0x57 => OpCode::And64Imm,
201 0x5f => OpCode::And64Reg,
202 0x67 => OpCode::Lsh64Imm,
203 0x6f => OpCode::Lsh64Reg,
204 0x77 => OpCode::Rsh64Imm,
205 0x7f => OpCode::Rsh64Reg,
206 0x87 => OpCode::Neg64,
207 0x97 => OpCode::Mod64Imm,
208 0x9f => OpCode::Mod64Reg,
209 0xa7 => OpCode::Xor64Imm,
210 0xaf => OpCode::Xor64Reg,
211 0xb7 => OpCode::Mov64Imm,
212 0xbf => OpCode::Mov64Reg,
213 0xc7 => OpCode::Arsh64Imm,
214 0xcf => OpCode::Arsh64Reg,
215 0xf7 => OpCode::Hor64Imm,
216 0x96 => OpCode::Lmul64Imm,
217 0x9e => OpCode::Lmul64Reg,
218 0x36 => OpCode::Uhmul64Imm,
219 0x3e => OpCode::Uhmul64Reg,
220 0x56 => OpCode::Udiv64Imm,
221 0x5e => OpCode::Udiv64Reg,
222 0x76 => OpCode::Urem64Imm,
223 0x7e => OpCode::Urem64Reg,
224 0xb6 => OpCode::Shmul64Imm,
225 0xbe => OpCode::Shmul64Reg,
226 0xd6 => OpCode::Sdiv64Imm,
227 0xde => OpCode::Sdiv64Reg,
228 0xf6 => OpCode::Srem64Imm,
229 0xfe => OpCode::Srem64Reg,
230 0x05 => OpCode::Ja,
231 0x15 => OpCode::JeqImm,
232 0x1d => OpCode::JeqReg,
233 0x25 => OpCode::JgtImm,
234 0x2d => OpCode::JgtReg,
235 0x35 => OpCode::JgeImm,
236 0x3d => OpCode::JgeReg,
237 0xa5 => OpCode::JltImm,
238 0xad => OpCode::JltReg,
239 0xb5 => OpCode::JleImm,
240 0xbd => OpCode::JleReg,
241 0x45 => OpCode::JsetImm,
242 0x4d => OpCode::JsetReg,
243 0x55 => OpCode::JneImm,
244 0x5d => OpCode::JneReg,
245 0x65 => OpCode::JsgtImm,
246 0x6d => OpCode::JsgtReg,
247 0x75 => OpCode::JsgeImm,
248 0x7d => OpCode::JsgeReg,
249 0xc5 => OpCode::JsltImm,
250 0xcd => OpCode::JsltReg,
251 0xd5 => OpCode::JsleImm,
252 0xdd => OpCode::JsleReg,
253 0x85 => OpCode::Call,
254 0x8d => OpCode::Callx,
255 0x95 => OpCode::Exit,
256 _ => return Err(DisassemblerError::InvalidOpcode),
257 })
258 }
259}
260
261impl From<OpCode> for u8 {
262 fn from(val: OpCode) -> Self {
263 val as u8
264 }
265}
266
267impl From<OpCode> for &str {
268 fn from(val: OpCode) -> Self {
269 match val {
270 OpCode::Lddw => "lddw",
271 OpCode::Ldxb => "ldxb",
272 OpCode::Ldxh => "ldxh",
273 OpCode::Ldxw => "ldxw",
274 OpCode::Ldxdw => "ldxdw",
275 OpCode::Stb => "stb",
276 OpCode::Sth => "sth",
277 OpCode::Stw => "stw",
278 OpCode::Stdw => "stdw",
279 OpCode::Stxb => "stxb",
280 OpCode::Stxh => "stxh",
281 OpCode::Stxw => "stxw",
282 OpCode::Stxdw => "stxdw",
283 OpCode::Add32Imm => "add32",
284 OpCode::Add32Reg => "add32",
285 OpCode::Sub32Imm => "sub32",
286 OpCode::Sub32Reg => "sub32",
287 OpCode::Mul32Imm => "mul32",
288 OpCode::Mul32Reg => "mul32",
289 OpCode::Div32Imm => "div32",
290 OpCode::Div32Reg => "div32",
291 OpCode::Or32Imm => "or32",
292 OpCode::Or32Reg => "or32",
293 OpCode::And32Imm => "and32",
294 OpCode::And32Reg => "and32",
295 OpCode::Lsh32Imm => "lsh32",
296 OpCode::Lsh32Reg => "lsh32",
297 OpCode::Rsh32Imm => "rsh32",
298 OpCode::Rsh32Reg => "rsh32",
299 OpCode::Neg32 => "neg32",
300 OpCode::Mod32Imm => "mod32",
301 OpCode::Mod32Reg => "mod32",
302 OpCode::Xor32Imm => "xor32",
303 OpCode::Xor32Reg => "xor32",
304 OpCode::Mov32Imm => "mov32",
305 OpCode::Mov32Reg => "mov32",
306 OpCode::Arsh32Imm => "arsh32",
307 OpCode::Arsh32Reg => "arsh32",
308 OpCode::Lmul32Imm => "lmul32",
309 OpCode::Lmul32Reg => "lmul32",
310 OpCode::Udiv32Imm => "udiv32",
311 OpCode::Udiv32Reg => "udiv32",
312 OpCode::Urem32Imm => "urem32",
313 OpCode::Urem32Reg => "urem32",
314 OpCode::Sdiv32Imm => "sdiv32",
315 OpCode::Sdiv32Reg => "sdiv32",
316 OpCode::Srem32Imm => "srem32",
317 OpCode::Srem32Reg => "srem32",
318 OpCode::Le => "le",
319 OpCode::Be => "be",
320 OpCode::Add64Imm => "add64",
321 OpCode::Add64Reg => "add64",
322 OpCode::Sub64Imm => "sub64",
323 OpCode::Sub64Reg => "sub64",
324 OpCode::Mul64Imm => "mul64",
325 OpCode::Mul64Reg => "mul64",
326 OpCode::Div64Imm => "div64",
327 OpCode::Div64Reg => "div64",
328 OpCode::Or64Imm => "or64",
329 OpCode::Or64Reg => "or64",
330 OpCode::And64Imm => "and64",
331 OpCode::And64Reg => "and64",
332 OpCode::Lsh64Imm => "lsh64",
333 OpCode::Lsh64Reg => "lsh64",
334 OpCode::Rsh64Imm => "rsh64",
335 OpCode::Rsh64Reg => "rsh64",
336 OpCode::Neg64 => "neg64",
337 OpCode::Mod64Imm => "mod64",
338 OpCode::Mod64Reg => "mod64",
339 OpCode::Xor64Imm => "xor64",
340 OpCode::Xor64Reg => "xor64",
341 OpCode::Mov64Imm => "mov64",
342 OpCode::Mov64Reg => "mov64",
343 OpCode::Arsh64Imm => "arsh64",
344 OpCode::Arsh64Reg => "arsh64",
345 OpCode::Hor64Imm => "hor64",
346 OpCode::Lmul64Imm => "lmul64",
347 OpCode::Lmul64Reg => "lmul64",
348 OpCode::Uhmul64Imm => "uhmul64",
349 OpCode::Uhmul64Reg => "uhmul64",
350 OpCode::Udiv64Imm => "udiv64",
351 OpCode::Udiv64Reg => "udiv64",
352 OpCode::Urem64Imm => "urem64",
353 OpCode::Urem64Reg => "urem64",
354 OpCode::Shmul64Imm => "shmul64",
355 OpCode::Shmul64Reg => "shmul64",
356 OpCode::Sdiv64Imm => "sdiv64",
357 OpCode::Sdiv64Reg => "sdiv64",
358 OpCode::Srem64Imm => "srem64",
359 OpCode::Srem64Reg => "srem64",
360 OpCode::Ja => "ja",
361 OpCode::JeqImm => "jeq",
362 OpCode::JeqReg => "jeq",
363 OpCode::JgtImm => "jgt",
364 OpCode::JgtReg => "jgt",
365 OpCode::JgeImm => "jge",
366 OpCode::JgeReg => "jge",
367 OpCode::JltImm => "jlt",
368 OpCode::JltReg => "jlt",
369 OpCode::JleImm => "jle",
370 OpCode::JleReg => "jle",
371 OpCode::JsetImm => "jset",
372 OpCode::JsetReg => "jset",
373 OpCode::JneImm => "jne",
374 OpCode::JneReg => "jne",
375 OpCode::JsgtImm => "jsgt",
376 OpCode::JsgtReg => "jsgt",
377 OpCode::JsgeImm => "jsge",
378 OpCode::JsgeReg => "jsge",
379 OpCode::JsltImm => "jslt",
380 OpCode::JsltReg => "jslt",
381 OpCode::JsleImm => "jsle",
382 OpCode::JsleReg => "jsle",
383 OpCode::Call => "call",
384 OpCode::Callx => "callx",
385 OpCode::Exit => "exit",
386 }
387 }
388}