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