// SPDX-License-Identifier: GPL-2.012//! Bit manipulation macros.3//!4//! C header: [`include/linux/bits.h`](srctree/include/linux/bits.h)56use crate::prelude::*;7use core::ops::RangeInclusive;8use macros::paste;910macro_rules! impl_bit_fn {11(12$ty:ty13) => {14paste! {15/// Computes `1 << n` if `n` is in bounds, i.e.: if `n` is smaller than16/// the maximum number of bits supported by the type.17///18/// Returns [`None`] otherwise.19#[inline]20pub fn [<checked_bit_ $ty>](n: u32) -> Option<$ty> {21(1 as $ty).checked_shl(n)22}2324/// Computes `1 << n` by performing a compile-time assertion that `n` is25/// in bounds.26///27/// This version is the default and should be used if `n` is known at28/// compile time.29#[inline]30pub const fn [<bit_ $ty>](n: u32) -> $ty {31build_assert!(n < <$ty>::BITS);32(1 as $ty) << n33}34}35};36}3738impl_bit_fn!(u64);39impl_bit_fn!(u32);40impl_bit_fn!(u16);41impl_bit_fn!(u8);4243macro_rules! impl_genmask_fn {44(45$ty:ty,46$(#[$genmask_checked_ex:meta])*,47$(#[$genmask_ex:meta])*48) => {49paste! {50/// Creates a contiguous bitmask for the given range by validating51/// the range at runtime.52///53/// Returns [`None`] if the range is invalid, i.e.: if the start is54/// greater than the end or if the range is outside of the55/// representable range for the type.56$(#[$genmask_checked_ex])*57#[inline]58pub fn [<genmask_checked_ $ty>](range: RangeInclusive<u32>) -> Option<$ty> {59let start = *range.start();60let end = *range.end();6162if start > end {63return None;64}6566let high = [<checked_bit_ $ty>](end)?;67let low = [<checked_bit_ $ty>](start)?;68Some((high | (high - 1)) & !(low - 1))69}7071/// Creates a compile-time contiguous bitmask for the given range by72/// performing a compile-time assertion that the range is valid.73///74/// This version is the default and should be used if the range is known75/// at compile time.76$(#[$genmask_ex])*77#[inline]78pub const fn [<genmask_ $ty>](range: RangeInclusive<u32>) -> $ty {79let start = *range.start();80let end = *range.end();8182build_assert!(start <= end);8384let high = [<bit_ $ty>](end);85let low = [<bit_ $ty>](start);86(high | (high - 1)) & !(low - 1)87}88}89};90}9192impl_genmask_fn!(93u64,94/// # Examples95///96/// ```97/// # #![expect(clippy::reversed_empty_ranges)]98/// # use kernel::bits::genmask_checked_u64;99/// assert_eq!(genmask_checked_u64(0..=0), Some(0b1));100/// assert_eq!(genmask_checked_u64(0..=63), Some(u64::MAX));101/// assert_eq!(genmask_checked_u64(21..=39), Some(0x0000_00ff_ffe0_0000));102///103/// // `80` is out of the supported bit range.104/// assert_eq!(genmask_checked_u64(21..=80), None);105///106/// // Invalid range where the start is bigger than the end.107/// assert_eq!(genmask_checked_u64(15..=8), None);108/// ```109,110/// # Examples111///112/// ```113/// # use kernel::bits::genmask_u64;114/// assert_eq!(genmask_u64(21..=39), 0x0000_00ff_ffe0_0000);115/// assert_eq!(genmask_u64(0..=0), 0b1);116/// assert_eq!(genmask_u64(0..=63), u64::MAX);117/// ```118);119120impl_genmask_fn!(121u32,122/// # Examples123///124/// ```125/// # #![expect(clippy::reversed_empty_ranges)]126/// # use kernel::bits::genmask_checked_u32;127/// assert_eq!(genmask_checked_u32(0..=0), Some(0b1));128/// assert_eq!(genmask_checked_u32(0..=31), Some(u32::MAX));129/// assert_eq!(genmask_checked_u32(21..=31), Some(0xffe0_0000));130///131/// // `40` is out of the supported bit range.132/// assert_eq!(genmask_checked_u32(21..=40), None);133///134/// // Invalid range where the start is bigger than the end.135/// assert_eq!(genmask_checked_u32(15..=8), None);136/// ```137,138/// # Examples139///140/// ```141/// # use kernel::bits::genmask_u32;142/// assert_eq!(genmask_u32(21..=31), 0xffe0_0000);143/// assert_eq!(genmask_u32(0..=0), 0b1);144/// assert_eq!(genmask_u32(0..=31), u32::MAX);145/// ```146);147148impl_genmask_fn!(149u16,150/// # Examples151///152/// ```153/// # #![expect(clippy::reversed_empty_ranges)]154/// # use kernel::bits::genmask_checked_u16;155/// assert_eq!(genmask_checked_u16(0..=0), Some(0b1));156/// assert_eq!(genmask_checked_u16(0..=15), Some(u16::MAX));157/// assert_eq!(genmask_checked_u16(6..=15), Some(0xffc0));158///159/// // `20` is out of the supported bit range.160/// assert_eq!(genmask_checked_u16(6..=20), None);161///162/// // Invalid range where the start is bigger than the end.163/// assert_eq!(genmask_checked_u16(10..=5), None);164/// ```165,166/// # Examples167///168/// ```169/// # use kernel::bits::genmask_u16;170/// assert_eq!(genmask_u16(6..=15), 0xffc0);171/// assert_eq!(genmask_u16(0..=0), 0b1);172/// assert_eq!(genmask_u16(0..=15), u16::MAX);173/// ```174);175176impl_genmask_fn!(177u8,178/// # Examples179///180/// ```181/// # #![expect(clippy::reversed_empty_ranges)]182/// # use kernel::bits::genmask_checked_u8;183/// assert_eq!(genmask_checked_u8(0..=0), Some(0b1));184/// assert_eq!(genmask_checked_u8(0..=7), Some(u8::MAX));185/// assert_eq!(genmask_checked_u8(6..=7), Some(0xc0));186///187/// // `10` is out of the supported bit range.188/// assert_eq!(genmask_checked_u8(6..=10), None);189///190/// // Invalid range where the start is bigger than the end.191/// assert_eq!(genmask_checked_u8(5..=2), None);192/// ```193,194/// # Examples195///196/// ```197/// # use kernel::bits::genmask_u8;198/// assert_eq!(genmask_u8(6..=7), 0xc0);199/// assert_eq!(genmask_u8(0..=0), 0b1);200/// assert_eq!(genmask_u8(0..=7), u8::MAX);201/// ```202);203204205