nasmlib: set of neat macros to create a useful bitfield enum

When dealing with bitmasks/bitfields, definining them in macros tends
to cause a lot of desirable constants out because it is a pain to
create all of them.  C macros can't create other macros, but they
*can* be used to create fields in an enum, so provide some neat
convenience macros for doing so.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin 2025-09-20 17:26:48 -07:00
parent 5d75c20105
commit 47c56d122e
2 changed files with 54 additions and 0 deletions

View file

@ -54,6 +54,59 @@ union intorptr {
};
typedef union intorptr intorptr;
/*
* Handy macro to use as the base of shifts
*/
#define ONE ((uintmax_t)1)
/*
* Handy macros for defining and accessing enums of bitfields;
* provides a set of standard-named parameters for each field.
*
* mk_field_mask() is indended to be used for non-contiguous fields.
*/
#define mk_field_mask(name,pos,width,basemask) \
name ## _POS = (pos), \
name ## _WIDTH = (width), \
name ## _BASEMASK = (basemask), \
name ## _MASK = name ## _BASEMASK << name ## _POS, \
name = name ## _MASK
#define mk_field(name,pos,width) \
mk_field_mask(name,pos,width, \
(ONE << name ## _WIDTH)-1)
/*
* Cast a value to a suitable type to represent the encoded
* (post-shift) and extracted (pre-shift) values, respectively.
*/
#ifdef HAVE_TYPEOF
# define fieldenc_cast(x,y) ((typeof(x ## _MASK))(y))
# define fieldval_cast(x,y) ((typeof(x ## _BASEMASK))(y))
#else
# define fieldenc_cast(x,y) ((uintmax_t)(y))
# define fieldval_cast(x,y) (y)
#endif
/*
* Macros to get/set bitfield values (the set macro returns the
* updated value, it does not change the input.)
*
* The fieldenc() macro produces the masked and shifted value
* corresponding to a base value; it is equivalent to
* setfield(field,0,val).
*/
#define getfield(field,from) \
fieldval_cast(field, \
(((from) >> field ## _POS) & \
field ## _BASEMASK))
#define fieldval(field,val) \
(((val) & fieldenc_cast(field,field ## _BASEMASK)) \
<< field ## _POS)
#define setfield(field,from,val) \
(((from) & ~(field ## _MASK)) + fieldval(field,val))
/*
* Wrappers around malloc, realloc, free and a few more. nasm_malloc
* will fatal-error and die rather than return NULL; nasm_realloc will