Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 29 Dec 2004 04:18:17 +1100 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        John-Mark Gurney <gurney_j@resnet.uoregon.edu>
Cc:        amd64@freebsd.org
Subject:   Re: what is the proper asm spec for xchg
Message-ID:  <20041229032725.P90388@delplex.bde.org>
In-Reply-To: <20041223202302.GG19624@funkthat.com>
References:  <1103830283.53421.3.camel@server.mcneil.com> <20041223202302.GG19624@funkthat.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 23 Dec 2004, John-Mark Gurney wrote:

> Sean McNeil wrote this message on Thu, Dec 23, 2004 at 11:31 -0800:
> > I'm looking at why audio/sdl_mixer will not compile and I see that
> > devel/sdl12 has an include with
> >
> > #elif defined(__GNUC__) && defined(__x86_64__)
> > static __inline__ Uint16 SDL_Swap16(Uint16 x)
> > {
> >         __asm__("xchgb %b0,%h0" : "=q" (x) :  "0" (x));
> >         return x;
> > }
> >
> > This appears to be incorrect as it is giving errors when compiled.  Does
> > anyone more conversant with asm directives for amd64 have an idea what
> > this should be?
>
> well, from amd64/include/endian.h:
> #define __byte_swap_word_var(x) \
> __extension__ ({ register __uint16_t __X = (x); \
>    __asm ("xchgb %h0, %b0" : "+Q" (__X)); \
                                 ^ actually q
>    __X; })

The critical difference is that the "q" constraint gives all general
registers on amd64's, but "%h" (to give the second lowest 8-bit subregister)
only works for the a, b, c and d registers.  The "Q" constraint must be
used to restrict to the latter.  This difference from i386's is because
gcc defines "q" registers to be ones whose lowest 8 bits can be addressed
directly and amd64's support this for all general registers.

The unimportant differences are:

(1) The working version uses the "+" constraint where the broken version
uses the "=" and "0" constraints.  "0" is just old-fashioned and harder
to use here.  It was needed for general operands before "+" existed,
and caused problems depending on optimization and register pressure.
Now it is only supported for register operands, but the above only uses
register operands so "0" should work.

(2) The operand orders are are reversed.  This makes no difference to the
result because the operand order doesn't matter for exchanges.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20041229032725.P90388>