revm_interpreter/instructions/
arithmetic.rs

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