1use {
2 crate::errors::SBPFError,
3 core::{fmt, str::FromStr},
4 num_derive::FromPrimitive,
5 serde::{Deserialize, Serialize},
6};
7
8#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum OperationType {
10 LoadImmediate,
11 LoadMemory,
12 StoreImmediate,
13 StoreRegister,
14 BinaryImmediate,
15 BinaryRegister,
16 Unary,
17 Jump,
18 JumpImmediate,
19 JumpRegister,
20 CallImmediate,
21 CallRegister,
22 Exit,
23}
24
25pub const LOAD_IMM_OPS: &[Opcode] = &[Opcode::Lddw]; pub const LOAD_MEMORY_OPS: &[Opcode] = &[
28 Opcode::Ldxb, Opcode::Ldxh,
30 Opcode::Ldxw,
31 Opcode::Ldxdw,
32];
33
34pub const STORE_IMM_OPS: &[Opcode] = &[
35 Opcode::Stb, Opcode::Sth,
37 Opcode::Stw,
38 Opcode::Stdw,
39];
40
41pub const STORE_REG_OPS: &[Opcode] = &[
42 Opcode::Stxb, Opcode::Stxh,
44 Opcode::Stxw,
45 Opcode::Stxdw,
46];
47
48pub const BIN_IMM_OPS: &[Opcode] = &[
49 Opcode::Add32Imm, Opcode::Sub32Imm,
51 Opcode::Mul32Imm,
52 Opcode::Div32Imm,
53 Opcode::Or32Imm,
54 Opcode::And32Imm,
55 Opcode::Lsh32Imm,
56 Opcode::Rsh32Imm,
57 Opcode::Mod32Imm,
58 Opcode::Xor32Imm,
59 Opcode::Mov32Imm,
60 Opcode::Arsh32Imm,
61 Opcode::Lmul32Imm,
62 Opcode::Udiv32Imm,
63 Opcode::Urem32Imm,
64 Opcode::Sdiv32Imm,
65 Opcode::Srem32Imm,
66 Opcode::Le,
67 Opcode::Be,
68 Opcode::Add64Imm,
69 Opcode::Sub64Imm,
70 Opcode::Mul64Imm,
71 Opcode::Div64Imm,
72 Opcode::Or64Imm,
73 Opcode::And64Imm,
74 Opcode::Lsh64Imm,
75 Opcode::Rsh64Imm,
76 Opcode::Mod64Imm,
77 Opcode::Xor64Imm,
78 Opcode::Mov64Imm,
79 Opcode::Arsh64Imm,
80 Opcode::Hor64Imm,
81 Opcode::Lmul64Imm,
82 Opcode::Uhmul64Imm,
83 Opcode::Udiv64Imm,
84 Opcode::Urem64Imm,
85 Opcode::Shmul64Imm,
86 Opcode::Sdiv64Imm,
87 Opcode::Srem64Imm,
88];
89
90pub const BIN_REG_OPS: &[Opcode] = &[
91 Opcode::Add32Reg, Opcode::Sub32Reg,
93 Opcode::Mul32Reg,
94 Opcode::Div32Reg,
95 Opcode::Or32Reg,
96 Opcode::And32Reg,
97 Opcode::Lsh32Reg,
98 Opcode::Rsh32Reg,
99 Opcode::Mod32Reg,
100 Opcode::Xor32Reg,
101 Opcode::Mov32Reg,
102 Opcode::Arsh32Reg,
103 Opcode::Lmul32Reg,
104 Opcode::Udiv32Reg,
105 Opcode::Urem32Reg,
106 Opcode::Sdiv32Reg,
107 Opcode::Srem32Reg,
108 Opcode::Add64Reg,
109 Opcode::Sub64Reg,
110 Opcode::Mul64Reg,
111 Opcode::Div64Reg,
112 Opcode::Or64Reg,
113 Opcode::And64Reg,
114 Opcode::Lsh64Reg,
115 Opcode::Rsh64Reg,
116 Opcode::Mod64Reg,
117 Opcode::Xor64Reg,
118 Opcode::Mov64Reg,
119 Opcode::Arsh64Reg,
120 Opcode::Lmul64Reg,
121 Opcode::Uhmul64Reg,
122 Opcode::Udiv64Reg,
123 Opcode::Urem64Reg,
124 Opcode::Shmul64Reg,
125 Opcode::Sdiv64Reg,
126 Opcode::Srem64Reg,
127];
128
129pub const UNARY_OPS: &[Opcode] = &[
130 Opcode::Neg32, Opcode::Neg64,
132];
133
134pub const JUMP_OPS: &[Opcode] = &[Opcode::Ja]; pub const JUMP_IMM_OPS: &[Opcode] = &[
137 Opcode::JeqImm, Opcode::JgtImm,
139 Opcode::JgeImm,
140 Opcode::JltImm,
141 Opcode::JleImm,
142 Opcode::JsetImm,
143 Opcode::JneImm,
144 Opcode::JsgtImm,
145 Opcode::JsgeImm,
146 Opcode::JsltImm,
147 Opcode::JsleImm,
148];
149
150pub const JUMP_REG_OPS: &[Opcode] = &[
151 Opcode::JeqReg, Opcode::JgtReg,
153 Opcode::JgeReg,
154 Opcode::JltReg,
155 Opcode::JleReg,
156 Opcode::JsetReg,
157 Opcode::JneReg,
158 Opcode::JsgtReg,
159 Opcode::JsgeReg,
160 Opcode::JsltReg,
161 Opcode::JsleReg,
162];
163
164pub const CALL_IMM_OPS: &[Opcode] = &[Opcode::Call]; pub const CALL_REG_OPS: &[Opcode] = &[Opcode::Callx]; pub const EXIT_OPS: &[Opcode] = &[Opcode::Exit]; #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, FromPrimitive, Serialize, Deserialize)]
171pub enum Opcode {
172 Lddw,
173 Ldxb,
174 Ldxh,
175 Ldxw,
176 Ldxdw,
177 Stb,
178 Sth,
179 Stw,
180 Stdw,
181 Stxb,
182 Stxh,
183 Stxw,
184 Stxdw,
185 Add32Imm,
186 Add32Reg,
187 Sub32Imm,
188 Sub32Reg,
189 Mul32Imm,
190 Mul32Reg,
191 Div32Imm,
192 Div32Reg,
193 Or32Imm,
194 Or32Reg,
195 And32Imm,
196 And32Reg,
197 Lsh32Imm,
198 Lsh32Reg,
199 Rsh32Imm,
200 Rsh32Reg,
201 Mod32Imm,
202 Mod32Reg,
203 Xor32Imm,
204 Xor32Reg,
205 Mov32Imm,
206 Mov32Reg,
207 Arsh32Imm,
208 Arsh32Reg,
209 Lmul32Imm,
210 Lmul32Reg,
211 Udiv32Imm,
212 Udiv32Reg,
213 Urem32Imm,
214 Urem32Reg,
215 Sdiv32Imm,
216 Sdiv32Reg,
217 Srem32Imm,
218 Srem32Reg,
219 Le,
220 Be,
221 Add64Imm,
222 Add64Reg,
223 Sub64Imm,
224 Sub64Reg,
225 Mul64Imm,
226 Mul64Reg,
227 Div64Imm,
228 Div64Reg,
229 Or64Imm,
230 Or64Reg,
231 And64Imm,
232 And64Reg,
233 Lsh64Imm,
234 Lsh64Reg,
235 Rsh64Imm,
236 Rsh64Reg,
237 Mod64Imm,
238 Mod64Reg,
239 Xor64Imm,
240 Xor64Reg,
241 Mov64Imm,
242 Mov64Reg,
243 Arsh64Imm,
244 Arsh64Reg,
245 Hor64Imm,
246 Lmul64Imm,
247 Lmul64Reg,
248 Uhmul64Imm,
249 Uhmul64Reg,
250 Udiv64Imm,
251 Udiv64Reg,
252 Urem64Imm,
253 Urem64Reg,
254 Shmul64Imm,
255 Shmul64Reg,
256 Sdiv64Imm,
257 Sdiv64Reg,
258 Srem64Imm,
259 Srem64Reg,
260 Neg32,
261 Neg64,
262 Ja,
263 JeqImm,
264 JeqReg,
265 JgtImm,
266 JgtReg,
267 JgeImm,
268 JgeReg,
269 JltImm,
270 JltReg,
271 JleImm,
272 JleReg,
273 JsetImm,
274 JsetReg,
275 JneImm,
276 JneReg,
277 JsgtImm,
278 JsgtReg,
279 JsgeImm,
280 JsgeReg,
281 JsltImm,
282 JsltReg,
283 JsleImm,
284 JsleReg,
285 Call,
286 Callx,
287 Exit,
288}
289
290impl FromStr for Opcode {
291 type Err = &'static str;
292
293 fn from_str(s: &str) -> Result<Self, Self::Err> {
294 match s.to_lowercase().as_str() {
295 "lddw" => Ok(Opcode::Lddw),
296 "ldxb" => Ok(Opcode::Ldxb),
297 "ldxh" => Ok(Opcode::Ldxh),
298 "ldxw" => Ok(Opcode::Ldxw),
299 "ldxdw" => Ok(Opcode::Ldxdw),
300 "stb" => Ok(Opcode::Stb),
301 "sth" => Ok(Opcode::Sth),
302 "stw" => Ok(Opcode::Stw),
303 "stdw" => Ok(Opcode::Stdw),
304 "stxb" => Ok(Opcode::Stxb),
305 "stxh" => Ok(Opcode::Stxh),
306 "stxw" => Ok(Opcode::Stxw),
307 "stxdw" => Ok(Opcode::Stxdw),
308 "add32" => Ok(Opcode::Add32Imm),
309 "sub32" => Ok(Opcode::Sub32Imm),
310 "mul32" => Ok(Opcode::Mul32Imm),
311 "div32" => Ok(Opcode::Div32Imm),
312 "or32" => Ok(Opcode::Or32Imm),
313 "and32" => Ok(Opcode::And32Imm),
314 "lsh32" => Ok(Opcode::Lsh32Imm),
315 "rsh32" => Ok(Opcode::Rsh32Imm),
316 "neg32" => Ok(Opcode::Neg32),
317 "mod32" => Ok(Opcode::Mod32Imm),
318 "xor32" => Ok(Opcode::Xor32Imm),
319 "mov32" => Ok(Opcode::Mov32Imm),
320 "arsh32" => Ok(Opcode::Arsh32Imm),
321 "lmul32" => Ok(Opcode::Lmul32Imm),
322 "udiv32" => Ok(Opcode::Udiv32Imm),
323 "urem32" => Ok(Opcode::Urem32Imm),
324 "sdiv32" => Ok(Opcode::Sdiv32Imm),
325 "srem32" => Ok(Opcode::Srem32Imm),
326 "le" => Ok(Opcode::Le),
327 "be" => Ok(Opcode::Be),
328 "add64" => Ok(Opcode::Add64Imm),
329 "sub64" => Ok(Opcode::Sub64Imm),
330 "mul64" => Ok(Opcode::Mul64Imm),
331 "div64" => Ok(Opcode::Div64Imm),
332 "or64" => Ok(Opcode::Or64Imm),
333 "and64" => Ok(Opcode::And64Imm),
334 "lsh64" => Ok(Opcode::Lsh64Imm),
335 "rsh64" => Ok(Opcode::Rsh64Imm),
336 "neg64" => Ok(Opcode::Neg64),
337 "mod64" => Ok(Opcode::Mod64Imm),
338 "xor64" => Ok(Opcode::Xor64Imm),
339 "mov64" => Ok(Opcode::Mov64Imm),
340 "arsh64" => Ok(Opcode::Arsh64Imm),
341 "hor64" => Ok(Opcode::Hor64Imm),
342 "lmul64" => Ok(Opcode::Lmul64Imm),
343 "uhmul64" => Ok(Opcode::Uhmul64Imm),
344 "udiv64" => Ok(Opcode::Udiv64Imm),
345 "urem64" => Ok(Opcode::Urem64Imm),
346 "shmul64" => Ok(Opcode::Shmul64Imm),
347 "sdiv64" => Ok(Opcode::Sdiv64Imm),
348 "srem64" => Ok(Opcode::Srem64Imm),
349 "ja" => Ok(Opcode::Ja),
350 "jeq" => Ok(Opcode::JeqImm),
351 "jgt" => Ok(Opcode::JgtImm),
352 "jge" => Ok(Opcode::JgeImm),
353 "jlt" => Ok(Opcode::JltImm),
354 "jle" => Ok(Opcode::JleImm),
355 "jset" => Ok(Opcode::JsetImm),
356 "jne" => Ok(Opcode::JneImm),
357 "jsgt" => Ok(Opcode::JsgtImm),
358 "jsge" => Ok(Opcode::JsgeImm),
359 "jslt" => Ok(Opcode::JsltImm),
360 "jsle" => Ok(Opcode::JsleImm),
361 "call" => Ok(Opcode::Call),
362 "callx" => Ok(Opcode::Callx),
363 "exit" => Ok(Opcode::Exit),
364 _ => Err("Invalid opcode"),
365 }
366 }
367}
368
369impl fmt::Display for Opcode {
370 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
371 write!(f, "{}", self.to_str())
372 }
373}
374
375impl TryFrom<u8> for Opcode {
376 type Error = SBPFError;
377
378 fn try_from(opcode: u8) -> Result<Self, Self::Error> {
379 match opcode {
380 0x18 => Ok(Opcode::Lddw),
381 0x71 => Ok(Opcode::Ldxb),
382 0x69 => Ok(Opcode::Ldxh),
383 0x61 => Ok(Opcode::Ldxw),
384 0x79 => Ok(Opcode::Ldxdw),
385 0x72 => Ok(Opcode::Stb),
386 0x6a => Ok(Opcode::Sth),
387 0x62 => Ok(Opcode::Stw),
388 0x7a => Ok(Opcode::Stdw),
389 0x73 => Ok(Opcode::Stxb),
390 0x6b => Ok(Opcode::Stxh),
391 0x63 => Ok(Opcode::Stxw),
392 0x7b => Ok(Opcode::Stxdw),
393 0x04 => Ok(Opcode::Add32Imm),
394 0x0c => Ok(Opcode::Add32Reg),
395 0x14 => Ok(Opcode::Sub32Imm),
396 0x1c => Ok(Opcode::Sub32Reg),
397 0x24 => Ok(Opcode::Mul32Imm),
398 0x2c => Ok(Opcode::Mul32Reg),
399 0x34 => Ok(Opcode::Div32Imm),
400 0x3c => Ok(Opcode::Div32Reg),
401 0x44 => Ok(Opcode::Or32Imm),
402 0x4c => Ok(Opcode::Or32Reg),
403 0x54 => Ok(Opcode::And32Imm),
404 0x5c => Ok(Opcode::And32Reg),
405 0x64 => Ok(Opcode::Lsh32Imm),
406 0x6c => Ok(Opcode::Lsh32Reg),
407 0x74 => Ok(Opcode::Rsh32Imm),
408 0x7c => Ok(Opcode::Rsh32Reg),
409 0x94 => Ok(Opcode::Mod32Imm),
410 0x9c => Ok(Opcode::Mod32Reg),
411 0xa4 => Ok(Opcode::Xor32Imm),
412 0xac => Ok(Opcode::Xor32Reg),
413 0xb4 => Ok(Opcode::Mov32Imm),
414 0xbc => Ok(Opcode::Mov32Reg),
415 0xc4 => Ok(Opcode::Arsh32Imm),
416 0xcc => Ok(Opcode::Arsh32Reg),
417 0x86 => Ok(Opcode::Lmul32Imm),
418 0x8e => Ok(Opcode::Lmul32Reg),
419 0x46 => Ok(Opcode::Udiv32Imm),
420 0x4e => Ok(Opcode::Udiv32Reg),
421 0x66 => Ok(Opcode::Urem32Imm),
422 0x6e => Ok(Opcode::Urem32Reg),
423 0xc6 => Ok(Opcode::Sdiv32Imm),
424 0xce => Ok(Opcode::Sdiv32Reg),
425 0xe6 => Ok(Opcode::Srem32Imm),
426 0xee => Ok(Opcode::Srem32Reg),
427 0xd4 => Ok(Opcode::Le),
428 0xdc => Ok(Opcode::Be),
429 0x07 => Ok(Opcode::Add64Imm),
430 0x0f => Ok(Opcode::Add64Reg),
431 0x17 => Ok(Opcode::Sub64Imm),
432 0x1f => Ok(Opcode::Sub64Reg),
433 0x27 => Ok(Opcode::Mul64Imm),
434 0x2f => Ok(Opcode::Mul64Reg),
435 0x37 => Ok(Opcode::Div64Imm),
436 0x3f => Ok(Opcode::Div64Reg),
437 0x47 => Ok(Opcode::Or64Imm),
438 0x4f => Ok(Opcode::Or64Reg),
439 0x57 => Ok(Opcode::And64Imm),
440 0x5f => Ok(Opcode::And64Reg),
441 0x67 => Ok(Opcode::Lsh64Imm),
442 0x6f => Ok(Opcode::Lsh64Reg),
443 0x77 => Ok(Opcode::Rsh64Imm),
444 0x7f => Ok(Opcode::Rsh64Reg),
445 0x97 => Ok(Opcode::Mod64Imm),
446 0x9f => Ok(Opcode::Mod64Reg),
447 0xa7 => Ok(Opcode::Xor64Imm),
448 0xaf => Ok(Opcode::Xor64Reg),
449 0xb7 => Ok(Opcode::Mov64Imm),
450 0xbf => Ok(Opcode::Mov64Reg),
451 0xc7 => Ok(Opcode::Arsh64Imm),
452 0xcf => Ok(Opcode::Arsh64Reg),
453 0xf7 => Ok(Opcode::Hor64Imm),
454 0x96 => Ok(Opcode::Lmul64Imm),
455 0x9e => Ok(Opcode::Lmul64Reg),
456 0x36 => Ok(Opcode::Uhmul64Imm),
457 0x3e => Ok(Opcode::Uhmul64Reg),
458 0x56 => Ok(Opcode::Udiv64Imm),
459 0x5e => Ok(Opcode::Udiv64Reg),
460 0x76 => Ok(Opcode::Urem64Imm),
461 0x7e => Ok(Opcode::Urem64Reg),
462 0xb6 => Ok(Opcode::Shmul64Imm),
463 0xbe => Ok(Opcode::Shmul64Reg),
464 0xd6 => Ok(Opcode::Sdiv64Imm),
465 0xde => Ok(Opcode::Sdiv64Reg),
466 0xf6 => Ok(Opcode::Srem64Imm),
467 0xfe => Ok(Opcode::Srem64Reg),
468 0x84 => Ok(Opcode::Neg32),
469 0x87 => Ok(Opcode::Neg64),
470 0x05 => Ok(Opcode::Ja),
471 0x15 => Ok(Opcode::JeqImm),
472 0x1d => Ok(Opcode::JeqReg),
473 0x25 => Ok(Opcode::JgtImm),
474 0x2d => Ok(Opcode::JgtReg),
475 0x35 => Ok(Opcode::JgeImm),
476 0x3d => Ok(Opcode::JgeReg),
477 0xa5 => Ok(Opcode::JltImm),
478 0xad => Ok(Opcode::JltReg),
479 0xb5 => Ok(Opcode::JleImm),
480 0xbd => Ok(Opcode::JleReg),
481 0x45 => Ok(Opcode::JsetImm),
482 0x4d => Ok(Opcode::JsetReg),
483 0x55 => Ok(Opcode::JneImm),
484 0x5d => Ok(Opcode::JneReg),
485 0x65 => Ok(Opcode::JsgtImm),
486 0x6d => Ok(Opcode::JsgtReg),
487 0x75 => Ok(Opcode::JsgeImm),
488 0x7d => Ok(Opcode::JsgeReg),
489 0xc5 => Ok(Opcode::JsltImm),
490 0xcd => Ok(Opcode::JsltReg),
491 0xd5 => Ok(Opcode::JsleImm),
492 0xdd => Ok(Opcode::JsleReg),
493 0x85 => Ok(Opcode::Call),
494 0x8d => Ok(Opcode::Callx),
495 0x95 => Ok(Opcode::Exit),
496 _ => Err(SBPFError::BytecodeError {
497 error: format!("no decode handler for opcode 0x{:02x}", opcode),
498 span: 0..1,
499 custom_label: Some("Invalid opcode".to_string()),
500 }),
501 }
502 }
503}
504
505impl From<Opcode> for u8 {
506 fn from(opcode: Opcode) -> u8 {
507 match opcode {
508 Opcode::Lddw => 0x18,
509 Opcode::Ldxb => 0x71,
510 Opcode::Ldxh => 0x69,
511 Opcode::Ldxw => 0x61,
512 Opcode::Ldxdw => 0x79,
513 Opcode::Stb => 0x72,
514 Opcode::Sth => 0x6a,
515 Opcode::Stw => 0x62,
516 Opcode::Stdw => 0x7a,
517 Opcode::Stxb => 0x73,
518 Opcode::Stxh => 0x6b,
519 Opcode::Stxw => 0x63,
520 Opcode::Stxdw => 0x7b,
521 Opcode::Add32Imm => 0x04,
522 Opcode::Add32Reg => 0x0c,
523 Opcode::Sub32Imm => 0x14,
524 Opcode::Sub32Reg => 0x1c,
525 Opcode::Mul32Imm => 0x24,
526 Opcode::Mul32Reg => 0x2c,
527 Opcode::Div32Imm => 0x34,
528 Opcode::Div32Reg => 0x3c,
529 Opcode::Or32Imm => 0x44,
530 Opcode::Or32Reg => 0x4c,
531 Opcode::And32Imm => 0x54,
532 Opcode::And32Reg => 0x5c,
533 Opcode::Lsh32Imm => 0x64,
534 Opcode::Lsh32Reg => 0x6c,
535 Opcode::Rsh32Imm => 0x74,
536 Opcode::Rsh32Reg => 0x7c,
537 Opcode::Mod32Imm => 0x94,
538 Opcode::Mod32Reg => 0x9c,
539 Opcode::Xor32Imm => 0xa4,
540 Opcode::Xor32Reg => 0xac,
541 Opcode::Mov32Imm => 0xb4,
542 Opcode::Mov32Reg => 0xbc,
543 Opcode::Arsh32Imm => 0xc4,
544 Opcode::Arsh32Reg => 0xcc,
545 Opcode::Lmul32Imm => 0x86,
546 Opcode::Lmul32Reg => 0x8e,
547 Opcode::Udiv32Imm => 0x46,
548 Opcode::Udiv32Reg => 0x4e,
549 Opcode::Urem32Imm => 0x66,
550 Opcode::Urem32Reg => 0x6e,
551 Opcode::Sdiv32Imm => 0xc6,
552 Opcode::Sdiv32Reg => 0xce,
553 Opcode::Srem32Imm => 0xe6,
554 Opcode::Srem32Reg => 0xee,
555 Opcode::Le => 0xd4,
556 Opcode::Be => 0xdc,
557 Opcode::Add64Imm => 0x07,
558 Opcode::Add64Reg => 0x0f,
559 Opcode::Sub64Imm => 0x17,
560 Opcode::Sub64Reg => 0x1f,
561 Opcode::Mul64Imm => 0x27,
562 Opcode::Mul64Reg => 0x2f,
563 Opcode::Div64Imm => 0x37,
564 Opcode::Div64Reg => 0x3f,
565 Opcode::Or64Imm => 0x47,
566 Opcode::Or64Reg => 0x4f,
567 Opcode::And64Imm => 0x57,
568 Opcode::And64Reg => 0x5f,
569 Opcode::Lsh64Imm => 0x67,
570 Opcode::Lsh64Reg => 0x6f,
571 Opcode::Rsh64Imm => 0x77,
572 Opcode::Rsh64Reg => 0x7f,
573 Opcode::Mod64Imm => 0x97,
574 Opcode::Mod64Reg => 0x9f,
575 Opcode::Xor64Imm => 0xa7,
576 Opcode::Xor64Reg => 0xaf,
577 Opcode::Mov64Imm => 0xb7,
578 Opcode::Mov64Reg => 0xbf,
579 Opcode::Arsh64Imm => 0xc7,
580 Opcode::Arsh64Reg => 0xcf,
581 Opcode::Hor64Imm => 0xf7,
582 Opcode::Lmul64Imm => 0x96,
583 Opcode::Lmul64Reg => 0x9e,
584 Opcode::Uhmul64Imm => 0x36,
585 Opcode::Uhmul64Reg => 0x3e,
586 Opcode::Udiv64Imm => 0x56,
587 Opcode::Udiv64Reg => 0x5e,
588 Opcode::Urem64Imm => 0x76,
589 Opcode::Urem64Reg => 0x7e,
590 Opcode::Shmul64Imm => 0xb6,
591 Opcode::Shmul64Reg => 0xbe,
592 Opcode::Sdiv64Imm => 0xd6,
593 Opcode::Sdiv64Reg => 0xde,
594 Opcode::Srem64Imm => 0xf6,
595 Opcode::Srem64Reg => 0xfe,
596 Opcode::Neg32 => 0x84,
597 Opcode::Neg64 => 0x87,
598 Opcode::Ja => 0x05,
599 Opcode::JeqImm => 0x15,
600 Opcode::JeqReg => 0x1d,
601 Opcode::JgtImm => 0x25,
602 Opcode::JgtReg => 0x2d,
603 Opcode::JgeImm => 0x35,
604 Opcode::JgeReg => 0x3d,
605 Opcode::JltImm => 0xa5,
606 Opcode::JltReg => 0xad,
607 Opcode::JleImm => 0xb5,
608 Opcode::JleReg => 0xbd,
609 Opcode::JsetImm => 0x45,
610 Opcode::JsetReg => 0x4d,
611 Opcode::JneImm => 0x55,
612 Opcode::JneReg => 0x5d,
613 Opcode::JsgtImm => 0x65,
614 Opcode::JsgtReg => 0x6d,
615 Opcode::JsgeImm => 0x75,
616 Opcode::JsgeReg => 0x7d,
617 Opcode::JsltImm => 0xc5,
618 Opcode::JsltReg => 0xcd,
619 Opcode::JsleImm => 0xd5,
620 Opcode::JsleReg => 0xdd,
621 Opcode::Call => 0x85,
622 Opcode::Callx => 0x8d,
623 Opcode::Exit => 0x95,
624 }
625 }
626}
627
628impl Opcode {
629 pub fn to_str(&self) -> &'static str {
630 match self {
631 Opcode::Lddw => "lddw",
632 Opcode::Ldxb => "ldxb",
633 Opcode::Ldxh => "ldxh",
634 Opcode::Ldxw => "ldxw",
635 Opcode::Ldxdw => "ldxdw",
636 Opcode::Stb => "stb",
637 Opcode::Sth => "sth",
638 Opcode::Stw => "stw",
639 Opcode::Stdw => "stdw",
640 Opcode::Stxb => "stxb",
641 Opcode::Stxh => "stxh",
642 Opcode::Stxw => "stxw",
643 Opcode::Stxdw => "stxdw",
644 Opcode::Add32Imm | Opcode::Add32Reg => "add32",
645 Opcode::Sub32Imm | Opcode::Sub32Reg => "sub32",
646 Opcode::Mul32Imm | Opcode::Mul32Reg => "mul32",
647 Opcode::Div32Imm | Opcode::Div32Reg => "div32",
648 Opcode::Or32Imm | Opcode::Or32Reg => "or32",
649 Opcode::And32Imm | Opcode::And32Reg => "and32",
650 Opcode::Lsh32Imm | Opcode::Lsh32Reg => "lsh32",
651 Opcode::Rsh32Imm | Opcode::Rsh32Reg => "rsh32",
652 Opcode::Neg32 => "neg32",
653 Opcode::Mod32Imm | Opcode::Mod32Reg => "mod32",
654 Opcode::Xor32Imm | Opcode::Xor32Reg => "xor32",
655 Opcode::Mov32Imm | Opcode::Mov32Reg => "mov32",
656 Opcode::Arsh32Imm | Opcode::Arsh32Reg => "arsh32",
657 Opcode::Lmul32Imm | Opcode::Lmul32Reg => "lmul32",
658 Opcode::Udiv32Imm | Opcode::Udiv32Reg => "udiv32",
659 Opcode::Urem32Imm | Opcode::Urem32Reg => "urem32",
660 Opcode::Sdiv32Imm | Opcode::Sdiv32Reg => "sdiv32",
661 Opcode::Srem32Imm | Opcode::Srem32Reg => "srem32",
662 Opcode::Le => "le",
663 Opcode::Be => "be",
664 Opcode::Add64Imm | Opcode::Add64Reg => "add64",
665 Opcode::Sub64Imm | Opcode::Sub64Reg => "sub64",
666 Opcode::Mul64Imm | Opcode::Mul64Reg => "mul64",
667 Opcode::Div64Imm | Opcode::Div64Reg => "div64",
668 Opcode::Or64Imm | Opcode::Or64Reg => "or64",
669 Opcode::And64Imm | Opcode::And64Reg => "and64",
670 Opcode::Lsh64Imm | Opcode::Lsh64Reg => "lsh64",
671 Opcode::Rsh64Imm | Opcode::Rsh64Reg => "rsh64",
672 Opcode::Neg64 => "neg64",
673 Opcode::Mod64Imm | Opcode::Mod64Reg => "mod64",
674 Opcode::Xor64Imm | Opcode::Xor64Reg => "xor64",
675 Opcode::Mov64Imm | Opcode::Mov64Reg => "mov64",
676 Opcode::Arsh64Imm | Opcode::Arsh64Reg => "arsh64",
677 Opcode::Hor64Imm => "hor64",
678 Opcode::Lmul64Imm | Opcode::Lmul64Reg => "lmul64",
679 Opcode::Uhmul64Imm | Opcode::Uhmul64Reg => "uhmul64",
680 Opcode::Udiv64Imm | Opcode::Udiv64Reg => "udiv64",
681 Opcode::Urem64Imm | Opcode::Urem64Reg => "urem64",
682 Opcode::Shmul64Imm | Opcode::Shmul64Reg => "shmul64",
683 Opcode::Sdiv64Imm | Opcode::Sdiv64Reg => "sdiv64",
684 Opcode::Srem64Imm | Opcode::Srem64Reg => "srem64",
685 Opcode::Ja => "ja",
686 Opcode::JeqImm | Opcode::JeqReg => "jeq",
687 Opcode::JgtImm | Opcode::JgtReg => "jgt",
688 Opcode::JgeImm | Opcode::JgeReg => "jge",
689 Opcode::JltImm | Opcode::JltReg => "jlt",
690 Opcode::JleImm | Opcode::JleReg => "jle",
691 Opcode::JsetImm | Opcode::JsetReg => "jset",
692 Opcode::JneImm | Opcode::JneReg => "jne",
693 Opcode::JsgtImm | Opcode::JsgtReg => "jsgt",
694 Opcode::JsgeImm | Opcode::JsgeReg => "jsge",
695 Opcode::JsltImm | Opcode::JsltReg => "jslt",
696 Opcode::JsleImm | Opcode::JsleReg => "jsle",
697 Opcode::Call => "call",
698 Opcode::Callx => "callx",
699 Opcode::Exit => "exit",
700 }
701 }
702}
703
704#[cfg(test)]
705mod tests {
706 use super::*;
707
708 #[test]
709 fn test_opcode_from_str_load_ops() {
710 assert_eq!(Opcode::from_str("lddw").unwrap(), Opcode::Lddw);
711 assert_eq!(Opcode::from_str("LDDW").unwrap(), Opcode::Lddw);
712 assert_eq!(Opcode::from_str("ldxb").unwrap(), Opcode::Ldxb);
713 assert_eq!(Opcode::from_str("ldxh").unwrap(), Opcode::Ldxh);
714 assert_eq!(Opcode::from_str("ldxw").unwrap(), Opcode::Ldxw);
715 assert_eq!(Opcode::from_str("ldxdw").unwrap(), Opcode::Ldxdw);
716 }
717
718 #[test]
719 fn test_opcode_from_str_store_ops() {
720 assert_eq!(Opcode::from_str("stb").unwrap(), Opcode::Stb);
721 assert_eq!(Opcode::from_str("sth").unwrap(), Opcode::Sth);
722 assert_eq!(Opcode::from_str("stw").unwrap(), Opcode::Stw);
723 assert_eq!(Opcode::from_str("stdw").unwrap(), Opcode::Stdw);
724 assert_eq!(Opcode::from_str("stxb").unwrap(), Opcode::Stxb);
725 assert_eq!(Opcode::from_str("stxh").unwrap(), Opcode::Stxh);
726 assert_eq!(Opcode::from_str("stxw").unwrap(), Opcode::Stxw);
727 assert_eq!(Opcode::from_str("stxdw").unwrap(), Opcode::Stxdw);
728 }
729
730 #[test]
731 fn test_opcode_from_str_alu32_ops() {
732 assert_eq!(Opcode::from_str("add32").unwrap(), Opcode::Add32Imm);
733 assert_eq!(Opcode::from_str("sub32").unwrap(), Opcode::Sub32Imm);
734 assert_eq!(Opcode::from_str("mul32").unwrap(), Opcode::Mul32Imm);
735 assert_eq!(Opcode::from_str("div32").unwrap(), Opcode::Div32Imm);
736 assert_eq!(Opcode::from_str("or32").unwrap(), Opcode::Or32Imm);
737 assert_eq!(Opcode::from_str("and32").unwrap(), Opcode::And32Imm);
738 assert_eq!(Opcode::from_str("lsh32").unwrap(), Opcode::Lsh32Imm);
739 assert_eq!(Opcode::from_str("rsh32").unwrap(), Opcode::Rsh32Imm);
740 assert_eq!(Opcode::from_str("neg32").unwrap(), Opcode::Neg32);
741 assert_eq!(Opcode::from_str("mod32").unwrap(), Opcode::Mod32Imm);
742 assert_eq!(Opcode::from_str("xor32").unwrap(), Opcode::Xor32Imm);
743 assert_eq!(Opcode::from_str("mov32").unwrap(), Opcode::Mov32Imm);
744 assert_eq!(Opcode::from_str("arsh32").unwrap(), Opcode::Arsh32Imm);
745 assert_eq!(Opcode::from_str("lmul32").unwrap(), Opcode::Lmul32Imm);
746 assert_eq!(Opcode::from_str("udiv32").unwrap(), Opcode::Udiv32Imm);
747 assert_eq!(Opcode::from_str("urem32").unwrap(), Opcode::Urem32Imm);
748 assert_eq!(Opcode::from_str("sdiv32").unwrap(), Opcode::Sdiv32Imm);
749 assert_eq!(Opcode::from_str("srem32").unwrap(), Opcode::Srem32Imm);
750 }
751
752 #[test]
753 fn test_opcode_from_str_alu64_ops() {
754 assert_eq!(Opcode::from_str("add64").unwrap(), Opcode::Add64Imm);
755 assert_eq!(Opcode::from_str("sub64").unwrap(), Opcode::Sub64Imm);
756 assert_eq!(Opcode::from_str("mul64").unwrap(), Opcode::Mul64Imm);
757 assert_eq!(Opcode::from_str("div64").unwrap(), Opcode::Div64Imm);
758 assert_eq!(Opcode::from_str("or64").unwrap(), Opcode::Or64Imm);
759 assert_eq!(Opcode::from_str("and64").unwrap(), Opcode::And64Imm);
760 assert_eq!(Opcode::from_str("neg64").unwrap(), Opcode::Neg64);
761 assert_eq!(Opcode::from_str("mov64").unwrap(), Opcode::Mov64Imm);
762 assert_eq!(Opcode::from_str("lsh64").unwrap(), Opcode::Lsh64Imm);
763 assert_eq!(Opcode::from_str("rsh64").unwrap(), Opcode::Rsh64Imm);
764 assert_eq!(Opcode::from_str("mod64").unwrap(), Opcode::Mod64Imm);
765 assert_eq!(Opcode::from_str("xor64").unwrap(), Opcode::Xor64Imm);
766 assert_eq!(Opcode::from_str("arsh64").unwrap(), Opcode::Arsh64Imm);
767 assert_eq!(Opcode::from_str("hor64").unwrap(), Opcode::Hor64Imm);
768 assert_eq!(Opcode::from_str("lmul64").unwrap(), Opcode::Lmul64Imm);
769 assert_eq!(Opcode::from_str("uhmul64").unwrap(), Opcode::Uhmul64Imm);
770 assert_eq!(Opcode::from_str("udiv64").unwrap(), Opcode::Udiv64Imm);
771 assert_eq!(Opcode::from_str("urem64").unwrap(), Opcode::Urem64Imm);
772 assert_eq!(Opcode::from_str("shmul64").unwrap(), Opcode::Shmul64Imm);
773 assert_eq!(Opcode::from_str("sdiv64").unwrap(), Opcode::Sdiv64Imm);
774 assert_eq!(Opcode::from_str("srem64").unwrap(), Opcode::Srem64Imm);
775 }
776
777 #[test]
778 fn test_opcode_from_str_be_le() {
779 assert_eq!(Opcode::from_str("le").unwrap(), Opcode::Le);
780 assert_eq!(Opcode::from_str("be").unwrap(), Opcode::Be);
781 }
782
783 #[test]
784 fn test_opcode_from_str_jump_ops() {
785 assert_eq!(Opcode::from_str("ja").unwrap(), Opcode::Ja);
786 assert_eq!(Opcode::from_str("jeq").unwrap(), Opcode::JeqImm);
787 assert_eq!(Opcode::from_str("jgt").unwrap(), Opcode::JgtImm);
788 assert_eq!(Opcode::from_str("jge").unwrap(), Opcode::JgeImm);
789 assert_eq!(Opcode::from_str("jlt").unwrap(), Opcode::JltImm);
790 assert_eq!(Opcode::from_str("jne").unwrap(), Opcode::JneImm);
791 assert_eq!(Opcode::from_str("jle").unwrap(), Opcode::JleImm);
792 assert_eq!(Opcode::from_str("jset").unwrap(), Opcode::JsetImm);
793 assert_eq!(Opcode::from_str("jsgt").unwrap(), Opcode::JsgtImm);
794 assert_eq!(Opcode::from_str("jsge").unwrap(), Opcode::JsgeImm);
795 assert_eq!(Opcode::from_str("jslt").unwrap(), Opcode::JsltImm);
796 assert_eq!(Opcode::from_str("jsle").unwrap(), Opcode::JsleImm);
797 }
798
799 #[test]
800 fn test_opcode_from_str_call_and_exit_ops() {
801 assert!(Opcode::from_str("invalid").is_err());
802 assert!(Opcode::from_str("").is_err());
803 assert!(Opcode::from_str("xyz").is_err());
804 assert_eq!(Opcode::from_str("call").unwrap(), Opcode::Call);
805 assert_eq!(Opcode::from_str("callx").unwrap(), Opcode::Callx);
806 assert_eq!(Opcode::from_str("exit").unwrap(), Opcode::Exit);
807 }
808
809 #[test]
810 fn test_opcode_from_str_invalid() {
811 assert!(Opcode::from_str("invalid").is_err());
812 assert!(Opcode::from_str("").is_err());
813 assert!(Opcode::from_str("xyz").is_err());
814 }
815
816 #[test]
817 fn test_all_load_memory_ops() {
818 for &op in LOAD_MEMORY_OPS {
819 let byte: u8 = op.into();
820 let roundtrip = Opcode::try_from(byte).unwrap();
821 assert_eq!(roundtrip, op);
822 }
823 }
824
825 #[test]
826 fn test_all_bin_imm_ops() {
827 for &op in BIN_IMM_OPS {
828 let byte: u8 = op.into();
829 let roundtrip = Opcode::try_from(byte).unwrap();
830 assert_eq!(roundtrip, op);
831 }
832 }
833
834 #[test]
835 fn test_all_jump_imm_ops() {
836 for &op in JUMP_IMM_OPS {
837 let byte: u8 = op.into();
838 let roundtrip = Opcode::try_from(byte).unwrap();
839 assert_eq!(roundtrip, op);
840 }
841 }
842
843 #[test]
844 fn test_all_store_imm_ops() {
845 for &op in STORE_IMM_OPS {
846 let byte: u8 = op.into();
847 let roundtrip = Opcode::try_from(byte).unwrap();
848 assert_eq!(roundtrip, op);
849 }
850 }
851
852 #[test]
853 fn test_all_store_reg_ops() {
854 for &op in STORE_REG_OPS {
855 let byte: u8 = op.into();
856 let roundtrip = Opcode::try_from(byte).unwrap();
857 assert_eq!(roundtrip, op);
858 }
859 }
860
861 #[test]
862 fn test_all_bin_reg_ops() {
863 for &op in BIN_REG_OPS {
864 let byte: u8 = op.into();
865 let roundtrip = Opcode::try_from(byte).unwrap();
866 assert_eq!(roundtrip, op);
867 }
868 }
869
870 #[test]
871 fn test_all_unary_ops() {
872 for &op in UNARY_OPS {
873 let byte: u8 = op.into();
874 let roundtrip = Opcode::try_from(byte).unwrap();
875 assert_eq!(roundtrip, op);
876 }
877 }
878
879 #[test]
880 fn test_all_jump_ops() {
881 for &op in JUMP_OPS {
882 let byte: u8 = op.into();
883 let roundtrip = Opcode::try_from(byte).unwrap();
884 assert_eq!(roundtrip, op);
885 }
886 }
887
888 #[test]
889 fn test_all_jump_reg_ops() {
890 for &op in JUMP_REG_OPS {
891 let byte: u8 = op.into();
892 let roundtrip = Opcode::try_from(byte).unwrap();
893 assert_eq!(roundtrip, op);
894 }
895 }
896
897 #[test]
898 fn test_all_call_ops() {
899 for &op in CALL_IMM_OPS {
900 let byte: u8 = op.into();
901 let roundtrip = Opcode::try_from(byte).unwrap();
902 assert_eq!(roundtrip, op);
903 }
904 for &op in CALL_REG_OPS {
905 let byte: u8 = op.into();
906 let roundtrip = Opcode::try_from(byte).unwrap();
907 assert_eq!(roundtrip, op);
908 }
909 }
910
911 #[test]
912 fn test_exit_op() {
913 for &op in EXIT_OPS {
914 let byte: u8 = op.into();
915 let roundtrip = Opcode::try_from(byte).unwrap();
916 assert_eq!(roundtrip, op);
917 }
918 }
919
920 #[test]
921 fn test_to_str_all_load_ops() {
922 assert_eq!(Opcode::Lddw.to_str(), "lddw");
923 assert_eq!(Opcode::Ldxb.to_str(), "ldxb");
924 assert_eq!(Opcode::Ldxh.to_str(), "ldxh");
925 assert_eq!(Opcode::Ldxw.to_str(), "ldxw");
926 assert_eq!(Opcode::Ldxdw.to_str(), "ldxdw");
927 }
928
929 #[test]
930 fn test_to_str_all_store_ops() {
931 assert_eq!(Opcode::Stb.to_str(), "stb");
932 assert_eq!(Opcode::Sth.to_str(), "sth");
933 assert_eq!(Opcode::Stw.to_str(), "stw");
934 assert_eq!(Opcode::Stdw.to_str(), "stdw");
935 assert_eq!(Opcode::Stxb.to_str(), "stxb");
936 assert_eq!(Opcode::Stxh.to_str(), "stxh");
937 assert_eq!(Opcode::Stxw.to_str(), "stxw");
938 assert_eq!(Opcode::Stxdw.to_str(), "stxdw");
939 }
940
941 #[test]
942 fn test_to_str_all_alu32_ops() {
943 assert_eq!(Opcode::Add32Imm.to_str(), "add32");
944 assert_eq!(Opcode::Add32Reg.to_str(), "add32");
945 assert_eq!(Opcode::Sub32Imm.to_str(), "sub32");
946 assert_eq!(Opcode::Mul32Imm.to_str(), "mul32");
947 assert_eq!(Opcode::Div32Imm.to_str(), "div32");
948 assert_eq!(Opcode::Or32Imm.to_str(), "or32");
949 assert_eq!(Opcode::And32Imm.to_str(), "and32");
950 assert_eq!(Opcode::Lsh32Imm.to_str(), "lsh32");
951 assert_eq!(Opcode::Rsh32Imm.to_str(), "rsh32");
952 assert_eq!(Opcode::Neg32.to_str(), "neg32");
953 assert_eq!(Opcode::Mod32Imm.to_str(), "mod32");
954 assert_eq!(Opcode::Xor32Imm.to_str(), "xor32");
955 assert_eq!(Opcode::Mov32Imm.to_str(), "mov32");
956 assert_eq!(Opcode::Arsh32Imm.to_str(), "arsh32");
957 assert_eq!(Opcode::Lmul32Imm.to_str(), "lmul32");
958 assert_eq!(Opcode::Lmul32Reg.to_str(), "lmul32");
959 assert_eq!(Opcode::Udiv32Imm.to_str(), "udiv32");
960 assert_eq!(Opcode::Urem32Imm.to_str(), "urem32");
961 assert_eq!(Opcode::Sdiv32Imm.to_str(), "sdiv32");
962 assert_eq!(Opcode::Srem32Imm.to_str(), "srem32");
963 }
964
965 #[test]
966 fn test_to_str_all_alu64_ops() {
967 assert_eq!(Opcode::Add64Imm.to_str(), "add64");
968 assert_eq!(Opcode::Sub64Imm.to_str(), "sub64");
969 assert_eq!(Opcode::Mul64Imm.to_str(), "mul64");
970 assert_eq!(Opcode::Div64Imm.to_str(), "div64");
971 assert_eq!(Opcode::Or64Imm.to_str(), "or64");
972 assert_eq!(Opcode::And64Imm.to_str(), "and64");
973 assert_eq!(Opcode::Lsh64Imm.to_str(), "lsh64");
974 assert_eq!(Opcode::Rsh64Imm.to_str(), "rsh64");
975 assert_eq!(Opcode::Neg64.to_str(), "neg64");
976 assert_eq!(Opcode::Mod64Imm.to_str(), "mod64");
977 assert_eq!(Opcode::Xor64Imm.to_str(), "xor64");
978 assert_eq!(Opcode::Mov64Imm.to_str(), "mov64");
979 assert_eq!(Opcode::Arsh64Imm.to_str(), "arsh64");
980 assert_eq!(Opcode::Hor64Imm.to_str(), "hor64");
981 assert_eq!(Opcode::Lmul64Imm.to_str(), "lmul64");
982 assert_eq!(Opcode::Uhmul64Imm.to_str(), "uhmul64");
983 assert_eq!(Opcode::Udiv64Imm.to_str(), "udiv64");
984 assert_eq!(Opcode::Urem64Imm.to_str(), "urem64");
985 assert_eq!(Opcode::Shmul64Imm.to_str(), "shmul64");
986 assert_eq!(Opcode::Sdiv64Imm.to_str(), "sdiv64");
987 assert_eq!(Opcode::Srem64Imm.to_str(), "srem64");
988 }
989
990 #[test]
991 fn test_to_str_be_le_ops() {
992 assert_eq!(Opcode::Be.to_str(), "be");
993 assert_eq!(Opcode::Le.to_str(), "le");
994 }
995
996 #[test]
997 fn test_to_str_all_jump_ops() {
998 assert_eq!(Opcode::Ja.to_str(), "ja");
999 assert_eq!(Opcode::JeqImm.to_str(), "jeq");
1000 assert_eq!(Opcode::JeqReg.to_str(), "jeq");
1001 assert_eq!(Opcode::JgtImm.to_str(), "jgt");
1002 assert_eq!(Opcode::JgeImm.to_str(), "jge");
1003 assert_eq!(Opcode::JltImm.to_str(), "jlt");
1004 assert_eq!(Opcode::JleImm.to_str(), "jle");
1005 assert_eq!(Opcode::JsetImm.to_str(), "jset");
1006 assert_eq!(Opcode::JneImm.to_str(), "jne");
1007 assert_eq!(Opcode::JsgtImm.to_str(), "jsgt");
1008 assert_eq!(Opcode::JsgeImm.to_str(), "jsge");
1009 assert_eq!(Opcode::JsltImm.to_str(), "jslt");
1010 assert_eq!(Opcode::JsleImm.to_str(), "jsle");
1011 }
1012
1013 #[test]
1014 fn test_to_str_call_and_exit_ops() {
1015 assert_eq!(Opcode::Call.to_str(), "call");
1016 assert_eq!(Opcode::Callx.to_str(), "callx");
1017 assert_eq!(Opcode::Exit.to_str(), "exit");
1018 }
1019}