|
// this is some ugly math :) |
|
|
|
//----------- MASK SETS ----------------- |
|
// MASK Sets are arrays of bit-fields of some bit-width (5, 3, ... ) |
|
// they are set/returned as unsigned integer values. |
|
// They are stored-in/accessed via a uint8_t which gives byte-offset calculations. |
|
// they return their value as uintmax_t from the offset memory address directly; |
|
// Some platforms(Arm) may SIGBUS because of wide offset accesses spanning word boundaries. |
|
// This issue may be fixed by rounding, grabbing the word aligned values and shifting manually |
|
// Declarataion/Instantiation of a mask set is done with MASKSET macro below |
|
|
|
// 32 bits max for range on mask |
|
#define MASK_MAX_LENGTH (sizeof(MASKSET_READTYPE)*CHAR_BIT) |
|
|
|
/* gives a 32 bit mask possible from flagset.. |
|
- updated; return max int possible; but only the low N bits will be set |
|
- mask sets are meant for small values, but could be used for like 21 bit fields. (another form of unicode encoding I suppose) |
|
*/ |
|
#define MASKSET_READTYPE uintmax_t |
|
|
|
// gives byte index... |
|
#define MASKSETTYPE uint8_t |
|
/* how many bits the type specified can hold |
|
Parameters |
|
t : data type to measure (int, uint32_t, ... ) */ |
|
#define MASKTYPEBITS(t) (sizeof(t)*CHAR_BIT) |
|
/* the maximum number of bits storable in a type */ |
|
#define MASK_MAX_TYPEBITS(t) (sizeof(t)*CHAR_BIT) |
|
/* round up to the next count of types that fits 1 bit - used as a cieling round factor */ |
|
#define MASKROUND(t) (MASKTYPEBITS(t)-1) |
|
/* define MAX_MAX_ROUND factor based on MASKSET_READTYPE - how to read it... */ |
|
#define MASK_MAX_ROUND() (MASK_MAX_TYPEBITS(MASKSET_READTYPE)-1) |
|
/* byte index of the start of the mask |
|
Parameters |
|
t : type to measure with |
|
n : mask index */ |
|
#define MASKTYPE_INDEX(t,n) (((n)+MASKROUND(t))/MASKTYPEBITS(t)) |
|
/* The number of bytes the set would be. |
|
Parameters |
|
t : the given type to measure with |
|
n : the count of masks to fit. */ |
|
#define MASKSETSIZE(t,n) (MASKTYPE_INDEX(t,(n+1))) |
|
// declare a set of flags... |
|
|
|
#define MASK_TOP_MASK_VAL(length,val) ((val)&( ((MASKSET_READTYPE)-1) >> ((sizeof(MASKSET_READTYPE) * CHAR_BIT)-(length)) )) |
|
/* the mask in the dword resulting from shift-right. (gets a mask of X bits in length) */ |
|
#define MASK_TOP_MASK(length) ( ((MASKSET_READTYPE)-1) >> ((sizeof(MASKSET_READTYPE) * CHAR_BIT)-(length)) ) |
|
/* the mast in the dword shifted to the left to overlap the field in the word */ |
|
#define MASK_MASK(n,length) (MASK_TOP_MASK(length) << (((n)*(length)) & (sizeof(MASKSET_READTYPE) - 1) ) ) |
|
// masks value with the mask size, then applies that mask back to the correct word indexing |
|
#define MASK_MASK_VAL(n,length,val) (MASK_TOP_MASK_VAL(length,val) << (((n)*(length))&0x7) ) |
|
|
|
/* declare a mask set. |
|
MASKSET( maskVariableName |
|
, 32 //number of items |
|
, 5 // number of bits per field |
|
); |
|
|
|
declares |
|
uint8_t maskVariableName[ (32*5 +(CHAR_BIT-1))/CHAR_BIT ]; //data array used for storage. |
|
const int askVariableName_mask_size = 5; // used aautomatically by macros |
|
*/ |
|
#define MASKSET(v,n,r) MASKSETTYPE (v)[(((n)*(r))+MASK_MAX_ROUND())/MASKTYPEBITS(MASKSETTYPE)]; const int v##_mask_size = r; |
|
|
|
/* set a field index to a value |
|
SETMASK( askVariableName, 3, 13 ); // set set member 3 to the value '13' |
|
*/ |
|
#define SETMASK(v,n,val) (((MASKSET_READTYPE*)((v)+((n)*(v##_mask_size))/MASKTYPEBITS((v)[0])))[0] = \ |
|
( ((MASKSET_READTYPE*)((v)+((n)*(v##_mask_size))/MASKTYPEBITS(uint8_t)))[0] \ |
|
& (~(MASK_MASK(n,v##_mask_size))) ) \ |
|
| MASK_MASK_VAL(n,v##_mask_size,val) ) |
|
|
|
/* get the value of a field |
|
GETMASK( maskVariableName, 3 ); // returns '13' given the SETMASK() example code. |
|
*/ |
|
#define GETMASK(v,n) ( ( ((MASKSET_READTYPE*)((v)+((n)*(v##_mask_size))/MASKTYPEBITS((v)[0])))[0] \ |
|
& MASK_MASK(n,v##_mask_size) ) \ |
|
>> (((n)*(v##_mask_size))&0x7)) |