1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Bit manipulation macros. 4 //! 5 //! C header: [`include/linux/bits.h`](srctree/include/linux/bits.h) 6 7 use crate::prelude::*; 8 use core::ops::RangeInclusive; 9 use macros::paste; 10 11 macro_rules! impl_bit_fn { 12 ( 13 $ty:ty 14 ) => { 15 paste! { 16 /// Computes `1 << n` if `n` is in bounds, i.e.: if `n` is smaller than 17 /// the maximum number of bits supported by the type. 18 /// 19 /// Returns [`None`] otherwise. 20 #[inline] 21 pub fn [<checked_bit_ $ty>](n: u32) -> Option<$ty> { 22 (1 as $ty).checked_shl(n) 23 } 24 25 /// Computes `1 << n` by performing a compile-time assertion that `n` is 26 /// in bounds. 27 /// 28 /// This version is the default and should be used if `n` is known at 29 /// compile time. 30 // Always inline to optimize out error path of `build_assert`. 31 #[inline(always)] 32 pub const fn [<bit_ $ty>](n: u32) -> $ty { 33 build_assert!(n < <$ty>::BITS); 34 (1 as $ty) << n 35 } 36 } 37 }; 38 } 39 40 impl_bit_fn!(u64); 41 impl_bit_fn!(u32); 42 impl_bit_fn!(u16); 43 impl_bit_fn!(u8); 44 45 macro_rules! impl_genmask_fn { 46 ( 47 $ty:ty, 48 $(#[$genmask_checked_ex:meta])*, 49 $(#[$genmask_ex:meta])* 50 ) => { 51 paste! { 52 /// Creates a contiguous bitmask for the given range by validating 53 /// the range at runtime. 54 /// 55 /// Returns [`None`] if the range is invalid, i.e.: if the start is 56 /// greater than the end or if the range is outside of the 57 /// representable range for the type. 58 $(#[$genmask_checked_ex])* 59 #[inline] 60 pub fn [<genmask_checked_ $ty>](range: RangeInclusive<u32>) -> Option<$ty> { 61 let start = *range.start(); 62 let end = *range.end(); 63 64 if start > end { 65 return None; 66 } 67 68 let high = [<checked_bit_ $ty>](end)?; 69 let low = [<checked_bit_ $ty>](start)?; 70 Some((high | (high - 1)) & !(low - 1)) 71 } 72 73 /// Creates a compile-time contiguous bitmask for the given range by 74 /// performing a compile-time assertion that the range is valid. 75 /// 76 /// This version is the default and should be used if the range is known 77 /// at compile time. 78 $(#[$genmask_ex])* 79 // Always inline to optimize out error path of `build_assert`. 80 #[inline(always)] 81 pub const fn [<genmask_ $ty>](range: RangeInclusive<u32>) -> $ty { 82 let start = *range.start(); 83 let end = *range.end(); 84 85 build_assert!(start <= end); 86 87 let high = [<bit_ $ty>](end); 88 let low = [<bit_ $ty>](start); 89 (high | (high - 1)) & !(low - 1) 90 } 91 } 92 }; 93 } 94 95 impl_genmask_fn!( 96 u64, 97 /// # Examples 98 /// 99 /// ``` 100 /// # #![expect(clippy::reversed_empty_ranges)] 101 /// # use kernel::bits::genmask_checked_u64; 102 /// assert_eq!(genmask_checked_u64(0..=0), Some(0b1)); 103 /// assert_eq!(genmask_checked_u64(0..=63), Some(u64::MAX)); 104 /// assert_eq!(genmask_checked_u64(21..=39), Some(0x0000_00ff_ffe0_0000)); 105 /// 106 /// // `80` is out of the supported bit range. 107 /// assert_eq!(genmask_checked_u64(21..=80), None); 108 /// 109 /// // Invalid range where the start is bigger than the end. 110 /// assert_eq!(genmask_checked_u64(15..=8), None); 111 /// ``` 112 , 113 /// # Examples 114 /// 115 /// ``` 116 /// # use kernel::bits::genmask_u64; 117 /// assert_eq!(genmask_u64(21..=39), 0x0000_00ff_ffe0_0000); 118 /// assert_eq!(genmask_u64(0..=0), 0b1); 119 /// assert_eq!(genmask_u64(0..=63), u64::MAX); 120 /// ``` 121 ); 122 123 impl_genmask_fn!( 124 u32, 125 /// # Examples 126 /// 127 /// ``` 128 /// # #![expect(clippy::reversed_empty_ranges)] 129 /// # use kernel::bits::genmask_checked_u32; 130 /// assert_eq!(genmask_checked_u32(0..=0), Some(0b1)); 131 /// assert_eq!(genmask_checked_u32(0..=31), Some(u32::MAX)); 132 /// assert_eq!(genmask_checked_u32(21..=31), Some(0xffe0_0000)); 133 /// 134 /// // `40` is out of the supported bit range. 135 /// assert_eq!(genmask_checked_u32(21..=40), None); 136 /// 137 /// // Invalid range where the start is bigger than the end. 138 /// assert_eq!(genmask_checked_u32(15..=8), None); 139 /// ``` 140 , 141 /// # Examples 142 /// 143 /// ``` 144 /// # use kernel::bits::genmask_u32; 145 /// assert_eq!(genmask_u32(21..=31), 0xffe0_0000); 146 /// assert_eq!(genmask_u32(0..=0), 0b1); 147 /// assert_eq!(genmask_u32(0..=31), u32::MAX); 148 /// ``` 149 ); 150 151 impl_genmask_fn!( 152 u16, 153 /// # Examples 154 /// 155 /// ``` 156 /// # #![expect(clippy::reversed_empty_ranges)] 157 /// # use kernel::bits::genmask_checked_u16; 158 /// assert_eq!(genmask_checked_u16(0..=0), Some(0b1)); 159 /// assert_eq!(genmask_checked_u16(0..=15), Some(u16::MAX)); 160 /// assert_eq!(genmask_checked_u16(6..=15), Some(0xffc0)); 161 /// 162 /// // `20` is out of the supported bit range. 163 /// assert_eq!(genmask_checked_u16(6..=20), None); 164 /// 165 /// // Invalid range where the start is bigger than the end. 166 /// assert_eq!(genmask_checked_u16(10..=5), None); 167 /// ``` 168 , 169 /// # Examples 170 /// 171 /// ``` 172 /// # use kernel::bits::genmask_u16; 173 /// assert_eq!(genmask_u16(6..=15), 0xffc0); 174 /// assert_eq!(genmask_u16(0..=0), 0b1); 175 /// assert_eq!(genmask_u16(0..=15), u16::MAX); 176 /// ``` 177 ); 178 179 impl_genmask_fn!( 180 u8, 181 /// # Examples 182 /// 183 /// ``` 184 /// # #![expect(clippy::reversed_empty_ranges)] 185 /// # use kernel::bits::genmask_checked_u8; 186 /// assert_eq!(genmask_checked_u8(0..=0), Some(0b1)); 187 /// assert_eq!(genmask_checked_u8(0..=7), Some(u8::MAX)); 188 /// assert_eq!(genmask_checked_u8(6..=7), Some(0xc0)); 189 /// 190 /// // `10` is out of the supported bit range. 191 /// assert_eq!(genmask_checked_u8(6..=10), None); 192 /// 193 /// // Invalid range where the start is bigger than the end. 194 /// assert_eq!(genmask_checked_u8(5..=2), None); 195 /// ``` 196 , 197 /// # Examples 198 /// 199 /// ``` 200 /// # use kernel::bits::genmask_u8; 201 /// assert_eq!(genmask_u8(6..=7), 0xc0); 202 /// assert_eq!(genmask_u8(0..=0), 0b1); 203 /// assert_eq!(genmask_u8(0..=7), u8::MAX); 204 /// ``` 205 ); 206