Skip to main content

sbpf_common/execute/
jump.rs

1use {
2    super::{ExecutionResult, Vm, helpers::*},
3    crate::{errors::ExecutionError, instruction::Instruction, opcode::Opcode},
4};
5
6pub fn execute_jump(vm: &mut dyn Vm, inst: &Instruction) -> ExecutionResult<()> {
7    let off = get_offset(inst)?;
8    vm.set_pc(((vm.get_pc() as i64) + 1 + (off as i64)) as usize);
9    Ok(())
10}
11
12pub fn execute_jump_immediate(vm: &mut dyn Vm, inst: &Instruction) -> ExecutionResult<()> {
13    match inst.opcode {
14        Opcode::JeqImm => execute_jump_immediate_conditional(vm, inst, |a, b| a == b),
15        Opcode::JgtImm => execute_jump_immediate_conditional(vm, inst, |a, b| a > b),
16        Opcode::JgeImm => execute_jump_immediate_conditional(vm, inst, |a, b| a >= b),
17        Opcode::JltImm => execute_jump_immediate_conditional(vm, inst, |a, b| a < b),
18        Opcode::JleImm => execute_jump_immediate_conditional(vm, inst, |a, b| a <= b),
19        Opcode::JsetImm => execute_jump_immediate_conditional(vm, inst, |a, b| (a & b) != 0),
20        Opcode::JneImm => execute_jump_immediate_conditional(vm, inst, |a, b| a != b),
21        Opcode::JsgtImm => {
22            execute_jump_immediate_conditional(vm, inst, |a, b| (a as i64) > (b as i64))
23        }
24        Opcode::JsgeImm => {
25            execute_jump_immediate_conditional(vm, inst, |a, b| (a as i64) >= (b as i64))
26        }
27        Opcode::JsltImm => {
28            execute_jump_immediate_conditional(vm, inst, |a, b| (a as i64) < (b as i64))
29        }
30        Opcode::JsleImm => {
31            execute_jump_immediate_conditional(vm, inst, |a, b| (a as i64) <= (b as i64))
32        }
33        Opcode::Jeq32Imm => execute_jump_immediate_conditional_u32(vm, inst, |a, b| a == b),
34        Opcode::Jgt32Imm => execute_jump_immediate_conditional_u32(vm, inst, |a, b| a > b),
35        Opcode::Jge32Imm => execute_jump_immediate_conditional_u32(vm, inst, |a, b| a >= b),
36        Opcode::Jlt32Imm => execute_jump_immediate_conditional_u32(vm, inst, |a, b| a < b),
37        Opcode::Jle32Imm => execute_jump_immediate_conditional_u32(vm, inst, |a, b| a <= b),
38        Opcode::Jset32Imm => execute_jump_immediate_conditional_u32(vm, inst, |a, b| (a & b) != 0),
39        Opcode::Jne32Imm => execute_jump_immediate_conditional_u32(vm, inst, |a, b| a != b),
40        Opcode::Jsgt32Imm => execute_jump_immediate_conditional_i32(vm, inst, |a, b| a > b),
41        Opcode::Jsge32Imm => execute_jump_immediate_conditional_i32(vm, inst, |a, b| a >= b),
42        Opcode::Jslt32Imm => execute_jump_immediate_conditional_i32(vm, inst, |a, b| a < b),
43        Opcode::Jsle32Imm => execute_jump_immediate_conditional_i32(vm, inst, |a, b| a <= b),
44        _ => Err(ExecutionError::InvalidInstruction),
45    }
46}
47
48pub fn execute_jump_register(vm: &mut dyn Vm, inst: &Instruction) -> ExecutionResult<()> {
49    match inst.opcode {
50        Opcode::JeqReg => execute_jump_register_conditional(vm, inst, |a, b| a == b),
51        Opcode::JgtReg => execute_jump_register_conditional(vm, inst, |a, b| a > b),
52        Opcode::JgeReg => execute_jump_register_conditional(vm, inst, |a, b| a >= b),
53        Opcode::JltReg => execute_jump_register_conditional(vm, inst, |a, b| a < b),
54        Opcode::JleReg => execute_jump_register_conditional(vm, inst, |a, b| a <= b),
55        Opcode::JsetReg => execute_jump_register_conditional(vm, inst, |a, b| (a & b) != 0),
56        Opcode::JneReg => execute_jump_register_conditional(vm, inst, |a, b| a != b),
57        Opcode::JsgtReg => {
58            execute_jump_register_conditional(vm, inst, |a, b| (a as i64) > (b as i64))
59        }
60        Opcode::JsgeReg => {
61            execute_jump_register_conditional(vm, inst, |a, b| (a as i64) >= (b as i64))
62        }
63        Opcode::JsltReg => {
64            execute_jump_register_conditional(vm, inst, |a, b| (a as i64) < (b as i64))
65        }
66        Opcode::JsleReg => {
67            execute_jump_register_conditional(vm, inst, |a, b| (a as i64) <= (b as i64))
68        }
69        Opcode::Jeq32Reg => execute_jump_register_conditional_u32(vm, inst, |a, b| a == b),
70        Opcode::Jgt32Reg => execute_jump_register_conditional_u32(vm, inst, |a, b| a > b),
71        Opcode::Jge32Reg => execute_jump_register_conditional_u32(vm, inst, |a, b| a >= b),
72        Opcode::Jlt32Reg => execute_jump_register_conditional_u32(vm, inst, |a, b| a < b),
73        Opcode::Jle32Reg => execute_jump_register_conditional_u32(vm, inst, |a, b| a <= b),
74        Opcode::Jset32Reg => execute_jump_register_conditional_u32(vm, inst, |a, b| (a & b) != 0),
75        Opcode::Jne32Reg => execute_jump_register_conditional_u32(vm, inst, |a, b| a != b),
76        Opcode::Jsgt32Reg => execute_jump_register_conditional_i32(vm, inst, |a, b| a > b),
77        Opcode::Jsge32Reg => execute_jump_register_conditional_i32(vm, inst, |a, b| a >= b),
78        Opcode::Jslt32Reg => execute_jump_register_conditional_i32(vm, inst, |a, b| a < b),
79        Opcode::Jsle32Reg => execute_jump_register_conditional_i32(vm, inst, |a, b| a <= b),
80        _ => Err(ExecutionError::InvalidInstruction),
81    }
82}
83
84fn execute_jump_immediate_conditional(
85    vm: &mut dyn Vm,
86    inst: &Instruction,
87    condition: fn(u64, u64) -> bool,
88) -> ExecutionResult<()> {
89    let dst = get_dst(inst)?;
90    let off = get_offset(inst)?;
91    let imm = (get_imm_i64(inst)? as i32 as i64) as u64;
92
93    if condition(vm.get_register(dst), imm) {
94        vm.set_pc(((vm.get_pc() as i64) + 1 + (off as i64)) as usize);
95    } else {
96        vm.advance_pc();
97    }
98    Ok(())
99}
100
101fn execute_jump_register_conditional(
102    vm: &mut dyn Vm,
103    inst: &Instruction,
104    condition: fn(u64, u64) -> bool,
105) -> ExecutionResult<()> {
106    let dst = get_dst(inst)?;
107    let src = get_src(inst)?;
108    let off = get_offset(inst)?;
109
110    if condition(vm.get_register(dst), vm.get_register(src)) {
111        vm.set_pc(((vm.get_pc() as i64) + 1 + (off as i64)) as usize);
112    } else {
113        vm.advance_pc();
114    }
115    Ok(())
116}
117
118fn execute_jump_immediate_conditional_u32(
119    vm: &mut dyn Vm,
120    inst: &Instruction,
121    condition: fn(u32, u32) -> bool,
122) -> ExecutionResult<()> {
123    let dst = get_dst(inst)?;
124    let off = get_offset(inst)?;
125    let lhs = vm.get_register(dst) as u32;
126    let rhs = get_imm_i64(inst)? as u32;
127
128    if condition(lhs, rhs) {
129        vm.set_pc(((vm.get_pc() as i64) + 1 + (off as i64)) as usize);
130    } else {
131        vm.advance_pc();
132    }
133    Ok(())
134}
135
136fn execute_jump_immediate_conditional_i32(
137    vm: &mut dyn Vm,
138    inst: &Instruction,
139    condition: fn(i32, i32) -> bool,
140) -> ExecutionResult<()> {
141    let dst = get_dst(inst)?;
142    let off = get_offset(inst)?;
143    let lhs = vm.get_register(dst) as i32;
144    let rhs = get_imm_i64(inst)? as i32;
145
146    if condition(lhs, rhs) {
147        vm.set_pc(((vm.get_pc() as i64) + 1 + (off as i64)) as usize);
148    } else {
149        vm.advance_pc();
150    }
151    Ok(())
152}
153
154fn execute_jump_register_conditional_u32(
155    vm: &mut dyn Vm,
156    inst: &Instruction,
157    condition: fn(u32, u32) -> bool,
158) -> ExecutionResult<()> {
159    let dst = get_dst(inst)?;
160    let src = get_src(inst)?;
161    let off = get_offset(inst)?;
162    let lhs = vm.get_register(dst) as u32;
163    let rhs = vm.get_register(src) as u32;
164
165    if condition(lhs, rhs) {
166        vm.set_pc(((vm.get_pc() as i64) + 1 + (off as i64)) as usize);
167    } else {
168        vm.advance_pc();
169    }
170    Ok(())
171}
172
173fn execute_jump_register_conditional_i32(
174    vm: &mut dyn Vm,
175    inst: &Instruction,
176    condition: fn(i32, i32) -> bool,
177) -> ExecutionResult<()> {
178    let dst = get_dst(inst)?;
179    let src = get_src(inst)?;
180    let off = get_offset(inst)?;
181    let lhs = vm.get_register(dst) as i32;
182    let rhs = vm.get_register(src) as i32;
183
184    if condition(lhs, rhs) {
185        vm.set_pc(((vm.get_pc() as i64) + 1 + (off as i64)) as usize);
186    } else {
187        vm.advance_pc();
188    }
189    Ok(())
190}
191
192#[cfg(test)]
193mod tests {
194    use {
195        super::*,
196        crate::{
197            execute::{MockVm, make_test_instruction},
198            inst_param::{Number, Register},
199        },
200        either::Either,
201    };
202
203    #[test]
204    fn test_ja_forward() {
205        // ja +5
206        let inst = make_test_instruction(Opcode::Ja, None, None, Some(Either::Right(5)), None);
207        let mut vm = MockVm::new();
208
209        execute_jump(&mut vm, &inst).unwrap();
210
211        assert_eq!(vm.pc, 6);
212    }
213
214    #[test]
215    fn test_ja_backward() {
216        // ja -3
217        let inst = make_test_instruction(Opcode::Ja, None, None, Some(Either::Right(-3)), None);
218        let mut vm = MockVm::new();
219        vm.pc = 10;
220
221        execute_jump(&mut vm, &inst).unwrap();
222
223        assert_eq!(vm.pc, 8);
224    }
225
226    #[test]
227    fn test_jeq_imm() {
228        // jeq r1, 5, +10
229        let inst = make_test_instruction(
230            Opcode::JeqImm,
231            Some(Register { n: 1 }),
232            None,
233            Some(Either::Right(10)),
234            Some(Either::Right(Number::Int(5))),
235        );
236        let mut vm = MockVm::new();
237        vm.registers[1] = 5;
238
239        execute_jump_immediate(&mut vm, &inst).unwrap();
240
241        assert_eq!(vm.pc, 11);
242    }
243
244    #[test]
245    fn test_jgt_imm() {
246        // jgt r1, 10, +3
247        let inst = make_test_instruction(
248            Opcode::JgtImm,
249            Some(Register { n: 1 }),
250            None,
251            Some(Either::Right(3)),
252            Some(Either::Right(Number::Int(10))),
253        );
254        let mut vm = MockVm::new();
255        vm.registers[1] = 11;
256
257        execute_jump_immediate(&mut vm, &inst).unwrap();
258
259        assert_eq!(vm.pc, 4);
260    }
261
262    #[test]
263    fn test_jge_imm() {
264        // jge r1, 10, +2
265        let inst = make_test_instruction(
266            Opcode::JgeImm,
267            Some(Register { n: 1 }),
268            None,
269            Some(Either::Right(2)),
270            Some(Either::Right(Number::Int(10))),
271        );
272        let mut vm = MockVm::new();
273        vm.registers[1] = 10;
274
275        execute_jump_immediate(&mut vm, &inst).unwrap();
276
277        assert_eq!(vm.pc, 3);
278    }
279
280    #[test]
281    fn test_jlt_imm() {
282        // jlt r1, 10, +3
283        let inst = make_test_instruction(
284            Opcode::JltImm,
285            Some(Register { n: 1 }),
286            None,
287            Some(Either::Right(3)),
288            Some(Either::Right(Number::Int(10))),
289        );
290        let mut vm = MockVm::new();
291        vm.registers[1] = 5;
292
293        execute_jump_immediate(&mut vm, &inst).unwrap();
294
295        assert_eq!(vm.pc, 4);
296    }
297
298    #[test]
299    fn test_jle_imm() {
300        // jle r0, 10, +4
301        let inst = make_test_instruction(
302            Opcode::JleImm,
303            Some(Register { n: 0 }),
304            None,
305            Some(Either::Right(4)),
306            Some(Either::Right(Number::Int(10))),
307        );
308        let mut vm = MockVm::new();
309        vm.registers[0] = 0;
310
311        execute_jump_immediate(&mut vm, &inst).unwrap();
312
313        assert_eq!(vm.pc, 5);
314    }
315
316    #[test]
317    fn test_jset_imm() {
318        // jset r1, 0x0f, +2
319        let inst = make_test_instruction(
320            Opcode::JsetImm,
321            Some(Register { n: 1 }),
322            None,
323            Some(Either::Right(2)),
324            Some(Either::Right(Number::Int(0x0f))),
325        );
326        let mut vm = MockVm::new();
327        vm.registers[1] = 0xff;
328
329        execute_jump_immediate(&mut vm, &inst).unwrap();
330
331        assert_eq!(vm.pc, 3);
332    }
333
334    #[test]
335    fn test_jne_imm() {
336        // jne r1, 10, +2
337        let inst = make_test_instruction(
338            Opcode::JneImm,
339            Some(Register { n: 1 }),
340            None,
341            Some(Either::Right(2)),
342            Some(Either::Right(Number::Int(10))),
343        );
344        let mut vm = MockVm::new();
345        vm.registers[1] = 9;
346
347        execute_jump_immediate(&mut vm, &inst).unwrap();
348
349        assert_eq!(vm.pc, 3);
350    }
351
352    #[test]
353    fn test_jsgt_imm() {
354        // jsgt r1, -10, +4
355        let inst = make_test_instruction(
356            Opcode::JsgtImm,
357            Some(Register { n: 1 }),
358            None,
359            Some(Either::Right(4)),
360            Some(Either::Right(Number::Int(-10))),
361        );
362        let mut vm = MockVm::new();
363        vm.registers[1] = 5;
364
365        execute_jump_immediate(&mut vm, &inst).unwrap();
366
367        assert_eq!(vm.pc, 5);
368    }
369
370    #[test]
371    fn test_jsge_imm() {
372        // jsge r1, -5, +1
373        let inst = make_test_instruction(
374            Opcode::JsgeImm,
375            Some(Register { n: 1 }),
376            None,
377            Some(Either::Right(1)),
378            Some(Either::Right(Number::Int(-5))),
379        );
380        let mut vm = MockVm::new();
381        vm.registers[1] = (-5i64) as u64;
382
383        execute_jump_immediate(&mut vm, &inst).unwrap();
384
385        assert_eq!(vm.pc, 2);
386    }
387
388    #[test]
389    fn test_jslt_imm() {
390        // jslt r1, -4, +3
391        let inst = make_test_instruction(
392            Opcode::JsltImm,
393            Some(Register { n: 1 }),
394            None,
395            Some(Either::Right(3)),
396            Some(Either::Right(Number::Int(-4))),
397        );
398        let mut vm = MockVm::new();
399        vm.registers[1] = (-5i64) as u64;
400
401        execute_jump_immediate(&mut vm, &inst).unwrap();
402
403        assert_eq!(vm.pc, 4);
404    }
405
406    #[test]
407    fn test_jsle_imm() {
408        // jsle r1, -5, +2
409        let inst = make_test_instruction(
410            Opcode::JsleImm,
411            Some(Register { n: 1 }),
412            None,
413            Some(Either::Right(2)),
414            Some(Either::Right(Number::Int(-5))),
415        );
416        let mut vm = MockVm::new();
417        vm.registers[1] = (-10i64) as u64;
418
419        execute_jump_immediate(&mut vm, &inst).unwrap();
420
421        assert_eq!(vm.pc, 3);
422    }
423
424    #[test]
425    fn test_jeq_reg() {
426        // jeq r1, r2, +3
427        let inst = make_test_instruction(
428            Opcode::JeqReg,
429            Some(Register { n: 1 }),
430            Some(Register { n: 2 }),
431            Some(Either::Right(3)),
432            None,
433        );
434        let mut vm = MockVm::new();
435        vm.registers[1] = 5;
436        vm.registers[2] = 5;
437
438        execute_jump_register(&mut vm, &inst).unwrap();
439
440        assert_eq!(vm.pc, 4);
441    }
442
443    #[test]
444    fn test_jgt_reg() {
445        // jgt r1, r2, +5
446        let inst = make_test_instruction(
447            Opcode::JgtReg,
448            Some(Register { n: 1 }),
449            Some(Register { n: 2 }),
450            Some(Either::Right(5)),
451            None,
452        );
453        let mut vm = MockVm::new();
454        vm.registers[1] = 100;
455        vm.registers[2] = 50;
456
457        execute_jump_register(&mut vm, &inst).unwrap();
458
459        assert_eq!(vm.pc, 6);
460    }
461
462    #[test]
463    fn test_jge_reg() {
464        // jge r1, r2, +2
465        let inst = make_test_instruction(
466            Opcode::JgeReg,
467            Some(Register { n: 1 }),
468            Some(Register { n: 2 }),
469            Some(Either::Right(2)),
470            None,
471        );
472        let mut vm = MockVm::new();
473        vm.registers[1] = 100;
474        vm.registers[2] = 100;
475
476        execute_jump_register(&mut vm, &inst).unwrap();
477
478        assert_eq!(vm.pc, 3);
479    }
480
481    #[test]
482    fn test_jlt_reg() {
483        // jlt r1, r2, +4
484        let inst = make_test_instruction(
485            Opcode::JltReg,
486            Some(Register { n: 1 }),
487            Some(Register { n: 2 }),
488            Some(Either::Right(4)),
489            None,
490        );
491        let mut vm = MockVm::new();
492        vm.registers[1] = 50;
493        vm.registers[2] = 100;
494
495        execute_jump_register(&mut vm, &inst).unwrap();
496
497        assert_eq!(vm.pc, 5);
498    }
499
500    #[test]
501    fn test_jle_reg() {
502        // jle r1, r2, +3
503        let inst = make_test_instruction(
504            Opcode::JleReg,
505            Some(Register { n: 1 }),
506            Some(Register { n: 2 }),
507            Some(Either::Right(3)),
508            None,
509        );
510        let mut vm = MockVm::new();
511        vm.registers[1] = 50;
512        vm.registers[2] = 60;
513
514        execute_jump_register(&mut vm, &inst).unwrap();
515
516        assert_eq!(vm.pc, 4);
517    }
518
519    #[test]
520    fn test_jset_reg() {
521        // jset r1, r2, +2
522        let inst = make_test_instruction(
523            Opcode::JsetReg,
524            Some(Register { n: 1 }),
525            Some(Register { n: 2 }),
526            Some(Either::Right(2)),
527            None,
528        );
529        let mut vm = MockVm::new();
530        vm.registers[1] = 0xFF;
531        vm.registers[2] = 0x0F;
532
533        execute_jump_register(&mut vm, &inst).unwrap();
534
535        assert_eq!(vm.pc, 3);
536    }
537
538    #[test]
539    fn test_jne_reg() {
540        // jne r1, r2, +1
541        let inst = make_test_instruction(
542            Opcode::JneReg,
543            Some(Register { n: 1 }),
544            Some(Register { n: 2 }),
545            Some(Either::Right(1)),
546            None,
547        );
548        let mut vm = MockVm::new();
549        vm.registers[1] = 10;
550        vm.registers[2] = 20;
551
552        execute_jump_register(&mut vm, &inst).unwrap();
553
554        assert_eq!(vm.pc, 2);
555    }
556
557    #[test]
558    fn test_jsgt_reg() {
559        // jsgt r1, r2, +3
560        let inst = make_test_instruction(
561            Opcode::JsgtReg,
562            Some(Register { n: 1 }),
563            Some(Register { n: 2 }),
564            Some(Either::Right(3)),
565            None,
566        );
567        let mut vm = MockVm::new();
568        vm.registers[1] = 5;
569        vm.registers[2] = (-10i64) as u64;
570
571        execute_jump_register(&mut vm, &inst).unwrap();
572
573        assert_eq!(vm.pc, 4);
574    }
575
576    #[test]
577    fn test_jsge_reg() {
578        // jsge r1, r2, +2
579        let inst = make_test_instruction(
580            Opcode::JsgeReg,
581            Some(Register { n: 1 }),
582            Some(Register { n: 2 }),
583            Some(Either::Right(2)),
584            None,
585        );
586        let mut vm = MockVm::new();
587        vm.registers[1] = (-5i64) as u64;
588        vm.registers[2] = (-6i64) as u64;
589
590        execute_jump_register(&mut vm, &inst).unwrap();
591
592        assert_eq!(vm.pc, 3);
593    }
594
595    #[test]
596    fn test_jslt_reg() {
597        // jslt r1, r2, +2
598        let inst = make_test_instruction(
599            Opcode::JsltReg,
600            Some(Register { n: 1 }),
601            Some(Register { n: 2 }),
602            Some(Either::Right(2)),
603            None,
604        );
605        let mut vm = MockVm::new();
606        vm.registers[1] = (-5i64) as u64;
607        vm.registers[2] = 2;
608
609        execute_jump_register(&mut vm, &inst).unwrap();
610
611        assert_eq!(vm.pc, 3);
612    }
613
614    #[test]
615    fn test_jsle_reg() {
616        // jsle r1, r2, +2
617        let inst = make_test_instruction(
618            Opcode::JsleReg,
619            Some(Register { n: 1 }),
620            Some(Register { n: 2 }),
621            Some(Either::Right(2)),
622            None,
623        );
624        let mut vm = MockVm::new();
625        vm.registers[1] = (-10i64) as u64;
626        vm.registers[2] = 5;
627
628        execute_jump_register(&mut vm, &inst).unwrap();
629
630        assert_eq!(vm.pc, 3);
631    }
632
633    #[test]
634    fn test_jeq32_imm() {
635        // jeq32 r1, 5, +2
636        let inst = make_test_instruction(
637            Opcode::Jeq32Imm,
638            Some(Register { n: 1 }),
639            None,
640            Some(Either::Right(2)),
641            Some(Either::Right(Number::Int(5))),
642        );
643        let mut vm = MockVm::new();
644        vm.registers[1] = 0x0000_0001_0000_0005;
645
646        execute_jump_immediate(&mut vm, &inst).unwrap();
647
648        assert_eq!(vm.pc, 3);
649    }
650
651    #[test]
652    fn test_jgt32_imm() {
653        // jgt32 r1, -1, +3
654        let inst = make_test_instruction(
655            Opcode::Jgt32Imm,
656            Some(Register { n: 1 }),
657            None,
658            Some(Either::Right(3)),
659            Some(Either::Right(Number::Int(-1))),
660        );
661        let mut vm = MockVm::new();
662        vm.registers[1] = 0xffff_fffe;
663
664        execute_jump_immediate(&mut vm, &inst).unwrap();
665
666        assert_eq!(vm.pc, 1);
667    }
668
669    #[test]
670    fn test_jge32_imm() {
671        // jge32 r1, 10, +2
672        let inst = make_test_instruction(
673            Opcode::Jge32Imm,
674            Some(Register { n: 1 }),
675            None,
676            Some(Either::Right(2)),
677            Some(Either::Right(Number::Int(10))),
678        );
679        let mut vm = MockVm::new();
680        vm.registers[1] = 0x0000_0002_0000_000a;
681
682        execute_jump_immediate(&mut vm, &inst).unwrap();
683
684        assert_eq!(vm.pc, 3);
685    }
686
687    #[test]
688    fn test_jlt32_imm() {
689        // jlt32 r1, 10, +3
690        let inst = make_test_instruction(
691            Opcode::Jlt32Imm,
692            Some(Register { n: 1 }),
693            None,
694            Some(Either::Right(3)),
695            Some(Either::Right(Number::Int(10))),
696        );
697        let mut vm = MockVm::new();
698        vm.registers[1] = 5;
699
700        execute_jump_immediate(&mut vm, &inst).unwrap();
701
702        assert_eq!(vm.pc, 4);
703    }
704
705    #[test]
706    fn test_jle32_imm() {
707        // jle32 r1, 10, +4
708        let inst = make_test_instruction(
709            Opcode::Jle32Imm,
710            Some(Register { n: 1 }),
711            None,
712            Some(Either::Right(4)),
713            Some(Either::Right(Number::Int(10))),
714        );
715        let mut vm = MockVm::new();
716        vm.registers[1] = 10;
717
718        execute_jump_immediate(&mut vm, &inst).unwrap();
719
720        assert_eq!(vm.pc, 5);
721    }
722
723    #[test]
724    fn test_jset32_imm() {
725        // jset32 r1, 0x0f, +2
726        let inst = make_test_instruction(
727            Opcode::Jset32Imm,
728            Some(Register { n: 1 }),
729            None,
730            Some(Either::Right(2)),
731            Some(Either::Right(Number::Int(0x0f))),
732        );
733        let mut vm = MockVm::new();
734        vm.registers[1] = 0x0000_0001_0000_000f;
735
736        execute_jump_immediate(&mut vm, &inst).unwrap();
737
738        assert_eq!(vm.pc, 3);
739    }
740
741    #[test]
742    fn test_jne32_imm() {
743        // jne32 r1, 10, +1
744        let inst = make_test_instruction(
745            Opcode::Jne32Imm,
746            Some(Register { n: 1 }),
747            None,
748            Some(Either::Right(1)),
749            Some(Either::Right(Number::Int(10))),
750        );
751        let mut vm = MockVm::new();
752        vm.registers[1] = 9;
753
754        execute_jump_immediate(&mut vm, &inst).unwrap();
755
756        assert_eq!(vm.pc, 2);
757    }
758
759    #[test]
760    fn test_jsgt32_imm() {
761        // jsgt32 r1, -1, +1
762        let inst = make_test_instruction(
763            Opcode::Jsgt32Imm,
764            Some(Register { n: 1 }),
765            None,
766            Some(Either::Right(1)),
767            Some(Either::Right(Number::Int(-1))),
768        );
769        let mut vm = MockVm::new();
770        vm.registers[1] = 1;
771
772        execute_jump_immediate(&mut vm, &inst).unwrap();
773
774        assert_eq!(vm.pc, 2);
775    }
776
777    #[test]
778    fn test_jsge32_imm() {
779        // jsge32 r1, -1, +2
780        let inst = make_test_instruction(
781            Opcode::Jsge32Imm,
782            Some(Register { n: 1 }),
783            None,
784            Some(Either::Right(2)),
785            Some(Either::Right(Number::Int(-1))),
786        );
787        let mut vm = MockVm::new();
788        vm.registers[1] = 1;
789
790        execute_jump_immediate(&mut vm, &inst).unwrap();
791
792        assert_eq!(vm.pc, 3);
793    }
794
795    #[test]
796    fn test_jslt32_imm() {
797        // jslt32 r1, 1, +3
798        let inst = make_test_instruction(
799            Opcode::Jslt32Imm,
800            Some(Register { n: 1 }),
801            None,
802            Some(Either::Right(3)),
803            Some(Either::Right(Number::Int(1))),
804        );
805        let mut vm = MockVm::new();
806        vm.registers[1] = 0xffff_ffff;
807
808        execute_jump_immediate(&mut vm, &inst).unwrap();
809
810        assert_eq!(vm.pc, 4);
811    }
812
813    #[test]
814    fn test_jsle32_imm() {
815        // jsle32 r1, 5, +2
816        let inst = make_test_instruction(
817            Opcode::Jsle32Imm,
818            Some(Register { n: 1 }),
819            None,
820            Some(Either::Right(2)),
821            Some(Either::Right(Number::Int(5))),
822        );
823        let mut vm = MockVm::new();
824        vm.registers[1] = 0xffff_fff6;
825
826        execute_jump_immediate(&mut vm, &inst).unwrap();
827
828        assert_eq!(vm.pc, 3);
829    }
830
831    #[test]
832    fn test_jeq32_reg() {
833        // jeq32 r1, r2, +2
834        let inst = make_test_instruction(
835            Opcode::Jeq32Reg,
836            Some(Register { n: 1 }),
837            Some(Register { n: 2 }),
838            Some(Either::Right(2)),
839            None,
840        );
841        let mut vm = MockVm::new();
842        vm.registers[1] = 0x0000_0001_0000_0005;
843        vm.registers[2] = 0x0000_0002_0000_0005;
844
845        execute_jump_register(&mut vm, &inst).unwrap();
846
847        assert_eq!(vm.pc, 3);
848    }
849
850    #[test]
851    fn test_jgt32_reg() {
852        // jgt32 r1, r2, +3
853        let inst = make_test_instruction(
854            Opcode::Jgt32Reg,
855            Some(Register { n: 1 }),
856            Some(Register { n: 2 }),
857            Some(Either::Right(3)),
858            None,
859        );
860        let mut vm = MockVm::new();
861        vm.registers[1] = 11;
862        vm.registers[2] = 10;
863
864        execute_jump_register(&mut vm, &inst).unwrap();
865
866        assert_eq!(vm.pc, 4);
867    }
868
869    #[test]
870    fn test_jge32_reg() {
871        // jge32 r1, r2, +2
872        let inst = make_test_instruction(
873            Opcode::Jge32Reg,
874            Some(Register { n: 1 }),
875            Some(Register { n: 2 }),
876            Some(Either::Right(2)),
877            None,
878        );
879        let mut vm = MockVm::new();
880        vm.registers[1] = 10;
881        vm.registers[2] = 10;
882
883        execute_jump_register(&mut vm, &inst).unwrap();
884
885        assert_eq!(vm.pc, 3);
886    }
887
888    #[test]
889    fn test_jlt32_reg() {
890        // jlt32 r1, r2, +3
891        let inst = make_test_instruction(
892            Opcode::Jlt32Reg,
893            Some(Register { n: 1 }),
894            Some(Register { n: 2 }),
895            Some(Either::Right(3)),
896            None,
897        );
898        let mut vm = MockVm::new();
899        vm.registers[1] = 5;
900        vm.registers[2] = 10;
901
902        execute_jump_register(&mut vm, &inst).unwrap();
903
904        assert_eq!(vm.pc, 4);
905    }
906
907    #[test]
908    fn test_jle32_reg() {
909        // jle32 r1, r2, +2
910        let inst = make_test_instruction(
911            Opcode::Jle32Reg,
912            Some(Register { n: 1 }),
913            Some(Register { n: 2 }),
914            Some(Either::Right(2)),
915            None,
916        );
917        let mut vm = MockVm::new();
918        vm.registers[1] = 5;
919        vm.registers[2] = 5;
920
921        execute_jump_register(&mut vm, &inst).unwrap();
922
923        assert_eq!(vm.pc, 3);
924    }
925
926    #[test]
927    fn test_jset32_reg() {
928        // jset32 r1, r2, +4
929        let inst = make_test_instruction(
930            Opcode::Jset32Reg,
931            Some(Register { n: 1 }),
932            Some(Register { n: 2 }),
933            Some(Either::Right(4)),
934            None,
935        );
936        let mut vm = MockVm::new();
937        vm.registers[1] = 0x0000_0001_0000_0000;
938        vm.registers[2] = 0x0000_0002_0000_0000;
939
940        execute_jump_register(&mut vm, &inst).unwrap();
941
942        assert_eq!(vm.pc, 1);
943    }
944
945    #[test]
946    fn test_jne32_reg() {
947        // jne32 r1, r2, +1
948        let inst = make_test_instruction(
949            Opcode::Jne32Reg,
950            Some(Register { n: 1 }),
951            Some(Register { n: 2 }),
952            Some(Either::Right(1)),
953            None,
954        );
955        let mut vm = MockVm::new();
956        vm.registers[1] = 9;
957        vm.registers[2] = 10;
958
959        execute_jump_register(&mut vm, &inst).unwrap();
960
961        assert_eq!(vm.pc, 2);
962    }
963
964    #[test]
965    fn test_jsgt32_reg() {
966        // jsgt32 r1, r2, +2
967        let inst = make_test_instruction(
968            Opcode::Jsgt32Reg,
969            Some(Register { n: 1 }),
970            Some(Register { n: 2 }),
971            Some(Either::Right(2)),
972            None,
973        );
974        let mut vm = MockVm::new();
975        vm.registers[1] = 1;
976        vm.registers[2] = 0xffff_ffff;
977
978        execute_jump_register(&mut vm, &inst).unwrap();
979
980        assert_eq!(vm.pc, 3);
981    }
982
983    #[test]
984    fn test_jsge32_reg() {
985        // jsge32 r1, r2, +2
986        let inst = make_test_instruction(
987            Opcode::Jsge32Reg,
988            Some(Register { n: 1 }),
989            Some(Register { n: 2 }),
990            Some(Either::Right(2)),
991            None,
992        );
993        let mut vm = MockVm::new();
994        vm.registers[1] = 1;
995        vm.registers[2] = 0xffff_ffff;
996
997        execute_jump_register(&mut vm, &inst).unwrap();
998
999        assert_eq!(vm.pc, 3);
1000    }
1001
1002    #[test]
1003    fn test_jslt32_reg() {
1004        // jslt32 r1, r2, +2
1005        let inst = make_test_instruction(
1006            Opcode::Jslt32Reg,
1007            Some(Register { n: 1 }),
1008            Some(Register { n: 2 }),
1009            Some(Either::Right(2)),
1010            None,
1011        );
1012        let mut vm = MockVm::new();
1013        vm.registers[1] = 0x0000_0000_8000_0000;
1014        vm.registers[2] = 0x0000_0000_7fff_ffff;
1015
1016        execute_jump_register(&mut vm, &inst).unwrap();
1017
1018        assert_eq!(vm.pc, 3);
1019    }
1020
1021    #[test]
1022    fn test_jsle32_reg() {
1023        // jsle32 r1, r2, +2
1024        let inst = make_test_instruction(
1025            Opcode::Jsle32Reg,
1026            Some(Register { n: 1 }),
1027            Some(Register { n: 2 }),
1028            Some(Either::Right(2)),
1029            None,
1030        );
1031        let mut vm = MockVm::new();
1032        vm.registers[1] = 0xffff_fff6;
1033        vm.registers[2] = 5;
1034
1035        execute_jump_register(&mut vm, &inst).unwrap();
1036
1037        assert_eq!(vm.pc, 3);
1038    }
1039}