revm_interpreter/instructions/
arithmetic.rs

1use super::i256::{i256_div, i256_mod};
2use crate::{
3    gas,
4    interpreter_types::{InterpreterTypes, RuntimeFlag, StackTr},
5    InstructionContext,
6};
7use primitives::U256;
8
9/// Implements the ADD instruction - adds two values from stack.
10pub fn add<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
11    gas!(context.interpreter, gas::VERYLOW);
12    popn_top!([op1], op2, context.interpreter);
13    *op2 = op1.wrapping_add(*op2);
14}
15
16/// Implements the MUL instruction - multiplies two values from stack.
17pub fn mul<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
18    gas!(context.interpreter, gas::LOW);
19    popn_top!([op1], op2, context.interpreter);
20    *op2 = op1.wrapping_mul(*op2);
21}
22
23/// Implements the SUB instruction - subtracts two values from stack.
24pub fn sub<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
25    gas!(context.interpreter, gas::VERYLOW);
26    popn_top!([op1], op2, context.interpreter);
27    *op2 = op1.wrapping_sub(*op2);
28}
29
30/// Implements the DIV instruction - divides two values from stack.
31pub fn div<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
32    gas!(context.interpreter, gas::LOW);
33    popn_top!([op1], op2, context.interpreter);
34    if !op2.is_zero() {
35        *op2 = op1.wrapping_div(*op2);
36    }
37}
38
39/// Implements the SDIV instruction.
40///
41/// Performs signed division of two values from stack.
42pub fn sdiv<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
43    gas!(context.interpreter, gas::LOW);
44    popn_top!([op1], op2, context.interpreter);
45    *op2 = i256_div(op1, *op2);
46}
47
48/// Implements the MOD instruction.
49///
50/// Pops two values from stack and pushes the remainder of their division.
51pub fn rem<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
52    gas!(context.interpreter, gas::LOW);
53    popn_top!([op1], op2, context.interpreter);
54    if !op2.is_zero() {
55        *op2 = op1.wrapping_rem(*op2);
56    }
57}
58
59/// Implements the SMOD instruction.
60///
61/// Performs signed modulo of two values from stack.
62pub fn smod<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
63    gas!(context.interpreter, gas::LOW);
64    popn_top!([op1], op2, context.interpreter);
65    *op2 = i256_mod(op1, *op2)
66}
67
68/// Implements the ADDMOD instruction.
69///
70/// Pops three values from stack and pushes (a + b) % n.
71pub fn addmod<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
72    gas!(context.interpreter, gas::MID);
73    popn_top!([op1, op2], op3, context.interpreter);
74    *op3 = op1.add_mod(op2, *op3)
75}
76
77/// Implements the MULMOD instruction.
78///
79/// Pops three values from stack and pushes (a * b) % n.
80pub fn mulmod<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
81    gas!(context.interpreter, gas::MID);
82    popn_top!([op1, op2], op3, context.interpreter);
83    *op3 = op1.mul_mod(op2, *op3)
84}
85
86/// Implements the EXP instruction - exponentiates two values from stack.
87pub fn exp<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
88    let spec_id = context.interpreter.runtime_flag.spec_id();
89    popn_top!([op1], op2, context.interpreter);
90    gas_or_fail!(context.interpreter, gas::exp_cost(spec_id, *op2));
91    *op2 = op1.pow(*op2);
92}
93
94/// Implements the `SIGNEXTEND` opcode as defined in the Ethereum Yellow Paper.
95///
96/// In the yellow paper `SIGNEXTEND` is defined to take two inputs, we will call them
97/// `x` and `y`, and produce one output.
98///
99/// The first `t` bits of the output (numbering from the left, starting from 0) are
100/// equal to the `t`-th bit of `y`, where `t` is equal to `256 - 8(x + 1)`.
101///
102/// The remaining bits of the output are equal to the corresponding bits of `y`.
103///
104/// **Note**: If `x >= 32` then the output is equal to `y` since `t <= 0`.
105///
106/// To efficiently implement this algorithm in the case `x < 32` we do the following.
107///
108/// Let `b` be equal to the `t`-th bit of `y` and let `s = 255 - t = 8x + 7`
109/// (this is effectively the same index as `t`, but numbering the bits from the
110/// right instead of the left).
111///
112/// We can create a bit mask which is all zeros up to and including the `t`-th bit,
113/// and all ones afterwards by computing the quantity `2^s - 1`.
114///
115/// We can use this mask to compute the output depending on the value of `b`.
116///
117/// If `b == 1` then the yellow paper says the output should be all ones up to
118/// and including the `t`-th bit, followed by the remaining bits of `y`; this is equal to
119/// `y | !mask` where `|` is the bitwise `OR` and `!` is bitwise negation.
120///
121/// Similarly, if `b == 0` then the yellow paper says the output should start with all zeros,
122/// then end with bits from `b`; this is equal to `y & mask` where `&` is bitwise `AND`.
123pub fn signextend<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
124    gas!(context.interpreter, gas::LOW);
125    popn_top!([ext], x, context.interpreter);
126    // For 31 we also don't need to do anything.
127    if ext < U256::from(31) {
128        let ext = ext.as_limbs()[0];
129        let bit_index = (8 * ext + 7) as usize;
130        let bit = x.bit(bit_index);
131        let mask = (U256::from(1) << bit_index) - U256::from(1);
132        *x = if bit { *x | !mask } else { *x & mask };
133    }
134}