1use super::{i256::i256_cmp, Context};
19use crate::vm::Ext;
20use core::cmp::Ordering;
21use revm::{
22 interpreter::{gas as revm_gas, interpreter_types::StackTr},
23 primitives::U256,
24};
25
26pub fn lt<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
28 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
29 popn_top!([op1], op2, context.interpreter);
30 *op2 = U256::from(op1 < *op2);
31}
32
33pub fn gt<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
35 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
36 popn_top!([op1], op2, context.interpreter);
37
38 *op2 = U256::from(op1 > *op2);
39}
40
41pub fn clz<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
43 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
44 popn_top!([], op1, context.interpreter);
45
46 let leading_zeros = op1.leading_zeros();
47 *op1 = U256::from(leading_zeros);
48}
49
50pub fn slt<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
54 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
55 popn_top!([op1], op2, context.interpreter);
56
57 *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Less);
58}
59
60pub fn sgt<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
64 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
65 popn_top!([op1], op2, context.interpreter);
66
67 *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Greater);
68}
69
70pub fn eq<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
74 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
75 popn_top!([op1], op2, context.interpreter);
76
77 *op2 = U256::from(op1 == *op2);
78}
79
80pub fn iszero<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
84 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
85 popn_top!([], op1, context.interpreter);
86 *op1 = U256::from(op1.is_zero());
87}
88
89pub fn bitand<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
93 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
94 popn_top!([op1], op2, context.interpreter);
95 *op2 = op1 & *op2;
96}
97
98pub fn bitor<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
102 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
103 popn_top!([op1], op2, context.interpreter);
104
105 *op2 = op1 | *op2;
106}
107
108pub fn bitxor<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
112 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
113 popn_top!([op1], op2, context.interpreter);
114
115 *op2 = op1 ^ *op2;
116}
117
118pub fn not<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
122 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
123 popn_top!([], op1, context.interpreter);
124
125 *op1 = !*op1;
126}
127
128pub fn byte<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
132 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
133 popn_top!([op1], op2, context.interpreter);
134
135 let o1 = as_usize_saturated!(op1);
136 *op2 = if o1 < 32 {
137 U256::from(op2.byte(31 - o1))
139 } else {
140 U256::ZERO
141 };
142}
143
144pub fn shl<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
146 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
147 popn_top!([op1], op2, context.interpreter);
148
149 let shift = as_usize_saturated!(op1);
150 *op2 = if shift < 256 { *op2 << shift } else { U256::ZERO }
151}
152
153pub fn shr<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
155 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
156 popn_top!([op1], op2, context.interpreter);
157
158 let shift = as_usize_saturated!(op1);
159 *op2 = if shift < 256 { *op2 >> shift } else { U256::ZERO }
160}
161
162pub fn sar<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
164 gas_legacy!(context.interpreter, revm_gas::VERYLOW);
165 popn_top!([op1], op2, context.interpreter);
166
167 let shift = as_usize_saturated!(op1);
168 *op2 = if shift < 256 {
169 op2.arithmetic_shr(shift)
170 } else if op2.bit(255) {
171 U256::MAX
172 } else {
173 U256::ZERO
174 };
175}
176
177#[cfg(test)]
178mod tests {
179 use super::{byte, clz, sar, shl, shr};
180 use revm::{
181 interpreter::{host::DummyHost, InstructionContext},
182 primitives::{hardfork::SpecId, uint, U256},
183 };
184
185 pub fn test_interpreter() -> revm::interpreter::Interpreter<
186 crate::vm::evm::EVMInterpreter<'static, crate::exec::mock_ext::MockExt<crate::tests::Test>>,
187 > {
188 use crate::tests::Test;
189 use revm::{
190 interpreter::{
191 interpreter::{RuntimeFlags, SharedMemory},
192 Interpreter, Stack,
193 },
194 primitives::hardfork::SpecId,
195 };
196
197 let mock_ext = Box::leak(Box::new(crate::exec::mock_ext::MockExt::<Test>::new()));
198
199 Interpreter {
200 gas: revm::interpreter::Gas::new(0),
201 bytecode: Default::default(),
202 stack: Stack::new(),
203 return_data: Default::default(),
204 memory: SharedMemory::new(),
205 input: crate::vm::evm::EVMInputs::default(),
206 runtime_flag: RuntimeFlags { is_static: false, spec_id: SpecId::default() },
207 extend: mock_ext,
208 }
209 }
210
211 #[test]
212 fn test_shift_left() {
213 let mut interpreter = test_interpreter();
214
215 struct TestCase {
216 value: U256,
217 shift: U256,
218 expected: U256,
219 }
220
221 uint! {
222 let test_cases = [
223 TestCase {
224 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
225 shift: 0x00_U256,
226 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
227 },
228 TestCase {
229 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
230 shift: 0x01_U256,
231 expected: 0x0000000000000000000000000000000000000000000000000000000000000002_U256,
232 },
233 TestCase {
234 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
235 shift: 0xff_U256,
236 expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
237 },
238 TestCase {
239 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
240 shift: 0x0100_U256,
241 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
242 },
243 TestCase {
244 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
245 shift: 0x0101_U256,
246 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
247 },
248 TestCase {
249 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
250 shift: 0x00_U256,
251 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
252 },
253 TestCase {
254 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
255 shift: 0x01_U256,
256 expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
257 },
258 TestCase {
259 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
260 shift: 0xff_U256,
261 expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
262 },
263 TestCase {
264 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
265 shift: 0x0100_U256,
266 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
267 },
268 TestCase {
269 value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
270 shift: 0x01_U256,
271 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
272 },
273 TestCase {
274 value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
275 shift: 0x01_U256,
276 expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
277 },
278 ];
279 }
280
281 for test in test_cases {
282 push!(interpreter, test.value);
283 push!(interpreter, test.shift);
284 let context =
285 InstructionContext { host: &mut DummyHost, interpreter: &mut interpreter };
286 shl(context);
287 let res = interpreter.stack.pop().unwrap();
288 assert_eq!(res, test.expected);
289 }
290 }
291
292 #[test]
293 fn test_logical_shift_right() {
294 let mut interpreter = test_interpreter();
295
296 struct TestCase {
297 value: U256,
298 shift: U256,
299 expected: U256,
300 }
301
302 uint! {
303 let test_cases = [
304 TestCase {
305 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
306 shift: 0x00_U256,
307 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
308 },
309 TestCase {
310 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
311 shift: 0x01_U256,
312 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
313 },
314 TestCase {
315 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
316 shift: 0x01_U256,
317 expected: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
318 },
319 TestCase {
320 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
321 shift: 0xff_U256,
322 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
323 },
324 TestCase {
325 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
326 shift: 0x0100_U256,
327 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
328 },
329 TestCase {
330 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
331 shift: 0x0101_U256,
332 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
333 },
334 TestCase {
335 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
336 shift: 0x00_U256,
337 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
338 },
339 TestCase {
340 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
341 shift: 0x01_U256,
342 expected: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
343 },
344 TestCase {
345 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
346 shift: 0xff_U256,
347 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
348 },
349 TestCase {
350 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
351 shift: 0x0100_U256,
352 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
353 },
354 TestCase {
355 value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
356 shift: 0x01_U256,
357 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
358 },
359 ];
360 }
361
362 for test in test_cases {
363 push!(interpreter, test.value);
364 push!(interpreter, test.shift);
365 let context =
366 InstructionContext { host: &mut DummyHost, interpreter: &mut interpreter };
367 shr(context);
368 let res = interpreter.stack.pop().unwrap();
369 assert_eq!(res, test.expected);
370 }
371 }
372
373 #[test]
374 fn test_arithmetic_shift_right() {
375 let mut interpreter = test_interpreter();
376
377 struct TestCase {
378 value: U256,
379 shift: U256,
380 expected: U256,
381 }
382
383 uint! {
384 let test_cases = [
385 TestCase {
386 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
387 shift: 0x00_U256,
388 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
389 },
390 TestCase {
391 value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
392 shift: 0x01_U256,
393 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
394 },
395 TestCase {
396 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
397 shift: 0x01_U256,
398 expected: 0xc000000000000000000000000000000000000000000000000000000000000000_U256,
399 },
400 TestCase {
401 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
402 shift: 0xff_U256,
403 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
404 },
405 TestCase {
406 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
407 shift: 0x0100_U256,
408 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
409 },
410 TestCase {
411 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
412 shift: 0x0101_U256,
413 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
414 },
415 TestCase {
416 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
417 shift: 0x00_U256,
418 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
419 },
420 TestCase {
421 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
422 shift: 0x01_U256,
423 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
424 },
425 TestCase {
426 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
427 shift: 0xff_U256,
428 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
429 },
430 TestCase {
431 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
432 shift: 0x0100_U256,
433 expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
434 },
435 TestCase {
436 value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
437 shift: 0x01_U256,
438 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
439 },
440 TestCase {
441 value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
442 shift: 0xfe_U256,
443 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
444 },
445 TestCase {
446 value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
447 shift: 0xf8_U256,
448 expected: 0x000000000000000000000000000000000000000000000000000000000000007f_U256,
449 },
450 TestCase {
451 value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
452 shift: 0xfe_U256,
453 expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
454 },
455 TestCase {
456 value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
457 shift: 0xff_U256,
458 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
459 },
460 TestCase {
461 value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
462 shift: 0x0100_U256,
463 expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
464 },
465 ];
466 }
467
468 for test in test_cases {
469 push!(interpreter, test.value);
470 push!(interpreter, test.shift);
471 let context =
472 InstructionContext { host: &mut DummyHost, interpreter: &mut interpreter };
473 sar(context);
474 let res = interpreter.stack.pop().unwrap();
475 assert_eq!(res, test.expected);
476 }
477 }
478
479 #[test]
480 fn test_byte() {
481 struct TestCase {
482 input: U256,
483 index: usize,
484 expected: U256,
485 }
486
487 let mut interpreter = test_interpreter();
488
489 let input_value = U256::from(0x1234567890abcdef1234567890abcdef_u128);
490 let test_cases = (0..32)
491 .map(|i| {
492 let byte_pos = 31 - i;
493
494 let shift_amount = U256::from(byte_pos * 8);
495 let byte_value = (input_value >> shift_amount) & U256::from(0xFF);
496 TestCase { input: input_value, index: i, expected: byte_value }
497 })
498 .collect::<Vec<_>>();
499
500 for test in test_cases.iter() {
501 push!(interpreter, test.input);
502 push!(interpreter, U256::from(test.index));
503 let context =
504 InstructionContext { host: &mut DummyHost, interpreter: &mut interpreter };
505 byte(context);
506 let res = interpreter.stack.pop().unwrap();
507 assert_eq!(res, test.expected, "Failed at index: {}", test.index);
508 }
509 }
510
511 #[test]
512 fn test_clz() {
513 let mut interpreter = test_interpreter();
514 interpreter.runtime_flag.spec_id = SpecId::OSAKA;
515
516 struct TestCase {
517 value: U256,
518 expected: U256,
519 }
520
521 uint! {
522 let test_cases = [
523 TestCase { value: 0x0_U256, expected: 256_U256 },
524 TestCase { value: 0x1_U256, expected: 255_U256 },
525 TestCase { value: 0x2_U256, expected: 254_U256 },
526 TestCase { value: 0x3_U256, expected: 254_U256 },
527 TestCase { value: 0x4_U256, expected: 253_U256 },
528 TestCase { value: 0x7_U256, expected: 253_U256 },
529 TestCase { value: 0x8_U256, expected: 252_U256 },
530 TestCase { value: 0xff_U256, expected: 248_U256 },
531 TestCase { value: 0x100_U256, expected: 247_U256 },
532 TestCase { value: 0xffff_U256, expected: 240_U256 },
533 TestCase {
534 value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, expected: 0_U256,
536 },
537 TestCase {
538 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, expected: 0_U256,
540 },
541 TestCase { value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256, expected: 1_U256,
544 },
545 TestCase { value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
547 expected: 1_U256,
548 },
549 ];
550 }
551
552 for test in test_cases {
553 push!(interpreter, test.value);
554 let context =
555 InstructionContext { host: &mut DummyHost, interpreter: &mut interpreter };
556 clz(context);
557 let res = interpreter.stack.pop().unwrap();
558 assert_eq!(
559 res, test.expected,
560 "CLZ for value {:#x} failed. Expected: {}, Got: {}",
561 test.value, test.expected, res
562 );
563 }
564 }
565}