|
31 | 31 | #define BIT_ULL_MASK(nr) (ULL(1) << ((nr) % BITS_PER_LONG_LONG)) |
32 | 32 | #define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) |
33 | 33 | #define BITS_PER_BYTE 8 |
| 34 | +#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) |
34 | 35 |
|
35 | 36 | /* |
36 | 37 | * Create a contiguous bitmask starting at bit position @l and ending at |
37 | 38 | * position @h. For example |
38 | 39 | * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000. |
39 | 40 | */ |
40 | 41 | #if !defined(__ASSEMBLY__) |
| 42 | + |
| 43 | +/* |
| 44 | + * Missing asm support |
| 45 | + * |
| 46 | + * GENMASK_U*() and BIT_U*() depend on BITS_PER_TYPE() which relies on sizeof(), |
| 47 | + * something not available in asm. Nevertheless, fixed width integers is a C |
| 48 | + * concept. Assembly code can rely on the long and long long versions instead. |
| 49 | + */ |
| 50 | + |
41 | 51 | #include <linux/build_bug.h> |
42 | 52 | #include <linux/compiler.h> |
43 | 53 | #define GENMASK_INPUT_CHECK(h, l) BUILD_BUG_ON_ZERO(const_true((l) > (h))) |
|
57 | 67 | (type_max(t) << (l) & \ |
58 | 68 | type_max(t) >> (BITS_PER_TYPE(t) - 1 - (h))))) |
59 | 69 |
|
| 70 | +#define GENMASK(h, l) GENMASK_TYPE(unsigned long, h, l) |
| 71 | +#define GENMASK_ULL(h, l) GENMASK_TYPE(unsigned long long, h, l) |
| 72 | + |
60 | 73 | #define GENMASK_U8(h, l) GENMASK_TYPE(u8, h, l) |
61 | 74 | #define GENMASK_U16(h, l) GENMASK_TYPE(u16, h, l) |
62 | 75 | #define GENMASK_U32(h, l) GENMASK_TYPE(u32, h, l) |
63 | 76 | #define GENMASK_U64(h, l) GENMASK_TYPE(u64, h, l) |
| 77 | +#define GENMASK_U128(h, l) GENMASK_TYPE(u128, h, l) |
64 | 78 |
|
65 | 79 | /* |
66 | 80 | * Fixed-type variants of BIT(), with additional checks like GENMASK_TYPE(). The |
|
86 | 100 | * BUILD_BUG_ON_ZERO is not available in h files included from asm files, |
87 | 101 | * disable the input check if that is the case. |
88 | 102 | */ |
89 | | -#define GENMASK_INPUT_CHECK(h, l) 0 |
| 103 | +#define GENMASK(h, l) __GENMASK(h, l) |
| 104 | +#define GENMASK_ULL(h, l) __GENMASK_ULL(h, l) |
90 | 105 |
|
91 | 106 | #endif /* !defined(__ASSEMBLY__) */ |
92 | 107 |
|
93 | | -#define GENMASK(h, l) \ |
94 | | - (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l)) |
95 | | -#define GENMASK_ULL(h, l) \ |
96 | | - (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l)) |
97 | | - |
98 | | -#if !defined(__ASSEMBLY__) |
99 | | -/* |
100 | | - * Missing asm support |
101 | | - * |
102 | | - * __GENMASK_U128() depends on _BIT128() which would not work |
103 | | - * in the asm code, as it shifts an 'unsigned __int128' data |
104 | | - * type instead of direct representation of 128 bit constants |
105 | | - * such as long and unsigned long. The fundamental problem is |
106 | | - * that a 128 bit constant will get silently truncated by the |
107 | | - * gcc compiler. |
108 | | - */ |
109 | | -#define GENMASK_U128(h, l) \ |
110 | | - (GENMASK_INPUT_CHECK(h, l) + __GENMASK_U128(h, l)) |
111 | | -#endif |
112 | | - |
113 | 108 | #endif /* __LINUX_BITS_H */ |
0 commit comments