gcc-4.3.0/ppc32 inline assembly produces bad code

Till Straumann strauman at slac.stanford.edu
Wed Mar 26 19:37:19 UTC 2008


Daniel Jacobowitz wrote:
> On Wed, Mar 26, 2008 at 09:25:05AM -0700, Till Straumann wrote:
>> Is my inline assembly wrong or is this a gcc bug ?
>
> Your inline assembly seems wrong.
I'm not yet convinced about that...
>
>> /* Powerpc I/O barrier instruction */
>> #define EIEIO(pmem) do { asm volatile("eieio":"=m"(*pmem):"m"(*pmem)); }  
>> while (0)
>
> An output memory doesn't mean what you think.
How do I tell gcc that the asm modifies a certain area of memory
w/o adding all memory to the clobber list? I thought the output
memory operand did just that.
>   I suspect GCC gave you
> an input memory operand as "%r0(%r9)" 
Hmm you mean it gave me 0(%r9) in %r0 ? That would still be wrong
because I asked for *reg_p which would be 16(%r9). Plus, I thought
gcc would do that if the constraint was "r" not "m".
> and an output memory operand as
> "%r9",
In any case, bad code is also produced by gcc-4.3.0 if I omit the
memory output operand and use an example that comes pretty
close to what is in the gcc info page (example illustrating
a memory input in the 'extended asm' section):

******************
C-Code
******************

#define IEVENT_REG                      0x010
#define IEVENT_GRSC                     (1<<8)

void
test(volatile unsigned *base)
{
    volatile unsigned *reg_p = base + IEVENT_REG/sizeof(*base);
    unsigned           val;

    /* tell gcc that the asm needs/looks at *reg_p */
    asm volatile ("lwz %0, 16(%1)":"=r"(val):"b"(base),"m"(*reg_p));

    while ( ! (val & IEVENT_GRSC) )
        val = *reg_p;
    ;
}

*******************
assembly produced by gcc-4.3.0
*******************

        .file   "tst.c"
        .gnu_attribute 4, 1
        .gnu_attribute 8, 1
        .section        ".text"
        .align 2
        .globl test
        .type   test, @function
test:
        mr 9,3
 # 13 "b.c" 1
        lwz 3, 16(3)
 # 0 "" 2
        andi. 0,3,256
        bnelr- 0
.L5:
        lwz 0,0(9)      /* BAD: R0 = *base instead of R0 = *reg_p */
        andi. 11,0,256
        beq+ 0,.L5
        blr
        .size   test, .-test
        .ident  "GCC: (GNU) 4.3.0"

********************
assembly produced by gcc-4.2.3
********************

        .file   "tst.c"
        .section        ".text"
        .align 2
        .globl test
        .type   test, @function
test:
        addi 9,3,16
        lwz 3, 16(3)
        andi. 0,3,256
        bnelr- 0
.L5:
        lwz 0,0(9)   /* GOOD R0 = *reg_p */
        andi. 11,0,256
        beq+ 0,.L5
        blr
        .size   test, .-test
        .ident  "GCC: (GNU) 4.2.3"

>  and expected the asm to do what it said it would do with its
> operands.
>
> Which doesn't make much sense... but there you go.
>
> Try clobbering it instead, but you don't even need to since the
> pointer is already volatile.  asm volatile ("eieio") should work fine.
Yes but there still seems to be a problem (see example in
this message)

-- Till.




More information about the users mailing list