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