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