Skip to main content

sbpf_common/
opcode.rs

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]; // OperationType::LoadImmediate
33
34pub const LOAD_MEMORY_OPS: &[Opcode] = &[
35    Opcode::Ldxb, // OperationType::LoadMemory
36    Opcode::Ldxh,
37    Opcode::Ldxw,
38    Opcode::Ldxdw,
39];
40
41pub const STORE_IMM_OPS: &[Opcode] = &[
42    Opcode::Stb, // OperationType::StoreImmediate
43    Opcode::Sth,
44    Opcode::Stw,
45    Opcode::Stdw,
46];
47
48pub const STORE_REG_OPS: &[Opcode] = &[
49    Opcode::Stxb, // OperationType::StoreRegister
50    Opcode::Stxh,
51    Opcode::Stxw,
52    Opcode::Stxdw,
53];
54
55pub const BIN_IMM_OPS: &[Opcode] = &[
56    Opcode::Add32Imm, // OperationType::BinaryImmediate
57    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, // OperationType::BinaryRegister
99    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, // OperationType::Unary
138    Opcode::Neg64,
139];
140
141pub const JUMP_OPS: &[Opcode] = &[Opcode::Ja]; // OperationType::Jump
142
143pub const JUMP_IMM_OPS: &[Opcode] = &[
144    Opcode::JeqImm, // OperationType::JumpImmediate
145    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, // OperationType::JumpRegister
159    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]; // OperationType::CallImmediate
172
173pub const CALL_REG_OPS: &[Opcode] = &[Opcode::Callx]; // OperationType::CallRegister
174
175pub const EXIT_OPS: &[Opcode] = &[Opcode::Exit]; // OperationType::Exit
176//
177#[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}