]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/fixed-bit.c
Assert for POINTER_TYPE_P in expr_callee_abi
[thirdparty/gcc.git] / libgcc / fixed-bit.c
CommitLineData
10535d4f 1/* This is a software fixed-point library.
fbd26352 2 Copyright (C) 2007-2019 Free Software Foundation, Inc.
10535d4f 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
6bc9506f 8Software Foundation; either version 3, or (at your option) any later
10535d4f 9version.
10
10535d4f 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
6bc9506f 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/>. */
10535d4f 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"
022a2799 49#include "libgcc_tm.h"
10535d4f 50
51#ifndef MIN_UNITS_PER_WORD
52#define MIN_UNITS_PER_WORD UNITS_PER_WORD
53#endif
54
36a5227d 55#include "fixed-bit.h"
10535d4f 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);
990457e2 83 z = x + (UINT_C_TYPE) y;
10535d4f 84 if ((((x ^ y) >> I_F_BITS) & 1) == 0)
85 {
86 if (((z ^ x) >> I_F_BITS) & 1)
87 {
990457e2 88 z = ((UINT_C_TYPE) 1) << I_F_BITS;
89 if (x >= 0)
90 z -= (UINT_C_TYPE) 1;
10535d4f 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);
990457e2 154 z = x - (UINT_C_TYPE) y;
10535d4f 155 if (((x ^ y) >> I_F_BITS) & 1)
156 {
157 if (((z ^ x) >> I_F_BITS) & 1)
158 {
990457e2 159 z = ((UINT_C_TYPE) 1) << I_F_BITS;
160 if (x >= 0)
161 z -= (UINT_C_TYPE) 1;
10535d4f 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
c7684b8e 462 /* Unsigned divide r by pos_b to quo_r. The remainder is in mod. */
10535d4f 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;
990457e2 570 z = x - (UINT_C_TYPE) y;
10535d4f 571 if (((x ^ y) >> I_F_BITS) & 1)
572 {
573 if (((z ^ x) >> I_F_BITS) & 1)
990457e2 574 z = (((UINT_C_TYPE) 1) << I_F_BITS) - 1;
10535d4f 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;
dd509879 764#if TO_MODE_UNSIGNED == 0
10535d4f 765 BIG_SINT_C_TYPE min_high, min_low;
dd509879 766#endif
10535d4f 767#else
768 BIG_UINT_C_TYPE high, low;
769 BIG_UINT_C_TYPE max_high, max_low;
10535d4f 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
10535d4f 816 stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1);
817 stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS);
dd509879 818#if FROM_MODE_UNSIGNED == 0
819 min_high = -1;
10535d4f 820 min_low = stemp;
dd509879 821#endif
10535d4f 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. */
dd509879 960#if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 1 && TO_TYPE == 4
10535d4f 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;
10535d4f 969#if TO_MODE_UNSIGNED == 0
dd509879 970 BIG_SINT_C_TYPE min_high, min_low;
10535d4f 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;
10535d4f 1011
10535d4f 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