2016-12-05 17:49:37

by Sebastian Frias

[permalink] [raw]
Subject: [PATCH v2] add equivalent of BIT(x) for bitfields

Introduce GENVALUE(msb, lsb, value) macro to ease dealing with
continuous bitfields, just as BIT(x) does for single bits.

GENVALUE_ULL(msb, lsb, value) macro is also added.

This is useful mostly for creating values to be packed together
via OR operations, ex:

u32 val = 0x11110000;
val |= GENVALUE(19, 12, 0x5a);

now 'val = 0x1115a000'


Signed-off-by: Sebastian Frias <[email protected]>
---

Change in v2:
- rename the macro to GENVALUE as proposed by Linus
- longer comment attempts to show use case for the macro as
proposed by Borislav

---
include/linux/bitops.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index a83c822..641675d 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -24,6 +24,20 @@
#define GENMASK_ULL(h, l) \
(((~0ULL) << (l)) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))

+#ifdef __KERNEL__
+/*
+ * Equivalent of BIT(x) but for contiguous bitfields
+ * GENVALUE(1, 0,0xff) = 0x00000003
+ * GENVALUE(3, 0,0xff) = 0x0000000f
+ * GENVALUE(15,8,0xff) = 0x0000ff00
+ * GENVALUE(6, 6, 1) = 0x00000040 == BIT(6)
+ */
+#define GENVALUE(msb, lsb, val) \
+ (((val) << (lsb)) & (GENMASK((msb), (lsb))))
+#define GENVALUE_ULL(msb, lsb, val) \
+ (((val) << (lsb)) & (GENMASK_ULL((msb), (lsb))))
+#endif
+
extern unsigned int __sw_hweight8(unsigned int w);
extern unsigned int __sw_hweight16(unsigned int w);
extern unsigned int __sw_hweight32(unsigned int w);
--
1.8.3.1


2016-12-05 18:23:07

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH v2] add equivalent of BIT(x) for bitfields

On Mon, Dec 5, 2016 at 9:49 AM, Sebastian Frias <[email protected]> wrote:
> Introduce GENVALUE(msb, lsb, value) macro to ease dealing with
> continuous bitfields, just as BIT(x) does for single bits.

Oh, and looking at the implementation, this is wrong. You use "lsb"
twice, so it mustn't have side effects.

That's fine for all expected users (since you'd expect that the only
real use of this is with constant values for msb/lsb), but please add
actual checking.

You can use BUILD_BUG_ON_ZERO(!__builtin_constant_p(x)) or something.
That returns zero, so it's easy to use in expressions.

Linus

2016-12-06 10:35:23

by Sebastian Frias

[permalink] [raw]
Subject: Re: [PATCH v2] add equivalent of BIT(x) for bitfields

On 05/12/16 19:23, Linus Torvalds wrote:
> On Mon, Dec 5, 2016 at 9:49 AM, Sebastian Frias <[email protected]> wrote:
>> Introduce GENVALUE(msb, lsb, value) macro to ease dealing with
>> continuous bitfields, just as BIT(x) does for single bits.
>
> Oh, and looking at the implementation, this is wrong. You use "lsb"
> twice, so it mustn't have side effects.
>
> That's fine for all expected users (since you'd expect that the only
> real use of this is with constant values for msb/lsb),

Yes, that's what I thought.

>but please add
> actual checking.

Sure! Thanks for the advice.

>
> You can use BUILD_BUG_ON_ZERO(!__builtin_constant_p(x)) or something.
> That returns zero, so it's easy to use in expressions.

Done. v3 of the patch is submitted.

>
> Linus
>