evm_core/eval/
bitwise.rs

1use crate::utils::{Sign, I256};
2use primitive_types::U256;
3
4#[inline]
5pub fn slt(op1: U256, op2: U256) -> U256 {
6	let op1: I256 = op1.into();
7	let op2: I256 = op2.into();
8
9	if op1.lt(&op2) {
10		U256::one()
11	} else {
12		U256::zero()
13	}
14}
15
16#[inline]
17pub fn sgt(op1: U256, op2: U256) -> U256 {
18	let op1: I256 = op1.into();
19	let op2: I256 = op2.into();
20
21	if op1.gt(&op2) {
22		U256::one()
23	} else {
24		U256::zero()
25	}
26}
27
28#[inline]
29pub fn iszero(op1: U256) -> U256 {
30	if op1 == U256::zero() {
31		U256::one()
32	} else {
33		U256::zero()
34	}
35}
36
37#[inline]
38pub fn not(op1: U256) -> U256 {
39	!op1
40}
41
42#[inline]
43pub fn byte(op1: U256, op2: U256) -> U256 {
44	let mut ret = U256::zero();
45
46	for i in 0..256 {
47		if i < 8 && op1 < 32.into() {
48			let o: usize = op1.as_usize();
49			let t = 255 - (7 - i + 8 * o);
50			let bit_mask = U256::one() << t;
51			let value = (op2 & bit_mask) >> t;
52			ret = ret.overflowing_add(value << i).0;
53		}
54	}
55
56	ret
57}
58
59#[inline]
60pub fn shl(shift: U256, value: U256) -> U256 {
61	if value == U256::zero() || shift >= U256::from(256) {
62		U256::zero()
63	} else {
64		let shift: u64 = shift.as_u64();
65		value << shift as usize
66	}
67}
68
69#[inline]
70pub fn shr(shift: U256, value: U256) -> U256 {
71	if value == U256::zero() || shift >= U256::from(256) {
72		U256::zero()
73	} else {
74		let shift: u64 = shift.as_u64();
75		value >> shift as usize
76	}
77}
78
79#[inline]
80pub fn sar(shift: U256, value: U256) -> U256 {
81	let value = I256::from(value);
82
83	if value == I256::zero() || shift >= U256::from(256) {
84		let I256(sign, _) = value;
85		match sign {
86			// value is 0 or >=1, pushing 0
87			Sign::Plus | Sign::Zero => U256::zero(),
88			// value is <0, pushing -1
89			Sign::Minus => I256(Sign::Minus, U256::one()).into(),
90		}
91	} else {
92		let shift: u64 = shift.as_u64();
93
94		match value.0 {
95			Sign::Plus | Sign::Zero => value.1 >> shift as usize,
96			Sign::Minus => {
97				let shifted = ((value.1.overflowing_sub(U256::one()).0) >> shift as usize)
98					.overflowing_add(U256::one())
99					.0;
100				I256(Sign::Minus, shifted).into()
101			}
102		}
103	}
104}