Re: [RFC][PATCH] new byteorder primitives - ..._{replace,get}_bits()

From: Jakub Kicinski
Date: Mon Dec 11 2017 - 23:02:44 EST


On Mon, 11 Dec 2017 15:54:22 +0000, Al Viro wrote:
> Essentially, it gives helpers for work with bitfields in fixed-endian.
> Suppose we have e.g. a little-endian 32bit value with fixed layout;
> expressing that as a bitfield would go like
> struct foo {
> unsigned foo:4; /* bits 0..3 */
> unsigned :2;
> unsigned bar:12; /* bits 6..17 */
> unsigned baz:14; /* bits 18..31 */
> }
> Even for host-endian it doesn't work all that well - you end up with
> ifdefs in structure definition and generated code stinks. For fixed-endian
> it gets really painful, and people tend to use explicit shift-and-mask
> kind of macros for accessing the fields (and often enough get the
> endianness conversions wrong, at that). With these primitives
>
> struct foo v <=> __le32 v
> v.foo = i ? 1 : 2 <=> v = le32_replace_bits(v, i ? 1 : 2, 0, 4)
> f(4 + v.baz) <=> f(4 + le32_get_bits(v, 18, 14))

Looks very useful. The [start bit, size] pair may not land itself
too nicely to creating defines, though. Which is why in
include/linux/bitfield.h we tried to use a shifted mask and work
backwards from that single value what the start and size are. commit
3e9b3112ec74 ("add basic register-field manipulation macros") has the
description. Could a similar trick perhaps be applicable here?