1use {
2 crate::{
3 errors::SBPFError,
4 inst_param::{Number, Register},
5 instruction::Instruction,
6 opcode::Opcode,
7 syscalls::SYSCALLS,
8 },
9 either::Either,
10};
11
12#[inline]
15fn parse_bytes(bytes: &[u8]) -> Result<(Opcode, u8, u8, i16, i32), SBPFError> {
16 let opcode: Opcode = bytes[0].try_into()?;
17 let reg = bytes[1];
18 let dst = reg & 0x0f;
19 let src = reg >> 4;
20 let off = i16::from_le_bytes([bytes[2], bytes[3]]);
21 let imm = i32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
22 Ok((opcode, dst, src, off, imm))
23}
24
25#[inline]
26fn parse_bytes_v3(bytes: &[u8]) -> Result<(Opcode, u8, u8, i16, i32), SBPFError> {
27 let opcode: Opcode = Opcode::try_from_sbpf_v3(bytes[0])?;
28 let reg = bytes[1];
29 let dst = reg & 0x0f;
30 let src = reg >> 4;
31 let off = i16::from_le_bytes([bytes[2], bytes[3]]);
32 let imm = i32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
33 Ok((opcode, dst, src, off, imm))
34}
35
36pub fn decode_load_immediate(bytes: &[u8]) -> Result<Instruction, SBPFError> {
37 assert!(bytes.len() >= 16);
38 let (opcode, dst, src, off, imm_low) = parse_bytes(bytes)?;
39 if src != 0 || off != 0 {
40 return Err(SBPFError::BytecodeError {
41 error: format!(
42 "{} instruction has src: {}, off: {} supposed to be zero",
43 opcode, src, off
44 ),
45 span: 0..16,
46 custom_label: None,
47 });
48 }
49 let imm_high = i32::from_le_bytes([bytes[12], bytes[13], bytes[14], bytes[15]]);
50 let imm = ((imm_high as i64) << 32) | (imm_low as u32 as i64);
51 Ok(Instruction {
52 opcode,
53 dst: Some(Register { n: dst }),
54 src: None,
55 off: None,
56 imm: Some(Either::Right(Number::Int(imm))),
57 span: 0..16,
58 })
59}
60
61pub fn decode_load_memory(bytes: &[u8]) -> Result<Instruction, SBPFError> {
62 assert!(bytes.len() >= 8);
63 let (opcode, dst, src, off, imm) = parse_bytes(bytes)?;
64 if imm != 0 {
65 return Err(SBPFError::BytecodeError {
66 error: format!(
67 "{} instruction has imm: {} supposed to be zero",
68 opcode, imm
69 ),
70 span: 0..8,
71 custom_label: None,
72 });
73 }
74 Ok(Instruction {
75 opcode,
76 dst: Some(Register { n: dst }),
77 src: Some(Register { n: src }),
78 off: Some(Either::Right(off)),
79 imm: None,
80 span: 0..8,
81 })
82}
83
84pub fn decode_store_immediate(bytes: &[u8]) -> Result<Instruction, SBPFError> {
85 assert!(bytes.len() >= 8);
86 let (opcode, dst, src, off, imm) = parse_bytes(bytes)?;
87 if src != 0 {
88 return Err(SBPFError::BytecodeError {
89 error: format!(
90 "{} instruction has src: {} supposed to be zero",
91 opcode, src
92 ),
93 span: 0..8,
94 custom_label: None,
95 });
96 }
97 Ok(Instruction {
98 opcode,
99 dst: Some(Register { n: dst }),
100 src: None,
101 off: Some(Either::Right(off)),
102 imm: Some(Either::Right(Number::Int(imm.into()))),
103 span: 0..8,
104 })
105}
106
107pub fn decode_store_register(bytes: &[u8]) -> Result<Instruction, SBPFError> {
108 assert!(bytes.len() >= 8);
109 let (opcode, dst, src, off, imm) = parse_bytes(bytes)?;
110 if imm != 0 {
111 return Err(SBPFError::BytecodeError {
112 error: format!(
113 "{} instruction has imm: {} supposed to be zero",
114 opcode, imm
115 ),
116 span: 0..8,
117 custom_label: None,
118 });
119 }
120 Ok(Instruction {
121 opcode,
122 dst: Some(Register { n: dst }),
123 src: Some(Register { n: src }),
124 off: Some(Either::Right(off)),
125 imm: None,
126 span: 0..8,
127 })
128}
129
130pub fn decode_binary_immediate(bytes: &[u8]) -> Result<Instruction, SBPFError> {
131 assert!(bytes.len() >= 8);
132 let (opcode, dst, src, off, imm) = parse_bytes(bytes)?;
133 if src != 0 || off != 0 {
134 return Err(SBPFError::BytecodeError {
135 error: format!(
136 "{} instruction has src: {}, off: {} supposed to be zeros",
137 opcode, src, off
138 ),
139 span: 0..8,
140 custom_label: None,
141 });
142 }
143 Ok(Instruction {
144 opcode,
145 dst: Some(Register { n: dst }),
146 src: None,
147 off: None,
148 imm: Some(Either::Right(Number::Int(imm.into()))),
149 span: 0..8,
150 })
151}
152
153pub fn decode_endian(bytes: &[u8]) -> Result<Instruction, SBPFError> {
154 assert!(bytes.len() >= 8);
155 let (opcode, dst, src, off, imm) = parse_bytes(bytes)?;
156 if src != 0 || off != 0 {
157 return Err(SBPFError::BytecodeError {
158 error: format!(
159 "{} instruction has src: {}, off: {} supposed to be zeros",
160 opcode, src, off
161 ),
162 span: 0..8,
163 custom_label: None,
164 });
165 }
166 Ok(Instruction {
167 opcode,
168 dst: Some(Register { n: dst }),
169 src: None,
170 off: None,
171 imm: Some(Either::Right(Number::Int(imm.into()))),
172 span: 0..8,
173 })
174}
175
176pub fn decode_binary_register(bytes: &[u8]) -> Result<Instruction, SBPFError> {
177 assert!(bytes.len() >= 8);
178 let (opcode, dst, src, off, imm) = parse_bytes(bytes)?;
179 if off != 0 || imm != 0 {
180 return Err(SBPFError::BytecodeError {
181 error: format!(
182 "{} instruction has off: {}, imm: {} supposed to be zeros",
183 opcode, off, imm
184 ),
185 span: 0..8,
186 custom_label: None,
187 });
188 }
189 Ok(Instruction {
190 opcode,
191 dst: Some(Register { n: dst }),
192 src: Some(Register { n: src }),
193 off: None,
194 imm: None,
195 span: 0..8,
196 })
197}
198
199pub fn decode_unary(bytes: &[u8]) -> Result<Instruction, SBPFError> {
200 assert!(bytes.len() >= 8);
201 let (opcode, dst, src, off, imm) = parse_bytes(bytes)?;
202 if src != 0 || off != 0 || imm != 0 {
203 return Err(SBPFError::BytecodeError {
204 error: format!(
205 "{} instruction has src: {}, off: {}, imm: {} supposed to be zeros",
206 opcode, src, off, imm
207 ),
208 span: 0..8,
209 custom_label: None,
210 });
211 }
212 Ok(Instruction {
213 opcode,
214 dst: Some(Register { n: dst }),
215 src: None,
216 off: None,
217 imm: None,
218 span: 0..8,
219 })
220}
221
222pub fn decode_jump(bytes: &[u8]) -> Result<Instruction, SBPFError> {
223 assert!(bytes.len() >= 8);
224 let (opcode, dst, src, off, imm) = parse_bytes(bytes)?;
225 if dst != 0 || src != 0 || imm != 0 {
226 return Err(SBPFError::BytecodeError {
227 error: format!(
228 "{} instruction has dst: {}, src: {}, imm: {} supposed to be zeros",
229 opcode, dst, src, imm
230 ),
231 span: 0..8,
232 custom_label: None,
233 });
234 }
235 Ok(Instruction {
236 opcode,
237 dst: None,
238 src: None,
239 off: Some(Either::Right(off)),
240 imm: None,
241 span: 0..8,
242 })
243}
244
245pub fn decode_jump_immediate(bytes: &[u8]) -> Result<Instruction, SBPFError> {
246 assert!(bytes.len() >= 8);
247 let (opcode, dst, src, off, imm) = parse_bytes(bytes)?;
248 if src != 0 {
249 return Err(SBPFError::BytecodeError {
250 error: format!(
251 "{} instruction has src: {} supposed to be zero",
252 opcode, src
253 ),
254 span: 0..8,
255 custom_label: None,
256 });
257 }
258 Ok(Instruction {
259 opcode,
260 dst: Some(Register { n: dst }),
261 src: None,
262 off: Some(Either::Right(off)),
263 imm: Some(Either::Right(Number::Int(imm.into()))),
264 span: 0..8,
265 })
266}
267
268pub fn decode_jump_register(bytes: &[u8]) -> Result<Instruction, SBPFError> {
269 assert!(bytes.len() >= 8);
270 let (opcode, dst, src, off, imm) = parse_bytes(bytes)?;
271 if imm != 0 {
272 return Err(SBPFError::BytecodeError {
273 error: format!(
274 "{} instruction has imm: {} supposed to be zero",
275 opcode, imm
276 ),
277 span: 0..8,
278 custom_label: None,
279 });
280 }
281 Ok(Instruction {
282 opcode,
283 dst: Some(Register { n: dst }),
284 src: Some(Register { n: src }),
285 off: Some(Either::Right(off)),
286 imm: None,
287 span: 0..8,
288 })
289}
290
291pub fn decode_call_immediate(bytes: &[u8]) -> Result<Instruction, SBPFError> {
292 assert!(bytes.len() >= 8);
293 let (opcode, dst, src, off, imm) = parse_bytes(bytes)?;
294
295 if dst != 0 || off != 0 {
296 return Err(SBPFError::BytecodeError {
297 error: format!(
298 "{} instruction has dst: {} and off: {}, expected to be zeros",
299 opcode, dst, off
300 ),
301 span: 0..8,
302 custom_label: None,
303 });
304 }
305
306 let callimm = match src {
307 0 => {
308 if let Some(syscall) = SYSCALLS.get(imm as u32) {
310 Either::Left(syscall.to_string())
311 } else {
312 Either::Right(Number::Int(imm.into()))
313 }
314 }
315 1 => Either::Right(Number::Int(imm.into())),
316 _ => {
317 return Err(SBPFError::BytecodeError {
318 error: format!("{} instruction has invalid src register: {}", opcode, src),
319 span: 0..8,
320 custom_label: None,
321 });
322 }
323 };
324
325 Ok(Instruction {
326 opcode,
327 dst: None,
328 src: Some(Register { n: src }),
329 off: None,
330 imm: Some(callimm),
331 span: 0..8,
332 })
333}
334
335pub fn decode_call_register(bytes: &[u8]) -> Result<Instruction, SBPFError> {
336 assert!(bytes.len() >= 8);
337 let (opcode, dst, src, off, imm) = parse_bytes(bytes)?;
338 let (dst, imm) = if dst == 0 && imm != 0 {
340 (imm as u8, 0)
341 } else {
342 (dst, 0)
343 };
344
345 if src != 0 || off != 0 || imm != 0 {
347 return Err(SBPFError::BytecodeError {
348 error: format!(
349 "{} instruction has src: {}, off: {}, imm: {} supposed to be zeros",
350 opcode, src, off, imm
351 ),
352 span: 0..8,
353 custom_label: None,
354 });
355 }
356 Ok(Instruction {
357 opcode,
358 dst: Some(Register { n: dst }),
359 src: None,
360 off: None,
361 imm: None,
362 span: 0..8,
363 })
364}
365
366pub fn decode_exit(bytes: &[u8]) -> Result<Instruction, SBPFError> {
367 assert!(bytes.len() >= 8);
368 let (opcode, dst, src, off, imm) = parse_bytes(bytes)?;
369 if dst != 0 || src != 0 || off != 0 || imm != 0 {
370 return Err(SBPFError::BytecodeError {
371 error: format!(
372 "{} instruction dst: {}, src: {}, off: {}, imm: {} supposed to be zero",
373 opcode, dst, src, off, imm
374 ),
375 span: 0..8,
376 custom_label: None,
377 });
378 }
379 Ok(Instruction {
380 opcode,
381 dst: None,
382 src: None,
383 off: None,
384 imm: None,
385 span: 0..8,
386 })
387}
388
389pub fn decode_jump32_immediate(bytes: &[u8]) -> Result<Instruction, SBPFError> {
390 assert!(bytes.len() >= 8);
391 let (opcode, dst, src, off, imm) = parse_bytes_v3(bytes)?;
392 if src != 0 {
393 return Err(SBPFError::BytecodeError {
394 error: format!(
395 "{} instruction has src: {} supposed to be zero",
396 opcode, src
397 ),
398 span: 0..8,
399 custom_label: None,
400 });
401 }
402 Ok(Instruction {
403 opcode,
404 dst: Some(Register { n: dst }),
405 src: None,
406 off: Some(Either::Right(off)),
407 imm: Some(Either::Right(Number::Int(imm.into()))),
408 span: 0..8,
409 })
410}
411
412pub fn decode_jump32_register(bytes: &[u8]) -> Result<Instruction, SBPFError> {
413 assert!(bytes.len() >= 8);
414 let (opcode, dst, src, off, imm) = parse_bytes_v3(bytes)?;
415 if imm != 0 {
416 return Err(SBPFError::BytecodeError {
417 error: format!(
418 "{} instruction has imm: {} supposed to be zero",
419 opcode, imm
420 ),
421 span: 0..8,
422 custom_label: None,
423 });
424 }
425 Ok(Instruction {
426 opcode,
427 dst: Some(Register { n: dst }),
428 src: Some(Register { n: src }),
429 off: Some(Either::Right(off)),
430 imm: None,
431 span: 0..8,
432 })
433}
434
435#[cfg(test)]
436mod tests {
437 use {super::*, crate::syscalls::REGISTERED_SYSCALLS, syscall_map::murmur3_32};
438
439 #[test]
440 fn test_decode_load_immediate_valid() {
441 let mut bytes = vec![0x18, 0x01, 0x00, 0x00, 0xf0, 0xde, 0xbc, 0x9a];
443 bytes.extend_from_slice(&[0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12]);
444
445 let result = decode_load_immediate(&bytes).unwrap();
446 assert_eq!(result.opcode, Opcode::Lddw);
447 assert_eq!(result.dst.unwrap().n, 1);
448 assert!(result.src.is_none());
449 assert!(result.off.is_none());
450 assert_eq!(result.span, 0..16);
451 }
452
453 #[test]
454 fn test_decode_load_immediate_error_nonzero_src() {
455 let mut bytes = vec![0x18, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
456 bytes.extend_from_slice(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
457
458 let result = decode_load_immediate(&bytes);
459 assert!(result.is_err());
460 }
461
462 #[test]
463 fn test_decode_load_immediate_error_nonzero_off() {
464 let mut bytes = vec![0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00];
465 bytes.extend_from_slice(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
466
467 let result = decode_load_immediate(&bytes);
468 assert!(result.is_err());
469 }
470
471 #[test]
472 fn test_decode_load_memory_valid() {
473 let bytes = vec![0x61, 0x32, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00];
475
476 let result = decode_load_memory(&bytes).unwrap();
477 assert_eq!(result.opcode, Opcode::Ldxw);
478 assert_eq!(result.dst.unwrap().n, 2);
479 assert_eq!(result.src.unwrap().n, 3);
480 assert_eq!(result.span, 0..8);
481 }
482
483 #[test]
484 fn test_decode_load_memory_error_nonzero_imm() {
485 let bytes = vec![0x61, 0x32, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00];
486
487 let result = decode_load_memory(&bytes);
488 assert!(result.is_err());
489 }
490
491 #[test]
492 fn test_decode_store_immediate_valid() {
493 let bytes = vec![0x62, 0x01, 0x04, 0x00, 0x64, 0x00, 0x00, 0x00];
495
496 let result = decode_store_immediate(&bytes).unwrap();
497 assert_eq!(result.opcode, Opcode::Stw);
498 assert_eq!(result.dst.unwrap().n, 1);
499 assert!(result.src.is_none());
500 assert_eq!(result.span, 0..8);
501 }
502
503 #[test]
504 fn test_decode_store_immediate_error_nonzero_src() {
505 let bytes = vec![0x62, 0x11, 0x04, 0x00, 0x64, 0x00, 0x00, 0x00];
506
507 let result = decode_store_immediate(&bytes);
508 assert!(result.is_err());
509 }
510
511 #[test]
512 fn test_decode_store_register_valid() {
513 let bytes = vec![0x63, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00];
515
516 let result = decode_store_register(&bytes).unwrap();
517 assert_eq!(result.opcode, Opcode::Stxw);
518 assert_eq!(result.dst.unwrap().n, 1);
519 assert_eq!(result.src.unwrap().n, 2);
520 assert_eq!(result.span, 0..8);
521 }
522
523 #[test]
524 fn test_decode_store_register_error_nonzero_imm() {
525 let bytes = vec![0x63, 0x21, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00];
526
527 let result = decode_store_register(&bytes);
528 assert!(result.is_err());
529 }
530
531 #[test]
532 fn test_decode_binary_immediate_valid() {
533 let bytes = vec![0x04, 0x01, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00];
535
536 let result = decode_binary_immediate(&bytes).unwrap();
537 assert_eq!(result.opcode, Opcode::Add32Imm);
538 assert_eq!(result.dst.unwrap().n, 1);
539 assert!(result.src.is_none());
540 assert!(result.off.is_none());
541 assert_eq!(result.span, 0..8);
542 }
543
544 #[test]
545 fn test_decode_binary_immediate_error_nonzero_src() {
546 let bytes = vec![0x04, 0x11, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00];
547
548 let result = decode_binary_immediate(&bytes);
549 assert!(result.is_err());
550 }
551
552 #[test]
553 fn test_decode_binary_immediate_error_nonzero_off() {
554 let bytes = vec![0x04, 0x01, 0x01, 0x00, 0x64, 0x00, 0x00, 0x00];
555
556 let result = decode_binary_immediate(&bytes);
557 assert!(result.is_err());
558 }
559
560 #[test]
561 fn test_decode_binary_register_valid() {
562 let bytes = vec![0x0c, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
564
565 let result = decode_binary_register(&bytes).unwrap();
566 assert_eq!(result.opcode, Opcode::Add32Reg);
567 assert_eq!(result.dst.unwrap().n, 1);
568 assert_eq!(result.src.unwrap().n, 2);
569 assert!(result.off.is_none());
570 assert!(result.imm.is_none());
571 assert_eq!(result.span, 0..8);
572 }
573
574 #[test]
575 fn test_decode_binary_register_error_nonzero_off() {
576 let bytes = vec![0x0c, 0x21, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00];
577
578 let result = decode_binary_register(&bytes);
579 assert!(result.is_err());
580 }
581
582 #[test]
583 fn test_decode_binary_register_error_nonzero_imm() {
584 let bytes = vec![0x0c, 0x21, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00];
585
586 let result = decode_binary_register(&bytes);
587 assert!(result.is_err());
588 }
589
590 #[test]
591 fn test_decode_unary_valid() {
592 let bytes = vec![0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
594
595 let result = decode_unary(&bytes).unwrap();
596 assert_eq!(result.opcode, Opcode::Neg64);
597 assert_eq!(result.dst.unwrap().n, 1);
598 assert!(result.src.is_none());
599 assert!(result.off.is_none());
600 assert!(result.imm.is_none());
601 assert_eq!(result.span, 0..8);
602 }
603
604 #[test]
605 fn test_decode_unary_error_nonzero_src() {
606 let bytes = vec![0x87, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
607
608 let result = decode_unary(&bytes);
609 assert!(result.is_err());
610 }
611
612 #[test]
613 fn test_decode_unary_error_nonzero_off() {
614 let bytes = vec![0x87, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00];
615
616 let result = decode_unary(&bytes);
617 assert!(result.is_err());
618 }
619
620 #[test]
621 fn test_decode_unary_error_nonzero_imm() {
622 let bytes = vec![0x87, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00];
623
624 let result = decode_unary(&bytes);
625 assert!(result.is_err());
626 }
627
628 #[test]
629 fn test_decode_endian_valid() {
630 let bytes = vec![0xd4, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00];
632
633 let result = decode_endian(&bytes).unwrap();
634 assert_eq!(result.opcode, Opcode::Le);
635 assert_eq!(result.dst.unwrap().n, 1);
636 assert!(result.src.is_none());
637 assert!(result.off.is_none());
638 assert_eq!(result.span, 0..8);
639 }
640
641 #[test]
642 fn test_decode_endian_error_nonzero_src() {
643 let bytes = vec![0xd4, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00];
644
645 let result = decode_endian(&bytes);
646 assert!(result.is_err());
647 }
648
649 #[test]
650 fn test_decode_endian_error_nonzero_off() {
651 let bytes = vec![0xdc, 0x01, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00];
652
653 let result = decode_endian(&bytes);
654 assert!(result.is_err());
655 }
656
657 #[test]
658 fn test_decode_jump_valid() {
659 let bytes = vec![0x05, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00];
661
662 let result = decode_jump(&bytes).unwrap();
663 assert_eq!(result.opcode, Opcode::Ja);
664 assert!(result.dst.is_none());
665 assert!(result.src.is_none());
666 assert!(result.imm.is_none());
667 assert_eq!(result.span, 0..8);
668 }
669
670 #[test]
671 fn test_decode_jump_error_nonzero_dst() {
672 let bytes = vec![0x05, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00];
673
674 let result = decode_jump(&bytes);
675 assert!(result.is_err());
676 }
677
678 #[test]
679 fn test_decode_jump_error_nonzero_src() {
680 let bytes = vec![0x05, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00];
681
682 let result = decode_jump(&bytes);
683 assert!(result.is_err());
684 }
685
686 #[test]
687 fn test_decode_jump_error_nonzero_imm() {
688 let bytes = vec![0x05, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00];
689
690 let result = decode_jump(&bytes);
691 assert!(result.is_err());
692 }
693
694 #[test]
695 fn test_decode_jump_immediate_valid() {
696 let bytes = vec![0x15, 0x01, 0x0a, 0x00, 0x64, 0x00, 0x00, 0x00];
698
699 let result = decode_jump_immediate(&bytes).unwrap();
700 assert_eq!(result.opcode, Opcode::JeqImm);
701 assert_eq!(result.dst.unwrap().n, 1);
702 assert!(result.src.is_none());
703 assert_eq!(result.span, 0..8);
704 }
705
706 #[test]
707 fn test_decode_jump_immediate_error_nonzero_src() {
708 let bytes = vec![0x15, 0x11, 0x0a, 0x00, 0x64, 0x00, 0x00, 0x00];
709
710 let result = decode_jump_immediate(&bytes);
711 assert!(result.is_err());
712 }
713
714 #[test]
715 fn test_decode_jump_register_valid() {
716 let bytes = vec![0x1d, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00];
718
719 let result = decode_jump_register(&bytes).unwrap();
720 assert_eq!(result.opcode, Opcode::JeqReg);
721 assert_eq!(result.dst.unwrap().n, 1);
722 assert_eq!(result.src.unwrap().n, 2);
723 assert_eq!(result.span, 0..8);
724 }
725
726 #[test]
727 fn test_decode_jump_register_error_nonzero_imm() {
728 let bytes = vec![0x1d, 0x21, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00];
729
730 let result = decode_jump_register(&bytes);
731 assert!(result.is_err());
732 }
733
734 #[test]
735 fn test_decode_call_immediate_valid_regular() {
736 let bytes = vec![0x85, 0x10, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00];
738
739 let result = decode_call_immediate(&bytes).unwrap();
740 assert_eq!(result.opcode, Opcode::Call);
741 assert!(result.dst.is_none());
742 assert_eq!(result.src.unwrap().n, 1);
743 assert_eq!(result.span, 0..8);
744 }
745
746 #[test]
747 fn test_decode_call_immediate_error_invalid_regular() {
748 let bytes = vec![0x85, 0x01, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00];
750
751 let result = decode_call_immediate(&bytes);
752 assert!(result.is_err());
753 }
754
755 #[test]
756 fn test_decode_call_immediate_valid_syscall() {
757 let syscall_name = REGISTERED_SYSCALLS[0];
758 let syscall_hash = murmur3_32(syscall_name);
759 let hash_bytes = syscall_hash.to_le_bytes();
760
761 let bytes = vec![
763 0x85,
764 0x00,
765 0x00,
766 0x00,
767 hash_bytes[0],
768 hash_bytes[1],
769 hash_bytes[2],
770 hash_bytes[3],
771 ];
772
773 let result = decode_call_immediate(&bytes).unwrap();
774 assert_eq!(result.opcode, Opcode::Call);
775 assert!(result.dst.is_none());
776 assert_eq!(result.src.unwrap().n, 0);
777 }
778
779 #[test]
780 fn test_decode_call_immediate_syscall_error_nonzero_dst() {
781 let syscall_hash = murmur3_32(REGISTERED_SYSCALLS[0]);
782 let hash_bytes = syscall_hash.to_le_bytes();
783
784 let bytes = vec![
785 0x85,
786 0x01,
787 0x00,
788 0x00,
789 hash_bytes[0],
790 hash_bytes[1],
791 hash_bytes[2],
792 hash_bytes[3],
793 ];
794
795 let result = decode_call_immediate(&bytes);
796 assert!(result.is_err());
797 }
798
799 #[test]
800 fn test_decode_call_immediate_syscall_nonzero_src() {
801 let syscall_hash = murmur3_32(REGISTERED_SYSCALLS[0]);
802 let hash_bytes = syscall_hash.to_le_bytes();
803
804 let bytes = vec![
805 0x85,
806 0x10,
807 0x00,
808 0x00,
809 hash_bytes[0],
810 hash_bytes[1],
811 hash_bytes[2],
812 hash_bytes[3],
813 ];
814
815 let result = decode_call_immediate(&bytes).unwrap();
816 assert_eq!(result.src.unwrap().n, 1);
817 assert!(matches!(result.imm, Some(Either::Right(_))));
818 }
819
820 #[test]
821 fn test_decode_call_immediate_syscall_error_nonzero_off() {
822 let syscall_hash = murmur3_32(REGISTERED_SYSCALLS[0]);
823 let hash_bytes = syscall_hash.to_le_bytes();
824
825 let bytes = vec![
826 0x85,
827 0x00,
828 0x01,
829 0x00,
830 hash_bytes[0],
831 hash_bytes[1],
832 hash_bytes[2],
833 hash_bytes[3],
834 ];
835 let result = decode_call_immediate(&bytes);
836 assert!(result.is_err());
837 }
838
839 #[test]
840 fn test_decode_call_register_valid() {
841 let bytes = vec![0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
843
844 let result = decode_call_register(&bytes).unwrap();
845 assert_eq!(result.opcode, Opcode::Callx);
846 assert_eq!(result.dst.unwrap().n, 1);
847 assert!(result.src.is_none());
848 assert!(result.off.is_none());
849 assert!(result.imm.is_none());
850 assert_eq!(result.span, 0..8);
851 }
852
853 #[test]
854 fn test_decode_call_register_normalized() {
855 let bytes = vec![0x8d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00];
857 let result = decode_call_register(&bytes).unwrap();
858 assert_eq!(result.dst.unwrap().n, 5);
859 }
860
861 #[test]
862 fn test_decode_call_register_error_nonzero_src() {
863 let bytes = vec![0x8d, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
864
865 let result = decode_call_register(&bytes);
866 assert!(result.is_err());
867 }
868
869 #[test]
870 fn test_decode_call_register_error_nonzero_off() {
871 let bytes = vec![0x8d, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00];
872
873 let result = decode_call_register(&bytes);
874 assert!(result.is_err());
875 }
876
877 #[test]
878 fn test_decode_exit_valid() {
879 let bytes = vec![0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
881
882 let result = decode_exit(&bytes).unwrap();
883 assert_eq!(result.opcode, Opcode::Exit);
884 assert!(result.dst.is_none());
885 assert!(result.src.is_none());
886 assert!(result.off.is_none());
887 assert!(result.imm.is_none());
888 assert_eq!(result.span, 0..8);
889 }
890
891 #[test]
892 fn test_decode_exit_error_nonzero_dst() {
893 let bytes = vec![0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
894
895 let result = decode_exit(&bytes);
896 assert!(result.is_err());
897 }
898
899 #[test]
900 fn test_decode_exit_error_nonzero_src() {
901 let bytes = vec![0x95, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
902
903 let result = decode_exit(&bytes);
904 assert!(result.is_err());
905 }
906
907 #[test]
908 fn test_decode_exit_error_nonzero_off() {
909 let bytes = vec![0x95, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00];
910
911 let result = decode_exit(&bytes);
912 assert!(result.is_err());
913 }
914
915 #[test]
916 fn test_decode_exit_error_nonzero_imm() {
917 let bytes = vec![0x95, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00];
918
919 let result = decode_exit(&bytes);
920 assert!(result.is_err());
921 }
922
923 #[test]
924 fn test_all_load_memory_opcodes() {
925 let opcodes = vec![
926 (0x71, Opcode::Ldxb),
927 (0x69, Opcode::Ldxh),
928 (0x61, Opcode::Ldxw),
929 (0x79, Opcode::Ldxdw),
930 ];
931
932 for (byte, expected_opcode) in opcodes {
933 let bytes = vec![byte, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00];
934 let result = decode_load_memory(&bytes).unwrap();
935 assert_eq!(result.opcode, expected_opcode);
936 }
937 }
938
939 #[test]
940 fn test_all_store_immediate_opcodes() {
941 let opcodes = vec![
942 (0x72, Opcode::Stb),
943 (0x6a, Opcode::Sth),
944 (0x62, Opcode::Stw),
945 (0x7a, Opcode::Stdw),
946 ];
947
948 for (byte, expected_opcode) in opcodes {
949 let bytes = vec![byte, 0x01, 0x04, 0x00, 0x64, 0x00, 0x00, 0x00];
950 let result = decode_store_immediate(&bytes).unwrap();
951 assert_eq!(result.opcode, expected_opcode);
952 }
953 }
954
955 #[test]
956 fn test_all_store_register_opcodes() {
957 let opcodes = vec![
958 (0x73, Opcode::Stxb),
959 (0x6b, Opcode::Stxh),
960 (0x63, Opcode::Stxw),
961 (0x7b, Opcode::Stxdw),
962 ];
963
964 for (byte, expected_opcode) in opcodes {
965 let bytes = vec![byte, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00];
966 let result = decode_store_register(&bytes).unwrap();
967 assert_eq!(result.opcode, expected_opcode);
968 }
969 }
970
971 #[test]
972 fn test_decode_alu64_operations() {
973 let ops = vec![
974 (0x07, Opcode::Add64Imm),
975 (0x0f, Opcode::Add64Reg),
976 (0x17, Opcode::Sub64Imm),
977 (0x1f, Opcode::Sub64Reg),
978 ];
979
980 for (byte, expected_opcode) in ops {
981 let mut bytes = vec![byte, 0x01, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00];
982
983 if byte & 0x08 == 0 {
984 let result = decode_binary_immediate(&bytes).unwrap();
986 assert_eq!(result.opcode, expected_opcode);
987 } else {
988 bytes[4] = 0x00; bytes[1] = 0x21; let result = decode_binary_register(&bytes).unwrap();
992 assert_eq!(result.opcode, expected_opcode);
993 }
994 }
995 }
996
997 #[test]
998 fn test_decode_neg32() {
999 let bytes = vec![0x84, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
1000
1001 let result = decode_unary(&bytes).unwrap();
1002 assert_eq!(result.opcode, Opcode::Neg32);
1003 assert_eq!(result.dst.unwrap().n, 1);
1004 }
1005
1006 #[test]
1007 fn test_decode_various_jump_immediates() {
1008 let jumps = vec![
1009 (0x15, Opcode::JeqImm),
1010 (0x25, Opcode::JgtImm),
1011 (0x35, Opcode::JgeImm),
1012 ];
1013
1014 for (byte, expected_opcode) in jumps {
1015 let bytes = vec![byte, 0x01, 0x0a, 0x00, 0x64, 0x00, 0x00, 0x00];
1016 let result = decode_jump_immediate(&bytes).unwrap();
1017 assert_eq!(result.opcode, expected_opcode);
1018 }
1019 }
1020
1021 #[test]
1022 fn test_decode_various_jump_registers() {
1023 let jumps = vec![
1024 (0x1d, Opcode::JeqReg),
1025 (0x2d, Opcode::JgtReg),
1026 (0x3d, Opcode::JgeReg),
1027 ];
1028
1029 for (byte, expected_opcode) in jumps {
1030 let bytes = vec![byte, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00];
1031 let result = decode_jump_register(&bytes).unwrap();
1032 assert_eq!(result.opcode, expected_opcode);
1033 }
1034 }
1035
1036 #[test]
1037 fn test_decode_static_syscall_unknown_hash() {
1038 let unknown_hash: u32 = 0x12345678;
1039 let hash_bytes = unknown_hash.to_le_bytes();
1040
1041 let bytes = vec![
1042 0x85,
1043 0x00, 0x00,
1045 0x00,
1046 hash_bytes[0],
1047 hash_bytes[1],
1048 hash_bytes[2],
1049 hash_bytes[3],
1050 ];
1051
1052 let result = decode_call_immediate(&bytes).unwrap();
1053 assert_eq!(result.opcode, Opcode::Call);
1054 assert!(result.dst.is_none());
1055 assert_eq!(result.src.unwrap().n, 0);
1056
1057 match result.imm {
1059 Some(Either::Right(Number::Int(imm))) => {
1060 assert_eq!(imm as u32, unknown_hash);
1061 }
1062 _ => panic!("Expected numeric immediate for unknown syscall hash"),
1063 }
1064 }
1065
1066 #[test]
1067 fn test_decode_call_invalid_src_register() {
1068 let bytes = vec![0x85, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let result = decode_call_immediate(&bytes);
1070 assert!(result.is_err());
1071 }
1072}