[U-Boot] packed attribute problem

Wolfgang Denk wd at denx.de
Mon Oct 4 14:29:00 CEST 2010


Dear Reinhard Meyer,

In message <4CA9BE94.6000401 at emk-elektronik.de> you wrote:
>
> Do you imply that the code is really different when the pointer gets
> its value by assigning it NOT to a packed entity? Hard to believe.

This is a special "feature" of GCC on ARM.

-> cat foo.c
#define writel(v,a)              (*(volatile unsigned int *)(a) = (v))

struct p {
        int n;
} __attribute__ ((packed));

struct q {
        int n;
};

void foo()
{
        struct p *pp = (struct p *)0x1000;

        pp->n = 5;
}

void bar()
{
        struct q *qq = (struct q *)0x1000;

        qq->n = 5;
}
-> arm-linux-gcc -O -S foo.c
-> cat foo.s
        .file   "foo.c"
        .text
        .align  2
        .global foo
        .type   foo, %function
foo:
        @ Function supports interworking.
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        @ link register save eliminated.
        @ lr needed for prologue
        mov     r3, #4096
        mov     r2, #0
        orr     r1, r2, #5
        strb    r1, [r3, #0]
        strb    r2, [r3, #1]
        strb    r2, [r3, #2]
        strb    r2, [r3, #3]
        bx      lr
        .size   foo, .-foo
        .align  2
        .global bar
        .type   bar, %function
bar:
        @ Function supports interworking.
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        @ link register save eliminated.
        @ lr needed for prologue
        mov     r2, #5
        mov     r3, #4096
        str     r2, [r3, #0]
        bx      lr
        .size   bar, .-bar
        .ident  "GCC: (GNU) 4.2.2"


Note that this is with GCC 4.2.2. Even GCC 4.0.0 behaves the same, so
this is *not* an issue with very recent tool chains.


> 2. the culprit on ARM is that unaligned accesses do not raise any signal
> but silently IGNORE the "unused" adress lines which leads to very
> undesirable effects that are hard to find.

Well, the compiler turning a single 32 bit access silently into 4 x 8
bit accesses can also lead to very undesirable effects that are hard
to find, especially when accessing hardware that performs
auto-incrementing or any kind of (IRQ or similar) ACK for each
access.

> *((int *)0x10000) = 5 is the same as *((int *)0x10003) = 5 !
> Both write 5 to the word at adress 0x10000 !
> 
> So, MAYBE, in newer toolchains it was decided to circumvent that problem
> by always assuming unaligned pointers unless clearly instructed otherwise.

No, AFAICT this behaviour has not changed in the last few months / years.

> Nope. It does not have to do with packed. It would have to do with the fact
> that I/O registers cannot be safely written byte-wise.

Yes, it has to do with pcked. See above.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
If a person (a) is poorly, (b) receives treatment  intended  to  make
him  better, and (c) gets better, then no power of reasoning known to
medical science can convince him  that  it  may  not  have  been  the
treatment that restored his health.
- Sir Peter Medawar, The Art of the Soluble


More information about the U-Boot mailing list