On Wed, Oct 5, 2011 at 10:11 PM, Ulf Magnusson <ulfali...@gmail.com> wrote: > Hi, > > I've been experimenting with different methods for emulating the > signed overflow of an 8-bit CPU. 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. > > /Ulf >
Is *((int8_t*)&sum) safe (assuming little endian)? Unfortunately that seems to generate worse code. On X86 it generates the following (GCC 4.5.2): 00000050 <_Z9overflow4jj>: 50: 83 ec 10 sub $0x10,%esp 53: 0f be 54 24 18 movsbl 0x18(%esp),%edx 58: 0f be 44 24 14 movsbl 0x14(%esp),%eax 5d: 8d 04 02 lea (%edx,%eax,1),%eax 60: 0f be d0 movsbl %al,%edx 63: 39 d0 cmp %edx,%eax 65: 0f 95 c0 setne %al 68: 83 c4 10 add $0x10,%esp 6b: c3 ret With the straight (int8_t) cast you get 50: 0f be 54 24 08 movsbl 0x8(%esp),%edx 55: 0f be 44 24 04 movsbl 0x4(%esp),%eax 5a: 8d 04 02 lea (%edx,%eax,1),%eax 5d: 0f be d0 movsbl %al,%edx 60: 39 c2 cmp %eax,%edx 62: 0f 95 c0 setne %al 65: c3 ret What's with the extra add/sub of ESP? /Ulf