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