1use super::i256::i256_cmp;
2use crate::{
3 interpreter_types::{InterpreterTypes as ITy, RuntimeFlag, StackTr},
4 InstructionContext as Ictx, InstructionExecResult as Result,
5};
6use core::cmp::Ordering;
7use primitives::U256;
8
9pub fn lt<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
11 popn_top!([op1], op2, context.interpreter);
12 *op2 = U256::from(op1 < *op2);
13 Ok(())
14}
15
16pub fn gt<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
18 popn_top!([op1], op2, context.interpreter);
19 *op2 = U256::from(op1 > *op2);
20 Ok(())
21}
22
23pub fn clz<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
25 check!(context.interpreter, OSAKA);
26 popn_top!([], op1, context.interpreter);
27 let leading_zeros = op1.leading_zeros();
28 *op1 = U256::from(leading_zeros);
29 Ok(())
30}
31
32pub fn slt<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
36 popn_top!([op1], op2, context.interpreter);
37 *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Less);
38 Ok(())
39}
40
41pub fn sgt<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
45 popn_top!([op1], op2, context.interpreter);
46 *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Greater);
47 Ok(())
48}
49
50pub fn eq<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
54 popn_top!([op1], op2, context.interpreter);
55 *op2 = U256::from(op1 == *op2);
56 Ok(())
57}
58
59pub fn iszero<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
63 popn_top!([], op1, context.interpreter);
64 *op1 = U256::from(op1.is_zero());
65 Ok(())
66}
67
68pub fn bitand<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
72 popn_top!([op1], op2, context.interpreter);
73 *op2 = op1 & *op2;
74 Ok(())
75}
76
77pub fn bitor<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
81 popn_top!([op1], op2, context.interpreter);
82 *op2 = op1 | *op2;
83 Ok(())
84}
85
86pub fn bitxor<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
90 popn_top!([op1], op2, context.interpreter);
91 *op2 = op1 ^ *op2;
92 Ok(())
93}
94
95pub fn not<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
99 popn_top!([], op1, context.interpreter);
100 *op1 = !*op1;
101 Ok(())
102}
103
104pub fn byte<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
108 popn_top!([op1], op2, context.interpreter);
109 let o1 = as_usize_saturated!(op1);
110 *op2 = if o1 < 32 {
111 U256::from(op2.byte(31 - o1))
113 } else {
114 U256::ZERO
115 };
116 Ok(())
117}
118
119pub fn shl<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
121 check!(context.interpreter, PETERSBURG);
122 popn_top!([op1], op2, context.interpreter);
123 let shift = as_usize_saturated!(op1);
124 *op2 = if shift < 256 {
125 *op2 << shift
126 } else {
127 U256::ZERO
128 };
129 Ok(())
130}
131
132pub fn shr<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
134 check!(context.interpreter, PETERSBURG);
135 popn_top!([op1], op2, context.interpreter);
136 let shift = as_usize_saturated!(op1);
137 *op2 = if shift < 256 {
138 *op2 >> shift
139 } else {
140 U256::ZERO
141 };
142 Ok(())
143}
144
145pub fn sar<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
147 check!(context.interpreter, PETERSBURG);
148 popn_top!([op1], op2, context.interpreter);
149 let shift = as_usize_saturated!(op1);
150 *op2 = if shift < 256 {
151 op2.arithmetic_shr(shift)
152 } else if op2.bit(255) {
153 U256::MAX
154 } else {
155 U256::ZERO
156 };
157 Ok(())
158}
159
160#[cfg(test)]
161mod tests {
162 use crate::{
163 host::DummyHost,
164 instructions::bitwise::{byte, clz, sar, shl, shr},
165 InstructionContext as Ictx, Interpreter,
166 };
167 use primitives::{hardfork::SpecId, uint, U256};
168
169 #[test]
170 fn test_shift_left() {
171 let mut interpreter = Interpreter::default();
172
173 struct TestCase {
174 value: U256,
175 shift: U256,
176 expected: U256,
177 }
178
179 uint! {
180 let test_cases = [
181 TestCase {
182 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
183 shift: 0x00_U256,
184 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
185 },
186 TestCase {
187 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
188 shift: 0x01_U256,
189 expected: 0x0000000000000000000000000000000000000000000000000000000000000002_U256,
190 },
191 TestCase {
192 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
193 shift: 0xff_U256,
194 expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
195 },
196 TestCase {
197 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
198 shift: 0x0100_U256,
199 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
200 },
201 TestCase {
202 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
203 shift: 0x0101_U256,
204 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
205 },
206 TestCase {
207 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
208 shift: 0x00_U256,
209 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
210 },
211 TestCase {
212 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
213 shift: 0x01_U256,
214 expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
215 },
216 TestCase {
217 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
218 shift: 0xff_U256,
219 expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
220 },
221 TestCase {
222 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
223 shift: 0x0100_U256,
224 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
225 },
226 TestCase {
227 value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
228 shift: 0x01_U256,
229 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
230 },
231 TestCase {
232 value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
233 shift: 0x01_U256,
234 expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
235 },
236 ];
237 }
238
239 for test in test_cases {
240 assert!(interpreter.stack.push(test.value));
241 assert!(interpreter.stack.push(test.shift));
242 let context = Ictx {
243 host: &mut DummyHost::default(),
244 interpreter: &mut interpreter,
245 };
246 let _ = shl(context);
247 let res = interpreter.stack.pop().unwrap();
248 assert_eq!(res, test.expected);
249 }
250 }
251
252 #[test]
253 fn test_logical_shift_right() {
254 let mut interpreter = Interpreter::default();
255
256 struct TestCase {
257 value: U256,
258 shift: U256,
259 expected: U256,
260 }
261
262 uint! {
263 let test_cases = [
264 TestCase {
265 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
266 shift: 0x00_U256,
267 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
268 },
269 TestCase {
270 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
271 shift: 0x01_U256,
272 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
273 },
274 TestCase {
275 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
276 shift: 0x01_U256,
277 expected: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
278 },
279 TestCase {
280 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
281 shift: 0xff_U256,
282 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
283 },
284 TestCase {
285 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
286 shift: 0x0100_U256,
287 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
288 },
289 TestCase {
290 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
291 shift: 0x0101_U256,
292 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
293 },
294 TestCase {
295 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
296 shift: 0x00_U256,
297 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
298 },
299 TestCase {
300 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
301 shift: 0x01_U256,
302 expected: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
303 },
304 TestCase {
305 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
306 shift: 0xff_U256,
307 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
308 },
309 TestCase {
310 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
311 shift: 0x0100_U256,
312 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
313 },
314 TestCase {
315 value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
316 shift: 0x01_U256,
317 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
318 },
319 ];
320 }
321
322 for test in test_cases {
323 assert!(interpreter.stack.push(test.value));
324 assert!(interpreter.stack.push(test.shift));
325 let context = Ictx {
326 host: &mut DummyHost::default(),
327 interpreter: &mut interpreter,
328 };
329 let _ = shr(context);
330 let res = interpreter.stack.pop().unwrap();
331 assert_eq!(res, test.expected);
332 }
333 }
334
335 #[test]
336 fn test_arithmetic_shift_right() {
337 let mut interpreter = Interpreter::default();
338
339 struct TestCase {
340 value: U256,
341 shift: U256,
342 expected: U256,
343 }
344
345 uint! {
346 let test_cases = [
347 TestCase {
348 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
349 shift: 0x00_U256,
350 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
351 },
352 TestCase {
353 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
354 shift: 0x01_U256,
355 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
356 },
357 TestCase {
358 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
359 shift: 0x01_U256,
360 expected: 0xc000000000000000000000000000000000000000000000000000000000000000_U256,
361 },
362 TestCase {
363 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
364 shift: 0xff_U256,
365 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
366 },
367 TestCase {
368 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
369 shift: 0x0100_U256,
370 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
371 },
372 TestCase {
373 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
374 shift: 0x0101_U256,
375 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
376 },
377 TestCase {
378 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
379 shift: 0x00_U256,
380 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
381 },
382 TestCase {
383 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
384 shift: 0x01_U256,
385 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
386 },
387 TestCase {
388 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
389 shift: 0xff_U256,
390 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
391 },
392 TestCase {
393 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
394 shift: 0x0100_U256,
395 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
396 },
397 TestCase {
398 value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
399 shift: 0x01_U256,
400 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
401 },
402 TestCase {
403 value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
404 shift: 0xfe_U256,
405 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
406 },
407 TestCase {
408 value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
409 shift: 0xf8_U256,
410 expected: 0x000000000000000000000000000000000000000000000000000000000000007f_U256,
411 },
412 TestCase {
413 value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
414 shift: 0xfe_U256,
415 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
416 },
417 TestCase {
418 value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
419 shift: 0xff_U256,
420 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
421 },
422 TestCase {
423 value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
424 shift: 0x0100_U256,
425 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
426 },
427 ];
428 }
429
430 for test in test_cases {
431 assert!(interpreter.stack.push(test.value));
432 assert!(interpreter.stack.push(test.shift));
433 let context = Ictx {
434 host: &mut DummyHost::default(),
435 interpreter: &mut interpreter,
436 };
437 let _ = sar(context);
438 let res = interpreter.stack.pop().unwrap();
439 assert_eq!(res, test.expected);
440 }
441 }
442
443 #[test]
444 fn test_byte() {
445 struct TestCase {
446 input: U256,
447 index: usize,
448 expected: U256,
449 }
450
451 let mut interpreter = Interpreter::default();
452
453 let input_value = U256::from(0x1234567890abcdef1234567890abcdef_u128);
454 let test_cases = (0..32)
455 .map(|i| {
456 let byte_pos = 31 - i;
457
458 let shift_amount = U256::from(byte_pos * 8);
459 let byte_value = (input_value >> shift_amount) & U256::from(0xFF);
460 TestCase {
461 input: input_value,
462 index: i,
463 expected: byte_value,
464 }
465 })
466 .collect::<Vec<_>>();
467
468 for test in test_cases.iter() {
469 assert!(interpreter.stack.push(test.input));
470 assert!(interpreter.stack.push(U256::from(test.index)));
471 let context = Ictx {
472 host: &mut DummyHost::default(),
473 interpreter: &mut interpreter,
474 };
475 let _ = byte(context);
476 let res = interpreter.stack.pop().unwrap();
477 assert_eq!(res, test.expected, "Failed at index: {}", test.index);
478 }
479 }
480
481 #[test]
482 fn test_clz() {
483 let mut interpreter = Interpreter::default();
484 interpreter.runtime_flag.spec_id = SpecId::OSAKA;
485 let mut host = DummyHost::new(SpecId::OSAKA);
486
487 struct TestCase {
488 value: U256,
489 expected: U256,
490 }
491
492 uint! {
493 let test_cases = [
494 TestCase { value: 0x0_U256, expected: 256_U256 },
495 TestCase { value: 0x1_U256, expected: 255_U256 },
496 TestCase { value: 0x2_U256, expected: 254_U256 },
497 TestCase { value: 0x3_U256, expected: 254_U256 },
498 TestCase { value: 0x4_U256, expected: 253_U256 },
499 TestCase { value: 0x7_U256, expected: 253_U256 },
500 TestCase { value: 0x8_U256, expected: 252_U256 },
501 TestCase { value: 0xff_U256, expected: 248_U256 },
502 TestCase { value: 0x100_U256, expected: 247_U256 },
503 TestCase { value: 0xffff_U256, expected: 240_U256 },
504 TestCase {
505 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, expected: 0_U256,
507 },
508 TestCase {
509 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, expected: 0_U256,
511 },
512 TestCase { value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256, expected: 1_U256,
515 },
516 TestCase { value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
518 expected: 1_U256,
519 },
520 ];
521 }
522
523 for test in test_cases {
524 assert!(interpreter.stack.push(test.value));
525 let context = Ictx {
526 host: &mut host,
527 interpreter: &mut interpreter,
528 };
529 let _ = clz(context);
530 let res = interpreter.stack.pop().unwrap();
531 assert_eq!(
532 res, test.expected,
533 "CLZ for value {:#x} failed. Expected: {}, Got: {}",
534 test.value, test.expected, res
535 );
536 }
537 }
538}