Mark ChangeLog
[official-gcc.git] / gcc / config / fixed-bit.c
blob40ac2e29f8c91c8c4e1ead1f1472ab8f553a7901
1 /* This is a software fixed-point library.
2 Copyright (C) 2007, 2009 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"
50 #ifndef MIN_UNITS_PER_WORD
51 #define MIN_UNITS_PER_WORD UNITS_PER_WORD
52 #endif
54 #include "config/fixed-bit.h"
56 #if defined(FIXED_ADD) && defined(L_add)
57 FIXED_C_TYPE
58 FIXED_ADD (FIXED_C_TYPE a, FIXED_C_TYPE b)
60 FIXED_C_TYPE c;
61 INT_C_TYPE x, y, z;
62 memcpy (&x, &a, FIXED_SIZE);
63 memcpy (&y, &b, FIXED_SIZE);
64 z = x + y;
65 #if HAVE_PADDING_BITS
66 z = z << PADDING_BITS;
67 z = z >> PADDING_BITS;
68 #endif
69 memcpy (&c, &z, FIXED_SIZE);
70 return c;
72 #endif /* FIXED_ADD */
74 #if defined(FIXED_SSADD) && defined(L_ssadd)
75 FIXED_C_TYPE
76 FIXED_SSADD (FIXED_C_TYPE a, FIXED_C_TYPE b)
78 FIXED_C_TYPE c;
79 INT_C_TYPE x, y, z;
80 memcpy (&x, &a, FIXED_SIZE);
81 memcpy (&y, &b, FIXED_SIZE);
82 z = x + y;
83 if ((((x ^ y) >> I_F_BITS) & 1) == 0)
85 if (((z ^ x) >> I_F_BITS) & 1)
87 z = 1;
88 z = z << I_F_BITS;
89 if (x >= 0)
90 z--;
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 - y;
155 if (((x ^ y) >> I_F_BITS) & 1)
157 if (((z ^ x) >> I_F_BITS) & 1)
159 z = 1;
160 z = z << I_F_BITS;
161 if (x >= 0)
162 z--;
165 #if HAVE_PADDING_BITS
166 z = z << PADDING_BITS;
167 z = z >> PADDING_BITS;
168 #endif
169 memcpy (&c, &z, FIXED_SIZE);
170 return c;
172 #endif /* FIXED_SSSUB */
174 #if defined(FIXED_USSUB) && defined(L_ussub)
175 FIXED_C_TYPE
176 FIXED_USSUB (FIXED_C_TYPE a, FIXED_C_TYPE b)
178 FIXED_C_TYPE c;
179 INT_C_TYPE x, y, z;
180 memcpy (&x, &a, FIXED_SIZE);
181 memcpy (&y, &b, FIXED_SIZE);
182 z = x - y;
183 if (x < y)
184 z = 0;
185 #if HAVE_PADDING_BITS
186 z = z << PADDING_BITS;
187 z = z >> PADDING_BITS;
188 #endif
189 memcpy (&c, &z, FIXED_SIZE);
190 return c;
192 #endif /* FIXED_USSUB */
194 #if defined(FIXED_SATURATE1) && defined(L_saturate1)
195 void
196 FIXED_SATURATE1 (DINT_C_TYPE *a)
198 DINT_C_TYPE max, min;
199 max = (DINT_C_TYPE)1 << I_F_BITS;
200 max = max - 1;
201 #if MODE_UNSIGNED == 0
202 min = (DINT_C_TYPE)1 << (2 * FIXED_WIDTH - 1);
203 min = min >> (2 * FIXED_WIDTH - 1 - I_F_BITS);
204 #else
205 min = 0;
206 #endif
207 if (*a > max)
208 *a = max;
209 else if (*a < min)
210 *a = min;
212 #endif /* FIXED_SATURATE1 */
214 #if defined(FIXED_SATURATE2) && defined(L_saturate2)
215 void
216 FIXED_SATURATE2 (INT_C_TYPE *high, INT_C_TYPE *low)
218 INT_C_TYPE r_max, s_max, r_min, s_min;
219 r_max = 0;
220 #if (MODE_UNSIGNED == 0) || HAVE_PADDING_BITS
221 s_max = (INT_C_TYPE)1 << I_F_BITS;
222 s_max = s_max - 1;
223 #else
224 s_max = -1;
225 #endif
226 #if MODE_UNSIGNED == 0
227 r_min = -1;
228 s_min = (INT_C_TYPE)1 << (FIXED_WIDTH - 1);
229 s_min = s_min >> (FIXED_WIDTH - 1 - I_F_BITS);
230 #else
231 r_min = 0;
232 s_min = 0;
233 #endif
235 if (*high > r_max
236 || (*high == r_max && (UINT_C_TYPE)(*low) > (UINT_C_TYPE)s_max))
238 *high = r_max;
239 *low = s_max;
241 else if (*high < r_min ||
242 (*high == r_min && (UINT_C_TYPE)(*low) < (UINT_C_TYPE)s_min))
244 *high = r_min;
245 *low = s_min;
248 #endif /* FIXED_SATURATE2 */
250 #if defined(FIXED_MULHELPER) && defined(L_mulhelper)
251 FIXED_C_TYPE
252 FIXED_MULHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp)
254 FIXED_C_TYPE c;
255 INT_C_TYPE x, y;
257 #if defined (DINT_C_TYPE)
258 INT_C_TYPE z;
259 DINT_C_TYPE dx, dy, dz;
260 memcpy (&x, &a, FIXED_SIZE);
261 memcpy (&y, &b, FIXED_SIZE);
262 dx = (DINT_C_TYPE) x;
263 dy = (DINT_C_TYPE) y;
264 dz = dx * dy;
265 /* Round the result by adding (1 << (FBITS -1)). */
266 dz += ((DINT_C_TYPE) 1 << (FBITS - 1));
267 dz = dz >> FBITS;
268 if (satp)
269 FIXED_SATURATE1 (&dz);
271 z = (INT_C_TYPE) dz;
272 #if HAVE_PADDING_BITS
273 z = z << PADDING_BITS;
274 z = z >> PADDING_BITS;
275 #endif
276 memcpy (&c, &z, FIXED_SIZE);
277 return c;
279 #else /* No DINT_C_TYPE */
280 /* The result of multiplication expands to two INT_C_TYPE. */
281 INTunion aa, bb;
282 INTunion a_high, a_low, b_high, b_low;
283 INTunion high_high, high_low, low_high, low_low;
284 INTunion r, s, temp1, temp2;
285 INT_C_TYPE carry = 0;
286 INT_C_TYPE z;
288 memcpy (&x, &a, FIXED_SIZE);
289 memcpy (&y, &b, FIXED_SIZE);
291 /* Decompose a and b. */
292 aa.ll = x;
293 bb.ll = y;
295 a_high.s.low = aa.s.high;
296 a_high.s.high = 0;
297 a_low.s.low = aa.s.low;
298 a_low.s.high = 0;
299 b_high.s.low = bb.s.high;
300 b_high.s.high = 0;
301 b_low.s.low = bb.s.low;
302 b_low.s.high = 0;
304 /* Perform four multiplications. */
305 low_low.ll = a_low.ll * b_low.ll;
306 low_high.ll = a_low.ll * b_high.ll;
307 high_low.ll = a_high.ll * b_low.ll;
308 high_high.ll = a_high.ll * b_high.ll;
310 /* Accumulate four results to {r, s}. */
311 temp1.s.high = high_low.s.low;
312 temp1.s.low = 0;
313 s.ll = low_low.ll + temp1.ll;
314 if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) low_low.ll
315 || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll)
316 carry ++; /* Carry. */
317 temp1.ll = s.ll;
318 temp2.s.high = low_high.s.low;
319 temp2.s.low = 0;
320 s.ll = temp1.ll + temp2.ll;
321 if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll
322 || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp2.ll)
323 carry ++; /* Carry. */
325 temp1.s.low = high_low.s.high;
326 temp1.s.high = 0;
327 r.ll = high_high.ll + temp1.ll;
328 temp1.s.low = low_high.s.high;
329 temp1.s.high = 0;
330 r.ll = r.ll + temp1.ll + carry;
332 #if MODE_UNSIGNED == 0
333 /* For signed types, we need to add neg(y) to r, if x < 0. */
334 if (x < 0)
335 r.ll = r.ll - y;
336 /* We need to add neg(x) to r, if y < 0. */
337 if (y < 0)
338 r.ll = r.ll - x;
339 #endif
341 /* Round the result by adding (1 << (FBITS -1)). */
342 temp1.ll = s.ll;
343 s.ll += ((INT_C_TYPE) 1 << (FBITS -1));
344 if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll
345 || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) ((INT_C_TYPE) 1 << (FBITS -1)))
346 r.ll += 1;
348 /* Shift right the result by FBITS. */
349 #if FBITS == FIXED_WIDTH
350 /* This happens only for unsigned types without any padding bits.
351 So, it is safe to set r.ll to 0 as it is logically shifted right. */
352 s.ll = r.ll;
353 r.ll = 0;
354 #else
355 s.ll = ((UINT_C_TYPE)s.ll) >> FBITS;
356 temp1.ll = r.ll << (FIXED_WIDTH - FBITS);
357 s.ll = s.ll | temp1.ll;
358 r.ll = r.ll >> FBITS;
359 #endif
361 if (satp)
362 FIXED_SATURATE2 (&r.ll, &s.ll);
364 z = (INT_C_TYPE) s.ll;
365 #if HAVE_PADDING_BITS
366 z = z << PADDING_BITS;
367 z = z >> PADDING_BITS;
368 #endif
369 memcpy (&c, &z, FIXED_SIZE);
370 return c;
371 #endif
373 #endif /* FIXED_MULHELPER */
375 #if defined(FIXED_MUL) && defined(L_mul)
376 FIXED_C_TYPE
377 FIXED_MUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
379 return FIXED_MULHELPER (a, b, 0);
381 #endif /* FIXED_MUL */
383 #if defined(FIXED_SSMUL) && defined(L_ssmul)
384 FIXED_C_TYPE
385 FIXED_SSMUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
387 return FIXED_MULHELPER (a, b, 1);
389 #endif /* FIXED_SSMUL */
391 #if defined(FIXED_USMUL) && defined(L_usmul)
392 FIXED_C_TYPE
393 FIXED_USMUL (FIXED_C_TYPE a, FIXED_C_TYPE b)
395 return FIXED_MULHELPER (a, b, 1);
397 #endif /* FIXED_USMUL */
399 #if defined(FIXED_DIVHELPER) && defined(L_divhelper)
400 FIXED_C_TYPE
401 FIXED_DIVHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp)
403 FIXED_C_TYPE c;
404 INT_C_TYPE x, y;
405 INT_C_TYPE z;
407 #if defined (DINT_C_TYPE)
408 DINT_C_TYPE dx, dy, dz;
409 memcpy (&x, &a, FIXED_SIZE);
410 memcpy (&y, &b, FIXED_SIZE);
411 dx = (DINT_C_TYPE) x;
412 dy = (DINT_C_TYPE) y;
413 dx = dx << FBITS;
414 dz = dx / dy;
415 if (satp)
416 FIXED_SATURATE1 (&dz);
417 z = (INT_C_TYPE) dz;
418 #if HAVE_PADDING_BITS
419 z = z << PADDING_BITS;
420 z = z >> PADDING_BITS;
421 #endif
422 memcpy (&c, &z, FIXED_SIZE);
423 return c;
425 #else /* No DINT_C_TYPE */
426 INT_C_TYPE pos_a, pos_b, r, s;
427 INT_C_TYPE quo_r, quo_s, mod, temp;
428 word_type i;
429 #if MODE_UNSIGNED == 0
430 word_type num_of_neg = 0;
431 #endif
433 memcpy (&x, &a, FIXED_SIZE);
434 memcpy (&y, &b, FIXED_SIZE);
435 pos_a = x;
436 pos_b = y;
438 #if MODE_UNSIGNED == 0
439 /* If a < 0, negate a. */
440 if (pos_a < 0)
442 pos_a = -pos_a;
443 num_of_neg ++;
445 /* If b < 0, negate b. */
446 if (pos_b < 0)
448 pos_b = -pos_b;
449 num_of_neg ++;
451 #endif
453 /* Left shift pos_a to {r, s} by FBITS. */
454 #if FBITS == FIXED_WIDTH
455 /* This happens only for unsigned types without any padding bits. */
456 r = pos_a;
457 s = 0;
458 #else
459 s = pos_a << FBITS;
460 r = pos_a >> (FIXED_WIDTH - FBITS);
461 #endif
463 /* Unsigned divide r by pos_b to quo_r. The remainder is in mod. */
464 quo_r = (UINT_C_TYPE)r / (UINT_C_TYPE)pos_b;
465 mod = (UINT_C_TYPE)r % (UINT_C_TYPE)pos_b;
466 quo_s = 0;
468 for (i = 0; i < FIXED_WIDTH; i++)
470 /* Record the leftmost bit of mod. */
471 word_type leftmost_mode = (mod >> (FIXED_WIDTH - 1)) & 1;
472 /* Shift left mod by 1 bit. */
473 mod = mod << 1;
474 /* Test the leftmost bit of s to add to mod. */
475 if ((s >> (FIXED_WIDTH - 1)) & 1)
476 mod ++;
477 /* Shift left quo_s by 1 bit. */
478 quo_s = quo_s << 1;
479 /* Try to calculate (mod - pos_b). */
480 temp = mod - pos_b;
481 if (leftmost_mode || (UINT_C_TYPE)mod >= (UINT_C_TYPE)pos_b)
483 quo_s ++;
484 mod = temp;
486 /* Shift left s by 1 bit. */
487 s = s << 1;
490 #if MODE_UNSIGNED == 0
491 if (num_of_neg == 1)
493 quo_s = -quo_s;
494 if (quo_s == 0)
495 quo_r = -quo_r;
496 else
497 quo_r = ~quo_r;
499 #endif
500 if (satp)
501 FIXED_SATURATE2 (&quo_r, &quo_s);
502 z = quo_s;
503 #if HAVE_PADDING_BITS
504 z = z << PADDING_BITS;
505 z = z >> PADDING_BITS;
506 #endif
507 memcpy (&c, &z, FIXED_SIZE);
508 return c;
509 #endif
511 #endif /* FIXED_DIVHELPER */
513 #if defined(FIXED_DIV) && defined(L_div)
514 FIXED_C_TYPE
515 FIXED_DIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
517 return FIXED_DIVHELPER (a, b, 0);
519 #endif /* FIXED_DIV */
522 #if defined(FIXED_UDIV) && defined(L_udiv)
523 FIXED_C_TYPE
524 FIXED_UDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
526 return FIXED_DIVHELPER (a, b, 0);
528 #endif /* FIXED_UDIV */
530 #if defined(FIXED_SSDIV) && defined(L_ssdiv)
531 FIXED_C_TYPE
532 FIXED_SSDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
534 return FIXED_DIVHELPER (a, b, 1);
536 #endif /* FIXED_SSDIV */
538 #if defined(FIXED_USDIV) && defined(L_usdiv)
539 FIXED_C_TYPE
540 FIXED_USDIV (FIXED_C_TYPE a, FIXED_C_TYPE b)
542 return FIXED_DIVHELPER (a, b, 1);
544 #endif /* FIXED_USDIV */
546 #if defined(FIXED_NEG) && defined(L_neg)
547 FIXED_C_TYPE
548 FIXED_NEG (FIXED_C_TYPE a)
550 FIXED_C_TYPE c;
551 INT_C_TYPE x, z;
552 memcpy (&x, &a, FIXED_SIZE);
553 z = -x;
554 #if HAVE_PADDING_BITS
555 z = z << PADDING_BITS;
556 z = z >> PADDING_BITS;
557 #endif
558 memcpy (&c, &z, FIXED_SIZE);
559 return c;
561 #endif /* FIXED_NEG */
563 #if defined(FIXED_SSNEG) && defined(L_ssneg)
564 FIXED_C_TYPE
565 FIXED_SSNEG (FIXED_C_TYPE a)
567 FIXED_C_TYPE c;
568 INT_C_TYPE x, y, z;
569 memcpy (&y, &a, FIXED_SIZE);
570 x = 0;
571 z = x - y;
572 if (((x ^ y) >> I_F_BITS) & 1)
574 if (((z ^ x) >> I_F_BITS) & 1)
576 z = 1;
577 z = z << I_F_BITS;
578 if (x >= 0)
579 z--;
582 #if HAVE_PADDING_BITS
583 z = z << PADDING_BITS;
584 z = z >> PADDING_BITS;
585 #endif
586 memcpy (&c, &z, FIXED_SIZE);
587 return c;
589 #endif /* FIXED_SSNEG */
591 #if defined(FIXED_USNEG) && defined(L_usneg)
592 FIXED_C_TYPE
593 FIXED_USNEG (FIXED_C_TYPE a __attribute__ ((__unused__)))
595 FIXED_C_TYPE c;
596 INT_C_TYPE z;
597 z = 0;
598 memcpy (&c, &z, FIXED_SIZE);
599 return c;
601 #endif /* FIXED_USNEG */
603 #if defined(FIXED_ASHLHELPER) && defined(L_ashlhelper)
604 FIXED_C_TYPE
605 FIXED_ASHLHELPER (FIXED_C_TYPE a, word_type b, word_type satp)
607 FIXED_C_TYPE c;
608 INT_C_TYPE x, z;
610 #if defined (DINT_C_TYPE)
611 DINT_C_TYPE dx, dz;
612 memcpy (&x, &a, FIXED_SIZE);
613 dx = (DINT_C_TYPE) x;
614 if (b >= FIXED_WIDTH)
615 dz = dx << FIXED_WIDTH;
616 else
617 dz = dx << b;
618 if (satp)
619 FIXED_SATURATE1 (&dz);
620 z = (INT_C_TYPE) dz;
621 #if HAVE_PADDING_BITS
622 z = z << PADDING_BITS;
623 z = z >> PADDING_BITS;
624 #endif
625 memcpy (&c, &z, FIXED_SIZE);
626 return c;
628 #else /* No DINT_C_TYPE */
629 INT_C_TYPE r, s;
630 memcpy (&x, &a, FIXED_SIZE);
631 /* We need to shift left x by b bits to {r, s}. */
632 if (b >= FIXED_WIDTH)
634 r = b;
635 s = 0;
637 else
639 s = x << b;
640 r = x >> (FIXED_WIDTH - b);
642 if (satp)
643 FIXED_SATURATE2 (&r, &s);
644 z = s;
645 #if HAVE_PADDING_BITS
646 z = z << PADDING_BITS;
647 z = z >> PADDING_BITS;
648 #endif
649 memcpy (&c, &z, FIXED_SIZE);
650 return c;
651 #endif
653 #endif /* FIXED_ASHLHELPER */
655 #if defined(FIXED_ASHL) && defined(L_ashl)
656 FIXED_C_TYPE
657 FIXED_ASHL (FIXED_C_TYPE a, word_type b)
659 return FIXED_ASHLHELPER (a, b, 0);
661 #endif /* FIXED_ASHL */
663 #if defined(FIXED_ASHR) && defined(L_ashr)
664 FIXED_C_TYPE
665 FIXED_ASHR (FIXED_C_TYPE a, word_type b)
667 FIXED_C_TYPE c;
668 INT_C_TYPE x, z;
669 memcpy (&x, &a, FIXED_SIZE);
670 z = x >> b;
671 #if HAVE_PADDING_BITS
672 z = z << PADDING_BITS;
673 z = z >> PADDING_BITS;
674 #endif
675 memcpy (&c, &z, FIXED_SIZE);
676 return c;
678 #endif /* FIXED_ASHR */
680 #if defined(FIXED_LSHR) && defined(L_lshr)
681 FIXED_C_TYPE
682 FIXED_LSHR (FIXED_C_TYPE a, word_type b)
684 FIXED_C_TYPE c;
685 INT_C_TYPE x, z;
686 memcpy (&x, &a, FIXED_SIZE);
687 z = x >> b;
688 #if HAVE_PADDING_BITS
689 z = z << PADDING_BITS;
690 z = z >> PADDING_BITS;
691 #endif
692 memcpy (&c, &z, FIXED_SIZE);
693 return c;
695 #endif /* FIXED_LSHR */
697 #if defined(FIXED_SSASHL) && defined(L_ssashl)
698 FIXED_C_TYPE
699 FIXED_SSASHL (FIXED_C_TYPE a, word_type b)
701 return FIXED_ASHLHELPER (a, b, 1);
703 #endif /* FIXED_SSASHL */
705 #if defined(FIXED_USASHL) && defined(L_usashl)
706 FIXED_C_TYPE
707 FIXED_USASHL (FIXED_C_TYPE a, word_type b)
709 return FIXED_ASHLHELPER (a, b, 1);
711 #endif /* FIXED_USASHL */
713 #if defined(FIXED_CMP) && defined(L_cmp)
714 word_type
715 FIXED_CMP (FIXED_C_TYPE a, FIXED_C_TYPE b)
717 INT_C_TYPE x, y;
718 memcpy (&x, &a, FIXED_SIZE);
719 memcpy (&y, &b, FIXED_SIZE);
721 if (x < y)
722 return 0;
723 else if (x > y)
724 return 2;
726 return 1;
728 #endif /* FIXED_CMP */
730 /* Fixed -> Fixed. */
731 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 4
732 TO_FIXED_C_TYPE
733 FRACT (FROM_FIXED_C_TYPE a)
735 TO_FIXED_C_TYPE c;
736 FROM_INT_C_TYPE x;
737 TO_INT_C_TYPE z;
738 int shift_amount;
739 memcpy (&x, &a, FROM_FIXED_SIZE);
740 #if TO_FBITS > FROM_FBITS /* Need left shift. */
741 shift_amount = TO_FBITS - FROM_FBITS;
742 z = (TO_INT_C_TYPE) x;
743 z = z << shift_amount;
744 #else /* TO_FBITS <= FROM_FBITS. Need right Shift. */
745 shift_amount = FROM_FBITS - TO_FBITS;
746 x = x >> shift_amount;
747 z = (TO_INT_C_TYPE) x;
748 #endif /* TO_FBITS > FROM_FBITS */
750 #if TO_HAVE_PADDING_BITS
751 z = z << TO_PADDING_BITS;
752 z = z >> TO_PADDING_BITS;
753 #endif
754 memcpy (&c, &z, TO_FIXED_SIZE);
755 return c;
757 #endif /* FRACT && FROM_TYPE == 4 && TO_TYPE == 4 */
759 /* Fixed -> Fixed with saturation. */
760 #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 4 && TO_TYPE == 4
761 TO_FIXED_C_TYPE
762 SATFRACT (FROM_FIXED_C_TYPE a)
764 TO_FIXED_C_TYPE c;
765 TO_INT_C_TYPE z;
766 FROM_INT_C_TYPE x;
767 #if FROM_MODE_UNSIGNED == 0
768 BIG_SINT_C_TYPE high, low;
769 BIG_SINT_C_TYPE max_high, max_low;
770 BIG_SINT_C_TYPE min_high, min_low;
771 #else
772 BIG_UINT_C_TYPE high, low;
773 BIG_UINT_C_TYPE max_high, max_low;
774 BIG_UINT_C_TYPE min_high, min_low;
775 #endif
776 #if TO_FBITS > FROM_FBITS
777 BIG_UINT_C_TYPE utemp;
778 #endif
779 #if TO_MODE_UNSIGNED == 0
780 BIG_SINT_C_TYPE stemp;
781 #endif
782 #if TO_FBITS != FROM_FBITS
783 int shift_amount;
784 #endif
785 memcpy (&x, &a, FROM_FIXED_SIZE);
787 /* Step 1. We need to store x to {high, low}. */
788 #if FROM_MODE_UNSIGNED == 0
789 low = (BIG_SINT_C_TYPE) x;
790 if (x < 0)
791 high = -1;
792 else
793 high = 0;
794 #else
795 low = (BIG_UINT_C_TYPE) x;
796 high = 0;
797 #endif
799 /* Step 2. We need to shift {high, low}. */
800 #if TO_FBITS > FROM_FBITS /* Left shift. */
801 shift_amount = TO_FBITS - FROM_FBITS;
802 utemp = (BIG_UINT_C_TYPE) low;
803 utemp = utemp >> (BIG_WIDTH - shift_amount);
804 high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
805 low = low << shift_amount;
806 #elif TO_FBITS < FROM_FBITS /* Right shift. */
807 shift_amount = FROM_FBITS - TO_FBITS;
808 low = low >> shift_amount;
809 #endif
811 /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */
812 max_high = 0;
813 #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
814 max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
815 max_low = max_low - 1;
816 #else
817 max_low = -1;
818 #endif
820 #if TO_MODE_UNSIGNED == 0
821 min_high = -1;
822 stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1);
823 stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS);
824 min_low = stemp;
825 #else
826 min_high = 0;
827 min_low = 0;
828 #endif
830 #if FROM_MODE_UNSIGNED == 0 && TO_MODE_UNSIGNED == 0
831 /* Signed -> Signed. */
832 if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
833 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
834 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
835 low = max_low; /* Maximum. */
836 else if ((BIG_SINT_C_TYPE) high < (BIG_SINT_C_TYPE) min_high
837 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) min_high
838 && (BIG_UINT_C_TYPE) low < (BIG_UINT_C_TYPE) min_low))
839 low = min_low; /* Minimum. */
840 #elif FROM_MODE_UNSIGNED == 1 && TO_MODE_UNSIGNED == 1
841 /* Unigned -> Unsigned. */
842 if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
843 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
844 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
845 low = max_low; /* Maximum. */
846 #elif FROM_MODE_UNSIGNED == 0 && TO_MODE_UNSIGNED == 1
847 /* Signed -> Unsigned. */
848 if (x < 0)
849 low = 0; /* Minimum. */
850 else if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
851 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
852 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
853 low = max_low; /* Maximum. */
854 #elif FROM_MODE_UNSIGNED == 1 && TO_MODE_UNSIGNED == 0
855 /* Unsigned -> Signed. */
856 if ((BIG_SINT_C_TYPE) high < 0)
857 low = max_low; /* Maximum. */
858 else if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
859 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
860 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
861 low = max_low; /* Maximum. */
862 #endif
864 /* Step 4. Store the result. */
865 z = (TO_INT_C_TYPE) low;
866 #if TO_HAVE_PADDING_BITS
867 z = z << TO_PADDING_BITS;
868 z = z >> TO_PADDING_BITS;
869 #endif
870 memcpy (&c, &z, TO_FIXED_SIZE);
871 return c;
873 #endif /* defined(SATFRACT) && FROM_TYPE == 4 && TO_TYPE == 4 */
875 /* Fixed -> Int. */
876 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 1
877 TO_INT_C_TYPE
878 FRACT (FROM_FIXED_C_TYPE a)
880 FROM_INT_C_TYPE x;
881 TO_INT_C_TYPE z;
882 FROM_INT_C_TYPE i = 0;
883 memcpy (&x, &a, FROM_FIXED_SIZE);
885 #if FROM_MODE_UNSIGNED == 0
886 if (x < 0)
888 #if FROM_FIXED_WIDTH == FROM_FBITS
889 if (x != 0)
890 i = 1;
891 #else
892 if (((FROM_INT_C_TYPE)(x << (FROM_FIXED_WIDTH - FROM_FBITS))) != 0)
893 i = 1;
894 #endif
896 #endif
898 #if FROM_FIXED_WIDTH == FROM_FBITS
899 x = 0;
900 #else
901 x = x >> FROM_FBITS;
902 #endif
903 x = x + i;
904 z = (TO_INT_C_TYPE) x;
905 return z;
907 #endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 1 */
909 /* Fixed -> Unsigned int. */
910 #if defined(FRACTUNS) && defined(L_fractuns) && FROM_TYPE == 4 && TO_TYPE == 2
911 TO_INT_C_TYPE
912 FRACTUNS (FROM_FIXED_C_TYPE a)
914 FROM_INT_C_TYPE x;
915 TO_INT_C_TYPE z;
916 FROM_INT_C_TYPE i = 0;
917 memcpy (&x, &a, FROM_FIXED_SIZE);
919 #if FROM_MODE_UNSIGNED == 0
920 if (x < 0)
922 #if FROM_FIXED_WIDTH == FROM_FBITS
923 if (x != 0)
924 i = 1;
925 #else
926 if (((FROM_INT_C_TYPE)(x << (FROM_FIXED_WIDTH - FROM_FBITS))) != 0)
927 i = 1;
928 #endif
930 #endif
932 #if FROM_FIXED_WIDTH == FROM_FBITS
933 x = 0;
934 #else
935 x = x >> FROM_FBITS;
936 #endif
937 x = x + i;
938 z = (TO_INT_C_TYPE) x;
939 return z;
941 #endif /* defined(FRACTUNS) && FROM_TYPE == 4 && TO_TYPE == 2 */
943 /* Int -> Fixed. */
944 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 1 && TO_TYPE == 4
945 TO_FIXED_C_TYPE
946 FRACT (FROM_INT_C_TYPE a)
948 TO_FIXED_C_TYPE c;
949 TO_INT_C_TYPE z;
950 z = (TO_INT_C_TYPE) a;
951 #if TO_FIXED_WIDTH == TO_FBITS
952 z = 0;
953 #else
954 z = z << TO_FBITS;
955 #endif
956 #if TO_HAVE_PADDING_BITS
957 z = z << TO_PADDING_BITS;
958 z = z >> TO_PADDING_BITS;
959 #endif
960 memcpy (&c, &z, TO_FIXED_SIZE);
961 return c;
963 #endif /* defined(FRACT) && FROM_TYPE == 1 && TO_TYPE == 4 */
965 /* Signed int -> Fixed with saturation. */
966 #if defined(SATFRACT) && defined(L_satfract) &&FROM_TYPE == 1 && TO_TYPE == 4
967 TO_FIXED_C_TYPE
968 SATFRACT (FROM_INT_C_TYPE a)
970 TO_FIXED_C_TYPE c;
971 TO_INT_C_TYPE z;
972 FROM_INT_C_TYPE x = a;
973 BIG_SINT_C_TYPE high, low;
974 BIG_SINT_C_TYPE max_high, max_low;
975 BIG_SINT_C_TYPE min_high, min_low;
976 #if TO_MODE_UNSIGNED == 0
977 BIG_SINT_C_TYPE stemp;
978 #endif
979 #if BIG_WIDTH != TO_FBITS
980 BIG_UINT_C_TYPE utemp;
981 int shift_amount;
982 #endif
984 /* Step 1. We need to store x to {high, low}. */
985 low = (BIG_SINT_C_TYPE) x;
986 if (x < 0)
987 high = -1;
988 else
989 high = 0;
991 /* Step 2. We need to left shift {high, low}. */
992 #if BIG_WIDTH == TO_FBITS
993 high = low;
994 low = 0;
995 #else
996 shift_amount = TO_FBITS;
997 utemp = (BIG_UINT_C_TYPE) low;
998 utemp = utemp >> (BIG_WIDTH - shift_amount);
999 high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
1000 low = low << shift_amount;
1001 #endif
1003 /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */
1004 max_high = 0;
1005 #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
1006 max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
1007 max_low = max_low - 1;
1008 #else
1009 max_low = -1;
1010 #endif
1012 #if TO_MODE_UNSIGNED == 0
1013 min_high = -1;
1014 stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1);
1015 stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS);
1016 min_low = stemp;
1017 #else
1018 min_high = 0;
1019 min_low = 0;
1020 #endif
1022 #if TO_MODE_UNSIGNED == 0
1023 /* Signed -> Signed. */
1024 if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
1025 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
1026 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1027 low = max_low; /* Maximum. */
1028 else if ((BIG_SINT_C_TYPE) high < (BIG_SINT_C_TYPE) min_high
1029 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) min_high
1030 && (BIG_UINT_C_TYPE) low < (BIG_UINT_C_TYPE) min_low))
1031 low = min_low; /* Minimum. */
1032 #else
1033 /* Signed -> Unsigned. */
1034 if (x < 0)
1035 low = 0; /* Minimum. */
1036 else if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
1037 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
1038 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1039 low = max_low; /* Maximum. */
1040 #endif
1042 /* Step 4. Store the result. */
1043 z = (TO_INT_C_TYPE) low;
1044 #if TO_HAVE_PADDING_BITS
1045 z = z << TO_PADDING_BITS;
1046 z = z >> TO_PADDING_BITS;
1047 #endif
1048 memcpy (&c, &z, TO_FIXED_SIZE);
1049 return c;
1051 #endif /* defined(SATFRACT) && FROM_TYPE == 1 && TO_TYPE == 4 */
1053 /* Unsigned int -> Fixed. */
1054 #if defined(FRACTUNS) && defined(L_fractuns) &&FROM_TYPE == 2 && TO_TYPE == 4
1055 TO_FIXED_C_TYPE
1056 FRACTUNS (FROM_INT_C_TYPE a)
1058 TO_FIXED_C_TYPE c;
1059 TO_INT_C_TYPE z;
1060 z = (TO_INT_C_TYPE) a;
1061 #if TO_FIXED_WIDTH == TO_FBITS
1062 z = 0;
1063 #else
1064 z = z << TO_FBITS;
1065 #endif
1066 #if TO_HAVE_PADDING_BITS
1067 z = z << TO_PADDING_BITS;
1068 z = z >> TO_PADDING_BITS;
1069 #endif
1070 memcpy (&c, &z, TO_FIXED_SIZE);
1071 return c;
1073 #endif /* defined(FRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4 */
1075 /* Unsigned int -> Fixed with saturation. */
1076 #if defined(SATFRACTUNS) && defined(L_satfractuns) && FROM_TYPE == 2 && TO_TYPE == 4
1077 TO_FIXED_C_TYPE
1078 SATFRACTUNS (FROM_INT_C_TYPE a)
1080 TO_FIXED_C_TYPE c;
1081 TO_INT_C_TYPE z;
1082 FROM_INT_C_TYPE x = a;
1083 BIG_UINT_C_TYPE high, low;
1084 BIG_UINT_C_TYPE max_high, max_low;
1085 #if BIG_WIDTH != TO_FBITS
1086 BIG_UINT_C_TYPE utemp;
1087 int shift_amount;
1088 #endif
1090 /* Step 1. We need to store x to {high, low}. */
1091 low = (BIG_UINT_C_TYPE) x;
1092 high = 0;
1094 /* Step 2. We need to left shift {high, low}. */
1095 #if BIG_WIDTH == TO_FBITS
1096 high = low;
1097 low = 0;
1098 #else
1099 shift_amount = TO_FBITS;
1100 utemp = (BIG_UINT_C_TYPE) low;
1101 utemp = utemp >> (BIG_WIDTH - shift_amount);
1102 high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp;
1103 low = low << shift_amount;
1104 #endif
1106 /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */
1107 max_high = 0;
1108 #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
1109 max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS;
1110 max_low = max_low - 1;
1111 #else
1112 max_low = -1;
1113 #endif
1115 #if TO_MODE_UNSIGNED == 1
1116 /* Unigned -> Unsigned. */
1117 if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high
1118 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high
1119 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1120 low = max_low; /* Maximum. */
1121 #else
1122 /* Unsigned -> Signed. */
1123 if ((BIG_SINT_C_TYPE) high < 0)
1124 low = max_low; /* Maximum. */
1125 else if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high
1126 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high
1127 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low))
1128 low = max_low; /* Maximum. */
1129 #endif
1131 /* Step 4. Store the result. */
1132 z = (TO_INT_C_TYPE) low;
1133 #if TO_HAVE_PADDING_BITS
1134 z = z << TO_PADDING_BITS;
1135 z = z >> TO_PADDING_BITS;
1136 #endif
1137 memcpy (&c, &z, TO_FIXED_SIZE);
1138 return c;
1140 #endif /* defined(SATFRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4 */
1142 /* Fixed -> Float. */
1143 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 3
1144 TO_FLOAT_C_TYPE
1145 FRACT (FROM_FIXED_C_TYPE a)
1147 FROM_INT_C_TYPE x;
1148 TO_FLOAT_C_TYPE z;
1149 memcpy (&x, &a, FROM_FIXED_SIZE);
1150 z = (TO_FLOAT_C_TYPE) x;
1151 z = z / BASE;
1152 return z;
1154 #endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 3 */
1156 /* Float -> Fixed. */
1157 #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 3 && TO_TYPE == 4
1158 TO_FIXED_C_TYPE
1159 FRACT (FROM_FLOAT_C_TYPE a)
1161 FROM_FLOAT_C_TYPE temp;
1162 TO_INT_C_TYPE z;
1163 TO_FIXED_C_TYPE c;
1165 temp = a * BASE;
1166 z = (TO_INT_C_TYPE) temp;
1167 #if TO_HAVE_PADDING_BITS
1168 z = z << TO_PADDING_BITS;
1169 z = z >> TO_PADDING_BITS;
1170 #endif
1171 memcpy (&c, &z, TO_FIXED_SIZE);
1172 return c;
1174 #endif /* defined(FRACT) && FROM_TYPE == 3 && TO_TYPE == 4 */
1176 /* Float -> Fixed with saturation. */
1177 #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 3 && TO_TYPE == 4
1178 TO_FIXED_C_TYPE
1179 SATFRACT (FROM_FLOAT_C_TYPE a)
1181 FROM_FLOAT_C_TYPE temp;
1182 TO_INT_C_TYPE z;
1183 TO_FIXED_C_TYPE c;
1185 if (a >= FIXED_MAX)
1187 #if TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS
1188 z = (TO_INT_C_TYPE)1 << TO_I_F_BITS;
1189 z = z - 1;
1190 #else
1191 z = -1;
1192 #endif
1194 else if (a <= FIXED_MIN)
1196 #if TO_MODE_UNSIGNED == 0
1197 z = (TO_INT_C_TYPE)1 << TO_I_F_BITS;
1198 #else
1199 z = 0;
1200 #endif
1202 else
1204 temp = a * BASE;
1205 z = (TO_INT_C_TYPE) temp;
1208 #if TO_HAVE_PADDING_BITS
1209 z = z << TO_PADDING_BITS;
1210 z = z >> TO_PADDING_BITS;
1211 #endif
1212 memcpy (&c, &z, TO_FIXED_SIZE);
1213 return c;
1215 #endif /* defined(SATFRACT) && FROM_TYPE == 3 && TO_TYPE == 4 */