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