// 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// Always inline to optimize out error path of `build_assert`.30#[inline(always)]31pub const fn [<bit_ $ty>](n: u32) -> $ty {32build_assert!(n < <$ty>::BITS);33(1 as $ty) << n34}35}36};37}3839impl_bit_fn!(u64);40impl_bit_fn!(u32);41impl_bit_fn!(u16);42impl_bit_fn!(u8);4344macro_rules! impl_genmask_fn {45(46$ty:ty,47$(#[$genmask_checked_ex:meta])*,48$(#[$genmask_ex:meta])*49) => {50paste! {51/// Creates a contiguous bitmask for the given range by validating52/// the range at runtime.53///54/// Returns [`None`] if the range is invalid, i.e.: if the start is55/// greater than the end or if the range is outside of the56/// representable range for the type.57$(#[$genmask_checked_ex])*58#[inline]59pub fn [<genmask_checked_ $ty>](range: RangeInclusive<u32>) -> Option<$ty> {60let start = *range.start();61let end = *range.end();6263if start > end {64return None;65}6667let high = [<checked_bit_ $ty>](end)?;68let low = [<checked_bit_ $ty>](start)?;69Some((high | (high - 1)) & !(low - 1))70}7172/// Creates a compile-time contiguous bitmask for the given range by73/// 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 known76/// at compile time.77$(#[$genmask_ex])*78// Always inline to optimize out error path of `build_assert`.79#[inline(always)]80pub const fn [<genmask_ $ty>](range: RangeInclusive<u32>) -> $ty {81let start = *range.start();82let end = *range.end();8384build_assert!(start <= end);8586let high = [<bit_ $ty>](end);87let low = [<bit_ $ty>](start);88(high | (high - 1)) & !(low - 1)89}90}91};92}9394impl_genmask_fn!(95u64,96/// # Examples97///98/// ```99/// # #![expect(clippy::reversed_empty_ranges)]100/// # use kernel::bits::genmask_checked_u64;101/// assert_eq!(genmask_checked_u64(0..=0), Some(0b1));102/// assert_eq!(genmask_checked_u64(0..=63), Some(u64::MAX));103/// assert_eq!(genmask_checked_u64(21..=39), Some(0x0000_00ff_ffe0_0000));104///105/// // `80` is out of the supported bit range.106/// assert_eq!(genmask_checked_u64(21..=80), None);107///108/// // Invalid range where the start is bigger than the end.109/// assert_eq!(genmask_checked_u64(15..=8), None);110/// ```111,112/// # Examples113///114/// ```115/// # use kernel::bits::genmask_u64;116/// assert_eq!(genmask_u64(21..=39), 0x0000_00ff_ffe0_0000);117/// assert_eq!(genmask_u64(0..=0), 0b1);118/// assert_eq!(genmask_u64(0..=63), u64::MAX);119/// ```120);121122impl_genmask_fn!(123u32,124/// # Examples125///126/// ```127/// # #![expect(clippy::reversed_empty_ranges)]128/// # use kernel::bits::genmask_checked_u32;129/// assert_eq!(genmask_checked_u32(0..=0), Some(0b1));130/// assert_eq!(genmask_checked_u32(0..=31), Some(u32::MAX));131/// assert_eq!(genmask_checked_u32(21..=31), Some(0xffe0_0000));132///133/// // `40` is out of the supported bit range.134/// assert_eq!(genmask_checked_u32(21..=40), None);135///136/// // Invalid range where the start is bigger than the end.137/// assert_eq!(genmask_checked_u32(15..=8), None);138/// ```139,140/// # Examples141///142/// ```143/// # use kernel::bits::genmask_u32;144/// assert_eq!(genmask_u32(21..=31), 0xffe0_0000);145/// assert_eq!(genmask_u32(0..=0), 0b1);146/// assert_eq!(genmask_u32(0..=31), u32::MAX);147/// ```148);149150impl_genmask_fn!(151u16,152/// # Examples153///154/// ```155/// # #![expect(clippy::reversed_empty_ranges)]156/// # use kernel::bits::genmask_checked_u16;157/// assert_eq!(genmask_checked_u16(0..=0), Some(0b1));158/// assert_eq!(genmask_checked_u16(0..=15), Some(u16::MAX));159/// assert_eq!(genmask_checked_u16(6..=15), Some(0xffc0));160///161/// // `20` is out of the supported bit range.162/// assert_eq!(genmask_checked_u16(6..=20), None);163///164/// // Invalid range where the start is bigger than the end.165/// assert_eq!(genmask_checked_u16(10..=5), None);166/// ```167,168/// # Examples169///170/// ```171/// # use kernel::bits::genmask_u16;172/// assert_eq!(genmask_u16(6..=15), 0xffc0);173/// assert_eq!(genmask_u16(0..=0), 0b1);174/// assert_eq!(genmask_u16(0..=15), u16::MAX);175/// ```176);177178impl_genmask_fn!(179u8,180/// # Examples181///182/// ```183/// # #![expect(clippy::reversed_empty_ranges)]184/// # use kernel::bits::genmask_checked_u8;185/// assert_eq!(genmask_checked_u8(0..=0), Some(0b1));186/// assert_eq!(genmask_checked_u8(0..=7), Some(u8::MAX));187/// assert_eq!(genmask_checked_u8(6..=7), Some(0xc0));188///189/// // `10` is out of the supported bit range.190/// assert_eq!(genmask_checked_u8(6..=10), None);191///192/// // Invalid range where the start is bigger than the end.193/// assert_eq!(genmask_checked_u8(5..=2), None);194/// ```195,196/// # Examples197///198/// ```199/// # use kernel::bits::genmask_u8;200/// assert_eq!(genmask_u8(6..=7), 0xc0);201/// assert_eq!(genmask_u8(0..=0), 0b1);202/// assert_eq!(genmask_u8(0..=7), u8::MAX);203/// ```204);205206207