1 /* $Id: asm1.h 7697 2006-02-16 17:34:46Z kb $
2 
3 Copyright (C) 2000  The PARI group.
4 
5 This file is part of the PARI/GP package.
6 
7 PARI/GP is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation. It is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY WHATSOEVER.
11 
12 Check the License for details. You should have received a copy of it, along
13 with the package; see the file 'COPYING'. If not, write to the Free Software
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
15 
16 /* This file is a slight adaptation of source code extracted from gmp-3.1.1
17   (from T. Granlund), files longlong.h and gmp-impl.h
18 
19   Copyright (C) 2000 Free Software Foundation, Inc.
20 
21  * FIXME: This file is unused until somebody implements
22  * invert_word(x) = return floor( 2^(2*BIL)/x ) */
23 
24 extern ulong invert_word(ulong);
25 
26 #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
27   do {                                     \
28     ulong __x;                             \
29     __x = (al) - (bl);                     \
30     (sh) = (ah) - (bh) - (__x > (al));     \
31     (sl) = __x;                            \
32   } while (0)
33 
34 #ifdef __GNUC__
35 
36 #define divll(x, y)                                      \
37 ({                                                       \
38   register ulong _di, _x = (x), _y = (y), _q, _ql, _r;   \
39   register ulong _xh, _xl, _k, __hire;                   \
40                                                          \
41   if (_y & 0x8000000000000000UL)                         \
42       { _k = 0; __hire = hiremainder; }                  \
43   else                                                   \
44   {                                                      \
45     _k = bfffo(_y);                                      \
46     __hire = (hiremainder << _k) | (_x >> (64 - _k));    \
47     _x <<= _k; _y <<=  _k;                               \
48   }                                                      \
49   _di = invert_word(_y);                                 \
50   _ql = mulll (__hire, _di);                             \
51   _q = __hire + hiremainder;                             \
52   _xl = mulll(_q, _y); _xh = hiremainder;                \
53   sub_ddmmss (_xh, _r, __hire, _x, _xh, _xl);            \
54   if (_xh != 0)                                          \
55   {                                                      \
56     sub_ddmmss (_xh, _r, _xh, _r, 0, _y); _q += 1;       \
57     if (_xh != 0)                                        \
58       { sub_ddmmss (_xh, _r, _xh, _r, 0, _y); _q += 1; } \
59   }                                                      \
60   if (_r >= _y)                                          \
61     { _r -= _y; _q += 1; }                               \
62   hiremainder = _r >> _k;                                \
63   _q;                                                    \
64 })
65 
66 #else /* __GNUC__ */
67 
68 static ulong
divll(ulong x,ulong y)69 divll(ulong x, ulong y)
70 {
71   register ulong _di, _x = (x), _y = (y), _q, _ql, _r;
72   register ulong _xh, _xl, _k, __hire;
73 
74   if (_y & 0x8000000000000000UL)
75       { _k = 0; __hire = hiremainder; }
76   else
77   {
78     _k = bfffo(_y);
79     __hire = (hiremainder << _k) | (_x >> (64 - _k));
80     _x <<= _k; _y <<=  _k;
81   }
82   _di = invert_word(_y);
83   _ql = mulll (__hire, _di);
84   _q = __hire + hiremainder;
85   _xl = mulll(_q, _y); _xh = hiremainder;
86   sub_ddmmss (_xh, _r, __hire, _x, _xh, _xl);
87   if (_xh != 0)
88   {
89     sub_ddmmss (_xh, _r, _xh, _r, 0, _y); _q += 1;
90     if (_xh != 0)
91       { sub_ddmmss (_xh, _r, _xh, _r, 0, _y); _q += 1; }
92   }
93   if (_r >= _y)
94     { _r -= _y; _q += 1; }
95   hiremainder = _r >> _k;
96   return _q;
97 }
98 
99 #endif /* __GNUC__ */
100