linux/arch/powerpc/math-emu/udivmodti4.c
<<
>>
Prefs
   1/* This has so very few changes over libgcc2's __udivmoddi4 it isn't funny.  */
   2
   3#include <math-emu/soft-fp.h>
   4
   5#undef count_leading_zeros
   6#define count_leading_zeros  __FP_CLZ
   7
   8void
   9_fp_udivmodti4(_FP_W_TYPE q[2], _FP_W_TYPE r[2],
  10               _FP_W_TYPE n1, _FP_W_TYPE n0,
  11               _FP_W_TYPE d1, _FP_W_TYPE d0)
  12{
  13  _FP_W_TYPE q0, q1, r0, r1;
  14  _FP_I_TYPE b, bm;
  15
  16  if (d1 == 0)
  17    {
  18#if !UDIV_NEEDS_NORMALIZATION
  19      if (d0 > n1)
  20        {
  21          /* 0q = nn / 0D */
  22
  23          udiv_qrnnd (q0, n0, n1, n0, d0);
  24          q1 = 0;
  25
  26          /* Remainder in n0.  */
  27        }
  28      else
  29        {
  30          /* qq = NN / 0d */
  31
  32          if (d0 == 0)
  33            d0 = 1 / d0;        /* Divide intentionally by zero.  */
  34
  35          udiv_qrnnd (q1, n1, 0, n1, d0);
  36          udiv_qrnnd (q0, n0, n1, n0, d0);
  37
  38          /* Remainder in n0.  */
  39        }
  40
  41      r0 = n0;
  42      r1 = 0;
  43
  44#else /* UDIV_NEEDS_NORMALIZATION */
  45
  46      if (d0 > n1)
  47        {
  48          /* 0q = nn / 0D */
  49
  50          count_leading_zeros (bm, d0);
  51
  52          if (bm != 0)
  53            {
  54              /* Normalize, i.e. make the most significant bit of the
  55                 denominator set.  */
  56
  57              d0 = d0 << bm;
  58              n1 = (n1 << bm) | (n0 >> (_FP_W_TYPE_SIZE - bm));
  59              n0 = n0 << bm;
  60            }
  61
  62          udiv_qrnnd (q0, n0, n1, n0, d0);
  63          q1 = 0;
  64
  65          /* Remainder in n0 >> bm.  */
  66        }
  67      else
  68        {
  69          /* qq = NN / 0d */
  70
  71          if (d0 == 0)
  72            d0 = 1 / d0;        /* Divide intentionally by zero.  */
  73
  74          count_leading_zeros (bm, d0);
  75
  76          if (bm == 0)
  77            {
  78              /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
  79                 conclude (the most significant bit of n1 is set) /\ (the
  80                 leading quotient digit q1 = 1).
  81
  82                 This special case is necessary, not an optimization.
  83                 (Shifts counts of SI_TYPE_SIZE are undefined.)  */
  84
  85              n1 -= d0;
  86              q1 = 1;
  87            }
  88          else
  89            {
  90              _FP_W_TYPE n2;
  91
  92              /* Normalize.  */
  93
  94              b = _FP_W_TYPE_SIZE - bm;
  95
  96              d0 = d0 << bm;
  97              n2 = n1 >> b;
  98              n1 = (n1 << bm) | (n0 >> b);
  99              n0 = n0 << bm;
 100
 101              udiv_qrnnd (q1, n1, n2, n1, d0);
 102            }
 103
 104          /* n1 != d0...  */
 105
 106          udiv_qrnnd (q0, n0, n1, n0, d0);
 107
 108          /* Remainder in n0 >> bm.  */
 109        }
 110
 111      r0 = n0 >> bm;
 112      r1 = 0;
 113#endif /* UDIV_NEEDS_NORMALIZATION */
 114    }
 115  else
 116    {
 117      if (d1 > n1)
 118        {
 119          /* 00 = nn / DD */
 120
 121          q0 = 0;
 122          q1 = 0;
 123
 124          /* Remainder in n1n0.  */
 125          r0 = n0;
 126          r1 = n1;
 127        }
 128      else
 129        {
 130          /* 0q = NN / dd */
 131
 132          count_leading_zeros (bm, d1);
 133          if (bm == 0)
 134            {
 135              /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
 136                 conclude (the most significant bit of n1 is set) /\ (the
 137                 quotient digit q0 = 0 or 1).
 138
 139                 This special case is necessary, not an optimization.  */
 140
 141              /* The condition on the next line takes advantage of that
 142                 n1 >= d1 (true due to program flow).  */
 143              if (n1 > d1 || n0 >= d0)
 144                {
 145                  q0 = 1;
 146                  sub_ddmmss (n1, n0, n1, n0, d1, d0);
 147                }
 148              else
 149                q0 = 0;
 150
 151              q1 = 0;
 152
 153              r0 = n0;
 154              r1 = n1;
 155            }
 156          else
 157            {
 158              _FP_W_TYPE m1, m0, n2;
 159
 160              /* Normalize.  */
 161
 162              b = _FP_W_TYPE_SIZE - bm;
 163
 164              d1 = (d1 << bm) | (d0 >> b);
 165              d0 = d0 << bm;
 166              n2 = n1 >> b;
 167              n1 = (n1 << bm) | (n0 >> b);
 168              n0 = n0 << bm;
 169
 170              udiv_qrnnd (q0, n1, n2, n1, d1);
 171              umul_ppmm (m1, m0, q0, d0);
 172
 173              if (m1 > n1 || (m1 == n1 && m0 > n0))
 174                {
 175                  q0--;
 176                  sub_ddmmss (m1, m0, m1, m0, d1, d0);
 177                }
 178
 179              q1 = 0;
 180
 181              /* Remainder in (n1n0 - m1m0) >> bm.  */
 182              sub_ddmmss (n1, n0, n1, n0, m1, m0);
 183              r0 = (n1 << b) | (n0 >> bm);
 184              r1 = n1 >> bm;
 185            }
 186        }
 187    }
 188
 189  q[0] = q0; q[1] = q1;
 190  r[0] = r0, r[1] = r1;
 191}
 192