x86: Update __CET__ check
[official-gcc.git] / libgcc / fixed-bit.c
blobf50abf05ee84772db52a05f397a7d82246473fd3
1 /* This is a software fixed-point library.
2 Copyright (C) 2007-2018 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
25 /* This implements fixed-point arithmetic.
27 Contributed by Chao-ying Fu <fu@mips.com>. */
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.
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. */
45 #include "tconfig.h"
46 #include "tsystem.h"
47 #include "coretypes.h"
48 #include "tm.h"
49 #include "libgcc_tm.h"
51 #ifndef MIN_UNITS_PER_WORD
52 #define MIN_UNITS_PER_WORD UNITS_PER_WORD
53 #endif
55 #include "fixed-bit.h"
57 #if defined(FIXED_ADD) && defined(L_add)
58 FIXED_C_TYPE
59 FIXED_ADD (FIXED_C_TYPE a, FIXED_C_TYPE b)
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;
73 #endif /* FIXED_ADD */
75 #if defined(FIXED_SSADD) && defined(L_ssadd)
76 FIXED_C_TYPE
77 FIXED_SSADD (FIXED_C_TYPE a, FIXED_C_TYPE b)
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)
86 if (((z ^ x) >> I_F_BITS) & 1)
88 z = ((UINT_C_TYPE) 1) << I_F_BITS;
89 if (x >= 0)
90 z -= (UINT_C_TYPE) 1;
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;
100 #endif /* FIXED_SSADD */
102 #if defined(FIXED_USADD) && defined(L_usadd)
103 FIXED_C_TYPE
104 FIXED_USADD (FIXED_C_TYPE a, FIXED_C_TYPE b)
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 */
117 z = -1;
118 #if HAVE_PADDING_BITS
119 z = z << PADDING_BITS;
120 z = z >> PADDING_BITS;
121 #endif
123 memcpy (&c, &z, FIXED_SIZE);
124 return c;
126 #endif /* FIXED_USADD */
128 #if defined(FIXED_SUB) && defined(L_sub)
129 FIXED_C_TYPE
130 FIXED_SUB (FIXED_C_TYPE a, FIXED_C_TYPE b)
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;
144 #endif /* FIXED_SUB */
146 #if defined(FIXED_SSSUB) && defined(L_sssub)
147 FIXED_C_TYPE
148 FIXED_SSSUB (FIXED_C_TYPE a, FIXED_C_TYPE b)
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)
157 if (((z ^ x) >> I_F_BITS) & 1)
159 z = ((UINT_C_TYPE) 1) << I_F_BITS;
160 if (x >= 0)
161 z -= (UINT_C_TYPE) 1;
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;
171 #endif /* FIXED_SSSUB */
173 #if defined(FIXED_USSUB) && defined(L_ussub)
174 FIXED_C_TYPE
175 FIXED_USSUB (FIXED_C_TYPE a, FIXED_C_TYPE b)
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;
191 #endif /* FIXED_USSUB */
193 #if defined(FIXED_SATURATE1) && defined(L_saturate1)
194 void
195 FIXED_SATURATE1 (DINT_C_TYPE *a)
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;
211 #endif /* FIXED_SATURATE1 */
213 #if defined(FIXED_SATURATE2) && defined(L_saturate2)
214 void
215 FIXED_SATURATE2 (INT_C_TYPE *high, INT_C_TYPE *low)
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
234 if (*high > r_max
235 || (*high == r_max && (UINT_C_TYPE)(*low) > (UINT_C_TYPE)s_max))
237 *high = r_max;
238 *low = s_max;
240 else if (*high < r_min ||
241 (*high == r_min && (UINT_C_TYPE)(*low) < (UINT_C_TYPE)s_min))
243 *high = r_min;
244 *low = s_min;
247 #endif /* FIXED_SATURATE2 */
249 #if defined(FIXED_MULHELPER) && defined(L_mulhelper)
250 FIXED_C_TYPE
251 FIXED_MULHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp)
253 FIXED_C_TYPE c;
254 INT_C_TYPE x, y;
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);
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;
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;
287 memcpy (&x, &a, FIXED_SIZE);
288 memcpy (&y, &b, FIXED_SIZE);
290 /* Decompose a and b. */
291 aa.ll = x;
292 bb.ll = y;
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;
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;
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. */
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;
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
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;
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
360 if (satp)
361 FIXED_SATURATE2 (&r.ll, &s.ll);
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
372 #endif /* FIXED_MULHELPER */
374 #if defined(FIXED_MUL) && defined(L_mul)
375 FIXED_C_TYPE
376 FIXED_MUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
378 return FIXED_MULHELPER (a, b, 0);
380 #endif /* FIXED_MUL */
382 #if defined(FIXED_SSMUL) && defined(L_ssmul)
383 FIXED_C_TYPE
384 FIXED_SSMUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
386 return FIXED_MULHELPER (a, b, 1);
388 #endif /* FIXED_SSMUL */
390 #if defined(FIXED_USMUL) && defined(L_usmul)
391 FIXED_C_TYPE
392 FIXED_USMUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
394 return FIXED_MULHELPER (a, b, 1);
396 #endif /* FIXED_USMUL */
398 #if defined(FIXED_DIVHELPER) && defined(L_divhelper)
399 FIXED_C_TYPE
400 FIXED_DIVHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp)
402 FIXED_C_TYPE c;
403 INT_C_TYPE x, y;
404 INT_C_TYPE z;
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;
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
432 memcpy (&x, &a, FIXED_SIZE);
433 memcpy (&y, &b, FIXED_SIZE);
434 pos_a = x;
435 pos_b = y;
437 #if MODE_UNSIGNED == 0
438 /* If a < 0, negate a. */
439 if (pos_a < 0)
441 pos_a = -pos_a;
442 num_of_neg ++;
444 /* If b < 0, negate b. */
445 if (pos_b < 0)
447 pos_b = -pos_b;
448 num_of_neg ++;
450 #endif
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
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;
467 for (i = 0; i < FIXED_WIDTH; i++)
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)
482 quo_s ++;
483 mod = temp;
485 /* Shift left s by 1 bit. */
486 s = s << 1;
489 #if MODE_UNSIGNED == 0
490 if (num_of_neg == 1)
492 quo_s = -quo_s;
493 if (quo_s == 0)
494 quo_r = -quo_r;
495 else
496 quo_r = ~quo_r;
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
510 #endif /* FIXED_DIVHELPER */
512 #if defined(FIXED_DIV) && defined(L_div)
513 FIXED_C_TYPE
514 FIXED_DIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
516 return FIXED_DIVHELPER (a, b, 0);
518 #endif /* FIXED_DIV */
521 #if defined(FIXED_UDIV) && defined(L_udiv)
522 FIXED_C_TYPE
523 FIXED_UDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
525 return FIXED_DIVHELPER (a, b, 0);
527 #endif /* FIXED_UDIV */
529 #if defined(FIXED_SSDIV) && defined(L_ssdiv)
530 FIXED_C_TYPE
531 FIXED_SSDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
533 return FIXED_DIVHELPER (a, b, 1);
535 #endif /* FIXED_SSDIV */
537 #if defined(FIXED_USDIV) && defined(L_usdiv)
538 FIXED_C_TYPE
539 FIXED_USDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
541 return FIXED_DIVHELPER (a, b, 1);
543 #endif /* FIXED_USDIV */
545 #if defined(FIXED_NEG) && defined(L_neg)
546 FIXED_C_TYPE
547 FIXED_NEG (FIXED_C_TYPE a)
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;
560 #endif /* FIXED_NEG */
562 #if defined(FIXED_SSNEG) && defined(L_ssneg)
563 FIXED_C_TYPE
564 FIXED_SSNEG (FIXED_C_TYPE a)
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)
573 if (((z ^ x) >> I_F_BITS) & 1)
574 z = (((UINT_C_TYPE) 1) << I_F_BITS) - 1;
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;
583 #endif /* FIXED_SSNEG */
585 #if defined(FIXED_USNEG) && defined(L_usneg)
586 FIXED_C_TYPE
587 FIXED_USNEG (FIXED_C_TYPE a __attribute__ ((__unused__)))
589 FIXED_C_TYPE c;
590 INT_C_TYPE z;
591 z = 0;
592 memcpy (&c, &z, FIXED_SIZE);
593 return c;
595 #endif /* FIXED_USNEG */
597 #if defined(FIXED_ASHLHELPER) && defined(L_ashlhelper)
598 FIXED_C_TYPE
599 FIXED_ASHLHELPER (FIXED_C_TYPE a, word_type b, word_type satp)
601 FIXED_C_TYPE c;
602 INT_C_TYPE x, z;
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;
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)
628 r = b;
629 s = 0;
631 else
633 s = x << b;
634 r = x >> (FIXED_WIDTH - b);
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
647 #endif /* FIXED_ASHLHELPER */
649 #if defined(FIXED_ASHL) && defined(L_ashl)
650 FIXED_C_TYPE
651 FIXED_ASHL (FIXED_C_TYPE a, word_type b)
653 return FIXED_ASHLHELPER (a, b, 0);
655 #endif /* FIXED_ASHL */
657 #if defined(FIXED_ASHR) && defined(L_ashr)
658 FIXED_C_TYPE
659 FIXED_ASHR (FIXED_C_TYPE a, word_type b)
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;
672 #endif /* FIXED_ASHR */
674 #if defined(FIXED_LSHR) && defined(L_lshr)
675 FIXED_C_TYPE
676 FIXED_LSHR (FIXED_C_TYPE a, word_type b)
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;
689 #endif /* FIXED_LSHR */
691 #if defined(FIXED_SSASHL) && defined(L_ssashl)
692 FIXED_C_TYPE
693 FIXED_SSASHL (FIXED_C_TYPE a, word_type b)
695 return FIXED_ASHLHELPER (a, b, 1);
697 #endif /* FIXED_SSASHL */
699 #if defined(FIXED_USASHL) && defined(L_usashl)
700 FIXED_C_TYPE
701 FIXED_USASHL (FIXED_C_TYPE a, word_type b)
703 return FIXED_ASHLHELPER (a, b, 1);
705 #endif /* FIXED_USASHL */
707 #if defined(FIXED_CMP) && defined(L_cmp)
708 word_type
709 FIXED_CMP (FIXED_C_TYPE a, FIXED_C_TYPE b)
711 INT_C_TYPE x, y;
712 memcpy (&x, &a, FIXED_SIZE);
713 memcpy (&y, &b, FIXED_SIZE);
715 if (x < y)
716 return 0;
717 else if (x > y)
718 return 2;
720 return 1;
722 #endif /* FIXED_CMP */
724 /* Fixed -> Fixed. */
725 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 4
726 TO_FIXED_C_TYPE
727 FRACT (FROM_FIXED_C_TYPE a)
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 */
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;
751 #endif /* FRACT && FROM_TYPE == 4 && TO_TYPE == 4 */
753 /* Fixed -> Fixed with saturation. */
754 #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 4 && TO_TYPE == 4
755 TO_FIXED_C_TYPE
756 SATFRACT (FROM_FIXED_C_TYPE a)
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);
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
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
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
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
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
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;
867 #endif /* defined(SATFRACT) && FROM_TYPE == 4 && TO_TYPE == 4 */
869 /* Fixed -> Int. */
870 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 1
871 TO_INT_C_TYPE
872 FRACT (FROM_FIXED_C_TYPE a)
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);
879 #if FROM_MODE_UNSIGNED == 0
880 if (x < 0)
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
890 #endif
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;
901 #endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 1 */
903 /* Fixed -> Unsigned int. */
904 #if defined(FRACTUNS) && defined(L_fractuns) && FROM_TYPE == 4 && TO_TYPE == 2
905 TO_INT_C_TYPE
906 FRACTUNS (FROM_FIXED_C_TYPE a)
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);
913 #if FROM_MODE_UNSIGNED == 0
914 if (x < 0)
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
924 #endif
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;
935 #endif /* defined(FRACTUNS) && FROM_TYPE == 4 && TO_TYPE == 2 */
937 /* Int -> Fixed. */
938 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 1 && TO_TYPE == 4
939 TO_FIXED_C_TYPE
940 FRACT (FROM_INT_C_TYPE a)
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;
957 #endif /* defined(FRACT) && FROM_TYPE == 1 && TO_TYPE == 4 */
959 /* Signed int -> Fixed with saturation. */
960 #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 1 && TO_TYPE == 4
961 TO_FIXED_C_TYPE
962 SATFRACT (FROM_INT_C_TYPE a)
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
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;
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
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
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;
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
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;
1040 #endif /* defined(SATFRACT) && FROM_TYPE == 1 && TO_TYPE == 4 */
1042 /* Unsigned int -> Fixed. */
1043 #if defined(FRACTUNS) && defined(L_fractuns) &&FROM_TYPE == 2 && TO_TYPE == 4
1044 TO_FIXED_C_TYPE
1045 FRACTUNS (FROM_INT_C_TYPE a)
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;
1062 #endif /* defined(FRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4 */
1064 /* Unsigned int -> Fixed with saturation. */
1065 #if defined(SATFRACTUNS) && defined(L_satfractuns) && FROM_TYPE == 2 && TO_TYPE == 4
1066 TO_FIXED_C_TYPE
1067 SATFRACTUNS (FROM_INT_C_TYPE a)
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
1079 /* Step 1. We need to store x to {high, low}. */
1080 low = (BIG_UINT_C_TYPE) x;
1081 high = 0;
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
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
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
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;
1129 #endif /* defined(SATFRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4 */
1131 /* Fixed -> Float. */
1132 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 3
1133 TO_FLOAT_C_TYPE
1134 FRACT (FROM_FIXED_C_TYPE a)
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;
1143 #endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 3 */
1145 /* Float -> Fixed. */
1146 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 3 && TO_TYPE == 4
1147 TO_FIXED_C_TYPE
1148 FRACT (FROM_FLOAT_C_TYPE a)
1150 FROM_FLOAT_C_TYPE temp;
1151 TO_INT_C_TYPE z;
1152 TO_FIXED_C_TYPE c;
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;
1163 #endif /* defined(FRACT) && FROM_TYPE == 3 && TO_TYPE == 4 */
1165 /* Float -> Fixed with saturation. */
1166 #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 3 && TO_TYPE == 4
1167 TO_FIXED_C_TYPE
1168 SATFRACT (FROM_FLOAT_C_TYPE a)
1170 FROM_FLOAT_C_TYPE temp;
1171 TO_INT_C_TYPE z;
1172 TO_FIXED_C_TYPE c;
1174 if (a >= FIXED_MAX)
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
1183 else if (a <= FIXED_MIN)
1185 #if TO_MODE_UNSIGNED == 0
1186 z = (TO_INT_C_TYPE)1 << TO_I_F_BITS;
1187 #else
1188 z = 0;
1189 #endif
1191 else
1193 temp = a * BASE;
1194 z = (TO_INT_C_TYPE) temp;
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;
1204 #endif /* defined(SATFRACT) && FROM_TYPE == 3 && TO_TYPE == 4 */