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
10pub 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
17pub 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
25pub 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
35pub 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
45pub 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
55pub 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
65pub 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
74pub 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
83pub 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
93pub 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
103pub 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
113pub 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 U256::from(op2.byte(31 - o1))
124 } else {
125 U256::ZERO
126 };
127}
128
129pub 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
143pub 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
157pub 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, expected: 0_U256,
519 },
520 TestCase {
521 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, expected: 0_U256,
523 },
524 TestCase { value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256, expected: 1_U256,
527 },
528 TestCase { 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}