
/** Unions and Macros for Accessing 16-bit and 32-bit Data Objects'
 *  Individual Bytes and Words
 *
 *  U16_'(u) macros yield union U16_ u's 16-bit word or the
 *  individual bytes of u's word.
 *
 *  U32_'(u) macros yield union U32_ u's 32-bit long word, or
 *  the individual words of u's long word, or the individual
 *  bytes of u's long word.
 *
 *  P16_'(p) macros access the individual bytes of the 16-bit
 *  word at address p.
 *
 *  P32_'(p) macros access the individual words or the
 *  individual bytes of the 32-bit long word at address p.
 *
 *  WARNING: Be aware of architecture-dependent alignment issues
 *           when using the P16_' and P32_' macros.  See
 *           UNALIGNED_DATA_ACCESS_OK
 */
union U16_
{
    U16 w;
    U8  b[2];
};

union U32_
{
    U32 l;
    U16 w[2];
    U8  b[4];
};

#if BIG_ENDIAN
#define U16_WRD(u)      ((u).w)
#define U16_MSB(u)      ((u).b[0])
#define U16_LSB(u)      ((u).b[1])
#define U32_LNG(u)      ((u).l)
#define U32_MSW(u)      ((u).w[0])
#define U32_LSW(u)      ((u).w[1])
#define U32_MSW_MSB(u)  ((u).b[0])
#define U32_MSW_LSB(u)  ((u).b[1])
#define U32_LSW_MSB(u)  ((u).b[2])
#define U32_LSW_LSB(u)  ((u).b[3])
#define P16_MSB(p)      (*(( U8 *)(void *)(p) + 0))
#define P16_LSB(p)      (*(( U8 *)(void *)(p) + 1))
#define P32_MSW(p)      (*((U16 *)(void *)(p) + 0))
#define P32_LSW(p)      (*((U16 *)(void *)(p) + 1))
#define P32_MSW_MSB(p)  (*(( U8 *)(void *)(p) + 0))
#define P32_MSW_LSB(p)  (*(( U8 *)(void *)(p) + 1))
#define P32_LSW_MSB(p)  (*(( U8 *)(void *)(p) + 2))
#define P32_LSW_LSB(p)  (*(( U8 *)(void *)(p) + 3))
#else   /* LITTLE_ENDIAN */
#define U16_WRD(u)      ((u).w)
#define U16_MSB(u)      ((u).b[1])
#define U16_LSB(u)      ((u).b[0])
#define U32_LNG(u)      ((u).l)
#define U32_MSW(u)      ((u).w[1])
#define U32_LSW(u)      ((u).w[0])
#define U32_MSW_MSB(u)  ((u).b[3])
#define U32_MSW_LSB(u)  ((u).b[2])
#define U32_LSW_MSB(u)  ((u).b[1])
#define U32_LSW_LSB(u)  ((u).b[0])
#define P16_MSB(p)      (*(( U8 *)(void *)(p) + 1))
#define P16_LSB(p)      (*(( U8 *)(void *)(p) + 0))
#define P32_MSW(p)      (*((U16 *)(void *)(p) + 1))
#define P32_LSW(p)      (*((U16 *)(void *)(p) + 0))
#define P32_MSW_MSB(p)  (*(( U8 *)(void *)(p) + 3))
#define P32_MSW_LSB(p)  (*(( U8 *)(void *)(p) + 2))
#define P32_LSW_MSB(p)  (*(( U8 *)(void *)(p) + 1))
#define P32_LSW_LSB(p)  (*(( U8 *)(void *)(p) + 0))
#endif
