Linux Audio

Check our new training course

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