@@ -16,6 +16,7 @@ _qemu_api_rs = static_library(
[
'src/lib.rs',
'src/bindings.rs',
+ 'src/bitops.rs',
'src/cell.rs',
'src/c_str.rs',
'src/definitions.rs',
new file mode 100644
@@ -0,0 +1,119 @@
+// Copyright (C) 2024 Intel Corporation.
+// Author(s): Zhao Liu <zhai1.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);
+ }
+}
@@ -12,6 +12,7 @@
#[rustfmt::skip]
pub mod prelude;
+pub mod bitops;
pub mod c_str;
pub mod cell;
pub mod definitions;
@@ -2,5 +2,7 @@
// Author(s): Paolo Bonzini <pbonzini@redhat.com>
// SPDX-License-Identifier: GPL-2.0-or-later
+pub use crate::bitops::IntegerExt;
+
pub use crate::cell::BqlCell;
pub use crate::cell::BqlRefCell;