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]; pub const LOAD_MEMORY_OPS: &[Opcode] = &[
38 Opcode::Ldxb, Opcode::Ldxh,
40 Opcode::Ldxw,
41 Opcode::Ldxdw,
42];
43
44pub const STORE_IMM_OPS: &[Opcode] = &[
45 Opcode::Stb, Opcode::Sth,
47 Opcode::Stw,
48 Opcode::Stdw,
49];
50
51pub const STORE_REG_OPS: &[Opcode] = &[
52 Opcode::Stxb, Opcode::Stxh,
54 Opcode::Stxw,
55 Opcode::Stxdw,
56];
57
58pub const BIN_IMM_OPS: &[Opcode] = &[
59 Opcode::Add32Imm, 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, Opcode::Be,
101];
102
103pub const BIN_REG_OPS: &[Opcode] = &[
104 Opcode::Add32Reg, 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, Opcode::Neg64,
145];
146
147pub const JUMP_OPS: &[Opcode] = &[Opcode::Ja]; pub const JUMP_IMM_OPS: &[Opcode] = &[
150 Opcode::JeqImm, 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, 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, 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, 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]; pub const CALL_REG_OPS: &[Opcode] = &[Opcode::Callx]; pub const EXIT_OPS: &[Opcode] = &[Opcode::Exit]; #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, FromPrimitive, Serialize, Deserialize)]
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 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}