汎用的なビットフィールドを扱う

昨日の続きで、
通常のビットフィールドのように
複数ビットの操作も可能なように改変した。

1ビットのスイッチとしても使えるけど、
計算量が多いので、1ビット版とは使い分けたほうがよさそう。


以下のように使う。

  BitFld8 a;
  
  initBitFld(a, &REG, 3, 3);  // B'0000 XXX0
  
  setBitFld(a, 2);            // B'0000 0100
  setBitFld(a, 5);            // B'0000 1010
  
  getBitFld(a);               // 5

フィールド幅のはみ出しなんかのエラーチェックはしていない。

/*
 * Bit Field: 汎用的なビットフィールドを扱う関数群
 */

// Bit Field (8bits)
typedef struct bitfld8 {
    unsigned char *adr;
    unsigned char  msk;
    unsigned char  sht;
} BitFld8;

// Bit Field (16bits)
typedef struct bitfld16 {
    unsigned short *adr;
    unsigned short  msk;
    unsigned char   sht;
} BitFld16;

// Bit Field (32bits)
typedef struct bitfld32 {
    unsigned int *adr;
    unsigned int  msk;
    unsigned int  sht;
} BitFld32;

#define initBitFld(bitfld, address, location, size)             \
    do {                                                        \
        (bitfld).adr = (address);                               \
        (bitfld).msk = ~(~0 << size) << (location - size + 1);  \
        (bitfld).sht = (location) - (size) + 1;                 \
    } while(0)

#define setBitFld(bitfld, data)                 \
    do {                                        \
        *(bitfld).adr &= ~(bitfld).msk;         \
        *(bitfld).adr |= data << (bitfld).sht;  \
    } while(0)

#define getBitFld(bitfld)                           \
    (*(bitfld).adr & (bitfld).msk) >> (bitfld).sht