PR other/54324
[official-gcc.git] / libgcc / fixed-bit.c
blob71243c1295a6da2cdbbeb9fbaea88321e70d65db
1 /* This is a software fixed-point library.
2 Copyright (C) 2007, 2009, 2011, 2012 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 BIG_SINT_C_TYPE min_high, min_low;
765 #else
766 BIG_UINT_C_TYPE high, low;
767 BIG_UINT_C_TYPE max_high, max_low;
768 BIG_UINT_C_TYPE min_high, min_low;
769 #endif
770 #if TO_FBITS > FROM_FBITS
771 BIG_UINT_C_TYPE utemp;
772 #endif
773 #if TO_MODE_UNSIGNED == 0
774 BIG_SINT_C_TYPE stemp;
775 #endif
776 #if TO_FBITS != FROM_FBITS
777 int shift_amount;
778 #endif
779 memcpy (&x, &a, FROM_FIXED_SIZE);
781 /* Step 1. We need to store x to {high, low}. */
782 #if FROM_MODE_UNSIGNED == 0
783 low = (BIG_SINT_C_TYPE) x;
784 if (x < 0)
785 high = -1;
786 else
787 high = 0;
788 #else
789 low = (BIG_UINT_C_TYPE) x;
790 high = 0;
791 #endif
793 /* Step 2. We need to shift {high, low}. */
794 #if TO_FBITS > FROM_FBITS /* Left shift. */
795 shift_amount = TO_FBITS - FROM_FBITS;
796 utemp = (BIG_UINT_C_TYPE) low;
797 utemp = utemp >> (BIG_WIDTH - shift_amount);
798 high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
799 low = low << shift_amount;
800 #elif TO_FBITS < FROM_FBITS /* Right shift. */
801 shift_amount = FROM_FBITS - TO_FBITS;
802 low = low >> shift_amount;
803 #endif
805 /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */
806 max_high = 0;
807 #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
808 max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
809 max_low = max_low - 1;
810 #else
811 max_low = -1;
812 #endif
814 #if TO_MODE_UNSIGNED == 0
815 min_high = -1;
816 stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1);
817 stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS);
818 min_low = stemp;
819 #else
820 min_high = 0;
821 min_low = 0;
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 BIG_SINT_C_TYPE min_high, min_low;
970 #if TO_MODE_UNSIGNED == 0
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;
1011 #else
1012 min_high = 0;
1013 min_low = 0;
1014 #endif
1016 #if TO_MODE_UNSIGNED == 0
1017 /* Signed -> Signed. */
1018 if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
1019 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
1020 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1021 low = max_low; /* Maximum. */
1022 else if ((BIG_SINT_C_TYPE) high < (BIG_SINT_C_TYPE) min_high
1023 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) min_high
1024 && (BIG_UINT_C_TYPE) low < (BIG_UINT_C_TYPE) min_low))
1025 low = min_low; /* Minimum. */
1026 #else
1027 /* Signed -> Unsigned. */
1028 if (x < 0)
1029 low = 0; /* Minimum. */
1030 else if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
1031 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
1032 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1033 low = max_low; /* Maximum. */
1034 #endif
1036 /* Step 4. Store the result. */
1037 z = (TO_INT_C_TYPE) low;
1038 #if TO_HAVE_PADDING_BITS
1039 z = z << TO_PADDING_BITS;
1040 z = z >> TO_PADDING_BITS;
1041 #endif
1042 memcpy (&c, &z, TO_FIXED_SIZE);
1043 return c;
1045 #endif /* defined(SATFRACT) && FROM_TYPE == 1 && TO_TYPE == 4 */
1047 /* Unsigned int -> Fixed. */
1048 #if defined(FRACTUNS) && defined(L_fractuns) &&FROM_TYPE == 2 && TO_TYPE == 4
1049 TO_FIXED_C_TYPE
1050 FRACTUNS (FROM_INT_C_TYPE a)
1052 TO_FIXED_C_TYPE c;
1053 TO_INT_C_TYPE z;
1054 z = (TO_INT_C_TYPE) a;
1055 #if TO_FIXED_WIDTH == TO_FBITS
1056 z = 0;
1057 #else
1058 z = z << TO_FBITS;
1059 #endif
1060 #if TO_HAVE_PADDING_BITS
1061 z = z << TO_PADDING_BITS;
1062 z = z >> TO_PADDING_BITS;
1063 #endif
1064 memcpy (&c, &z, TO_FIXED_SIZE);
1065 return c;
1067 #endif /* defined(FRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4 */
1069 /* Unsigned int -> Fixed with saturation. */
1070 #if defined(SATFRACTUNS) && defined(L_satfractuns) && FROM_TYPE == 2 && TO_TYPE == 4
1071 TO_FIXED_C_TYPE
1072 SATFRACTUNS (FROM_INT_C_TYPE a)
1074 TO_FIXED_C_TYPE c;
1075 TO_INT_C_TYPE z;
1076 FROM_INT_C_TYPE x = a;
1077 BIG_UINT_C_TYPE high, low;
1078 BIG_UINT_C_TYPE max_high, max_low;
1079 #if BIG_WIDTH != TO_FBITS
1080 BIG_UINT_C_TYPE utemp;
1081 int shift_amount;
1082 #endif
1084 /* Step 1. We need to store x to {high, low}. */
1085 low = (BIG_UINT_C_TYPE) x;
1086 high = 0;
1088 /* Step 2. We need to left shift {high, low}. */
1089 #if BIG_WIDTH == TO_FBITS
1090 high = low;
1091 low = 0;
1092 #else
1093 shift_amount = TO_FBITS;
1094 utemp = (BIG_UINT_C_TYPE) low;
1095 utemp = utemp >> (BIG_WIDTH - shift_amount);
1096 high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
1097 low = low << shift_amount;
1098 #endif
1100 /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */
1101 max_high = 0;
1102 #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
1103 max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
1104 max_low = max_low - 1;
1105 #else
1106 max_low = -1;
1107 #endif
1109 #if TO_MODE_UNSIGNED == 1
1110 /* Unigned -> Unsigned. */
1111 if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
1112 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
1113 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1114 low = max_low; /* Maximum. */
1115 #else
1116 /* Unsigned -> Signed. */
1117 if ((BIG_SINT_C_TYPE) high < 0)
1118 low = max_low; /* Maximum. */
1119 else if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
1120 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
1121 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1122 low = max_low; /* Maximum. */
1123 #endif
1125 /* Step 4. Store the result. */
1126 z = (TO_INT_C_TYPE) low;
1127 #if TO_HAVE_PADDING_BITS
1128 z = z << TO_PADDING_BITS;
1129 z = z >> TO_PADDING_BITS;
1130 #endif
1131 memcpy (&c, &z, TO_FIXED_SIZE);
1132 return c;
1134 #endif /* defined(SATFRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4 */
1136 /* Fixed -> Float. */
1137 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 3
1138 TO_FLOAT_C_TYPE
1139 FRACT (FROM_FIXED_C_TYPE a)
1141 FROM_INT_C_TYPE x;
1142 TO_FLOAT_C_TYPE z;
1143 memcpy (&x, &a, FROM_FIXED_SIZE);
1144 z = (TO_FLOAT_C_TYPE) x;
1145 z = z / BASE;
1146 return z;
1148 #endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 3 */
1150 /* Float -> Fixed. */
1151 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 3 && TO_TYPE == 4
1152 TO_FIXED_C_TYPE
1153 FRACT (FROM_FLOAT_C_TYPE a)
1155 FROM_FLOAT_C_TYPE temp;
1156 TO_INT_C_TYPE z;
1157 TO_FIXED_C_TYPE c;
1159 temp = a * BASE;
1160 z = (TO_INT_C_TYPE) temp;
1161 #if TO_HAVE_PADDING_BITS
1162 z = z << TO_PADDING_BITS;
1163 z = z >> TO_PADDING_BITS;
1164 #endif
1165 memcpy (&c, &z, TO_FIXED_SIZE);
1166 return c;
1168 #endif /* defined(FRACT) && FROM_TYPE == 3 && TO_TYPE == 4 */
1170 /* Float -> Fixed with saturation. */
1171 #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 3 && TO_TYPE == 4
1172 TO_FIXED_C_TYPE
1173 SATFRACT (FROM_FLOAT_C_TYPE a)
1175 FROM_FLOAT_C_TYPE temp;
1176 TO_INT_C_TYPE z;
1177 TO_FIXED_C_TYPE c;
1179 if (a >= FIXED_MAX)
1181 #if TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
1182 z = (TO_INT_C_TYPE)1 << TO_I_F_BITS;
1183 z = z - 1;
1184 #else
1185 z = -1;
1186 #endif
1188 else if (a <= FIXED_MIN)
1190 #if TO_MODE_UNSIGNED == 0
1191 z = (TO_INT_C_TYPE)1 << TO_I_F_BITS;
1192 #else
1193 z = 0;
1194 #endif
1196 else
1198 temp = a * BASE;
1199 z = (TO_INT_C_TYPE) temp;
1202 #if TO_HAVE_PADDING_BITS
1203 z = z << TO_PADDING_BITS;
1204 z = z >> TO_PADDING_BITS;
1205 #endif
1206 memcpy (&c, &z, TO_FIXED_SIZE);
1207 return c;
1209 #endif /* defined(SATFRACT) && FROM_TYPE == 3 && TO_TYPE == 4 */