revm_interpreter/instructions/
bitwise.rs

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