xref: /dflybsd-src/contrib/gcc-4.7/libgcc/fixed-bit.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* This is a software fixed-point library.
2*e4b17023SJohn Marino    Copyright (C) 2007, 2009, 2011 Free Software Foundation, Inc.
3*e4b17023SJohn Marino 
4*e4b17023SJohn Marino This file is part of GCC.
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
7*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
8*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
9*e4b17023SJohn Marino version.
10*e4b17023SJohn Marino 
11*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*e4b17023SJohn Marino for more details.
15*e4b17023SJohn Marino 
16*e4b17023SJohn Marino Under Section 7 of GPL version 3, you are granted additional
17*e4b17023SJohn Marino permissions described in the GCC Runtime Library Exception, version
18*e4b17023SJohn Marino 3.1, as published by the Free Software Foundation.
19*e4b17023SJohn Marino 
20*e4b17023SJohn Marino You should have received a copy of the GNU General Public License and
21*e4b17023SJohn Marino a copy of the GCC Runtime Library Exception along with this program;
22*e4b17023SJohn Marino see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
24*e4b17023SJohn Marino 
25*e4b17023SJohn Marino /* This implements fixed-point arithmetic.
26*e4b17023SJohn Marino 
27*e4b17023SJohn Marino    Contributed by Chao-ying Fu  <fu@mips.com>.  */
28*e4b17023SJohn Marino 
29*e4b17023SJohn Marino /* To use this file, we need to define one of the following:
30*e4b17023SJohn Marino    QQ_MODE, UQQ_MODE, HQ_MODE, UHQ_MODE, SQ_MODE, USQ_MODE, DQ_MODE, UDQ_MODE,
31*e4b17023SJohn Marino    TQ_MODE, UTQ_MODE, HA_MODE, UHA_MODE, SA_MODE, USA_MODE, DA_MODE, UDA_MODE,
32*e4b17023SJohn Marino    TA_MODE, UTA_MODE.
33*e4b17023SJohn Marino    Then, all operators for this machine mode will be created.
34*e4b17023SJohn Marino 
35*e4b17023SJohn Marino    Or, we need to define FROM_* TO_* for conversions from one mode to another
36*e4b17023SJohn Marino    mode.  The mode could be one of the following:
37*e4b17023SJohn Marino    Fract: QQ, UQQ, HQ, UHQ, SQ, USQ, DQ, UDQ, TQ, UTQ
38*e4b17023SJohn Marino    Accum: HA, UHA, SA, USA, DA, UDA, TA, UTA
39*e4b17023SJohn Marino    Signed integer: QI, HI, SI, DI, TI
40*e4b17023SJohn Marino    Unsigned integer: UQI, UHI, USI, UDI, UTI
41*e4b17023SJohn Marino    Floating-point: SF, DF
42*e4b17023SJohn Marino    Ex: If we define FROM_QQ and TO_SI, the conversion from QQ to SI is
43*e4b17023SJohn Marino    generated.  */
44*e4b17023SJohn Marino 
45*e4b17023SJohn Marino #include "tconfig.h"
46*e4b17023SJohn Marino #include "tsystem.h"
47*e4b17023SJohn Marino #include "coretypes.h"
48*e4b17023SJohn Marino #include "tm.h"
49*e4b17023SJohn Marino #include "libgcc_tm.h"
50*e4b17023SJohn Marino 
51*e4b17023SJohn Marino #ifndef MIN_UNITS_PER_WORD
52*e4b17023SJohn Marino #define MIN_UNITS_PER_WORD UNITS_PER_WORD
53*e4b17023SJohn Marino #endif
54*e4b17023SJohn Marino 
55*e4b17023SJohn Marino #include "fixed-bit.h"
56*e4b17023SJohn Marino 
57*e4b17023SJohn Marino #if defined(FIXED_ADD) && defined(L_add)
58*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_ADD(FIXED_C_TYPE a,FIXED_C_TYPE b)59*e4b17023SJohn Marino FIXED_ADD (FIXED_C_TYPE a, FIXED_C_TYPE b)
60*e4b17023SJohn Marino {
61*e4b17023SJohn Marino   FIXED_C_TYPE c;
62*e4b17023SJohn Marino   INT_C_TYPE x, y, z;
63*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
64*e4b17023SJohn Marino   memcpy (&y, &b, FIXED_SIZE);
65*e4b17023SJohn Marino   z = x + y;
66*e4b17023SJohn Marino #if HAVE_PADDING_BITS
67*e4b17023SJohn Marino   z = z << PADDING_BITS;
68*e4b17023SJohn Marino   z = z >> PADDING_BITS;
69*e4b17023SJohn Marino #endif
70*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
71*e4b17023SJohn Marino   return c;
72*e4b17023SJohn Marino }
73*e4b17023SJohn Marino #endif /* FIXED_ADD */
74*e4b17023SJohn Marino 
75*e4b17023SJohn Marino #if defined(FIXED_SSADD) && defined(L_ssadd)
76*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_SSADD(FIXED_C_TYPE a,FIXED_C_TYPE b)77*e4b17023SJohn Marino FIXED_SSADD (FIXED_C_TYPE a, FIXED_C_TYPE b)
78*e4b17023SJohn Marino {
79*e4b17023SJohn Marino   FIXED_C_TYPE c;
80*e4b17023SJohn Marino   INT_C_TYPE x, y, z;
81*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
82*e4b17023SJohn Marino   memcpy (&y, &b, FIXED_SIZE);
83*e4b17023SJohn Marino   z = x + y;
84*e4b17023SJohn Marino   if ((((x ^ y) >> I_F_BITS) & 1) == 0)
85*e4b17023SJohn Marino     {
86*e4b17023SJohn Marino       if (((z ^ x) >> I_F_BITS) & 1)
87*e4b17023SJohn Marino         {
88*e4b17023SJohn Marino           z = 1;
89*e4b17023SJohn Marino           z = z << I_F_BITS;
90*e4b17023SJohn Marino           if (x >= 0)
91*e4b17023SJohn Marino             z--;
92*e4b17023SJohn Marino         }
93*e4b17023SJohn Marino     }
94*e4b17023SJohn Marino #if HAVE_PADDING_BITS
95*e4b17023SJohn Marino   z = z << PADDING_BITS;
96*e4b17023SJohn Marino   z = z >> PADDING_BITS;
97*e4b17023SJohn Marino #endif
98*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
99*e4b17023SJohn Marino   return c;
100*e4b17023SJohn Marino }
101*e4b17023SJohn Marino #endif /* FIXED_SSADD */
102*e4b17023SJohn Marino 
103*e4b17023SJohn Marino #if defined(FIXED_USADD) && defined(L_usadd)
104*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_USADD(FIXED_C_TYPE a,FIXED_C_TYPE b)105*e4b17023SJohn Marino FIXED_USADD (FIXED_C_TYPE a, FIXED_C_TYPE b)
106*e4b17023SJohn Marino {
107*e4b17023SJohn Marino   FIXED_C_TYPE c;
108*e4b17023SJohn Marino   INT_C_TYPE x, y, z;
109*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
110*e4b17023SJohn Marino   memcpy (&y, &b, FIXED_SIZE);
111*e4b17023SJohn Marino   z = x + y;
112*e4b17023SJohn Marino #if HAVE_PADDING_BITS
113*e4b17023SJohn Marino   z = z << PADDING_BITS;
114*e4b17023SJohn Marino   z = z >> PADDING_BITS;
115*e4b17023SJohn Marino #endif
116*e4b17023SJohn Marino   if (z < x || z < y) /* max */
117*e4b17023SJohn Marino     {
118*e4b17023SJohn Marino        z = -1;
119*e4b17023SJohn Marino #if HAVE_PADDING_BITS
120*e4b17023SJohn Marino        z = z << PADDING_BITS;
121*e4b17023SJohn Marino        z = z >> PADDING_BITS;
122*e4b17023SJohn Marino #endif
123*e4b17023SJohn Marino     }
124*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
125*e4b17023SJohn Marino   return c;
126*e4b17023SJohn Marino }
127*e4b17023SJohn Marino #endif /* FIXED_USADD */
128*e4b17023SJohn Marino 
129*e4b17023SJohn Marino #if defined(FIXED_SUB) && defined(L_sub)
130*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_SUB(FIXED_C_TYPE a,FIXED_C_TYPE b)131*e4b17023SJohn Marino FIXED_SUB (FIXED_C_TYPE a, FIXED_C_TYPE b)
132*e4b17023SJohn Marino {
133*e4b17023SJohn Marino   FIXED_C_TYPE c;
134*e4b17023SJohn Marino   INT_C_TYPE x, y, z;
135*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
136*e4b17023SJohn Marino   memcpy (&y, &b, FIXED_SIZE);
137*e4b17023SJohn Marino   z = x - y;
138*e4b17023SJohn Marino #if HAVE_PADDING_BITS
139*e4b17023SJohn Marino   z = z << PADDING_BITS;
140*e4b17023SJohn Marino   z = z >> PADDING_BITS;
141*e4b17023SJohn Marino #endif
142*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
143*e4b17023SJohn Marino   return c;
144*e4b17023SJohn Marino }
145*e4b17023SJohn Marino #endif /* FIXED_SUB */
146*e4b17023SJohn Marino 
147*e4b17023SJohn Marino #if defined(FIXED_SSSUB) && defined(L_sssub)
148*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_SSSUB(FIXED_C_TYPE a,FIXED_C_TYPE b)149*e4b17023SJohn Marino FIXED_SSSUB (FIXED_C_TYPE a, FIXED_C_TYPE b)
150*e4b17023SJohn Marino {
151*e4b17023SJohn Marino   FIXED_C_TYPE c;
152*e4b17023SJohn Marino   INT_C_TYPE x, y, z;
153*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
154*e4b17023SJohn Marino   memcpy (&y, &b, FIXED_SIZE);
155*e4b17023SJohn Marino   z = x - y;
156*e4b17023SJohn Marino   if (((x ^ y) >> I_F_BITS) & 1)
157*e4b17023SJohn Marino     {
158*e4b17023SJohn Marino       if (((z ^ x) >> I_F_BITS) & 1)
159*e4b17023SJohn Marino         {
160*e4b17023SJohn Marino           z = 1;
161*e4b17023SJohn Marino           z = z << I_F_BITS;
162*e4b17023SJohn Marino           if (x >= 0)
163*e4b17023SJohn Marino             z--;
164*e4b17023SJohn Marino         }
165*e4b17023SJohn Marino     }
166*e4b17023SJohn Marino #if HAVE_PADDING_BITS
167*e4b17023SJohn Marino   z = z << PADDING_BITS;
168*e4b17023SJohn Marino   z = z >> PADDING_BITS;
169*e4b17023SJohn Marino #endif
170*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
171*e4b17023SJohn Marino   return c;
172*e4b17023SJohn Marino }
173*e4b17023SJohn Marino #endif /* FIXED_SSSUB */
174*e4b17023SJohn Marino 
175*e4b17023SJohn Marino #if defined(FIXED_USSUB) && defined(L_ussub)
176*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_USSUB(FIXED_C_TYPE a,FIXED_C_TYPE b)177*e4b17023SJohn Marino FIXED_USSUB (FIXED_C_TYPE a, FIXED_C_TYPE b)
178*e4b17023SJohn Marino {
179*e4b17023SJohn Marino   FIXED_C_TYPE c;
180*e4b17023SJohn Marino   INT_C_TYPE x, y, z;
181*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
182*e4b17023SJohn Marino   memcpy (&y, &b, FIXED_SIZE);
183*e4b17023SJohn Marino   z = x - y;
184*e4b17023SJohn Marino   if (x < y)
185*e4b17023SJohn Marino     z = 0;
186*e4b17023SJohn Marino #if HAVE_PADDING_BITS
187*e4b17023SJohn Marino   z = z << PADDING_BITS;
188*e4b17023SJohn Marino   z = z >> PADDING_BITS;
189*e4b17023SJohn Marino #endif
190*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
191*e4b17023SJohn Marino   return c;
192*e4b17023SJohn Marino }
193*e4b17023SJohn Marino #endif /* FIXED_USSUB */
194*e4b17023SJohn Marino 
195*e4b17023SJohn Marino #if defined(FIXED_SATURATE1) && defined(L_saturate1)
196*e4b17023SJohn Marino void
FIXED_SATURATE1(DINT_C_TYPE * a)197*e4b17023SJohn Marino FIXED_SATURATE1 (DINT_C_TYPE *a)
198*e4b17023SJohn Marino {
199*e4b17023SJohn Marino   DINT_C_TYPE max, min;
200*e4b17023SJohn Marino   max = (DINT_C_TYPE)1 << I_F_BITS;
201*e4b17023SJohn Marino   max = max - 1;
202*e4b17023SJohn Marino #if MODE_UNSIGNED == 0
203*e4b17023SJohn Marino   min = (DINT_C_TYPE)1 << (2 * FIXED_WIDTH - 1);
204*e4b17023SJohn Marino   min = min >> (2 * FIXED_WIDTH - 1 - I_F_BITS);
205*e4b17023SJohn Marino #else
206*e4b17023SJohn Marino   min = 0;
207*e4b17023SJohn Marino #endif
208*e4b17023SJohn Marino   if (*a > max)
209*e4b17023SJohn Marino     *a = max;
210*e4b17023SJohn Marino   else if (*a < min)
211*e4b17023SJohn Marino     *a = min;
212*e4b17023SJohn Marino }
213*e4b17023SJohn Marino #endif /* FIXED_SATURATE1 */
214*e4b17023SJohn Marino 
215*e4b17023SJohn Marino #if defined(FIXED_SATURATE2) && defined(L_saturate2)
216*e4b17023SJohn Marino void
FIXED_SATURATE2(INT_C_TYPE * high,INT_C_TYPE * low)217*e4b17023SJohn Marino FIXED_SATURATE2 (INT_C_TYPE *high, INT_C_TYPE *low)
218*e4b17023SJohn Marino {
219*e4b17023SJohn Marino   INT_C_TYPE r_max, s_max, r_min, s_min;
220*e4b17023SJohn Marino   r_max = 0;
221*e4b17023SJohn Marino #if (MODE_UNSIGNED == 0) || HAVE_PADDING_BITS
222*e4b17023SJohn Marino   s_max = (INT_C_TYPE)1 << I_F_BITS;
223*e4b17023SJohn Marino   s_max = s_max - 1;
224*e4b17023SJohn Marino #else
225*e4b17023SJohn Marino   s_max = -1;
226*e4b17023SJohn Marino #endif
227*e4b17023SJohn Marino #if MODE_UNSIGNED == 0
228*e4b17023SJohn Marino   r_min = -1;
229*e4b17023SJohn Marino   s_min = (INT_C_TYPE)1 << (FIXED_WIDTH - 1);
230*e4b17023SJohn Marino   s_min = s_min >> (FIXED_WIDTH - 1 - I_F_BITS);
231*e4b17023SJohn Marino #else
232*e4b17023SJohn Marino   r_min = 0;
233*e4b17023SJohn Marino   s_min = 0;
234*e4b17023SJohn Marino #endif
235*e4b17023SJohn Marino 
236*e4b17023SJohn Marino   if (*high > r_max
237*e4b17023SJohn Marino       || (*high == r_max && (UINT_C_TYPE)(*low) > (UINT_C_TYPE)s_max))
238*e4b17023SJohn Marino     {
239*e4b17023SJohn Marino       *high = r_max;
240*e4b17023SJohn Marino       *low = s_max;
241*e4b17023SJohn Marino     }
242*e4b17023SJohn Marino   else if (*high < r_min ||
243*e4b17023SJohn Marino 	   (*high == r_min && (UINT_C_TYPE)(*low) < (UINT_C_TYPE)s_min))
244*e4b17023SJohn Marino     {
245*e4b17023SJohn Marino       *high = r_min;
246*e4b17023SJohn Marino       *low = s_min;
247*e4b17023SJohn Marino     }
248*e4b17023SJohn Marino }
249*e4b17023SJohn Marino #endif /* FIXED_SATURATE2 */
250*e4b17023SJohn Marino 
251*e4b17023SJohn Marino #if defined(FIXED_MULHELPER) && defined(L_mulhelper)
252*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_MULHELPER(FIXED_C_TYPE a,FIXED_C_TYPE b,word_type satp)253*e4b17023SJohn Marino FIXED_MULHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp)
254*e4b17023SJohn Marino {
255*e4b17023SJohn Marino   FIXED_C_TYPE c;
256*e4b17023SJohn Marino   INT_C_TYPE x, y;
257*e4b17023SJohn Marino 
258*e4b17023SJohn Marino #if defined (DINT_C_TYPE)
259*e4b17023SJohn Marino   INT_C_TYPE z;
260*e4b17023SJohn Marino   DINT_C_TYPE dx, dy, dz;
261*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
262*e4b17023SJohn Marino   memcpy (&y, &b, FIXED_SIZE);
263*e4b17023SJohn Marino   dx = (DINT_C_TYPE) x;
264*e4b17023SJohn Marino   dy = (DINT_C_TYPE) y;
265*e4b17023SJohn Marino   dz = dx * dy;
266*e4b17023SJohn Marino   /* Round the result by adding (1 << (FBITS -1)).  */
267*e4b17023SJohn Marino   dz += ((DINT_C_TYPE) 1 << (FBITS - 1));
268*e4b17023SJohn Marino   dz = dz >> FBITS;
269*e4b17023SJohn Marino   if (satp)
270*e4b17023SJohn Marino     FIXED_SATURATE1 (&dz);
271*e4b17023SJohn Marino 
272*e4b17023SJohn Marino   z = (INT_C_TYPE) dz;
273*e4b17023SJohn Marino #if HAVE_PADDING_BITS
274*e4b17023SJohn Marino   z = z << PADDING_BITS;
275*e4b17023SJohn Marino   z = z >> PADDING_BITS;
276*e4b17023SJohn Marino #endif
277*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
278*e4b17023SJohn Marino   return c;
279*e4b17023SJohn Marino 
280*e4b17023SJohn Marino #else /* No DINT_C_TYPE */
281*e4b17023SJohn Marino   /* The result of multiplication expands to two INT_C_TYPE.  */
282*e4b17023SJohn Marino   INTunion aa, bb;
283*e4b17023SJohn Marino   INTunion a_high, a_low, b_high, b_low;
284*e4b17023SJohn Marino   INTunion high_high, high_low, low_high, low_low;
285*e4b17023SJohn Marino   INTunion r, s, temp1, temp2;
286*e4b17023SJohn Marino   INT_C_TYPE carry = 0;
287*e4b17023SJohn Marino   INT_C_TYPE z;
288*e4b17023SJohn Marino 
289*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
290*e4b17023SJohn Marino   memcpy (&y, &b, FIXED_SIZE);
291*e4b17023SJohn Marino 
292*e4b17023SJohn Marino   /* Decompose a and b.  */
293*e4b17023SJohn Marino   aa.ll = x;
294*e4b17023SJohn Marino   bb.ll = y;
295*e4b17023SJohn Marino 
296*e4b17023SJohn Marino   a_high.s.low = aa.s.high;
297*e4b17023SJohn Marino   a_high.s.high = 0;
298*e4b17023SJohn Marino   a_low.s.low = aa.s.low;
299*e4b17023SJohn Marino   a_low.s.high = 0;
300*e4b17023SJohn Marino   b_high.s.low = bb.s.high;
301*e4b17023SJohn Marino   b_high.s.high = 0;
302*e4b17023SJohn Marino   b_low.s.low = bb.s.low;
303*e4b17023SJohn Marino   b_low.s.high = 0;
304*e4b17023SJohn Marino 
305*e4b17023SJohn Marino   /* Perform four multiplications.  */
306*e4b17023SJohn Marino   low_low.ll = a_low.ll * b_low.ll;
307*e4b17023SJohn Marino   low_high.ll = a_low.ll * b_high.ll;
308*e4b17023SJohn Marino   high_low.ll = a_high.ll * b_low.ll;
309*e4b17023SJohn Marino   high_high.ll = a_high.ll * b_high.ll;
310*e4b17023SJohn Marino 
311*e4b17023SJohn Marino   /* Accumulate four results to {r, s}.  */
312*e4b17023SJohn Marino   temp1.s.high = high_low.s.low;
313*e4b17023SJohn Marino   temp1.s.low = 0;
314*e4b17023SJohn Marino   s.ll = low_low.ll + temp1.ll;
315*e4b17023SJohn Marino   if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) low_low.ll
316*e4b17023SJohn Marino       || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll)
317*e4b17023SJohn Marino     carry ++; /* Carry.  */
318*e4b17023SJohn Marino   temp1.ll = s.ll;
319*e4b17023SJohn Marino   temp2.s.high = low_high.s.low;
320*e4b17023SJohn Marino   temp2.s.low = 0;
321*e4b17023SJohn Marino   s.ll = temp1.ll + temp2.ll;
322*e4b17023SJohn Marino   if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll
323*e4b17023SJohn Marino       || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp2.ll)
324*e4b17023SJohn Marino     carry ++; /* Carry.  */
325*e4b17023SJohn Marino 
326*e4b17023SJohn Marino   temp1.s.low = high_low.s.high;
327*e4b17023SJohn Marino   temp1.s.high = 0;
328*e4b17023SJohn Marino   r.ll = high_high.ll + temp1.ll;
329*e4b17023SJohn Marino   temp1.s.low = low_high.s.high;
330*e4b17023SJohn Marino   temp1.s.high = 0;
331*e4b17023SJohn Marino   r.ll = r.ll + temp1.ll + carry;
332*e4b17023SJohn Marino 
333*e4b17023SJohn Marino #if MODE_UNSIGNED == 0
334*e4b17023SJohn Marino   /* For signed types, we need to add neg(y) to r, if x < 0.  */
335*e4b17023SJohn Marino   if (x < 0)
336*e4b17023SJohn Marino     r.ll = r.ll - y;
337*e4b17023SJohn Marino   /* We need to add neg(x) to r, if y < 0.  */
338*e4b17023SJohn Marino   if (y < 0)
339*e4b17023SJohn Marino     r.ll = r.ll - x;
340*e4b17023SJohn Marino #endif
341*e4b17023SJohn Marino 
342*e4b17023SJohn Marino   /* Round the result by adding (1 << (FBITS -1)).  */
343*e4b17023SJohn Marino   temp1.ll = s.ll;
344*e4b17023SJohn Marino   s.ll += ((INT_C_TYPE) 1 << (FBITS -1));
345*e4b17023SJohn Marino   if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll
346*e4b17023SJohn Marino       || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) ((INT_C_TYPE) 1 << (FBITS -1)))
347*e4b17023SJohn Marino     r.ll += 1;
348*e4b17023SJohn Marino 
349*e4b17023SJohn Marino   /* Shift right the result by FBITS.  */
350*e4b17023SJohn Marino #if FBITS == FIXED_WIDTH
351*e4b17023SJohn Marino   /* This happens only for unsigned types without any padding bits.
352*e4b17023SJohn Marino      So, it is safe to set r.ll to 0 as it is logically shifted right.  */
353*e4b17023SJohn Marino   s.ll = r.ll;
354*e4b17023SJohn Marino   r.ll = 0;
355*e4b17023SJohn Marino #else
356*e4b17023SJohn Marino   s.ll = ((UINT_C_TYPE)s.ll) >> FBITS;
357*e4b17023SJohn Marino   temp1.ll = r.ll << (FIXED_WIDTH - FBITS);
358*e4b17023SJohn Marino   s.ll = s.ll | temp1.ll;
359*e4b17023SJohn Marino   r.ll = r.ll >> FBITS;
360*e4b17023SJohn Marino #endif
361*e4b17023SJohn Marino 
362*e4b17023SJohn Marino   if (satp)
363*e4b17023SJohn Marino     FIXED_SATURATE2 (&r.ll, &s.ll);
364*e4b17023SJohn Marino 
365*e4b17023SJohn Marino   z = (INT_C_TYPE) s.ll;
366*e4b17023SJohn Marino #if HAVE_PADDING_BITS
367*e4b17023SJohn Marino   z = z << PADDING_BITS;
368*e4b17023SJohn Marino   z = z >> PADDING_BITS;
369*e4b17023SJohn Marino #endif
370*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
371*e4b17023SJohn Marino   return c;
372*e4b17023SJohn Marino #endif
373*e4b17023SJohn Marino }
374*e4b17023SJohn Marino #endif /* FIXED_MULHELPER */
375*e4b17023SJohn Marino 
376*e4b17023SJohn Marino #if defined(FIXED_MUL) && defined(L_mul)
377*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_MUL(FIXED_C_TYPE a,FIXED_C_TYPE b)378*e4b17023SJohn Marino FIXED_MUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
379*e4b17023SJohn Marino {
380*e4b17023SJohn Marino   return FIXED_MULHELPER (a, b, 0);
381*e4b17023SJohn Marino }
382*e4b17023SJohn Marino #endif /* FIXED_MUL */
383*e4b17023SJohn Marino 
384*e4b17023SJohn Marino #if defined(FIXED_SSMUL) && defined(L_ssmul)
385*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_SSMUL(FIXED_C_TYPE a,FIXED_C_TYPE b)386*e4b17023SJohn Marino FIXED_SSMUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
387*e4b17023SJohn Marino {
388*e4b17023SJohn Marino   return FIXED_MULHELPER (a, b, 1);
389*e4b17023SJohn Marino }
390*e4b17023SJohn Marino #endif /* FIXED_SSMUL */
391*e4b17023SJohn Marino 
392*e4b17023SJohn Marino #if defined(FIXED_USMUL) && defined(L_usmul)
393*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_USMUL(FIXED_C_TYPE a,FIXED_C_TYPE b)394*e4b17023SJohn Marino FIXED_USMUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
395*e4b17023SJohn Marino {
396*e4b17023SJohn Marino   return FIXED_MULHELPER (a, b, 1);
397*e4b17023SJohn Marino }
398*e4b17023SJohn Marino #endif /* FIXED_USMUL */
399*e4b17023SJohn Marino 
400*e4b17023SJohn Marino #if defined(FIXED_DIVHELPER) && defined(L_divhelper)
401*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_DIVHELPER(FIXED_C_TYPE a,FIXED_C_TYPE b,word_type satp)402*e4b17023SJohn Marino FIXED_DIVHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp)
403*e4b17023SJohn Marino {
404*e4b17023SJohn Marino   FIXED_C_TYPE c;
405*e4b17023SJohn Marino   INT_C_TYPE x, y;
406*e4b17023SJohn Marino   INT_C_TYPE z;
407*e4b17023SJohn Marino 
408*e4b17023SJohn Marino #if defined (DINT_C_TYPE)
409*e4b17023SJohn Marino   DINT_C_TYPE dx, dy, dz;
410*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
411*e4b17023SJohn Marino   memcpy (&y, &b, FIXED_SIZE);
412*e4b17023SJohn Marino   dx = (DINT_C_TYPE) x;
413*e4b17023SJohn Marino   dy = (DINT_C_TYPE) y;
414*e4b17023SJohn Marino   dx = dx << FBITS;
415*e4b17023SJohn Marino   dz = dx / dy;
416*e4b17023SJohn Marino   if (satp)
417*e4b17023SJohn Marino     FIXED_SATURATE1 (&dz);
418*e4b17023SJohn Marino   z = (INT_C_TYPE) dz;
419*e4b17023SJohn Marino #if HAVE_PADDING_BITS
420*e4b17023SJohn Marino   z = z << PADDING_BITS;
421*e4b17023SJohn Marino   z = z >> PADDING_BITS;
422*e4b17023SJohn Marino #endif
423*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
424*e4b17023SJohn Marino   return c;
425*e4b17023SJohn Marino 
426*e4b17023SJohn Marino #else /* No DINT_C_TYPE */
427*e4b17023SJohn Marino   INT_C_TYPE pos_a, pos_b, r, s;
428*e4b17023SJohn Marino   INT_C_TYPE quo_r, quo_s, mod, temp;
429*e4b17023SJohn Marino   word_type i;
430*e4b17023SJohn Marino #if MODE_UNSIGNED == 0
431*e4b17023SJohn Marino   word_type num_of_neg = 0;
432*e4b17023SJohn Marino #endif
433*e4b17023SJohn Marino 
434*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
435*e4b17023SJohn Marino   memcpy (&y, &b, FIXED_SIZE);
436*e4b17023SJohn Marino   pos_a = x;
437*e4b17023SJohn Marino   pos_b = y;
438*e4b17023SJohn Marino 
439*e4b17023SJohn Marino #if MODE_UNSIGNED == 0
440*e4b17023SJohn Marino   /* If a < 0, negate a.  */
441*e4b17023SJohn Marino   if (pos_a < 0)
442*e4b17023SJohn Marino     {
443*e4b17023SJohn Marino       pos_a = -pos_a;
444*e4b17023SJohn Marino       num_of_neg ++;
445*e4b17023SJohn Marino     }
446*e4b17023SJohn Marino   /* If b < 0, negate b.  */
447*e4b17023SJohn Marino   if (pos_b < 0)
448*e4b17023SJohn Marino     {
449*e4b17023SJohn Marino       pos_b = -pos_b;
450*e4b17023SJohn Marino       num_of_neg ++;
451*e4b17023SJohn Marino     }
452*e4b17023SJohn Marino #endif
453*e4b17023SJohn Marino 
454*e4b17023SJohn Marino   /* Left shift pos_a to {r, s} by FBITS.  */
455*e4b17023SJohn Marino #if FBITS == FIXED_WIDTH
456*e4b17023SJohn Marino   /* This happens only for unsigned types without any padding bits.  */
457*e4b17023SJohn Marino   r = pos_a;
458*e4b17023SJohn Marino   s = 0;
459*e4b17023SJohn Marino #else
460*e4b17023SJohn Marino   s = pos_a << FBITS;
461*e4b17023SJohn Marino   r = pos_a >> (FIXED_WIDTH - FBITS);
462*e4b17023SJohn Marino #endif
463*e4b17023SJohn Marino 
464*e4b17023SJohn Marino   /* Unsigned divide r by pos_b to quo_r.  The remainder is in mod.  */
465*e4b17023SJohn Marino   quo_r = (UINT_C_TYPE)r / (UINT_C_TYPE)pos_b;
466*e4b17023SJohn Marino   mod = (UINT_C_TYPE)r % (UINT_C_TYPE)pos_b;
467*e4b17023SJohn Marino   quo_s = 0;
468*e4b17023SJohn Marino 
469*e4b17023SJohn Marino   for (i = 0; i < FIXED_WIDTH; i++)
470*e4b17023SJohn Marino     {
471*e4b17023SJohn Marino       /* Record the leftmost bit of mod.  */
472*e4b17023SJohn Marino       word_type leftmost_mode = (mod >> (FIXED_WIDTH - 1)) & 1;
473*e4b17023SJohn Marino       /* Shift left mod by 1 bit.  */
474*e4b17023SJohn Marino       mod = mod << 1;
475*e4b17023SJohn Marino       /* Test the leftmost bit of s to add to mod.  */
476*e4b17023SJohn Marino       if ((s >> (FIXED_WIDTH - 1)) & 1)
477*e4b17023SJohn Marino 	mod ++;
478*e4b17023SJohn Marino       /* Shift left quo_s by 1 bit.  */
479*e4b17023SJohn Marino       quo_s = quo_s << 1;
480*e4b17023SJohn Marino       /* Try to calculate (mod - pos_b).  */
481*e4b17023SJohn Marino       temp = mod - pos_b;
482*e4b17023SJohn Marino       if (leftmost_mode || (UINT_C_TYPE)mod >= (UINT_C_TYPE)pos_b)
483*e4b17023SJohn Marino 	{
484*e4b17023SJohn Marino 	  quo_s ++;
485*e4b17023SJohn Marino 	  mod = temp;
486*e4b17023SJohn Marino 	}
487*e4b17023SJohn Marino       /* Shift left s by 1 bit.  */
488*e4b17023SJohn Marino       s = s << 1;
489*e4b17023SJohn Marino     }
490*e4b17023SJohn Marino 
491*e4b17023SJohn Marino #if MODE_UNSIGNED == 0
492*e4b17023SJohn Marino     if (num_of_neg == 1)
493*e4b17023SJohn Marino       {
494*e4b17023SJohn Marino 	quo_s = -quo_s;
495*e4b17023SJohn Marino 	if (quo_s == 0)
496*e4b17023SJohn Marino 	  quo_r = -quo_r;
497*e4b17023SJohn Marino 	else
498*e4b17023SJohn Marino 	  quo_r = ~quo_r;
499*e4b17023SJohn Marino       }
500*e4b17023SJohn Marino #endif
501*e4b17023SJohn Marino   if (satp)
502*e4b17023SJohn Marino     FIXED_SATURATE2 (&quo_r, &quo_s);
503*e4b17023SJohn Marino   z = quo_s;
504*e4b17023SJohn Marino #if HAVE_PADDING_BITS
505*e4b17023SJohn Marino   z = z << PADDING_BITS;
506*e4b17023SJohn Marino   z = z >> PADDING_BITS;
507*e4b17023SJohn Marino #endif
508*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
509*e4b17023SJohn Marino   return c;
510*e4b17023SJohn Marino #endif
511*e4b17023SJohn Marino }
512*e4b17023SJohn Marino #endif /* FIXED_DIVHELPER */
513*e4b17023SJohn Marino 
514*e4b17023SJohn Marino #if defined(FIXED_DIV) && defined(L_div)
515*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_DIV(FIXED_C_TYPE a,FIXED_C_TYPE b)516*e4b17023SJohn Marino FIXED_DIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
517*e4b17023SJohn Marino {
518*e4b17023SJohn Marino   return FIXED_DIVHELPER (a, b, 0);
519*e4b17023SJohn Marino }
520*e4b17023SJohn Marino #endif /* FIXED_DIV */
521*e4b17023SJohn Marino 
522*e4b17023SJohn Marino 
523*e4b17023SJohn Marino #if defined(FIXED_UDIV) && defined(L_udiv)
524*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_UDIV(FIXED_C_TYPE a,FIXED_C_TYPE b)525*e4b17023SJohn Marino FIXED_UDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
526*e4b17023SJohn Marino {
527*e4b17023SJohn Marino   return FIXED_DIVHELPER (a, b, 0);
528*e4b17023SJohn Marino }
529*e4b17023SJohn Marino #endif /* FIXED_UDIV */
530*e4b17023SJohn Marino 
531*e4b17023SJohn Marino #if defined(FIXED_SSDIV) && defined(L_ssdiv)
532*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_SSDIV(FIXED_C_TYPE a,FIXED_C_TYPE b)533*e4b17023SJohn Marino FIXED_SSDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
534*e4b17023SJohn Marino {
535*e4b17023SJohn Marino   return FIXED_DIVHELPER (a, b, 1);
536*e4b17023SJohn Marino }
537*e4b17023SJohn Marino #endif /* FIXED_SSDIV */
538*e4b17023SJohn Marino 
539*e4b17023SJohn Marino #if defined(FIXED_USDIV) && defined(L_usdiv)
540*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_USDIV(FIXED_C_TYPE a,FIXED_C_TYPE b)541*e4b17023SJohn Marino FIXED_USDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
542*e4b17023SJohn Marino {
543*e4b17023SJohn Marino   return FIXED_DIVHELPER (a, b, 1);
544*e4b17023SJohn Marino }
545*e4b17023SJohn Marino #endif /* FIXED_USDIV */
546*e4b17023SJohn Marino 
547*e4b17023SJohn Marino #if defined(FIXED_NEG) && defined(L_neg)
548*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_NEG(FIXED_C_TYPE a)549*e4b17023SJohn Marino FIXED_NEG (FIXED_C_TYPE a)
550*e4b17023SJohn Marino {
551*e4b17023SJohn Marino   FIXED_C_TYPE c;
552*e4b17023SJohn Marino   INT_C_TYPE x, z;
553*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
554*e4b17023SJohn Marino   z = -x;
555*e4b17023SJohn Marino #if HAVE_PADDING_BITS
556*e4b17023SJohn Marino   z = z << PADDING_BITS;
557*e4b17023SJohn Marino   z = z >> PADDING_BITS;
558*e4b17023SJohn Marino #endif
559*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
560*e4b17023SJohn Marino   return c;
561*e4b17023SJohn Marino }
562*e4b17023SJohn Marino #endif /* FIXED_NEG */
563*e4b17023SJohn Marino 
564*e4b17023SJohn Marino #if defined(FIXED_SSNEG) && defined(L_ssneg)
565*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_SSNEG(FIXED_C_TYPE a)566*e4b17023SJohn Marino FIXED_SSNEG (FIXED_C_TYPE a)
567*e4b17023SJohn Marino {
568*e4b17023SJohn Marino   FIXED_C_TYPE c;
569*e4b17023SJohn Marino   INT_C_TYPE x, y, z;
570*e4b17023SJohn Marino   memcpy (&y, &a, FIXED_SIZE);
571*e4b17023SJohn Marino   x = 0;
572*e4b17023SJohn Marino   z = x - y;
573*e4b17023SJohn Marino   if (((x ^ y) >> I_F_BITS) & 1)
574*e4b17023SJohn Marino     {
575*e4b17023SJohn Marino       if (((z ^ x) >> I_F_BITS) & 1)
576*e4b17023SJohn Marino         {
577*e4b17023SJohn Marino           z = 1;
578*e4b17023SJohn Marino           z = z << I_F_BITS;
579*e4b17023SJohn Marino           if (x >= 0)
580*e4b17023SJohn Marino             z--;
581*e4b17023SJohn Marino         }
582*e4b17023SJohn Marino     }
583*e4b17023SJohn Marino #if HAVE_PADDING_BITS
584*e4b17023SJohn Marino   z = z << PADDING_BITS;
585*e4b17023SJohn Marino   z = z >> PADDING_BITS;
586*e4b17023SJohn Marino #endif
587*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
588*e4b17023SJohn Marino   return c;
589*e4b17023SJohn Marino }
590*e4b17023SJohn Marino #endif /* FIXED_SSNEG */
591*e4b17023SJohn Marino 
592*e4b17023SJohn Marino #if defined(FIXED_USNEG) && defined(L_usneg)
593*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_USNEG(FIXED_C_TYPE a)594*e4b17023SJohn Marino FIXED_USNEG (FIXED_C_TYPE a __attribute__ ((__unused__)))
595*e4b17023SJohn Marino {
596*e4b17023SJohn Marino   FIXED_C_TYPE c;
597*e4b17023SJohn Marino   INT_C_TYPE z;
598*e4b17023SJohn Marino   z = 0;
599*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
600*e4b17023SJohn Marino   return c;
601*e4b17023SJohn Marino }
602*e4b17023SJohn Marino #endif /* FIXED_USNEG */
603*e4b17023SJohn Marino 
604*e4b17023SJohn Marino #if defined(FIXED_ASHLHELPER) && defined(L_ashlhelper)
605*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_ASHLHELPER(FIXED_C_TYPE a,word_type b,word_type satp)606*e4b17023SJohn Marino FIXED_ASHLHELPER (FIXED_C_TYPE a, word_type b, word_type satp)
607*e4b17023SJohn Marino {
608*e4b17023SJohn Marino   FIXED_C_TYPE c;
609*e4b17023SJohn Marino   INT_C_TYPE x, z;
610*e4b17023SJohn Marino 
611*e4b17023SJohn Marino #if defined (DINT_C_TYPE)
612*e4b17023SJohn Marino   DINT_C_TYPE dx, dz;
613*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
614*e4b17023SJohn Marino   dx = (DINT_C_TYPE) x;
615*e4b17023SJohn Marino   if (b >= FIXED_WIDTH)
616*e4b17023SJohn Marino     dz = dx << FIXED_WIDTH;
617*e4b17023SJohn Marino   else
618*e4b17023SJohn Marino     dz = dx << b;
619*e4b17023SJohn Marino   if (satp)
620*e4b17023SJohn Marino     FIXED_SATURATE1 (&dz);
621*e4b17023SJohn Marino   z = (INT_C_TYPE) dz;
622*e4b17023SJohn Marino #if HAVE_PADDING_BITS
623*e4b17023SJohn Marino   z = z << PADDING_BITS;
624*e4b17023SJohn Marino   z = z >> PADDING_BITS;
625*e4b17023SJohn Marino #endif
626*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
627*e4b17023SJohn Marino   return c;
628*e4b17023SJohn Marino 
629*e4b17023SJohn Marino #else /* No DINT_C_TYPE */
630*e4b17023SJohn Marino   INT_C_TYPE r, s;
631*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
632*e4b17023SJohn Marino   /* We need to shift left x by b bits to {r, s}.  */
633*e4b17023SJohn Marino   if (b >= FIXED_WIDTH)
634*e4b17023SJohn Marino     {
635*e4b17023SJohn Marino       r = b;
636*e4b17023SJohn Marino       s = 0;
637*e4b17023SJohn Marino     }
638*e4b17023SJohn Marino   else
639*e4b17023SJohn Marino     {
640*e4b17023SJohn Marino       s = x << b;
641*e4b17023SJohn Marino       r = x >> (FIXED_WIDTH - b);
642*e4b17023SJohn Marino     }
643*e4b17023SJohn Marino   if (satp)
644*e4b17023SJohn Marino     FIXED_SATURATE2 (&r, &s);
645*e4b17023SJohn Marino   z = s;
646*e4b17023SJohn Marino #if HAVE_PADDING_BITS
647*e4b17023SJohn Marino   z = z << PADDING_BITS;
648*e4b17023SJohn Marino   z = z >> PADDING_BITS;
649*e4b17023SJohn Marino #endif
650*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
651*e4b17023SJohn Marino   return c;
652*e4b17023SJohn Marino #endif
653*e4b17023SJohn Marino }
654*e4b17023SJohn Marino #endif /* FIXED_ASHLHELPER */
655*e4b17023SJohn Marino 
656*e4b17023SJohn Marino #if defined(FIXED_ASHL) && defined(L_ashl)
657*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_ASHL(FIXED_C_TYPE a,word_type b)658*e4b17023SJohn Marino FIXED_ASHL (FIXED_C_TYPE a, word_type b)
659*e4b17023SJohn Marino {
660*e4b17023SJohn Marino   return FIXED_ASHLHELPER (a, b, 0);
661*e4b17023SJohn Marino }
662*e4b17023SJohn Marino #endif /* FIXED_ASHL */
663*e4b17023SJohn Marino 
664*e4b17023SJohn Marino #if defined(FIXED_ASHR) && defined(L_ashr)
665*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_ASHR(FIXED_C_TYPE a,word_type b)666*e4b17023SJohn Marino FIXED_ASHR (FIXED_C_TYPE a, word_type b)
667*e4b17023SJohn Marino {
668*e4b17023SJohn Marino   FIXED_C_TYPE c;
669*e4b17023SJohn Marino   INT_C_TYPE x, z;
670*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
671*e4b17023SJohn Marino   z = x >> b;
672*e4b17023SJohn Marino #if HAVE_PADDING_BITS
673*e4b17023SJohn Marino   z = z << PADDING_BITS;
674*e4b17023SJohn Marino   z = z >> PADDING_BITS;
675*e4b17023SJohn Marino #endif
676*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
677*e4b17023SJohn Marino   return c;
678*e4b17023SJohn Marino }
679*e4b17023SJohn Marino #endif /* FIXED_ASHR */
680*e4b17023SJohn Marino 
681*e4b17023SJohn Marino #if defined(FIXED_LSHR) && defined(L_lshr)
682*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_LSHR(FIXED_C_TYPE a,word_type b)683*e4b17023SJohn Marino FIXED_LSHR (FIXED_C_TYPE a, word_type b)
684*e4b17023SJohn Marino {
685*e4b17023SJohn Marino   FIXED_C_TYPE c;
686*e4b17023SJohn Marino   INT_C_TYPE x, z;
687*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
688*e4b17023SJohn Marino   z = x >> b;
689*e4b17023SJohn Marino #if HAVE_PADDING_BITS
690*e4b17023SJohn Marino   z = z << PADDING_BITS;
691*e4b17023SJohn Marino   z = z >> PADDING_BITS;
692*e4b17023SJohn Marino #endif
693*e4b17023SJohn Marino   memcpy (&c, &z, FIXED_SIZE);
694*e4b17023SJohn Marino   return c;
695*e4b17023SJohn Marino }
696*e4b17023SJohn Marino #endif /* FIXED_LSHR */
697*e4b17023SJohn Marino 
698*e4b17023SJohn Marino #if defined(FIXED_SSASHL) && defined(L_ssashl)
699*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_SSASHL(FIXED_C_TYPE a,word_type b)700*e4b17023SJohn Marino FIXED_SSASHL (FIXED_C_TYPE a, word_type b)
701*e4b17023SJohn Marino {
702*e4b17023SJohn Marino   return FIXED_ASHLHELPER (a, b, 1);
703*e4b17023SJohn Marino }
704*e4b17023SJohn Marino #endif /* FIXED_SSASHL */
705*e4b17023SJohn Marino 
706*e4b17023SJohn Marino #if defined(FIXED_USASHL) && defined(L_usashl)
707*e4b17023SJohn Marino FIXED_C_TYPE
FIXED_USASHL(FIXED_C_TYPE a,word_type b)708*e4b17023SJohn Marino FIXED_USASHL (FIXED_C_TYPE a, word_type b)
709*e4b17023SJohn Marino {
710*e4b17023SJohn Marino   return FIXED_ASHLHELPER (a, b, 1);
711*e4b17023SJohn Marino }
712*e4b17023SJohn Marino #endif /* FIXED_USASHL */
713*e4b17023SJohn Marino 
714*e4b17023SJohn Marino #if defined(FIXED_CMP) && defined(L_cmp)
715*e4b17023SJohn Marino word_type
FIXED_CMP(FIXED_C_TYPE a,FIXED_C_TYPE b)716*e4b17023SJohn Marino FIXED_CMP (FIXED_C_TYPE a, FIXED_C_TYPE b)
717*e4b17023SJohn Marino {
718*e4b17023SJohn Marino   INT_C_TYPE x, y;
719*e4b17023SJohn Marino   memcpy (&x, &a, FIXED_SIZE);
720*e4b17023SJohn Marino   memcpy (&y, &b, FIXED_SIZE);
721*e4b17023SJohn Marino 
722*e4b17023SJohn Marino   if (x < y)
723*e4b17023SJohn Marino     return 0;
724*e4b17023SJohn Marino   else if (x > y)
725*e4b17023SJohn Marino     return 2;
726*e4b17023SJohn Marino 
727*e4b17023SJohn Marino   return 1;
728*e4b17023SJohn Marino }
729*e4b17023SJohn Marino #endif /* FIXED_CMP */
730*e4b17023SJohn Marino 
731*e4b17023SJohn Marino /* Fixed -> Fixed.  */
732*e4b17023SJohn Marino #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 4
733*e4b17023SJohn Marino TO_FIXED_C_TYPE
FRACT(FROM_FIXED_C_TYPE a)734*e4b17023SJohn Marino FRACT (FROM_FIXED_C_TYPE a)
735*e4b17023SJohn Marino {
736*e4b17023SJohn Marino   TO_FIXED_C_TYPE c;
737*e4b17023SJohn Marino   FROM_INT_C_TYPE x;
738*e4b17023SJohn Marino   TO_INT_C_TYPE z;
739*e4b17023SJohn Marino   int shift_amount;
740*e4b17023SJohn Marino   memcpy (&x, &a, FROM_FIXED_SIZE);
741*e4b17023SJohn Marino #if TO_FBITS > FROM_FBITS  /* Need left shift.  */
742*e4b17023SJohn Marino   shift_amount = TO_FBITS - FROM_FBITS;
743*e4b17023SJohn Marino   z = (TO_INT_C_TYPE) x;
744*e4b17023SJohn Marino   z = z << shift_amount;
745*e4b17023SJohn Marino #else /* TO_FBITS <= FROM_FBITS.  Need right Shift.  */
746*e4b17023SJohn Marino   shift_amount = FROM_FBITS - TO_FBITS;
747*e4b17023SJohn Marino   x = x >> shift_amount;
748*e4b17023SJohn Marino   z = (TO_INT_C_TYPE) x;
749*e4b17023SJohn Marino #endif /* TO_FBITS > FROM_FBITS  */
750*e4b17023SJohn Marino 
751*e4b17023SJohn Marino #if TO_HAVE_PADDING_BITS
752*e4b17023SJohn Marino   z = z << TO_PADDING_BITS;
753*e4b17023SJohn Marino   z = z >> TO_PADDING_BITS;
754*e4b17023SJohn Marino #endif
755*e4b17023SJohn Marino   memcpy (&c, &z, TO_FIXED_SIZE);
756*e4b17023SJohn Marino   return c;
757*e4b17023SJohn Marino }
758*e4b17023SJohn Marino #endif /* FRACT && FROM_TYPE == 4 && TO_TYPE == 4  */
759*e4b17023SJohn Marino 
760*e4b17023SJohn Marino /* Fixed -> Fixed with saturation.  */
761*e4b17023SJohn Marino #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 4 && TO_TYPE == 4
762*e4b17023SJohn Marino TO_FIXED_C_TYPE
SATFRACT(FROM_FIXED_C_TYPE a)763*e4b17023SJohn Marino SATFRACT (FROM_FIXED_C_TYPE a)
764*e4b17023SJohn Marino {
765*e4b17023SJohn Marino   TO_FIXED_C_TYPE c;
766*e4b17023SJohn Marino   TO_INT_C_TYPE z;
767*e4b17023SJohn Marino   FROM_INT_C_TYPE x;
768*e4b17023SJohn Marino #if FROM_MODE_UNSIGNED == 0
769*e4b17023SJohn Marino   BIG_SINT_C_TYPE high, low;
770*e4b17023SJohn Marino   BIG_SINT_C_TYPE max_high, max_low;
771*e4b17023SJohn Marino   BIG_SINT_C_TYPE min_high, min_low;
772*e4b17023SJohn Marino #else
773*e4b17023SJohn Marino   BIG_UINT_C_TYPE high, low;
774*e4b17023SJohn Marino   BIG_UINT_C_TYPE max_high, max_low;
775*e4b17023SJohn Marino   BIG_UINT_C_TYPE min_high, min_low;
776*e4b17023SJohn Marino #endif
777*e4b17023SJohn Marino #if TO_FBITS > FROM_FBITS
778*e4b17023SJohn Marino   BIG_UINT_C_TYPE utemp;
779*e4b17023SJohn Marino #endif
780*e4b17023SJohn Marino #if TO_MODE_UNSIGNED == 0
781*e4b17023SJohn Marino   BIG_SINT_C_TYPE stemp;
782*e4b17023SJohn Marino #endif
783*e4b17023SJohn Marino #if TO_FBITS != FROM_FBITS
784*e4b17023SJohn Marino   int shift_amount;
785*e4b17023SJohn Marino #endif
786*e4b17023SJohn Marino   memcpy (&x, &a, FROM_FIXED_SIZE);
787*e4b17023SJohn Marino 
788*e4b17023SJohn Marino   /* Step 1. We need to store x to {high, low}.  */
789*e4b17023SJohn Marino #if FROM_MODE_UNSIGNED == 0
790*e4b17023SJohn Marino   low = (BIG_SINT_C_TYPE) x;
791*e4b17023SJohn Marino   if (x < 0)
792*e4b17023SJohn Marino     high = -1;
793*e4b17023SJohn Marino   else
794*e4b17023SJohn Marino     high = 0;
795*e4b17023SJohn Marino #else
796*e4b17023SJohn Marino   low = (BIG_UINT_C_TYPE) x;
797*e4b17023SJohn Marino   high = 0;
798*e4b17023SJohn Marino #endif
799*e4b17023SJohn Marino 
800*e4b17023SJohn Marino   /* Step 2. We need to shift {high, low}.  */
801*e4b17023SJohn Marino #if TO_FBITS > FROM_FBITS /* Left shift.  */
802*e4b17023SJohn Marino   shift_amount = TO_FBITS - FROM_FBITS;
803*e4b17023SJohn Marino   utemp = (BIG_UINT_C_TYPE) low;
804*e4b17023SJohn Marino   utemp = utemp >> (BIG_WIDTH - shift_amount);
805*e4b17023SJohn Marino   high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
806*e4b17023SJohn Marino   low = low << shift_amount;
807*e4b17023SJohn Marino #elif TO_FBITS < FROM_FBITS /* Right shift.  */
808*e4b17023SJohn Marino   shift_amount = FROM_FBITS - TO_FBITS;
809*e4b17023SJohn Marino   low = low >> shift_amount;
810*e4b17023SJohn Marino #endif
811*e4b17023SJohn Marino 
812*e4b17023SJohn Marino   /* Step 3. Compare {high, low} with max and  min of TO_FIXED_C_TYPE.  */
813*e4b17023SJohn Marino   max_high = 0;
814*e4b17023SJohn Marino #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
815*e4b17023SJohn Marino   max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
816*e4b17023SJohn Marino   max_low = max_low - 1;
817*e4b17023SJohn Marino #else
818*e4b17023SJohn Marino   max_low = -1;
819*e4b17023SJohn Marino #endif
820*e4b17023SJohn Marino 
821*e4b17023SJohn Marino #if TO_MODE_UNSIGNED == 0
822*e4b17023SJohn Marino   min_high = -1;
823*e4b17023SJohn Marino   stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1);
824*e4b17023SJohn Marino   stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS);
825*e4b17023SJohn Marino   min_low = stemp;
826*e4b17023SJohn Marino #else
827*e4b17023SJohn Marino   min_high = 0;
828*e4b17023SJohn Marino   min_low = 0;
829*e4b17023SJohn Marino #endif
830*e4b17023SJohn Marino 
831*e4b17023SJohn Marino #if FROM_MODE_UNSIGNED == 0 && TO_MODE_UNSIGNED == 0
832*e4b17023SJohn Marino   /* Signed -> Signed.  */
833*e4b17023SJohn Marino   if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
834*e4b17023SJohn Marino       || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
835*e4b17023SJohn Marino 	  && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
836*e4b17023SJohn Marino     low = max_low; /* Maximum.  */
837*e4b17023SJohn Marino   else if ((BIG_SINT_C_TYPE) high < (BIG_SINT_C_TYPE) min_high
838*e4b17023SJohn Marino 	   || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) min_high
839*e4b17023SJohn Marino 	       && (BIG_UINT_C_TYPE) low < (BIG_UINT_C_TYPE) min_low))
840*e4b17023SJohn Marino     low = min_low; /* Minimum.  */
841*e4b17023SJohn Marino #elif FROM_MODE_UNSIGNED == 1 && TO_MODE_UNSIGNED == 1
842*e4b17023SJohn Marino   /* Unigned -> Unsigned.  */
843*e4b17023SJohn Marino   if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
844*e4b17023SJohn Marino       || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
845*e4b17023SJohn Marino 	  && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
846*e4b17023SJohn Marino     low = max_low; /* Maximum.  */
847*e4b17023SJohn Marino #elif FROM_MODE_UNSIGNED == 0 && TO_MODE_UNSIGNED == 1
848*e4b17023SJohn Marino   /* Signed -> Unsigned.  */
849*e4b17023SJohn Marino   if (x < 0)
850*e4b17023SJohn Marino     low = 0; /* Minimum.  */
851*e4b17023SJohn Marino   else if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
852*e4b17023SJohn Marino 	   || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
853*e4b17023SJohn Marino 	       && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
854*e4b17023SJohn Marino     low = max_low; /* Maximum.  */
855*e4b17023SJohn Marino #elif FROM_MODE_UNSIGNED == 1 && TO_MODE_UNSIGNED == 0
856*e4b17023SJohn Marino   /* Unsigned -> Signed.  */
857*e4b17023SJohn Marino   if ((BIG_SINT_C_TYPE) high < 0)
858*e4b17023SJohn Marino     low = max_low; /* Maximum.  */
859*e4b17023SJohn Marino   else if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
860*e4b17023SJohn Marino 	   || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
861*e4b17023SJohn Marino 	       && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
862*e4b17023SJohn Marino     low = max_low; /* Maximum.  */
863*e4b17023SJohn Marino #endif
864*e4b17023SJohn Marino 
865*e4b17023SJohn Marino   /* Step 4. Store the result.  */
866*e4b17023SJohn Marino   z = (TO_INT_C_TYPE) low;
867*e4b17023SJohn Marino #if TO_HAVE_PADDING_BITS
868*e4b17023SJohn Marino   z = z << TO_PADDING_BITS;
869*e4b17023SJohn Marino   z = z >> TO_PADDING_BITS;
870*e4b17023SJohn Marino #endif
871*e4b17023SJohn Marino   memcpy (&c, &z, TO_FIXED_SIZE);
872*e4b17023SJohn Marino   return c;
873*e4b17023SJohn Marino }
874*e4b17023SJohn Marino #endif /* defined(SATFRACT) && FROM_TYPE == 4 && TO_TYPE == 4  */
875*e4b17023SJohn Marino 
876*e4b17023SJohn Marino /* Fixed -> Int.  */
877*e4b17023SJohn Marino #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 1
878*e4b17023SJohn Marino TO_INT_C_TYPE
FRACT(FROM_FIXED_C_TYPE a)879*e4b17023SJohn Marino FRACT (FROM_FIXED_C_TYPE a)
880*e4b17023SJohn Marino {
881*e4b17023SJohn Marino   FROM_INT_C_TYPE x;
882*e4b17023SJohn Marino   TO_INT_C_TYPE z;
883*e4b17023SJohn Marino   FROM_INT_C_TYPE i = 0;
884*e4b17023SJohn Marino   memcpy (&x, &a, FROM_FIXED_SIZE);
885*e4b17023SJohn Marino 
886*e4b17023SJohn Marino #if FROM_MODE_UNSIGNED == 0
887*e4b17023SJohn Marino   if (x < 0)
888*e4b17023SJohn Marino     {
889*e4b17023SJohn Marino #if FROM_FIXED_WIDTH == FROM_FBITS
890*e4b17023SJohn Marino       if (x != 0)
891*e4b17023SJohn Marino 	i = 1;
892*e4b17023SJohn Marino #else
893*e4b17023SJohn Marino       if (((FROM_INT_C_TYPE)(x << (FROM_FIXED_WIDTH - FROM_FBITS))) != 0)
894*e4b17023SJohn Marino 	i = 1;
895*e4b17023SJohn Marino #endif
896*e4b17023SJohn Marino     }
897*e4b17023SJohn Marino #endif
898*e4b17023SJohn Marino 
899*e4b17023SJohn Marino #if FROM_FIXED_WIDTH == FROM_FBITS
900*e4b17023SJohn Marino   x = 0;
901*e4b17023SJohn Marino #else
902*e4b17023SJohn Marino   x = x >> FROM_FBITS;
903*e4b17023SJohn Marino #endif
904*e4b17023SJohn Marino   x = x + i;
905*e4b17023SJohn Marino   z = (TO_INT_C_TYPE) x;
906*e4b17023SJohn Marino   return z;
907*e4b17023SJohn Marino }
908*e4b17023SJohn Marino #endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 1  */
909*e4b17023SJohn Marino 
910*e4b17023SJohn Marino /* Fixed -> Unsigned int.  */
911*e4b17023SJohn Marino #if defined(FRACTUNS) && defined(L_fractuns) && FROM_TYPE == 4 && TO_TYPE == 2
912*e4b17023SJohn Marino TO_INT_C_TYPE
FRACTUNS(FROM_FIXED_C_TYPE a)913*e4b17023SJohn Marino FRACTUNS (FROM_FIXED_C_TYPE a)
914*e4b17023SJohn Marino {
915*e4b17023SJohn Marino   FROM_INT_C_TYPE x;
916*e4b17023SJohn Marino   TO_INT_C_TYPE z;
917*e4b17023SJohn Marino   FROM_INT_C_TYPE i = 0;
918*e4b17023SJohn Marino   memcpy (&x, &a, FROM_FIXED_SIZE);
919*e4b17023SJohn Marino 
920*e4b17023SJohn Marino #if FROM_MODE_UNSIGNED == 0
921*e4b17023SJohn Marino   if (x < 0)
922*e4b17023SJohn Marino     {
923*e4b17023SJohn Marino #if FROM_FIXED_WIDTH == FROM_FBITS
924*e4b17023SJohn Marino       if (x != 0)
925*e4b17023SJohn Marino 	i = 1;
926*e4b17023SJohn Marino #else
927*e4b17023SJohn Marino       if (((FROM_INT_C_TYPE)(x << (FROM_FIXED_WIDTH - FROM_FBITS))) != 0)
928*e4b17023SJohn Marino 	i = 1;
929*e4b17023SJohn Marino #endif
930*e4b17023SJohn Marino     }
931*e4b17023SJohn Marino #endif
932*e4b17023SJohn Marino 
933*e4b17023SJohn Marino #if FROM_FIXED_WIDTH == FROM_FBITS
934*e4b17023SJohn Marino   x = 0;
935*e4b17023SJohn Marino #else
936*e4b17023SJohn Marino   x = x >> FROM_FBITS;
937*e4b17023SJohn Marino #endif
938*e4b17023SJohn Marino   x = x + i;
939*e4b17023SJohn Marino   z = (TO_INT_C_TYPE) x;
940*e4b17023SJohn Marino   return z;
941*e4b17023SJohn Marino }
942*e4b17023SJohn Marino #endif /* defined(FRACTUNS) && FROM_TYPE == 4 && TO_TYPE == 2  */
943*e4b17023SJohn Marino 
944*e4b17023SJohn Marino /* Int -> Fixed.  */
945*e4b17023SJohn Marino #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 1 && TO_TYPE == 4
946*e4b17023SJohn Marino TO_FIXED_C_TYPE
FRACT(FROM_INT_C_TYPE a)947*e4b17023SJohn Marino FRACT (FROM_INT_C_TYPE a)
948*e4b17023SJohn Marino {
949*e4b17023SJohn Marino   TO_FIXED_C_TYPE c;
950*e4b17023SJohn Marino   TO_INT_C_TYPE z;
951*e4b17023SJohn Marino   z = (TO_INT_C_TYPE) a;
952*e4b17023SJohn Marino #if TO_FIXED_WIDTH == TO_FBITS
953*e4b17023SJohn Marino   z = 0;
954*e4b17023SJohn Marino #else
955*e4b17023SJohn Marino   z = z << TO_FBITS;
956*e4b17023SJohn Marino #endif
957*e4b17023SJohn Marino #if TO_HAVE_PADDING_BITS
958*e4b17023SJohn Marino   z = z << TO_PADDING_BITS;
959*e4b17023SJohn Marino   z = z >> TO_PADDING_BITS;
960*e4b17023SJohn Marino #endif
961*e4b17023SJohn Marino   memcpy (&c, &z, TO_FIXED_SIZE);
962*e4b17023SJohn Marino   return c;
963*e4b17023SJohn Marino }
964*e4b17023SJohn Marino #endif /* defined(FRACT) && FROM_TYPE == 1 && TO_TYPE == 4  */
965*e4b17023SJohn Marino 
966*e4b17023SJohn Marino /* Signed int -> Fixed with saturation.  */
967*e4b17023SJohn Marino #if defined(SATFRACT) && defined(L_satfract) &&FROM_TYPE == 1 && TO_TYPE == 4
968*e4b17023SJohn Marino TO_FIXED_C_TYPE
SATFRACT(FROM_INT_C_TYPE a)969*e4b17023SJohn Marino SATFRACT (FROM_INT_C_TYPE a)
970*e4b17023SJohn Marino {
971*e4b17023SJohn Marino   TO_FIXED_C_TYPE c;
972*e4b17023SJohn Marino   TO_INT_C_TYPE z;
973*e4b17023SJohn Marino   FROM_INT_C_TYPE x = a;
974*e4b17023SJohn Marino   BIG_SINT_C_TYPE high, low;
975*e4b17023SJohn Marino   BIG_SINT_C_TYPE max_high, max_low;
976*e4b17023SJohn Marino   BIG_SINT_C_TYPE min_high, min_low;
977*e4b17023SJohn Marino #if TO_MODE_UNSIGNED == 0
978*e4b17023SJohn Marino   BIG_SINT_C_TYPE stemp;
979*e4b17023SJohn Marino #endif
980*e4b17023SJohn Marino #if BIG_WIDTH != TO_FBITS
981*e4b17023SJohn Marino   BIG_UINT_C_TYPE utemp;
982*e4b17023SJohn Marino   int shift_amount;
983*e4b17023SJohn Marino #endif
984*e4b17023SJohn Marino 
985*e4b17023SJohn Marino   /* Step 1. We need to store x to {high, low}.  */
986*e4b17023SJohn Marino   low = (BIG_SINT_C_TYPE) x;
987*e4b17023SJohn Marino   if (x < 0)
988*e4b17023SJohn Marino     high = -1;
989*e4b17023SJohn Marino   else
990*e4b17023SJohn Marino     high = 0;
991*e4b17023SJohn Marino 
992*e4b17023SJohn Marino   /* Step 2. We need to left shift {high, low}.  */
993*e4b17023SJohn Marino #if BIG_WIDTH == TO_FBITS
994*e4b17023SJohn Marino   high = low;
995*e4b17023SJohn Marino   low = 0;
996*e4b17023SJohn Marino #else
997*e4b17023SJohn Marino   shift_amount = TO_FBITS;
998*e4b17023SJohn Marino   utemp = (BIG_UINT_C_TYPE) low;
999*e4b17023SJohn Marino   utemp = utemp >> (BIG_WIDTH - shift_amount);
1000*e4b17023SJohn Marino   high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
1001*e4b17023SJohn Marino   low = low << shift_amount;
1002*e4b17023SJohn Marino #endif
1003*e4b17023SJohn Marino 
1004*e4b17023SJohn Marino   /* Step 3. Compare {high, low} with max and  min of TO_FIXED_C_TYPE.  */
1005*e4b17023SJohn Marino   max_high = 0;
1006*e4b17023SJohn Marino #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
1007*e4b17023SJohn Marino   max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
1008*e4b17023SJohn Marino   max_low = max_low - 1;
1009*e4b17023SJohn Marino #else
1010*e4b17023SJohn Marino   max_low = -1;
1011*e4b17023SJohn Marino #endif
1012*e4b17023SJohn Marino 
1013*e4b17023SJohn Marino #if TO_MODE_UNSIGNED == 0
1014*e4b17023SJohn Marino   min_high = -1;
1015*e4b17023SJohn Marino   stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1);
1016*e4b17023SJohn Marino   stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS);
1017*e4b17023SJohn Marino   min_low = stemp;
1018*e4b17023SJohn Marino #else
1019*e4b17023SJohn Marino   min_high = 0;
1020*e4b17023SJohn Marino   min_low = 0;
1021*e4b17023SJohn Marino #endif
1022*e4b17023SJohn Marino 
1023*e4b17023SJohn Marino #if TO_MODE_UNSIGNED == 0
1024*e4b17023SJohn Marino   /* Signed -> Signed.  */
1025*e4b17023SJohn Marino   if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
1026*e4b17023SJohn Marino       || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
1027*e4b17023SJohn Marino           && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1028*e4b17023SJohn Marino     low = max_low; /* Maximum.  */
1029*e4b17023SJohn Marino   else if ((BIG_SINT_C_TYPE) high < (BIG_SINT_C_TYPE) min_high
1030*e4b17023SJohn Marino            || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) min_high
1031*e4b17023SJohn Marino                && (BIG_UINT_C_TYPE) low < (BIG_UINT_C_TYPE) min_low))
1032*e4b17023SJohn Marino     low = min_low; /* Minimum.  */
1033*e4b17023SJohn Marino #else
1034*e4b17023SJohn Marino   /* Signed -> Unsigned.  */
1035*e4b17023SJohn Marino   if (x < 0)
1036*e4b17023SJohn Marino     low = 0; /* Minimum.  */
1037*e4b17023SJohn Marino   else if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
1038*e4b17023SJohn Marino            || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
1039*e4b17023SJohn Marino                && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1040*e4b17023SJohn Marino     low = max_low; /* Maximum.  */
1041*e4b17023SJohn Marino #endif
1042*e4b17023SJohn Marino 
1043*e4b17023SJohn Marino   /* Step 4. Store the result.  */
1044*e4b17023SJohn Marino   z = (TO_INT_C_TYPE) low;
1045*e4b17023SJohn Marino #if TO_HAVE_PADDING_BITS
1046*e4b17023SJohn Marino   z = z << TO_PADDING_BITS;
1047*e4b17023SJohn Marino   z = z >> TO_PADDING_BITS;
1048*e4b17023SJohn Marino #endif
1049*e4b17023SJohn Marino   memcpy (&c, &z, TO_FIXED_SIZE);
1050*e4b17023SJohn Marino   return c;
1051*e4b17023SJohn Marino }
1052*e4b17023SJohn Marino #endif /* defined(SATFRACT) && FROM_TYPE == 1 && TO_TYPE == 4  */
1053*e4b17023SJohn Marino 
1054*e4b17023SJohn Marino /* Unsigned int -> Fixed.  */
1055*e4b17023SJohn Marino #if defined(FRACTUNS) && defined(L_fractuns) &&FROM_TYPE == 2 && TO_TYPE == 4
1056*e4b17023SJohn Marino TO_FIXED_C_TYPE
FRACTUNS(FROM_INT_C_TYPE a)1057*e4b17023SJohn Marino FRACTUNS (FROM_INT_C_TYPE a)
1058*e4b17023SJohn Marino {
1059*e4b17023SJohn Marino   TO_FIXED_C_TYPE c;
1060*e4b17023SJohn Marino   TO_INT_C_TYPE z;
1061*e4b17023SJohn Marino   z = (TO_INT_C_TYPE) a;
1062*e4b17023SJohn Marino #if TO_FIXED_WIDTH == TO_FBITS
1063*e4b17023SJohn Marino   z = 0;
1064*e4b17023SJohn Marino #else
1065*e4b17023SJohn Marino   z = z << TO_FBITS;
1066*e4b17023SJohn Marino #endif
1067*e4b17023SJohn Marino #if TO_HAVE_PADDING_BITS
1068*e4b17023SJohn Marino   z = z << TO_PADDING_BITS;
1069*e4b17023SJohn Marino   z = z >> TO_PADDING_BITS;
1070*e4b17023SJohn Marino #endif
1071*e4b17023SJohn Marino   memcpy (&c, &z, TO_FIXED_SIZE);
1072*e4b17023SJohn Marino   return c;
1073*e4b17023SJohn Marino }
1074*e4b17023SJohn Marino #endif /* defined(FRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4  */
1075*e4b17023SJohn Marino 
1076*e4b17023SJohn Marino /* Unsigned int -> Fixed with saturation.  */
1077*e4b17023SJohn Marino #if defined(SATFRACTUNS) && defined(L_satfractuns) && FROM_TYPE == 2 && TO_TYPE == 4
1078*e4b17023SJohn Marino TO_FIXED_C_TYPE
SATFRACTUNS(FROM_INT_C_TYPE a)1079*e4b17023SJohn Marino SATFRACTUNS (FROM_INT_C_TYPE a)
1080*e4b17023SJohn Marino {
1081*e4b17023SJohn Marino   TO_FIXED_C_TYPE c;
1082*e4b17023SJohn Marino   TO_INT_C_TYPE z;
1083*e4b17023SJohn Marino   FROM_INT_C_TYPE x = a;
1084*e4b17023SJohn Marino   BIG_UINT_C_TYPE high, low;
1085*e4b17023SJohn Marino   BIG_UINT_C_TYPE max_high, max_low;
1086*e4b17023SJohn Marino #if BIG_WIDTH != TO_FBITS
1087*e4b17023SJohn Marino   BIG_UINT_C_TYPE utemp;
1088*e4b17023SJohn Marino   int shift_amount;
1089*e4b17023SJohn Marino #endif
1090*e4b17023SJohn Marino 
1091*e4b17023SJohn Marino   /* Step 1. We need to store x to {high, low}.  */
1092*e4b17023SJohn Marino   low = (BIG_UINT_C_TYPE) x;
1093*e4b17023SJohn Marino   high = 0;
1094*e4b17023SJohn Marino 
1095*e4b17023SJohn Marino   /* Step 2. We need to left shift {high, low}.  */
1096*e4b17023SJohn Marino #if BIG_WIDTH == TO_FBITS
1097*e4b17023SJohn Marino   high = low;
1098*e4b17023SJohn Marino   low = 0;
1099*e4b17023SJohn Marino #else
1100*e4b17023SJohn Marino   shift_amount = TO_FBITS;
1101*e4b17023SJohn Marino   utemp = (BIG_UINT_C_TYPE) low;
1102*e4b17023SJohn Marino   utemp = utemp >> (BIG_WIDTH - shift_amount);
1103*e4b17023SJohn Marino   high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
1104*e4b17023SJohn Marino   low = low << shift_amount;
1105*e4b17023SJohn Marino #endif
1106*e4b17023SJohn Marino 
1107*e4b17023SJohn Marino   /* Step 3. Compare {high, low} with max and  min of TO_FIXED_C_TYPE.  */
1108*e4b17023SJohn Marino   max_high = 0;
1109*e4b17023SJohn Marino #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
1110*e4b17023SJohn Marino   max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
1111*e4b17023SJohn Marino   max_low = max_low - 1;
1112*e4b17023SJohn Marino #else
1113*e4b17023SJohn Marino   max_low = -1;
1114*e4b17023SJohn Marino #endif
1115*e4b17023SJohn Marino 
1116*e4b17023SJohn Marino #if TO_MODE_UNSIGNED == 1
1117*e4b17023SJohn Marino   /* Unigned -> Unsigned.  */
1118*e4b17023SJohn Marino   if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
1119*e4b17023SJohn Marino       || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
1120*e4b17023SJohn Marino           && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1121*e4b17023SJohn Marino     low = max_low; /* Maximum.  */
1122*e4b17023SJohn Marino #else
1123*e4b17023SJohn Marino   /* Unsigned -> Signed.  */
1124*e4b17023SJohn Marino   if ((BIG_SINT_C_TYPE) high < 0)
1125*e4b17023SJohn Marino     low = max_low; /* Maximum.  */
1126*e4b17023SJohn Marino   else if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
1127*e4b17023SJohn Marino            || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
1128*e4b17023SJohn Marino                && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1129*e4b17023SJohn Marino     low = max_low; /* Maximum.  */
1130*e4b17023SJohn Marino #endif
1131*e4b17023SJohn Marino 
1132*e4b17023SJohn Marino   /* Step 4. Store the result.  */
1133*e4b17023SJohn Marino   z = (TO_INT_C_TYPE) low;
1134*e4b17023SJohn Marino #if TO_HAVE_PADDING_BITS
1135*e4b17023SJohn Marino   z = z << TO_PADDING_BITS;
1136*e4b17023SJohn Marino   z = z >> TO_PADDING_BITS;
1137*e4b17023SJohn Marino #endif
1138*e4b17023SJohn Marino   memcpy (&c, &z, TO_FIXED_SIZE);
1139*e4b17023SJohn Marino   return c;
1140*e4b17023SJohn Marino }
1141*e4b17023SJohn Marino #endif /* defined(SATFRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4  */
1142*e4b17023SJohn Marino 
1143*e4b17023SJohn Marino /* Fixed -> Float.  */
1144*e4b17023SJohn Marino #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 3
1145*e4b17023SJohn Marino TO_FLOAT_C_TYPE
FRACT(FROM_FIXED_C_TYPE a)1146*e4b17023SJohn Marino FRACT (FROM_FIXED_C_TYPE a)
1147*e4b17023SJohn Marino {
1148*e4b17023SJohn Marino   FROM_INT_C_TYPE x;
1149*e4b17023SJohn Marino   TO_FLOAT_C_TYPE z;
1150*e4b17023SJohn Marino   memcpy (&x, &a, FROM_FIXED_SIZE);
1151*e4b17023SJohn Marino   z = (TO_FLOAT_C_TYPE) x;
1152*e4b17023SJohn Marino   z = z / BASE;
1153*e4b17023SJohn Marino   return z;
1154*e4b17023SJohn Marino }
1155*e4b17023SJohn Marino #endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 3  */
1156*e4b17023SJohn Marino 
1157*e4b17023SJohn Marino /* Float -> Fixed.  */
1158*e4b17023SJohn Marino #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 3 && TO_TYPE == 4
1159*e4b17023SJohn Marino TO_FIXED_C_TYPE
FRACT(FROM_FLOAT_C_TYPE a)1160*e4b17023SJohn Marino FRACT (FROM_FLOAT_C_TYPE a)
1161*e4b17023SJohn Marino {
1162*e4b17023SJohn Marino   FROM_FLOAT_C_TYPE temp;
1163*e4b17023SJohn Marino   TO_INT_C_TYPE z;
1164*e4b17023SJohn Marino   TO_FIXED_C_TYPE c;
1165*e4b17023SJohn Marino 
1166*e4b17023SJohn Marino   temp = a * BASE;
1167*e4b17023SJohn Marino   z = (TO_INT_C_TYPE) temp;
1168*e4b17023SJohn Marino #if TO_HAVE_PADDING_BITS
1169*e4b17023SJohn Marino   z = z << TO_PADDING_BITS;
1170*e4b17023SJohn Marino   z = z >> TO_PADDING_BITS;
1171*e4b17023SJohn Marino #endif
1172*e4b17023SJohn Marino   memcpy (&c, &z, TO_FIXED_SIZE);
1173*e4b17023SJohn Marino   return c;
1174*e4b17023SJohn Marino }
1175*e4b17023SJohn Marino #endif /* defined(FRACT) && FROM_TYPE == 3 && TO_TYPE == 4  */
1176*e4b17023SJohn Marino 
1177*e4b17023SJohn Marino /* Float -> Fixed with saturation.  */
1178*e4b17023SJohn Marino #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 3 && TO_TYPE == 4
1179*e4b17023SJohn Marino TO_FIXED_C_TYPE
SATFRACT(FROM_FLOAT_C_TYPE a)1180*e4b17023SJohn Marino SATFRACT (FROM_FLOAT_C_TYPE a)
1181*e4b17023SJohn Marino {
1182*e4b17023SJohn Marino   FROM_FLOAT_C_TYPE temp;
1183*e4b17023SJohn Marino   TO_INT_C_TYPE z;
1184*e4b17023SJohn Marino   TO_FIXED_C_TYPE c;
1185*e4b17023SJohn Marino 
1186*e4b17023SJohn Marino   if (a >= FIXED_MAX)
1187*e4b17023SJohn Marino     {
1188*e4b17023SJohn Marino #if TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
1189*e4b17023SJohn Marino       z = (TO_INT_C_TYPE)1 << TO_I_F_BITS;
1190*e4b17023SJohn Marino       z = z - 1;
1191*e4b17023SJohn Marino #else
1192*e4b17023SJohn Marino       z = -1;
1193*e4b17023SJohn Marino #endif
1194*e4b17023SJohn Marino     }
1195*e4b17023SJohn Marino   else if (a <= FIXED_MIN)
1196*e4b17023SJohn Marino     {
1197*e4b17023SJohn Marino #if TO_MODE_UNSIGNED == 0
1198*e4b17023SJohn Marino       z = (TO_INT_C_TYPE)1 << TO_I_F_BITS;
1199*e4b17023SJohn Marino #else
1200*e4b17023SJohn Marino       z = 0;
1201*e4b17023SJohn Marino #endif
1202*e4b17023SJohn Marino     }
1203*e4b17023SJohn Marino   else
1204*e4b17023SJohn Marino     {
1205*e4b17023SJohn Marino       temp = a * BASE;
1206*e4b17023SJohn Marino       z = (TO_INT_C_TYPE) temp;
1207*e4b17023SJohn Marino     }
1208*e4b17023SJohn Marino 
1209*e4b17023SJohn Marino #if TO_HAVE_PADDING_BITS
1210*e4b17023SJohn Marino   z = z << TO_PADDING_BITS;
1211*e4b17023SJohn Marino   z = z >> TO_PADDING_BITS;
1212*e4b17023SJohn Marino #endif
1213*e4b17023SJohn Marino   memcpy (&c, &z, TO_FIXED_SIZE);
1214*e4b17023SJohn Marino   return c;
1215*e4b17023SJohn Marino }
1216*e4b17023SJohn Marino #endif /* defined(SATFRACT) && FROM_TYPE == 3 && TO_TYPE == 4  */
1217*e4b17023SJohn Marino 
1218