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