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