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