On 2020-06-16 14:47:23 +0200, Torbjorn Granlund wrote:
> Vincent Lefevre <[email protected]> writes:
> 
>   On 2020-06-16 13:40:14 +0200, Torbjorn Granlund wrote:
>   > Vincent Lefevre <[email protected]> writes:
>   > 
>   >   #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);
>   > 
>   > The two - signs ought to be ~, I think.  Let me think a buit more about 
> that.
> 
>   Note that the "else" case, which doesn't have a - sign in its
>   arguments is affected too, AFAIK.
> 
> I cannot follow you here.
> 
> Are you saying that the asm in the else clause is broken too?
> Please explain.

Sorry, it seems OK (I thought that on (0,0), subs and adds would
be equivalent, but the carry out is actually different).

Note that I'm rather surprised to see that the issue disappears
if I add unrelated code. For instance, in the following testcase,
with GCC 9.1.0 -O2, I get "h = 0xffffffffffffffff", which is
incorrect, but if I define V, I get the correct "h = 0x0".

typedef unsigned int UDItype __attribute__ ((mode (DI)));
typedef unsigned long UWtype;
#define W_TYPE_SIZE 64
#define __GMP_DECLSPEC
#define __GMP_GNUC_PREREQ(maj, min) \
  ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#include <stdio.h>
#include "longlong.h"

int v = 0;

int main (void)
{
  volatile unsigned long u0 = 0x4000000000000000, r0 = 0x7ffffffffffffffd;
  unsigned long u, r, h, l;
  u = u0;
  r = r0;
  if (r < 0x8000000000000000)
    r = 0x8000000000000000;
#ifdef V
  if (v)
    fflush (stdout);
#endif
  umul_ppmm (h, l, r, r);
  sub_ddmmss (h, l, u, 0, h, l);
  printf ("h = 0x%lx\n", h);
  return 0;
}

-- 
Vincent Lefèvre <[email protected]> - 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)
_______________________________________________
gmp-bugs mailing list
[email protected]
https://gmplib.org/mailman/listinfo/gmp-bugs

Reply via email to