1use crate::{Vm, get_reg, i16_from_u8s, set_reg};
6use std::ptr;
7use swamp_vm_isa::{RangeHeader, RangeIterator};
8
9impl Vm {
10 #[inline]
11 #[must_use]
12 pub fn get_range_header_ptr_from_reg(&self, range_reg: u8) -> *mut RangeHeader {
13 self.get_ptr_from_reg(range_reg) as *mut RangeHeader
14 }
15
16 #[inline]
17 #[must_use]
18 pub fn range_header_from_reg(&self, range_reg: u8) -> RangeHeader {
19 unsafe { *(self.get_const_ptr_from_reg(range_reg) as *const RangeHeader) }
20 }
21
22 pub fn range_iterator_ptr_from_reg(&self, range_iterator_reg: u8) -> *mut RangeIterator {
23 self.get_ptr_from_reg(range_iterator_reg) as *mut RangeIterator
24 }
25
26 #[inline]
27 pub fn execute_range_init(
28 &mut self,
29 range_target_reg: u8,
30 min_reg: u8,
31 max_reg: u8,
32 is_inclusive: u8,
33 ) {
34 let range_header = self.get_range_header_ptr_from_reg(range_target_reg);
35
36 unsafe {
37 (*range_header).min = get_reg!(self, min_reg) as i32;
38 (*range_header).max = get_reg!(self, max_reg) as i32;
39 (*range_header).inclusive = get_reg!(self, is_inclusive) as i32 != 0;
40 }
41 }
42
43 #[inline]
44 pub fn execute_range_iter_init(&mut self, target_iterator_reg: u8, range_header_reg: u8) {
45 let range_header = self.range_header_from_reg(range_header_reg);
46
47 let extra = i32::from(range_header.inclusive);
48
49 let (start, end, direction) = if range_header.min <= range_header.max {
50 (
52 range_header.min,
53 range_header.max + extra, 1,
55 )
56 } else {
57 (
60 range_header.min,
61 range_header.max - extra, -1,
63 )
64 };
65
66 #[cfg(feature = "debug_vm")]
67 {}
68
69 let iterator_target_ptr = self.range_iterator_ptr_from_reg(target_iterator_reg);
70
71 unsafe {
72 let range_iterator = RangeIterator {
73 index: start,
74 end,
75 direction,
76 };
77
78 ptr::write(iterator_target_ptr, range_iterator);
79 }
80 }
81
82 #[inline]
83 pub fn execute_range_iter_next(
84 &mut self,
85 target_iterator_reg: u8,
86 target_int_reg: u8,
87 jmp_offset_lower: u8,
88 jmp_offset_upper: u8,
89 ) {
90 let range_iterator = self.range_iterator_ptr_from_reg(target_iterator_reg);
91 unsafe {
92 #[cfg(feature = "debug_vm")]
93 {
94 if self.debug_operations_enabled {
95 eprintln!(
96 "range_iterator: index={}, end={}, direction={}",
97 (*range_iterator).index,
98 (*range_iterator).end,
99 (*range_iterator).direction
100 );
101 }
102 }
103
104 if (*range_iterator).index == (*range_iterator).end {
105 let jump_offset = i16_from_u8s!(jmp_offset_lower, jmp_offset_upper);
106 #[cfg(feature = "debug_vm")]
107 {
108 if self.debug_operations_enabled {
109 eprintln!("range_iter_next complete. jumping with offset {jump_offset}");
110 }
111 }
112 self.pc = (self.pc as i32 + jump_offset as i32) as usize;
113 } else {
114 set_reg!(self, target_int_reg, (*range_iterator).index);
115 (*range_iterator).index += (*range_iterator).direction;
116 }
117 }
118 }
119}