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