xref: /netbsd-src/external/gpl3/gcc/dist/libgcc/fixed-bit.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
148fb7bfaSmrg /* This is a software fixed-point library.
2*b1e83836Smrg    Copyright (C) 2007-2022 Free Software Foundation, Inc.
348fb7bfaSmrg 
448fb7bfaSmrg This file is part of GCC.
548fb7bfaSmrg 
648fb7bfaSmrg GCC is free software; you can redistribute it and/or modify it under
748fb7bfaSmrg the terms of the GNU General Public License as published by the Free
848fb7bfaSmrg Software Foundation; either version 3, or (at your option) any later
948fb7bfaSmrg version.
1048fb7bfaSmrg 
1148fb7bfaSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1248fb7bfaSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
1348fb7bfaSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1448fb7bfaSmrg for more details.
1548fb7bfaSmrg 
1648fb7bfaSmrg Under Section 7 of GPL version 3, you are granted additional
1748fb7bfaSmrg permissions described in the GCC Runtime Library Exception, version
1848fb7bfaSmrg 3.1, as published by the Free Software Foundation.
1948fb7bfaSmrg 
2048fb7bfaSmrg You should have received a copy of the GNU General Public License and
2148fb7bfaSmrg a copy of the GCC Runtime Library Exception along with this program;
2248fb7bfaSmrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2348fb7bfaSmrg <http://www.gnu.org/licenses/>.  */
2448fb7bfaSmrg 
2548fb7bfaSmrg /* This implements fixed-point arithmetic.
2648fb7bfaSmrg 
2748fb7bfaSmrg    Contributed by Chao-ying Fu  <fu@mips.com>.  */
2848fb7bfaSmrg 
2948fb7bfaSmrg /* To use this file, we need to define one of the following:
3048fb7bfaSmrg    QQ_MODE, UQQ_MODE, HQ_MODE, UHQ_MODE, SQ_MODE, USQ_MODE, DQ_MODE, UDQ_MODE,
3148fb7bfaSmrg    TQ_MODE, UTQ_MODE, HA_MODE, UHA_MODE, SA_MODE, USA_MODE, DA_MODE, UDA_MODE,
3248fb7bfaSmrg    TA_MODE, UTA_MODE.
3348fb7bfaSmrg    Then, all operators for this machine mode will be created.
3448fb7bfaSmrg 
3548fb7bfaSmrg    Or, we need to define FROM_* TO_* for conversions from one mode to another
3648fb7bfaSmrg    mode.  The mode could be one of the following:
3748fb7bfaSmrg    Fract: QQ, UQQ, HQ, UHQ, SQ, USQ, DQ, UDQ, TQ, UTQ
3848fb7bfaSmrg    Accum: HA, UHA, SA, USA, DA, UDA, TA, UTA
3948fb7bfaSmrg    Signed integer: QI, HI, SI, DI, TI
4048fb7bfaSmrg    Unsigned integer: UQI, UHI, USI, UDI, UTI
4148fb7bfaSmrg    Floating-point: SF, DF
4248fb7bfaSmrg    Ex: If we define FROM_QQ and TO_SI, the conversion from QQ to SI is
4348fb7bfaSmrg    generated.  */
4448fb7bfaSmrg 
4548fb7bfaSmrg #include "tconfig.h"
4648fb7bfaSmrg #include "tsystem.h"
4748fb7bfaSmrg #include "coretypes.h"
4848fb7bfaSmrg #include "tm.h"
4948fb7bfaSmrg #include "libgcc_tm.h"
5048fb7bfaSmrg 
5148fb7bfaSmrg #ifndef MIN_UNITS_PER_WORD
5248fb7bfaSmrg #define MIN_UNITS_PER_WORD UNITS_PER_WORD
5348fb7bfaSmrg #endif
5448fb7bfaSmrg 
5548fb7bfaSmrg #include "fixed-bit.h"
5648fb7bfaSmrg 
5748fb7bfaSmrg #if defined(FIXED_ADD) && defined(L_add)
5848fb7bfaSmrg FIXED_C_TYPE
FIXED_ADD(FIXED_C_TYPE a,FIXED_C_TYPE b)5948fb7bfaSmrg FIXED_ADD (FIXED_C_TYPE a, FIXED_C_TYPE b)
6048fb7bfaSmrg {
6148fb7bfaSmrg   FIXED_C_TYPE c;
6248fb7bfaSmrg   INT_C_TYPE x, y, z;
6348fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
6448fb7bfaSmrg   memcpy (&y, &b, FIXED_SIZE);
6548fb7bfaSmrg   z = x + y;
6648fb7bfaSmrg #if HAVE_PADDING_BITS
6748fb7bfaSmrg   z = z << PADDING_BITS;
6848fb7bfaSmrg   z = z >> PADDING_BITS;
6948fb7bfaSmrg #endif
7048fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
7148fb7bfaSmrg   return c;
7248fb7bfaSmrg }
7348fb7bfaSmrg #endif /* FIXED_ADD */
7448fb7bfaSmrg 
7548fb7bfaSmrg #if defined(FIXED_SSADD) && defined(L_ssadd)
7648fb7bfaSmrg FIXED_C_TYPE
FIXED_SSADD(FIXED_C_TYPE a,FIXED_C_TYPE b)7748fb7bfaSmrg FIXED_SSADD (FIXED_C_TYPE a, FIXED_C_TYPE b)
7848fb7bfaSmrg {
7948fb7bfaSmrg   FIXED_C_TYPE c;
8048fb7bfaSmrg   INT_C_TYPE x, y, z;
8148fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
8248fb7bfaSmrg   memcpy (&y, &b, FIXED_SIZE);
8348fb7bfaSmrg   z = x + (UINT_C_TYPE) y;
8448fb7bfaSmrg   if ((((x ^ y) >> I_F_BITS) & 1) == 0)
8548fb7bfaSmrg     {
8648fb7bfaSmrg       if (((z ^ x) >> I_F_BITS) & 1)
8748fb7bfaSmrg         {
8848fb7bfaSmrg 	  z = ((UINT_C_TYPE) 1) << I_F_BITS;
8948fb7bfaSmrg 	  if (x >= 0)
9048fb7bfaSmrg 	    z -= (UINT_C_TYPE) 1;
9148fb7bfaSmrg         }
9248fb7bfaSmrg     }
9348fb7bfaSmrg #if HAVE_PADDING_BITS
9448fb7bfaSmrg   z = z << PADDING_BITS;
9548fb7bfaSmrg   z = z >> PADDING_BITS;
9648fb7bfaSmrg #endif
9748fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
9848fb7bfaSmrg   return c;
9948fb7bfaSmrg }
10048fb7bfaSmrg #endif /* FIXED_SSADD */
10148fb7bfaSmrg 
10248fb7bfaSmrg #if defined(FIXED_USADD) && defined(L_usadd)
10348fb7bfaSmrg FIXED_C_TYPE
FIXED_USADD(FIXED_C_TYPE a,FIXED_C_TYPE b)10448fb7bfaSmrg FIXED_USADD (FIXED_C_TYPE a, FIXED_C_TYPE b)
10548fb7bfaSmrg {
10648fb7bfaSmrg   FIXED_C_TYPE c;
10748fb7bfaSmrg   INT_C_TYPE x, y, z;
10848fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
10948fb7bfaSmrg   memcpy (&y, &b, FIXED_SIZE);
11048fb7bfaSmrg   z = x + y;
11148fb7bfaSmrg #if HAVE_PADDING_BITS
11248fb7bfaSmrg   z = z << PADDING_BITS;
11348fb7bfaSmrg   z = z >> PADDING_BITS;
11448fb7bfaSmrg #endif
11548fb7bfaSmrg   if (z < x || z < y) /* max */
11648fb7bfaSmrg     {
11748fb7bfaSmrg        z = -1;
11848fb7bfaSmrg #if HAVE_PADDING_BITS
11948fb7bfaSmrg        z = z << PADDING_BITS;
12048fb7bfaSmrg        z = z >> PADDING_BITS;
12148fb7bfaSmrg #endif
12248fb7bfaSmrg     }
12348fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
12448fb7bfaSmrg   return c;
12548fb7bfaSmrg }
12648fb7bfaSmrg #endif /* FIXED_USADD */
12748fb7bfaSmrg 
12848fb7bfaSmrg #if defined(FIXED_SUB) && defined(L_sub)
12948fb7bfaSmrg FIXED_C_TYPE
FIXED_SUB(FIXED_C_TYPE a,FIXED_C_TYPE b)13048fb7bfaSmrg FIXED_SUB (FIXED_C_TYPE a, FIXED_C_TYPE b)
13148fb7bfaSmrg {
13248fb7bfaSmrg   FIXED_C_TYPE c;
13348fb7bfaSmrg   INT_C_TYPE x, y, z;
13448fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
13548fb7bfaSmrg   memcpy (&y, &b, FIXED_SIZE);
13648fb7bfaSmrg   z = x - y;
13748fb7bfaSmrg #if HAVE_PADDING_BITS
13848fb7bfaSmrg   z = z << PADDING_BITS;
13948fb7bfaSmrg   z = z >> PADDING_BITS;
14048fb7bfaSmrg #endif
14148fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
14248fb7bfaSmrg   return c;
14348fb7bfaSmrg }
14448fb7bfaSmrg #endif /* FIXED_SUB */
14548fb7bfaSmrg 
14648fb7bfaSmrg #if defined(FIXED_SSSUB) && defined(L_sssub)
14748fb7bfaSmrg FIXED_C_TYPE
FIXED_SSSUB(FIXED_C_TYPE a,FIXED_C_TYPE b)14848fb7bfaSmrg FIXED_SSSUB (FIXED_C_TYPE a, FIXED_C_TYPE b)
14948fb7bfaSmrg {
15048fb7bfaSmrg   FIXED_C_TYPE c;
15148fb7bfaSmrg   INT_C_TYPE x, y, z;
15248fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
15348fb7bfaSmrg   memcpy (&y, &b, FIXED_SIZE);
15448fb7bfaSmrg   z = x - (UINT_C_TYPE) y;
15548fb7bfaSmrg   if (((x ^ y) >> I_F_BITS) & 1)
15648fb7bfaSmrg     {
15748fb7bfaSmrg       if (((z ^ x) >> I_F_BITS) & 1)
15848fb7bfaSmrg         {
15948fb7bfaSmrg 	  z = ((UINT_C_TYPE) 1) << I_F_BITS;
16048fb7bfaSmrg 	  if (x >= 0)
16148fb7bfaSmrg 	    z -= (UINT_C_TYPE) 1;
16248fb7bfaSmrg         }
16348fb7bfaSmrg     }
16448fb7bfaSmrg #if HAVE_PADDING_BITS
16548fb7bfaSmrg   z = z << PADDING_BITS;
16648fb7bfaSmrg   z = z >> PADDING_BITS;
16748fb7bfaSmrg #endif
16848fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
16948fb7bfaSmrg   return c;
17048fb7bfaSmrg }
17148fb7bfaSmrg #endif /* FIXED_SSSUB */
17248fb7bfaSmrg 
17348fb7bfaSmrg #if defined(FIXED_USSUB) && defined(L_ussub)
17448fb7bfaSmrg FIXED_C_TYPE
FIXED_USSUB(FIXED_C_TYPE a,FIXED_C_TYPE b)17548fb7bfaSmrg FIXED_USSUB (FIXED_C_TYPE a, FIXED_C_TYPE b)
17648fb7bfaSmrg {
17748fb7bfaSmrg   FIXED_C_TYPE c;
17848fb7bfaSmrg   INT_C_TYPE x, y, z;
17948fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
18048fb7bfaSmrg   memcpy (&y, &b, FIXED_SIZE);
18148fb7bfaSmrg   z = x - y;
18248fb7bfaSmrg   if (x < y)
18348fb7bfaSmrg     z = 0;
18448fb7bfaSmrg #if HAVE_PADDING_BITS
18548fb7bfaSmrg   z = z << PADDING_BITS;
18648fb7bfaSmrg   z = z >> PADDING_BITS;
18748fb7bfaSmrg #endif
18848fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
18948fb7bfaSmrg   return c;
19048fb7bfaSmrg }
19148fb7bfaSmrg #endif /* FIXED_USSUB */
19248fb7bfaSmrg 
19348fb7bfaSmrg #if defined(FIXED_SATURATE1) && defined(L_saturate1)
19448fb7bfaSmrg void
FIXED_SATURATE1(DINT_C_TYPE * a)19548fb7bfaSmrg FIXED_SATURATE1 (DINT_C_TYPE *a)
19648fb7bfaSmrg {
19748fb7bfaSmrg   DINT_C_TYPE max, min;
19848fb7bfaSmrg   max = (DINT_C_TYPE)1 << I_F_BITS;
19948fb7bfaSmrg   max = max - 1;
20048fb7bfaSmrg #if MODE_UNSIGNED == 0
20148fb7bfaSmrg   min = (DINT_C_TYPE)1 << (2 * FIXED_WIDTH - 1);
20248fb7bfaSmrg   min = min >> (2 * FIXED_WIDTH - 1 - I_F_BITS);
20348fb7bfaSmrg #else
20448fb7bfaSmrg   min = 0;
20548fb7bfaSmrg #endif
20648fb7bfaSmrg   if (*a > max)
20748fb7bfaSmrg     *a = max;
20848fb7bfaSmrg   else if (*a < min)
20948fb7bfaSmrg     *a = min;
21048fb7bfaSmrg }
21148fb7bfaSmrg #endif /* FIXED_SATURATE1 */
21248fb7bfaSmrg 
21348fb7bfaSmrg #if defined(FIXED_SATURATE2) && defined(L_saturate2)
21448fb7bfaSmrg void
FIXED_SATURATE2(INT_C_TYPE * high,INT_C_TYPE * low)21548fb7bfaSmrg FIXED_SATURATE2 (INT_C_TYPE *high, INT_C_TYPE *low)
21648fb7bfaSmrg {
21748fb7bfaSmrg   INT_C_TYPE r_max, s_max, r_min, s_min;
21848fb7bfaSmrg   r_max = 0;
21948fb7bfaSmrg #if (MODE_UNSIGNED == 0) || HAVE_PADDING_BITS
22048fb7bfaSmrg   s_max = (INT_C_TYPE)1 << I_F_BITS;
22148fb7bfaSmrg   s_max = s_max - 1;
22248fb7bfaSmrg #else
22348fb7bfaSmrg   s_max = -1;
22448fb7bfaSmrg #endif
22548fb7bfaSmrg #if MODE_UNSIGNED == 0
22648fb7bfaSmrg   r_min = -1;
22748fb7bfaSmrg   s_min = (INT_C_TYPE)1 << (FIXED_WIDTH - 1);
22848fb7bfaSmrg   s_min = s_min >> (FIXED_WIDTH - 1 - I_F_BITS);
22948fb7bfaSmrg #else
23048fb7bfaSmrg   r_min = 0;
23148fb7bfaSmrg   s_min = 0;
23248fb7bfaSmrg #endif
23348fb7bfaSmrg 
23448fb7bfaSmrg   if (*high > r_max
23548fb7bfaSmrg       || (*high == r_max && (UINT_C_TYPE)(*low) > (UINT_C_TYPE)s_max))
23648fb7bfaSmrg     {
23748fb7bfaSmrg       *high = r_max;
23848fb7bfaSmrg       *low = s_max;
23948fb7bfaSmrg     }
24048fb7bfaSmrg   else if (*high < r_min ||
24148fb7bfaSmrg 	   (*high == r_min && (UINT_C_TYPE)(*low) < (UINT_C_TYPE)s_min))
24248fb7bfaSmrg     {
24348fb7bfaSmrg       *high = r_min;
24448fb7bfaSmrg       *low = s_min;
24548fb7bfaSmrg     }
24648fb7bfaSmrg }
24748fb7bfaSmrg #endif /* FIXED_SATURATE2 */
24848fb7bfaSmrg 
24948fb7bfaSmrg #if defined(FIXED_MULHELPER) && defined(L_mulhelper)
25048fb7bfaSmrg FIXED_C_TYPE
FIXED_MULHELPER(FIXED_C_TYPE a,FIXED_C_TYPE b,word_type satp)25148fb7bfaSmrg FIXED_MULHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp)
25248fb7bfaSmrg {
25348fb7bfaSmrg   FIXED_C_TYPE c;
25448fb7bfaSmrg   INT_C_TYPE x, y;
25548fb7bfaSmrg 
25648fb7bfaSmrg #if defined (DINT_C_TYPE)
25748fb7bfaSmrg   INT_C_TYPE z;
25848fb7bfaSmrg   DINT_C_TYPE dx, dy, dz;
25948fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
26048fb7bfaSmrg   memcpy (&y, &b, FIXED_SIZE);
26148fb7bfaSmrg   dx = (DINT_C_TYPE) x;
26248fb7bfaSmrg   dy = (DINT_C_TYPE) y;
26348fb7bfaSmrg   dz = dx * dy;
26448fb7bfaSmrg   /* Round the result by adding (1 << (FBITS -1)).  */
26548fb7bfaSmrg   dz += ((DINT_C_TYPE) 1 << (FBITS - 1));
26648fb7bfaSmrg   dz = dz >> FBITS;
26748fb7bfaSmrg   if (satp)
26848fb7bfaSmrg     FIXED_SATURATE1 (&dz);
26948fb7bfaSmrg 
27048fb7bfaSmrg   z = (INT_C_TYPE) dz;
27148fb7bfaSmrg #if HAVE_PADDING_BITS
27248fb7bfaSmrg   z = z << PADDING_BITS;
27348fb7bfaSmrg   z = z >> PADDING_BITS;
27448fb7bfaSmrg #endif
27548fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
27648fb7bfaSmrg   return c;
27748fb7bfaSmrg 
27848fb7bfaSmrg #else /* No DINT_C_TYPE */
27948fb7bfaSmrg   /* The result of multiplication expands to two INT_C_TYPE.  */
28048fb7bfaSmrg   INTunion aa, bb;
28148fb7bfaSmrg   INTunion a_high, a_low, b_high, b_low;
28248fb7bfaSmrg   INTunion high_high, high_low, low_high, low_low;
28348fb7bfaSmrg   INTunion r, s, temp1, temp2;
28448fb7bfaSmrg   INT_C_TYPE carry = 0;
28548fb7bfaSmrg   INT_C_TYPE z;
28648fb7bfaSmrg 
28748fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
28848fb7bfaSmrg   memcpy (&y, &b, FIXED_SIZE);
28948fb7bfaSmrg 
29048fb7bfaSmrg   /* Decompose a and b.  */
29148fb7bfaSmrg   aa.ll = x;
29248fb7bfaSmrg   bb.ll = y;
29348fb7bfaSmrg 
29448fb7bfaSmrg   a_high.s.low = aa.s.high;
29548fb7bfaSmrg   a_high.s.high = 0;
29648fb7bfaSmrg   a_low.s.low = aa.s.low;
29748fb7bfaSmrg   a_low.s.high = 0;
29848fb7bfaSmrg   b_high.s.low = bb.s.high;
29948fb7bfaSmrg   b_high.s.high = 0;
30048fb7bfaSmrg   b_low.s.low = bb.s.low;
30148fb7bfaSmrg   b_low.s.high = 0;
30248fb7bfaSmrg 
30348fb7bfaSmrg   /* Perform four multiplications.  */
30448fb7bfaSmrg   low_low.ll = a_low.ll * b_low.ll;
30548fb7bfaSmrg   low_high.ll = a_low.ll * b_high.ll;
30648fb7bfaSmrg   high_low.ll = a_high.ll * b_low.ll;
30748fb7bfaSmrg   high_high.ll = a_high.ll * b_high.ll;
30848fb7bfaSmrg 
30948fb7bfaSmrg   /* Accumulate four results to {r, s}.  */
31048fb7bfaSmrg   temp1.s.high = high_low.s.low;
31148fb7bfaSmrg   temp1.s.low = 0;
31248fb7bfaSmrg   s.ll = low_low.ll + temp1.ll;
31348fb7bfaSmrg   if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) low_low.ll
31448fb7bfaSmrg       || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll)
31548fb7bfaSmrg     carry ++; /* Carry.  */
31648fb7bfaSmrg   temp1.ll = s.ll;
31748fb7bfaSmrg   temp2.s.high = low_high.s.low;
31848fb7bfaSmrg   temp2.s.low = 0;
31948fb7bfaSmrg   s.ll = temp1.ll + temp2.ll;
32048fb7bfaSmrg   if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll
32148fb7bfaSmrg       || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp2.ll)
32248fb7bfaSmrg     carry ++; /* Carry.  */
32348fb7bfaSmrg 
32448fb7bfaSmrg   temp1.s.low = high_low.s.high;
32548fb7bfaSmrg   temp1.s.high = 0;
32648fb7bfaSmrg   r.ll = high_high.ll + temp1.ll;
32748fb7bfaSmrg   temp1.s.low = low_high.s.high;
32848fb7bfaSmrg   temp1.s.high = 0;
32948fb7bfaSmrg   r.ll = r.ll + temp1.ll + carry;
33048fb7bfaSmrg 
33148fb7bfaSmrg #if MODE_UNSIGNED == 0
33248fb7bfaSmrg   /* For signed types, we need to add neg(y) to r, if x < 0.  */
33348fb7bfaSmrg   if (x < 0)
33448fb7bfaSmrg     r.ll = r.ll - y;
33548fb7bfaSmrg   /* We need to add neg(x) to r, if y < 0.  */
33648fb7bfaSmrg   if (y < 0)
33748fb7bfaSmrg     r.ll = r.ll - x;
33848fb7bfaSmrg #endif
33948fb7bfaSmrg 
34048fb7bfaSmrg   /* Round the result by adding (1 << (FBITS -1)).  */
34148fb7bfaSmrg   temp1.ll = s.ll;
34248fb7bfaSmrg   s.ll += ((INT_C_TYPE) 1 << (FBITS -1));
34348fb7bfaSmrg   if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll
34448fb7bfaSmrg       || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) ((INT_C_TYPE) 1 << (FBITS -1)))
34548fb7bfaSmrg     r.ll += 1;
34648fb7bfaSmrg 
34748fb7bfaSmrg   /* Shift right the result by FBITS.  */
34848fb7bfaSmrg #if FBITS == FIXED_WIDTH
34948fb7bfaSmrg   /* This happens only for unsigned types without any padding bits.
35048fb7bfaSmrg      So, it is safe to set r.ll to 0 as it is logically shifted right.  */
35148fb7bfaSmrg   s.ll = r.ll;
35248fb7bfaSmrg   r.ll = 0;
35348fb7bfaSmrg #else
35448fb7bfaSmrg   s.ll = ((UINT_C_TYPE)s.ll) >> FBITS;
35548fb7bfaSmrg   temp1.ll = r.ll << (FIXED_WIDTH - FBITS);
35648fb7bfaSmrg   s.ll = s.ll | temp1.ll;
35748fb7bfaSmrg   r.ll = r.ll >> FBITS;
35848fb7bfaSmrg #endif
35948fb7bfaSmrg 
36048fb7bfaSmrg   if (satp)
36148fb7bfaSmrg     FIXED_SATURATE2 (&r.ll, &s.ll);
36248fb7bfaSmrg 
36348fb7bfaSmrg   z = (INT_C_TYPE) s.ll;
36448fb7bfaSmrg #if HAVE_PADDING_BITS
36548fb7bfaSmrg   z = z << PADDING_BITS;
36648fb7bfaSmrg   z = z >> PADDING_BITS;
36748fb7bfaSmrg #endif
36848fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
36948fb7bfaSmrg   return c;
37048fb7bfaSmrg #endif
37148fb7bfaSmrg }
37248fb7bfaSmrg #endif /* FIXED_MULHELPER */
37348fb7bfaSmrg 
37448fb7bfaSmrg #if defined(FIXED_MUL) && defined(L_mul)
37548fb7bfaSmrg FIXED_C_TYPE
FIXED_MUL(FIXED_C_TYPE a,FIXED_C_TYPE b)37648fb7bfaSmrg FIXED_MUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
37748fb7bfaSmrg {
37848fb7bfaSmrg   return FIXED_MULHELPER (a, b, 0);
37948fb7bfaSmrg }
38048fb7bfaSmrg #endif /* FIXED_MUL */
38148fb7bfaSmrg 
38248fb7bfaSmrg #if defined(FIXED_SSMUL) && defined(L_ssmul)
38348fb7bfaSmrg FIXED_C_TYPE
FIXED_SSMUL(FIXED_C_TYPE a,FIXED_C_TYPE b)38448fb7bfaSmrg FIXED_SSMUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
38548fb7bfaSmrg {
38648fb7bfaSmrg   return FIXED_MULHELPER (a, b, 1);
38748fb7bfaSmrg }
38848fb7bfaSmrg #endif /* FIXED_SSMUL */
38948fb7bfaSmrg 
39048fb7bfaSmrg #if defined(FIXED_USMUL) && defined(L_usmul)
39148fb7bfaSmrg FIXED_C_TYPE
FIXED_USMUL(FIXED_C_TYPE a,FIXED_C_TYPE b)39248fb7bfaSmrg FIXED_USMUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
39348fb7bfaSmrg {
39448fb7bfaSmrg   return FIXED_MULHELPER (a, b, 1);
39548fb7bfaSmrg }
39648fb7bfaSmrg #endif /* FIXED_USMUL */
39748fb7bfaSmrg 
39848fb7bfaSmrg #if defined(FIXED_DIVHELPER) && defined(L_divhelper)
39948fb7bfaSmrg FIXED_C_TYPE
FIXED_DIVHELPER(FIXED_C_TYPE a,FIXED_C_TYPE b,word_type satp)40048fb7bfaSmrg FIXED_DIVHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp)
40148fb7bfaSmrg {
40248fb7bfaSmrg   FIXED_C_TYPE c;
40348fb7bfaSmrg   INT_C_TYPE x, y;
40448fb7bfaSmrg   INT_C_TYPE z;
40548fb7bfaSmrg 
40648fb7bfaSmrg #if defined (DINT_C_TYPE)
40748fb7bfaSmrg   DINT_C_TYPE dx, dy, dz;
40848fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
40948fb7bfaSmrg   memcpy (&y, &b, FIXED_SIZE);
41048fb7bfaSmrg   dx = (DINT_C_TYPE) x;
41148fb7bfaSmrg   dy = (DINT_C_TYPE) y;
41248fb7bfaSmrg   dx = dx << FBITS;
41348fb7bfaSmrg   dz = dx / dy;
41448fb7bfaSmrg   if (satp)
41548fb7bfaSmrg     FIXED_SATURATE1 (&dz);
41648fb7bfaSmrg   z = (INT_C_TYPE) dz;
41748fb7bfaSmrg #if HAVE_PADDING_BITS
41848fb7bfaSmrg   z = z << PADDING_BITS;
41948fb7bfaSmrg   z = z >> PADDING_BITS;
42048fb7bfaSmrg #endif
42148fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
42248fb7bfaSmrg   return c;
42348fb7bfaSmrg 
42448fb7bfaSmrg #else /* No DINT_C_TYPE */
42548fb7bfaSmrg   INT_C_TYPE pos_a, pos_b, r, s;
42648fb7bfaSmrg   INT_C_TYPE quo_r, quo_s, mod, temp;
42748fb7bfaSmrg   word_type i;
42848fb7bfaSmrg #if MODE_UNSIGNED == 0
42948fb7bfaSmrg   word_type num_of_neg = 0;
43048fb7bfaSmrg #endif
43148fb7bfaSmrg 
43248fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
43348fb7bfaSmrg   memcpy (&y, &b, FIXED_SIZE);
43448fb7bfaSmrg   pos_a = x;
43548fb7bfaSmrg   pos_b = y;
43648fb7bfaSmrg 
43748fb7bfaSmrg #if MODE_UNSIGNED == 0
43848fb7bfaSmrg   /* If a < 0, negate a.  */
43948fb7bfaSmrg   if (pos_a < 0)
44048fb7bfaSmrg     {
44148fb7bfaSmrg       pos_a = -pos_a;
44248fb7bfaSmrg       num_of_neg ++;
44348fb7bfaSmrg     }
44448fb7bfaSmrg   /* If b < 0, negate b.  */
44548fb7bfaSmrg   if (pos_b < 0)
44648fb7bfaSmrg     {
44748fb7bfaSmrg       pos_b = -pos_b;
44848fb7bfaSmrg       num_of_neg ++;
44948fb7bfaSmrg     }
45048fb7bfaSmrg #endif
45148fb7bfaSmrg 
45248fb7bfaSmrg   /* Left shift pos_a to {r, s} by FBITS.  */
45348fb7bfaSmrg #if FBITS == FIXED_WIDTH
45448fb7bfaSmrg   /* This happens only for unsigned types without any padding bits.  */
45548fb7bfaSmrg   r = pos_a;
45648fb7bfaSmrg   s = 0;
45748fb7bfaSmrg #else
45848fb7bfaSmrg   s = pos_a << FBITS;
45948fb7bfaSmrg   r = pos_a >> (FIXED_WIDTH - FBITS);
46048fb7bfaSmrg #endif
46148fb7bfaSmrg 
46248fb7bfaSmrg   /* Unsigned divide r by pos_b to quo_r.  The remainder is in mod.  */
46348fb7bfaSmrg   quo_r = (UINT_C_TYPE)r / (UINT_C_TYPE)pos_b;
46448fb7bfaSmrg   mod = (UINT_C_TYPE)r % (UINT_C_TYPE)pos_b;
46548fb7bfaSmrg   quo_s = 0;
46648fb7bfaSmrg 
46748fb7bfaSmrg   for (i = 0; i < FIXED_WIDTH; i++)
46848fb7bfaSmrg     {
46948fb7bfaSmrg       /* Record the leftmost bit of mod.  */
47048fb7bfaSmrg       word_type leftmost_mode = (mod >> (FIXED_WIDTH - 1)) & 1;
47148fb7bfaSmrg       /* Shift left mod by 1 bit.  */
47248fb7bfaSmrg       mod = mod << 1;
47348fb7bfaSmrg       /* Test the leftmost bit of s to add to mod.  */
47448fb7bfaSmrg       if ((s >> (FIXED_WIDTH - 1)) & 1)
47548fb7bfaSmrg 	mod ++;
47648fb7bfaSmrg       /* Shift left quo_s by 1 bit.  */
47748fb7bfaSmrg       quo_s = quo_s << 1;
47848fb7bfaSmrg       /* Try to calculate (mod - pos_b).  */
47948fb7bfaSmrg       temp = mod - pos_b;
48048fb7bfaSmrg       if (leftmost_mode || (UINT_C_TYPE)mod >= (UINT_C_TYPE)pos_b)
48148fb7bfaSmrg 	{
48248fb7bfaSmrg 	  quo_s ++;
48348fb7bfaSmrg 	  mod = temp;
48448fb7bfaSmrg 	}
48548fb7bfaSmrg       /* Shift left s by 1 bit.  */
48648fb7bfaSmrg       s = s << 1;
48748fb7bfaSmrg     }
48848fb7bfaSmrg 
48948fb7bfaSmrg #if MODE_UNSIGNED == 0
49048fb7bfaSmrg     if (num_of_neg == 1)
49148fb7bfaSmrg       {
49248fb7bfaSmrg 	quo_s = -quo_s;
49348fb7bfaSmrg 	if (quo_s == 0)
49448fb7bfaSmrg 	  quo_r = -quo_r;
49548fb7bfaSmrg 	else
49648fb7bfaSmrg 	  quo_r = ~quo_r;
49748fb7bfaSmrg       }
49848fb7bfaSmrg #endif
49948fb7bfaSmrg   if (satp)
50048fb7bfaSmrg     FIXED_SATURATE2 (&quo_r, &quo_s);
50148fb7bfaSmrg   z = quo_s;
50248fb7bfaSmrg #if HAVE_PADDING_BITS
50348fb7bfaSmrg   z = z << PADDING_BITS;
50448fb7bfaSmrg   z = z >> PADDING_BITS;
50548fb7bfaSmrg #endif
50648fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
50748fb7bfaSmrg   return c;
50848fb7bfaSmrg #endif
50948fb7bfaSmrg }
51048fb7bfaSmrg #endif /* FIXED_DIVHELPER */
51148fb7bfaSmrg 
51248fb7bfaSmrg #if defined(FIXED_DIV) && defined(L_div)
51348fb7bfaSmrg FIXED_C_TYPE
FIXED_DIV(FIXED_C_TYPE a,FIXED_C_TYPE b)51448fb7bfaSmrg FIXED_DIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
51548fb7bfaSmrg {
51648fb7bfaSmrg   return FIXED_DIVHELPER (a, b, 0);
51748fb7bfaSmrg }
51848fb7bfaSmrg #endif /* FIXED_DIV */
51948fb7bfaSmrg 
52048fb7bfaSmrg 
52148fb7bfaSmrg #if defined(FIXED_UDIV) && defined(L_udiv)
52248fb7bfaSmrg FIXED_C_TYPE
FIXED_UDIV(FIXED_C_TYPE a,FIXED_C_TYPE b)52348fb7bfaSmrg FIXED_UDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
52448fb7bfaSmrg {
52548fb7bfaSmrg   return FIXED_DIVHELPER (a, b, 0);
52648fb7bfaSmrg }
52748fb7bfaSmrg #endif /* FIXED_UDIV */
52848fb7bfaSmrg 
52948fb7bfaSmrg #if defined(FIXED_SSDIV) && defined(L_ssdiv)
53048fb7bfaSmrg FIXED_C_TYPE
FIXED_SSDIV(FIXED_C_TYPE a,FIXED_C_TYPE b)53148fb7bfaSmrg FIXED_SSDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
53248fb7bfaSmrg {
53348fb7bfaSmrg   return FIXED_DIVHELPER (a, b, 1);
53448fb7bfaSmrg }
53548fb7bfaSmrg #endif /* FIXED_SSDIV */
53648fb7bfaSmrg 
53748fb7bfaSmrg #if defined(FIXED_USDIV) && defined(L_usdiv)
53848fb7bfaSmrg FIXED_C_TYPE
FIXED_USDIV(FIXED_C_TYPE a,FIXED_C_TYPE b)53948fb7bfaSmrg FIXED_USDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
54048fb7bfaSmrg {
54148fb7bfaSmrg   return FIXED_DIVHELPER (a, b, 1);
54248fb7bfaSmrg }
54348fb7bfaSmrg #endif /* FIXED_USDIV */
54448fb7bfaSmrg 
54548fb7bfaSmrg #if defined(FIXED_NEG) && defined(L_neg)
54648fb7bfaSmrg FIXED_C_TYPE
FIXED_NEG(FIXED_C_TYPE a)54748fb7bfaSmrg FIXED_NEG (FIXED_C_TYPE a)
54848fb7bfaSmrg {
54948fb7bfaSmrg   FIXED_C_TYPE c;
55048fb7bfaSmrg   INT_C_TYPE x, z;
55148fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
55248fb7bfaSmrg   z = -x;
55348fb7bfaSmrg #if HAVE_PADDING_BITS
55448fb7bfaSmrg   z = z << PADDING_BITS;
55548fb7bfaSmrg   z = z >> PADDING_BITS;
55648fb7bfaSmrg #endif
55748fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
55848fb7bfaSmrg   return c;
55948fb7bfaSmrg }
56048fb7bfaSmrg #endif /* FIXED_NEG */
56148fb7bfaSmrg 
56248fb7bfaSmrg #if defined(FIXED_SSNEG) && defined(L_ssneg)
56348fb7bfaSmrg FIXED_C_TYPE
FIXED_SSNEG(FIXED_C_TYPE a)56448fb7bfaSmrg FIXED_SSNEG (FIXED_C_TYPE a)
56548fb7bfaSmrg {
56648fb7bfaSmrg   FIXED_C_TYPE c;
56748fb7bfaSmrg   INT_C_TYPE x, y, z;
56848fb7bfaSmrg   memcpy (&y, &a, FIXED_SIZE);
56948fb7bfaSmrg   x = 0;
57048fb7bfaSmrg   z = x - (UINT_C_TYPE) y;
57148fb7bfaSmrg   if (((x ^ y) >> I_F_BITS) & 1)
57248fb7bfaSmrg     {
57348fb7bfaSmrg       if (((z ^ x) >> I_F_BITS) & 1)
57448fb7bfaSmrg 	z = (((UINT_C_TYPE) 1) << I_F_BITS) - 1;
57548fb7bfaSmrg     }
57648fb7bfaSmrg #if HAVE_PADDING_BITS
57748fb7bfaSmrg   z = z << PADDING_BITS;
57848fb7bfaSmrg   z = z >> PADDING_BITS;
57948fb7bfaSmrg #endif
58048fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
58148fb7bfaSmrg   return c;
58248fb7bfaSmrg }
58348fb7bfaSmrg #endif /* FIXED_SSNEG */
58448fb7bfaSmrg 
58548fb7bfaSmrg #if defined(FIXED_USNEG) && defined(L_usneg)
58648fb7bfaSmrg FIXED_C_TYPE
FIXED_USNEG(FIXED_C_TYPE a)58748fb7bfaSmrg FIXED_USNEG (FIXED_C_TYPE a __attribute__ ((__unused__)))
58848fb7bfaSmrg {
58948fb7bfaSmrg   FIXED_C_TYPE c;
59048fb7bfaSmrg   INT_C_TYPE z;
59148fb7bfaSmrg   z = 0;
59248fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
59348fb7bfaSmrg   return c;
59448fb7bfaSmrg }
59548fb7bfaSmrg #endif /* FIXED_USNEG */
59648fb7bfaSmrg 
59748fb7bfaSmrg #if defined(FIXED_ASHLHELPER) && defined(L_ashlhelper)
59848fb7bfaSmrg FIXED_C_TYPE
FIXED_ASHLHELPER(FIXED_C_TYPE a,word_type b,word_type satp)59948fb7bfaSmrg FIXED_ASHLHELPER (FIXED_C_TYPE a, word_type b, word_type satp)
60048fb7bfaSmrg {
60148fb7bfaSmrg   FIXED_C_TYPE c;
60248fb7bfaSmrg   INT_C_TYPE x, z;
60348fb7bfaSmrg 
60448fb7bfaSmrg #if defined (DINT_C_TYPE)
60548fb7bfaSmrg   DINT_C_TYPE dx, dz;
60648fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
60748fb7bfaSmrg   dx = (DINT_C_TYPE) x;
60848fb7bfaSmrg   if (b >= FIXED_WIDTH)
60948fb7bfaSmrg     dz = dx << FIXED_WIDTH;
61048fb7bfaSmrg   else
61148fb7bfaSmrg     dz = dx << b;
61248fb7bfaSmrg   if (satp)
61348fb7bfaSmrg     FIXED_SATURATE1 (&dz);
61448fb7bfaSmrg   z = (INT_C_TYPE) dz;
61548fb7bfaSmrg #if HAVE_PADDING_BITS
61648fb7bfaSmrg   z = z << PADDING_BITS;
61748fb7bfaSmrg   z = z >> PADDING_BITS;
61848fb7bfaSmrg #endif
61948fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
62048fb7bfaSmrg   return c;
62148fb7bfaSmrg 
62248fb7bfaSmrg #else /* No DINT_C_TYPE */
62348fb7bfaSmrg   INT_C_TYPE r, s;
62448fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
62548fb7bfaSmrg   /* We need to shift left x by b bits to {r, s}.  */
62648fb7bfaSmrg   if (b >= FIXED_WIDTH)
62748fb7bfaSmrg     {
62848fb7bfaSmrg       r = b;
62948fb7bfaSmrg       s = 0;
63048fb7bfaSmrg     }
63148fb7bfaSmrg   else
63248fb7bfaSmrg     {
63348fb7bfaSmrg       s = x << b;
63448fb7bfaSmrg       r = x >> (FIXED_WIDTH - b);
63548fb7bfaSmrg     }
63648fb7bfaSmrg   if (satp)
63748fb7bfaSmrg     FIXED_SATURATE2 (&r, &s);
63848fb7bfaSmrg   z = s;
63948fb7bfaSmrg #if HAVE_PADDING_BITS
64048fb7bfaSmrg   z = z << PADDING_BITS;
64148fb7bfaSmrg   z = z >> PADDING_BITS;
64248fb7bfaSmrg #endif
64348fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
64448fb7bfaSmrg   return c;
64548fb7bfaSmrg #endif
64648fb7bfaSmrg }
64748fb7bfaSmrg #endif /* FIXED_ASHLHELPER */
64848fb7bfaSmrg 
64948fb7bfaSmrg #if defined(FIXED_ASHL) && defined(L_ashl)
65048fb7bfaSmrg FIXED_C_TYPE
FIXED_ASHL(FIXED_C_TYPE a,word_type b)65148fb7bfaSmrg FIXED_ASHL (FIXED_C_TYPE a, word_type b)
65248fb7bfaSmrg {
65348fb7bfaSmrg   return FIXED_ASHLHELPER (a, b, 0);
65448fb7bfaSmrg }
65548fb7bfaSmrg #endif /* FIXED_ASHL */
65648fb7bfaSmrg 
65748fb7bfaSmrg #if defined(FIXED_ASHR) && defined(L_ashr)
65848fb7bfaSmrg FIXED_C_TYPE
FIXED_ASHR(FIXED_C_TYPE a,word_type b)65948fb7bfaSmrg FIXED_ASHR (FIXED_C_TYPE a, word_type b)
66048fb7bfaSmrg {
66148fb7bfaSmrg   FIXED_C_TYPE c;
66248fb7bfaSmrg   INT_C_TYPE x, z;
66348fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
66448fb7bfaSmrg   z = x >> b;
66548fb7bfaSmrg #if HAVE_PADDING_BITS
66648fb7bfaSmrg   z = z << PADDING_BITS;
66748fb7bfaSmrg   z = z >> PADDING_BITS;
66848fb7bfaSmrg #endif
66948fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
67048fb7bfaSmrg   return c;
67148fb7bfaSmrg }
67248fb7bfaSmrg #endif /* FIXED_ASHR */
67348fb7bfaSmrg 
67448fb7bfaSmrg #if defined(FIXED_LSHR) && defined(L_lshr)
67548fb7bfaSmrg FIXED_C_TYPE
FIXED_LSHR(FIXED_C_TYPE a,word_type b)67648fb7bfaSmrg FIXED_LSHR (FIXED_C_TYPE a, word_type b)
67748fb7bfaSmrg {
67848fb7bfaSmrg   FIXED_C_TYPE c;
67948fb7bfaSmrg   INT_C_TYPE x, z;
68048fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
68148fb7bfaSmrg   z = x >> b;
68248fb7bfaSmrg #if HAVE_PADDING_BITS
68348fb7bfaSmrg   z = z << PADDING_BITS;
68448fb7bfaSmrg   z = z >> PADDING_BITS;
68548fb7bfaSmrg #endif
68648fb7bfaSmrg   memcpy (&c, &z, FIXED_SIZE);
68748fb7bfaSmrg   return c;
68848fb7bfaSmrg }
68948fb7bfaSmrg #endif /* FIXED_LSHR */
69048fb7bfaSmrg 
69148fb7bfaSmrg #if defined(FIXED_SSASHL) && defined(L_ssashl)
69248fb7bfaSmrg FIXED_C_TYPE
FIXED_SSASHL(FIXED_C_TYPE a,word_type b)69348fb7bfaSmrg FIXED_SSASHL (FIXED_C_TYPE a, word_type b)
69448fb7bfaSmrg {
69548fb7bfaSmrg   return FIXED_ASHLHELPER (a, b, 1);
69648fb7bfaSmrg }
69748fb7bfaSmrg #endif /* FIXED_SSASHL */
69848fb7bfaSmrg 
69948fb7bfaSmrg #if defined(FIXED_USASHL) && defined(L_usashl)
70048fb7bfaSmrg FIXED_C_TYPE
FIXED_USASHL(FIXED_C_TYPE a,word_type b)70148fb7bfaSmrg FIXED_USASHL (FIXED_C_TYPE a, word_type b)
70248fb7bfaSmrg {
70348fb7bfaSmrg   return FIXED_ASHLHELPER (a, b, 1);
70448fb7bfaSmrg }
70548fb7bfaSmrg #endif /* FIXED_USASHL */
70648fb7bfaSmrg 
70748fb7bfaSmrg #if defined(FIXED_CMP) && defined(L_cmp)
70848fb7bfaSmrg word_type
FIXED_CMP(FIXED_C_TYPE a,FIXED_C_TYPE b)70948fb7bfaSmrg FIXED_CMP (FIXED_C_TYPE a, FIXED_C_TYPE b)
71048fb7bfaSmrg {
71148fb7bfaSmrg   INT_C_TYPE x, y;
71248fb7bfaSmrg   memcpy (&x, &a, FIXED_SIZE);
71348fb7bfaSmrg   memcpy (&y, &b, FIXED_SIZE);
71448fb7bfaSmrg 
71548fb7bfaSmrg   if (x < y)
71648fb7bfaSmrg     return 0;
71748fb7bfaSmrg   else if (x > y)
71848fb7bfaSmrg     return 2;
71948fb7bfaSmrg 
72048fb7bfaSmrg   return 1;
72148fb7bfaSmrg }
72248fb7bfaSmrg #endif /* FIXED_CMP */
72348fb7bfaSmrg 
72448fb7bfaSmrg /* Fixed -> Fixed.  */
72548fb7bfaSmrg #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 4
72648fb7bfaSmrg TO_FIXED_C_TYPE
FRACT(FROM_FIXED_C_TYPE a)72748fb7bfaSmrg FRACT (FROM_FIXED_C_TYPE a)
72848fb7bfaSmrg {
72948fb7bfaSmrg   TO_FIXED_C_TYPE c;
73048fb7bfaSmrg   FROM_INT_C_TYPE x;
73148fb7bfaSmrg   TO_INT_C_TYPE z;
73248fb7bfaSmrg   int shift_amount;
73348fb7bfaSmrg   memcpy (&x, &a, FROM_FIXED_SIZE);
73448fb7bfaSmrg #if TO_FBITS > FROM_FBITS  /* Need left shift.  */
73548fb7bfaSmrg   shift_amount = TO_FBITS - FROM_FBITS;
73648fb7bfaSmrg   z = (TO_INT_C_TYPE) x;
73748fb7bfaSmrg   z = z << shift_amount;
73848fb7bfaSmrg #else /* TO_FBITS <= FROM_FBITS.  Need right Shift.  */
73948fb7bfaSmrg   shift_amount = FROM_FBITS - TO_FBITS;
74048fb7bfaSmrg   x = x >> shift_amount;
74148fb7bfaSmrg   z = (TO_INT_C_TYPE) x;
74248fb7bfaSmrg #endif /* TO_FBITS > FROM_FBITS  */
74348fb7bfaSmrg 
74448fb7bfaSmrg #if TO_HAVE_PADDING_BITS
74548fb7bfaSmrg   z = z << TO_PADDING_BITS;
74648fb7bfaSmrg   z = z >> TO_PADDING_BITS;
74748fb7bfaSmrg #endif
74848fb7bfaSmrg   memcpy (&c, &z, TO_FIXED_SIZE);
74948fb7bfaSmrg   return c;
75048fb7bfaSmrg }
75148fb7bfaSmrg #endif /* FRACT && FROM_TYPE == 4 && TO_TYPE == 4  */
75248fb7bfaSmrg 
75348fb7bfaSmrg /* Fixed -> Fixed with saturation.  */
75448fb7bfaSmrg #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 4 && TO_TYPE == 4
75548fb7bfaSmrg TO_FIXED_C_TYPE
SATFRACT(FROM_FIXED_C_TYPE a)75648fb7bfaSmrg SATFRACT (FROM_FIXED_C_TYPE a)
75748fb7bfaSmrg {
75848fb7bfaSmrg   TO_FIXED_C_TYPE c;
75948fb7bfaSmrg   TO_INT_C_TYPE z;
76048fb7bfaSmrg   FROM_INT_C_TYPE x;
76148fb7bfaSmrg #if FROM_MODE_UNSIGNED == 0
76248fb7bfaSmrg   BIG_SINT_C_TYPE high, low;
76348fb7bfaSmrg   BIG_SINT_C_TYPE max_high, max_low;
76448fb7bfaSmrg #if TO_MODE_UNSIGNED == 0
76548fb7bfaSmrg   BIG_SINT_C_TYPE min_high, min_low;
76648fb7bfaSmrg #endif
76748fb7bfaSmrg #else
76848fb7bfaSmrg   BIG_UINT_C_TYPE high, low;
76948fb7bfaSmrg   BIG_UINT_C_TYPE max_high, max_low;
77048fb7bfaSmrg #endif
77148fb7bfaSmrg #if TO_FBITS > FROM_FBITS
77248fb7bfaSmrg   BIG_UINT_C_TYPE utemp;
77348fb7bfaSmrg #endif
77448fb7bfaSmrg #if TO_MODE_UNSIGNED == 0
77548fb7bfaSmrg   BIG_SINT_C_TYPE stemp;
77648fb7bfaSmrg #endif
77748fb7bfaSmrg #if TO_FBITS != FROM_FBITS
77848fb7bfaSmrg   int shift_amount;
77948fb7bfaSmrg #endif
78048fb7bfaSmrg   memcpy (&x, &a, FROM_FIXED_SIZE);
78148fb7bfaSmrg 
78248fb7bfaSmrg   /* Step 1. We need to store x to {high, low}.  */
78348fb7bfaSmrg #if FROM_MODE_UNSIGNED == 0
78448fb7bfaSmrg   low = (BIG_SINT_C_TYPE) x;
78548fb7bfaSmrg   if (x < 0)
78648fb7bfaSmrg     high = -1;
78748fb7bfaSmrg   else
78848fb7bfaSmrg     high = 0;
78948fb7bfaSmrg #else
79048fb7bfaSmrg   low = (BIG_UINT_C_TYPE) x;
79148fb7bfaSmrg   high = 0;
79248fb7bfaSmrg #endif
79348fb7bfaSmrg 
79448fb7bfaSmrg   /* Step 2. We need to shift {high, low}.  */
79548fb7bfaSmrg #if TO_FBITS > FROM_FBITS /* Left shift.  */
79648fb7bfaSmrg   shift_amount = TO_FBITS - FROM_FBITS;
79748fb7bfaSmrg   utemp = (BIG_UINT_C_TYPE) low;
79848fb7bfaSmrg   utemp = utemp >> (BIG_WIDTH - shift_amount);
79948fb7bfaSmrg   high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
80048fb7bfaSmrg   low = low << shift_amount;
80148fb7bfaSmrg #elif TO_FBITS < FROM_FBITS /* Right shift.  */
80248fb7bfaSmrg   shift_amount = FROM_FBITS - TO_FBITS;
80348fb7bfaSmrg   low = low >> shift_amount;
80448fb7bfaSmrg #endif
80548fb7bfaSmrg 
80648fb7bfaSmrg   /* Step 3. Compare {high, low} with max and  min of TO_FIXED_C_TYPE.  */
80748fb7bfaSmrg   max_high = 0;
80848fb7bfaSmrg #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
80948fb7bfaSmrg   max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
81048fb7bfaSmrg   max_low = max_low - 1;
81148fb7bfaSmrg #else
81248fb7bfaSmrg   max_low = -1;
81348fb7bfaSmrg #endif
81448fb7bfaSmrg 
81548fb7bfaSmrg #if TO_MODE_UNSIGNED == 0
81648fb7bfaSmrg   stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1);
81748fb7bfaSmrg   stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS);
81848fb7bfaSmrg #if FROM_MODE_UNSIGNED == 0
81948fb7bfaSmrg   min_high = -1;
82048fb7bfaSmrg   min_low = stemp;
82148fb7bfaSmrg #endif
82248fb7bfaSmrg #endif
82348fb7bfaSmrg 
82448fb7bfaSmrg #if FROM_MODE_UNSIGNED == 0 && TO_MODE_UNSIGNED == 0
82548fb7bfaSmrg   /* Signed -> Signed.  */
82648fb7bfaSmrg   if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
82748fb7bfaSmrg       || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
82848fb7bfaSmrg 	  && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
82948fb7bfaSmrg     low = max_low; /* Maximum.  */
83048fb7bfaSmrg   else if ((BIG_SINT_C_TYPE) high < (BIG_SINT_C_TYPE) min_high
83148fb7bfaSmrg 	   || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) min_high
83248fb7bfaSmrg 	       && (BIG_UINT_C_TYPE) low < (BIG_UINT_C_TYPE) min_low))
83348fb7bfaSmrg     low = min_low; /* Minimum.  */
83448fb7bfaSmrg #elif FROM_MODE_UNSIGNED == 1 && TO_MODE_UNSIGNED == 1
83548fb7bfaSmrg   /* Unigned -> Unsigned.  */
83648fb7bfaSmrg   if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
83748fb7bfaSmrg       || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
83848fb7bfaSmrg 	  && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
83948fb7bfaSmrg     low = max_low; /* Maximum.  */
84048fb7bfaSmrg #elif FROM_MODE_UNSIGNED == 0 && TO_MODE_UNSIGNED == 1
84148fb7bfaSmrg   /* Signed -> Unsigned.  */
84248fb7bfaSmrg   if (x < 0)
84348fb7bfaSmrg     low = 0; /* Minimum.  */
84448fb7bfaSmrg   else if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
84548fb7bfaSmrg 	   || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
84648fb7bfaSmrg 	       && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
84748fb7bfaSmrg     low = max_low; /* Maximum.  */
84848fb7bfaSmrg #elif FROM_MODE_UNSIGNED == 1 && TO_MODE_UNSIGNED == 0
84948fb7bfaSmrg   /* Unsigned -> Signed.  */
85048fb7bfaSmrg   if ((BIG_SINT_C_TYPE) high < 0)
85148fb7bfaSmrg     low = max_low; /* Maximum.  */
85248fb7bfaSmrg   else if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
85348fb7bfaSmrg 	   || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
85448fb7bfaSmrg 	       && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
85548fb7bfaSmrg     low = max_low; /* Maximum.  */
85648fb7bfaSmrg #endif
85748fb7bfaSmrg 
85848fb7bfaSmrg   /* Step 4. Store the result.  */
85948fb7bfaSmrg   z = (TO_INT_C_TYPE) low;
86048fb7bfaSmrg #if TO_HAVE_PADDING_BITS
86148fb7bfaSmrg   z = z << TO_PADDING_BITS;
86248fb7bfaSmrg   z = z >> TO_PADDING_BITS;
86348fb7bfaSmrg #endif
86448fb7bfaSmrg   memcpy (&c, &z, TO_FIXED_SIZE);
86548fb7bfaSmrg   return c;
86648fb7bfaSmrg }
86748fb7bfaSmrg #endif /* defined(SATFRACT) && FROM_TYPE == 4 && TO_TYPE == 4  */
86848fb7bfaSmrg 
86948fb7bfaSmrg /* Fixed -> Int.  */
87048fb7bfaSmrg #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 1
87148fb7bfaSmrg TO_INT_C_TYPE
FRACT(FROM_FIXED_C_TYPE a)87248fb7bfaSmrg FRACT (FROM_FIXED_C_TYPE a)
87348fb7bfaSmrg {
87448fb7bfaSmrg   FROM_INT_C_TYPE x;
87548fb7bfaSmrg   TO_INT_C_TYPE z;
87648fb7bfaSmrg   FROM_INT_C_TYPE i = 0;
87748fb7bfaSmrg   memcpy (&x, &a, FROM_FIXED_SIZE);
87848fb7bfaSmrg 
87948fb7bfaSmrg #if FROM_MODE_UNSIGNED == 0
88048fb7bfaSmrg   if (x < 0)
88148fb7bfaSmrg     {
88248fb7bfaSmrg #if FROM_FIXED_WIDTH == FROM_FBITS
88348fb7bfaSmrg       if (x != 0)
88448fb7bfaSmrg 	i = 1;
88548fb7bfaSmrg #else
88648fb7bfaSmrg       if (((FROM_INT_C_TYPE)(x << (FROM_FIXED_WIDTH - FROM_FBITS))) != 0)
88748fb7bfaSmrg 	i = 1;
88848fb7bfaSmrg #endif
88948fb7bfaSmrg     }
89048fb7bfaSmrg #endif
89148fb7bfaSmrg 
89248fb7bfaSmrg #if FROM_FIXED_WIDTH == FROM_FBITS
89348fb7bfaSmrg   x = 0;
89448fb7bfaSmrg #else
89548fb7bfaSmrg   x = x >> FROM_FBITS;
89648fb7bfaSmrg #endif
89748fb7bfaSmrg   x = x + i;
89848fb7bfaSmrg   z = (TO_INT_C_TYPE) x;
89948fb7bfaSmrg   return z;
90048fb7bfaSmrg }
90148fb7bfaSmrg #endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 1  */
90248fb7bfaSmrg 
90348fb7bfaSmrg /* Fixed -> Unsigned int.  */
90448fb7bfaSmrg #if defined(FRACTUNS) && defined(L_fractuns) && FROM_TYPE == 4 && TO_TYPE == 2
90548fb7bfaSmrg TO_INT_C_TYPE
FRACTUNS(FROM_FIXED_C_TYPE a)90648fb7bfaSmrg FRACTUNS (FROM_FIXED_C_TYPE a)
90748fb7bfaSmrg {
90848fb7bfaSmrg   FROM_INT_C_TYPE x;
90948fb7bfaSmrg   TO_INT_C_TYPE z;
91048fb7bfaSmrg   FROM_INT_C_TYPE i = 0;
91148fb7bfaSmrg   memcpy (&x, &a, FROM_FIXED_SIZE);
91248fb7bfaSmrg 
91348fb7bfaSmrg #if FROM_MODE_UNSIGNED == 0
91448fb7bfaSmrg   if (x < 0)
91548fb7bfaSmrg     {
91648fb7bfaSmrg #if FROM_FIXED_WIDTH == FROM_FBITS
91748fb7bfaSmrg       if (x != 0)
91848fb7bfaSmrg 	i = 1;
91948fb7bfaSmrg #else
92048fb7bfaSmrg       if (((FROM_INT_C_TYPE)(x << (FROM_FIXED_WIDTH - FROM_FBITS))) != 0)
92148fb7bfaSmrg 	i = 1;
92248fb7bfaSmrg #endif
92348fb7bfaSmrg     }
92448fb7bfaSmrg #endif
92548fb7bfaSmrg 
92648fb7bfaSmrg #if FROM_FIXED_WIDTH == FROM_FBITS
92748fb7bfaSmrg   x = 0;
92848fb7bfaSmrg #else
92948fb7bfaSmrg   x = x >> FROM_FBITS;
93048fb7bfaSmrg #endif
93148fb7bfaSmrg   x = x + i;
93248fb7bfaSmrg   z = (TO_INT_C_TYPE) x;
93348fb7bfaSmrg   return z;
93448fb7bfaSmrg }
93548fb7bfaSmrg #endif /* defined(FRACTUNS) && FROM_TYPE == 4 && TO_TYPE == 2  */
93648fb7bfaSmrg 
93748fb7bfaSmrg /* Int -> Fixed.  */
93848fb7bfaSmrg #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 1 && TO_TYPE == 4
93948fb7bfaSmrg TO_FIXED_C_TYPE
FRACT(FROM_INT_C_TYPE a)94048fb7bfaSmrg FRACT (FROM_INT_C_TYPE a)
94148fb7bfaSmrg {
94248fb7bfaSmrg   TO_FIXED_C_TYPE c;
94348fb7bfaSmrg   TO_INT_C_TYPE z;
94448fb7bfaSmrg   z = (TO_INT_C_TYPE) a;
94548fb7bfaSmrg #if TO_FIXED_WIDTH == TO_FBITS
94648fb7bfaSmrg   z = 0;
94748fb7bfaSmrg #else
94848fb7bfaSmrg   z = z << TO_FBITS;
94948fb7bfaSmrg #endif
95048fb7bfaSmrg #if TO_HAVE_PADDING_BITS
95148fb7bfaSmrg   z = z << TO_PADDING_BITS;
95248fb7bfaSmrg   z = z >> TO_PADDING_BITS;
95348fb7bfaSmrg #endif
95448fb7bfaSmrg   memcpy (&c, &z, TO_FIXED_SIZE);
95548fb7bfaSmrg   return c;
95648fb7bfaSmrg }
95748fb7bfaSmrg #endif /* defined(FRACT) && FROM_TYPE == 1 && TO_TYPE == 4  */
95848fb7bfaSmrg 
95948fb7bfaSmrg /* Signed int -> Fixed with saturation.  */
96048fb7bfaSmrg #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 1 && TO_TYPE == 4
96148fb7bfaSmrg TO_FIXED_C_TYPE
SATFRACT(FROM_INT_C_TYPE a)96248fb7bfaSmrg SATFRACT (FROM_INT_C_TYPE a)
96348fb7bfaSmrg {
96448fb7bfaSmrg   TO_FIXED_C_TYPE c;
96548fb7bfaSmrg   TO_INT_C_TYPE z;
96648fb7bfaSmrg   FROM_INT_C_TYPE x = a;
96748fb7bfaSmrg   BIG_SINT_C_TYPE high, low;
96848fb7bfaSmrg   BIG_SINT_C_TYPE max_high, max_low;
96948fb7bfaSmrg #if TO_MODE_UNSIGNED == 0
97048fb7bfaSmrg   BIG_SINT_C_TYPE min_high, min_low;
97148fb7bfaSmrg   BIG_SINT_C_TYPE stemp;
97248fb7bfaSmrg #endif
97348fb7bfaSmrg #if BIG_WIDTH != TO_FBITS
97448fb7bfaSmrg   BIG_UINT_C_TYPE utemp;
97548fb7bfaSmrg   int shift_amount;
97648fb7bfaSmrg #endif
97748fb7bfaSmrg 
97848fb7bfaSmrg   /* Step 1. We need to store x to {high, low}.  */
97948fb7bfaSmrg   low = (BIG_SINT_C_TYPE) x;
98048fb7bfaSmrg   if (x < 0)
98148fb7bfaSmrg     high = -1;
98248fb7bfaSmrg   else
98348fb7bfaSmrg     high = 0;
98448fb7bfaSmrg 
98548fb7bfaSmrg   /* Step 2. We need to left shift {high, low}.  */
98648fb7bfaSmrg #if BIG_WIDTH == TO_FBITS
98748fb7bfaSmrg   high = low;
98848fb7bfaSmrg   low = 0;
98948fb7bfaSmrg #else
99048fb7bfaSmrg   shift_amount = TO_FBITS;
99148fb7bfaSmrg   utemp = (BIG_UINT_C_TYPE) low;
99248fb7bfaSmrg   utemp = utemp >> (BIG_WIDTH - shift_amount);
99348fb7bfaSmrg   high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
99448fb7bfaSmrg   low = low << shift_amount;
99548fb7bfaSmrg #endif
99648fb7bfaSmrg 
99748fb7bfaSmrg   /* Step 3. Compare {high, low} with max and  min of TO_FIXED_C_TYPE.  */
99848fb7bfaSmrg   max_high = 0;
99948fb7bfaSmrg #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
100048fb7bfaSmrg   max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
100148fb7bfaSmrg   max_low = max_low - 1;
100248fb7bfaSmrg #else
100348fb7bfaSmrg   max_low = -1;
100448fb7bfaSmrg #endif
100548fb7bfaSmrg 
100648fb7bfaSmrg #if TO_MODE_UNSIGNED == 0
100748fb7bfaSmrg   min_high = -1;
100848fb7bfaSmrg   stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1);
100948fb7bfaSmrg   stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS);
101048fb7bfaSmrg   min_low = stemp;
101148fb7bfaSmrg 
101248fb7bfaSmrg   /* Signed -> Signed.  */
101348fb7bfaSmrg   if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
101448fb7bfaSmrg       || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
101548fb7bfaSmrg           && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
101648fb7bfaSmrg     low = max_low; /* Maximum.  */
101748fb7bfaSmrg   else if ((BIG_SINT_C_TYPE) high < (BIG_SINT_C_TYPE) min_high
101848fb7bfaSmrg            || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) min_high
101948fb7bfaSmrg                && (BIG_UINT_C_TYPE) low < (BIG_UINT_C_TYPE) min_low))
102048fb7bfaSmrg     low = min_low; /* Minimum.  */
102148fb7bfaSmrg #else
102248fb7bfaSmrg   /* Signed -> Unsigned.  */
102348fb7bfaSmrg   if (x < 0)
102448fb7bfaSmrg     low = 0; /* Minimum.  */
102548fb7bfaSmrg   else if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
102648fb7bfaSmrg            || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
102748fb7bfaSmrg                && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
102848fb7bfaSmrg     low = max_low; /* Maximum.  */
102948fb7bfaSmrg #endif
103048fb7bfaSmrg 
103148fb7bfaSmrg   /* Step 4. Store the result.  */
103248fb7bfaSmrg   z = (TO_INT_C_TYPE) low;
103348fb7bfaSmrg #if TO_HAVE_PADDING_BITS
103448fb7bfaSmrg   z = z << TO_PADDING_BITS;
103548fb7bfaSmrg   z = z >> TO_PADDING_BITS;
103648fb7bfaSmrg #endif
103748fb7bfaSmrg   memcpy (&c, &z, TO_FIXED_SIZE);
103848fb7bfaSmrg   return c;
103948fb7bfaSmrg }
104048fb7bfaSmrg #endif /* defined(SATFRACT) && FROM_TYPE == 1 && TO_TYPE == 4  */
104148fb7bfaSmrg 
104248fb7bfaSmrg /* Unsigned int -> Fixed.  */
104348fb7bfaSmrg #if defined(FRACTUNS) && defined(L_fractuns) &&FROM_TYPE == 2 && TO_TYPE == 4
104448fb7bfaSmrg TO_FIXED_C_TYPE
FRACTUNS(FROM_INT_C_TYPE a)104548fb7bfaSmrg FRACTUNS (FROM_INT_C_TYPE a)
104648fb7bfaSmrg {
104748fb7bfaSmrg   TO_FIXED_C_TYPE c;
104848fb7bfaSmrg   TO_INT_C_TYPE z;
104948fb7bfaSmrg   z = (TO_INT_C_TYPE) a;
105048fb7bfaSmrg #if TO_FIXED_WIDTH == TO_FBITS
105148fb7bfaSmrg   z = 0;
105248fb7bfaSmrg #else
105348fb7bfaSmrg   z = z << TO_FBITS;
105448fb7bfaSmrg #endif
105548fb7bfaSmrg #if TO_HAVE_PADDING_BITS
105648fb7bfaSmrg   z = z << TO_PADDING_BITS;
105748fb7bfaSmrg   z = z >> TO_PADDING_BITS;
105848fb7bfaSmrg #endif
105948fb7bfaSmrg   memcpy (&c, &z, TO_FIXED_SIZE);
106048fb7bfaSmrg   return c;
106148fb7bfaSmrg }
106248fb7bfaSmrg #endif /* defined(FRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4  */
106348fb7bfaSmrg 
106448fb7bfaSmrg /* Unsigned int -> Fixed with saturation.  */
106548fb7bfaSmrg #if defined(SATFRACTUNS) && defined(L_satfractuns) && FROM_TYPE == 2 && TO_TYPE == 4
106648fb7bfaSmrg TO_FIXED_C_TYPE
SATFRACTUNS(FROM_INT_C_TYPE a)106748fb7bfaSmrg SATFRACTUNS (FROM_INT_C_TYPE a)
106848fb7bfaSmrg {
106948fb7bfaSmrg   TO_FIXED_C_TYPE c;
107048fb7bfaSmrg   TO_INT_C_TYPE z;
107148fb7bfaSmrg   FROM_INT_C_TYPE x = a;
107248fb7bfaSmrg   BIG_UINT_C_TYPE high, low;
107348fb7bfaSmrg   BIG_UINT_C_TYPE max_high, max_low;
107448fb7bfaSmrg #if BIG_WIDTH != TO_FBITS
107548fb7bfaSmrg   BIG_UINT_C_TYPE utemp;
107648fb7bfaSmrg   int shift_amount;
107748fb7bfaSmrg #endif
107848fb7bfaSmrg 
107948fb7bfaSmrg   /* Step 1. We need to store x to {high, low}.  */
108048fb7bfaSmrg   low = (BIG_UINT_C_TYPE) x;
108148fb7bfaSmrg   high = 0;
108248fb7bfaSmrg 
108348fb7bfaSmrg   /* Step 2. We need to left shift {high, low}.  */
108448fb7bfaSmrg #if BIG_WIDTH == TO_FBITS
108548fb7bfaSmrg   high = low;
108648fb7bfaSmrg   low = 0;
108748fb7bfaSmrg #else
108848fb7bfaSmrg   shift_amount = TO_FBITS;
108948fb7bfaSmrg   utemp = (BIG_UINT_C_TYPE) low;
109048fb7bfaSmrg   utemp = utemp >> (BIG_WIDTH - shift_amount);
109148fb7bfaSmrg   high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
109248fb7bfaSmrg   low = low << shift_amount;
109348fb7bfaSmrg #endif
109448fb7bfaSmrg 
109548fb7bfaSmrg   /* Step 3. Compare {high, low} with max and  min of TO_FIXED_C_TYPE.  */
109648fb7bfaSmrg   max_high = 0;
109748fb7bfaSmrg #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
109848fb7bfaSmrg   max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
109948fb7bfaSmrg   max_low = max_low - 1;
110048fb7bfaSmrg #else
110148fb7bfaSmrg   max_low = -1;
110248fb7bfaSmrg #endif
110348fb7bfaSmrg 
110448fb7bfaSmrg #if TO_MODE_UNSIGNED == 1
110548fb7bfaSmrg   /* Unigned -> Unsigned.  */
110648fb7bfaSmrg   if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
110748fb7bfaSmrg       || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
110848fb7bfaSmrg           && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
110948fb7bfaSmrg     low = max_low; /* Maximum.  */
111048fb7bfaSmrg #else
111148fb7bfaSmrg   /* Unsigned -> Signed.  */
111248fb7bfaSmrg   if ((BIG_SINT_C_TYPE) high < 0)
111348fb7bfaSmrg     low = max_low; /* Maximum.  */
111448fb7bfaSmrg   else if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
111548fb7bfaSmrg            || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
111648fb7bfaSmrg                && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
111748fb7bfaSmrg     low = max_low; /* Maximum.  */
111848fb7bfaSmrg #endif
111948fb7bfaSmrg 
112048fb7bfaSmrg   /* Step 4. Store the result.  */
112148fb7bfaSmrg   z = (TO_INT_C_TYPE) low;
112248fb7bfaSmrg #if TO_HAVE_PADDING_BITS
112348fb7bfaSmrg   z = z << TO_PADDING_BITS;
112448fb7bfaSmrg   z = z >> TO_PADDING_BITS;
112548fb7bfaSmrg #endif
112648fb7bfaSmrg   memcpy (&c, &z, TO_FIXED_SIZE);
112748fb7bfaSmrg   return c;
112848fb7bfaSmrg }
112948fb7bfaSmrg #endif /* defined(SATFRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4  */
113048fb7bfaSmrg 
113148fb7bfaSmrg /* Fixed -> Float.  */
113248fb7bfaSmrg #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 3
113348fb7bfaSmrg TO_FLOAT_C_TYPE
FRACT(FROM_FIXED_C_TYPE a)113448fb7bfaSmrg FRACT (FROM_FIXED_C_TYPE a)
113548fb7bfaSmrg {
113648fb7bfaSmrg   FROM_INT_C_TYPE x;
113748fb7bfaSmrg   TO_FLOAT_C_TYPE z;
113848fb7bfaSmrg   memcpy (&x, &a, FROM_FIXED_SIZE);
113948fb7bfaSmrg   z = (TO_FLOAT_C_TYPE) x;
114048fb7bfaSmrg   z = z / BASE;
114148fb7bfaSmrg   return z;
114248fb7bfaSmrg }
114348fb7bfaSmrg #endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 3  */
114448fb7bfaSmrg 
114548fb7bfaSmrg /* Float -> Fixed.  */
114648fb7bfaSmrg #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 3 && TO_TYPE == 4
114748fb7bfaSmrg TO_FIXED_C_TYPE
FRACT(FROM_FLOAT_C_TYPE a)114848fb7bfaSmrg FRACT (FROM_FLOAT_C_TYPE a)
114948fb7bfaSmrg {
115048fb7bfaSmrg   FROM_FLOAT_C_TYPE temp;
115148fb7bfaSmrg   TO_INT_C_TYPE z;
115248fb7bfaSmrg   TO_FIXED_C_TYPE c;
115348fb7bfaSmrg 
115448fb7bfaSmrg   temp = a * BASE;
115548fb7bfaSmrg   z = (TO_INT_C_TYPE) temp;
115648fb7bfaSmrg #if TO_HAVE_PADDING_BITS
115748fb7bfaSmrg   z = z << TO_PADDING_BITS;
115848fb7bfaSmrg   z = z >> TO_PADDING_BITS;
115948fb7bfaSmrg #endif
116048fb7bfaSmrg   memcpy (&c, &z, TO_FIXED_SIZE);
116148fb7bfaSmrg   return c;
116248fb7bfaSmrg }
116348fb7bfaSmrg #endif /* defined(FRACT) && FROM_TYPE == 3 && TO_TYPE == 4  */
116448fb7bfaSmrg 
116548fb7bfaSmrg /* Float -> Fixed with saturation.  */
116648fb7bfaSmrg #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 3 && TO_TYPE == 4
116748fb7bfaSmrg TO_FIXED_C_TYPE
SATFRACT(FROM_FLOAT_C_TYPE a)116848fb7bfaSmrg SATFRACT (FROM_FLOAT_C_TYPE a)
116948fb7bfaSmrg {
117048fb7bfaSmrg   FROM_FLOAT_C_TYPE temp;
117148fb7bfaSmrg   TO_INT_C_TYPE z;
117248fb7bfaSmrg   TO_FIXED_C_TYPE c;
117348fb7bfaSmrg 
117448fb7bfaSmrg   if (a >= FIXED_MAX)
117548fb7bfaSmrg     {
117648fb7bfaSmrg #if TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
117748fb7bfaSmrg       z = (TO_INT_C_TYPE)1 << TO_I_F_BITS;
117848fb7bfaSmrg       z = z - 1;
117948fb7bfaSmrg #else
118048fb7bfaSmrg       z = -1;
118148fb7bfaSmrg #endif
118248fb7bfaSmrg     }
118348fb7bfaSmrg   else if (a <= FIXED_MIN)
118448fb7bfaSmrg     {
118548fb7bfaSmrg #if TO_MODE_UNSIGNED == 0
118648fb7bfaSmrg       z = (TO_INT_C_TYPE)1 << TO_I_F_BITS;
118748fb7bfaSmrg #else
118848fb7bfaSmrg       z = 0;
118948fb7bfaSmrg #endif
119048fb7bfaSmrg     }
119148fb7bfaSmrg   else
119248fb7bfaSmrg     {
119348fb7bfaSmrg       temp = a * BASE;
119448fb7bfaSmrg       z = (TO_INT_C_TYPE) temp;
119548fb7bfaSmrg     }
119648fb7bfaSmrg 
119748fb7bfaSmrg #if TO_HAVE_PADDING_BITS
119848fb7bfaSmrg   z = z << TO_PADDING_BITS;
119948fb7bfaSmrg   z = z >> TO_PADDING_BITS;
120048fb7bfaSmrg #endif
120148fb7bfaSmrg   memcpy (&c, &z, TO_FIXED_SIZE);
120248fb7bfaSmrg   return c;
120348fb7bfaSmrg }
120448fb7bfaSmrg #endif /* defined(SATFRACT) && FROM_TYPE == 3 && TO_TYPE == 4  */
120548fb7bfaSmrg 
1206