home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / GCC / GERLIB_DEV08B.LHA / gerlib / gnulib / normal / gnulib2.h < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-12  |  5.4 KB  |  185 lines

  1. /* More subroutines needed by GCC output code on some machines.  */
  2. /* Compile this one with gcc.  */
  3. /* Copyright (C) 1989, 1990 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 1, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /* As a special exception, if you link this library with files
  22.    compiled with GCC to produce an executable, this does not cause
  23.    the resulting executable to be covered by the GNU General Public License.
  24.    This exception does not however invalidate any other reasons why
  25.    the executable file might be covered by the GNU General Public License.  */
  26.  
  27. #include "config.h"
  28. #include <stddef.h>
  29.  
  30. /* In case config.h defined it.  */
  31. #undef abort
  32.  
  33. #ifndef LONG_TYPE_SIZE
  34. #define LONG_TYPE_SIZE (sizeof (long) * BITS_PER_UNIT)
  35. #endif
  36.  
  37. #ifndef SItype
  38. #define SItype long int
  39. #endif
  40.  
  41. /* long long ints are pairs of long ints in the order determined by
  42.    WORDS_BIG_ENDIAN.  */
  43.  
  44. #if WORDS_BIG_ENDIAN
  45.   struct longlong {long high, low;};
  46. #else
  47.   struct longlong {long low, high;};
  48. #endif
  49.  
  50. /* We need this union to unpack/pack longlongs, since we don't have
  51.    any arithmetic yet.  Incoming long long parameters are stored
  52.    into the `ll' field, and the unpacked result is read from the struct
  53.    longlong.  */
  54.  
  55. typedef union
  56. {
  57.   struct longlong s;
  58.   long long ll;
  59. } long_long;
  60.  
  61. /* Internally, long long ints are strings of unsigned shorts in the
  62.    order determined by BYTES_BIG_ENDIAN.  */
  63.  
  64. #define B (1 << (LONG_TYPE_SIZE / 2))
  65. #define lowpart(t) ((unsigned long) (t) % B)
  66. #define highpart(t) ((unsigned long) (t) / B)
  67.  
  68.  
  69. /* Define auxilliary functions for multiplication and division.
  70.    1) __umulsidi3(a,b) multiplies two unsigned long integers A and B,
  71.    and returns a long long product.
  72.    2) div_qrnnd(q,r,n1,n0,d) divides a long long integer, composed by the
  73.    long integers N1 and N0, by D and places the quotient in Q and the
  74.    remainder in R.  If N1 >= D the quotient cannot be represented, and
  75.    the result is undefined.
  76.  
  77.    There's a simple machine instruction for these operations on almost
  78.    all CPUs.  Use them!  */
  79.  
  80. #if defined (L_udivdi3) || defined (L_muldi3)
  81.  
  82. #if defined (__mc68020__)
  83. #define __umulsidi3(u, v)                        \
  84.   ({long_long __w;                            \
  85.     asm ("mulul %3,%1:%0" : "=d" (__w.s.low), "=d" (__w.s.high)        \
  86.      : "%0" (u), "dmsK" (v));                    \
  87.     __w.ll;                                \
  88.   })
  89. #define div_qrnnd(q, r, n1, n0, d) \
  90.   asm ("divul %4,%1:%0" : "=d" (q), "=d" (r) : "0" (n0), "1" (n1), "dmsK" (d))
  91.  
  92. #elif defined (sparc)
  93. unsigned long long __umulsidi3 () asm (".umul");
  94.  
  95. #elif defined (ns32000)
  96. /* Try:
  97. #define __umulsidi3(u, v) \
  98.   ({long long __w;                            \
  99.     asm ("meid %2,%0" : "=g" (__w) : "%0" (u), "g" (v)); __w;        \
  100.   })
  101. */
  102. #define __umulsidi3(u, v) \
  103.   ({long_long __w;                            \
  104.     asm ("movd %2,r0;  meid %3,r0;  movd r0,%0;  movd r1,%1"        \
  105.      : "=g" (__w.s.low), "=g" (__w.s.high)                \
  106.      : "g" (u), "g" (v)                        \
  107.      : "r0", "r1"); __w.ll;                        \
  108.   })
  109. #define div_qrnnd(q, r, n1, n0, d) \
  110.   ({                                    \
  111.     asm ("movd %1,r0;  movd %2,r1;  deid %3,r0;  movd r1,%0"        \
  112.      : "=g" (q) : "g" (n0), "g" (n1), "g" (d) : "r0", "r1");    \
  113.     asm ("movd %1,r0;  movd %2,r1;  deid %3,r0;  movd r0,%0"        \
  114.      : "=g" (r) : "g" (n0), "g" (n1), "g" (d) : "r0", "r1");    \
  115.   })
  116.  
  117. #elif defined (__i386__)
  118. #define __umulsidi3(u, v) \
  119.   ({long_long __w;                            \
  120.     asm ("mull %3" : "=a" (__w.s.low), "=d" (__w.s.high)        \
  121.      : "%0" (u), "rm" (v)); __w.ll;                    \
  122.   })
  123. #define div_qrnnd(quo, rem, n1, n0, den) \
  124.   asm ("divl %4" : "=a" (quo), "=d" (rem) : "0" (n0), "1" (n1), "rm" (den))
  125.  
  126. #endif
  127.  
  128. /* If this machine has no inline assembler, use the C function.  */
  129. #if !defined (__umulsidi3)
  130. static inline unsigned long long
  131. __umulsidi3 (u, v)
  132.      unsigned long u, v;
  133. {
  134.   unsigned long x0, x1, x2, x3;
  135.   unsigned long ulow, vlow, uhigh, vhigh;
  136.   long_long w;
  137.  
  138.   ulow = lowpart (u);
  139.   uhigh = highpart (u);
  140.   vlow = lowpart (v);
  141.   vhigh = highpart (v);
  142.  
  143.   x0 = ulow * vlow;
  144.   x1 = ulow * vhigh + highpart (x0);
  145.   x2 = uhigh * vlow;
  146.   x3 = uhigh * vhigh;
  147.  
  148.   x1 += x2;
  149.   if (x1 < x2)
  150.     x3 += B;
  151.  
  152.   w.s.high = x3 + highpart (x1);
  153.   w.s.low = lowpart (x1) * B + lowpart (x0);
  154.  
  155.   return w.ll;
  156. }
  157. #endif
  158.  
  159. #if !defined (div_qrnnd)
  160.  
  161. /* Defined as a macro because of the two output parameters.  */
  162. #define div_qrnnd(q, r, n1, n0, d) \
  163.   ({                                    \
  164.     unsigned int __d1, __d0, __q1, __q0;                \
  165.     unsigned long __r1, __r0, __m;                    \
  166.     __d1 = highpart (d);                        \
  167.     __d0 = lowpart (d);                            \
  168.     __r1 = (n1) % __d1;                            \
  169.     __q1 = (n1) / __d1;                            \
  170.     __m = (unsigned long) __q1 * __d0;                    \
  171.     __r1 = __r1 * B | highpart (n0);                    \
  172.     while (__r1 < __m)                            \
  173.       __q1--, __r1 += (d);                        \
  174.     __r0 = __r1 % __d1;                            \
  175.     __q0 = __r1 / __d1;                            \
  176.     __m = (unsigned long) __q0 * __d0;                    \
  177.     __r0 = __r0 * B | lowpart (n0);                    \
  178.     while (__r0 < __m)                            \
  179.       __q0--, __r0 += (d);                        \
  180.     (q) = (unsigned long) __q1 * B | __q0;                \
  181.     (r) = __r0;                                \
  182.   })
  183. #endif
  184. #endif /* udiv or mul */
  185.