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