bug in longlong.h for aarch64 sub_ddmmss

Vincent Lefevre vincent at vinc17.net
Tue Jun 16 10:55:07 UTC 2020


In longlong.h from GMP 6.2.0:

#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  do {                                                                  \
    if (__builtin_constant_p (bl) && -(UDItype)(bl) < 0x1000)           \
      __asm__ ("adds\t%1, %x4, %5\n\tsbc\t%0, %x2, %x3"                 \
               : "=r,r" (sh), "=&r,&r" (sl)                             \
               : "rZ,rZ" ((UDItype)(ah)), "rZ,rZ" ((UDItype)(bh)),      \
                 "r,Z"   ((UDItype)(al)), "rI,r" (-(UDItype)(bl)) __CLOBBER_CC);\
    else                                                                \
      __asm__ ("subs\t%1, %x4, %5\n\tsbc\t%0, %x2, %x3"                 \
               : "=r,r" (sh), "=&r,&r" (sl)                             \
               : "rZ,rZ" ((UDItype)(ah)), "rZ,rZ" ((UDItype)(bh)),      \
                 "r,Z"   ((UDItype)(al)), "rI,r"  ((UDItype)(bl)) __CLOBBER_CC);\
  } while(0);

I don't understand this code. For instance, on ah=al=bh=bl=0, you
do adds(0,0), which unsets the carry. And since borrow = not(carry),
the sbc(0,0) will return -1.

This is consistent with what I observe in MPFR with

#include "mpfr-test.h"
#include "invsqrt_limb.h"

int main (void)
  mp_limb_t h, l;

  sub_ddmmss (h, l, 0x4000000000000000, 0, 0x4000000000000000, 0);
  printf ("%lx\n", h);
  return 0;

which outputs ffffffffffffffff instead of 0.

Vincent Lefèvre <vincent at vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

More information about the gmp-bugs mailing list