In the RX chip (and others, of course), the memory-mapped peripherals
have a fixed bit-ordering independent of the endianness of data.
However, GCC defines bitfields in structures differently for different
endians - effectively always beginning allocations with the lowest
addressed byte.

To avoid having two completely independent definitions of the
peripheral register structures, would it be acceptable to add a target
hook to tell gcc to reverse the bitfields?  This can be done in
finish_record_layout() by adjusting bit offsets, but is only defined
for targets where switching bitfield base types starts a new
allocation (i.e. "long x:4;" and "char x;" can't overlap) or where the
user is careful to avoid such a situation.

I propose a boolean hook that passes the type to the backend, and
controls if bitfield packing should be reversed for that type.  The
target can then use options, attributes, or pragmas to decide.  If gcc
determines that reversing the packing causes fields to overlap, an
error would be generated.  Caveat programmer.

Thus, one could do something like this (assuming I put the attribute
in the right place, of course):

typedef struct __attribute__((bit_packing(lsb_first)))
{
  unsigned long timer_start:1;
  unsigned long timer_clock:5;
  unsigned long :15;
  unsigned long timer_mode:11;
} TimerS;

and always have "timer_start" be the LSB of that 32-bit register.

(alternately, there could be a target-independent attribute (such as
above), but in the RX case, compatibility with other RX compilers
means the target needs to use a pragma)

Comments?

Reply via email to