/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright ( C ) 2014 Felix Fietkau < nbd @ nbd . name >
* Copyright ( C ) 2004 - 2009 Ivo van Doorn < IvDoorn @ gmail . com >
*/
#ifndef _LINUX_BITFIELD_H
#define _LINUX_BITFIELD_H
#include <linux/build_bug.h>
#include <asm /byteorder.h>
/*
* Bitfield access macros
*
* FIELD_ { GET , PREP } macros take as first parameter shifted mask
* from which they extract the base mask and shift amount .
* Mask must be a compilation time constant .
*
* Example :
*
* # define REG_FIELD_A GENMASK ( 6 , 0 )
* # define REG_FIELD_B BIT ( 7 )
* # define REG_FIELD_C GENMASK ( 15 , 8 )
* # define REG_FIELD_D GENMASK ( 31 , 16 )
*
* Get :
* a = FIELD_GET ( REG_FIELD_A , reg ) ;
* b = FIELD_GET ( REG_FIELD_B , reg ) ;
*
* Set :
* reg = FIELD_PREP ( REG_FIELD_A , 1 ) |
* FIELD_PREP ( REG_FIELD_B , 0 ) |
* FIELD_PREP ( REG_FIELD_C , c ) |
* FIELD_PREP ( REG_FIELD_D , 0 x40 ) ;
*
* Modify :
* reg & = ~ REG_FIELD_C ;
* reg | = FIELD_PREP ( REG_FIELD_C , c ) ;
*/
#define __bf_shf(x) (__builtin_ffsll(x) - 1 )
#define __scalar_type_to_unsigned_cases(type) \
unsigned type: (unsigned type)0 , \
signed type: (unsigned type)0
#define __unsigned_scalar_typeof(x) typeof( \
_Generic((x), \
char : (unsigned char )0 , \
__scalar_type_to_unsigned_cases(char ), \
__scalar_type_to_unsigned_cases(short ), \
__scalar_type_to_unsigned_cases(int ), \
__scalar_type_to_unsigned_cases(long ), \
__scalar_type_to_unsigned_cases(long long ), \
default : (x)))
#define __bf_cast_unsigned(type, x) ((__unsigned_scalar_typeof(type))(x))
#define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx) \
({ \
BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \
_pfx "mask is not constant" ); \
BUILD_BUG_ON_MSG((_mask) == 0 , _pfx "mask is zero" ); \
BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \
~((_mask) >> __bf_shf(_mask)) & (_val) : 0 , \
_pfx "value too large for the field" ); \
BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) > \
__bf_cast_unsigned(_reg, ~0 ull), \
_pfx "type of reg too small for mask" ); \
__BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \
(1 ULL << __bf_shf(_mask))); \
})
/**
* FIELD_MAX ( ) - produce the maximum value representable by a field
* @ _ mask : shifted mask defining the field ' s length and position
*
* FIELD_MAX ( ) returns the maximum value that can be held in the field
* specified by @ _ mask .
*/
#define FIELD_MAX(_mask) \
({ \
__BF_FIELD_CHECK(_mask, 0 ULL, 0 ULL, "FIELD_MAX: " ); \
(typeof(_mask))((_mask) >> __bf_shf(_mask)); \
})
/**
* FIELD_FIT ( ) - check if value fits in the field
* @ _ mask : shifted mask defining the field ' s length and position
* @ _ val : value to test against the field
*
* Return : true if @ _ val can fit inside @ _ mask , false if @ _ val is too big .
*/
#define FIELD_FIT(_mask, _val) \
({ \
__BF_FIELD_CHECK(_mask, 0 ULL, 0 ULL, "FIELD_FIT: " ); \
!((((typeof(_mask))_val) << __bf_shf(_mask)) & ~(_mask)); \
})
/**
* FIELD_PREP ( ) - prepare a bitfield element
* @ _ mask : shifted mask defining the field ' s length and position
* @ _ val : value to put in the field
*
* FIELD_PREP ( ) masks and shifts up the value . The result should
* be combined with other fields of the bitfield using logical OR .
*/
#define FIELD_PREP(_mask, _val) \
({ \
__BF_FIELD_CHECK(_mask, 0 ULL, _val, "FIELD_PREP: " ); \
((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \
})
/**
* FIELD_GET ( ) - extract a bitfield element
* @ _ mask : shifted mask defining the field ' s length and position
* @ _ reg : value of entire bitfield
*
* FIELD_GET ( ) extracts the field specified by @ _ mask from the
* bitfield passed in as @ _ reg by masking and shifting it down .
*/
#define FIELD_GET(_mask, _reg) \
({ \
__BF_FIELD_CHECK(_mask, _reg, 0 U, "FIELD_GET: " ); \
(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
})
extern void __compiletime_error("value doesn't fit into mask" )
__field_overflow(void );
extern void __compiletime_error("bad bitfield mask" )
__bad_mask(void );
static __always_inline u64 field_multiplier(u64 field)
{
if ((field | (field - 1 )) & ((field | (field - 1 )) + 1 ))
__bad_mask();
return field & -field;
}
static __always_inline u64 field_mask(u64 field)
{
return field / field_multiplier(field);
}
#define field_max(field) ((typeof(field))field_mask(field))
#define ____MAKE_OP(type,base,to,from) \
static __always_inline __## type type## _encode_bits(base v, base field) \
{ \
if (__builtin_constant_p(v) && (v & ~field_mask(field))) \
__field_overflow(); \
return to((v & field_mask(field)) * field_multiplier(field)); \
} \
static __always_inline __## type type## _replace_bits(__## type old, \
base val, base field) \
{ \
return (old & ~to(field)) | type## _encode_bits(val, field); \
} \
static __always_inline void type## p_replace_bits(__## type *p, \
base val, base field) \
{ \
*p = (*p & ~to(field)) | type## _encode_bits(val, field); \
} \
static __always_inline base type## _get_bits(__## type v, base field) \
{ \
return (from(v) & field)/field_multiplier(field); \
}
#define __MAKE_OP(size) \
____MAKE_OP(le## size,u## size,cpu_to_le## size,le## size## _to_cpu) \
____MAKE_OP(be## size,u## size,cpu_to_be## size,be## size## _to_cpu) \
____MAKE_OP(u## size,u## size,,)
____MAKE_OP(u8,u8,,)
__MAKE_OP(16 )
__MAKE_OP(32 )
__MAKE_OP(64 )
#undef __MAKE_OP
#undef ____MAKE_OP
#endif
Messung V0.5 in Prozent C=97 H=95 G=95
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-09-28)
¤
*© Formatika GbR, Deutschland