revm_interpreter/instructions/
arithmetic.rs

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