2012-01-27 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgcc / fixed-bit.c
blob84e58155ccd54e1e8b8b39cf0bdfc4e22b5a5242
1 /* This is a software fixed-point library.
2 Copyright (C) 2007, 2009, 2011 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 + y;
84 if ((((x ^ y) >> I_F_BITS) & 1) == 0)
86 if (((z ^ x) >> I_F_BITS) & 1)
88 z = 1;
89 z = z << I_F_BITS;
90 if (x >= 0)
91 z--;
94 #if HAVE_PADDING_BITS
95 z = z << PADDING_BITS;
96 z = z >> PADDING_BITS;
97 #endif
98 memcpy (&c, &z, FIXED_SIZE);
99 return c;
101 #endif /* FIXED_SSADD */
103 #if defined(FIXED_USADD) && defined(L_usadd)
104 FIXED_C_TYPE
105 FIXED_USADD (FIXED_C_TYPE a, FIXED_C_TYPE b)
107 FIXED_C_TYPE c;
108 INT_C_TYPE x, y, z;
109 memcpy (&x, &a, FIXED_SIZE);
110 memcpy (&y, &b, FIXED_SIZE);
111 z = x + y;
112 #if HAVE_PADDING_BITS
113 z = z << PADDING_BITS;
114 z = z >> PADDING_BITS;
115 #endif
116 if (z < x || z < y) /* max */
118 z = -1;
119 #if HAVE_PADDING_BITS
120 z = z << PADDING_BITS;
121 z = z >> PADDING_BITS;
122 #endif
124 memcpy (&c, &z, FIXED_SIZE);
125 return c;
127 #endif /* FIXED_USADD */
129 #if defined(FIXED_SUB) && defined(L_sub)
130 FIXED_C_TYPE
131 FIXED_SUB (FIXED_C_TYPE a, FIXED_C_TYPE b)
133 FIXED_C_TYPE c;
134 INT_C_TYPE x, y, z;
135 memcpy (&x, &a, FIXED_SIZE);
136 memcpy (&y, &b, FIXED_SIZE);
137 z = x - y;
138 #if HAVE_PADDING_BITS
139 z = z << PADDING_BITS;
140 z = z >> PADDING_BITS;
141 #endif
142 memcpy (&c, &z, FIXED_SIZE);
143 return c;
145 #endif /* FIXED_SUB */
147 #if defined(FIXED_SSSUB) && defined(L_sssub)
148 FIXED_C_TYPE
149 FIXED_SSSUB (FIXED_C_TYPE a, FIXED_C_TYPE b)
151 FIXED_C_TYPE c;
152 INT_C_TYPE x, y, z;
153 memcpy (&x, &a, FIXED_SIZE);
154 memcpy (&y, &b, FIXED_SIZE);
155 z = x - y;
156 if (((x ^ y) >> I_F_BITS) & 1)
158 if (((z ^ x) >> I_F_BITS) & 1)
160 z = 1;
161 z = z << I_F_BITS;
162 if (x >= 0)
163 z--;
166 #if HAVE_PADDING_BITS
167 z = z << PADDING_BITS;
168 z = z >> PADDING_BITS;
169 #endif
170 memcpy (&c, &z, FIXED_SIZE);
171 return c;
173 #endif /* FIXED_SSSUB */
175 #if defined(FIXED_USSUB) && defined(L_ussub)
176 FIXED_C_TYPE
177 FIXED_USSUB (FIXED_C_TYPE a, FIXED_C_TYPE b)
179 FIXED_C_TYPE c;
180 INT_C_TYPE x, y, z;
181 memcpy (&x, &a, FIXED_SIZE);
182 memcpy (&y, &b, FIXED_SIZE);
183 z = x - y;
184 if (x < y)
185 z = 0;
186 #if HAVE_PADDING_BITS
187 z = z << PADDING_BITS;
188 z = z >> PADDING_BITS;
189 #endif
190 memcpy (&c, &z, FIXED_SIZE);
191 return c;
193 #endif /* FIXED_USSUB */
195 #if defined(FIXED_SATURATE1) && defined(L_saturate1)
196 void
197 FIXED_SATURATE1 (DINT_C_TYPE *a)
199 DINT_C_TYPE max, min;
200 max = (DINT_C_TYPE)1 << I_F_BITS;
201 max = max - 1;
202 #if MODE_UNSIGNED == 0
203 min = (DINT_C_TYPE)1 << (2 * FIXED_WIDTH - 1);
204 min = min >> (2 * FIXED_WIDTH - 1 - I_F_BITS);
205 #else
206 min = 0;
207 #endif
208 if (*a > max)
209 *a = max;
210 else if (*a < min)
211 *a = min;
213 #endif /* FIXED_SATURATE1 */
215 #if defined(FIXED_SATURATE2) && defined(L_saturate2)
216 void
217 FIXED_SATURATE2 (INT_C_TYPE *high, INT_C_TYPE *low)
219 INT_C_TYPE r_max, s_max, r_min, s_min;
220 r_max = 0;
221 #if (MODE_UNSIGNED == 0) || HAVE_PADDING_BITS
222 s_max = (INT_C_TYPE)1 << I_F_BITS;
223 s_max = s_max - 1;
224 #else
225 s_max = -1;
226 #endif
227 #if MODE_UNSIGNED == 0
228 r_min = -1;
229 s_min = (INT_C_TYPE)1 << (FIXED_WIDTH - 1);
230 s_min = s_min >> (FIXED_WIDTH - 1 - I_F_BITS);
231 #else
232 r_min = 0;
233 s_min = 0;
234 #endif
236 if (*high > r_max
237 || (*high == r_max && (UINT_C_TYPE)(*low) > (UINT_C_TYPE)s_max))
239 *high = r_max;
240 *low = s_max;
242 else if (*high < r_min ||
243 (*high == r_min && (UINT_C_TYPE)(*low) < (UINT_C_TYPE)s_min))
245 *high = r_min;
246 *low = s_min;
249 #endif /* FIXED_SATURATE2 */
251 #if defined(FIXED_MULHELPER) && defined(L_mulhelper)
252 FIXED_C_TYPE
253 FIXED_MULHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp)
255 FIXED_C_TYPE c;
256 INT_C_TYPE x, y;
258 #if defined (DINT_C_TYPE)
259 INT_C_TYPE z;
260 DINT_C_TYPE dx, dy, dz;
261 memcpy (&x, &a, FIXED_SIZE);
262 memcpy (&y, &b, FIXED_SIZE);
263 dx = (DINT_C_TYPE) x;
264 dy = (DINT_C_TYPE) y;
265 dz = dx * dy;
266 /* Round the result by adding (1 << (FBITS -1)). */
267 dz += ((DINT_C_TYPE) 1 << (FBITS - 1));
268 dz = dz >> FBITS;
269 if (satp)
270 FIXED_SATURATE1 (&dz);
272 z = (INT_C_TYPE) dz;
273 #if HAVE_PADDING_BITS
274 z = z << PADDING_BITS;
275 z = z >> PADDING_BITS;
276 #endif
277 memcpy (&c, &z, FIXED_SIZE);
278 return c;
280 #else /* No DINT_C_TYPE */
281 /* The result of multiplication expands to two INT_C_TYPE. */
282 INTunion aa, bb;
283 INTunion a_high, a_low, b_high, b_low;
284 INTunion high_high, high_low, low_high, low_low;
285 INTunion r, s, temp1, temp2;
286 INT_C_TYPE carry = 0;
287 INT_C_TYPE z;
289 memcpy (&x, &a, FIXED_SIZE);
290 memcpy (&y, &b, FIXED_SIZE);
292 /* Decompose a and b. */
293 aa.ll = x;
294 bb.ll = y;
296 a_high.s.low = aa.s.high;
297 a_high.s.high = 0;
298 a_low.s.low = aa.s.low;
299 a_low.s.high = 0;
300 b_high.s.low = bb.s.high;
301 b_high.s.high = 0;
302 b_low.s.low = bb.s.low;
303 b_low.s.high = 0;
305 /* Perform four multiplications. */
306 low_low.ll = a_low.ll * b_low.ll;
307 low_high.ll = a_low.ll * b_high.ll;
308 high_low.ll = a_high.ll * b_low.ll;
309 high_high.ll = a_high.ll * b_high.ll;
311 /* Accumulate four results to {r, s}. */
312 temp1.s.high = high_low.s.low;
313 temp1.s.low = 0;
314 s.ll = low_low.ll + temp1.ll;
315 if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) low_low.ll
316 || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll)
317 carry ++; /* Carry. */
318 temp1.ll = s.ll;
319 temp2.s.high = low_high.s.low;
320 temp2.s.low = 0;
321 s.ll = temp1.ll + temp2.ll;
322 if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll
323 || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp2.ll)
324 carry ++; /* Carry. */
326 temp1.s.low = high_low.s.high;
327 temp1.s.high = 0;
328 r.ll = high_high.ll + temp1.ll;
329 temp1.s.low = low_high.s.high;
330 temp1.s.high = 0;
331 r.ll = r.ll + temp1.ll + carry;
333 #if MODE_UNSIGNED == 0
334 /* For signed types, we need to add neg(y) to r, if x < 0. */
335 if (x < 0)
336 r.ll = r.ll - y;
337 /* We need to add neg(x) to r, if y < 0. */
338 if (y < 0)
339 r.ll = r.ll - x;
340 #endif
342 /* Round the result by adding (1 << (FBITS -1)). */
343 temp1.ll = s.ll;
344 s.ll += ((INT_C_TYPE) 1 << (FBITS -1));
345 if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll
346 || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) ((INT_C_TYPE) 1 << (FBITS -1)))
347 r.ll += 1;
349 /* Shift right the result by FBITS. */
350 #if FBITS == FIXED_WIDTH
351 /* This happens only for unsigned types without any padding bits.
352 So, it is safe to set r.ll to 0 as it is logically shifted right. */
353 s.ll = r.ll;
354 r.ll = 0;
355 #else
356 s.ll = ((UINT_C_TYPE)s.ll) >> FBITS;
357 temp1.ll = r.ll << (FIXED_WIDTH - FBITS);
358 s.ll = s.ll | temp1.ll;
359 r.ll = r.ll >> FBITS;
360 #endif
362 if (satp)
363 FIXED_SATURATE2 (&r.ll, &s.ll);
365 z = (INT_C_TYPE) s.ll;
366 #if HAVE_PADDING_BITS
367 z = z << PADDING_BITS;
368 z = z >> PADDING_BITS;
369 #endif
370 memcpy (&c, &z, FIXED_SIZE);
371 return c;
372 #endif
374 #endif /* FIXED_MULHELPER */
376 #if defined(FIXED_MUL) && defined(L_mul)
377 FIXED_C_TYPE
378 FIXED_MUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
380 return FIXED_MULHELPER (a, b, 0);
382 #endif /* FIXED_MUL */
384 #if defined(FIXED_SSMUL) && defined(L_ssmul)
385 FIXED_C_TYPE
386 FIXED_SSMUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
388 return FIXED_MULHELPER (a, b, 1);
390 #endif /* FIXED_SSMUL */
392 #if defined(FIXED_USMUL) && defined(L_usmul)
393 FIXED_C_TYPE
394 FIXED_USMUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
396 return FIXED_MULHELPER (a, b, 1);
398 #endif /* FIXED_USMUL */
400 #if defined(FIXED_DIVHELPER) && defined(L_divhelper)
401 FIXED_C_TYPE
402 FIXED_DIVHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp)
404 FIXED_C_TYPE c;
405 INT_C_TYPE x, y;
406 INT_C_TYPE z;
408 #if defined (DINT_C_TYPE)
409 DINT_C_TYPE dx, dy, dz;
410 memcpy (&x, &a, FIXED_SIZE);
411 memcpy (&y, &b, FIXED_SIZE);
412 dx = (DINT_C_TYPE) x;
413 dy = (DINT_C_TYPE) y;
414 dx = dx << FBITS;
415 dz = dx / dy;
416 if (satp)
417 FIXED_SATURATE1 (&dz);
418 z = (INT_C_TYPE) dz;
419 #if HAVE_PADDING_BITS
420 z = z << PADDING_BITS;
421 z = z >> PADDING_BITS;
422 #endif
423 memcpy (&c, &z, FIXED_SIZE);
424 return c;
426 #else /* No DINT_C_TYPE */
427 INT_C_TYPE pos_a, pos_b, r, s;
428 INT_C_TYPE quo_r, quo_s, mod, temp;
429 word_type i;
430 #if MODE_UNSIGNED == 0
431 word_type num_of_neg = 0;
432 #endif
434 memcpy (&x, &a, FIXED_SIZE);
435 memcpy (&y, &b, FIXED_SIZE);
436 pos_a = x;
437 pos_b = y;
439 #if MODE_UNSIGNED == 0
440 /* If a < 0, negate a. */
441 if (pos_a < 0)
443 pos_a = -pos_a;
444 num_of_neg ++;
446 /* If b < 0, negate b. */
447 if (pos_b < 0)
449 pos_b = -pos_b;
450 num_of_neg ++;
452 #endif
454 /* Left shift pos_a to {r, s} by FBITS. */
455 #if FBITS == FIXED_WIDTH
456 /* This happens only for unsigned types without any padding bits. */
457 r = pos_a;
458 s = 0;
459 #else
460 s = pos_a << FBITS;
461 r = pos_a >> (FIXED_WIDTH - FBITS);
462 #endif
464 /* Unsigned divide r by pos_b to quo_r. The remainder is in mod. */
465 quo_r = (UINT_C_TYPE)r / (UINT_C_TYPE)pos_b;
466 mod = (UINT_C_TYPE)r % (UINT_C_TYPE)pos_b;
467 quo_s = 0;
469 for (i = 0; i < FIXED_WIDTH; i++)
471 /* Record the leftmost bit of mod. */
472 word_type leftmost_mode = (mod >> (FIXED_WIDTH - 1)) & 1;
473 /* Shift left mod by 1 bit. */
474 mod = mod << 1;
475 /* Test the leftmost bit of s to add to mod. */
476 if ((s >> (FIXED_WIDTH - 1)) & 1)
477 mod ++;
478 /* Shift left quo_s by 1 bit. */
479 quo_s = quo_s << 1;
480 /* Try to calculate (mod - pos_b). */
481 temp = mod - pos_b;
482 if (leftmost_mode || (UINT_C_TYPE)mod >= (UINT_C_TYPE)pos_b)
484 quo_s ++;
485 mod = temp;
487 /* Shift left s by 1 bit. */
488 s = s << 1;
491 #if MODE_UNSIGNED == 0
492 if (num_of_neg == 1)
494 quo_s = -quo_s;
495 if (quo_s == 0)
496 quo_r = -quo_r;
497 else
498 quo_r = ~quo_r;
500 #endif
501 if (satp)
502 FIXED_SATURATE2 (&quo_r, &quo_s);
503 z = quo_s;
504 #if HAVE_PADDING_BITS
505 z = z << PADDING_BITS;
506 z = z >> PADDING_BITS;
507 #endif
508 memcpy (&c, &z, FIXED_SIZE);
509 return c;
510 #endif
512 #endif /* FIXED_DIVHELPER */
514 #if defined(FIXED_DIV) && defined(L_div)
515 FIXED_C_TYPE
516 FIXED_DIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
518 return FIXED_DIVHELPER (a, b, 0);
520 #endif /* FIXED_DIV */
523 #if defined(FIXED_UDIV) && defined(L_udiv)
524 FIXED_C_TYPE
525 FIXED_UDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
527 return FIXED_DIVHELPER (a, b, 0);
529 #endif /* FIXED_UDIV */
531 #if defined(FIXED_SSDIV) && defined(L_ssdiv)
532 FIXED_C_TYPE
533 FIXED_SSDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
535 return FIXED_DIVHELPER (a, b, 1);
537 #endif /* FIXED_SSDIV */
539 #if defined(FIXED_USDIV) && defined(L_usdiv)
540 FIXED_C_TYPE
541 FIXED_USDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
543 return FIXED_DIVHELPER (a, b, 1);
545 #endif /* FIXED_USDIV */
547 #if defined(FIXED_NEG) && defined(L_neg)
548 FIXED_C_TYPE
549 FIXED_NEG (FIXED_C_TYPE a)
551 FIXED_C_TYPE c;
552 INT_C_TYPE x, z;
553 memcpy (&x, &a, FIXED_SIZE);
554 z = -x;
555 #if HAVE_PADDING_BITS
556 z = z << PADDING_BITS;
557 z = z >> PADDING_BITS;
558 #endif
559 memcpy (&c, &z, FIXED_SIZE);
560 return c;
562 #endif /* FIXED_NEG */
564 #if defined(FIXED_SSNEG) && defined(L_ssneg)
565 FIXED_C_TYPE
566 FIXED_SSNEG (FIXED_C_TYPE a)
568 FIXED_C_TYPE c;
569 INT_C_TYPE x, y, z;
570 memcpy (&y, &a, FIXED_SIZE);
571 x = 0;
572 z = x - y;
573 if (((x ^ y) >> I_F_BITS) & 1)
575 if (((z ^ x) >> I_F_BITS) & 1)
577 z = 1;
578 z = z << I_F_BITS;
579 if (x >= 0)
580 z--;
583 #if HAVE_PADDING_BITS
584 z = z << PADDING_BITS;
585 z = z >> PADDING_BITS;
586 #endif
587 memcpy (&c, &z, FIXED_SIZE);
588 return c;
590 #endif /* FIXED_SSNEG */
592 #if defined(FIXED_USNEG) && defined(L_usneg)
593 FIXED_C_TYPE
594 FIXED_USNEG (FIXED_C_TYPE a __attribute__ ((__unused__)))
596 FIXED_C_TYPE c;
597 INT_C_TYPE z;
598 z = 0;
599 memcpy (&c, &z, FIXED_SIZE);
600 return c;
602 #endif /* FIXED_USNEG */
604 #if defined(FIXED_ASHLHELPER) && defined(L_ashlhelper)
605 FIXED_C_TYPE
606 FIXED_ASHLHELPER (FIXED_C_TYPE a, word_type b, word_type satp)
608 FIXED_C_TYPE c;
609 INT_C_TYPE x, z;
611 #if defined (DINT_C_TYPE)
612 DINT_C_TYPE dx, dz;
613 memcpy (&x, &a, FIXED_SIZE);
614 dx = (DINT_C_TYPE) x;
615 if (b >= FIXED_WIDTH)
616 dz = dx << FIXED_WIDTH;
617 else
618 dz = dx << b;
619 if (satp)
620 FIXED_SATURATE1 (&dz);
621 z = (INT_C_TYPE) dz;
622 #if HAVE_PADDING_BITS
623 z = z << PADDING_BITS;
624 z = z >> PADDING_BITS;
625 #endif
626 memcpy (&c, &z, FIXED_SIZE);
627 return c;
629 #else /* No DINT_C_TYPE */
630 INT_C_TYPE r, s;
631 memcpy (&x, &a, FIXED_SIZE);
632 /* We need to shift left x by b bits to {r, s}. */
633 if (b >= FIXED_WIDTH)
635 r = b;
636 s = 0;
638 else
640 s = x << b;
641 r = x >> (FIXED_WIDTH - b);
643 if (satp)
644 FIXED_SATURATE2 (&r, &s);
645 z = s;
646 #if HAVE_PADDING_BITS
647 z = z << PADDING_BITS;
648 z = z >> PADDING_BITS;
649 #endif
650 memcpy (&c, &z, FIXED_SIZE);
651 return c;
652 #endif
654 #endif /* FIXED_ASHLHELPER */
656 #if defined(FIXED_ASHL) && defined(L_ashl)
657 FIXED_C_TYPE
658 FIXED_ASHL (FIXED_C_TYPE a, word_type b)
660 return FIXED_ASHLHELPER (a, b, 0);
662 #endif /* FIXED_ASHL */
664 #if defined(FIXED_ASHR) && defined(L_ashr)
665 FIXED_C_TYPE
666 FIXED_ASHR (FIXED_C_TYPE a, word_type b)
668 FIXED_C_TYPE c;
669 INT_C_TYPE x, z;
670 memcpy (&x, &a, FIXED_SIZE);
671 z = x >> b;
672 #if HAVE_PADDING_BITS
673 z = z << PADDING_BITS;
674 z = z >> PADDING_BITS;
675 #endif
676 memcpy (&c, &z, FIXED_SIZE);
677 return c;
679 #endif /* FIXED_ASHR */
681 #if defined(FIXED_LSHR) && defined(L_lshr)
682 FIXED_C_TYPE
683 FIXED_LSHR (FIXED_C_TYPE a, word_type b)
685 FIXED_C_TYPE c;
686 INT_C_TYPE x, z;
687 memcpy (&x, &a, FIXED_SIZE);
688 z = x >> b;
689 #if HAVE_PADDING_BITS
690 z = z << PADDING_BITS;
691 z = z >> PADDING_BITS;
692 #endif
693 memcpy (&c, &z, FIXED_SIZE);
694 return c;
696 #endif /* FIXED_LSHR */
698 #if defined(FIXED_SSASHL) && defined(L_ssashl)
699 FIXED_C_TYPE
700 FIXED_SSASHL (FIXED_C_TYPE a, word_type b)
702 return FIXED_ASHLHELPER (a, b, 1);
704 #endif /* FIXED_SSASHL */
706 #if defined(FIXED_USASHL) && defined(L_usashl)
707 FIXED_C_TYPE
708 FIXED_USASHL (FIXED_C_TYPE a, word_type b)
710 return FIXED_ASHLHELPER (a, b, 1);
712 #endif /* FIXED_USASHL */
714 #if defined(FIXED_CMP) && defined(L_cmp)
715 word_type
716 FIXED_CMP (FIXED_C_TYPE a, FIXED_C_TYPE b)
718 INT_C_TYPE x, y;
719 memcpy (&x, &a, FIXED_SIZE);
720 memcpy (&y, &b, FIXED_SIZE);
722 if (x < y)
723 return 0;
724 else if (x > y)
725 return 2;
727 return 1;
729 #endif /* FIXED_CMP */
731 /* Fixed -> Fixed. */
732 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 4
733 TO_FIXED_C_TYPE
734 FRACT (FROM_FIXED_C_TYPE a)
736 TO_FIXED_C_TYPE c;
737 FROM_INT_C_TYPE x;
738 TO_INT_C_TYPE z;
739 int shift_amount;
740 memcpy (&x, &a, FROM_FIXED_SIZE);
741 #if TO_FBITS > FROM_FBITS /* Need left shift. */
742 shift_amount = TO_FBITS - FROM_FBITS;
743 z = (TO_INT_C_TYPE) x;
744 z = z << shift_amount;
745 #else /* TO_FBITS <= FROM_FBITS. Need right Shift. */
746 shift_amount = FROM_FBITS - TO_FBITS;
747 x = x >> shift_amount;
748 z = (TO_INT_C_TYPE) x;
749 #endif /* TO_FBITS > FROM_FBITS */
751 #if TO_HAVE_PADDING_BITS
752 z = z << TO_PADDING_BITS;
753 z = z >> TO_PADDING_BITS;
754 #endif
755 memcpy (&c, &z, TO_FIXED_SIZE);
756 return c;
758 #endif /* FRACT && FROM_TYPE == 4 && TO_TYPE == 4 */
760 /* Fixed -> Fixed with saturation. */
761 #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 4 && TO_TYPE == 4
762 TO_FIXED_C_TYPE
763 SATFRACT (FROM_FIXED_C_TYPE a)
765 TO_FIXED_C_TYPE c;
766 TO_INT_C_TYPE z;
767 FROM_INT_C_TYPE x;
768 #if FROM_MODE_UNSIGNED == 0
769 BIG_SINT_C_TYPE high, low;
770 BIG_SINT_C_TYPE max_high, max_low;
771 BIG_SINT_C_TYPE min_high, min_low;
772 #else
773 BIG_UINT_C_TYPE high, low;
774 BIG_UINT_C_TYPE max_high, max_low;
775 BIG_UINT_C_TYPE min_high, min_low;
776 #endif
777 #if TO_FBITS > FROM_FBITS
778 BIG_UINT_C_TYPE utemp;
779 #endif
780 #if TO_MODE_UNSIGNED == 0
781 BIG_SINT_C_TYPE stemp;
782 #endif
783 #if TO_FBITS != FROM_FBITS
784 int shift_amount;
785 #endif
786 memcpy (&x, &a, FROM_FIXED_SIZE);
788 /* Step 1. We need to store x to {high, low}. */
789 #if FROM_MODE_UNSIGNED == 0
790 low = (BIG_SINT_C_TYPE) x;
791 if (x < 0)
792 high = -1;
793 else
794 high = 0;
795 #else
796 low = (BIG_UINT_C_TYPE) x;
797 high = 0;
798 #endif
800 /* Step 2. We need to shift {high, low}. */
801 #if TO_FBITS > FROM_FBITS /* Left shift. */
802 shift_amount = TO_FBITS - FROM_FBITS;
803 utemp = (BIG_UINT_C_TYPE) low;
804 utemp = utemp >> (BIG_WIDTH - shift_amount);
805 high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
806 low = low << shift_amount;
807 #elif TO_FBITS < FROM_FBITS /* Right shift. */
808 shift_amount = FROM_FBITS - TO_FBITS;
809 low = low >> shift_amount;
810 #endif
812 /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */
813 max_high = 0;
814 #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
815 max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
816 max_low = max_low - 1;
817 #else
818 max_low = -1;
819 #endif
821 #if TO_MODE_UNSIGNED == 0
822 min_high = -1;
823 stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1);
824 stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS);
825 min_low = stemp;
826 #else
827 min_high = 0;
828 min_low = 0;
829 #endif
831 #if FROM_MODE_UNSIGNED == 0 && TO_MODE_UNSIGNED == 0
832 /* Signed -> Signed. */
833 if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
834 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
835 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
836 low = max_low; /* Maximum. */
837 else if ((BIG_SINT_C_TYPE) high < (BIG_SINT_C_TYPE) min_high
838 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) min_high
839 && (BIG_UINT_C_TYPE) low < (BIG_UINT_C_TYPE) min_low))
840 low = min_low; /* Minimum. */
841 #elif FROM_MODE_UNSIGNED == 1 && TO_MODE_UNSIGNED == 1
842 /* Unigned -> Unsigned. */
843 if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
844 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
845 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
846 low = max_low; /* Maximum. */
847 #elif FROM_MODE_UNSIGNED == 0 && TO_MODE_UNSIGNED == 1
848 /* Signed -> Unsigned. */
849 if (x < 0)
850 low = 0; /* Minimum. */
851 else if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
852 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
853 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
854 low = max_low; /* Maximum. */
855 #elif FROM_MODE_UNSIGNED == 1 && TO_MODE_UNSIGNED == 0
856 /* Unsigned -> Signed. */
857 if ((BIG_SINT_C_TYPE) high < 0)
858 low = max_low; /* Maximum. */
859 else if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
860 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
861 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
862 low = max_low; /* Maximum. */
863 #endif
865 /* Step 4. Store the result. */
866 z = (TO_INT_C_TYPE) low;
867 #if TO_HAVE_PADDING_BITS
868 z = z << TO_PADDING_BITS;
869 z = z >> TO_PADDING_BITS;
870 #endif
871 memcpy (&c, &z, TO_FIXED_SIZE);
872 return c;
874 #endif /* defined(SATFRACT) && FROM_TYPE == 4 && TO_TYPE == 4 */
876 /* Fixed -> Int. */
877 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 1
878 TO_INT_C_TYPE
879 FRACT (FROM_FIXED_C_TYPE a)
881 FROM_INT_C_TYPE x;
882 TO_INT_C_TYPE z;
883 FROM_INT_C_TYPE i = 0;
884 memcpy (&x, &a, FROM_FIXED_SIZE);
886 #if FROM_MODE_UNSIGNED == 0
887 if (x < 0)
889 #if FROM_FIXED_WIDTH == FROM_FBITS
890 if (x != 0)
891 i = 1;
892 #else
893 if (((FROM_INT_C_TYPE)(x << (FROM_FIXED_WIDTH - FROM_FBITS))) != 0)
894 i = 1;
895 #endif
897 #endif
899 #if FROM_FIXED_WIDTH == FROM_FBITS
900 x = 0;
901 #else
902 x = x >> FROM_FBITS;
903 #endif
904 x = x + i;
905 z = (TO_INT_C_TYPE) x;
906 return z;
908 #endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 1 */
910 /* Fixed -> Unsigned int. */
911 #if defined(FRACTUNS) && defined(L_fractuns) && FROM_TYPE == 4 && TO_TYPE == 2
912 TO_INT_C_TYPE
913 FRACTUNS (FROM_FIXED_C_TYPE a)
915 FROM_INT_C_TYPE x;
916 TO_INT_C_TYPE z;
917 FROM_INT_C_TYPE i = 0;
918 memcpy (&x, &a, FROM_FIXED_SIZE);
920 #if FROM_MODE_UNSIGNED == 0
921 if (x < 0)
923 #if FROM_FIXED_WIDTH == FROM_FBITS
924 if (x != 0)
925 i = 1;
926 #else
927 if (((FROM_INT_C_TYPE)(x << (FROM_FIXED_WIDTH - FROM_FBITS))) != 0)
928 i = 1;
929 #endif
931 #endif
933 #if FROM_FIXED_WIDTH == FROM_FBITS
934 x = 0;
935 #else
936 x = x >> FROM_FBITS;
937 #endif
938 x = x + i;
939 z = (TO_INT_C_TYPE) x;
940 return z;
942 #endif /* defined(FRACTUNS) && FROM_TYPE == 4 && TO_TYPE == 2 */
944 /* Int -> Fixed. */
945 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 1 && TO_TYPE == 4
946 TO_FIXED_C_TYPE
947 FRACT (FROM_INT_C_TYPE a)
949 TO_FIXED_C_TYPE c;
950 TO_INT_C_TYPE z;
951 z = (TO_INT_C_TYPE) a;
952 #if TO_FIXED_WIDTH == TO_FBITS
953 z = 0;
954 #else
955 z = z << TO_FBITS;
956 #endif
957 #if TO_HAVE_PADDING_BITS
958 z = z << TO_PADDING_BITS;
959 z = z >> TO_PADDING_BITS;
960 #endif
961 memcpy (&c, &z, TO_FIXED_SIZE);
962 return c;
964 #endif /* defined(FRACT) && FROM_TYPE == 1 && TO_TYPE == 4 */
966 /* Signed int -> Fixed with saturation. */
967 #if defined(SATFRACT) && defined(L_satfract) &&FROM_TYPE == 1 && TO_TYPE == 4
968 TO_FIXED_C_TYPE
969 SATFRACT (FROM_INT_C_TYPE a)
971 TO_FIXED_C_TYPE c;
972 TO_INT_C_TYPE z;
973 FROM_INT_C_TYPE x = a;
974 BIG_SINT_C_TYPE high, low;
975 BIG_SINT_C_TYPE max_high, max_low;
976 BIG_SINT_C_TYPE min_high, min_low;
977 #if TO_MODE_UNSIGNED == 0
978 BIG_SINT_C_TYPE stemp;
979 #endif
980 #if BIG_WIDTH != TO_FBITS
981 BIG_UINT_C_TYPE utemp;
982 int shift_amount;
983 #endif
985 /* Step 1. We need to store x to {high, low}. */
986 low = (BIG_SINT_C_TYPE) x;
987 if (x < 0)
988 high = -1;
989 else
990 high = 0;
992 /* Step 2. We need to left shift {high, low}. */
993 #if BIG_WIDTH == TO_FBITS
994 high = low;
995 low = 0;
996 #else
997 shift_amount = TO_FBITS;
998 utemp = (BIG_UINT_C_TYPE) low;
999 utemp = utemp >> (BIG_WIDTH - shift_amount);
1000 high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
1001 low = low << shift_amount;
1002 #endif
1004 /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */
1005 max_high = 0;
1006 #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
1007 max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
1008 max_low = max_low - 1;
1009 #else
1010 max_low = -1;
1011 #endif
1013 #if TO_MODE_UNSIGNED == 0
1014 min_high = -1;
1015 stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1);
1016 stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS);
1017 min_low = stemp;
1018 #else
1019 min_high = 0;
1020 min_low = 0;
1021 #endif
1023 #if TO_MODE_UNSIGNED == 0
1024 /* Signed -> Signed. */
1025 if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
1026 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
1027 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1028 low = max_low; /* Maximum. */
1029 else if ((BIG_SINT_C_TYPE) high < (BIG_SINT_C_TYPE) min_high
1030 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) min_high
1031 && (BIG_UINT_C_TYPE) low < (BIG_UINT_C_TYPE) min_low))
1032 low = min_low; /* Minimum. */
1033 #else
1034 /* Signed -> Unsigned. */
1035 if (x < 0)
1036 low = 0; /* Minimum. */
1037 else if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
1038 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
1039 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1040 low = max_low; /* Maximum. */
1041 #endif
1043 /* Step 4. Store the result. */
1044 z = (TO_INT_C_TYPE) low;
1045 #if TO_HAVE_PADDING_BITS
1046 z = z << TO_PADDING_BITS;
1047 z = z >> TO_PADDING_BITS;
1048 #endif
1049 memcpy (&c, &z, TO_FIXED_SIZE);
1050 return c;
1052 #endif /* defined(SATFRACT) && FROM_TYPE == 1 && TO_TYPE == 4 */
1054 /* Unsigned int -> Fixed. */
1055 #if defined(FRACTUNS) && defined(L_fractuns) &&FROM_TYPE == 2 && TO_TYPE == 4
1056 TO_FIXED_C_TYPE
1057 FRACTUNS (FROM_INT_C_TYPE a)
1059 TO_FIXED_C_TYPE c;
1060 TO_INT_C_TYPE z;
1061 z = (TO_INT_C_TYPE) a;
1062 #if TO_FIXED_WIDTH == TO_FBITS
1063 z = 0;
1064 #else
1065 z = z << TO_FBITS;
1066 #endif
1067 #if TO_HAVE_PADDING_BITS
1068 z = z << TO_PADDING_BITS;
1069 z = z >> TO_PADDING_BITS;
1070 #endif
1071 memcpy (&c, &z, TO_FIXED_SIZE);
1072 return c;
1074 #endif /* defined(FRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4 */
1076 /* Unsigned int -> Fixed with saturation. */
1077 #if defined(SATFRACTUNS) && defined(L_satfractuns) && FROM_TYPE == 2 && TO_TYPE == 4
1078 TO_FIXED_C_TYPE
1079 SATFRACTUNS (FROM_INT_C_TYPE a)
1081 TO_FIXED_C_TYPE c;
1082 TO_INT_C_TYPE z;
1083 FROM_INT_C_TYPE x = a;
1084 BIG_UINT_C_TYPE high, low;
1085 BIG_UINT_C_TYPE max_high, max_low;
1086 #if BIG_WIDTH != TO_FBITS
1087 BIG_UINT_C_TYPE utemp;
1088 int shift_amount;
1089 #endif
1091 /* Step 1. We need to store x to {high, low}. */
1092 low = (BIG_UINT_C_TYPE) x;
1093 high = 0;
1095 /* Step 2. We need to left shift {high, low}. */
1096 #if BIG_WIDTH == TO_FBITS
1097 high = low;
1098 low = 0;
1099 #else
1100 shift_amount = TO_FBITS;
1101 utemp = (BIG_UINT_C_TYPE) low;
1102 utemp = utemp >> (BIG_WIDTH - shift_amount);
1103 high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
1104 low = low << shift_amount;
1105 #endif
1107 /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */
1108 max_high = 0;
1109 #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
1110 max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
1111 max_low = max_low - 1;
1112 #else
1113 max_low = -1;
1114 #endif
1116 #if TO_MODE_UNSIGNED == 1
1117 /* Unigned -> Unsigned. */
1118 if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
1119 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
1120 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1121 low = max_low; /* Maximum. */
1122 #else
1123 /* Unsigned -> Signed. */
1124 if ((BIG_SINT_C_TYPE) high < 0)
1125 low = max_low; /* Maximum. */
1126 else if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
1127 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
1128 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1129 low = max_low; /* Maximum. */
1130 #endif
1132 /* Step 4. Store the result. */
1133 z = (TO_INT_C_TYPE) low;
1134 #if TO_HAVE_PADDING_BITS
1135 z = z << TO_PADDING_BITS;
1136 z = z >> TO_PADDING_BITS;
1137 #endif
1138 memcpy (&c, &z, TO_FIXED_SIZE);
1139 return c;
1141 #endif /* defined(SATFRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4 */
1143 /* Fixed -> Float. */
1144 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 3
1145 TO_FLOAT_C_TYPE
1146 FRACT (FROM_FIXED_C_TYPE a)
1148 FROM_INT_C_TYPE x;
1149 TO_FLOAT_C_TYPE z;
1150 memcpy (&x, &a, FROM_FIXED_SIZE);
1151 z = (TO_FLOAT_C_TYPE) x;
1152 z = z / BASE;
1153 return z;
1155 #endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 3 */
1157 /* Float -> Fixed. */
1158 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 3 && TO_TYPE == 4
1159 TO_FIXED_C_TYPE
1160 FRACT (FROM_FLOAT_C_TYPE a)
1162 FROM_FLOAT_C_TYPE temp;
1163 TO_INT_C_TYPE z;
1164 TO_FIXED_C_TYPE c;
1166 temp = a * BASE;
1167 z = (TO_INT_C_TYPE) temp;
1168 #if TO_HAVE_PADDING_BITS
1169 z = z << TO_PADDING_BITS;
1170 z = z >> TO_PADDING_BITS;
1171 #endif
1172 memcpy (&c, &z, TO_FIXED_SIZE);
1173 return c;
1175 #endif /* defined(FRACT) && FROM_TYPE == 3 && TO_TYPE == 4 */
1177 /* Float -> Fixed with saturation. */
1178 #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 3 && TO_TYPE == 4
1179 TO_FIXED_C_TYPE
1180 SATFRACT (FROM_FLOAT_C_TYPE a)
1182 FROM_FLOAT_C_TYPE temp;
1183 TO_INT_C_TYPE z;
1184 TO_FIXED_C_TYPE c;
1186 if (a >= FIXED_MAX)
1188 #if TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
1189 z = (TO_INT_C_TYPE)1 << TO_I_F_BITS;
1190 z = z - 1;
1191 #else
1192 z = -1;
1193 #endif
1195 else if (a <= FIXED_MIN)
1197 #if TO_MODE_UNSIGNED == 0
1198 z = (TO_INT_C_TYPE)1 << TO_I_F_BITS;
1199 #else
1200 z = 0;
1201 #endif
1203 else
1205 temp = a * BASE;
1206 z = (TO_INT_C_TYPE) temp;
1209 #if TO_HAVE_PADDING_BITS
1210 z = z << TO_PADDING_BITS;
1211 z = z >> TO_PADDING_BITS;
1212 #endif
1213 memcpy (&c, &z, TO_FIXED_SIZE);
1214 return c;
1216 #endif /* defined(SATFRACT) && FROM_TYPE == 3 && TO_TYPE == 4 */