1 /* { dg-require-effective-target int32plus } */
2 
3 typedef long unsigned int size_t;
4 extern void *memset (void *__s, int __c, size_t __n) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1)));
5 
6 static void
encode(words,low,hi)7 encode (words, low, hi)
8      long *words;
9      unsigned long low;
10      long hi;
11 {
12   words[0] = ((low) & (((unsigned long) 1 << (sizeof(unsigned long) / 2)) - 1));
13   words[1] = ((unsigned long) (low) >> sizeof(unsigned long) / 2);
14   words[2] = ((hi) & (((unsigned long) 1 << (sizeof(unsigned long) / 2)) - 1));
15   words[3] = ((unsigned long) (hi) >> sizeof(unsigned long) / 2);
16 }
17 
18 static void
decode(words,low,hi)19 decode (words, low, hi)
20      long *words;
21      unsigned long *low;
22      long *hi;
23 {
24   *low = words[0] + words[1] * ((unsigned long) 1 << sizeof(unsigned long) / 2);
25   *hi = words[2] + words[3] * ((unsigned long) 1 << sizeof(unsigned long) / 2);
26 }
27 
28 int
neg_double(l1,h1,lv,hv)29 neg_double (l1, h1, lv, hv)
30      unsigned long l1;
31      long h1;
32      unsigned long *lv;
33      long *hv;
34 {
35   if (l1 == 0)
36     {
37       *lv = 0;
38       *hv = - h1;
39       return (*hv & h1) < 0;
40     }
41   else
42     {
43       *lv = -l1;
44       *hv = ~h1;
45       return 0;
46     }
47 }
48 
49 int
add_double(l1,h1,l2,h2,lv,hv)50 add_double (l1, h1, l2, h2, lv, hv)
51      unsigned long l1, l2;
52      long h1, h2;
53      unsigned long *lv;
54      long *hv;
55 {
56   unsigned long l;
57   long h;
58 
59   l = l1 + l2;
60   h = h1 + h2 + (l < l1);
61 
62   *lv = l;
63   *hv = h;
64   return ((~((h1) ^ (h2)) & ((h1) ^ (h))) < 0);
65 }
66 
67 int
mul_double(l1,h1,l2,h2,lv,hv)68 mul_double (l1, h1, l2, h2, lv, hv)
69      unsigned long l1, l2;
70      long h1, h2;
71      unsigned long *lv;
72      long *hv;
73 {
74   long arg1[4];
75   long arg2[4];
76   long prod[4 * 2];
77   unsigned long carry;
78   int i, j, k;
79   unsigned long toplow, neglow;
80   long tophigh, neghigh;
81 
82   encode (arg1, l1, h1);
83   encode (arg2, l2, h2);
84 
85   memset ((char *) prod, 0, sizeof prod);
86 
87   for (i = 0; i < 4; i++)
88     {
89       carry = 0;
90       for (j = 0; j < 4; j++)
91 	{
92 	  k = i + j;
93 
94 	  carry += arg1[i] * arg2[j];
95 
96 	  carry += prod[k];
97 	  prod[k] = ((carry) & (((unsigned long) 1 << (sizeof(unsigned long) / 2)) - 1));
98 	  carry = ((unsigned long) (carry) >> sizeof(unsigned long) / 2);
99 	}
100       prod[i + 4] = carry;
101     }
102 
103   decode (prod, lv, hv);
104 
105 
106 
107   decode (prod + 4, &toplow, &tophigh);
108   if (h1 < 0)
109     {
110       neg_double (l2, h2, &neglow, &neghigh);
111       add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);
112     }
113   if (h2 < 0)
114     {
115       neg_double (l1, h1, &neglow, &neghigh);
116       add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);
117     }
118   return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0;
119 }
120