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

Reply via email to