use crate::core::utils::{Sign, I256};
use crate::utils::{U256_ONE, U256_VALUE_256, U256_VALUE_32, U256_ZERO};
use primitive_types::U256;
#[inline]
pub fn slt(op1: U256, op2: U256) -> U256 {
let op1: I256 = op1.into();
let op2: I256 = op2.into();
if op1.lt(&op2) {
U256_ONE
} else {
U256_ZERO
}
}
#[inline]
pub fn sgt(op1: U256, op2: U256) -> U256 {
let op1: I256 = op1.into();
let op2: I256 = op2.into();
if op1.gt(&op2) {
U256_ONE
} else {
U256_ZERO
}
}
#[inline]
pub fn iszero(op1: U256) -> U256 {
if op1 == U256_ZERO {
U256_ONE
} else {
U256_ZERO
}
}
#[inline]
pub fn not(op1: U256) -> U256 {
!op1
}
#[inline]
pub fn byte(op1: U256, op2: U256) -> U256 {
let mut ret = U256_ZERO;
if op1 < U256_VALUE_32 {
let o = op1.as_usize();
for i in 0..8 {
let t = 255 - (7 - i + 8 * o);
let value = (op2 >> t) & U256_ONE;
ret = ret.overflowing_add(value << i).0;
}
}
ret
}
#[inline]
pub fn shl(shift: U256, value: U256) -> U256 {
if value == U256_ZERO || shift >= U256_VALUE_256 {
U256_ZERO
} else {
value << shift.as_usize()
}
}
#[inline]
pub fn shr(shift: U256, value: U256) -> U256 {
if value == U256_ZERO || shift >= U256_VALUE_256 {
U256_ZERO
} else {
value >> shift.as_usize()
}
}
#[inline]
pub fn sar(shift: U256, value: U256) -> U256 {
let value = I256::from(value);
if value == I256::zero() || shift >= U256_VALUE_256 {
let I256(sign, _) = value;
match sign {
Sign::Plus | Sign::Zero => U256_ZERO,
Sign::Minus => I256(Sign::Minus, U256_ONE).into(),
}
} else {
let shift = shift.as_usize();
match value.0 {
Sign::Plus | Sign::Zero => value.1 >> shift,
Sign::Minus => {
let shifted = ((value.1.overflowing_sub(U256_ONE).0) >> shift)
.overflowing_add(U256_ONE)
.0;
I256(Sign::Minus, shifted).into()
}
}
}
}