GCC Inline Assembly for Sparc architecture

折月煮酒 提交于 2019-12-20 03:54:08

问题


I've found in internet the implementation of __sync_val_compare_and_swap:

#define LOCK_PREFIX "lock ; "

struct __xchg_dummy { unsigned long a[100]; };
#define __xg(x) ((struct __xchg_dummy *)(x))

static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
                  unsigned long new, int size)
{
   unsigned long prev;
   switch (size) {
   case 1:
      __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
                 : "=a"(prev)
                 : "q"(new), "m"(*__xg(ptr)), "0"(old)
                 : "memory");
      return prev;
   case 2:
      __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
                 : "=a"(prev)
                 : "q"(new), "m"(*__xg(ptr)), "0"(old)
                 : "memory");
      return prev;
   case 4:
      __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
                 : "=a"(prev)
                 : "q"(new), "m"(*__xg(ptr)), "0"(old)
                 : "memory");
      return prev;
   }
   return old;
}

#define cmpxchg(ptr,o,n)\
   ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
               (unsigned long)(n),sizeof(*(ptr))))

When I compile and use this function (cmpxchg) for i386 architecture - all good! But, when i compile under Sparc architecture, i've the following error:

error: impossible constraint in `asm'

What's the problem?


回答1:


On Solaris, better don't write your own code for this (neither on SPARC nor on x86); rather, use the atomic_cas(3C) functions for the purpose:

static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
              unsigned long new, int size)
{
    switch (size) {
    case 1: return atomic_cas_8(ptr, (unsigned char)old, (unsigned char)new);
    case 2: return atomic_cas_16(ptr, (unsigned short)old, (unsigned short)new);
    case 4: return atomic_cas_32(ptr, (unsigned int)old, (unsigned int)new);
#ifdef _LP64
    case 8: return atomic_cas_64(ptr, old, new);
#endif
    default: break;    
    }
    return old;
}

That'll do for Solaris.

Edit: if you absolutely have to inline this kind of thing, the SPARC (v8+, aka UltraSPARC) instruction to use is "compare and swap", aka CAS. It's always atomic (sparc doesn't know lock prefixes). It only comes in 32bit and 64bit (CASX) variants, so that the 8/16bit library functions perform 32bit CAS masking out the non-targeted word/bytes. I won't help with reimplementing that - it's not a good idea, use the library interfaces.

Edit2: Some help with reimplementing you get by reading the sourcecode (if you cannot link with Solaris libc).




回答2:


cmpxchgb is a i386 instruction, it won't work under Sparc.




回答3:


You can't compile an x86 asm for the sparc. Here's what I get using clang:

[~] main% ~/ellcc/bin/sparc-linux-ecc asm.c
asm.c:13:20: error: invalid output constraint '=a' in asm
             : "=a"(prev)

'a' is not a sparc register, it is specific to the x86.

Even it you were to fix the constraint, you'd get an assembly time error when the sparc assembler sees the cmpxchgb opcode, which is x86 specific.



来源:https://stackoverflow.com/questions/9276946/gcc-inline-assembly-for-sparc-architecture

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!