On Thu, Oct 6, 2011 at 10:25 AM, Ulf Magnusson <ulfali...@gmail.com> wrote: > On Thu, Oct 6, 2011 at 12:55 AM, Pedro Pedruzzi > <pedro.pedru...@gmail.com> wrote: >> Em 05-10-2011 17:11, Ulf Magnusson escreveu: >>> Hi, >>> >>> I've been experimenting with different methods for emulating the >>> signed overflow of an 8-bit CPU. >> >> You would like to check whether a 8-bit signed addition will overflow or >> not, given the two operands. Is that correct? >> >> As you used the word `emulating', I am assuming that your function will >> not run by the mentioned CPU. >> > > No, it'll most likely only run on systems with a wider bitness. > >> Does this 8-bit CPU use two's complement representation? > > Yes, and the criterion for signed overflow is "both numbers have the > same sign, but the sign of the sum is different". Should have made > that more clear. > >> >>> The method I've found that seems to >>> generate the most efficient code on both ARM and x86 is >>> >>> bool overflow(unsigned int a, unsigned int b) { >>> const unsigned int sum = (int8_t)a + (int8_t)b; >>> return (int8_t)sum != sum; >>> } >>> >>> (The real function would probably be 'inline', of course. Regs are >>> stored in overlong variables, hence 'unsigned int'.) >>> >>> Looking at the spec, it unfortunately seems the behavior of this >>> function is undefined, as it relies on signed int addition wrapping, >>> and that (int8_t)sum truncates bits. Is there some way to make this >>> guaranteed safe with GCC without resorting to inline asm? Locally >>> enabling -fwrap takes care of the addition, but that still leaves the >>> conversion. >> >> I believe the cast from unsigned int to int8_t is implementation-defined >> for values that can't be represented in int8_t (e.g. 0xff). A kind of >> `undefined behavior' as well. >> >> I tried: >> >> bool overflow(unsigned int a, unsigned int b) { >> const unsigned int sum = a + b; >> return ((a & 0x80) == (b & 0x80)) && ((a & 0x80) != (sum & 0x80)); >> } >> >> But it is not as efficient as yours. >> >> -- >> Pedro Pedruzzi >> > > Yeah, I tried similar bit-trickery along the lines of > > bool overflow(unsigned int a, unsigned int b) { > const uint8_t ab = (uint8_t)a; > const uint8_t bb = (uint8_t)b; > const uint8_t sum = ab + bb; > return (ab ^ bb) & ~(ab ^ sum) & 0x80; > } > > , but it doesn't seem to generate very efficient code. > > /Ulf >
Might as well do bool overflowbit(unsigned int a, unsigned int b) { const unsigned int sum = a + b; return (a ^ b) & ~(a ^ sum) & 0x80; } But still not very good output compared to other approaches as expected. /Ulf