]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/libgcc2.c
2003-02-03 Ranjit Mathew <rmathew@hotmail.com>
[thirdparty/gcc.git] / gcc / libgcc2.c
CommitLineData
62c63f32 1/* More subroutines needed by GCC output code on some machines. */
2/* Compile this one with gcc. */
7429c938 3/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
9cfab531 4 2000, 2001, 2002 Free Software Foundation, Inc.
62c63f32 5
f12b58b3 6This file is part of GCC.
62c63f32 7
f12b58b3 8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
62c63f32 12
4c9b6e71 13In addition to the permissions in the GNU General Public License, the
14Free Software Foundation gives you unlimited permission to link the
15compiled version of this file into combinations with other programs,
16and to distribute those combinations without any restriction coming
17from the use of this file. (The General Public License restrictions
18do apply in other respects; for example, they cover modification of
19the file, and distribution when not linked into a combine
20executable.)
21
f12b58b3 22GCC is distributed in the hope that it will be useful, but WITHOUT ANY
23WARRANTY; without even the implied warranty of MERCHANTABILITY or
24FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25for more details.
62c63f32 26
27You should have received a copy of the GNU General Public License
f12b58b3 28along with GCC; see the file COPYING. If not, write to the Free
29Software Foundation, 59 Temple Place - Suite 330, Boston, MA
3002111-1307, USA. */
62c63f32 31
395d450a 32
33/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
34 supposedly valid even though this is a "target" file. */
35#include "auto-host.h"
36
62c63f32 37/* It is incorrect to include config.h here, because this file is being
38 compiled for the target, and hence definitions concerning only the host
39 do not apply. */
c538053c 40#include "tconfig.h"
069631e1 41#include "tsystem.h"
805e22b2 42#include "coretypes.h"
43#include "tm.h"
8c304688 44
62c63f32 45/* Don't use `fancy_abort' here even if config.h says to use it. */
46#ifdef abort
47#undef abort
48#endif
49
395d450a 50#ifdef HAVE_GAS_HIDDEN
51#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
52#else
53#define ATTRIBUTE_HIDDEN
54#endif
55
b1e341a2 56#include "libgcc2.h"
62c63f32 57\f
856ba90e 58#ifdef DECLARE_LIBRARY_RENAMES
59 DECLARE_LIBRARY_RENAMES
60#endif
61
f4dbfb4e 62#if defined (L_negdi2)
e40ae714 63DWtype
64__negdi2 (DWtype u)
65{
66 DWunion w;
67 DWunion uu;
68
69 uu.ll = u;
70
71 w.s.low = -uu.s.low;
72 w.s.high = -uu.s.high - ((UWtype) w.s.low > 0);
73
74 return w.ll;
75}
76#endif
bec2d490 77
78#ifdef L_addvsi3
578dc367 79Wtype
80__addvsi3 (Wtype a, Wtype b)
bec2d490 81{
578dc367 82 Wtype w;
bec2d490 83
84 w = a + b;
85
86 if (b >= 0 ? w < a : w > a)
87 abort ();
88
89 return w;
87e97de6 90}
e40ae714 91#endif
bec2d490 92\f
93#ifdef L_addvdi3
578dc367 94DWtype
95__addvdi3 (DWtype a, DWtype b)
bec2d490 96{
578dc367 97 DWtype w;
bec2d490 98
99 w = a + b;
100
101 if (b >= 0 ? w < a : w > a)
102 abort ();
103
104 return w;
105}
106#endif
107\f
108#ifdef L_subvsi3
578dc367 109Wtype
110__subvsi3 (Wtype a, Wtype b)
bec2d490 111{
112#ifdef L_addvsi3
113 return __addvsi3 (a, (-b));
114#else
578dc367 115 DWtype w;
bec2d490 116
117 w = a - b;
118
119 if (b >= 0 ? w > a : w < a)
120 abort ();
121
122 return w;
123#endif
124}
125#endif
126\f
127#ifdef L_subvdi3
578dc367 128DWtype
129__subvdi3 (DWtype a, DWtype b)
bec2d490 130{
131#ifdef L_addvdi3
132 return (a, (-b));
133#else
578dc367 134 DWtype w;
bec2d490 135
136 w = a - b;
137
138 if (b >= 0 ? w > a : w < a)
139 abort ();
140
141 return w;
142#endif
143}
144#endif
145\f
146#ifdef L_mulvsi3
578dc367 147Wtype
148__mulvsi3 (Wtype a, Wtype b)
bec2d490 149{
578dc367 150 DWtype w;
bec2d490 151
152 w = a * b;
153
b0cf1b49 154 if (((a >= 0) == (b >= 0)) ? w < 0 : w > 0)
bec2d490 155 abort ();
156
157 return w;
158}
159#endif
160\f
161#ifdef L_negvsi2
578dc367 162Wtype
163__negvsi2 (Wtype a)
bec2d490 164{
8851e806 165 Wtype w;
bec2d490 166
8851e806 167 w = -a;
bec2d490 168
169 if (a >= 0 ? w > 0 : w < 0)
170 abort ();
171
172 return w;
173}
174#endif
175\f
176#ifdef L_negvdi2
578dc367 177DWtype
178__negvdi2 (DWtype a)
bec2d490 179{
8851e806 180 DWtype w;
bec2d490 181
8851e806 182 w = -a;
bec2d490 183
184 if (a >= 0 ? w > 0 : w < 0)
185 abort ();
186
8851e806 187 return w;
bec2d490 188}
189#endif
190\f
191#ifdef L_absvsi2
578dc367 192Wtype
193__absvsi2 (Wtype a)
bec2d490 194{
8851e806 195 Wtype w = a;
bec2d490 196
8851e806 197 if (a < 0)
bec2d490 198#ifdef L_negvsi2
8851e806 199 w = __negvsi2 (a);
bec2d490 200#else
8851e806 201 w = -a;
bec2d490 202
8851e806 203 if (w < 0)
204 abort ();
bec2d490 205#endif
206
207 return w;
208}
209#endif
210\f
211#ifdef L_absvdi2
578dc367 212DWtype
213__absvdi2 (DWtype a)
bec2d490 214{
8851e806 215 DWtype w = a;
bec2d490 216
8851e806 217 if (a < 0)
bec2d490 218#ifdef L_negvsi2
8851e806 219 w = __negvsi2 (a);
bec2d490 220#else
8851e806 221 w = -a;
bec2d490 222
8851e806 223 if (w < 0)
224 abort ();
bec2d490 225#endif
226
8851e806 227 return w;
bec2d490 228}
229#endif
230\f
231#ifdef L_mulvdi3
578dc367 232DWtype
233__mulvdi3 (DWtype u, DWtype v)
bec2d490 234{
8851e806 235 DWtype w;
bec2d490 236
237 w = u * v;
238
e40ae714 239 if (((u >= 0) == (v >= 0)) ? w < 0 : w > 0)
bec2d490 240 abort ();
241
242 return w;
243}
244#endif
245\f
62c63f32 246
b903337a 247/* Unless shift functions are defined with full ANSI prototypes,
4f195a89 248 parameter b will be promoted to int if word_type is smaller than an int. */
62c63f32 249#ifdef L_lshrdi3
cf378360 250DWtype
251__lshrdi3 (DWtype u, word_type b)
62c63f32 252{
cf378360 253 DWunion w;
60a744a6 254 word_type bm;
cf378360 255 DWunion uu;
62c63f32 256
257 if (b == 0)
258 return u;
259
260 uu.ll = u;
261
cf378360 262 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
62c63f32 263 if (bm <= 0)
264 {
265 w.s.high = 0;
d1138980 266 w.s.low = (UWtype) uu.s.high >> -bm;
62c63f32 267 }
268 else
269 {
d1138980 270 UWtype carries = (UWtype) uu.s.high << bm;
271
272 w.s.high = (UWtype) uu.s.high >> b;
273 w.s.low = ((UWtype) uu.s.low >> b) | carries;
62c63f32 274 }
275
276 return w.ll;
277}
278#endif
279
280#ifdef L_ashldi3
cf378360 281DWtype
282__ashldi3 (DWtype u, word_type b)
62c63f32 283{
cf378360 284 DWunion w;
60a744a6 285 word_type bm;
cf378360 286 DWunion uu;
62c63f32 287
288 if (b == 0)
289 return u;
290
291 uu.ll = u;
292
cf378360 293 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
62c63f32 294 if (bm <= 0)
295 {
296 w.s.low = 0;
d1138980 297 w.s.high = (UWtype) uu.s.low << -bm;
62c63f32 298 }
299 else
300 {
d1138980 301 UWtype carries = (UWtype) uu.s.low >> bm;
302
303 w.s.low = (UWtype) uu.s.low << b;
304 w.s.high = ((UWtype) uu.s.high << b) | carries;
62c63f32 305 }
306
307 return w.ll;
308}
309#endif
310
311#ifdef L_ashrdi3
cf378360 312DWtype
313__ashrdi3 (DWtype u, word_type b)
62c63f32 314{
cf378360 315 DWunion w;
60a744a6 316 word_type bm;
cf378360 317 DWunion uu;
62c63f32 318
319 if (b == 0)
320 return u;
321
322 uu.ll = u;
323
cf378360 324 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
62c63f32 325 if (bm <= 0)
326 {
327 /* w.s.high = 1..1 or 0..0 */
cf378360 328 w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 1);
62c63f32 329 w.s.low = uu.s.high >> -bm;
330 }
331 else
332 {
d1138980 333 UWtype carries = (UWtype) uu.s.high << bm;
334
62c63f32 335 w.s.high = uu.s.high >> b;
d1138980 336 w.s.low = ((UWtype) uu.s.low >> b) | carries;
62c63f32 337 }
338
339 return w.ll;
340}
341#endif
342\f
5e4e1583 343#ifdef L_ffsdi2
6a08d0ab 344Wtype
cf378360 345__ffsdi2 (DWtype u)
5e4e1583 346{
9ce1b52b 347 DWunion uu;
348 UWtype word, count, add;
349
5e4e1583 350 uu.ll = u;
9ce1b52b 351 if (uu.s.low != 0)
352 word = uu.s.low, add = 0;
353 else if (uu.s.high != 0)
354 word = uu.s.high, add = BITS_PER_UNIT * sizeof (Wtype);
355 else
356 return 0;
357
358 count_trailing_zeros (count, word);
359 return count + add + 1;
5e4e1583 360}
361#endif
362\f
62c63f32 363#ifdef L_muldi3
cf378360 364DWtype
365__muldi3 (DWtype u, DWtype v)
62c63f32 366{
cf378360 367 DWunion w;
368 DWunion uu, vv;
62c63f32 369
370 uu.ll = u,
371 vv.ll = v;
372
373 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
cf378360 374 w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
375 + (UWtype) uu.s.high * (UWtype) vv.s.low);
62c63f32 376
377 return w.ll;
378}
379#endif
380\f
1b3950b9 381#if (defined (L_udivdi3) || defined (L_divdi3) || \
382 defined (L_umoddi3) || defined (L_moddi3))
6b9d1b54 383#if defined (sdiv_qrnnd)
1b3950b9 384#define L_udiv_w_sdiv
385#endif
6b9d1b54 386#endif
1b3950b9 387
a46ef09f 388#ifdef L_udiv_w_sdiv
b10877f3 389#if defined (sdiv_qrnnd)
1b3950b9 390#if (defined (L_udivdi3) || defined (L_divdi3) || \
391 defined (L_umoddi3) || defined (L_moddi3))
9dae5ac3 392static inline __attribute__ ((__always_inline__))
1b3950b9 393#endif
cf378360 394UWtype
395__udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
ba628a68 396{
cf378360 397 UWtype q, r;
398 UWtype c0, c1, b1;
ba628a68 399
cf378360 400 if ((Wtype) d >= 0)
ba628a68 401 {
cf378360 402 if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1)))
ba628a68 403 {
404 /* dividend, divisor, and quotient are nonnegative */
405 sdiv_qrnnd (q, r, a1, a0, d);
406 }
407 else
408 {
409 /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
cf378360 410 sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1));
ba628a68 411 /* Divide (c1*2^32 + c0) by d */
412 sdiv_qrnnd (q, r, c1, c0, d);
413 /* Add 2^31 to quotient */
cf378360 414 q += (UWtype) 1 << (W_TYPE_SIZE - 1);
ba628a68 415 }
416 }
417 else
418 {
419 b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
420 c1 = a1 >> 1; /* A/2 */
cf378360 421 c0 = (a1 << (W_TYPE_SIZE - 1)) + (a0 >> 1);
ba628a68 422
423 if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
424 {
425 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
426
427 r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
428 if ((d & 1) != 0)
429 {
430 if (r >= q)
431 r = r - q;
432 else if (q - r <= d)
433 {
434 r = r - q + d;
435 q--;
436 }
437 else
438 {
439 r = r - q + 2*d;
440 q -= 2;
441 }
442 }
443 }
444 else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
445 {
446 c1 = (b1 - 1) - c1;
447 c0 = ~c0; /* logical NOT */
448
449 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
450
451 q = ~q; /* (A/2)/b1 */
452 r = (b1 - 1) - r;
453
454 r = 2*r + (a0 & 1); /* A/(2*b1) */
455
456 if ((d & 1) != 0)
457 {
458 if (r >= q)
459 r = r - q;
460 else if (q - r <= d)
461 {
462 r = r - q + d;
463 q--;
464 }
465 else
466 {
467 r = r - q + 2*d;
468 q -= 2;
469 }
470 }
471 }
472 else /* Implies c1 = b1 */
473 { /* Hence a1 = d - 1 = 2*b1 - 1 */
474 if (a0 >= -d)
475 {
476 q = -1;
477 r = a0 + d;
478 }
479 else
480 {
481 q = -2;
482 r = a0 + 2*d;
483 }
484 }
485 }
486
487 *rp = r;
488 return q;
489}
b10877f3 490#else
491/* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
cf378360 492UWtype
493__udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)),
494 UWtype a1 __attribute__ ((__unused__)),
495 UWtype a0 __attribute__ ((__unused__)),
496 UWtype d __attribute__ ((__unused__)))
73439ee0 497{
498 return 0;
499}
b10877f3 500#endif
ba628a68 501#endif
502\f
a47053cf 503#if (defined (L_udivdi3) || defined (L_divdi3) || \
504 defined (L_umoddi3) || defined (L_moddi3))
505#define L_udivmoddi4
506#endif
507
9ce1b52b 508#ifdef L_clz
509const UQItype __clz_tab[] =
62c63f32 510{
511 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
512 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
513 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
514 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
515 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
516 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
517 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
518 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
519};
9ce1b52b 520#endif
6a08d0ab 521\f
522#ifdef L_clzsi2
523Wtype
524__clzsi2 (USItype x)
525{
395d450a 526 UWtype w = x;
527 Wtype ret;
6a08d0ab 528
395d450a 529 count_leading_zeros (ret, w);
530 ret -= (sizeof(w) - sizeof(x)) * BITS_PER_UNIT;
531
532 return ret;
6a08d0ab 533}
534#endif
535\f
536#ifdef L_clzdi2
537Wtype
538__clzdi2 (UDItype x)
539{
395d450a 540 UWtype word;
541 Wtype ret, add;
542
543 if (sizeof(x) > sizeof(word))
544 {
545 DWunion uu;
6a08d0ab 546
395d450a 547 uu.ll = x;
548 if (uu.s.high)
549 word = uu.s.high, add = 0;
550 else
551 word = uu.s.low, add = W_TYPE_SIZE;
552 }
553 else
554 word = x, add = (Wtype)(sizeof(x) - sizeof(word)) * BITS_PER_UNIT;
6a08d0ab 555
395d450a 556 count_leading_zeros (ret, word);
557 return ret + add;
6a08d0ab 558}
559#endif
560\f
561#ifdef L_ctzsi2
562Wtype
563__ctzsi2 (USItype x)
564{
395d450a 565 Wtype ret;
6a08d0ab 566
395d450a 567 count_trailing_zeros (ret, x);
6a08d0ab 568
395d450a 569 return ret;
6a08d0ab 570}
571#endif
572\f
573#ifdef L_ctzdi2
574Wtype
575__ctzdi2 (UDItype x)
576{
395d450a 577 UWtype word;
578 Wtype ret, add;
579
580 if (sizeof(x) > sizeof(word))
581 {
582 DWunion uu;
6a08d0ab 583
395d450a 584 uu.ll = x;
585 if (uu.s.low)
586 word = uu.s.low, add = 0;
587 else
588 word = uu.s.high, add = W_TYPE_SIZE;
589 }
590 else
591 word = x, add = 0;
6a08d0ab 592
395d450a 593 count_trailing_zeros (ret, word);
594 return ret + add;
6a08d0ab 595}
596#endif
597
395d450a 598#if (defined (L_popcountsi2) || defined (L_popcountdi2) \
599 || defined (L_popcount_tab))
600extern const UQItype __popcount_tab[] ATTRIBUTE_HIDDEN;
6a08d0ab 601#endif
602
603#ifdef L_popcount_tab
604const UQItype __popcount_tab[] =
605{
606 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
607 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
608 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
609 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
610 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
611 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
612 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
613 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
614};
615#endif
616\f
617#ifdef L_popcountsi2
618Wtype
619__popcountsi2 (USItype x)
620{
621 return __popcount_tab[(x >> 0) & 0xff]
622 + __popcount_tab[(x >> 8) & 0xff]
623 + __popcount_tab[(x >> 16) & 0xff]
624 + __popcount_tab[(x >> 24) & 0xff];
625}
626#endif
627\f
628#ifdef L_popcountdi2
629Wtype
630__popcountdi2 (UDItype x)
631{
632 return __popcount_tab[(x >> 0) & 0xff]
633 + __popcount_tab[(x >> 8) & 0xff]
634 + __popcount_tab[(x >> 16) & 0xff]
635 + __popcount_tab[(x >> 24) & 0xff]
636 + __popcount_tab[(x >> 32) & 0xff]
637 + __popcount_tab[(x >> 40) & 0xff]
638 + __popcount_tab[(x >> 48) & 0xff]
639 + __popcount_tab[(x >> 56) & 0xff];
640}
641#endif
642\f
643#ifdef L_paritysi2
644Wtype
645__paritysi2 (USItype x)
646{
395d450a 647 UWtype nx = x;
648 nx ^= nx >> 16;
649 nx ^= nx >> 8;
650 nx ^= nx >> 4;
651 nx ^= nx >> 2;
652 nx ^= nx >> 1;
653 return nx & 1;
6a08d0ab 654}
655#endif
656\f
657#ifdef L_paritydi2
658Wtype
659__paritydi2 (UDItype x)
660{
395d450a 661 UWtype nx = x ^ (x >> 32);
6a08d0ab 662 nx ^= nx >> 16;
663 nx ^= nx >> 8;
395d450a 664 nx ^= nx >> 4;
665 nx ^= nx >> 2;
666 nx ^= nx >> 1;
667 return nx & 1;
6a08d0ab 668}
669#endif
9ce1b52b 670
671#ifdef L_udivmoddi4
62c63f32 672
a47053cf 673#if (defined (L_udivdi3) || defined (L_divdi3) || \
674 defined (L_umoddi3) || defined (L_moddi3))
9dae5ac3 675static inline __attribute__ ((__always_inline__))
a47053cf 676#endif
cf378360 677UDWtype
678__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
62c63f32 679{
cf378360 680 DWunion ww;
681 DWunion nn, dd;
682 DWunion rr;
683 UWtype d0, d1, n0, n1, n2;
684 UWtype q0, q1;
685 UWtype b, bm;
62c63f32 686
687 nn.ll = n;
688 dd.ll = d;
689
690 d0 = dd.s.low;
691 d1 = dd.s.high;
692 n0 = nn.s.low;
693 n1 = nn.s.high;
694
695#if !UDIV_NEEDS_NORMALIZATION
696 if (d1 == 0)
697 {
698 if (d0 > n1)
699 {
700 /* 0q = nn / 0D */
701
702 udiv_qrnnd (q0, n0, n1, n0, d0);
703 q1 = 0;
704
705 /* Remainder in n0. */
706 }
707 else
708 {
709 /* qq = NN / 0d */
710
711 if (d0 == 0)
712 d0 = 1 / d0; /* Divide intentionally by zero. */
713
714 udiv_qrnnd (q1, n1, 0, n1, d0);
715 udiv_qrnnd (q0, n0, n1, n0, d0);
716
717 /* Remainder in n0. */
718 }
719
720 if (rp != 0)
721 {
722 rr.s.low = n0;
723 rr.s.high = 0;
724 *rp = rr.ll;
725 }
726 }
727
728#else /* UDIV_NEEDS_NORMALIZATION */
729
730 if (d1 == 0)
731 {
732 if (d0 > n1)
733 {
734 /* 0q = nn / 0D */
735
736 count_leading_zeros (bm, d0);
737
738 if (bm != 0)
739 {
740 /* Normalize, i.e. make the most significant bit of the
741 denominator set. */
742
743 d0 = d0 << bm;
cf378360 744 n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
62c63f32 745 n0 = n0 << bm;
746 }
747
748 udiv_qrnnd (q0, n0, n1, n0, d0);
749 q1 = 0;
750
751 /* Remainder in n0 >> bm. */
752 }
753 else
754 {
755 /* qq = NN / 0d */
756
757 if (d0 == 0)
758 d0 = 1 / d0; /* Divide intentionally by zero. */
759
760 count_leading_zeros (bm, d0);
761
762 if (bm == 0)
763 {
764 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
765 conclude (the most significant bit of n1 is set) /\ (the
766 leading quotient digit q1 = 1).
767
768 This special case is necessary, not an optimization.
cf378360 769 (Shifts counts of W_TYPE_SIZE are undefined.) */
62c63f32 770
771 n1 -= d0;
772 q1 = 1;
773 }
774 else
775 {
776 /* Normalize. */
777
cf378360 778 b = W_TYPE_SIZE - bm;
62c63f32 779
780 d0 = d0 << bm;
781 n2 = n1 >> b;
782 n1 = (n1 << bm) | (n0 >> b);
783 n0 = n0 << bm;
784
785 udiv_qrnnd (q1, n1, n2, n1, d0);
786 }
787
a92771b8 788 /* n1 != d0... */
62c63f32 789
790 udiv_qrnnd (q0, n0, n1, n0, d0);
791
792 /* Remainder in n0 >> bm. */
793 }
794
795 if (rp != 0)
796 {
797 rr.s.low = n0 >> bm;
798 rr.s.high = 0;
799 *rp = rr.ll;
800 }
801 }
802#endif /* UDIV_NEEDS_NORMALIZATION */
803
804 else
805 {
806 if (d1 > n1)
807 {
808 /* 00 = nn / DD */
809
810 q0 = 0;
811 q1 = 0;
812
813 /* Remainder in n1n0. */
814 if (rp != 0)
815 {
816 rr.s.low = n0;
817 rr.s.high = n1;
818 *rp = rr.ll;
819 }
820 }
821 else
822 {
823 /* 0q = NN / dd */
824
825 count_leading_zeros (bm, d1);
826 if (bm == 0)
827 {
828 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
829 conclude (the most significant bit of n1 is set) /\ (the
830 quotient digit q0 = 0 or 1).
831
832 This special case is necessary, not an optimization. */
833
834 /* The condition on the next line takes advantage of that
835 n1 >= d1 (true due to program flow). */
836 if (n1 > d1 || n0 >= d0)
837 {
838 q0 = 1;
839 sub_ddmmss (n1, n0, n1, n0, d1, d0);
840 }
841 else
842 q0 = 0;
843
844 q1 = 0;
845
846 if (rp != 0)
847 {
848 rr.s.low = n0;
849 rr.s.high = n1;
850 *rp = rr.ll;
851 }
852 }
853 else
854 {
cf378360 855 UWtype m1, m0;
62c63f32 856 /* Normalize. */
857
cf378360 858 b = W_TYPE_SIZE - bm;
62c63f32 859
860 d1 = (d1 << bm) | (d0 >> b);
861 d0 = d0 << bm;
862 n2 = n1 >> b;
863 n1 = (n1 << bm) | (n0 >> b);
864 n0 = n0 << bm;
865
866 udiv_qrnnd (q0, n1, n2, n1, d1);
867 umul_ppmm (m1, m0, q0, d0);
868
869 if (m1 > n1 || (m1 == n1 && m0 > n0))
870 {
871 q0--;
872 sub_ddmmss (m1, m0, m1, m0, d1, d0);
873 }
874
875 q1 = 0;
876
877 /* Remainder in (n1n0 - m1m0) >> bm. */
878 if (rp != 0)
879 {
880 sub_ddmmss (n1, n0, n1, n0, m1, m0);
881 rr.s.low = (n1 << b) | (n0 >> bm);
882 rr.s.high = n1 >> bm;
883 *rp = rr.ll;
884 }
885 }
886 }
887 }
888
889 ww.s.low = q0;
890 ww.s.high = q1;
891 return ww.ll;
892}
893#endif
894
895#ifdef L_divdi3
cf378360 896DWtype
897__divdi3 (DWtype u, DWtype v)
62c63f32 898{
60a744a6 899 word_type c = 0;
cf378360 900 DWunion uu, vv;
901 DWtype w;
62c63f32 902
903 uu.ll = u;
904 vv.ll = v;
905
906 if (uu.s.high < 0)
907 c = ~c,
f4dbfb4e 908 uu.ll = -uu.ll;
62c63f32 909 if (vv.s.high < 0)
910 c = ~c,
f4dbfb4e 911 vv.ll = -vv.ll;
62c63f32 912
cf378360 913 w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
62c63f32 914 if (c)
f4dbfb4e 915 w = -w;
62c63f32 916
917 return w;
918}
919#endif
920
921#ifdef L_moddi3
cf378360 922DWtype
923__moddi3 (DWtype u, DWtype v)
62c63f32 924{
60a744a6 925 word_type c = 0;
cf378360 926 DWunion uu, vv;
927 DWtype w;
62c63f32 928
929 uu.ll = u;
930 vv.ll = v;
931
932 if (uu.s.high < 0)
933 c = ~c,
f4dbfb4e 934 uu.ll = -uu.ll;
62c63f32 935 if (vv.s.high < 0)
f4dbfb4e 936 vv.ll = -vv.ll;
62c63f32 937
938 (void) __udivmoddi4 (uu.ll, vv.ll, &w);
939 if (c)
f4dbfb4e 940 w = -w;
62c63f32 941
942 return w;
943}
944#endif
945
946#ifdef L_umoddi3
cf378360 947UDWtype
948__umoddi3 (UDWtype u, UDWtype v)
62c63f32 949{
cf378360 950 UDWtype w;
62c63f32 951
952 (void) __udivmoddi4 (u, v, &w);
953
954 return w;
955}
956#endif
957
958#ifdef L_udivdi3
cf378360 959UDWtype
960__udivdi3 (UDWtype n, UDWtype d)
62c63f32 961{
cf378360 962 return __udivmoddi4 (n, d, (UDWtype *) 0);
62c63f32 963}
964#endif
965\f
966#ifdef L_cmpdi2
61d95568 967word_type
cf378360 968__cmpdi2 (DWtype a, DWtype b)
62c63f32 969{
cf378360 970 DWunion au, bu;
62c63f32 971
972 au.ll = a, bu.ll = b;
973
974 if (au.s.high < bu.s.high)
975 return 0;
976 else if (au.s.high > bu.s.high)
977 return 2;
cf378360 978 if ((UWtype) au.s.low < (UWtype) bu.s.low)
62c63f32 979 return 0;
cf378360 980 else if ((UWtype) au.s.low > (UWtype) bu.s.low)
62c63f32 981 return 2;
982 return 1;
983}
984#endif
985
986#ifdef L_ucmpdi2
61d95568 987word_type
cf378360 988__ucmpdi2 (DWtype a, DWtype b)
62c63f32 989{
cf378360 990 DWunion au, bu;
62c63f32 991
992 au.ll = a, bu.ll = b;
993
cf378360 994 if ((UWtype) au.s.high < (UWtype) bu.s.high)
62c63f32 995 return 0;
cf378360 996 else if ((UWtype) au.s.high > (UWtype) bu.s.high)
62c63f32 997 return 2;
cf378360 998 if ((UWtype) au.s.low < (UWtype) bu.s.low)
62c63f32 999 return 0;
cf378360 1000 else if ((UWtype) au.s.low > (UWtype) bu.s.low)
62c63f32 1001 return 2;
1002 return 1;
1003}
1004#endif
1005\f
dd84cabc 1006#if defined(L_fixunstfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
cf378360 1007#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1008#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
ade0e71b 1009
cf378360 1010DWtype
d1138980 1011__fixunstfDI (TFtype a)
ade0e71b 1012{
1013 TFtype b;
cf378360 1014 UDWtype v;
ade0e71b 1015
1016 if (a < 0)
1017 return 0;
1018
1019 /* Compute high word of result, as a flonum. */
1020 b = (a / HIGH_WORD_COEFF);
cf378360 1021 /* Convert that to fixed (but not to DWtype!),
ade0e71b 1022 and shift it into the high word. */
cf378360 1023 v = (UWtype) b;
ade0e71b 1024 v <<= WORD_SIZE;
1025 /* Remove high part from the TFtype, leaving the low part as flonum. */
1026 a -= (TFtype)v;
cf378360 1027 /* Convert that to fixed (but not to DWtype!) and add it in.
ade0e71b 1028 Sometimes A comes out negative. This is significant, since
1029 A has more bits than a long int does. */
1030 if (a < 0)
cf378360 1031 v -= (UWtype) (- a);
ade0e71b 1032 else
cf378360 1033 v += (UWtype) a;
ade0e71b 1034 return v;
1035}
1036#endif
1037
dd84cabc 1038#if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
cf378360 1039DWtype
4f195a89 1040__fixtfdi (TFtype a)
ade0e71b 1041{
1042 if (a < 0)
d1138980 1043 return - __fixunstfDI (-a);
1044 return __fixunstfDI (a);
ade0e71b 1045}
1046#endif
1047
dd84cabc 1048#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
cf378360 1049#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1050#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
0e1cc047 1051
cf378360 1052DWtype
d1138980 1053__fixunsxfDI (XFtype a)
0e1cc047 1054{
1055 XFtype b;
cf378360 1056 UDWtype v;
0e1cc047 1057
1058 if (a < 0)
1059 return 0;
1060
1061 /* Compute high word of result, as a flonum. */
1062 b = (a / HIGH_WORD_COEFF);
cf378360 1063 /* Convert that to fixed (but not to DWtype!),
0e1cc047 1064 and shift it into the high word. */
cf378360 1065 v = (UWtype) b;
0e1cc047 1066 v <<= WORD_SIZE;
1067 /* Remove high part from the XFtype, leaving the low part as flonum. */
1068 a -= (XFtype)v;
cf378360 1069 /* Convert that to fixed (but not to DWtype!) and add it in.
0e1cc047 1070 Sometimes A comes out negative. This is significant, since
1071 A has more bits than a long int does. */
1072 if (a < 0)
cf378360 1073 v -= (UWtype) (- a);
0e1cc047 1074 else
cf378360 1075 v += (UWtype) a;
0e1cc047 1076 return v;
1077}
1078#endif
1079
dd84cabc 1080#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
cf378360 1081DWtype
4f195a89 1082__fixxfdi (XFtype a)
0e1cc047 1083{
1084 if (a < 0)
d1138980 1085 return - __fixunsxfDI (-a);
1086 return __fixunsxfDI (a);
0e1cc047 1087}
1088#endif
1089
62c63f32 1090#ifdef L_fixunsdfdi
cf378360 1091#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1092#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
62c63f32 1093
cf378360 1094DWtype
d1138980 1095__fixunsdfDI (DFtype a)
62c63f32 1096{
805e22b2 1097 UWtype hi, lo;
62c63f32 1098
805e22b2 1099 /* Get high part of result. The division here will just moves the radix
1100 point and will not cause any rounding. Then the conversion to integral
1101 type chops result as desired. */
1102 hi = a / HIGH_WORD_COEFF;
62c63f32 1103
805e22b2 1104 /* Get low part of result. Convert `hi' to floating type and scale it back,
1105 then subtract this from the number being converted. This leaves the low
1106 part. Convert that to integral type. */
1107 lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
1108
1109 /* Assemble result from the two parts. */
1110 return ((UDWtype) hi << WORD_SIZE) | lo;
62c63f32 1111}
1112#endif
1113
1114#ifdef L_fixdfdi
cf378360 1115DWtype
4f195a89 1116__fixdfdi (DFtype a)
62c63f32 1117{
1118 if (a < 0)
d1138980 1119 return - __fixunsdfDI (-a);
1120 return __fixunsdfDI (a);
62c63f32 1121}
1122#endif
1123
1124#ifdef L_fixunssfdi
cf378360 1125#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1126#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
62c63f32 1127
cf378360 1128DWtype
d1138980 1129__fixunssfDI (SFtype original_a)
62c63f32 1130{
ade0e71b 1131 /* Convert the SFtype to a DFtype, because that is surely not going
62c63f32 1132 to lose any bits. Some day someone else can write a faster version
ade0e71b 1133 that avoids converting to DFtype, and verify it really works right. */
1134 DFtype a = original_a;
805e22b2 1135 UWtype hi, lo;
62c63f32 1136
805e22b2 1137 /* Get high part of result. The division here will just moves the radix
1138 point and will not cause any rounding. Then the conversion to integral
1139 type chops result as desired. */
1140 hi = a / HIGH_WORD_COEFF;
62c63f32 1141
805e22b2 1142 /* Get low part of result. Convert `hi' to floating type and scale it back,
1143 then subtract this from the number being converted. This leaves the low
1144 part. Convert that to integral type. */
1145 lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
1146
1147 /* Assemble result from the two parts. */
1148 return ((UDWtype) hi << WORD_SIZE) | lo;
62c63f32 1149}
1150#endif
1151
1152#ifdef L_fixsfdi
cf378360 1153DWtype
ade0e71b 1154__fixsfdi (SFtype a)
62c63f32 1155{
1156 if (a < 0)
d1138980 1157 return - __fixunssfDI (-a);
1158 return __fixunssfDI (a);
62c63f32 1159}
1160#endif
1161
dd84cabc 1162#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
cf378360 1163#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1164#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1165#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
0e1cc047 1166
1167XFtype
cf378360 1168__floatdixf (DWtype u)
0e1cc047 1169{
1170 XFtype d;
0e1cc047 1171
cf378360 1172 d = (Wtype) (u >> WORD_SIZE);
0e1cc047 1173 d *= HIGH_HALFWORD_COEFF;
1174 d *= HIGH_HALFWORD_COEFF;
cf378360 1175 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
0e1cc047 1176
997d68fe 1177 return d;
0e1cc047 1178}
1179#endif
1180
dd84cabc 1181#if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
cf378360 1182#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1183#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1184#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
ade0e71b 1185
1186TFtype
cf378360 1187__floatditf (DWtype u)
ade0e71b 1188{
1189 TFtype d;
ade0e71b 1190
cf378360 1191 d = (Wtype) (u >> WORD_SIZE);
ade0e71b 1192 d *= HIGH_HALFWORD_COEFF;
1193 d *= HIGH_HALFWORD_COEFF;
cf378360 1194 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
ade0e71b 1195
997d68fe 1196 return d;
ade0e71b 1197}
1198#endif
1199
62c63f32 1200#ifdef L_floatdidf
cf378360 1201#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1202#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1203#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
62c63f32 1204
ade0e71b 1205DFtype
cf378360 1206__floatdidf (DWtype u)
62c63f32 1207{
ade0e71b 1208 DFtype d;
62c63f32 1209
cf378360 1210 d = (Wtype) (u >> WORD_SIZE);
62c63f32 1211 d *= HIGH_HALFWORD_COEFF;
1212 d *= HIGH_HALFWORD_COEFF;
cf378360 1213 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
62c63f32 1214
997d68fe 1215 return d;
62c63f32 1216}
1217#endif
1218
1219#ifdef L_floatdisf
cf378360 1220#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1221#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1222#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
87e97de6 1223
536f5fb1 1224#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
badfe841 1225#define DF_SIZE DBL_MANT_DIG
1226#define SF_SIZE FLT_MANT_DIG
62c63f32 1227
ade0e71b 1228SFtype
cf378360 1229__floatdisf (DWtype u)
62c63f32 1230{
a06dece2 1231 /* Do the calculation in DFmode
1232 so that we don't lose any of the precision of the high word
1233 while multiplying it. */
1234 DFtype f;
62c63f32 1235
b37ebc51 1236 /* Protect against double-rounding error.
1237 Represent any low-order bits, that might be truncated in DFmode,
1238 by a bit that won't be lost. The bit can go in anywhere below the
1239 rounding position of the SFmode. A fixed mask and bit position
1240 handles all usual configurations. It doesn't handle the case
1241 of 128-bit DImode, however. */
1242 if (DF_SIZE < DI_SIZE
1243 && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1244 {
d1138980 1245#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE))
cf378360 1246 if (! (- ((DWtype) 1 << DF_SIZE) < u
1247 && u < ((DWtype) 1 << DF_SIZE)))
b37ebc51 1248 {
d1138980 1249 if ((UDWtype) u & (REP_BIT - 1))
f9c9dcd7 1250 {
1251 u &= ~ (REP_BIT - 1);
1252 u |= REP_BIT;
1253 }
b37ebc51 1254 }
1255 }
cf378360 1256 f = (Wtype) (u >> WORD_SIZE);
62c63f32 1257 f *= HIGH_HALFWORD_COEFF;
1258 f *= HIGH_HALFWORD_COEFF;
cf378360 1259 f += (UWtype) (u & (HIGH_WORD_COEFF - 1));
62c63f32 1260
997d68fe 1261 return (SFtype) f;
62c63f32 1262}
1263#endif
1264
dd84cabc 1265#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
3873e172 1266/* Reenable the normal types, in case limits.h needs them. */
1267#undef char
1268#undef short
1269#undef int
1270#undef long
1271#undef unsigned
1272#undef float
1273#undef double
35e6d592 1274#undef MIN
1275#undef MAX
ab195728 1276#include <limits.h>
0e1cc047 1277
cf378360 1278UWtype
d1138980 1279__fixunsxfSI (XFtype a)
0e1cc047 1280{
7429c938 1281 if (a >= - (DFtype) Wtype_MIN)
1282 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
cf378360 1283 return (Wtype) a;
0e1cc047 1284}
1285#endif
1286
62c63f32 1287#ifdef L_fixunsdfsi
3873e172 1288/* Reenable the normal types, in case limits.h needs them. */
1289#undef char
1290#undef short
1291#undef int
1292#undef long
1293#undef unsigned
1294#undef float
1295#undef double
35e6d592 1296#undef MIN
1297#undef MAX
ab195728 1298#include <limits.h>
62c63f32 1299
cf378360 1300UWtype
d1138980 1301__fixunsdfSI (DFtype a)
62c63f32 1302{
7429c938 1303 if (a >= - (DFtype) Wtype_MIN)
1304 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
cf378360 1305 return (Wtype) a;
62c63f32 1306}
1307#endif
1308
1309#ifdef L_fixunssfsi
3873e172 1310/* Reenable the normal types, in case limits.h needs them. */
1311#undef char
1312#undef short
1313#undef int
1314#undef long
1315#undef unsigned
1316#undef float
1317#undef double
35e6d592 1318#undef MIN
1319#undef MAX
ab195728 1320#include <limits.h>
62c63f32 1321
cf378360 1322UWtype
d1138980 1323__fixunssfSI (SFtype a)
62c63f32 1324{
7429c938 1325 if (a >= - (SFtype) Wtype_MIN)
1326 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
cf378360 1327 return (Wtype) a;
62c63f32 1328}
1329#endif
1330\f
ade0e71b 1331/* From here on down, the routines use normal data types. */
1332
1333#define SItype bogus_type
1334#define USItype bogus_type
1335#define DItype bogus_type
1336#define UDItype bogus_type
1337#define SFtype bogus_type
1338#define DFtype bogus_type
cf378360 1339#undef Wtype
1340#undef UWtype
1341#undef HWtype
1342#undef UHWtype
1343#undef DWtype
1344#undef UDWtype
ade0e71b 1345
1346#undef char
1347#undef short
1348#undef int
1349#undef long
1350#undef unsigned
1351#undef float
1352#undef double
e674bcb7 1353\f
1354#ifdef L__gcc_bcmp
1355
1356/* Like bcmp except the sign is meaningful.
c3418f42 1357 Result is negative if S1 is less than S2,
e674bcb7 1358 positive if S1 is greater, 0 if S1 and S2 are equal. */
1359
1360int
b1e341a2 1361__gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size)
e674bcb7 1362{
1363 while (size > 0)
1364 {
e4ee4217 1365 unsigned char c1 = *s1++, c2 = *s2++;
e674bcb7 1366 if (c1 != c2)
1367 return c1 - c2;
1368 size--;
1369 }
1370 return 0;
1371}
ade0e71b 1372
0bad1e66 1373#endif
1374\f
1375/* __eprintf used to be used by GCC's private version of <assert.h>.
1376 We no longer provide that header, but this routine remains in libgcc.a
1377 for binary backward compatibility. Note that it is not included in
1378 the shared version of libgcc. */
1379#ifdef L_eprintf
1380#ifndef inhibit_libc
1381
1382#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1383#include <stdio.h>
1384
1385void
1386__eprintf (const char *string, const char *expression,
1387 unsigned int line, const char *filename)
1388{
1389 fprintf (stderr, string, expression, line, filename);
1390 fflush (stderr);
1391 abort ();
1392}
1393
1394#endif
62c63f32 1395#endif
1396
62c63f32 1397\f
62c63f32 1398#ifdef L_clear_cache
1399/* Clear part of an instruction cache. */
1400
1401#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1402
1403void
abbe5a3d 1404__clear_cache (char *beg __attribute__((__unused__)),
1405 char *end __attribute__((__unused__)))
62c63f32 1406{
87e97de6 1407#ifdef CLEAR_INSN_CACHE
efa58f1a 1408 CLEAR_INSN_CACHE (beg, end);
1409#else
62c63f32 1410#ifdef INSN_CACHE_SIZE
1411 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
5233d224 1412 static int initialized;
62c63f32 1413 int offset;
10307b3e 1414 void *start_addr
1415 void *end_addr;
71218a21 1416 typedef (*function_ptr) (void);
62c63f32 1417
1418#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1419 /* It's cheaper to clear the whole cache.
1420 Put in a series of jump instructions so that calling the beginning
1421 of the cache will clear the whole thing. */
1422
1423 if (! initialized)
1424 {
1425 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1426 & -INSN_CACHE_LINE_WIDTH);
1427 int end_ptr = ptr + INSN_CACHE_SIZE;
1428
1429 while (ptr < end_ptr)
1430 {
1431 *(INSTRUCTION_TYPE *)ptr
1432 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1433 ptr += INSN_CACHE_LINE_WIDTH;
1434 }
a92771b8 1435 *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
62c63f32 1436
1437 initialized = 1;
1438 }
1439
1440 /* Call the beginning of the sequence. */
1441 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1442 & -INSN_CACHE_LINE_WIDTH))
1443 ());
1444
1445#else /* Cache is large. */
1446
1447 if (! initialized)
1448 {
1449 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1450 & -INSN_CACHE_LINE_WIDTH);
1451
1452 while (ptr < (int) array + sizeof array)
1453 {
1454 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1455 ptr += INSN_CACHE_LINE_WIDTH;
1456 }
1457
1458 initialized = 1;
1459 }
1460
1461 /* Find the location in array that occupies the same cache line as BEG. */
1462
1463 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1464 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1465 & -INSN_CACHE_PLANE_SIZE)
1466 + offset);
1467
1468 /* Compute the cache alignment of the place to stop clearing. */
1469#if 0 /* This is not needed for gcc's purposes. */
1470 /* If the block to clear is bigger than a cache plane,
87e97de6 1471 we clear the entire cache, and OFFSET is already correct. */
62c63f32 1472 if (end < beg + INSN_CACHE_PLANE_SIZE)
1473#endif
1474 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1475 & -INSN_CACHE_LINE_WIDTH)
1476 & (INSN_CACHE_PLANE_SIZE - 1));
1477
1478#if INSN_CACHE_DEPTH > 1
1479 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1480 if (end_addr <= start_addr)
1481 end_addr += INSN_CACHE_PLANE_SIZE;
1482
1483 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1484 {
1485 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1486 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1487
1488 while (addr != stop)
1489 {
1490 /* Call the return instruction at ADDR. */
1491 ((function_ptr) addr) ();
1492
1493 addr += INSN_CACHE_LINE_WIDTH;
1494 }
1495 }
1496#else /* just one plane */
1497 do
1498 {
1499 /* Call the return instruction at START_ADDR. */
1500 ((function_ptr) start_addr) ();
1501
1502 start_addr += INSN_CACHE_LINE_WIDTH;
1503 }
1504 while ((start_addr % INSN_CACHE_SIZE) != offset);
1505#endif /* just one plane */
1506#endif /* Cache is large */
1507#endif /* Cache exists */
efa58f1a 1508#endif /* CLEAR_INSN_CACHE */
62c63f32 1509}
1510
1511#endif /* L_clear_cache */
1512\f
1513#ifdef L_trampoline
1514
1515/* Jump to a trampoline, loading the static chain address. */
1516
f1959ea2 1517#if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
8e782fcd 1518
71218a21 1519long
1520getpagesize (void)
e30b7e49 1521{
1522#ifdef _ALPHA_
1523 return 8192;
1524#else
1525 return 4096;
1526#endif
1527}
1528
1ec6144c 1529#ifdef __i386__
bdf89453 1530extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
1531#endif
1532
38e911c3 1533int
1534mprotect (char *addr, int len, int prot)
e30b7e49 1535{
1536 int np, op;
1537
38e911c3 1538 if (prot == 7)
1539 np = 0x40;
1540 else if (prot == 5)
1541 np = 0x20;
1542 else if (prot == 4)
1543 np = 0x10;
1544 else if (prot == 3)
1545 np = 0x04;
1546 else if (prot == 1)
1547 np = 0x02;
1548 else if (prot == 0)
1549 np = 0x01;
e30b7e49 1550
1551 if (VirtualProtect (addr, len, np, &op))
1552 return 0;
1553 else
1554 return -1;
e30b7e49 1555}
1556
f1959ea2 1557#endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
e30b7e49 1558
87e97de6 1559#ifdef TRANSFER_FROM_TRAMPOLINE
1560TRANSFER_FROM_TRAMPOLINE
62c63f32 1561#endif
1562
220345e0 1563#ifdef __sysV68__
1564
1565#include <sys/signal.h>
1566#include <errno.h>
1567
1568/* Motorola forgot to put memctl.o in the libp version of libc881.a,
1569 so define it here, because we need it in __clear_insn_cache below */
aaa36d7c 1570/* On older versions of this OS, no memctl or MCT_TEXT are defined;
1571 hence we enable this stuff only if MCT_TEXT is #define'd. */
220345e0 1572
aaa36d7c 1573#ifdef MCT_TEXT
220345e0 1574asm("\n\
1575 global memctl\n\
1576memctl:\n\
1577 movq &75,%d0\n\
1578 trap &0\n\
1579 bcc.b noerror\n\
1580 jmp cerror%\n\
1581noerror:\n\
1582 movq &0,%d0\n\
1583 rts");
aaa36d7c 1584#endif
220345e0 1585
1586/* Clear instruction cache so we can call trampolines on stack.
1587 This is called from FINALIZE_TRAMPOLINE in mot3300.h. */
1588
1589void
71218a21 1590__clear_insn_cache (void)
220345e0 1591{
aaa36d7c 1592#ifdef MCT_TEXT
220345e0 1593 int save_errno;
1594
1595 /* Preserve errno, because users would be surprised to have
aa40f561 1596 errno changing without explicitly calling any system-call. */
220345e0 1597 save_errno = errno;
1598
87e97de6 1599 /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
aa40f561 1600 No need to use an address derived from _start or %sp, as 0 works also. */
220345e0 1601 memctl(0, 4096, MCT_TEXT);
1602 errno = save_errno;
aaa36d7c 1603#endif
220345e0 1604}
1605
1606#endif /* __sysV68__ */
62c63f32 1607#endif /* L_trampoline */
1608\f
e678484c 1609#ifndef __CYGWIN__
62c63f32 1610#ifdef L__main
1611
1612#include "gbl-ctors.h"
0c945479 1613/* Some systems use __main in a way incompatible with its use in gcc, in these
1614 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
1615 give the same symbol without quotes for an alternative entry point. You
a92771b8 1616 must define both, or neither. */
0c945479 1617#ifndef NAME__MAIN
1618#define NAME__MAIN "__main"
1619#define SYMBOL__MAIN __main
1620#endif
62c63f32 1621
8313a782 1622#ifdef INIT_SECTION_ASM_OP
1623#undef HAS_INIT_SECTION
1624#define HAS_INIT_SECTION
1625#endif
1626
1627#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
a6881cf3 1628
1629/* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
1630 code to run constructors. In that case, we need to handle EH here, too. */
1631
eb86c6db 1632#ifdef EH_FRAME_SECTION_NAME
899c9389 1633#include "unwind-dw2-fde.h"
a6881cf3 1634extern unsigned char __EH_FRAME_BEGIN__[];
1635#endif
1636
62c63f32 1637/* Run all the global destructors on exit from the program. */
1638
1639void
71218a21 1640__do_global_dtors (void)
62c63f32 1641{
3a158972 1642#ifdef DO_GLOBAL_DTORS_BODY
1643 DO_GLOBAL_DTORS_BODY;
1644#else
113f9ca7 1645 static func_ptr *p = __DTOR_LIST__ + 1;
1646 while (*p)
1647 {
1648 p++;
1649 (*(p-1)) ();
1650 }
3a158972 1651#endif
eb86c6db 1652#if defined (EH_FRAME_SECTION_NAME) && !defined (HAS_INIT_SECTION)
3b1bfdbe 1653 {
1654 static int completed = 0;
1655 if (! completed)
1656 {
1657 completed = 1;
1658 __deregister_frame_info (__EH_FRAME_BEGIN__);
1659 }
1660 }
a6881cf3 1661#endif
62c63f32 1662}
b7c87ff2 1663#endif
62c63f32 1664
8313a782 1665#ifndef HAS_INIT_SECTION
62c63f32 1666/* Run all the global constructors on entry to the program. */
1667
62c63f32 1668void
71218a21 1669__do_global_ctors (void)
62c63f32 1670{
eb86c6db 1671#ifdef EH_FRAME_SECTION_NAME
a6881cf3 1672 {
1673 static struct object object;
1674 __register_frame_info (__EH_FRAME_BEGIN__, &object);
1675 }
1676#endif
62c63f32 1677 DO_GLOBAL_CTORS_BODY;
bd84a596 1678 atexit (__do_global_dtors);
62c63f32 1679}
8313a782 1680#endif /* no HAS_INIT_SECTION */
62c63f32 1681
8313a782 1682#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
62c63f32 1683/* Subroutine called automatically by `main'.
1684 Compiling a global function named `main'
1685 produces an automatic call to this function at the beginning.
1686
1687 For many systems, this routine calls __do_global_ctors.
1688 For systems which support a .init section we use the .init section
1689 to run __do_global_ctors, so we need not do anything here. */
1690
1691void
0c945479 1692SYMBOL__MAIN ()
62c63f32 1693{
1694 /* Support recursive calls to `main': run initializers just once. */
5233d224 1695 static int initialized;
62c63f32 1696 if (! initialized)
1697 {
1698 initialized = 1;
1699 __do_global_ctors ();
1700 }
1701}
8313a782 1702#endif /* no HAS_INIT_SECTION or INVOKE__main */
62c63f32 1703
1704#endif /* L__main */
e678484c 1705#endif /* __CYGWIN__ */
62c63f32 1706\f
a0f2694a 1707#ifdef L_ctors
62c63f32 1708
1709#include "gbl-ctors.h"
1710
1711/* Provide default definitions for the lists of constructors and
98ae6ed6 1712 destructors, so that we don't get linker errors. These symbols are
1713 intentionally bss symbols, so that gld and/or collect will provide
1714 the right values. */
62c63f32 1715
1716/* We declare the lists here with two elements each,
98ae6ed6 1717 so that they are valid empty lists if no other definition is loaded.
1718
1719 If we are using the old "set" extensions to have the gnu linker
1720 collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
1721 must be in the bss/common section.
1722
1723 Long term no port should use those extensions. But many still do. */
b13ae905 1724#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
e535c327 1725#if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2)
d069195c 1726func_ptr __CTOR_LIST__[2] = {0, 0};
1727func_ptr __DTOR_LIST__[2] = {0, 0};
98ae6ed6 1728#else
1729func_ptr __CTOR_LIST__[2];
1730func_ptr __DTOR_LIST__[2];
1731#endif
b13ae905 1732#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
a0f2694a 1733#endif /* L_ctors */
1734\f
1735#ifdef L_exit
1736
1737#include "gbl-ctors.h"
62c63f32 1738
2fea28a7 1739#ifdef NEED_ATEXIT
2fea28a7 1740
9f030acd 1741#ifndef ON_EXIT
62c63f32 1742
2fea28a7 1743# include <errno.h>
1744
2998886d 1745static func_ptr *atexit_chain = 0;
2fea28a7 1746static long atexit_chain_length = 0;
1747static volatile long last_atexit_chain_slot = -1;
1748
3da2e097 1749int
1750atexit (func_ptr func)
2fea28a7 1751{
1752 if (++last_atexit_chain_slot == atexit_chain_length)
1753 {
1754 atexit_chain_length += 32;
1755 if (atexit_chain)
3223d5a7 1756 atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
1757 * sizeof (func_ptr));
2fea28a7 1758 else
3223d5a7 1759 atexit_chain = (func_ptr *) malloc (atexit_chain_length
1760 * sizeof (func_ptr));
2fea28a7 1761 if (! atexit_chain)
1762 {
1763 atexit_chain_length = 0;
1764 last_atexit_chain_slot = -1;
1765 errno = ENOMEM;
1766 return (-1);
1767 }
1768 }
1769 atexit_chain[last_atexit_chain_slot] = func;
1770 return (0);
1771}
2fea28a7 1772
71218a21 1773extern void _cleanup (void);
1774extern void _exit (int) __attribute__ ((__noreturn__));
62c63f32 1775
87e97de6 1776void
4f195a89 1777exit (int status)
62c63f32 1778{
2fea28a7 1779 if (atexit_chain)
1780 {
1781 for ( ; last_atexit_chain_slot-- >= 0; )
1782 {
1783 (*atexit_chain[last_atexit_chain_slot + 1]) ();
2998886d 1784 atexit_chain[last_atexit_chain_slot + 1] = 0;
2fea28a7 1785 }
1786 free (atexit_chain);
2998886d 1787 atexit_chain = 0;
2fea28a7 1788 }
62c63f32 1789#ifdef EXIT_BODY
1790 EXIT_BODY;
1791#else
1792 _cleanup ();
1793#endif
1794 _exit (status);
1795}
1796
9f030acd 1797#else /* ON_EXIT */
729610a1 1798
3da2e097 1799/* Simple; we just need a wrapper for ON_EXIT. */
1800int
1801atexit (func_ptr func)
729610a1 1802{
3da2e097 1803 return ON_EXIT (func);
729610a1 1804}
3da2e097 1805
9f030acd 1806#endif /* ON_EXIT */
3da2e097 1807#endif /* NEED_ATEXIT */
62c63f32 1808
1809#endif /* L_exit */