This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
More on SUBREG
- To: gcc at gcc dot gnu dot org
- Subject: More on SUBREG
- From: Etienne Lorrain <etienne_lorrain at yahoo dot fr>
- Date: Mon, 26 Feb 2001 17:56:57 +0100 (CET)
> > > The mismatch is this: It's documented that stores into SUBREG's with
> > > a smaller mode, leave the other bits in undefined state:
> > > "Storing in a non-paradoxical `subreg' has undefined results for
> > > bits belonging to the same word as the `subreg'." (from docu of
> > ^^^^^^^^^^^^^^^^
> >
> > It's no mismatch. Bits belonging to other words remain unchanged.
>
> Ahh OK, thanks for clarifying. That makes things clean and easy ;)
Seems to be the reason why, on i386, the change endian function:
extern inline unsigned bswap(unsigned val)
{
union {
unsigned l;
unsigned short s;
} tmp = { val };
tmp.s = (tmp.s >> 8) | (tmp.s << 8);
tmp.l = (tmp.l >> 16) | (tmp.l << 16);
tmp.s = (tmp.s >> 8) | (tmp.s << 8);
return tmp.l;
}
Produces this:
movw %w0,%w1
rolw $8,%w1
movw %w1,%w0
roll $16,%0
movw %w0,%w1
rolw $8,%w1
movw %w1,%w0
(replace %w0 by %ax or 15(%esp), %0 by %eax or 15(%esp), and %w1 by %bx
if you do not like this notation)
Instead of the simplest:
rolw $8,%w0
roll $16,%0
rolw $8,%w0
So it is better to do it in assembly:
extern inline unsigned bswap(unsigned val)
{
unsigned val;
#if defined(__i386__)
__asm__ __volatile__ ("
rolw $8,%w0 # the 'w' is ignored if '+g' is a reference
roll $16,%0
rolw $8,%w0
"
: "+g" (val)
);
#else
__asm__ __volatile__ (" bswap %0 "
: "+r" (val));
#endif
return val;
}
But sometimes, even on 80486+, the "rol" version would be better
because bswap assembly instruction only accept a register as
parameter (when there is no more register available).
Only the compiler could choose correctly.
Not really a question, just my €0.02.
Etienne.
___________________________________________________________
Do You Yahoo!? -- Pour dialoguer en direct avec vos amis,
Yahoo! Messenger : http://fr.messenger.yahoo.com