1use super::i256::i256_cmp;
2use crate::{
3 interpreter_types::{InterpreterTypes, RuntimeFlag, StackTr},
4 InstructionContext,
5};
6use core::cmp::Ordering;
7use primitives::U256;
8
9pub fn lt<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
11 popn_top!([op1], op2, context.interpreter);
13 *op2 = U256::from(op1 < *op2);
14}
15
16pub fn gt<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
18 popn_top!([op1], op2, context.interpreter);
20
21 *op2 = U256::from(op1 > *op2);
22}
23
24pub fn clz<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
26 check!(context.interpreter, OSAKA);
27 popn_top!([], op1, context.interpreter);
29
30 let leading_zeros = op1.leading_zeros();
31 *op1 = U256::from(leading_zeros);
32}
33
34pub fn slt<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
38 popn_top!([op1], op2, context.interpreter);
40
41 *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Less);
42}
43
44pub fn sgt<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
48 popn_top!([op1], op2, context.interpreter);
50
51 *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Greater);
52}
53
54pub fn eq<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
58 popn_top!([op1], op2, context.interpreter);
60
61 *op2 = U256::from(op1 == *op2);
62}
63
64pub fn iszero<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
68 popn_top!([], op1, context.interpreter);
70 *op1 = U256::from(op1.is_zero());
71}
72
73pub fn bitand<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
77 popn_top!([op1], op2, context.interpreter);
79 *op2 = op1 & *op2;
80}
81
82pub fn bitor<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
86 popn_top!([op1], op2, context.interpreter);
88
89 *op2 = op1 | *op2;
90}
91
92pub fn bitxor<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
96 popn_top!([op1], op2, context.interpreter);
98
99 *op2 = op1 ^ *op2;
100}
101
102pub fn not<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
106 popn_top!([], op1, context.interpreter);
108
109 *op1 = !*op1;
110}
111
112pub fn byte<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
116 popn_top!([op1], op2, context.interpreter);
118
119 let o1 = as_usize_saturated!(op1);
120 *op2 = if o1 < 32 {
121 U256::from(op2.byte(31 - o1))
123 } else {
124 U256::ZERO
125 };
126}
127
128pub fn shl<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
130 check!(context.interpreter, CONSTANTINOPLE);
131 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
142pub fn shr<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
144 check!(context.interpreter, CONSTANTINOPLE);
145 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
156pub fn sar<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
158 check!(context.interpreter, CONSTANTINOPLE);
159 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, expected: 0_U256,
518 },
519 TestCase {
520 value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, expected: 0_U256,
522 },
523 TestCase { value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256, expected: 1_U256,
526 },
527 TestCase { 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}