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