@@ -5,6 +5,7 @@ use crate::{
5
5
Host , Interpreter ,
6
6
} ;
7
7
use core:: cmp:: Ordering ;
8
+ use revm_primitives:: uint;
8
9
9
10
pub fn lt < H : Host > ( interpreter : & mut Interpreter , _host : & mut H ) {
10
11
gas ! ( interpreter, gas:: VERYLOW ) ;
@@ -103,19 +104,299 @@ pub fn sar<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
103
104
104
105
let value_sign = i256_sign_compl ( op2) ;
105
106
106
- * op2 = if value_sign == Sign :: Zero || op1 >= U256 :: from ( 256 ) {
107
+ // If the shift count is 255+, we can short-circuit. This is because shifting by 255 bits is the
108
+ // maximum shift that still leaves 1 bit in the original 256-bit number. Shifting by 256 bits or
109
+ // more would mean that no original bits remain. The result depends on what the highest bit of
110
+ // the value is.
111
+ * op2 = if value_sign == Sign :: Zero || op1 >= U256 :: from ( 255 ) {
107
112
match value_sign {
108
113
// value is 0 or >=1, pushing 0
109
114
Sign :: Plus | Sign :: Zero => U256 :: ZERO ,
110
115
// value is <0, pushing -1
111
116
Sign :: Minus => U256 :: MAX ,
112
117
}
113
118
} else {
114
- const ONE : U256 = U256 :: from_limbs ( [ 1 , 0 , 0 , 0 ] ) ;
119
+ const ONE : U256 = uint ! ( 1_ U256 ) ;
120
+ // SAFETY: shift count is checked above; it's less than 255.
115
121
let shift = usize:: try_from ( op1) . unwrap ( ) ;
116
122
match value_sign {
117
123
Sign :: Plus | Sign :: Zero => op2. wrapping_shr ( shift) ,
118
124
Sign :: Minus => two_compl ( op2. wrapping_sub ( ONE ) . wrapping_shr ( shift) . wrapping_add ( ONE ) ) ,
119
125
}
120
126
} ;
121
127
}
128
+
129
+ #[ cfg( test) ]
130
+ mod tests {
131
+ use crate :: instructions:: bitwise:: { sar, shl, shr} ;
132
+ use crate :: { Contract , DummyHost , Interpreter } ;
133
+ use revm_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
+ }
0 commit comments