.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2014 Felix Fietkau <nbd@nbd.name> |
---|
3 | 4 | * Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify |
---|
6 | | - * it under the terms of the GNU General Public License version 2 |
---|
7 | | - * as published by the Free Software Foundation |
---|
8 | | - * |
---|
9 | | - * This program is distributed in the hope that it will be useful, |
---|
10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
12 | | - * GNU General Public License for more details. |
---|
13 | 5 | */ |
---|
14 | 6 | |
---|
15 | 7 | #ifndef _LINUX_BITFIELD_H |
---|
.. | .. |
---|
49 | 41 | |
---|
50 | 42 | #define __bf_shf(x) (__builtin_ffsll(x) - 1) |
---|
51 | 43 | |
---|
| 44 | +#define __scalar_type_to_unsigned_cases(type) \ |
---|
| 45 | + unsigned type: (unsigned type)0, \ |
---|
| 46 | + signed type: (unsigned type)0 |
---|
| 47 | + |
---|
| 48 | +#define __unsigned_scalar_typeof(x) typeof( \ |
---|
| 49 | + _Generic((x), \ |
---|
| 50 | + char: (unsigned char)0, \ |
---|
| 51 | + __scalar_type_to_unsigned_cases(char), \ |
---|
| 52 | + __scalar_type_to_unsigned_cases(short), \ |
---|
| 53 | + __scalar_type_to_unsigned_cases(int), \ |
---|
| 54 | + __scalar_type_to_unsigned_cases(long), \ |
---|
| 55 | + __scalar_type_to_unsigned_cases(long long), \ |
---|
| 56 | + default: (x))) |
---|
| 57 | + |
---|
| 58 | +#define __bf_cast_unsigned(type, x) ((__unsigned_scalar_typeof(type))(x)) |
---|
| 59 | + |
---|
52 | 60 | #define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx) \ |
---|
53 | 61 | ({ \ |
---|
54 | 62 | BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \ |
---|
.. | .. |
---|
57 | 65 | BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \ |
---|
58 | 66 | ~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \ |
---|
59 | 67 | _pfx "value too large for the field"); \ |
---|
60 | | - BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull, \ |
---|
| 68 | + BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) > \ |
---|
| 69 | + __bf_cast_unsigned(_reg, ~0ull), \ |
---|
61 | 70 | _pfx "type of reg too small for mask"); \ |
---|
62 | 71 | __BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \ |
---|
63 | 72 | (1ULL << __bf_shf(_mask))); \ |
---|
| 73 | + }) |
---|
| 74 | + |
---|
| 75 | +/** |
---|
| 76 | + * FIELD_MAX() - produce the maximum value representable by a field |
---|
| 77 | + * @_mask: shifted mask defining the field's length and position |
---|
| 78 | + * |
---|
| 79 | + * FIELD_MAX() returns the maximum value that can be held in the field |
---|
| 80 | + * specified by @_mask. |
---|
| 81 | + */ |
---|
| 82 | +#define FIELD_MAX(_mask) \ |
---|
| 83 | + ({ \ |
---|
| 84 | + __BF_FIELD_CHECK(_mask, 0ULL, 0ULL, "FIELD_MAX: "); \ |
---|
| 85 | + (typeof(_mask))((_mask) >> __bf_shf(_mask)); \ |
---|
64 | 86 | }) |
---|
65 | 87 | |
---|
66 | 88 | /** |
---|
.. | .. |
---|
118 | 140 | { |
---|
119 | 141 | return field / field_multiplier(field); |
---|
120 | 142 | } |
---|
| 143 | +#define field_max(field) ((typeof(field))field_mask(field)) |
---|
121 | 144 | #define ____MAKE_OP(type,base,to,from) \ |
---|
122 | 145 | static __always_inline __##type type##_encode_bits(base v, base field) \ |
---|
123 | 146 | { \ |
---|