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