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