On Sat, Jan 07, 2006 at 02:03:42AM -0800, David S. Miller wrote:
> From: Al Viro <[EMAIL PROTECTED]>
> Date: Sat, 7 Jan 2006 09:39:10 +0000
> 
> > BTW, is there any reason why
> > static inline void ip_eth_mc_map(u32 addr, char *buf)
> > {
> >         addr=ntohl(addr);
> >         buf[0]=0x01;
> >         buf[1]=0x00;
> >         buf[2]=0x5e;
> >         buf[5]=addr&0xFF;
> >         addr>>=8;
> >         buf[4]=addr&0xFF;
> >         addr>>=8;
> >         buf[3]=addr&0x7F;
> > }
> > is not doing just
> >     unsigned char *p = &addr;
> >         buf[0]=0x01;
> >         buf[1]=0x00;
> >         buf[2]=0x5e;
> >         buf[3]=p[1]&0x7F;
> >         buf[4]=p[2];
> >         buf[5]=p[3];
> 
> Because GCC can't make anything reasonable with it.
> 
> And besides wouldn't that need to be:
> 
>          buf[3]=p[3]&0x7F;
>          buf[4]=p[2];
>          buf[5]=p[1];
> 
> on big-endian? :-)

No.  Note the lack of ntohl() in that variant.  We are getting last
3 octets of address (sans one bit) into the last 3 octets of MAC,
preserving the order.
 
> GCC isn't (currently) smart enough to avoid tossing addr onto the
> stack when you do the pointer games like that.  With gcc-4.0.2 on
> sparc I get:
> 
>       mov     1, %g1
>       st      %o0, [%sp+68]
>       mov     94, %g2
>       stb     %g1, [%o1]
>       ldub    [%sp+69], %g1
>       and     %g1, 127, %g1
>       stb     %g2, [%o1+2]
>       stb     %g1, [%o1+3]
>       ldub    [%sp+70], %g2
>       ldub    [%sp+71], %g1
>       stb     %g0, [%o1+1]
>       stb     %g2, [%o1+4]
>       jmp     %o7+8
>        stb    %g1, [%o1+5]
> 
> That's with -O2, 32-bit.

Gaack...  I've just spent a while playing with sparc-linux-gcc and apparently
the only way to convince it _not_ to shit on stack is to do an equivalent
of put_unaligned().  Amusingly, __builtin_memcpy(&n, p, 4) does worse
than store to unaligned field...  Anyway, it's way too fscking ugly to
be taken seriously.


OK.  Another question: do you have any objections against
static inline void ip_eth_mc_map(__be32 addr, char *buf)
{
        __u32 n=ntohl(addr);
        buf[0]=0x01;
        buf[1]=0x00;
        buf[2]=0x5e;
        buf[5]=n&0xFF;
        addr>>=8;
        buf[4]=n&0xFF;
        addr>>=8;
        buf[3]=n&0x7F;
}

That does compile to exact same code as original - gcc fortunately has
enough clue to realize that addr is never used past the initialization of
n, which is, from C point of view, of exact same type as addr.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to