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