evm 0.9.4

Ethereum Virtual Machine implementation in Rust. Nightly version of SputnikVM.
Documentation
//! Arithmetic instructions

use bigint::{M256, U512};

use ::Memory;
use super::State;
use patch::Patch;

pub fn addmod<M: Memory + Default, P: Patch>(state: &mut State<M, P>) {
    pop!(state, op1: U512, op2: U512, op3: U512);

    if op3 == U512::zero() {
        push!(state, M256::zero());
    } else {
        let v = (op1 + op2) % op3;
        push!(state, v.into());
    }
}

pub fn mulmod<M: Memory + Default, P: Patch>(state: &mut State<M, P>) {
    pop!(state, op1: U512, op2: U512, op3: U512);

    if op3 == U512::zero() {
        push!(state, M256::zero());
    } else {
        let v = (op1 * op2) % op3;
        push!(state, v.into());
    }
}


pub fn exp<M: Memory + Default, P: Patch>(state: &mut State<M, P>) {
    pop!(state, op1, op2);
    let mut op1 = op1;
    let mut op2 = op2;
    let mut r: M256 = 1.into();

    while op2 != 0.into() {
        if op2 & 1.into() != 0.into() {
            r = r * op1;
        }
        op2 = op2 >> 1;
        op1 = op1 * op1;
    }

    push!(state, r);
}

pub fn signextend<M: Memory + Default, P: Patch>(state: &mut State<M, P>) {
    pop!(state, op1, op2);

    if op1 > M256::from(32) {
        push!(state, op2);
    } else {
        let mut ret = M256::zero();
        let len: usize = op1.as_usize();
        let t: usize = 8 * (len + 1) - 1;
        let t_bit_mask = M256::one() << t;
        let t_value = (op2 & t_bit_mask) >> t;
        for i in 0..256 {
            let bit_mask = M256::one() << i;
            let i_value = (op2 & bit_mask) >> i;
            if i <= t {
                ret = ret + (i_value << i);
            } else {
                ret = ret + (t_value << i);
            }
        }
        push!(state, ret);
    }
}