1 /* Fixed-point arithmetic support.
2 Copyright (C) 2006, 2007, 2008, 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
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
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
22 #include "coretypes.h"
25 #include "diagnostic-core.h"
28 /* Compare two fixed objects for bitwise identity. */
31 fixed_identical (const FIXED_VALUE_TYPE
*a
, const FIXED_VALUE_TYPE
*b
)
33 return (a
->mode
== b
->mode
34 && a
->data
.high
== b
->data
.high
35 && a
->data
.low
== b
->data
.low
);
38 /* Calculate a hash value. */
41 fixed_hash (const FIXED_VALUE_TYPE
*f
)
43 return (unsigned int) (f
->data
.low
^ f
->data
.high
);
46 /* Define the enum code for the range of the fixed-point value. */
47 enum fixed_value_range_code
{
48 FIXED_OK
, /* The value is within the range. */
49 FIXED_UNDERFLOW
, /* The value is less than the minimum. */
50 FIXED_GT_MAX_EPS
, /* The value is greater than the maximum, but not equal
51 to the maximum plus the epsilon. */
52 FIXED_MAX_EPS
/* The value equals the maximum plus the epsilon. */
55 /* Check REAL_VALUE against the range of the fixed-point mode.
56 Return FIXED_OK, if it is within the range.
57 FIXED_UNDERFLOW, if it is less than the minimum.
58 FIXED_GT_MAX_EPS, if it is greater than the maximum, but not equal to
59 the maximum plus the epsilon.
60 FIXED_MAX_EPS, if it is equal to the maximum plus the epsilon. */
62 static enum fixed_value_range_code
63 check_real_for_fixed_mode (REAL_VALUE_TYPE
*real_value
, enum machine_mode mode
)
65 REAL_VALUE_TYPE max_value
, min_value
, epsilon_value
;
67 real_2expN (&max_value
, GET_MODE_IBIT (mode
), mode
);
68 real_2expN (&epsilon_value
, -GET_MODE_FBIT (mode
), mode
);
70 if (SIGNED_FIXED_POINT_MODE_P (mode
))
71 min_value
= real_value_negate (&max_value
);
73 real_from_string (&min_value
, "0.0");
75 if (real_compare (LT_EXPR
, real_value
, &min_value
))
76 return FIXED_UNDERFLOW
;
77 if (real_compare (EQ_EXPR
, real_value
, &max_value
))
79 real_arithmetic (&max_value
, MINUS_EXPR
, &max_value
, &epsilon_value
);
80 if (real_compare (GT_EXPR
, real_value
, &max_value
))
81 return FIXED_GT_MAX_EPS
;
85 /* Initialize from a decimal or hexadecimal string. */
88 fixed_from_string (FIXED_VALUE_TYPE
*f
, const char *str
, enum machine_mode mode
)
90 REAL_VALUE_TYPE real_value
, fixed_value
, base_value
;
92 enum fixed_value_range_code temp
;
95 fbit
= GET_MODE_FBIT (mode
);
97 real_from_string (&real_value
, str
);
98 temp
= check_real_for_fixed_mode (&real_value
, f
->mode
);
99 /* We don't want to warn the case when the _Fract value is 1.0. */
100 if (temp
== FIXED_UNDERFLOW
101 || temp
== FIXED_GT_MAX_EPS
102 || (temp
== FIXED_MAX_EPS
&& ALL_ACCUM_MODE_P (f
->mode
)))
103 warning (OPT_Woverflow
,
104 "large fixed-point constant implicitly truncated to fixed-point type");
105 real_2expN (&base_value
, fbit
, mode
);
106 real_arithmetic (&fixed_value
, MULT_EXPR
, &real_value
, &base_value
);
107 real_to_integer2 ((HOST_WIDE_INT
*)&f
->data
.low
, &f
->data
.high
,
110 if (temp
== FIXED_MAX_EPS
&& ALL_FRACT_MODE_P (f
->mode
))
112 /* From the spec, we need to evaluate 1 to the maximal value. */
115 f
->data
= double_int_ext (f
->data
,
116 GET_MODE_FBIT (f
->mode
)
117 + GET_MODE_IBIT (f
->mode
), 1);
120 f
->data
= double_int_ext (f
->data
,
121 SIGNED_FIXED_POINT_MODE_P (f
->mode
)
122 + GET_MODE_FBIT (f
->mode
)
123 + GET_MODE_IBIT (f
->mode
),
124 UNSIGNED_FIXED_POINT_MODE_P (f
->mode
));
127 /* Render F as a decimal floating point constant. */
130 fixed_to_decimal (char *str
, const FIXED_VALUE_TYPE
*f_orig
,
133 REAL_VALUE_TYPE real_value
, base_value
, fixed_value
;
135 real_2expN (&base_value
, GET_MODE_FBIT (f_orig
->mode
), f_orig
->mode
);
136 real_from_integer (&real_value
, VOIDmode
, f_orig
->data
.low
, f_orig
->data
.high
,
137 UNSIGNED_FIXED_POINT_MODE_P (f_orig
->mode
));
138 real_arithmetic (&fixed_value
, RDIV_EXPR
, &real_value
, &base_value
);
139 real_to_decimal (str
, &fixed_value
, buf_size
, 0, 1);
142 /* If SAT_P, saturate A to the maximum or the minimum, and save to *F based on
143 the machine mode MODE.
144 Do not modify *F otherwise.
145 This function assumes the width of double_int is greater than the width
146 of the fixed-point value (the sum of a possible sign bit, possible ibits,
148 Return true, if !SAT_P and overflow. */
151 fixed_saturate1 (enum machine_mode mode
, double_int a
, double_int
*f
,
154 bool overflow_p
= false;
155 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (mode
);
156 int i_f_bits
= GET_MODE_IBIT (mode
) + GET_MODE_FBIT (mode
);
158 if (unsigned_p
) /* Unsigned type. */
163 max
= double_int_ext (max
, i_f_bits
, 1);
164 if (double_int_cmp (a
, max
, 1) == 1)
172 else /* Signed type. */
177 max
= double_int_ext (max
, i_f_bits
, 1);
180 lshift_double (min
.low
, min
.high
, i_f_bits
,
181 2 * HOST_BITS_PER_WIDE_INT
,
182 &min
.low
, &min
.high
, 1);
183 min
= double_int_ext (min
, 1 + i_f_bits
, 0);
184 if (double_int_cmp (a
, max
, 0) == 1)
191 else if (double_int_cmp (a
, min
, 0) == -1)
202 /* If SAT_P, saturate {A_HIGH, A_LOW} to the maximum or the minimum, and
203 save to *F based on the machine mode MODE.
204 Do not modify *F otherwise.
205 This function assumes the width of two double_int is greater than the width
206 of the fixed-point value (the sum of a possible sign bit, possible ibits,
208 Return true, if !SAT_P and overflow. */
211 fixed_saturate2 (enum machine_mode mode
, double_int a_high
, double_int a_low
,
212 double_int
*f
, bool sat_p
)
214 bool overflow_p
= false;
215 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (mode
);
216 int i_f_bits
= GET_MODE_IBIT (mode
) + GET_MODE_FBIT (mode
);
218 if (unsigned_p
) /* Unsigned type. */
220 double_int max_r
, max_s
;
225 max_s
= double_int_ext (max_s
, i_f_bits
, 1);
226 if (double_int_cmp (a_high
, max_r
, 1) == 1
227 || (double_int_equal_p (a_high
, max_r
) &&
228 double_int_cmp (a_low
, max_s
, 1) == 1))
236 else /* Signed type. */
238 double_int max_r
, max_s
, min_r
, min_s
;
243 max_s
= double_int_ext (max_s
, i_f_bits
, 1);
248 lshift_double (min_s
.low
, min_s
.high
, i_f_bits
,
249 2 * HOST_BITS_PER_WIDE_INT
,
250 &min_s
.low
, &min_s
.high
, 1);
251 min_s
= double_int_ext (min_s
, 1 + i_f_bits
, 0);
252 if (double_int_cmp (a_high
, max_r
, 0) == 1
253 || (double_int_equal_p (a_high
, max_r
) &&
254 double_int_cmp (a_low
, max_s
, 1) == 1))
261 else if (double_int_cmp (a_high
, min_r
, 0) == -1
262 || (double_int_equal_p (a_high
, min_r
) &&
263 double_int_cmp (a_low
, min_s
, 1) == -1))
274 /* Return the sign bit based on I_F_BITS. */
277 get_fixed_sign_bit (double_int a
, int i_f_bits
)
279 if (i_f_bits
< HOST_BITS_PER_WIDE_INT
)
280 return (a
.low
>> i_f_bits
) & 1;
282 return (a
.high
>> (i_f_bits
- HOST_BITS_PER_WIDE_INT
)) & 1;
285 /* Calculate F = A + (SUBTRACT_P ? -B : B).
286 If SAT_P, saturate the result to the max or the min.
287 Return true, if !SAT_P and overflow. */
290 do_fixed_add (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
,
291 const FIXED_VALUE_TYPE
*b
, bool subtract_p
, bool sat_p
)
293 bool overflow_p
= false;
298 /* This was a conditional expression but it triggered a bug in
301 temp
= double_int_neg (b
->data
);
305 unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
306 i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
308 f
->data
= double_int_add (a
->data
, temp
);
309 if (unsigned_p
) /* Unsigned type. */
311 if (subtract_p
) /* Unsigned subtraction. */
313 if (double_int_cmp (a
->data
, b
->data
, 1) == -1)
324 else /* Unsigned addition. */
326 f
->data
= double_int_ext (f
->data
, i_f_bits
, 1);
327 if (double_int_cmp (f
->data
, a
->data
, 1) == -1
328 || double_int_cmp (f
->data
, b
->data
, 1) == -1)
340 else /* Signed type. */
343 && (get_fixed_sign_bit (a
->data
, i_f_bits
)
344 == get_fixed_sign_bit (b
->data
, i_f_bits
))
345 && (get_fixed_sign_bit (a
->data
, i_f_bits
)
346 != get_fixed_sign_bit (f
->data
, i_f_bits
)))
348 && (get_fixed_sign_bit (a
->data
, i_f_bits
)
349 != get_fixed_sign_bit (b
->data
, i_f_bits
))
350 && (get_fixed_sign_bit (a
->data
, i_f_bits
)
351 != get_fixed_sign_bit (f
->data
, i_f_bits
))))
357 lshift_double (f
->data
.low
, f
->data
.high
, i_f_bits
,
358 2 * HOST_BITS_PER_WIDE_INT
,
359 &f
->data
.low
, &f
->data
.high
, 1);
360 if (get_fixed_sign_bit (a
->data
, i_f_bits
) == 0)
365 f
->data
= double_int_sub (f
->data
, one
);
372 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
376 /* Calculate F = A * B.
377 If SAT_P, saturate the result to the max or the min.
378 Return true, if !SAT_P and overflow. */
381 do_fixed_multiply (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
,
382 const FIXED_VALUE_TYPE
*b
, bool sat_p
)
384 bool overflow_p
= false;
385 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
386 int i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
388 if (GET_MODE_PRECISION (f
->mode
) <= HOST_BITS_PER_WIDE_INT
)
390 f
->data
= double_int_mul (a
->data
, b
->data
);
391 lshift_double (f
->data
.low
, f
->data
.high
,
392 (-GET_MODE_FBIT (f
->mode
)),
393 2 * HOST_BITS_PER_WIDE_INT
,
394 &f
->data
.low
, &f
->data
.high
, !unsigned_p
);
395 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
, sat_p
);
399 /* The result of multiplication expands to two double_int. */
400 double_int a_high
, a_low
, b_high
, b_low
;
401 double_int high_high
, high_low
, low_high
, low_low
;
402 double_int r
, s
, temp1
, temp2
;
405 /* Decompose a and b to four double_int. */
406 a_high
.low
= a
->data
.high
;
408 a_low
.low
= a
->data
.low
;
410 b_high
.low
= b
->data
.high
;
412 b_low
.low
= b
->data
.low
;
415 /* Perform four multiplications. */
416 low_low
= double_int_mul (a_low
, b_low
);
417 low_high
= double_int_mul (a_low
, b_high
);
418 high_low
= double_int_mul (a_high
, b_low
);
419 high_high
= double_int_mul (a_high
, b_high
);
421 /* Accumulate four results to {r, s}. */
422 temp1
.high
= high_low
.low
;
424 s
= double_int_add (low_low
, temp1
);
425 if (double_int_cmp (s
, low_low
, 1) == -1
426 || double_int_cmp (s
, temp1
, 1) == -1)
427 carry
++; /* Carry */
430 temp2
.high
= low_high
.low
;
432 s
= double_int_add (temp1
, temp2
);
433 if (double_int_cmp (s
, temp1
, 1) == -1
434 || double_int_cmp (s
, temp2
, 1) == -1)
435 carry
++; /* Carry */
437 temp1
.low
= high_low
.high
;
439 r
= double_int_add (high_high
, temp1
);
440 temp1
.low
= low_high
.high
;
442 r
= double_int_add (r
, temp1
);
445 r
= double_int_add (r
, temp1
);
447 /* We need to subtract b from r, if a < 0. */
448 if (!unsigned_p
&& a
->data
.high
< 0)
449 r
= double_int_sub (r
, b
->data
);
450 /* We need to subtract a from r, if b < 0. */
451 if (!unsigned_p
&& b
->data
.high
< 0)
452 r
= double_int_sub (r
, a
->data
);
454 /* Shift right the result by FBIT. */
455 if (GET_MODE_FBIT (f
->mode
) == 2 * HOST_BITS_PER_WIDE_INT
)
470 f
->data
.high
= s
.high
;
474 lshift_double (s
.low
, s
.high
,
475 (-GET_MODE_FBIT (f
->mode
)),
476 2 * HOST_BITS_PER_WIDE_INT
,
478 lshift_double (r
.low
, r
.high
,
479 (2 * HOST_BITS_PER_WIDE_INT
480 - GET_MODE_FBIT (f
->mode
)),
481 2 * HOST_BITS_PER_WIDE_INT
,
482 &f
->data
.low
, &f
->data
.high
, 0);
483 f
->data
.low
= f
->data
.low
| s
.low
;
484 f
->data
.high
= f
->data
.high
| s
.high
;
486 s
.high
= f
->data
.high
;
487 lshift_double (r
.low
, r
.high
,
488 (-GET_MODE_FBIT (f
->mode
)),
489 2 * HOST_BITS_PER_WIDE_INT
,
490 &r
.low
, &r
.high
, !unsigned_p
);
493 overflow_p
= fixed_saturate2 (f
->mode
, r
, s
, &f
->data
, sat_p
);
496 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
500 /* Calculate F = A / B.
501 If SAT_P, saturate the result to the max or the min.
502 Return true, if !SAT_P and overflow. */
505 do_fixed_divide (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
,
506 const FIXED_VALUE_TYPE
*b
, bool sat_p
)
508 bool overflow_p
= false;
509 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
510 int i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
512 if (GET_MODE_PRECISION (f
->mode
) <= HOST_BITS_PER_WIDE_INT
)
514 lshift_double (a
->data
.low
, a
->data
.high
,
515 GET_MODE_FBIT (f
->mode
),
516 2 * HOST_BITS_PER_WIDE_INT
,
517 &f
->data
.low
, &f
->data
.high
, !unsigned_p
);
518 f
->data
= double_int_div (f
->data
, b
->data
, unsigned_p
, TRUNC_DIV_EXPR
);
519 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
, sat_p
);
523 double_int pos_a
, pos_b
, r
, s
;
524 double_int quo_r
, quo_s
, mod
, temp
;
528 /* If a < 0, negate a. */
529 if (!unsigned_p
&& a
->data
.high
< 0)
531 pos_a
= double_int_neg (a
->data
);
537 /* If b < 0, negate b. */
538 if (!unsigned_p
&& b
->data
.high
< 0)
540 pos_b
= double_int_neg (b
->data
);
546 /* Left shift pos_a to {r, s} by FBIT. */
547 if (GET_MODE_FBIT (f
->mode
) == 2 * HOST_BITS_PER_WIDE_INT
)
555 lshift_double (pos_a
.low
, pos_a
.high
,
556 GET_MODE_FBIT (f
->mode
),
557 2 * HOST_BITS_PER_WIDE_INT
,
559 lshift_double (pos_a
.low
, pos_a
.high
,
560 - (2 * HOST_BITS_PER_WIDE_INT
561 - GET_MODE_FBIT (f
->mode
)),
562 2 * HOST_BITS_PER_WIDE_INT
,
566 /* Divide r by pos_b to quo_r. The remainder is in mod. */
567 div_and_round_double (TRUNC_DIV_EXPR
, 1, r
.low
, r
.high
, pos_b
.low
,
568 pos_b
.high
, &quo_r
.low
, &quo_r
.high
, &mod
.low
,
574 for (i
= 0; i
< 2 * HOST_BITS_PER_WIDE_INT
; i
++)
576 /* Record the leftmost bit of mod. */
577 int leftmost_mod
= (mod
.high
< 0);
579 /* Shift left mod by 1 bit. */
580 lshift_double (mod
.low
, mod
.high
, 1, 2 * HOST_BITS_PER_WIDE_INT
,
581 &mod
.low
, &mod
.high
, 0);
583 /* Test the leftmost bit of s to add to mod. */
587 /* Shift left quo_s by 1 bit. */
588 lshift_double (quo_s
.low
, quo_s
.high
, 1, 2 * HOST_BITS_PER_WIDE_INT
,
589 &quo_s
.low
, &quo_s
.high
, 0);
591 /* Try to calculate (mod - pos_b). */
592 temp
= double_int_sub (mod
, pos_b
);
594 if (leftmost_mod
== 1 || double_int_cmp (mod
, pos_b
, 1) != -1)
600 /* Shift left s by 1 bit. */
601 lshift_double (s
.low
, s
.high
, 1, 2 * HOST_BITS_PER_WIDE_INT
,
608 quo_s
= double_int_neg (quo_s
);
609 if (quo_s
.high
== 0 && quo_s
.low
== 0)
610 quo_r
= double_int_neg (quo_r
);
613 quo_r
.low
= ~quo_r
.low
;
614 quo_r
.high
= ~quo_r
.high
;
619 overflow_p
= fixed_saturate2 (f
->mode
, quo_r
, quo_s
, &f
->data
, sat_p
);
622 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
626 /* Calculate F = A << B if LEFT_P. Otherwise, F = A >> B.
627 If SAT_P, saturate the result to the max or the min.
628 Return true, if !SAT_P and overflow. */
631 do_fixed_shift (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
,
632 const FIXED_VALUE_TYPE
*b
, bool left_p
, bool sat_p
)
634 bool overflow_p
= false;
635 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
636 int i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
639 if (b
->data
.low
== 0)
645 if (GET_MODE_PRECISION (f
->mode
) <= HOST_BITS_PER_WIDE_INT
|| (!left_p
))
647 lshift_double (a
->data
.low
, a
->data
.high
,
648 left_p
? b
->data
.low
: (-b
->data
.low
),
649 2 * HOST_BITS_PER_WIDE_INT
,
650 &f
->data
.low
, &f
->data
.high
, !unsigned_p
);
651 if (left_p
) /* Only left shift saturates. */
652 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
, sat_p
);
654 else /* We need two double_int to store the left-shift result. */
656 double_int temp_high
, temp_low
;
657 if (b
->data
.low
== 2 * HOST_BITS_PER_WIDE_INT
)
665 lshift_double (a
->data
.low
, a
->data
.high
,
667 2 * HOST_BITS_PER_WIDE_INT
,
668 &temp_low
.low
, &temp_low
.high
, !unsigned_p
);
669 /* Logical shift right to temp_high. */
670 lshift_double (a
->data
.low
, a
->data
.high
,
671 b
->data
.low
- 2 * HOST_BITS_PER_WIDE_INT
,
672 2 * HOST_BITS_PER_WIDE_INT
,
673 &temp_high
.low
, &temp_high
.high
, 0);
675 if (!unsigned_p
&& a
->data
.high
< 0) /* Signed-extend temp_high. */
676 temp_high
= double_int_ext (temp_high
, b
->data
.low
, unsigned_p
);
678 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
, &f
->data
,
681 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
686 If SAT_P, saturate the result to the max or the min.
687 Return true, if !SAT_P and overflow. */
690 do_fixed_neg (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
, bool sat_p
)
692 bool overflow_p
= false;
693 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
694 int i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
696 f
->data
= double_int_neg (a
->data
);
697 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
699 if (unsigned_p
) /* Unsigned type. */
701 if (f
->data
.low
!= 0 || f
->data
.high
!= 0)
712 else /* Signed type. */
714 if (!(f
->data
.high
== 0 && f
->data
.low
== 0)
715 && f
->data
.high
== a
->data
.high
&& f
->data
.low
== a
->data
.low
)
719 /* Saturate to the maximum by subtracting f->data by one. */
722 f
->data
= double_int_ext (f
->data
, i_f_bits
, 1);
731 /* Perform the binary or unary operation described by CODE.
732 Note that OP0 and OP1 must have the same mode for binary operators.
733 For a unary operation, leave OP1 NULL.
734 Return true, if !SAT_P and overflow. */
737 fixed_arithmetic (FIXED_VALUE_TYPE
*f
, int icode
, const FIXED_VALUE_TYPE
*op0
,
738 const FIXED_VALUE_TYPE
*op1
, bool sat_p
)
743 return do_fixed_neg (f
, op0
, sat_p
);
747 gcc_assert (op0
->mode
== op1
->mode
);
748 return do_fixed_add (f
, op0
, op1
, false, sat_p
);
752 gcc_assert (op0
->mode
== op1
->mode
);
753 return do_fixed_add (f
, op0
, op1
, true, sat_p
);
757 gcc_assert (op0
->mode
== op1
->mode
);
758 return do_fixed_multiply (f
, op0
, op1
, sat_p
);
762 gcc_assert (op0
->mode
== op1
->mode
);
763 return do_fixed_divide (f
, op0
, op1
, sat_p
);
767 return do_fixed_shift (f
, op0
, op1
, true, sat_p
);
771 return do_fixed_shift (f
, op0
, op1
, false, sat_p
);
780 /* Compare fixed-point values by tree_code.
781 Note that OP0 and OP1 must have the same mode. */
784 fixed_compare (int icode
, const FIXED_VALUE_TYPE
*op0
,
785 const FIXED_VALUE_TYPE
*op1
)
787 enum tree_code code
= (enum tree_code
) icode
;
788 gcc_assert (op0
->mode
== op1
->mode
);
793 return !double_int_equal_p (op0
->data
, op1
->data
);
796 return double_int_equal_p (op0
->data
, op1
->data
);
799 return double_int_cmp (op0
->data
, op1
->data
,
800 UNSIGNED_FIXED_POINT_MODE_P (op0
->mode
)) == -1;
803 return double_int_cmp (op0
->data
, op1
->data
,
804 UNSIGNED_FIXED_POINT_MODE_P (op0
->mode
)) != 1;
807 return double_int_cmp (op0
->data
, op1
->data
,
808 UNSIGNED_FIXED_POINT_MODE_P (op0
->mode
)) == 1;
811 return double_int_cmp (op0
->data
, op1
->data
,
812 UNSIGNED_FIXED_POINT_MODE_P (op0
->mode
)) != -1;
819 /* Extend or truncate to a new mode.
820 If SAT_P, saturate the result to the max or the min.
821 Return true, if !SAT_P and overflow. */
824 fixed_convert (FIXED_VALUE_TYPE
*f
, enum machine_mode mode
,
825 const FIXED_VALUE_TYPE
*a
, bool sat_p
)
827 bool overflow_p
= false;
834 if (GET_MODE_FBIT (mode
) > GET_MODE_FBIT (a
->mode
))
836 /* Left shift a to temp_high, temp_low based on a->mode. */
837 double_int temp_high
, temp_low
;
838 int amount
= GET_MODE_FBIT (mode
) - GET_MODE_FBIT (a
->mode
);
839 lshift_double (a
->data
.low
, a
->data
.high
,
841 2 * HOST_BITS_PER_WIDE_INT
,
842 &temp_low
.low
, &temp_low
.high
,
843 SIGNED_FIXED_POINT_MODE_P (a
->mode
));
844 /* Logical shift right to temp_high. */
845 lshift_double (a
->data
.low
, a
->data
.high
,
846 amount
- 2 * HOST_BITS_PER_WIDE_INT
,
847 2 * HOST_BITS_PER_WIDE_INT
,
848 &temp_high
.low
, &temp_high
.high
, 0);
849 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
)
850 && a
->data
.high
< 0) /* Signed-extend temp_high. */
851 temp_high
= double_int_ext (temp_high
, amount
, 0);
854 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
) ==
855 SIGNED_FIXED_POINT_MODE_P (f
->mode
))
856 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
, &f
->data
,
860 /* Take care of the cases when converting between signed and
862 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
))
864 /* Signed -> Unsigned. */
865 if (a
->data
.high
< 0)
869 f
->data
.low
= 0; /* Set to zero. */
870 f
->data
.high
= 0; /* Set to zero. */
876 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
,
881 /* Unsigned -> Signed. */
882 if (temp_high
.high
< 0)
886 /* Set to maximum. */
887 f
->data
.low
= -1; /* Set to all ones. */
888 f
->data
.high
= -1; /* Set to all ones. */
889 f
->data
= double_int_ext (f
->data
,
890 GET_MODE_FBIT (f
->mode
)
891 + GET_MODE_IBIT (f
->mode
),
892 1); /* Clear the sign. */
898 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
,
905 /* Right shift a to temp based on a->mode. */
907 lshift_double (a
->data
.low
, a
->data
.high
,
908 GET_MODE_FBIT (mode
) - GET_MODE_FBIT (a
->mode
),
909 2 * HOST_BITS_PER_WIDE_INT
,
910 &temp
.low
, &temp
.high
,
911 SIGNED_FIXED_POINT_MODE_P (a
->mode
));
914 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
) ==
915 SIGNED_FIXED_POINT_MODE_P (f
->mode
))
916 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
, sat_p
);
919 /* Take care of the cases when converting between signed and
921 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
))
923 /* Signed -> Unsigned. */
924 if (a
->data
.high
< 0)
928 f
->data
.low
= 0; /* Set to zero. */
929 f
->data
.high
= 0; /* Set to zero. */
935 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
,
940 /* Unsigned -> Signed. */
945 /* Set to maximum. */
946 f
->data
.low
= -1; /* Set to all ones. */
947 f
->data
.high
= -1; /* Set to all ones. */
948 f
->data
= double_int_ext (f
->data
,
949 GET_MODE_FBIT (f
->mode
)
950 + GET_MODE_IBIT (f
->mode
),
951 1); /* Clear the sign. */
957 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
,
963 f
->data
= double_int_ext (f
->data
,
964 SIGNED_FIXED_POINT_MODE_P (f
->mode
)
965 + GET_MODE_FBIT (f
->mode
)
966 + GET_MODE_IBIT (f
->mode
),
967 UNSIGNED_FIXED_POINT_MODE_P (f
->mode
));
971 /* Convert to a new fixed-point mode from an integer.
972 If UNSIGNED_P, this integer is unsigned.
973 If SAT_P, saturate the result to the max or the min.
974 Return true, if !SAT_P and overflow. */
977 fixed_convert_from_int (FIXED_VALUE_TYPE
*f
, enum machine_mode mode
,
978 double_int a
, bool unsigned_p
, bool sat_p
)
980 bool overflow_p
= false;
981 /* Left shift a to temp_high, temp_low. */
982 double_int temp_high
, temp_low
;
983 int amount
= GET_MODE_FBIT (mode
);
984 if (amount
== 2 * HOST_BITS_PER_WIDE_INT
)
992 lshift_double (a
.low
, a
.high
,
994 2 * HOST_BITS_PER_WIDE_INT
,
995 &temp_low
.low
, &temp_low
.high
, 0);
997 /* Logical shift right to temp_high. */
998 lshift_double (a
.low
, a
.high
,
999 amount
- 2 * HOST_BITS_PER_WIDE_INT
,
1000 2 * HOST_BITS_PER_WIDE_INT
,
1001 &temp_high
.low
, &temp_high
.high
, 0);
1003 if (!unsigned_p
&& a
.high
< 0) /* Signed-extend temp_high. */
1004 temp_high
= double_int_ext (temp_high
, amount
, 0);
1009 if (unsigned_p
== UNSIGNED_FIXED_POINT_MODE_P (f
->mode
))
1010 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
, &f
->data
,
1014 /* Take care of the cases when converting between signed and unsigned. */
1017 /* Signed -> Unsigned. */
1022 f
->data
.low
= 0; /* Set to zero. */
1023 f
->data
.high
= 0; /* Set to zero. */
1029 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
,
1034 /* Unsigned -> Signed. */
1035 if (temp_high
.high
< 0)
1039 /* Set to maximum. */
1040 f
->data
.low
= -1; /* Set to all ones. */
1041 f
->data
.high
= -1; /* Set to all ones. */
1042 f
->data
= double_int_ext (f
->data
,
1043 GET_MODE_FBIT (f
->mode
)
1044 + GET_MODE_IBIT (f
->mode
),
1045 1); /* Clear the sign. */
1051 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
,
1055 f
->data
= double_int_ext (f
->data
,
1056 SIGNED_FIXED_POINT_MODE_P (f
->mode
)
1057 + GET_MODE_FBIT (f
->mode
)
1058 + GET_MODE_IBIT (f
->mode
),
1059 UNSIGNED_FIXED_POINT_MODE_P (f
->mode
));
1063 /* Convert to a new fixed-point mode from a real.
1064 If SAT_P, saturate the result to the max or the min.
1065 Return true, if !SAT_P and overflow. */
1068 fixed_convert_from_real (FIXED_VALUE_TYPE
*f
, enum machine_mode mode
,
1069 const REAL_VALUE_TYPE
*a
, bool sat_p
)
1071 bool overflow_p
= false;
1072 REAL_VALUE_TYPE real_value
, fixed_value
, base_value
;
1073 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (mode
);
1074 int i_f_bits
= GET_MODE_IBIT (mode
) + GET_MODE_FBIT (mode
);
1075 unsigned int fbit
= GET_MODE_FBIT (mode
);
1076 enum fixed_value_range_code temp
;
1080 real_2expN (&base_value
, fbit
, mode
);
1081 real_arithmetic (&fixed_value
, MULT_EXPR
, &real_value
, &base_value
);
1082 real_to_integer2 ((HOST_WIDE_INT
*)&f
->data
.low
, &f
->data
.high
, &fixed_value
);
1083 temp
= check_real_for_fixed_mode (&real_value
, mode
);
1084 if (temp
== FIXED_UNDERFLOW
) /* Minimum. */
1097 lshift_double (f
->data
.low
, f
->data
.high
, i_f_bits
,
1098 2 * HOST_BITS_PER_WIDE_INT
,
1099 &f
->data
.low
, &f
->data
.high
, 1);
1100 f
->data
= double_int_ext (f
->data
, 1 + i_f_bits
, 0);
1106 else if (temp
== FIXED_GT_MAX_EPS
|| temp
== FIXED_MAX_EPS
) /* Maximum. */
1112 f
->data
= double_int_ext (f
->data
, i_f_bits
, 1);
1117 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
1121 /* Convert to a new real mode from a fixed-point. */
1124 real_convert_from_fixed (REAL_VALUE_TYPE
*r
, enum machine_mode mode
,
1125 const FIXED_VALUE_TYPE
*f
)
1127 REAL_VALUE_TYPE base_value
, fixed_value
, real_value
;
1129 real_2expN (&base_value
, GET_MODE_FBIT (f
->mode
), f
->mode
);
1130 real_from_integer (&fixed_value
, VOIDmode
, f
->data
.low
, f
->data
.high
,
1131 UNSIGNED_FIXED_POINT_MODE_P (f
->mode
));
1132 real_arithmetic (&real_value
, RDIV_EXPR
, &fixed_value
, &base_value
);
1133 real_convert (r
, mode
, &real_value
);
1136 /* Determine whether a fixed-point value F is negative. */
1139 fixed_isneg (const FIXED_VALUE_TYPE
*f
)
1141 if (SIGNED_FIXED_POINT_MODE_P (f
->mode
))
1143 int i_f_bits
= GET_MODE_IBIT (f
->mode
) + GET_MODE_FBIT (f
->mode
);
1144 int sign_bit
= get_fixed_sign_bit (f
->data
, i_f_bits
);