ckb_vm/instructions/
register.rs

1use std::cmp::min;
2use std::fmt::Display;
3use std::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
4
5pub trait Register:
6    Sized
7    + Clone
8    + Default
9    + Display
10    + Not<Output = Self>
11    + BitAnd<Output = Self>
12    + BitOr<Output = Self>
13    + BitXor<Output = Self>
14    + Shl<Self, Output = Self>
15    + Shr<Self, Output = Self>
16{
17    const BITS: u8;
18    const SHIFT_MASK: u8;
19
20    fn zero() -> Self;
21    fn one() -> Self;
22
23    fn min_value() -> Self;
24    fn max_value() -> Self;
25
26    // Conditional operations, if the condition evaluated here is true, R::one()
27    // will be emitted, otherwise R::zero() will be emitted
28    fn eq(&self, other: &Self) -> Self;
29    fn lt(&self, other: &Self) -> Self;
30    fn lt_s(&self, other: &Self) -> Self;
31    fn logical_not(&self) -> Self;
32
33    // self here should be the result of one of the conditional operations, if
34    // self is R::one(), true_value will be returned, otherwise false_value will
35    // be returned. No values other than R::one() or R::zero() should be accepted
36    // as self here.
37    fn cond(&self, true_value: &Self, false_value: &Self) -> Self;
38
39    fn overflowing_add(&self, rhs: &Self) -> Self;
40    fn overflowing_sub(&self, rhs: &Self) -> Self;
41    fn overflowing_mul(&self, rhs: &Self) -> Self;
42
43    // Those 4 methods should implement RISC-V's overflowing strategies:
44    // +---------------------------------------------------------------------------------------+
45    // | Condition              | Dividend  | Divisor | DIVU[W] | REMU[W] |  DIV[W]   | REM[W] |
46    // +------------------------+-----------+---------+---------+---------+-----------+--------+
47    // | Division by zero       |     x     |    0    | 2**L-1  |    x    |    -1     |   x    |
48    // +------------------------+-----------+---------+---------+---------+-----------+--------+
49    // | Overflow (signed only) | āˆ’2**(Lāˆ’1) |   āˆ’1    |    -    |    -    | -2**(L-1) |   0    |
50    // +---------------------------------------------------------------------------------------+
51    fn overflowing_div(&self, rhs: &Self) -> Self;
52    fn overflowing_rem(&self, rhs: &Self) -> Self;
53    fn overflowing_div_signed(&self, rhs: &Self) -> Self;
54    fn overflowing_rem_signed(&self, rhs: &Self) -> Self;
55
56    fn overflowing_mul_high_signed(&self, rhs: &Self) -> Self;
57    fn overflowing_mul_high_unsigned(&self, rhs: &Self) -> Self;
58    fn overflowing_mul_high_signed_unsigned(&self, rhs: &Self) -> Self;
59
60    // The clz operation counts the number of 0 bits at the MSB end of the argument.
61    fn clz(&self) -> Self;
62    // The ctz operation counts the number of 0 bits at the LSB end of the argument.
63    fn ctz(&self) -> Self;
64    // Counts the number of 1 bits.
65    fn cpop(&self) -> Self;
66    // Carry-less multiply (low-part)
67    fn clmul(&self, rhs: &Self) -> Self;
68    // Carry-less multiply (high-part)
69    fn clmulh(&self, rhs: &Self) -> Self;
70    // Carry-less multiply (reversed)
71    fn clmulr(&self, rhs: &Self) -> Self;
72    fn orcb(&self) -> Self;
73    fn rev8(&self) -> Self;
74
75    fn signed_shl(&self, rhs: &Self) -> Self;
76    fn signed_shr(&self, rhs: &Self) -> Self;
77
78    // Rotate left/right.
79    fn rol(&self, rhs: &Self) -> Self;
80    fn ror(&self, rhs: &Self) -> Self;
81
82    // Zero extend from start_bit to the highest bit, note
83    // start_bit is offset by 0
84    fn zero_extend(&self, start_bit: &Self) -> Self;
85    // Sign extend from start_bit to the highest bit leveraging
86    // bit in (start_bit - 1), note start_bit is offset by 0
87    fn sign_extend(&self, start_bit: &Self) -> Self;
88
89    // NOTE: one alternative solution is to encode those methods using
90    // From/Into traits, however we opt for manual conversion here for 2
91    // reasons:
92    // 1. This leads to more clarity in code, so when we see `to_u8`, we know
93    // immediately that the method is called on a register type, while `as u8`
94    // tells us it's a different type.
95    // 2. Adding those additional methods allows us to implement this trait on
96    // plain u32/u64 types.
97    fn to_i8(&self) -> i8;
98    fn to_i16(&self) -> i16;
99    fn to_i32(&self) -> i32;
100    fn to_i64(&self) -> i64;
101    fn to_u8(&self) -> u8;
102    fn to_u16(&self) -> u16;
103    fn to_u32(&self) -> u32;
104    fn to_u64(&self) -> u64;
105
106    fn from_i8(v: i8) -> Self;
107    fn from_i16(v: i16) -> Self;
108    fn from_i32(v: i32) -> Self;
109    fn from_i64(v: i64) -> Self;
110    fn from_u8(v: u8) -> Self;
111    fn from_u16(v: u16) -> Self;
112    fn from_u32(v: u32) -> Self;
113    fn from_u64(v: u64) -> Self;
114
115    fn ne(&self, rhs: &Self) -> Self {
116        self.eq(rhs).logical_not()
117    }
118
119    fn ge(&self, other: &Self) -> Self {
120        self.lt(other).logical_not()
121    }
122
123    fn ge_s(&self, other: &Self) -> Self {
124        self.lt_s(other).logical_not()
125    }
126}
127
128impl Register for u32 {
129    const BITS: u8 = 32;
130    const SHIFT_MASK: u8 = 0x1F;
131
132    fn zero() -> u32 {
133        0
134    }
135
136    fn one() -> u32 {
137        1
138    }
139
140    fn min_value() -> u32 {
141        u32::MIN
142    }
143
144    fn max_value() -> u32 {
145        u32::MAX
146    }
147
148    fn eq(&self, other: &u32) -> u32 {
149        (self == other).into()
150    }
151
152    fn lt(&self, other: &u32) -> u32 {
153        (self < other).into()
154    }
155
156    fn lt_s(&self, other: &u32) -> u32 {
157        ((*self as i32) < (*other as i32)).into()
158    }
159
160    fn logical_not(&self) -> u32 {
161        (*self != Self::one()).into()
162    }
163
164    fn cond(&self, true_value: &u32, false_value: &u32) -> u32 {
165        if *self == Self::one() {
166            *true_value
167        } else {
168            *false_value
169        }
170    }
171
172    fn overflowing_add(&self, rhs: &u32) -> u32 {
173        (*self).overflowing_add(*rhs).0
174    }
175
176    fn overflowing_sub(&self, rhs: &u32) -> u32 {
177        (*self).overflowing_sub(*rhs).0
178    }
179
180    fn overflowing_mul(&self, rhs: &u32) -> u32 {
181        (*self).overflowing_mul(*rhs).0
182    }
183
184    fn overflowing_div(&self, rhs: &u32) -> u32 {
185        if *rhs == 0 {
186            Self::MAX
187        } else {
188            (*self).overflowing_div(*rhs).0
189        }
190    }
191
192    fn overflowing_rem(&self, rhs: &u32) -> u32 {
193        if *rhs == 0 {
194            *self
195        } else {
196            (*self).overflowing_rem(*rhs).0
197        }
198    }
199
200    fn overflowing_div_signed(&self, rhs: &u32) -> u32 {
201        if *rhs == 0 {
202            (-1i32) as u32
203        } else {
204            let (v, o) = (*self as i32).overflowing_div(*rhs as i32);
205            if o {
206                // -2**(L-1) implemented using (-1) << (L - 1)
207                ((-1i32) as u32) << (<Self as Register>::BITS - 1)
208            } else {
209                v as u32
210            }
211        }
212    }
213
214    fn overflowing_rem_signed(&self, rhs: &u32) -> u32 {
215        if *rhs == 0 {
216            *self
217        } else {
218            let (v, o) = (*self as i32).overflowing_rem(*rhs as i32);
219            if o {
220                0
221            } else {
222                v as u32
223            }
224        }
225    }
226
227    fn overflowing_mul_high_signed(&self, rhs: &u32) -> u32 {
228        let a = i64::from(*self as i32);
229        let b = i64::from(*rhs as i32);
230        let (value, _) = a.overflowing_mul(b);
231        (value >> 32) as u32
232    }
233
234    fn overflowing_mul_high_unsigned(&self, rhs: &u32) -> u32 {
235        let a = u64::from(*self);
236        let b = u64::from(*rhs);
237        let (value, _) = a.overflowing_mul(b);
238        (value >> 32) as u32
239    }
240
241    fn overflowing_mul_high_signed_unsigned(&self, rhs: &u32) -> u32 {
242        let a = i64::from(*self as i32);
243        let b = i64::from(*rhs);
244        let (value, _) = a.overflowing_mul(b);
245        (value >> 32) as u32
246    }
247
248    fn signed_shl(&self, rhs: &u32) -> u32 {
249        (*self as i32).shl(*rhs) as u32
250    }
251
252    fn signed_shr(&self, rhs: &u32) -> u32 {
253        (*self as i32).shr(*rhs) as u32
254    }
255
256    fn zero_extend(&self, start_bit: &u32) -> u32 {
257        let start_bit = min(*start_bit, 32);
258        debug_assert!(start_bit > 0);
259        (*self << (32 - start_bit)) >> (32 - start_bit)
260    }
261
262    fn sign_extend(&self, start_bit: &u32) -> u32 {
263        let start_bit = min(*start_bit, 32);
264        debug_assert!(start_bit > 0);
265        (((*self << (32 - start_bit)) as i32) >> (32 - start_bit)) as u32
266    }
267
268    fn clz(&self) -> u32 {
269        self.leading_zeros()
270    }
271
272    fn ctz(&self) -> u32 {
273        self.trailing_zeros()
274    }
275
276    fn cpop(&self) -> u32 {
277        self.count_ones()
278    }
279
280    fn clmul(&self, rhs: &u32) -> u32 {
281        let mut x: u32 = 0;
282        for i in 0..32 {
283            if ((rhs >> i) & 1) != 0 {
284                x ^= self << i;
285            }
286        }
287        x
288    }
289
290    fn clmulh(&self, rhs: &u32) -> u32 {
291        let mut x: u32 = 0;
292        for i in 1..32 {
293            if ((rhs >> i) & 1) != 0 {
294                x ^= self >> (32 - i);
295            }
296        }
297        x
298    }
299
300    fn clmulr(&self, rhs: &u32) -> u32 {
301        let mut x: u32 = 0;
302        for i in 0..32 {
303            if ((rhs >> i) & 1) != 0 {
304                x ^= self >> (31 - i);
305            }
306        }
307        x
308    }
309
310    fn orcb(&self) -> u32 {
311        let mut rr = 0;
312        if self & 0x000000ff != 0 {
313            rr |= 0x000000ff
314        }
315        if self & 0x0000ff00 != 0 {
316            rr |= 0x0000ff00
317        }
318        if self & 0x00ff0000 != 0 {
319            rr |= 0x00ff0000
320        }
321        if self & 0xff000000 != 0 {
322            rr |= 0xff000000
323        }
324        rr
325    }
326
327    fn rev8(&self) -> u32 {
328        let mut r = 0;
329        let a = self & 0x000000ff;
330        r |= a << 24;
331        let a = self & 0x0000ff00;
332        r |= a << 8;
333        let a = self & 0x00ff0000;
334        r |= a >> 8;
335        let a = self & 0xff000000;
336        r |= a >> 24;
337        r
338    }
339
340    fn rol(&self, rhs: &u32) -> u32 {
341        (*self as u32).rotate_left(*rhs) as u32
342    }
343
344    fn ror(&self, rhs: &u32) -> u32 {
345        (*self as u32).rotate_right(*rhs) as u32
346    }
347
348    fn to_i8(&self) -> i8 {
349        *self as i8
350    }
351
352    fn to_i16(&self) -> i16 {
353        *self as i16
354    }
355
356    fn to_i32(&self) -> i32 {
357        *self as i32
358    }
359
360    fn to_i64(&self) -> i64 {
361        i64::from(*self as i32)
362    }
363
364    fn to_u8(&self) -> u8 {
365        *self as u8
366    }
367
368    fn to_u16(&self) -> u16 {
369        *self as u16
370    }
371
372    fn to_u32(&self) -> u32 {
373        *self
374    }
375
376    fn to_u64(&self) -> u64 {
377        u64::from(*self)
378    }
379
380    fn from_i8(v: i8) -> u32 {
381        i32::from(v) as u32
382    }
383
384    fn from_i16(v: i16) -> u32 {
385        i32::from(v) as u32
386    }
387
388    fn from_i32(v: i32) -> u32 {
389        v as u32
390    }
391
392    fn from_i64(v: i64) -> u32 {
393        (v as i32) as u32
394    }
395
396    fn from_u8(v: u8) -> u32 {
397        u32::from(v)
398    }
399
400    fn from_u16(v: u16) -> u32 {
401        u32::from(v)
402    }
403
404    fn from_u32(v: u32) -> u32 {
405        v
406    }
407
408    fn from_u64(v: u64) -> u32 {
409        v as u32
410    }
411}
412
413impl Register for u64 {
414    const BITS: u8 = 64;
415    const SHIFT_MASK: u8 = 0x3F;
416
417    fn zero() -> u64 {
418        0
419    }
420
421    fn one() -> u64 {
422        1
423    }
424
425    fn min_value() -> u64 {
426        u64::MIN
427    }
428
429    fn max_value() -> u64 {
430        u64::MAX
431    }
432
433    fn eq(&self, other: &u64) -> u64 {
434        (self == other).into()
435    }
436
437    fn lt(&self, other: &u64) -> u64 {
438        (self < other).into()
439    }
440
441    fn lt_s(&self, other: &u64) -> u64 {
442        ((*self as i64) < (*other as i64)).into()
443    }
444
445    fn logical_not(&self) -> u64 {
446        (*self != Self::one()).into()
447    }
448
449    fn cond(&self, true_value: &u64, false_value: &u64) -> u64 {
450        if *self == Self::one() {
451            *true_value
452        } else {
453            *false_value
454        }
455    }
456
457    fn overflowing_add(&self, rhs: &u64) -> u64 {
458        (*self).overflowing_add(*rhs).0
459    }
460
461    fn overflowing_sub(&self, rhs: &u64) -> u64 {
462        (*self).overflowing_sub(*rhs).0
463    }
464
465    fn overflowing_mul(&self, rhs: &u64) -> u64 {
466        (*self).overflowing_mul(*rhs).0
467    }
468
469    fn overflowing_div(&self, rhs: &u64) -> u64 {
470        if *rhs == 0 {
471            Self::MAX
472        } else {
473            (*self).overflowing_div(*rhs).0
474        }
475    }
476
477    fn overflowing_rem(&self, rhs: &u64) -> u64 {
478        if *rhs == 0 {
479            *self
480        } else {
481            (*self).overflowing_rem(*rhs).0
482        }
483    }
484
485    fn overflowing_div_signed(&self, rhs: &u64) -> u64 {
486        if *rhs == 0 {
487            (-1i64) as u64
488        } else {
489            let (v, o) = (*self as i64).overflowing_div(*rhs as i64);
490            if o {
491                // -2**(L-1) implemented using (-1) << (L - 1)
492                ((-1i64) as u64) << (<Self as Register>::BITS - 1)
493            } else {
494                v as u64
495            }
496        }
497    }
498
499    fn overflowing_rem_signed(&self, rhs: &u64) -> u64 {
500        if *rhs == 0 {
501            *self
502        } else {
503            let (v, o) = (*self as i64).overflowing_rem(*rhs as i64);
504            if o {
505                0
506            } else {
507                v as u64
508            }
509        }
510    }
511
512    fn overflowing_mul_high_signed(&self, rhs: &u64) -> u64 {
513        let a = i128::from(*self as i64);
514        let b = i128::from(*rhs as i64);
515        let (value, _) = a.overflowing_mul(b);
516        (value >> 64) as u64
517    }
518
519    fn overflowing_mul_high_unsigned(&self, rhs: &u64) -> u64 {
520        let a = u128::from(*self);
521        let b = u128::from(*rhs);
522        let (value, _) = a.overflowing_mul(b);
523        (value >> 64) as u64
524    }
525
526    fn overflowing_mul_high_signed_unsigned(&self, rhs: &u64) -> u64 {
527        let a = i128::from(*self as i64);
528        let b = i128::from(*rhs);
529        let (value, _) = a.overflowing_mul(b);
530        (value >> 64) as u64
531    }
532
533    fn signed_shl(&self, rhs: &u64) -> u64 {
534        (*self as i64).shl(*rhs) as u64
535    }
536
537    fn signed_shr(&self, rhs: &u64) -> u64 {
538        (*self as i64).shr(*rhs) as u64
539    }
540
541    fn zero_extend(&self, start_bit: &u64) -> u64 {
542        let start_bit = min(*start_bit, 64);
543        debug_assert!(start_bit > 0);
544        (*self << (64 - start_bit)) >> (64 - start_bit)
545    }
546
547    fn sign_extend(&self, start_bit: &u64) -> u64 {
548        let start_bit = min(*start_bit, 64);
549        debug_assert!(start_bit > 0);
550        (((*self << (64 - start_bit)) as i64) >> (64 - start_bit)) as u64
551    }
552
553    fn clz(&self) -> u64 {
554        self.leading_zeros() as u64
555    }
556
557    fn ctz(&self) -> u64 {
558        self.trailing_zeros() as u64
559    }
560
561    fn cpop(&self) -> u64 {
562        self.count_ones() as u64
563    }
564
565    fn clmul(&self, rhs: &u64) -> u64 {
566        let mut x: u64 = 0;
567        for i in 0..64 {
568            if ((rhs >> i) & 1) != 0 {
569                x ^= self << i;
570            }
571        }
572        x
573    }
574
575    fn clmulh(&self, rhs: &u64) -> u64 {
576        let mut x: u64 = 0;
577        for i in 1..64 {
578            if ((rhs >> i) & 1) != 0 {
579                x ^= self >> (64 - i);
580            }
581        }
582        x
583    }
584
585    fn clmulr(&self, rhs: &u64) -> u64 {
586        let mut x: u64 = 0;
587        for i in 0..64 {
588            if ((rhs >> i) & 1) != 0 {
589                x ^= self >> (63 - i);
590            }
591        }
592        x
593    }
594
595    fn orcb(&self) -> u64 {
596        let mut rr = 0;
597        if self & 0x00000000000000ff != 0 {
598            rr |= 0x00000000000000ff
599        }
600        if self & 0x000000000000ff00 != 0 {
601            rr |= 0x000000000000ff00
602        }
603        if self & 0x0000000000ff0000 != 0 {
604            rr |= 0x0000000000ff0000
605        }
606        if self & 0x00000000ff000000 != 0 {
607            rr |= 0x00000000ff000000
608        }
609        if self & 0x000000ff00000000 != 0 {
610            rr |= 0x000000ff00000000
611        }
612        if self & 0x0000ff0000000000 != 0 {
613            rr |= 0x0000ff0000000000
614        }
615        if self & 0x00ff000000000000 != 0 {
616            rr |= 0x00ff000000000000
617        }
618        if self & 0xff00000000000000 != 0 {
619            rr |= 0xff00000000000000
620        }
621        rr
622    }
623
624    fn rev8(&self) -> u64 {
625        let mut r = 0;
626        let a = self & 0x00000000000000ff;
627        r |= a << 56;
628        let a = self & 0x000000000000ff00;
629        r |= a << 40;
630        let a = self & 0x0000000000ff0000;
631        r |= a << 24;
632        let a = self & 0x00000000ff000000;
633        r |= a << 8;
634        let a = self & 0x000000ff00000000;
635        r |= a >> 8;
636        let a = self & 0x0000ff0000000000;
637        r |= a >> 24;
638        let a = self & 0x00ff000000000000;
639        r |= a >> 40;
640        let a = self & 0xff00000000000000;
641        r |= a >> 56;
642        r
643    }
644
645    fn rol(&self, rhs: &u64) -> u64 {
646        (*self as u64).rotate_left((*rhs) as u32) as u64
647    }
648
649    fn ror(&self, rhs: &u64) -> u64 {
650        (*self as u64).rotate_right((*rhs) as u32) as u64
651    }
652
653    fn to_i8(&self) -> i8 {
654        *self as i8
655    }
656
657    fn to_i16(&self) -> i16 {
658        *self as i16
659    }
660
661    fn to_i32(&self) -> i32 {
662        *self as i32
663    }
664
665    fn to_i64(&self) -> i64 {
666        *self as i64
667    }
668
669    fn to_u8(&self) -> u8 {
670        *self as u8
671    }
672
673    fn to_u16(&self) -> u16 {
674        *self as u16
675    }
676
677    fn to_u32(&self) -> u32 {
678        *self as u32
679    }
680
681    fn to_u64(&self) -> u64 {
682        *self
683    }
684
685    fn from_i8(v: i8) -> u64 {
686        i64::from(v) as u64
687    }
688
689    fn from_i16(v: i16) -> u64 {
690        i64::from(v) as u64
691    }
692
693    fn from_i32(v: i32) -> u64 {
694        i64::from(v) as u64
695    }
696
697    fn from_i64(v: i64) -> u64 {
698        v as u64
699    }
700
701    fn from_u8(v: u8) -> u64 {
702        u64::from(v)
703    }
704
705    fn from_u16(v: u16) -> u64 {
706        u64::from(v)
707    }
708
709    fn from_u32(v: u32) -> u64 {
710        u64::from(v)
711    }
712
713    fn from_u64(v: u64) -> u64 {
714        v
715    }
716}