1use miden_core::{Felt, ZERO};
2
3use super::FastProcessor;
4use crate::{ErrorContext, ExecutionError, utils::split_element};
5
6impl FastProcessor {
7 #[inline(always)]
9 pub fn op_u32split(&mut self) -> Result<(), ExecutionError> {
10 let top = self.stack_get(0);
11 let (hi, lo) = split_element(top);
12
13 self.increment_stack_size()?;
14 self.stack_write(0, hi);
15 self.stack_write(1, lo);
16
17 Ok(())
18 }
19
20 pub fn op_u32add(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
22 self.u32_pop2_applyfn_push_lowhigh(|a, b| a + b, err_ctx)
23 }
24
25 #[inline(always)]
32 pub fn op_u32add3(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
33 let (sum_hi, sum_lo) = {
34 let c = self.stack_get(0).as_int();
35 let b = self.stack_get(1).as_int();
36 let a = self.stack_get(2).as_int();
37
38 if a > u32::MAX as u64 {
40 return Err(ExecutionError::not_u32_value(Felt::new(a), ZERO, err_ctx));
41 }
42 if b > u32::MAX as u64 {
43 return Err(ExecutionError::not_u32_value(Felt::new(b), ZERO, err_ctx));
44 }
45 if c > u32::MAX as u64 {
46 return Err(ExecutionError::not_u32_value(Felt::new(c), ZERO, err_ctx));
47 }
48 let result = Felt::new(a + b + c);
49 split_element(result)
50 };
51
52 self.decrement_stack_size();
54 self.stack_write(0, sum_hi);
55 self.stack_write(1, sum_lo);
56 Ok(())
57 }
58
59 #[inline(always)]
61 pub fn op_u32sub(
62 &mut self,
63 op_idx: usize,
64 err_ctx: &impl ErrorContext,
65 ) -> Result<(), ExecutionError> {
66 let op_idx = Felt::from(op_idx as u32);
67 self.u32_pop2_applyfn_push_results(
68 op_idx,
69 |first_old, second_old| {
70 let result = second_old.wrapping_sub(first_old);
71 let first_new = result >> 63;
72 let second_new = result & u32::MAX as u64;
73
74 Ok((first_new, second_new))
75 },
76 err_ctx,
77 )
78 }
79
80 pub fn op_u32mul(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
82 self.u32_pop2_applyfn_push_lowhigh(|a, b| a * b, err_ctx)
83 }
84
85 #[inline(always)]
91 pub fn op_u32madd(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
92 let (result_hi, result_lo) = {
93 let b = self.stack_get(0).as_int();
94 let a = self.stack_get(1).as_int();
95 let c = self.stack_get(2).as_int();
96
97 if b > u32::MAX as u64 {
99 return Err(ExecutionError::not_u32_value(Felt::new(a), ZERO, err_ctx));
100 }
101 if a > u32::MAX as u64 {
102 return Err(ExecutionError::not_u32_value(Felt::new(b), ZERO, err_ctx));
103 }
104 if c > u32::MAX as u64 {
105 return Err(ExecutionError::not_u32_value(Felt::new(c), ZERO, err_ctx));
106 }
107 let result = Felt::new(a * b + c);
108 split_element(result)
109 };
110
111 self.decrement_stack_size();
113 self.stack_write(0, result_hi);
114 self.stack_write(1, result_lo);
115 Ok(())
116 }
117
118 #[inline(always)]
120 pub fn op_u32div(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
121 let clk = self.clk;
122 self.u32_pop2_applyfn_push_results(
123 ZERO,
124 |first, second| {
125 if first == 0 {
126 return Err(ExecutionError::divide_by_zero(clk, err_ctx));
127 }
128
129 let q = second / first;
131 let r = second - q * first;
132
133 Ok((r, q))
135 },
136 err_ctx,
137 )
138 }
139
140 #[inline(always)]
142 pub fn op_u32and(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
143 self.u32_pop2_applyfn_push(|a, b| a & b, err_ctx)
144 }
145
146 #[inline(always)]
148 pub fn op_u32xor(&mut self, err_ctx: &impl ErrorContext) -> Result<(), ExecutionError> {
149 self.u32_pop2_applyfn_push(|a, b| a ^ b, err_ctx)
150 }
151
152 #[inline(always)]
154 pub fn op_u32assert2(
155 &mut self,
156 err_code: Felt,
157 err_ctx: &impl ErrorContext,
158 ) -> Result<(), ExecutionError> {
159 self.u32_pop2_applyfn_push_results(err_code, |first, second| Ok((first, second)), err_ctx)
160 }
161
162 #[inline(always)]
167 fn u32_pop2_applyfn_push(
168 &mut self,
169 f: impl FnOnce(u64, u64) -> u64,
170 err_ctx: &impl ErrorContext,
171 ) -> Result<(), ExecutionError> {
172 let b = self.stack_get(0).as_int();
173 let a = self.stack_get(1).as_int();
174
175 if b > u32::MAX as u64 {
177 return Err(ExecutionError::not_u32_value(Felt::new(b), ZERO, err_ctx));
178 }
179 if a > u32::MAX as u64 {
180 return Err(ExecutionError::not_u32_value(Felt::new(a), ZERO, err_ctx));
181 }
182
183 let result = f(a, b);
184 self.decrement_stack_size();
185 self.stack_write(0, Felt::new(result));
186
187 Ok(())
188 }
189
190 #[inline(always)]
201 fn u32_pop2_applyfn_push_lowhigh(
202 &mut self,
203 f: impl FnOnce(u64, u64) -> u64,
204 err_ctx: &impl ErrorContext,
205 ) -> Result<(), ExecutionError> {
206 let b = self.stack_get(0).as_int();
207 let a = self.stack_get(1).as_int();
208
209 if a > u32::MAX as u64 {
211 return Err(ExecutionError::not_u32_value(Felt::new(a), ZERO, err_ctx));
212 }
213 if b > u32::MAX as u64 {
214 return Err(ExecutionError::not_u32_value(Felt::new(b), ZERO, err_ctx));
215 }
216
217 let result = Felt::new(f(a, b));
218 let (hi, lo) = split_element(result);
219
220 self.stack_write(0, hi);
221 self.stack_write(1, lo);
222 Ok(())
223 }
224
225 #[inline(always)]
230 fn u32_pop2_applyfn_push_results(
231 &mut self,
232 err_code: Felt,
233 f: impl FnOnce(u64, u64) -> Result<(u64, u64), ExecutionError>,
234 err_ctx: &impl ErrorContext,
235 ) -> Result<(), ExecutionError> {
236 let first_old = self.stack_get(0).as_int();
237 let second_old = self.stack_get(1).as_int();
238
239 if first_old > u32::MAX as u64 {
241 return Err(ExecutionError::not_u32_value(Felt::new(first_old), err_code, err_ctx));
242 }
243 if second_old > u32::MAX as u64 {
244 return Err(ExecutionError::not_u32_value(Felt::new(second_old), err_code, err_ctx));
245 }
246
247 let (first_new, second_new) = f(first_old, second_old)?;
248
249 self.stack_write(0, Felt::new(first_new));
250 self.stack_write(1, Felt::new(second_new));
251 Ok(())
252 }
253}