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