|  | // Copyright (C) 2024 Intel Corporation. | 
|  | // Author(s): Zhao Liu <zhao1.liu@intel.com> | 
|  | // SPDX-License-Identifier: GPL-2.0-or-later | 
|  |  | 
|  | //! This module provides bit operation extensions to integer types. | 
|  | //! It is usually included via the `qemu_api` prelude. | 
|  |  | 
|  | use std::ops::{ | 
|  | Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, | 
|  | Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, | 
|  | }; | 
|  |  | 
|  | /// Trait for extensions to integer types | 
|  | pub trait IntegerExt: | 
|  | Add<Self, Output = Self> + AddAssign<Self> + | 
|  | BitAnd<Self, Output = Self> + BitAndAssign<Self> + | 
|  | BitOr<Self, Output = Self> + BitOrAssign<Self> + | 
|  | BitXor<Self, Output = Self> + BitXorAssign<Self> + | 
|  | Copy + | 
|  | Div<Self, Output = Self> + DivAssign<Self> + | 
|  | Eq + | 
|  | Mul<Self, Output = Self> + MulAssign<Self> + | 
|  | Not<Output = Self> + Ord + PartialOrd + | 
|  | Rem<Self, Output = Self> + RemAssign<Self> + | 
|  | Shl<Self, Output = Self> + ShlAssign<Self> + | 
|  | Shl<u32, Output = Self> + ShlAssign<u32> + // add more as needed | 
|  | Shr<Self, Output = Self> + ShrAssign<Self> + | 
|  | Shr<u32, Output = Self> + ShrAssign<u32> // add more as needed | 
|  | { | 
|  | const BITS: u32; | 
|  | const MAX: Self; | 
|  | const MIN: Self; | 
|  | const ONE: Self; | 
|  | const ZERO: Self; | 
|  |  | 
|  | #[inline] | 
|  | #[must_use] | 
|  | fn bit(start: u32) -> Self | 
|  | { | 
|  | debug_assert!(start < Self::BITS); | 
|  |  | 
|  | Self::ONE << start | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | #[must_use] | 
|  | fn mask(start: u32, length: u32) -> Self | 
|  | { | 
|  | /* FIXME: Implement a more elegant check with error handling support? */ | 
|  | debug_assert!(start < Self::BITS && length > 0 && length <= Self::BITS - start); | 
|  |  | 
|  | (Self::MAX >> (Self::BITS - length)) << start | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | #[must_use] | 
|  | fn deposit<U: IntegerExt>(self, start: u32, length: u32, | 
|  | fieldval: U) -> Self | 
|  | where Self: From<U> | 
|  | { | 
|  | debug_assert!(length <= U::BITS); | 
|  |  | 
|  | let mask = Self::mask(start, length); | 
|  | (self & !mask) | ((Self::from(fieldval) << start) & mask) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | #[must_use] | 
|  | fn extract(self, start: u32, length: u32) -> Self | 
|  | { | 
|  | let mask = Self::mask(start, length); | 
|  | (self & mask) >> start | 
|  | } | 
|  | } | 
|  |  | 
|  | macro_rules! impl_num_ext { | 
|  | ($type:ty) => { | 
|  | impl IntegerExt for $type { | 
|  | const BITS: u32 = <$type>::BITS; | 
|  | const MAX: Self = <$type>::MAX; | 
|  | const MIN: Self = <$type>::MIN; | 
|  | const ONE: Self = 1; | 
|  | const ZERO: Self = 0; | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | impl_num_ext!(u8); | 
|  | impl_num_ext!(u16); | 
|  | impl_num_ext!(u32); | 
|  | impl_num_ext!(u64); | 
|  |  | 
|  | #[cfg(test)] | 
|  | mod tests { | 
|  | use super::*; | 
|  |  | 
|  | #[test] | 
|  | fn test_deposit() { | 
|  | assert_eq!(15u32.deposit(8, 8, 1u32), 256 + 15); | 
|  | assert_eq!(15u32.deposit(8, 1, 255u8), 256 + 15); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_extract() { | 
|  | assert_eq!(15u32.extract(2, 4), 3); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_bit() { | 
|  | assert_eq!(u8::bit(7), 128); | 
|  | assert_eq!(u32::bit(16), 0x10000); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_mask() { | 
|  | assert_eq!(u8::mask(7, 1), 128); | 
|  | assert_eq!(u32::mask(8, 8), 0xff00); | 
|  | } | 
|  | } |