xref: /qemu/rust/qemu-api/src/bitops.rs (revision 98721058d6d50ef218e0c26e4f67c8ef96965859)
1 // Copyright (C) 2024 Intel Corporation.
2 // Author(s): Zhao Liu <zhao1.liu@intel.com>
3 // SPDX-License-Identifier: GPL-2.0-or-later
4 
5 //! This module provides bit operation extensions to integer types.
6 //! It is usually included via the `qemu_api` prelude.
7 
8 use std::ops::{
9     Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
10     Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign,
11 };
12 
13 /// Trait for extensions to integer types
14 pub trait IntegerExt:
15     Add<Self, Output = Self> + AddAssign<Self> +
16     BitAnd<Self, Output = Self> + BitAndAssign<Self> +
17     BitOr<Self, Output = Self> + BitOrAssign<Self> +
18     BitXor<Self, Output = Self> + BitXorAssign<Self> +
19     Copy +
20     Div<Self, Output = Self> + DivAssign<Self> +
21     Eq +
22     Mul<Self, Output = Self> + MulAssign<Self> +
23     Not<Output = Self> + Ord + PartialOrd +
24     Rem<Self, Output = Self> + RemAssign<Self> +
25     Shl<Self, Output = Self> + ShlAssign<Self> +
26     Shl<u32, Output = Self> + ShlAssign<u32> + // add more as needed
27     Shr<Self, Output = Self> + ShrAssign<Self> +
28     Shr<u32, Output = Self> + ShrAssign<u32> // add more as needed
29 {
30     const BITS: u32;
31     const MAX: Self;
32     const MIN: Self;
33     const ONE: Self;
34     const ZERO: Self;
35 
36     #[inline]
37     #[must_use]
bit(start: u32) -> Self38     fn bit(start: u32) -> Self
39     {
40         debug_assert!(start < Self::BITS);
41 
42         Self::ONE << start
43     }
44 
45     #[inline]
46     #[must_use]
mask(start: u32, length: u32) -> Self47     fn mask(start: u32, length: u32) -> Self
48     {
49         /* FIXME: Implement a more elegant check with error handling support? */
50         debug_assert!(start < Self::BITS && length > 0 && length <= Self::BITS - start);
51 
52         (Self::MAX >> (Self::BITS - length)) << start
53     }
54 
55     #[inline]
56     #[must_use]
deposit<U: IntegerExt>(self, start: u32, length: u32, fieldval: U) -> Self where Self: From<U>57     fn deposit<U: IntegerExt>(self, start: u32, length: u32,
58                           fieldval: U) -> Self
59         where Self: From<U>
60     {
61         debug_assert!(length <= U::BITS);
62 
63         let mask = Self::mask(start, length);
64         (self & !mask) | ((Self::from(fieldval) << start) & mask)
65     }
66 
67     #[inline]
68     #[must_use]
extract(self, start: u32, length: u32) -> Self69     fn extract(self, start: u32, length: u32) -> Self
70     {
71         let mask = Self::mask(start, length);
72         (self & mask) >> start
73     }
74 }
75 
76 macro_rules! impl_num_ext {
77     ($type:ty) => {
78         impl IntegerExt for $type {
79             const BITS: u32 = <$type>::BITS;
80             const MAX: Self = <$type>::MAX;
81             const MIN: Self = <$type>::MIN;
82             const ONE: Self = 1;
83             const ZERO: Self = 0;
84         }
85     };
86 }
87 
88 impl_num_ext!(u8);
89 impl_num_ext!(u16);
90 impl_num_ext!(u32);
91 impl_num_ext!(u64);
92 
93 #[cfg(test)]
94 mod tests {
95     use super::*;
96 
97     #[test]
test_deposit()98     fn test_deposit() {
99         assert_eq!(15u32.deposit(8, 8, 1u32), 256 + 15);
100         assert_eq!(15u32.deposit(8, 1, 255u8), 256 + 15);
101     }
102 
103     #[test]
test_extract()104     fn test_extract() {
105         assert_eq!(15u32.extract(2, 4), 3);
106     }
107 
108     #[test]
test_bit()109     fn test_bit() {
110         assert_eq!(u8::bit(7), 128);
111         assert_eq!(u32::bit(16), 0x10000);
112     }
113 
114     #[test]
test_mask()115     fn test_mask() {
116         assert_eq!(u8::mask(7, 1), 128);
117         assert_eq!(u32::mask(8, 8), 0xff00);
118     }
119 }
120