atomic asms and GCC 3.4.0

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I'm trying to get some code of ours to work with GCC 3.4.0, and I'm
running into some problems with some asms we use for atomic
operations.  (These were originally taken from a header originally
written by Doug Rabson, for what it's worth.)

The macros originally said:

#define MPLOCKED        "lock ; "

/*
 * The assembly is volatilized to demark potential before-and-after side
 * effects if an interrupt or SMP collision were to occur.
 */
#define ATOMIC_ASM(NAME, TYPE, OP, CONS, V)             \
static inline __attribute__((__always_inline__)) void   \
atomic_##NAME##_##TYPE(volatile unsigned TYPE *p, unsigned TYPE v)\
{                                                       \
        __asm __volatile(MPLOCKED OP                    \
                         : "+m" (*p)                    \
                         : CONS (V));                   \
}

ATOMIC_ASM(set,      long,  "orl %1,%0",   "ir",  v);
ATOMIC_ASM(clear,    long,  "andl %1,%0",  "ir", ~v);
ATOMIC_ASM(add,      long,  "addl %1,%0",  "ir",  v);
ATOMIC_ASM(subtract, long,  "subl %1,%0",  "ir",  v);


With GCC 3.4.0, I got a complaint about a read-write operation whose
constraint doesn't allow a non-register.  (I don't have the exact
error message written down, though I can regenerate it easily enough
if that would be helpful.)  

I've never written asm expressions myself, so I'm swimming in the dark
here to some extent, but looking at the info pages made it seem like
the "+m" was the problem, and the following alternative (which I also
found in a web search) seemed reasonable:


#define ATOMIC_ASM(NAME, TYPE, OP, CONS, V)             \
static inline __attribute__((__always_inline__)) void   \
atomic_##NAME##_##TYPE(volatile unsigned TYPE *p, unsigned TYPE v)\
{                                                       \
        __asm __volatile(MPLOCKED OP                    \
                         : "=m" (*p)                    \
                         : "0" (*p), CONS (V));         \
}

ATOMIC_ASM(set,      long,  "orl %2,%0",   "ir",  v);
ATOMIC_ASM(clear,    long,  "andl %2,%0",  "ir", ~v);
ATOMIC_ASM(add,      long,  "addl %2,%0",  "ir",  v);
ATOMIC_ASM(subtract, long,  "subl %2,%0",  "ir",  v);


In other words, I split the "+m" into two separate operands, with the
second refering to the first via "0", and changed the %1's into %2's:
so what used to be

  __asm __volatile( "lock; addl %1,%0" : "+m" (*p) : "ir" (v) );

becomes

  __asm __volatile( "lock; addl %2,%0" : "=m" (*p) : "0" (*p), "ir" (v) );

This time, however, I get the following message:

Atomic.h:112: warning: matching constraint does not allow a register
Atomic.h:112: warning: matching constraint does not allow a register
Atomic.h:112: error: inconsistent operand constraints in an `asm'

(Where line 112 is the ATOMIC_ASM(add) line.)

So obviously I did something wrong, but I'm not sure what, and I can't
really make head or tails of that error message.  Can anbody more
familiar with GCC 3.4 and asms help me?

I don't subscribe to gcc-help, so please Cc: me on any answers.

Thanks,
David Carlton
carlton@xxxxxxxxxx

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux