Initial implementation of couple of more instructions
This commit is contained in:
parent
5d0c294635
commit
c4e5271651
@ -734,9 +734,33 @@ impl Interpreter {
|
|||||||
U256::zero()
|
U256::zero()
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// TODO instructions::SDIV => {},
|
instructions::SDIV => {
|
||||||
// TODO instructions::SMOD => {},
|
let (a, sign_a) = get_and_reset_sign(stack.pop_back());
|
||||||
// TODO instructions::EXP => {},
|
let (b, sign_b) = get_and_reset_sign(stack.pop_back());
|
||||||
|
|
||||||
|
stack.push(if !self.is_zero(&b) {
|
||||||
|
let (c, _overflow) = a.overflowing_div(b);
|
||||||
|
set_sign(c, sign_a ^ sign_b)
|
||||||
|
} else {
|
||||||
|
U256::zero()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
instructions::SMOD => {
|
||||||
|
let (a, sign_a) = get_and_reset_sign(stack.pop_back());
|
||||||
|
let (b, sign_b) = get_and_reset_sign(stack.pop_back());
|
||||||
|
|
||||||
|
stack.push(if !self.is_zero(&b) {
|
||||||
|
let (c, _overflow) = a.overflowing_rem(b);
|
||||||
|
set_sign(c, sign_a ^ sign_b)
|
||||||
|
} else {
|
||||||
|
U256::zero()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
instructions::EXP => {
|
||||||
|
let base = stack.pop_back();
|
||||||
|
let expon = stack.pop_back();
|
||||||
|
stack.push(u256_pow(base, expon));
|
||||||
|
},
|
||||||
instructions::NOT => {
|
instructions::NOT => {
|
||||||
let a = stack.pop_back();
|
let a = stack.pop_back();
|
||||||
stack.push(!a);
|
stack.push(!a);
|
||||||
@ -746,13 +770,31 @@ impl Interpreter {
|
|||||||
let b = stack.pop_back();
|
let b = stack.pop_back();
|
||||||
stack.push(self.bool_to_u256(a < b));
|
stack.push(self.bool_to_u256(a < b));
|
||||||
},
|
},
|
||||||
// TODO instructions::SLT => {},
|
instructions::SLT => {
|
||||||
|
let (a, neg_a) = get_and_reset_sign(stack.pop_back());
|
||||||
|
let (b, neg_b) = get_and_reset_sign(stack.pop_back());
|
||||||
|
|
||||||
|
let is_positive_lt = a < b && (neg_a | neg_b) == false;
|
||||||
|
let is_negative_lt = a > b && (neg_a & neg_b) == true;
|
||||||
|
let has_different_signs = neg_a == true && neg_b == false;
|
||||||
|
|
||||||
|
stack.push(self.bool_to_u256(is_positive_lt | is_negative_lt | has_different_signs));
|
||||||
|
},
|
||||||
instructions::GT => {
|
instructions::GT => {
|
||||||
let a = stack.pop_back();
|
let a = stack.pop_back();
|
||||||
let b = stack.pop_back();
|
let b = stack.pop_back();
|
||||||
stack.push(self.bool_to_u256(a > b));
|
stack.push(self.bool_to_u256(a > b));
|
||||||
},
|
},
|
||||||
// TODO instructions::SGT => {},
|
instructions::SGT => {
|
||||||
|
let (a, neg_a) = get_and_reset_sign(stack.pop_back());
|
||||||
|
let (b, neg_b) = get_and_reset_sign(stack.pop_back());
|
||||||
|
|
||||||
|
let is_positive_gt = a > b && (neg_a | neg_b) == false;
|
||||||
|
let is_negative_gt = a < b && (neg_a & neg_b) == true;
|
||||||
|
let has_different_signs = neg_a == false && neg_b == true;
|
||||||
|
|
||||||
|
stack.push(self.bool_to_u256(is_positive_gt | is_negative_gt | has_different_signs));
|
||||||
|
},
|
||||||
instructions::EQ => {
|
instructions::EQ => {
|
||||||
let a = stack.pop_back();
|
let a = stack.pop_back();
|
||||||
let b = stack.pop_back();
|
let b = stack.pop_back();
|
||||||
@ -777,10 +819,42 @@ impl Interpreter {
|
|||||||
let b = stack.pop_back();
|
let b = stack.pop_back();
|
||||||
stack.push(a ^ b);
|
stack.push(a ^ b);
|
||||||
},
|
},
|
||||||
// TODO instructions::BYTE => {},
|
instructions::BYTE => {
|
||||||
// TODO instructions::ADDMOD => {},
|
let word = stack.pop_back();
|
||||||
// TODO instructions::MULMOD => {},
|
let byte = if word < U256::from(32) {
|
||||||
// TODO instructions::SIGNEXTEND => {},
|
word >> (8 * (31 - word.low_u64() as usize))
|
||||||
|
} else {
|
||||||
|
U256::zero()
|
||||||
|
};
|
||||||
|
stack.push(byte);
|
||||||
|
},
|
||||||
|
instructions::ADDMOD => {
|
||||||
|
let a = stack.pop_back();
|
||||||
|
let b = stack.pop_back();
|
||||||
|
let c = stack.pop_back();
|
||||||
|
|
||||||
|
stack.push(if !self.is_zero(&c) {
|
||||||
|
let (res, _overflow) = a.overflowing_add(b);
|
||||||
|
let (x, _overflow) = res.overflowing_rem(c);
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
U256::zero()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
instructions::MULMOD => {
|
||||||
|
let a = stack.pop_back();
|
||||||
|
let b = stack.pop_back();
|
||||||
|
let c = stack.pop_back();
|
||||||
|
|
||||||
|
stack.push(if !self.is_zero(&c) {
|
||||||
|
let (res, _overflow) = a.overflowing_mul(b);
|
||||||
|
let (x, _overflow) = res.overflowing_rem(c);
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
U256::zero()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
instructions::SIGNEXTEND => {},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(evm::Error::BadInstruction {
|
return Err(evm::Error::BadInstruction {
|
||||||
instruction: instruction
|
instruction: instruction
|
||||||
@ -810,6 +884,20 @@ impl Interpreter {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn u256_pow(value: U256, expon: U256) -> U256 {
|
||||||
|
// TODO implement me!
|
||||||
|
U256::zero()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_and_reset_sign(value: U256) -> (U256, bool) {
|
||||||
|
let sign = value.bit(255);
|
||||||
|
(set_sign(value, false), sign)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_sign(value: U256, sign: bool) -> U256 {
|
||||||
|
value | (U256::from(sign as usize) << 256)
|
||||||
|
}
|
||||||
|
|
||||||
fn add_u256_usize(value: &U256, num: usize) -> U256 {
|
fn add_u256_usize(value: &U256, num: usize) -> U256 {
|
||||||
value.clone() + U256::from(num)
|
value.clone() + U256::from(num)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user