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