On Wed, 2009-03-11 at 01:05 -0400, DJ Delorie wrote:
> > Can you provide example code? I'm confused enough to believe
> > that you *should* get this effect with PCC_BITFIELD_TYPE_MATTERS
> > (modulo current bugs).
>
> Imagine a device with four 8-bit registers followed by a 32-bit
> register with an 8-bit field:
>
> byte status (read-only, clears after reading)
> byte control (read/write)
> byte tx buf (write only)
> byte rx buf (read only)
> long uart configuration
> divisor:8
> bits:3
> stop:1
> start:1
> reserved:3
> clock source:8
> pin_selection:8
>
> so, you'd do this:
>
> typedef struct {
> char status:8;
> char control:8;
> char tx:8;
> char rx:8;
> long divisor:8;
> long bits:3;
> long stop:1;
> long start:1;
> long reserved:3;
> long clock_source:8;
> long pin_selection:8;
> } UartDev;
>
> extern volatile UartDev uart1;
>
> If you use SImode to access any of the first four registers, you may
> end up clearing a status bit you haven't read yet. If you use QImode
> to write the divisor, you may end up clearing the other bits if gcc
> doesn't drive the right values onto the bus.
>
> With our current code, the mode for access for the above would either
> always be QI or always be SI; there's no way to have QI for the first
> four and SI for the rest.
>
> The culprit is get_best_mode(), which doesn't know the C type of the
> field. PCC_BITFIELD_TYPE_MATTERS seems to only control layout, not
> access. Even if it did solve the type-v-mode problem, turning it on
> would break ABI compatibility.
I don't know how the Ada front-end achieve this and wether it's portable
but the following seem to work:
procedure Aa is
type U8 is mod 2**8;
for U8'Size use 8;
pragma Atomic (U8);
type U8B is mod 2**8;
type U3B is mod 2**3;
type U1B is mod 2;
type R1 is record
B1 : U8B;
B2 : U3B;
B3 : U1B;
B4 : U1B;
B5 : U3B;
B6, B7 : U8B;
end record;
pragma Pack (R1);
pragma Atomic (R1);
type R is record
B1, B2, B3, B4 : U8;
B5 : R1;
end record;
pragma Pack (R);
pragma Volatile (R);
X : R;
X1 : R1;
begin
X.B1 := 0;
X.B2 := 0;
X.B3 := 0;
X.B4 := 0;
X1 := X.B5;
end AA;
gcc -S -O2 aa.adb
_ada_aa:
.LFB1:
movb $0, -12(%rsp)
movb $0, -11(%rsp)
movb $0, -10(%rsp)
movb $0, -9(%rsp)
movl $0, -24(%rsp)
ret