1 /* Fixed-point arithmetic support.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010 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"
27 /* Compare two fixed objects for bitwise identity. */
30 fixed_identical (const FIXED_VALUE_TYPE
*a
, const FIXED_VALUE_TYPE
*b
)
32 return (a
->mode
== b
->mode
33 && a
->data
.high
== b
->data
.high
34 && a
->data
.low
== b
->data
.low
);
37 /* Calculate a hash value. */
40 fixed_hash (const FIXED_VALUE_TYPE
*f
)
42 return (unsigned int) (f
->data
.low
^ f
->data
.high
);
45 /* Define the enum code for the range of the fixed-point value. */
46 enum fixed_value_range_code
{
47 FIXED_OK
, /* The value is within the range. */
48 FIXED_UNDERFLOW
, /* The value is less than the minimum. */
49 FIXED_GT_MAX_EPS
, /* The value is greater than the maximum, but not equal
50 to the maximum plus the epsilon. */
51 FIXED_MAX_EPS
/* The value equals the maximum plus the epsilon. */
54 /* Check REAL_VALUE against the range of the fixed-point mode.
55 Return FIXED_OK, if it is within the range.
56 FIXED_UNDERFLOW, if it is less than the minimum.
57 FIXED_GT_MAX_EPS, if it is greater than the maximum, but not equal to
58 the maximum plus the epsilon.
59 FIXED_MAX_EPS, if it is equal to the maximum plus the epsilon. */
61 static enum fixed_value_range_code
62 check_real_for_fixed_mode (REAL_VALUE_TYPE
*real_value
, enum machine_mode mode
)
64 REAL_VALUE_TYPE max_value
, min_value
, epsilon_value
;
66 real_2expN (&max_value
, GET_MODE_IBIT (mode
), mode
);
67 real_2expN (&epsilon_value
, -GET_MODE_FBIT (mode
), mode
);
69 if (SIGNED_FIXED_POINT_MODE_P (mode
))
70 min_value
= real_value_negate (&max_value
);
72 real_from_string (&min_value
, "0.0");
74 if (real_compare (LT_EXPR
, real_value
, &min_value
))
75 return FIXED_UNDERFLOW
;
76 if (real_compare (EQ_EXPR
, real_value
, &max_value
))
78 real_arithmetic (&max_value
, MINUS_EXPR
, &max_value
, &epsilon_value
);
79 if (real_compare (GT_EXPR
, real_value
, &max_value
))
80 return FIXED_GT_MAX_EPS
;
84 /* Initialize from a decimal or hexadecimal string. */
87 fixed_from_string (FIXED_VALUE_TYPE
*f
, const char *str
, enum machine_mode mode
)
89 REAL_VALUE_TYPE real_value
, fixed_value
, base_value
;
91 enum fixed_value_range_code temp
;
94 fbit
= GET_MODE_FBIT (mode
);
96 real_from_string (&real_value
, str
);
97 temp
= check_real_for_fixed_mode (&real_value
, f
->mode
);
98 /* We don't want to warn the case when the _Fract value is 1.0. */
99 if (temp
== FIXED_UNDERFLOW
100 || temp
== FIXED_GT_MAX_EPS
101 || (temp
== FIXED_MAX_EPS
&& ALL_ACCUM_MODE_P (f
->mode
)))
102 warning (OPT_Woverflow
,
103 "large fixed-point constant implicitly truncated to fixed-point type");
104 real_2expN (&base_value
, fbit
, mode
);
105 real_arithmetic (&fixed_value
, MULT_EXPR
, &real_value
, &base_value
);
106 real_to_integer2 ((HOST_WIDE_INT
*)&f
->data
.low
, &f
->data
.high
,
109 if (temp
== FIXED_MAX_EPS
&& ALL_FRACT_MODE_P (f
->mode
))
111 /* From the spec, we need to evaluate 1 to the maximal value. */
114 f
->data
= double_int_ext (f
->data
,
115 GET_MODE_FBIT (f
->mode
)
116 + GET_MODE_IBIT (f
->mode
), 1);
119 f
->data
= double_int_ext (f
->data
,
120 SIGNED_FIXED_POINT_MODE_P (f
->mode
)
121 + GET_MODE_FBIT (f
->mode
)
122 + GET_MODE_IBIT (f
->mode
),
123 UNSIGNED_FIXED_POINT_MODE_P (f
->mode
));
126 /* Render F as a decimal floating point constant. */
129 fixed_to_decimal (char *str
, const FIXED_VALUE_TYPE
*f_orig
,
132 REAL_VALUE_TYPE real_value
, base_value
, fixed_value
;
134 real_2expN (&base_value
, GET_MODE_FBIT (f_orig
->mode
), f_orig
->mode
);
135 real_from_integer (&real_value
, VOIDmode
, f_orig
->data
.low
, f_orig
->data
.high
,
136 UNSIGNED_FIXED_POINT_MODE_P (f_orig
->mode
));
137 real_arithmetic (&fixed_value
, RDIV_EXPR
, &real_value
, &base_value
);
138 real_to_decimal (str
, &fixed_value
, buf_size
, 0, 1);
141 /* If SAT_P, saturate A to the maximum or the minimum, and save to *F based on
142 the machine mode MODE.
143 Do not modify *F otherwise.
144 This function assumes the width of double_int is greater than the width
145 of the fixed-point value (the sum of a possible sign bit, possible ibits,
147 Return true, if !SAT_P and overflow. */
150 fixed_saturate1 (enum machine_mode mode
, double_int a
, double_int
*f
,
153 bool overflow_p
= false;
154 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (mode
);
155 int i_f_bits
= GET_MODE_IBIT (mode
) + GET_MODE_FBIT (mode
);
157 if (unsigned_p
) /* Unsigned type. */
162 max
= double_int_ext (max
, i_f_bits
, 1);
163 if (double_int_cmp (a
, max
, 1) == 1)
171 else /* Signed type. */
176 max
= double_int_ext (max
, i_f_bits
, 1);
179 lshift_double (min
.low
, min
.high
, i_f_bits
,
180 2 * HOST_BITS_PER_WIDE_INT
,
181 &min
.low
, &min
.high
, 1);
182 min
= double_int_ext (min
, 1 + i_f_bits
, 0);
183 if (double_int_cmp (a
, max
, 0) == 1)
190 else if (double_int_cmp (a
, min
, 0) == -1)
201 /* If SAT_P, saturate {A_HIGH, A_LOW} to the maximum or the minimum, and
202 save to *F based on the machine mode MODE.
203 Do not modify *F otherwise.
204 This function assumes the width of two double_int is greater than the width
205 of the fixed-point value (the sum of a possible sign bit, possible ibits,
207 Return true, if !SAT_P and overflow. */
210 fixed_saturate2 (enum machine_mode mode
, double_int a_high
, double_int a_low
,
211 double_int
*f
, bool sat_p
)
213 bool overflow_p
= false;
214 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (mode
);
215 int i_f_bits
= GET_MODE_IBIT (mode
) + GET_MODE_FBIT (mode
);
217 if (unsigned_p
) /* Unsigned type. */
219 double_int max_r
, max_s
;
224 max_s
= double_int_ext (max_s
, i_f_bits
, 1);
225 if (double_int_cmp (a_high
, max_r
, 1) == 1
226 || (double_int_equal_p (a_high
, max_r
) &&
227 double_int_cmp (a_low
, max_s
, 1) == 1))
235 else /* Signed type. */
237 double_int max_r
, max_s
, min_r
, min_s
;
242 max_s
= double_int_ext (max_s
, i_f_bits
, 1);
247 lshift_double (min_s
.low
, min_s
.high
, i_f_bits
,
248 2 * HOST_BITS_PER_WIDE_INT
,
249 &min_s
.low
, &min_s
.high
, 1);
250 min_s
= double_int_ext (min_s
, 1 + i_f_bits
, 0);
251 if (double_int_cmp (a_high
, max_r
, 0) == 1
252 || (double_int_equal_p (a_high
, max_r
) &&
253 double_int_cmp (a_low
, max_s
, 1) == 1))
260 else if (double_int_cmp (a_high
, min_r
, 0) == -1
261 || (double_int_equal_p (a_high
, min_r
) &&
262 double_int_cmp (a_low
, min_s
, 1) == -1))
273 /* Return the sign bit based on I_F_BITS. */
276 get_fixed_sign_bit (double_int a
, int i_f_bits
)
278 if (i_f_bits
< HOST_BITS_PER_WIDE_INT
)
279 return (a
.low
>> i_f_bits
) & 1;
281 return (a
.high
>> (i_f_bits
- HOST_BITS_PER_WIDE_INT
)) & 1;
284 /* Calculate F = A + (SUBTRACT_P ? -B : B).
285 If SAT_P, saturate the result to the max or the min.
286 Return true, if !SAT_P and overflow. */
289 do_fixed_add (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
,
290 const FIXED_VALUE_TYPE
*b
, bool subtract_p
, bool sat_p
)
292 bool overflow_p
= false;
297 /* This was a conditional expression but it triggered a bug in
300 temp
= double_int_neg (b
->data
);
304 unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
305 i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
307 f
->data
= double_int_add (a
->data
, temp
);
308 if (unsigned_p
) /* Unsigned type. */
310 if (subtract_p
) /* Unsigned subtraction. */
312 if (double_int_cmp (a
->data
, b
->data
, 1) == -1)
323 else /* Unsigned addition. */
325 f
->data
= double_int_ext (f
->data
, i_f_bits
, 1);
326 if (double_int_cmp (f
->data
, a
->data
, 1) == -1
327 || double_int_cmp (f
->data
, b
->data
, 1) == -1)
339 else /* Signed type. */
342 && (get_fixed_sign_bit (a
->data
, i_f_bits
)
343 == get_fixed_sign_bit (b
->data
, i_f_bits
))
344 && (get_fixed_sign_bit (a
->data
, i_f_bits
)
345 != get_fixed_sign_bit (f
->data
, i_f_bits
)))
347 && (get_fixed_sign_bit (a
->data
, i_f_bits
)
348 != get_fixed_sign_bit (b
->data
, i_f_bits
))
349 && (get_fixed_sign_bit (a
->data
, i_f_bits
)
350 != get_fixed_sign_bit (f
->data
, i_f_bits
))))
356 lshift_double (f
->data
.low
, f
->data
.high
, i_f_bits
,
357 2 * HOST_BITS_PER_WIDE_INT
,
358 &f
->data
.low
, &f
->data
.high
, 1);
359 if (get_fixed_sign_bit (a
->data
, i_f_bits
) == 0)
364 f
->data
= double_int_sub (f
->data
, one
);
371 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
375 /* Calculate F = A * B.
376 If SAT_P, saturate the result to the max or the min.
377 Return true, if !SAT_P and overflow. */
380 do_fixed_multiply (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
,
381 const FIXED_VALUE_TYPE
*b
, bool sat_p
)
383 bool overflow_p
= false;
384 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
385 int i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
387 if (GET_MODE_PRECISION (f
->mode
) <= HOST_BITS_PER_WIDE_INT
)
389 f
->data
= double_int_mul (a
->data
, b
->data
);
390 lshift_double (f
->data
.low
, f
->data
.high
,
391 (-GET_MODE_FBIT (f
->mode
)),
392 2 * HOST_BITS_PER_WIDE_INT
,
393 &f
->data
.low
, &f
->data
.high
, !unsigned_p
);
394 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
, sat_p
);
398 /* The result of multiplication expands to two double_int. */
399 double_int a_high
, a_low
, b_high
, b_low
;
400 double_int high_high
, high_low
, low_high
, low_low
;
401 double_int r
, s
, temp1
, temp2
;
404 /* Decompose a and b to four double_int. */
405 a_high
.low
= a
->data
.high
;
407 a_low
.low
= a
->data
.low
;
409 b_high
.low
= b
->data
.high
;
411 b_low
.low
= b
->data
.low
;
414 /* Perform four multiplications. */
415 low_low
= double_int_mul (a_low
, b_low
);
416 low_high
= double_int_mul (a_low
, b_high
);
417 high_low
= double_int_mul (a_high
, b_low
);
418 high_high
= double_int_mul (a_high
, b_high
);
420 /* Accumulate four results to {r, s}. */
421 temp1
.high
= high_low
.low
;
423 s
= double_int_add (low_low
, temp1
);
424 if (double_int_cmp (s
, low_low
, 1) == -1
425 || double_int_cmp (s
, temp1
, 1) == -1)
426 carry
++; /* Carry */
429 temp2
.high
= low_high
.low
;
431 s
= double_int_add (temp1
, temp2
);
432 if (double_int_cmp (s
, temp1
, 1) == -1
433 || double_int_cmp (s
, temp2
, 1) == -1)
434 carry
++; /* Carry */
436 temp1
.low
= high_low
.high
;
438 r
= double_int_add (high_high
, temp1
);
439 temp1
.low
= low_high
.high
;
441 r
= double_int_add (r
, temp1
);
444 r
= double_int_add (r
, temp1
);
446 /* We need to subtract b from r, if a < 0. */
447 if (!unsigned_p
&& a
->data
.high
< 0)
448 r
= double_int_sub (r
, b
->data
);
449 /* We need to subtract a from r, if b < 0. */
450 if (!unsigned_p
&& b
->data
.high
< 0)
451 r
= double_int_sub (r
, a
->data
);
453 /* Shift right the result by FBIT. */
454 if (GET_MODE_FBIT (f
->mode
) == 2 * HOST_BITS_PER_WIDE_INT
)
469 f
->data
.high
= s
.high
;
473 lshift_double (s
.low
, s
.high
,
474 (-GET_MODE_FBIT (f
->mode
)),
475 2 * HOST_BITS_PER_WIDE_INT
,
477 lshift_double (r
.low
, r
.high
,
478 (2 * HOST_BITS_PER_WIDE_INT
479 - GET_MODE_FBIT (f
->mode
)),
480 2 * HOST_BITS_PER_WIDE_INT
,
481 &f
->data
.low
, &f
->data
.high
, 0);
482 f
->data
.low
= f
->data
.low
| s
.low
;
483 f
->data
.high
= f
->data
.high
| s
.high
;
485 s
.high
= f
->data
.high
;
486 lshift_double (r
.low
, r
.high
,
487 (-GET_MODE_FBIT (f
->mode
)),
488 2 * HOST_BITS_PER_WIDE_INT
,
489 &r
.low
, &r
.high
, !unsigned_p
);
492 overflow_p
= fixed_saturate2 (f
->mode
, r
, s
, &f
->data
, sat_p
);
495 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
499 /* Calculate F = A / B.
500 If SAT_P, saturate the result to the max or the min.
501 Return true, if !SAT_P and overflow. */
504 do_fixed_divide (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
,
505 const FIXED_VALUE_TYPE
*b
, bool sat_p
)
507 bool overflow_p
= false;
508 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
509 int i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
511 if (GET_MODE_PRECISION (f
->mode
) <= HOST_BITS_PER_WIDE_INT
)
513 lshift_double (a
->data
.low
, a
->data
.high
,
514 GET_MODE_FBIT (f
->mode
),
515 2 * HOST_BITS_PER_WIDE_INT
,
516 &f
->data
.low
, &f
->data
.high
, !unsigned_p
);
517 f
->data
= double_int_div (f
->data
, b
->data
, unsigned_p
, TRUNC_DIV_EXPR
);
518 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
, sat_p
);
522 double_int pos_a
, pos_b
, r
, s
;
523 double_int quo_r
, quo_s
, mod
, temp
;
527 /* If a < 0, negate a. */
528 if (!unsigned_p
&& a
->data
.high
< 0)
530 pos_a
= double_int_neg (a
->data
);
536 /* If b < 0, negate b. */
537 if (!unsigned_p
&& b
->data
.high
< 0)
539 pos_b
= double_int_neg (b
->data
);
545 /* Left shift pos_a to {r, s} by FBIT. */
546 if (GET_MODE_FBIT (f
->mode
) == 2 * HOST_BITS_PER_WIDE_INT
)
554 lshift_double (pos_a
.low
, pos_a
.high
,
555 GET_MODE_FBIT (f
->mode
),
556 2 * HOST_BITS_PER_WIDE_INT
,
558 lshift_double (pos_a
.low
, pos_a
.high
,
559 - (2 * HOST_BITS_PER_WIDE_INT
560 - GET_MODE_FBIT (f
->mode
)),
561 2 * HOST_BITS_PER_WIDE_INT
,
565 /* Divide r by pos_b to quo_r. The remainder is in mod. */
566 div_and_round_double (TRUNC_DIV_EXPR
, 1, r
.low
, r
.high
, pos_b
.low
,
567 pos_b
.high
, &quo_r
.low
, &quo_r
.high
, &mod
.low
,
573 for (i
= 0; i
< 2 * HOST_BITS_PER_WIDE_INT
; i
++)
575 /* Record the leftmost bit of mod. */
576 int leftmost_mod
= (mod
.high
< 0);
578 /* Shift left mod by 1 bit. */
579 lshift_double (mod
.low
, mod
.high
, 1, 2 * HOST_BITS_PER_WIDE_INT
,
580 &mod
.low
, &mod
.high
, 0);
582 /* Test the leftmost bit of s to add to mod. */
586 /* Shift left quo_s by 1 bit. */
587 lshift_double (quo_s
.low
, quo_s
.high
, 1, 2 * HOST_BITS_PER_WIDE_INT
,
588 &quo_s
.low
, &quo_s
.high
, 0);
590 /* Try to calculate (mod - pos_b). */
591 temp
= double_int_sub (mod
, pos_b
);
593 if (leftmost_mod
== 1 || double_int_cmp (mod
, pos_b
, 1) != -1)
599 /* Shift left s by 1 bit. */
600 lshift_double (s
.low
, s
.high
, 1, 2 * HOST_BITS_PER_WIDE_INT
,
607 quo_s
= double_int_neg (quo_s
);
608 if (quo_s
.high
== 0 && quo_s
.low
== 0)
609 quo_r
= double_int_neg (quo_r
);
612 quo_r
.low
= ~quo_r
.low
;
613 quo_r
.high
= ~quo_r
.high
;
618 overflow_p
= fixed_saturate2 (f
->mode
, quo_r
, quo_s
, &f
->data
, sat_p
);
621 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
625 /* Calculate F = A << B if LEFT_P. Otherwise, F = A >> B.
626 If SAT_P, saturate the result to the max or the min.
627 Return true, if !SAT_P and overflow. */
630 do_fixed_shift (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
,
631 const FIXED_VALUE_TYPE
*b
, bool left_p
, bool sat_p
)
633 bool overflow_p
= false;
634 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
635 int i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
638 if (b
->data
.low
== 0)
644 if (GET_MODE_PRECISION (f
->mode
) <= HOST_BITS_PER_WIDE_INT
|| (!left_p
))
646 lshift_double (a
->data
.low
, a
->data
.high
,
647 left_p
? b
->data
.low
: (-b
->data
.low
),
648 2 * HOST_BITS_PER_WIDE_INT
,
649 &f
->data
.low
, &f
->data
.high
, !unsigned_p
);
650 if (left_p
) /* Only left shift saturates. */
651 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
, sat_p
);
653 else /* We need two double_int to store the left-shift result. */
655 double_int temp_high
, temp_low
;
656 if (b
->data
.low
== 2 * HOST_BITS_PER_WIDE_INT
)
664 lshift_double (a
->data
.low
, a
->data
.high
,
666 2 * HOST_BITS_PER_WIDE_INT
,
667 &temp_low
.low
, &temp_low
.high
, !unsigned_p
);
668 /* Logical shift right to temp_high. */
669 lshift_double (a
->data
.low
, a
->data
.high
,
670 b
->data
.low
- 2 * HOST_BITS_PER_WIDE_INT
,
671 2 * HOST_BITS_PER_WIDE_INT
,
672 &temp_high
.low
, &temp_high
.high
, 0);
674 if (!unsigned_p
&& a
->data
.high
< 0) /* Signed-extend temp_high. */
675 temp_high
= double_int_ext (temp_high
, b
->data
.low
, unsigned_p
);
677 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
, &f
->data
,
680 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
685 If SAT_P, saturate the result to the max or the min.
686 Return true, if !SAT_P and overflow. */
689 do_fixed_neg (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
, bool sat_p
)
691 bool overflow_p
= false;
692 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
693 int i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
695 f
->data
= double_int_neg (a
->data
);
696 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
698 if (unsigned_p
) /* Unsigned type. */
700 if (f
->data
.low
!= 0 || f
->data
.high
!= 0)
711 else /* Signed type. */
713 if (!(f
->data
.high
== 0 && f
->data
.low
== 0)
714 && f
->data
.high
== a
->data
.high
&& f
->data
.low
== a
->data
.low
)
718 /* Saturate to the maximum by subtracting f->data by one. */
721 f
->data
= double_int_ext (f
->data
, i_f_bits
, 1);
730 /* Perform the binary or unary operation described by CODE.
731 Note that OP0 and OP1 must have the same mode for binary operators.
732 For a unary operation, leave OP1 NULL.
733 Return true, if !SAT_P and overflow. */
736 fixed_arithmetic (FIXED_VALUE_TYPE
*f
, int icode
, const FIXED_VALUE_TYPE
*op0
,
737 const FIXED_VALUE_TYPE
*op1
, bool sat_p
)
742 return do_fixed_neg (f
, op0
, sat_p
);
746 gcc_assert (op0
->mode
== op1
->mode
);
747 return do_fixed_add (f
, op0
, op1
, false, sat_p
);
751 gcc_assert (op0
->mode
== op1
->mode
);
752 return do_fixed_add (f
, op0
, op1
, true, sat_p
);
756 gcc_assert (op0
->mode
== op1
->mode
);
757 return do_fixed_multiply (f
, op0
, op1
, sat_p
);
761 gcc_assert (op0
->mode
== op1
->mode
);
762 return do_fixed_divide (f
, op0
, op1
, sat_p
);
766 return do_fixed_shift (f
, op0
, op1
, true, sat_p
);
770 return do_fixed_shift (f
, op0
, op1
, false, sat_p
);
779 /* Compare fixed-point values by tree_code.
780 Note that OP0 and OP1 must have the same mode. */
783 fixed_compare (int icode
, const FIXED_VALUE_TYPE
*op0
,
784 const FIXED_VALUE_TYPE
*op1
)
786 enum tree_code code
= (enum tree_code
) icode
;
787 gcc_assert (op0
->mode
== op1
->mode
);
792 return !double_int_equal_p (op0
->data
, op1
->data
);
795 return double_int_equal_p (op0
->data
, op1
->data
);
798 return double_int_cmp (op0
->data
, op1
->data
,
799 UNSIGNED_FIXED_POINT_MODE_P (op0
->mode
)) == -1;
802 return double_int_cmp (op0
->data
, op1
->data
,
803 UNSIGNED_FIXED_POINT_MODE_P (op0
->mode
)) != 1;
806 return double_int_cmp (op0
->data
, op1
->data
,
807 UNSIGNED_FIXED_POINT_MODE_P (op0
->mode
)) == 1;
810 return double_int_cmp (op0
->data
, op1
->data
,
811 UNSIGNED_FIXED_POINT_MODE_P (op0
->mode
)) != -1;
818 /* Extend or truncate to a new mode.
819 If SAT_P, saturate the result to the max or the min.
820 Return true, if !SAT_P and overflow. */
823 fixed_convert (FIXED_VALUE_TYPE
*f
, enum machine_mode mode
,
824 const FIXED_VALUE_TYPE
*a
, bool sat_p
)
826 bool overflow_p
= false;
833 if (GET_MODE_FBIT (mode
) > GET_MODE_FBIT (a
->mode
))
835 /* Left shift a to temp_high, temp_low based on a->mode. */
836 double_int temp_high
, temp_low
;
837 int amount
= GET_MODE_FBIT (mode
) - GET_MODE_FBIT (a
->mode
);
838 lshift_double (a
->data
.low
, a
->data
.high
,
840 2 * HOST_BITS_PER_WIDE_INT
,
841 &temp_low
.low
, &temp_low
.high
,
842 SIGNED_FIXED_POINT_MODE_P (a
->mode
));
843 /* Logical shift right to temp_high. */
844 lshift_double (a
->data
.low
, a
->data
.high
,
845 amount
- 2 * HOST_BITS_PER_WIDE_INT
,
846 2 * HOST_BITS_PER_WIDE_INT
,
847 &temp_high
.low
, &temp_high
.high
, 0);
848 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
)
849 && a
->data
.high
< 0) /* Signed-extend temp_high. */
850 temp_high
= double_int_ext (temp_high
, amount
, 0);
853 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
) ==
854 SIGNED_FIXED_POINT_MODE_P (f
->mode
))
855 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
, &f
->data
,
859 /* Take care of the cases when converting between signed and
861 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
))
863 /* Signed -> Unsigned. */
864 if (a
->data
.high
< 0)
868 f
->data
.low
= 0; /* Set to zero. */
869 f
->data
.high
= 0; /* Set to zero. */
875 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
,
880 /* Unsigned -> Signed. */
881 if (temp_high
.high
< 0)
885 /* Set to maximum. */
886 f
->data
.low
= -1; /* Set to all ones. */
887 f
->data
.high
= -1; /* Set to all ones. */
888 f
->data
= double_int_ext (f
->data
,
889 GET_MODE_FBIT (f
->mode
)
890 + GET_MODE_IBIT (f
->mode
),
891 1); /* Clear the sign. */
897 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
,
904 /* Right shift a to temp based on a->mode. */
906 lshift_double (a
->data
.low
, a
->data
.high
,
907 GET_MODE_FBIT (mode
) - GET_MODE_FBIT (a
->mode
),
908 2 * HOST_BITS_PER_WIDE_INT
,
909 &temp
.low
, &temp
.high
,
910 SIGNED_FIXED_POINT_MODE_P (a
->mode
));
913 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
) ==
914 SIGNED_FIXED_POINT_MODE_P (f
->mode
))
915 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
, sat_p
);
918 /* Take care of the cases when converting between signed and
920 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
))
922 /* Signed -> Unsigned. */
923 if (a
->data
.high
< 0)
927 f
->data
.low
= 0; /* Set to zero. */
928 f
->data
.high
= 0; /* Set to zero. */
934 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
,
939 /* Unsigned -> Signed. */
944 /* Set to maximum. */
945 f
->data
.low
= -1; /* Set to all ones. */
946 f
->data
.high
= -1; /* Set to all ones. */
947 f
->data
= double_int_ext (f
->data
,
948 GET_MODE_FBIT (f
->mode
)
949 + GET_MODE_IBIT (f
->mode
),
950 1); /* Clear the sign. */
956 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
,
962 f
->data
= double_int_ext (f
->data
,
963 SIGNED_FIXED_POINT_MODE_P (f
->mode
)
964 + GET_MODE_FBIT (f
->mode
)
965 + GET_MODE_IBIT (f
->mode
),
966 UNSIGNED_FIXED_POINT_MODE_P (f
->mode
));
970 /* Convert to a new fixed-point mode from an integer.
971 If UNSIGNED_P, this integer is unsigned.
972 If SAT_P, saturate the result to the max or the min.
973 Return true, if !SAT_P and overflow. */
976 fixed_convert_from_int (FIXED_VALUE_TYPE
*f
, enum machine_mode mode
,
977 double_int a
, bool unsigned_p
, bool sat_p
)
979 bool overflow_p
= false;
980 /* Left shift a to temp_high, temp_low. */
981 double_int temp_high
, temp_low
;
982 int amount
= GET_MODE_FBIT (mode
);
983 if (amount
== 2 * HOST_BITS_PER_WIDE_INT
)
991 lshift_double (a
.low
, a
.high
,
993 2 * HOST_BITS_PER_WIDE_INT
,
994 &temp_low
.low
, &temp_low
.high
, 0);
996 /* Logical shift right to temp_high. */
997 lshift_double (a
.low
, a
.high
,
998 amount
- 2 * HOST_BITS_PER_WIDE_INT
,
999 2 * HOST_BITS_PER_WIDE_INT
,
1000 &temp_high
.low
, &temp_high
.high
, 0);
1002 if (!unsigned_p
&& a
.high
< 0) /* Signed-extend temp_high. */
1003 temp_high
= double_int_ext (temp_high
, amount
, 0);
1008 if (unsigned_p
== UNSIGNED_FIXED_POINT_MODE_P (f
->mode
))
1009 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
, &f
->data
,
1013 /* Take care of the cases when converting between signed and unsigned. */
1016 /* Signed -> Unsigned. */
1021 f
->data
.low
= 0; /* Set to zero. */
1022 f
->data
.high
= 0; /* Set to zero. */
1028 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
,
1033 /* Unsigned -> Signed. */
1034 if (temp_high
.high
< 0)
1038 /* Set to maximum. */
1039 f
->data
.low
= -1; /* Set to all ones. */
1040 f
->data
.high
= -1; /* Set to all ones. */
1041 f
->data
= double_int_ext (f
->data
,
1042 GET_MODE_FBIT (f
->mode
)
1043 + GET_MODE_IBIT (f
->mode
),
1044 1); /* Clear the sign. */
1050 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
,
1054 f
->data
= double_int_ext (f
->data
,
1055 SIGNED_FIXED_POINT_MODE_P (f
->mode
)
1056 + GET_MODE_FBIT (f
->mode
)
1057 + GET_MODE_IBIT (f
->mode
),
1058 UNSIGNED_FIXED_POINT_MODE_P (f
->mode
));
1062 /* Convert to a new fixed-point mode from a real.
1063 If SAT_P, saturate the result to the max or the min.
1064 Return true, if !SAT_P and overflow. */
1067 fixed_convert_from_real (FIXED_VALUE_TYPE
*f
, enum machine_mode mode
,
1068 const REAL_VALUE_TYPE
*a
, bool sat_p
)
1070 bool overflow_p
= false;
1071 REAL_VALUE_TYPE real_value
, fixed_value
, base_value
;
1072 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (mode
);
1073 int i_f_bits
= GET_MODE_IBIT (mode
) + GET_MODE_FBIT (mode
);
1074 unsigned int fbit
= GET_MODE_FBIT (mode
);
1075 enum fixed_value_range_code temp
;
1079 real_2expN (&base_value
, fbit
, mode
);
1080 real_arithmetic (&fixed_value
, MULT_EXPR
, &real_value
, &base_value
);
1081 real_to_integer2 ((HOST_WIDE_INT
*)&f
->data
.low
, &f
->data
.high
, &fixed_value
);
1082 temp
= check_real_for_fixed_mode (&real_value
, mode
);
1083 if (temp
== FIXED_UNDERFLOW
) /* Minimum. */
1096 lshift_double (f
->data
.low
, f
->data
.high
, i_f_bits
,
1097 2 * HOST_BITS_PER_WIDE_INT
,
1098 &f
->data
.low
, &f
->data
.high
, 1);
1099 f
->data
= double_int_ext (f
->data
, 1 + i_f_bits
, 0);
1105 else if (temp
== FIXED_GT_MAX_EPS
|| temp
== FIXED_MAX_EPS
) /* Maximum. */
1111 f
->data
= double_int_ext (f
->data
, i_f_bits
, 1);
1116 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
1120 /* Convert to a new real mode from a fixed-point. */
1123 real_convert_from_fixed (REAL_VALUE_TYPE
*r
, enum machine_mode mode
,
1124 const FIXED_VALUE_TYPE
*f
)
1126 REAL_VALUE_TYPE base_value
, fixed_value
, real_value
;
1128 real_2expN (&base_value
, GET_MODE_FBIT (f
->mode
), f
->mode
);
1129 real_from_integer (&fixed_value
, VOIDmode
, f
->data
.low
, f
->data
.high
,
1130 UNSIGNED_FIXED_POINT_MODE_P (f
->mode
));
1131 real_arithmetic (&real_value
, RDIV_EXPR
, &fixed_value
, &base_value
);
1132 real_convert (r
, mode
, &real_value
);
1135 /* Determine whether a fixed-point value F is negative. */
1138 fixed_isneg (const FIXED_VALUE_TYPE
*f
)
1140 if (SIGNED_FIXED_POINT_MODE_P (f
->mode
))
1142 int i_f_bits
= GET_MODE_IBIT (f
->mode
) + GET_MODE_FBIT (f
->mode
);
1143 int sign_bit
= get_fixed_sign_bit (f
->data
, i_f_bits
);