1 /* 64-bit multiplication and division
2 Copyright (C) 1989, 1992-1999, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 #include <bits/wordsize.h>
26 #error This is for 32-bit targets only
29 typedef unsigned int UQItype __attribute__ ((mode (QI)));
30 typedef int SItype __attribute__ ((mode (SI)));
31 typedef unsigned int USItype __attribute__ ((mode (SI)));
32 typedef int DItype __attribute__ ((mode (DI)));
33 typedef unsigned int UDItype __attribute__ ((mode (DI)));
37 #define UWtype USItype
38 #define UHWtype USItype
39 #define UDWtype UDItype
40 #define W_TYPE_SIZE 32
42 #include <stdlib/longlong.h>
44 #if __BYTE_ORDER == __BIG_ENDIAN
45 struct DWstruct { Wtype high, low;};
46 #elif __BYTE_ORDER == __LITTLE_ENDIAN
47 struct DWstruct { Wtype low, high;};
49 #error Unhandled endianity
51 typedef union { struct DWstruct s; DWtype ll; } DWunion;
53 /* Prototypes of exported functions. */
54 extern DWtype __divdi3 (DWtype u, DWtype v);
55 extern DWtype __moddi3 (DWtype u, DWtype v);
56 extern UDWtype __udivdi3 (UDWtype u, UDWtype v);
57 extern UDWtype __umoddi3 (UDWtype u, UDWtype v);
60 __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
65 UWtype d0, d1, n0, n1, n2;
77 #if !UDIV_NEEDS_NORMALIZATION
84 udiv_qrnnd (q0, n0, n1, n0, d0);
87 /* Remainder in n0. */
94 d0 = 1 / d0; /* Divide intentionally by zero. */
96 udiv_qrnnd (q1, n1, 0, n1, d0);
97 udiv_qrnnd (q0, n0, n1, n0, d0);
99 /* Remainder in n0. */
110 #else /* UDIV_NEEDS_NORMALIZATION */
118 count_leading_zeros (bm, d0);
122 /* Normalize, i.e. make the most significant bit of the
126 n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
130 udiv_qrnnd (q0, n0, n1, n0, d0);
133 /* Remainder in n0 >> bm. */
140 d0 = 1 / d0; /* Divide intentionally by zero. */
142 count_leading_zeros (bm, d0);
146 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
147 conclude (the most significant bit of n1 is set) /\ (the
148 leading quotient digit q1 = 1).
150 This special case is necessary, not an optimization.
151 (Shifts counts of W_TYPE_SIZE are undefined.) */
160 b = W_TYPE_SIZE - bm;
164 n1 = (n1 << bm) | (n0 >> b);
167 udiv_qrnnd (q1, n1, n2, n1, d0);
172 udiv_qrnnd (q0, n0, n1, n0, d0);
174 /* Remainder in n0 >> bm. */
184 #endif /* UDIV_NEEDS_NORMALIZATION */
195 /* Remainder in n1n0. */
207 count_leading_zeros (bm, d1);
210 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
211 conclude (the most significant bit of n1 is set) /\ (the
212 quotient digit q0 = 0 or 1).
214 This special case is necessary, not an optimization. */
216 /* The condition on the next line takes advantage of that
217 n1 >= d1 (true due to program flow). */
218 if (n1 > d1 || n0 >= d0)
221 sub_ddmmss (n1, n0, n1, n0, d1, d0);
240 b = W_TYPE_SIZE - bm;
242 d1 = (d1 << bm) | (d0 >> b);
245 n1 = (n1 << bm) | (n0 >> b);
248 udiv_qrnnd (q0, n1, n2, n1, d1);
249 umul_ppmm (m1, m0, q0, d0);
251 if (m1 > n1 || (m1 == n1 && m0 > n0))
254 sub_ddmmss (m1, m0, m1, m0, d1, d0);
259 /* Remainder in (n1n0 - m1m0) >> bm. */
262 sub_ddmmss (n1, n0, n1, n0, m1, m0);
263 rr.s.low = (n1 << b) | (n0 >> bm);
264 rr.s.high = n1 >> bm;
277 __divdi3 (DWtype u, DWtype v)
292 w = __udivmoddi4 (u, v, NULL);
300 __moddi3 (DWtype u, DWtype v)
312 __udivmoddi4 (u, v, &w);
319 __udivdi3 (UDWtype u, UDWtype v)
321 return __udivmoddi4 (u, v, NULL);
325 __umoddi3 (UDWtype u, UDWtype v)
329 __udivmoddi4 (u, v, &w);