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