0001
0002
0003
0004
0005
0006
0007 #ifndef _LINUX_BITFIELD_H
0008 #define _LINUX_BITFIELD_H
0009
0010 #include <linux/build_bug.h>
0011 #include <asm/byteorder.h>
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 #define __bf_shf(x) (__builtin_ffsll(x) - 1)
0046
0047 #define __scalar_type_to_unsigned_cases(type) \
0048 unsigned type: (unsigned type)0, \
0049 signed type: (unsigned type)0
0050
0051 #define __unsigned_scalar_typeof(x) typeof( \
0052 _Generic((x), \
0053 char: (unsigned char)0, \
0054 __scalar_type_to_unsigned_cases(char), \
0055 __scalar_type_to_unsigned_cases(short), \
0056 __scalar_type_to_unsigned_cases(int), \
0057 __scalar_type_to_unsigned_cases(long), \
0058 __scalar_type_to_unsigned_cases(long long), \
0059 default: (x)))
0060
0061 #define __bf_cast_unsigned(type, x) ((__unsigned_scalar_typeof(type))(x))
0062
0063 #define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx) \
0064 ({ \
0065 BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \
0066 _pfx "mask is not constant"); \
0067 BUILD_BUG_ON_MSG((_mask) == 0, _pfx "mask is zero"); \
0068 BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \
0069 ~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \
0070 _pfx "value too large for the field"); \
0071 BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) > \
0072 __bf_cast_unsigned(_reg, ~0ull), \
0073 _pfx "type of reg too small for mask"); \
0074 __BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \
0075 (1ULL << __bf_shf(_mask))); \
0076 })
0077
0078
0079
0080
0081
0082
0083
0084
0085 #define FIELD_MAX(_mask) \
0086 ({ \
0087 __BF_FIELD_CHECK(_mask, 0ULL, 0ULL, "FIELD_MAX: "); \
0088 (typeof(_mask))((_mask) >> __bf_shf(_mask)); \
0089 })
0090
0091
0092
0093
0094
0095
0096
0097
0098 #define FIELD_FIT(_mask, _val) \
0099 ({ \
0100 __BF_FIELD_CHECK(_mask, 0ULL, 0ULL, "FIELD_FIT: "); \
0101 !((((typeof(_mask))_val) << __bf_shf(_mask)) & ~(_mask)); \
0102 })
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 #define FIELD_PREP(_mask, _val) \
0113 ({ \
0114 __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: "); \
0115 ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \
0116 })
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126 #define FIELD_GET(_mask, _reg) \
0127 ({ \
0128 __BF_FIELD_CHECK(_mask, _reg, 0U, "FIELD_GET: "); \
0129 (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
0130 })
0131
0132 extern void __compiletime_error("value doesn't fit into mask")
0133 __field_overflow(void);
0134 extern void __compiletime_error("bad bitfield mask")
0135 __bad_mask(void);
0136 static __always_inline u64 field_multiplier(u64 field)
0137 {
0138 if ((field | (field - 1)) & ((field | (field - 1)) + 1))
0139 __bad_mask();
0140 return field & -field;
0141 }
0142 static __always_inline u64 field_mask(u64 field)
0143 {
0144 return field / field_multiplier(field);
0145 }
0146 #define field_max(field) ((typeof(field))field_mask(field))
0147 #define ____MAKE_OP(type,base,to,from) \
0148 static __always_inline __##type type##_encode_bits(base v, base field) \
0149 { \
0150 if (__builtin_constant_p(v) && (v & ~field_mask(field))) \
0151 __field_overflow(); \
0152 return to((v & field_mask(field)) * field_multiplier(field)); \
0153 } \
0154 static __always_inline __##type type##_replace_bits(__##type old, \
0155 base val, base field) \
0156 { \
0157 return (old & ~to(field)) | type##_encode_bits(val, field); \
0158 } \
0159 static __always_inline void type##p_replace_bits(__##type *p, \
0160 base val, base field) \
0161 { \
0162 *p = (*p & ~to(field)) | type##_encode_bits(val, field); \
0163 } \
0164 static __always_inline base type##_get_bits(__##type v, base field) \
0165 { \
0166 return (from(v) & field)/field_multiplier(field); \
0167 }
0168 #define __MAKE_OP(size) \
0169 ____MAKE_OP(le##size,u##size,cpu_to_le##size,le##size##_to_cpu) \
0170 ____MAKE_OP(be##size,u##size,cpu_to_be##size,be##size##_to_cpu) \
0171 ____MAKE_OP(u##size,u##size,,)
0172 ____MAKE_OP(u8,u8,,)
0173 __MAKE_OP(16)
0174 __MAKE_OP(32)
0175 __MAKE_OP(64)
0176 #undef __MAKE_OP
0177 #undef ____MAKE_OP
0178
0179 #endif