Ada front-end depends on signed overflow

Segher Boessenkool segher@kernel.crashing.org
Mon Jun 6 08:37:00 GMT 2005


> There's also a fair amount of code whih relies on -1 ==
> (int)0xFFFFFFFF.
>
> Or is there any truly portable and efficient way to convert a sequence
> of bytes (in big-endian order) to a signed integer?

Of course there is.  Assuming no padding bits:


int conv(unsigned char *c)
{
         unsigned int i, u, hibit;

         hibit = ~0U;
         hibit ^= (hibit >> 1);

         u = 0;
         for (i = 0; i < sizeof u; i++)
                 u = (u << 8) + c[i];

         if ((u & hibit) == 0U)
                 return u;

         u -= hibit;

         if ((unsigned int)-1 == (hibit | 1U))
                 return -(int)u;

         return (int)u - (int)(~hibit) - ((unsigned int)-1 & 1U);
}


which generates


_conv:
         li r2,4
         li r0,0
         mtctr r2
L11:
         lbz r2,0(r3)
         slwi r0,r0,8
         addi r3,r3,1
         add r0,r0,r2
         bdnz L11
         mr r3,r0
         blr


with GCC 3.3 on Darwin, and


.conv:
         li 9,4
         li 0,0
         li 11,0
         mtctr 9
         .p2align 4,,15
.L2:
         lbzx 9,3,11
         slwi 0,0,8
         nop
         nop
         addi 11,11,1
         add 0,0,9
         nop
         nop
         rldicl 0,0,0,32
         nop
         nop
         nop
         nop
         bdnz .L2
         extsw 3,0
         nop
         nop
         nop
         nop
         blr


with a GCC-4.1.0 snapshot on powerpc64-unknown-linux-gnu (lots of
inefficiencies here, but nothing to do with the conversion itself).

Sorry, I couldn't test it on a ones' complement or sign-magnitude
machine -- just trust me it works (or embarrass me in public, if
a bug sneaked in while converting this to C) ;-)


Segher



More information about the Gcc mailing list