1 /* Fixed-point arithmetic support.
2 Copyright (C) 2006, 2007 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 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"
26 #include "fixed-value.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;
294 double_int temp
= subtract_p
? double_int_neg (b
->data
) : b
->data
;
295 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
296 int i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
298 f
->data
= double_int_add (a
->data
, temp
);
299 if (unsigned_p
) /* Unsigned type. */
301 if (subtract_p
) /* Unsigned subtraction. */
303 if (double_int_cmp (a
->data
, b
->data
, 1) == -1)
314 else /* Unsigned addition. */
316 f
->data
= double_int_ext (f
->data
, i_f_bits
, 1);
317 if (double_int_cmp (f
->data
, a
->data
, 1) == -1
318 || double_int_cmp (f
->data
, b
->data
, 1) == -1)
330 else /* Signed type. */
333 && (get_fixed_sign_bit (a
->data
, i_f_bits
)
334 == get_fixed_sign_bit (b
->data
, i_f_bits
))
335 && (get_fixed_sign_bit (a
->data
, i_f_bits
)
336 != get_fixed_sign_bit (f
->data
, i_f_bits
)))
338 && (get_fixed_sign_bit (a
->data
, i_f_bits
)
339 != get_fixed_sign_bit (b
->data
, i_f_bits
))
340 && (get_fixed_sign_bit (a
->data
, i_f_bits
)
341 != get_fixed_sign_bit (f
->data
, i_f_bits
))))
347 lshift_double (f
->data
.low
, f
->data
.high
, i_f_bits
,
348 2 * HOST_BITS_PER_WIDE_INT
,
349 &f
->data
.low
, &f
->data
.high
, 1);
350 if (get_fixed_sign_bit (a
->data
, i_f_bits
) == 0)
355 f
->data
= double_int_add (f
->data
, double_int_neg (one
));
362 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
366 /* Calculate F = A * B.
367 If SAT_P, saturate the result to the max or the min.
368 Return true, if !SAT_P and overflow. */
371 do_fixed_multiply (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
,
372 const FIXED_VALUE_TYPE
*b
, bool sat_p
)
374 bool overflow_p
= false;
375 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
376 int i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
378 if (GET_MODE_PRECISION (f
->mode
) <= HOST_BITS_PER_WIDE_INT
)
380 f
->data
= double_int_mul (a
->data
, b
->data
);
381 lshift_double (f
->data
.low
, f
->data
.high
,
382 (-GET_MODE_FBIT (f
->mode
)),
383 2 * HOST_BITS_PER_WIDE_INT
,
384 &f
->data
.low
, &f
->data
.high
, !unsigned_p
);
385 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
, sat_p
);
389 /* The result of multiplication expands to two double_int. */
390 double_int a_high
, a_low
, b_high
, b_low
;
391 double_int high_high
, high_low
, low_high
, low_low
;
392 double_int r
, s
, temp1
, temp2
;
395 /* Decompose a and b to four double_int. */
396 a_high
.low
= a
->data
.high
;
398 a_low
.low
= a
->data
.low
;
400 b_high
.low
= b
->data
.high
;
402 b_low
.low
= b
->data
.low
;
405 /* Perform four multiplications. */
406 low_low
= double_int_mul (a_low
, b_low
);
407 low_high
= double_int_mul (a_low
, b_high
);
408 high_low
= double_int_mul (a_high
, b_low
);
409 high_high
= double_int_mul (a_high
, b_high
);
411 /* Accumulate four results to {r, s}. */
412 temp1
.high
= high_low
.low
;
414 s
= double_int_add (low_low
, temp1
);
415 if (double_int_cmp (s
, low_low
, 1) == -1
416 || double_int_cmp (s
, temp1
, 1) == -1)
417 carry
++; /* Carry */
420 temp2
.high
= low_high
.low
;
422 s
= double_int_add (temp1
, temp2
);
423 if (double_int_cmp (s
, temp1
, 1) == -1
424 || double_int_cmp (s
, temp2
, 1) == -1)
425 carry
++; /* Carry */
427 temp1
.low
= high_low
.high
;
429 r
= double_int_add (high_high
, temp1
);
430 temp1
.low
= low_high
.high
;
432 r
= double_int_add (r
, temp1
);
435 r
= double_int_add (r
, temp1
);
437 /* We need to add neg(b) to r, if a < 0. */
438 if (!unsigned_p
&& a
->data
.high
< 0)
439 r
= double_int_add (r
, double_int_neg (b
->data
));
440 /* We need to add neg(a) to r, if b < 0. */
441 if (!unsigned_p
&& b
->data
.high
< 0)
442 r
= double_int_add (r
, double_int_neg (a
->data
));
444 /* Shift right the result by FBIT. */
445 if (GET_MODE_FBIT (f
->mode
) == 2 * HOST_BITS_PER_WIDE_INT
)
460 f
->data
.high
= s
.high
;
464 lshift_double (s
.low
, s
.high
,
465 (-GET_MODE_FBIT (f
->mode
)),
466 2 * HOST_BITS_PER_WIDE_INT
,
468 lshift_double (r
.low
, r
.high
,
469 (2 * HOST_BITS_PER_WIDE_INT
470 - GET_MODE_FBIT (f
->mode
)),
471 2 * HOST_BITS_PER_WIDE_INT
,
472 &f
->data
.low
, &f
->data
.high
, 0);
473 f
->data
.low
= f
->data
.low
| s
.low
;
474 f
->data
.high
= f
->data
.high
| s
.high
;
476 s
.high
= f
->data
.high
;
477 lshift_double (r
.low
, r
.high
,
478 (-GET_MODE_FBIT (f
->mode
)),
479 2 * HOST_BITS_PER_WIDE_INT
,
480 &r
.low
, &r
.high
, !unsigned_p
);
483 overflow_p
= fixed_saturate2 (f
->mode
, r
, s
, &f
->data
, sat_p
);
486 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
490 /* Calculate F = A / B.
491 If SAT_P, saturate the result to the max or the min.
492 Return true, if !SAT_P and overflow. */
495 do_fixed_divide (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
,
496 const FIXED_VALUE_TYPE
*b
, bool sat_p
)
498 bool overflow_p
= false;
499 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
500 int i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
502 if (GET_MODE_PRECISION (f
->mode
) <= HOST_BITS_PER_WIDE_INT
)
504 lshift_double (a
->data
.low
, a
->data
.high
,
505 GET_MODE_FBIT (f
->mode
),
506 2 * HOST_BITS_PER_WIDE_INT
,
507 &f
->data
.low
, &f
->data
.high
, !unsigned_p
);
508 f
->data
= double_int_div (f
->data
, b
->data
, unsigned_p
, TRUNC_DIV_EXPR
);
509 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
, sat_p
);
513 double_int pos_a
, pos_b
, r
, s
;
514 double_int quo_r
, quo_s
, mod
, temp
;
518 /* If a < 0, negate a. */
519 if (!unsigned_p
&& a
->data
.high
< 0)
521 pos_a
= double_int_neg (a
->data
);
527 /* If b < 0, negate b. */
528 if (!unsigned_p
&& b
->data
.high
< 0)
530 pos_b
= double_int_neg (b
->data
);
536 /* Left shift pos_a to {r, s} by FBIT. */
537 if (GET_MODE_FBIT (f
->mode
) == 2 * HOST_BITS_PER_WIDE_INT
)
545 lshift_double (pos_a
.low
, pos_a
.high
,
546 GET_MODE_FBIT (f
->mode
),
547 2 * HOST_BITS_PER_WIDE_INT
,
549 lshift_double (pos_a
.low
, pos_a
.high
,
550 - (2 * HOST_BITS_PER_WIDE_INT
551 - GET_MODE_FBIT (f
->mode
)),
552 2 * HOST_BITS_PER_WIDE_INT
,
556 /* Divide r by pos_b to quo_r. The remainder is in mod. */
557 div_and_round_double (TRUNC_DIV_EXPR
, 1, r
.low
, r
.high
, pos_b
.low
,
558 pos_b
.high
, &quo_r
.low
, &quo_r
.high
, &mod
.low
,
564 for (i
= 0; i
< 2 * HOST_BITS_PER_WIDE_INT
; i
++)
566 /* Record the leftmost bit of mod. */
567 int leftmost_mod
= (mod
.high
< 0);
569 /* Shift left mod by 1 bit. */
570 lshift_double (mod
.low
, mod
.high
, 1, 2 * HOST_BITS_PER_WIDE_INT
,
571 &mod
.low
, &mod
.high
, 0);
573 /* Test the leftmost bit of s to add to mod. */
577 /* Shift left quo_s by 1 bit. */
578 lshift_double (quo_s
.low
, quo_s
.high
, 1, 2 * HOST_BITS_PER_WIDE_INT
,
579 &quo_s
.low
, &quo_s
.high
, 0);
581 /* Try to calculate (mod - pos_b). */
582 temp
= double_int_add (mod
, double_int_neg (pos_b
));
584 if (leftmost_mod
== 1 || double_int_cmp (mod
, pos_b
, 1) != -1)
590 /* Shift left s by 1 bit. */
591 lshift_double (s
.low
, s
.high
, 1, 2 * HOST_BITS_PER_WIDE_INT
,
598 quo_s
= double_int_neg (quo_s
);
599 if (quo_s
.high
== 0 && quo_s
.low
== 0)
600 quo_r
= double_int_neg (quo_r
);
603 quo_r
.low
= ~quo_r
.low
;
604 quo_r
.high
= ~quo_r
.high
;
609 overflow_p
= fixed_saturate2 (f
->mode
, quo_r
, quo_s
, &f
->data
, sat_p
);
612 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
616 /* Calculate F = A << B if LEFT_P. Otherwise, F = A >> B.
617 If SAT_P, saturate the result to the max or the min.
618 Return true, if !SAT_P and overflow. */
621 do_fixed_shift (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
,
622 const FIXED_VALUE_TYPE
*b
, bool left_p
, bool sat_p
)
624 bool overflow_p
= false;
625 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
626 int i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
629 if (b
->data
.low
== 0)
635 if (GET_MODE_PRECISION (f
->mode
) <= HOST_BITS_PER_WIDE_INT
|| (!left_p
))
637 lshift_double (a
->data
.low
, a
->data
.high
,
638 left_p
? b
->data
.low
: (-b
->data
.low
),
639 2 * HOST_BITS_PER_WIDE_INT
,
640 &f
->data
.low
, &f
->data
.high
, !unsigned_p
);
641 if (left_p
) /* Only left shift saturates. */
642 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
, sat_p
);
644 else /* We need two double_int to store the left-shift result. */
646 double_int temp_high
, temp_low
;
647 if (b
->data
.low
== 2 * HOST_BITS_PER_WIDE_INT
)
655 lshift_double (a
->data
.low
, a
->data
.high
,
657 2 * HOST_BITS_PER_WIDE_INT
,
658 &temp_low
.low
, &temp_low
.high
, !unsigned_p
);
659 /* Logical shift right to temp_high. */
660 lshift_double (a
->data
.low
, a
->data
.high
,
661 b
->data
.low
- 2 * HOST_BITS_PER_WIDE_INT
,
662 2 * HOST_BITS_PER_WIDE_INT
,
663 &temp_high
.low
, &temp_high
.high
, 0);
665 if (!unsigned_p
&& a
->data
.high
< 0) /* Signed-extend temp_high. */
666 temp_high
= double_int_ext (temp_high
, b
->data
.low
, unsigned_p
);
668 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
, &f
->data
,
671 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
676 If SAT_P, saturate the result to the max or the min.
677 Return true, if !SAT_P and overflow. */
680 do_fixed_neg (FIXED_VALUE_TYPE
*f
, const FIXED_VALUE_TYPE
*a
, bool sat_p
)
682 bool overflow_p
= false;
683 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (a
->mode
);
684 int i_f_bits
= GET_MODE_IBIT (a
->mode
) + GET_MODE_FBIT (a
->mode
);
686 f
->data
= double_int_neg (a
->data
);
687 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
689 if (unsigned_p
) /* Unsigned type. */
691 if (f
->data
.low
!= 0 || f
->data
.high
!= 0)
702 else /* Signed type. */
704 if (!(f
->data
.high
== 0 && f
->data
.low
== 0)
705 && f
->data
.high
== a
->data
.high
&& f
->data
.low
== a
->data
.low
)
709 /* Saturate to the maximum by subtracting f->data by one. */
712 f
->data
= double_int_ext (f
->data
, i_f_bits
, 1);
721 /* Perform the binary or unary operation described by CODE.
722 Note that OP0 and OP1 must have the same mode for binary operators.
723 For a unary operation, leave OP1 NULL.
724 Return true, if !SAT_P and overflow. */
727 fixed_arithmetic (FIXED_VALUE_TYPE
*f
, int icode
, const FIXED_VALUE_TYPE
*op0
,
728 const FIXED_VALUE_TYPE
*op1
, bool sat_p
)
733 return do_fixed_neg (f
, op0
, sat_p
);
737 gcc_assert (op0
->mode
== op1
->mode
);
738 return do_fixed_add (f
, op0
, op1
, false, sat_p
);
742 gcc_assert (op0
->mode
== op1
->mode
);
743 return do_fixed_add (f
, op0
, op1
, true, sat_p
);
747 gcc_assert (op0
->mode
== op1
->mode
);
748 return do_fixed_multiply (f
, op0
, op1
, sat_p
);
752 gcc_assert (op0
->mode
== op1
->mode
);
753 return do_fixed_divide (f
, op0
, op1
, sat_p
);
757 return do_fixed_shift (f
, op0
, op1
, true, sat_p
);
761 return do_fixed_shift (f
, op0
, op1
, false, sat_p
);
770 /* Compare fixed-point values by tree_code.
771 Note that OP0 and OP1 must have the same mode. */
774 fixed_compare (int icode
, const FIXED_VALUE_TYPE
*op0
,
775 const FIXED_VALUE_TYPE
*op1
)
777 enum tree_code code
= icode
;
778 gcc_assert (op0
->mode
== op1
->mode
);
783 return !double_int_equal_p (op0
->data
, op1
->data
);
786 return double_int_equal_p (op0
->data
, op1
->data
);
789 return double_int_cmp (op0
->data
, op1
->data
,
790 UNSIGNED_FIXED_POINT_MODE_P (op0
->mode
)) == -1;
793 return double_int_cmp (op0
->data
, op1
->data
,
794 UNSIGNED_FIXED_POINT_MODE_P (op0
->mode
)) != 1;
797 return double_int_cmp (op0
->data
, op1
->data
,
798 UNSIGNED_FIXED_POINT_MODE_P (op0
->mode
)) == 1;
801 return double_int_cmp (op0
->data
, op1
->data
,
802 UNSIGNED_FIXED_POINT_MODE_P (op0
->mode
)) != -1;
809 /* Extend or truncate to a new mode.
810 If SAT_P, saturate the result to the max or the min.
811 Return true, if !SAT_P and overflow. */
814 fixed_convert (FIXED_VALUE_TYPE
*f
, enum machine_mode mode
,
815 const FIXED_VALUE_TYPE
*a
, bool sat_p
)
817 bool overflow_p
= false;
824 if (GET_MODE_FBIT (mode
) > GET_MODE_FBIT (a
->mode
))
826 /* Left shift a to temp_high, temp_low based on a->mode. */
827 double_int temp_high
, temp_low
;
828 int amount
= GET_MODE_FBIT (mode
) - GET_MODE_FBIT (a
->mode
);
829 lshift_double (a
->data
.low
, a
->data
.high
,
831 2 * HOST_BITS_PER_WIDE_INT
,
832 &temp_low
.low
, &temp_low
.high
,
833 SIGNED_FIXED_POINT_MODE_P (a
->mode
));
834 /* Logical shift right to temp_high. */
835 lshift_double (a
->data
.low
, a
->data
.high
,
836 amount
- 2 * HOST_BITS_PER_WIDE_INT
,
837 2 * HOST_BITS_PER_WIDE_INT
,
838 &temp_high
.low
, &temp_high
.high
, 0);
839 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
)
840 && a
->data
.high
< 0) /* Signed-extend temp_high. */
841 temp_high
= double_int_ext (temp_high
, amount
, 0);
844 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
) ==
845 SIGNED_FIXED_POINT_MODE_P (f
->mode
))
846 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
, &f
->data
,
850 /* Take care of the cases when converting between signed and
852 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
))
854 /* Signed -> Unsigned. */
855 if (a
->data
.high
< 0)
859 f
->data
.low
= 0; /* Set to zero. */
860 f
->data
.high
= 0; /* Set to zero. */
866 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
,
871 /* Unsigned -> Signed. */
872 if (temp_high
.high
< 0)
876 /* Set to maximum. */
877 f
->data
.low
= -1; /* Set to all ones. */
878 f
->data
.high
= -1; /* Set to all ones. */
879 f
->data
= double_int_ext (f
->data
,
880 GET_MODE_FBIT (f
->mode
)
881 + GET_MODE_IBIT (f
->mode
),
882 1); /* Clear the sign. */
888 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
,
895 /* Right shift a to temp based on a->mode. */
897 lshift_double (a
->data
.low
, a
->data
.high
,
898 GET_MODE_FBIT (mode
) - GET_MODE_FBIT (a
->mode
),
899 2 * HOST_BITS_PER_WIDE_INT
,
900 &temp
.low
, &temp
.high
,
901 SIGNED_FIXED_POINT_MODE_P (a
->mode
));
904 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
) ==
905 SIGNED_FIXED_POINT_MODE_P (f
->mode
))
906 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
, sat_p
);
909 /* Take care of the cases when converting between signed and
911 if (SIGNED_FIXED_POINT_MODE_P (a
->mode
))
913 /* Signed -> Unsigned. */
914 if (a
->data
.high
< 0)
918 f
->data
.low
= 0; /* Set to zero. */
919 f
->data
.high
= 0; /* Set to zero. */
925 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
,
930 /* Unsigned -> Signed. */
935 /* Set to maximum. */
936 f
->data
.low
= -1; /* Set to all ones. */
937 f
->data
.high
= -1; /* Set to all ones. */
938 f
->data
= double_int_ext (f
->data
,
939 GET_MODE_FBIT (f
->mode
)
940 + GET_MODE_IBIT (f
->mode
),
941 1); /* Clear the sign. */
947 overflow_p
= fixed_saturate1 (f
->mode
, f
->data
, &f
->data
,
953 f
->data
= double_int_ext (f
->data
,
954 SIGNED_FIXED_POINT_MODE_P (f
->mode
)
955 + GET_MODE_FBIT (f
->mode
)
956 + GET_MODE_IBIT (f
->mode
),
957 UNSIGNED_FIXED_POINT_MODE_P (f
->mode
));
961 /* Convert to a new fixed-point mode from an integer.
962 If UNSIGNED_P, this integer is unsigned.
963 If SAT_P, saturate the result to the max or the min.
964 Return true, if !SAT_P and overflow. */
967 fixed_convert_from_int (FIXED_VALUE_TYPE
*f
, enum machine_mode mode
,
968 double_int a
, bool unsigned_p
, bool sat_p
)
970 bool overflow_p
= false;
971 /* Left shift a to temp_high, temp_low. */
972 double_int temp_high
, temp_low
;
973 int amount
= GET_MODE_FBIT (mode
);
974 if (amount
== 2 * HOST_BITS_PER_WIDE_INT
)
982 lshift_double (a
.low
, a
.high
,
984 2 * HOST_BITS_PER_WIDE_INT
,
985 &temp_low
.low
, &temp_low
.high
, 0);
987 /* Logical shift right to temp_high. */
988 lshift_double (a
.low
, a
.high
,
989 amount
- 2 * HOST_BITS_PER_WIDE_INT
,
990 2 * HOST_BITS_PER_WIDE_INT
,
991 &temp_high
.low
, &temp_high
.high
, 0);
993 if (!unsigned_p
&& a
.high
< 0) /* Signed-extend temp_high. */
994 temp_high
= double_int_ext (temp_high
, amount
, 0);
999 if (unsigned_p
== UNSIGNED_FIXED_POINT_MODE_P (f
->mode
))
1000 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
, &f
->data
,
1004 /* Take care of the cases when converting between signed and unsigned. */
1007 /* Signed -> Unsigned. */
1012 f
->data
.low
= 0; /* Set to zero. */
1013 f
->data
.high
= 0; /* Set to zero. */
1019 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
,
1024 /* Unsigned -> Signed. */
1025 if (temp_high
.high
< 0)
1029 /* Set to maximum. */
1030 f
->data
.low
= -1; /* Set to all ones. */
1031 f
->data
.high
= -1; /* Set to all ones. */
1032 f
->data
= double_int_ext (f
->data
,
1033 GET_MODE_FBIT (f
->mode
)
1034 + GET_MODE_IBIT (f
->mode
),
1035 1); /* Clear the sign. */
1041 overflow_p
= fixed_saturate2 (f
->mode
, temp_high
, temp_low
,
1045 f
->data
= double_int_ext (f
->data
,
1046 SIGNED_FIXED_POINT_MODE_P (f
->mode
)
1047 + GET_MODE_FBIT (f
->mode
)
1048 + GET_MODE_IBIT (f
->mode
),
1049 UNSIGNED_FIXED_POINT_MODE_P (f
->mode
));
1053 /* Convert to a new fixed-point mode from a real.
1054 If SAT_P, saturate the result to the max or the min.
1055 Return true, if !SAT_P and overflow. */
1058 fixed_convert_from_real (FIXED_VALUE_TYPE
*f
, enum machine_mode mode
,
1059 const REAL_VALUE_TYPE
*a
, bool sat_p
)
1061 bool overflow_p
= false;
1062 REAL_VALUE_TYPE real_value
, fixed_value
, base_value
;
1063 bool unsigned_p
= UNSIGNED_FIXED_POINT_MODE_P (mode
);
1064 int i_f_bits
= GET_MODE_IBIT (mode
) + GET_MODE_FBIT (mode
);
1065 unsigned int fbit
= GET_MODE_FBIT (mode
);
1066 enum fixed_value_range_code temp
;
1070 real_2expN (&base_value
, fbit
, mode
);
1071 real_arithmetic (&fixed_value
, MULT_EXPR
, &real_value
, &base_value
);
1072 real_to_integer2 ((HOST_WIDE_INT
*)&f
->data
.low
, &f
->data
.high
, &fixed_value
);
1073 temp
= check_real_for_fixed_mode (&real_value
, mode
);
1074 if (temp
== FIXED_UNDERFLOW
) /* Minimum. */
1087 lshift_double (f
->data
.low
, f
->data
.high
, i_f_bits
,
1088 2 * HOST_BITS_PER_WIDE_INT
,
1089 &f
->data
.low
, &f
->data
.high
, 1);
1090 f
->data
= double_int_ext (f
->data
, 1 + i_f_bits
, 0);
1096 else if (temp
== FIXED_GT_MAX_EPS
|| temp
== FIXED_MAX_EPS
) /* Maximum. */
1102 f
->data
= double_int_ext (f
->data
, i_f_bits
, 1);
1107 f
->data
= double_int_ext (f
->data
, (!unsigned_p
) + i_f_bits
, unsigned_p
);
1111 /* Convert to a new real mode from a fixed-point. */
1114 real_convert_from_fixed (REAL_VALUE_TYPE
*r
, enum machine_mode mode
,
1115 const FIXED_VALUE_TYPE
*f
)
1117 REAL_VALUE_TYPE base_value
, fixed_value
, real_value
;
1119 real_2expN (&base_value
, GET_MODE_FBIT (f
->mode
), f
->mode
);
1120 real_from_integer (&fixed_value
, VOIDmode
, f
->data
.low
, f
->data
.high
,
1121 UNSIGNED_FIXED_POINT_MODE_P (f
->mode
));
1122 real_arithmetic (&real_value
, RDIV_EXPR
, &fixed_value
, &base_value
);
1123 real_convert (r
, mode
, &real_value
);
1126 /* Determine whether a fixed-point value F is negative. */
1129 fixed_isneg (const FIXED_VALUE_TYPE
*f
)
1131 if (SIGNED_FIXED_POINT_MODE_P (f
->mode
))
1133 int i_f_bits
= GET_MODE_IBIT (f
->mode
) + GET_MODE_FBIT (f
->mode
);
1134 int sign_bit
= get_fixed_sign_bit (f
->data
, i_f_bits
);