revm_interpreter/instructions/
bitwise.rs

1use super::i256::i256_cmp;
2use crate::{
3    gas,
4    interpreter_types::{InterpreterTypes, RuntimeFlag, StackTr},
5    InstructionContext,
6};
7use core::cmp::Ordering;
8use primitives::U256;
9
10/// Implements the LT instruction - less than comparison.
11pub fn lt<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
12    gas!(context.interpreter, gas::VERYLOW);
13    popn_top!([op1], op2, context.interpreter);
14    *op2 = U256::from(op1 < *op2);
15}
16
17/// Implements the GT instruction - greater than comparison.
18pub fn gt<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
19    gas!(context.interpreter, gas::VERYLOW);
20    popn_top!([op1], op2, context.interpreter);
21
22    *op2 = U256::from(op1 > *op2);
23}
24
25/// Implements the CLZ instruction - count leading zeros.
26pub fn clz<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
27    check!(context.interpreter, OSAKA);
28    gas!(context.interpreter, gas::VERYLOW);
29    popn_top!([], op1, context.interpreter);
30
31    let leading_zeros = op1.leading_zeros();
32    *op1 = U256::from(leading_zeros);
33}
34
35/// Implements the SLT instruction.
36///
37/// Signed less than comparison of two values from stack.
38pub fn slt<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
39    gas!(context.interpreter, gas::VERYLOW);
40    popn_top!([op1], op2, context.interpreter);
41
42    *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Less);
43}
44
45/// Implements the SGT instruction.
46///
47/// Signed greater than comparison of two values from stack.
48pub fn sgt<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
49    gas!(context.interpreter, gas::VERYLOW);
50    popn_top!([op1], op2, context.interpreter);
51
52    *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Greater);
53}
54
55/// Implements the EQ instruction.
56///
57/// Equality comparison of two values from stack.
58pub fn eq<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
59    gas!(context.interpreter, gas::VERYLOW);
60    popn_top!([op1], op2, context.interpreter);
61
62    *op2 = U256::from(op1 == *op2);
63}
64
65/// Implements the ISZERO instruction.
66///
67/// Checks if the top stack value is zero.
68pub fn iszero<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
69    gas!(context.interpreter, gas::VERYLOW);
70    popn_top!([], op1, context.interpreter);
71    *op1 = U256::from(op1.is_zero());
72}
73
74/// Implements the AND instruction.
75///
76/// Bitwise AND of two values from stack.
77pub fn bitand<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
78    gas!(context.interpreter, gas::VERYLOW);
79    popn_top!([op1], op2, context.interpreter);
80    *op2 = op1 & *op2;
81}
82
83/// Implements the OR instruction.
84///
85/// Bitwise OR of two values from stack.
86pub fn bitor<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
87    gas!(context.interpreter, gas::VERYLOW);
88    popn_top!([op1], op2, context.interpreter);
89
90    *op2 = op1 | *op2;
91}
92
93/// Implements the XOR instruction.
94///
95/// Bitwise XOR of two values from stack.
96pub fn bitxor<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
97    gas!(context.interpreter, gas::VERYLOW);
98    popn_top!([op1], op2, context.interpreter);
99
100    *op2 = op1 ^ *op2;
101}
102
103/// Implements the NOT instruction.
104///
105/// Bitwise NOT (negation) of the top stack value.
106pub fn not<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
107    gas!(context.interpreter, gas::VERYLOW);
108    popn_top!([], op1, context.interpreter);
109
110    *op1 = !*op1;
111}
112
113/// Implements the BYTE instruction.
114///
115/// Extracts a single byte from a word at a given index.
116pub fn byte<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
117    gas!(context.interpreter, gas::VERYLOW);
118    popn_top!([op1], op2, context.interpreter);
119
120    let o1 = as_usize_saturated!(op1);
121    *op2 = if o1 < 32 {
122        // `31 - o1` because `byte` returns LE, while we want BE
123        U256::from(op2.byte(31 - o1))
124    } else {
125        U256::ZERO
126    };
127}
128
129/// EIP-145: Bitwise shifting instructions in EVM
130pub fn shl<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
131    check!(context.interpreter, CONSTANTINOPLE);
132    gas!(context.interpreter, gas::VERYLOW);
133    popn_top!([op1], op2, context.interpreter);
134
135    let shift = as_usize_saturated!(op1);
136    *op2 = if shift < 256 {
137        *op2 << shift
138    } else {
139        U256::ZERO
140    }
141}
142
143/// EIP-145: Bitwise shifting instructions in EVM
144pub fn shr<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
145    check!(context.interpreter, CONSTANTINOPLE);
146    gas!(context.interpreter, gas::VERYLOW);
147    popn_top!([op1], op2, context.interpreter);
148
149    let shift = as_usize_saturated!(op1);
150    *op2 = if shift < 256 {
151        *op2 >> shift
152    } else {
153        U256::ZERO
154    }
155}
156
157/// EIP-145: Bitwise shifting instructions in EVM
158pub fn sar<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
159    check!(context.interpreter, CONSTANTINOPLE);
160    gas!(context.interpreter, gas::VERYLOW);
161    popn_top!([op1], op2, context.interpreter);
162
163    let shift = as_usize_saturated!(op1);
164    *op2 = if shift < 256 {
165        op2.arithmetic_shr(shift)
166    } else if op2.bit(255) {
167        U256::MAX
168    } else {
169        U256::ZERO
170    };
171}
172
173#[cfg(test)]
174mod tests {
175    use crate::{
176        host::DummyHost,
177        instructions::bitwise::{byte, clz, sar, shl, shr},
178        InstructionContext, Interpreter,
179    };
180    use primitives::{hardfork::SpecId, uint, U256};
181
182    #[test]
183    fn test_shift_left() {
184        let mut interpreter = Interpreter::default();
185
186        struct TestCase {
187            value: U256,
188            shift: U256,
189            expected: U256,
190        }
191
192        uint! {
193            let test_cases = [
194                TestCase {
195                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
196                    shift: 0x00_U256,
197                    expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
198                },
199                TestCase {
200                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
201                    shift: 0x01_U256,
202                    expected: 0x0000000000000000000000000000000000000000000000000000000000000002_U256,
203                },
204                TestCase {
205                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
206                    shift: 0xff_U256,
207                    expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
208                },
209                TestCase {
210                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
211                    shift: 0x0100_U256,
212                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
213                },
214                TestCase {
215                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
216                    shift: 0x0101_U256,
217                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
218                },
219                TestCase {
220                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
221                    shift: 0x00_U256,
222                    expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
223                },
224                TestCase {
225                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
226                    shift: 0x01_U256,
227                    expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
228                },
229                TestCase {
230                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
231                    shift: 0xff_U256,
232                    expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
233                },
234                TestCase {
235                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
236                    shift: 0x0100_U256,
237                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
238                },
239                TestCase {
240                    value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
241                    shift: 0x01_U256,
242                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
243                },
244                TestCase {
245                    value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
246                    shift: 0x01_U256,
247                    expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
248                },
249            ];
250        }
251
252        for test in test_cases {
253            push!(interpreter, test.value);
254            push!(interpreter, test.shift);
255            let context = InstructionContext {
256                host: &mut DummyHost,
257                interpreter: &mut interpreter,
258            };
259            shl(context);
260            let res = interpreter.stack.pop().unwrap();
261            assert_eq!(res, test.expected);
262        }
263    }
264
265    #[test]
266    fn test_logical_shift_right() {
267        let mut interpreter = Interpreter::default();
268
269        struct TestCase {
270            value: U256,
271            shift: U256,
272            expected: U256,
273        }
274
275        uint! {
276            let test_cases = [
277                TestCase {
278                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
279                    shift: 0x00_U256,
280                    expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
281                },
282                TestCase {
283                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
284                    shift: 0x01_U256,
285                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
286                },
287                TestCase {
288                    value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
289                    shift: 0x01_U256,
290                    expected: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
291                },
292                TestCase {
293                    value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
294                    shift: 0xff_U256,
295                    expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
296                },
297                TestCase {
298                    value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
299                    shift: 0x0100_U256,
300                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
301                },
302                TestCase {
303                    value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
304                    shift: 0x0101_U256,
305                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
306                },
307                TestCase {
308                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
309                    shift: 0x00_U256,
310                    expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
311                },
312                TestCase {
313                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
314                    shift: 0x01_U256,
315                    expected: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
316                },
317                TestCase {
318                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
319                    shift: 0xff_U256,
320                    expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
321                },
322                TestCase {
323                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
324                    shift: 0x0100_U256,
325                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
326                },
327                TestCase {
328                    value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
329                    shift: 0x01_U256,
330                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
331                },
332            ];
333        }
334
335        for test in test_cases {
336            push!(interpreter, test.value);
337            push!(interpreter, test.shift);
338            let context = InstructionContext {
339                host: &mut DummyHost,
340                interpreter: &mut interpreter,
341            };
342            shr(context);
343            let res = interpreter.stack.pop().unwrap();
344            assert_eq!(res, test.expected);
345        }
346    }
347
348    #[test]
349    fn test_arithmetic_shift_right() {
350        let mut interpreter = Interpreter::default();
351
352        struct TestCase {
353            value: U256,
354            shift: U256,
355            expected: U256,
356        }
357
358        uint! {
359        let test_cases = [
360            TestCase {
361                value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
362                shift: 0x00_U256,
363                expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
364            },
365            TestCase {
366                value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
367                shift: 0x01_U256,
368                expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
369            },
370            TestCase {
371                value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
372                shift: 0x01_U256,
373                expected: 0xc000000000000000000000000000000000000000000000000000000000000000_U256,
374            },
375            TestCase {
376                value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
377                shift: 0xff_U256,
378                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
379            },
380            TestCase {
381                value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
382                shift: 0x0100_U256,
383                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
384            },
385            TestCase {
386                value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
387                shift: 0x0101_U256,
388                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
389            },
390            TestCase {
391                value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
392                shift: 0x00_U256,
393                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
394            },
395            TestCase {
396                value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
397                shift: 0x01_U256,
398                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
399            },
400            TestCase {
401                value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
402                shift: 0xff_U256,
403                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
404            },
405            TestCase {
406                value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
407                shift: 0x0100_U256,
408                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
409            },
410            TestCase {
411                value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
412                shift: 0x01_U256,
413                expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
414            },
415            TestCase {
416                value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
417                shift: 0xfe_U256,
418                expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
419            },
420            TestCase {
421                value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
422                shift: 0xf8_U256,
423                expected: 0x000000000000000000000000000000000000000000000000000000000000007f_U256,
424            },
425            TestCase {
426                value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
427                shift: 0xfe_U256,
428                expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
429            },
430            TestCase {
431                value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
432                shift: 0xff_U256,
433                expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
434            },
435            TestCase {
436                value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
437                shift: 0x0100_U256,
438                expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
439            },
440        ];
441            }
442
443        for test in test_cases {
444            push!(interpreter, test.value);
445            push!(interpreter, test.shift);
446            let context = InstructionContext {
447                host: &mut DummyHost,
448                interpreter: &mut interpreter,
449            };
450            sar(context);
451            let res = interpreter.stack.pop().unwrap();
452            assert_eq!(res, test.expected);
453        }
454    }
455
456    #[test]
457    fn test_byte() {
458        struct TestCase {
459            input: U256,
460            index: usize,
461            expected: U256,
462        }
463
464        let mut interpreter = Interpreter::default();
465
466        let input_value = U256::from(0x1234567890abcdef1234567890abcdef_u128);
467        let test_cases = (0..32)
468            .map(|i| {
469                let byte_pos = 31 - i;
470
471                let shift_amount = U256::from(byte_pos * 8);
472                let byte_value = (input_value >> shift_amount) & U256::from(0xFF);
473                TestCase {
474                    input: input_value,
475                    index: i,
476                    expected: byte_value,
477                }
478            })
479            .collect::<Vec<_>>();
480
481        for test in test_cases.iter() {
482            push!(interpreter, test.input);
483            push!(interpreter, U256::from(test.index));
484            let context = InstructionContext {
485                host: &mut DummyHost,
486                interpreter: &mut interpreter,
487            };
488            byte(context);
489            let res = interpreter.stack.pop().unwrap();
490            assert_eq!(res, test.expected, "Failed at index: {}", test.index);
491        }
492    }
493
494    #[test]
495    fn test_clz() {
496        let mut interpreter = Interpreter::default();
497        interpreter.set_spec_id(SpecId::OSAKA);
498
499        struct TestCase {
500            value: U256,
501            expected: U256,
502        }
503
504        uint! {
505            let test_cases = [
506                TestCase { value: 0x0_U256, expected: 256_U256 },
507                TestCase { value: 0x1_U256, expected: 255_U256 },
508                TestCase { value: 0x2_U256, expected: 254_U256 },
509                TestCase { value: 0x3_U256, expected: 254_U256 },
510                TestCase { value: 0x4_U256, expected: 253_U256 },
511                TestCase { value: 0x7_U256, expected: 253_U256 },
512                TestCase { value: 0x8_U256, expected: 252_U256 },
513                TestCase { value: 0xff_U256, expected: 248_U256 },
514                TestCase { value: 0x100_U256, expected: 247_U256 },
515                TestCase { value: 0xffff_U256, expected: 240_U256 },
516                TestCase {
517                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, // U256::MAX
518                    expected: 0_U256,
519                },
520                TestCase {
521                    value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, // 1 << 255
522                    expected: 0_U256,
523                },
524                TestCase { // Smallest value with 1 leading zero
525                    value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256, // 1 << 254
526                    expected: 1_U256,
527                },
528                TestCase { // Value just below 1 << 255
529                    value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
530                    expected: 1_U256,
531                },
532            ];
533        }
534
535        for test in test_cases {
536            push!(interpreter, test.value);
537            let context = InstructionContext {
538                host: &mut DummyHost,
539                interpreter: &mut interpreter,
540            };
541            clz(context);
542            let res = interpreter.stack.pop().unwrap();
543            assert_eq!(
544                res, test.expected,
545                "CLZ for value {:#x} failed. Expected: {}, Got: {}",
546                test.value, test.expected, res
547            );
548        }
549    }
550}