11debfc3dSmrg /* Fixed-point arithmetic support.
2*8feb0f0bSmrg Copyright (C) 2006-2020 Free Software Foundation, Inc.
31debfc3dSmrg
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
71debfc3dSmrg the terms of the GNU General Public License as published by the Free
81debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
91debfc3dSmrg version.
101debfc3dSmrg
111debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
121debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
141debfc3dSmrg for more details.
151debfc3dSmrg
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3. If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>. */
191debfc3dSmrg
201debfc3dSmrg #include "config.h"
211debfc3dSmrg #include "system.h"
221debfc3dSmrg #include "coretypes.h"
231debfc3dSmrg #include "tm.h"
241debfc3dSmrg #include "tree.h"
251debfc3dSmrg #include "diagnostic-core.h"
261debfc3dSmrg
271debfc3dSmrg /* Compare two fixed objects for bitwise identity. */
281debfc3dSmrg
291debfc3dSmrg bool
fixed_identical(const FIXED_VALUE_TYPE * a,const FIXED_VALUE_TYPE * b)301debfc3dSmrg fixed_identical (const FIXED_VALUE_TYPE *a, const FIXED_VALUE_TYPE *b)
311debfc3dSmrg {
321debfc3dSmrg return (a->mode == b->mode
331debfc3dSmrg && a->data.high == b->data.high
341debfc3dSmrg && a->data.low == b->data.low);
351debfc3dSmrg }
361debfc3dSmrg
371debfc3dSmrg /* Calculate a hash value. */
381debfc3dSmrg
391debfc3dSmrg unsigned int
fixed_hash(const FIXED_VALUE_TYPE * f)401debfc3dSmrg fixed_hash (const FIXED_VALUE_TYPE *f)
411debfc3dSmrg {
421debfc3dSmrg return (unsigned int) (f->data.low ^ f->data.high);
431debfc3dSmrg }
441debfc3dSmrg
451debfc3dSmrg /* Define the enum code for the range of the fixed-point value. */
461debfc3dSmrg enum fixed_value_range_code {
471debfc3dSmrg FIXED_OK, /* The value is within the range. */
481debfc3dSmrg FIXED_UNDERFLOW, /* The value is less than the minimum. */
491debfc3dSmrg FIXED_GT_MAX_EPS, /* The value is greater than the maximum, but not equal
501debfc3dSmrg to the maximum plus the epsilon. */
511debfc3dSmrg FIXED_MAX_EPS /* The value equals the maximum plus the epsilon. */
521debfc3dSmrg };
531debfc3dSmrg
541debfc3dSmrg /* Check REAL_VALUE against the range of the fixed-point mode.
551debfc3dSmrg Return FIXED_OK, if it is within the range.
561debfc3dSmrg FIXED_UNDERFLOW, if it is less than the minimum.
571debfc3dSmrg FIXED_GT_MAX_EPS, if it is greater than the maximum, but not equal to
581debfc3dSmrg the maximum plus the epsilon.
591debfc3dSmrg FIXED_MAX_EPS, if it is equal to the maximum plus the epsilon. */
601debfc3dSmrg
611debfc3dSmrg static enum fixed_value_range_code
check_real_for_fixed_mode(REAL_VALUE_TYPE * real_value,machine_mode mode)621debfc3dSmrg check_real_for_fixed_mode (REAL_VALUE_TYPE *real_value, machine_mode mode)
631debfc3dSmrg {
641debfc3dSmrg REAL_VALUE_TYPE max_value, min_value, epsilon_value;
651debfc3dSmrg
661debfc3dSmrg real_2expN (&max_value, GET_MODE_IBIT (mode), VOIDmode);
671debfc3dSmrg real_2expN (&epsilon_value, -GET_MODE_FBIT (mode), VOIDmode);
681debfc3dSmrg
691debfc3dSmrg if (SIGNED_FIXED_POINT_MODE_P (mode))
701debfc3dSmrg min_value = real_value_negate (&max_value);
711debfc3dSmrg else
721debfc3dSmrg real_from_string (&min_value, "0.0");
731debfc3dSmrg
741debfc3dSmrg if (real_compare (LT_EXPR, real_value, &min_value))
751debfc3dSmrg return FIXED_UNDERFLOW;
761debfc3dSmrg if (real_compare (EQ_EXPR, real_value, &max_value))
771debfc3dSmrg return FIXED_MAX_EPS;
781debfc3dSmrg real_arithmetic (&max_value, MINUS_EXPR, &max_value, &epsilon_value);
791debfc3dSmrg if (real_compare (GT_EXPR, real_value, &max_value))
801debfc3dSmrg return FIXED_GT_MAX_EPS;
811debfc3dSmrg return FIXED_OK;
821debfc3dSmrg }
831debfc3dSmrg
841debfc3dSmrg
851debfc3dSmrg /* Construct a CONST_FIXED from a bit payload and machine mode MODE.
861debfc3dSmrg The bits in PAYLOAD are sign-extended/zero-extended according to MODE. */
871debfc3dSmrg
881debfc3dSmrg FIXED_VALUE_TYPE
fixed_from_double_int(double_int payload,scalar_mode mode)89a2dc1f3fSmrg fixed_from_double_int (double_int payload, scalar_mode mode)
901debfc3dSmrg {
911debfc3dSmrg FIXED_VALUE_TYPE value;
921debfc3dSmrg
931debfc3dSmrg gcc_assert (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_DOUBLE_INT);
941debfc3dSmrg
951debfc3dSmrg if (SIGNED_SCALAR_FIXED_POINT_MODE_P (mode))
961debfc3dSmrg value.data = payload.sext (1 + GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode));
971debfc3dSmrg else if (UNSIGNED_SCALAR_FIXED_POINT_MODE_P (mode))
981debfc3dSmrg value.data = payload.zext (GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode));
991debfc3dSmrg else
1001debfc3dSmrg gcc_unreachable ();
1011debfc3dSmrg
1021debfc3dSmrg value.mode = mode;
1031debfc3dSmrg
1041debfc3dSmrg return value;
1051debfc3dSmrg }
1061debfc3dSmrg
1071debfc3dSmrg
1081debfc3dSmrg /* Initialize from a decimal or hexadecimal string. */
1091debfc3dSmrg
1101debfc3dSmrg void
fixed_from_string(FIXED_VALUE_TYPE * f,const char * str,scalar_mode mode)111a2dc1f3fSmrg fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, scalar_mode mode)
1121debfc3dSmrg {
1131debfc3dSmrg REAL_VALUE_TYPE real_value, fixed_value, base_value;
1141debfc3dSmrg unsigned int fbit;
1151debfc3dSmrg enum fixed_value_range_code temp;
1161debfc3dSmrg bool fail;
1171debfc3dSmrg
1181debfc3dSmrg f->mode = mode;
1191debfc3dSmrg fbit = GET_MODE_FBIT (mode);
1201debfc3dSmrg
1211debfc3dSmrg real_from_string (&real_value, str);
1221debfc3dSmrg temp = check_real_for_fixed_mode (&real_value, f->mode);
1231debfc3dSmrg /* We don't want to warn the case when the _Fract value is 1.0. */
1241debfc3dSmrg if (temp == FIXED_UNDERFLOW
1251debfc3dSmrg || temp == FIXED_GT_MAX_EPS
1261debfc3dSmrg || (temp == FIXED_MAX_EPS && ALL_ACCUM_MODE_P (f->mode)))
1271debfc3dSmrg warning (OPT_Woverflow,
1281debfc3dSmrg "large fixed-point constant implicitly truncated to fixed-point type");
1291debfc3dSmrg real_2expN (&base_value, fbit, VOIDmode);
1301debfc3dSmrg real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value);
1311debfc3dSmrg wide_int w = real_to_integer (&fixed_value, &fail,
1321debfc3dSmrg GET_MODE_PRECISION (mode));
1331debfc3dSmrg f->data.low = w.ulow ();
1341debfc3dSmrg f->data.high = w.elt (1);
1351debfc3dSmrg
1361debfc3dSmrg if (temp == FIXED_MAX_EPS && ALL_FRACT_MODE_P (f->mode))
1371debfc3dSmrg {
1381debfc3dSmrg /* From the spec, we need to evaluate 1 to the maximal value. */
1391debfc3dSmrg f->data.low = -1;
1401debfc3dSmrg f->data.high = -1;
1411debfc3dSmrg f->data = f->data.zext (GET_MODE_FBIT (f->mode)
1421debfc3dSmrg + GET_MODE_IBIT (f->mode));
1431debfc3dSmrg }
1441debfc3dSmrg else
1451debfc3dSmrg f->data = f->data.ext (SIGNED_FIXED_POINT_MODE_P (f->mode)
1461debfc3dSmrg + GET_MODE_FBIT (f->mode)
1471debfc3dSmrg + GET_MODE_IBIT (f->mode),
1481debfc3dSmrg UNSIGNED_FIXED_POINT_MODE_P (f->mode));
1491debfc3dSmrg }
1501debfc3dSmrg
1511debfc3dSmrg /* Render F as a decimal floating point constant. */
1521debfc3dSmrg
1531debfc3dSmrg void
fixed_to_decimal(char * str,const FIXED_VALUE_TYPE * f_orig,size_t buf_size)1541debfc3dSmrg fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig,
1551debfc3dSmrg size_t buf_size)
1561debfc3dSmrg {
1571debfc3dSmrg REAL_VALUE_TYPE real_value, base_value, fixed_value;
1581debfc3dSmrg
1591debfc3dSmrg signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode) ? UNSIGNED : SIGNED;
1601debfc3dSmrg real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), VOIDmode);
1611debfc3dSmrg real_from_integer (&real_value, VOIDmode,
1621debfc3dSmrg wide_int::from (f_orig->data,
1631debfc3dSmrg GET_MODE_PRECISION (f_orig->mode), sgn),
1641debfc3dSmrg sgn);
1651debfc3dSmrg real_arithmetic (&fixed_value, RDIV_EXPR, &real_value, &base_value);
1661debfc3dSmrg real_to_decimal (str, &fixed_value, buf_size, 0, 1);
1671debfc3dSmrg }
1681debfc3dSmrg
1691debfc3dSmrg /* If SAT_P, saturate A to the maximum or the minimum, and save to *F based on
1701debfc3dSmrg the machine mode MODE.
1711debfc3dSmrg Do not modify *F otherwise.
1721debfc3dSmrg This function assumes the width of double_int is greater than the width
1731debfc3dSmrg of the fixed-point value (the sum of a possible sign bit, possible ibits,
1741debfc3dSmrg and fbits).
1751debfc3dSmrg Return true, if !SAT_P and overflow. */
1761debfc3dSmrg
1771debfc3dSmrg static bool
fixed_saturate1(machine_mode mode,double_int a,double_int * f,bool sat_p)1781debfc3dSmrg fixed_saturate1 (machine_mode mode, double_int a, double_int *f,
1791debfc3dSmrg bool sat_p)
1801debfc3dSmrg {
1811debfc3dSmrg bool overflow_p = false;
1821debfc3dSmrg bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode);
1831debfc3dSmrg int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode);
1841debfc3dSmrg
1851debfc3dSmrg if (unsigned_p) /* Unsigned type. */
1861debfc3dSmrg {
1871debfc3dSmrg double_int max;
1881debfc3dSmrg max.low = -1;
1891debfc3dSmrg max.high = -1;
1901debfc3dSmrg max = max.zext (i_f_bits);
1911debfc3dSmrg if (a.ugt (max))
1921debfc3dSmrg {
1931debfc3dSmrg if (sat_p)
1941debfc3dSmrg *f = max;
1951debfc3dSmrg else
1961debfc3dSmrg overflow_p = true;
1971debfc3dSmrg }
1981debfc3dSmrg }
1991debfc3dSmrg else /* Signed type. */
2001debfc3dSmrg {
2011debfc3dSmrg double_int max, min;
2021debfc3dSmrg max.high = -1;
2031debfc3dSmrg max.low = -1;
2041debfc3dSmrg max = max.zext (i_f_bits);
2051debfc3dSmrg min.high = 0;
2061debfc3dSmrg min.low = 1;
2071debfc3dSmrg min = min.alshift (i_f_bits, HOST_BITS_PER_DOUBLE_INT);
2081debfc3dSmrg min = min.sext (1 + i_f_bits);
2091debfc3dSmrg if (a.sgt (max))
2101debfc3dSmrg {
2111debfc3dSmrg if (sat_p)
2121debfc3dSmrg *f = max;
2131debfc3dSmrg else
2141debfc3dSmrg overflow_p = true;
2151debfc3dSmrg }
2161debfc3dSmrg else if (a.slt (min))
2171debfc3dSmrg {
2181debfc3dSmrg if (sat_p)
2191debfc3dSmrg *f = min;
2201debfc3dSmrg else
2211debfc3dSmrg overflow_p = true;
2221debfc3dSmrg }
2231debfc3dSmrg }
2241debfc3dSmrg return overflow_p;
2251debfc3dSmrg }
2261debfc3dSmrg
2271debfc3dSmrg /* If SAT_P, saturate {A_HIGH, A_LOW} to the maximum or the minimum, and
2281debfc3dSmrg save to *F based on the machine mode MODE.
2291debfc3dSmrg Do not modify *F otherwise.
2301debfc3dSmrg This function assumes the width of two double_int is greater than the width
2311debfc3dSmrg of the fixed-point value (the sum of a possible sign bit, possible ibits,
2321debfc3dSmrg and fbits).
2331debfc3dSmrg Return true, if !SAT_P and overflow. */
2341debfc3dSmrg
2351debfc3dSmrg static bool
fixed_saturate2(machine_mode mode,double_int a_high,double_int a_low,double_int * f,bool sat_p)2361debfc3dSmrg fixed_saturate2 (machine_mode mode, double_int a_high, double_int a_low,
2371debfc3dSmrg double_int *f, bool sat_p)
2381debfc3dSmrg {
2391debfc3dSmrg bool overflow_p = false;
2401debfc3dSmrg bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode);
2411debfc3dSmrg int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode);
2421debfc3dSmrg
2431debfc3dSmrg if (unsigned_p) /* Unsigned type. */
2441debfc3dSmrg {
2451debfc3dSmrg double_int max_r, max_s;
2461debfc3dSmrg max_r.high = 0;
2471debfc3dSmrg max_r.low = 0;
2481debfc3dSmrg max_s.high = -1;
2491debfc3dSmrg max_s.low = -1;
2501debfc3dSmrg max_s = max_s.zext (i_f_bits);
2511debfc3dSmrg if (a_high.ugt (max_r)
2521debfc3dSmrg || (a_high == max_r &&
2531debfc3dSmrg a_low.ugt (max_s)))
2541debfc3dSmrg {
2551debfc3dSmrg if (sat_p)
2561debfc3dSmrg *f = max_s;
2571debfc3dSmrg else
2581debfc3dSmrg overflow_p = true;
2591debfc3dSmrg }
2601debfc3dSmrg }
2611debfc3dSmrg else /* Signed type. */
2621debfc3dSmrg {
2631debfc3dSmrg double_int max_r, max_s, min_r, min_s;
2641debfc3dSmrg max_r.high = 0;
2651debfc3dSmrg max_r.low = 0;
2661debfc3dSmrg max_s.high = -1;
2671debfc3dSmrg max_s.low = -1;
2681debfc3dSmrg max_s = max_s.zext (i_f_bits);
2691debfc3dSmrg min_r.high = -1;
2701debfc3dSmrg min_r.low = -1;
2711debfc3dSmrg min_s.high = 0;
2721debfc3dSmrg min_s.low = 1;
2731debfc3dSmrg min_s = min_s.alshift (i_f_bits, HOST_BITS_PER_DOUBLE_INT);
2741debfc3dSmrg min_s = min_s.sext (1 + i_f_bits);
2751debfc3dSmrg if (a_high.sgt (max_r)
2761debfc3dSmrg || (a_high == max_r &&
2771debfc3dSmrg a_low.ugt (max_s)))
2781debfc3dSmrg {
2791debfc3dSmrg if (sat_p)
2801debfc3dSmrg *f = max_s;
2811debfc3dSmrg else
2821debfc3dSmrg overflow_p = true;
2831debfc3dSmrg }
2841debfc3dSmrg else if (a_high.slt (min_r)
2851debfc3dSmrg || (a_high == min_r &&
2861debfc3dSmrg a_low.ult (min_s)))
2871debfc3dSmrg {
2881debfc3dSmrg if (sat_p)
2891debfc3dSmrg *f = min_s;
2901debfc3dSmrg else
2911debfc3dSmrg overflow_p = true;
2921debfc3dSmrg }
2931debfc3dSmrg }
2941debfc3dSmrg return overflow_p;
2951debfc3dSmrg }
2961debfc3dSmrg
2971debfc3dSmrg /* Return the sign bit based on I_F_BITS. */
2981debfc3dSmrg
2991debfc3dSmrg static inline int
get_fixed_sign_bit(double_int a,int i_f_bits)3001debfc3dSmrg get_fixed_sign_bit (double_int a, int i_f_bits)
3011debfc3dSmrg {
3021debfc3dSmrg if (i_f_bits < HOST_BITS_PER_WIDE_INT)
3031debfc3dSmrg return (a.low >> i_f_bits) & 1;
3041debfc3dSmrg else
3051debfc3dSmrg return (a.high >> (i_f_bits - HOST_BITS_PER_WIDE_INT)) & 1;
3061debfc3dSmrg }
3071debfc3dSmrg
3081debfc3dSmrg /* Calculate F = A + (SUBTRACT_P ? -B : B).
3091debfc3dSmrg If SAT_P, saturate the result to the max or the min.
3101debfc3dSmrg Return true, if !SAT_P and overflow. */
3111debfc3dSmrg
3121debfc3dSmrg static bool
do_fixed_add(FIXED_VALUE_TYPE * f,const FIXED_VALUE_TYPE * a,const FIXED_VALUE_TYPE * b,bool subtract_p,bool sat_p)3131debfc3dSmrg do_fixed_add (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
3141debfc3dSmrg const FIXED_VALUE_TYPE *b, bool subtract_p, bool sat_p)
3151debfc3dSmrg {
3161debfc3dSmrg bool overflow_p = false;
3171debfc3dSmrg bool unsigned_p;
3181debfc3dSmrg double_int temp;
3191debfc3dSmrg int i_f_bits;
3201debfc3dSmrg
3211debfc3dSmrg /* This was a conditional expression but it triggered a bug in
3221debfc3dSmrg Sun C 5.5. */
3231debfc3dSmrg if (subtract_p)
3241debfc3dSmrg temp = -b->data;
3251debfc3dSmrg else
3261debfc3dSmrg temp = b->data;
3271debfc3dSmrg
3281debfc3dSmrg unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
3291debfc3dSmrg i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
3301debfc3dSmrg f->mode = a->mode;
3311debfc3dSmrg f->data = a->data + temp;
3321debfc3dSmrg if (unsigned_p) /* Unsigned type. */
3331debfc3dSmrg {
3341debfc3dSmrg if (subtract_p) /* Unsigned subtraction. */
3351debfc3dSmrg {
3361debfc3dSmrg if (a->data.ult (b->data))
3371debfc3dSmrg {
3381debfc3dSmrg if (sat_p)
3391debfc3dSmrg {
3401debfc3dSmrg f->data.high = 0;
3411debfc3dSmrg f->data.low = 0;
3421debfc3dSmrg }
3431debfc3dSmrg else
3441debfc3dSmrg overflow_p = true;
3451debfc3dSmrg }
3461debfc3dSmrg }
3471debfc3dSmrg else /* Unsigned addition. */
3481debfc3dSmrg {
3491debfc3dSmrg f->data = f->data.zext (i_f_bits);
3501debfc3dSmrg if (f->data.ult (a->data)
3511debfc3dSmrg || f->data.ult (b->data))
3521debfc3dSmrg {
3531debfc3dSmrg if (sat_p)
3541debfc3dSmrg {
3551debfc3dSmrg f->data.high = -1;
3561debfc3dSmrg f->data.low = -1;
3571debfc3dSmrg }
3581debfc3dSmrg else
3591debfc3dSmrg overflow_p = true;
3601debfc3dSmrg }
3611debfc3dSmrg }
3621debfc3dSmrg }
3631debfc3dSmrg else /* Signed type. */
3641debfc3dSmrg {
3651debfc3dSmrg if ((!subtract_p
3661debfc3dSmrg && (get_fixed_sign_bit (a->data, i_f_bits)
3671debfc3dSmrg == get_fixed_sign_bit (b->data, i_f_bits))
3681debfc3dSmrg && (get_fixed_sign_bit (a->data, i_f_bits)
3691debfc3dSmrg != get_fixed_sign_bit (f->data, i_f_bits)))
3701debfc3dSmrg || (subtract_p
3711debfc3dSmrg && (get_fixed_sign_bit (a->data, i_f_bits)
3721debfc3dSmrg != get_fixed_sign_bit (b->data, i_f_bits))
3731debfc3dSmrg && (get_fixed_sign_bit (a->data, i_f_bits)
3741debfc3dSmrg != get_fixed_sign_bit (f->data, i_f_bits))))
3751debfc3dSmrg {
3761debfc3dSmrg if (sat_p)
3771debfc3dSmrg {
3781debfc3dSmrg f->data.low = 1;
3791debfc3dSmrg f->data.high = 0;
3801debfc3dSmrg f->data = f->data.alshift (i_f_bits, HOST_BITS_PER_DOUBLE_INT);
3811debfc3dSmrg if (get_fixed_sign_bit (a->data, i_f_bits) == 0)
3821debfc3dSmrg {
3831debfc3dSmrg --f->data;
3841debfc3dSmrg }
3851debfc3dSmrg }
3861debfc3dSmrg else
3871debfc3dSmrg overflow_p = true;
3881debfc3dSmrg }
3891debfc3dSmrg }
3901debfc3dSmrg f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p);
3911debfc3dSmrg return overflow_p;
3921debfc3dSmrg }
3931debfc3dSmrg
3941debfc3dSmrg /* Calculate F = A * B.
3951debfc3dSmrg If SAT_P, saturate the result to the max or the min.
3961debfc3dSmrg Return true, if !SAT_P and overflow. */
3971debfc3dSmrg
3981debfc3dSmrg static bool
do_fixed_multiply(FIXED_VALUE_TYPE * f,const FIXED_VALUE_TYPE * a,const FIXED_VALUE_TYPE * b,bool sat_p)3991debfc3dSmrg do_fixed_multiply (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
4001debfc3dSmrg const FIXED_VALUE_TYPE *b, bool sat_p)
4011debfc3dSmrg {
4021debfc3dSmrg bool overflow_p = false;
4031debfc3dSmrg bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
4041debfc3dSmrg int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
4051debfc3dSmrg f->mode = a->mode;
4061debfc3dSmrg if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT)
4071debfc3dSmrg {
4081debfc3dSmrg f->data = a->data * b->data;
4091debfc3dSmrg f->data = f->data.lshift (-GET_MODE_FBIT (f->mode),
4101debfc3dSmrg HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
4111debfc3dSmrg overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
4121debfc3dSmrg }
4131debfc3dSmrg else
4141debfc3dSmrg {
4151debfc3dSmrg /* The result of multiplication expands to two double_int. */
4161debfc3dSmrg double_int a_high, a_low, b_high, b_low;
4171debfc3dSmrg double_int high_high, high_low, low_high, low_low;
4181debfc3dSmrg double_int r, s, temp1, temp2;
4191debfc3dSmrg int carry = 0;
4201debfc3dSmrg
4211debfc3dSmrg /* Decompose a and b to four double_int. */
4221debfc3dSmrg a_high.low = a->data.high;
4231debfc3dSmrg a_high.high = 0;
4241debfc3dSmrg a_low.low = a->data.low;
4251debfc3dSmrg a_low.high = 0;
4261debfc3dSmrg b_high.low = b->data.high;
4271debfc3dSmrg b_high.high = 0;
4281debfc3dSmrg b_low.low = b->data.low;
4291debfc3dSmrg b_low.high = 0;
4301debfc3dSmrg
4311debfc3dSmrg /* Perform four multiplications. */
4321debfc3dSmrg low_low = a_low * b_low;
4331debfc3dSmrg low_high = a_low * b_high;
4341debfc3dSmrg high_low = a_high * b_low;
4351debfc3dSmrg high_high = a_high * b_high;
4361debfc3dSmrg
4371debfc3dSmrg /* Accumulate four results to {r, s}. */
4381debfc3dSmrg temp1.high = high_low.low;
4391debfc3dSmrg temp1.low = 0;
4401debfc3dSmrg s = low_low + temp1;
4411debfc3dSmrg if (s.ult (low_low)
4421debfc3dSmrg || s.ult (temp1))
4431debfc3dSmrg carry ++; /* Carry */
4441debfc3dSmrg temp1.high = s.high;
4451debfc3dSmrg temp1.low = s.low;
4461debfc3dSmrg temp2.high = low_high.low;
4471debfc3dSmrg temp2.low = 0;
4481debfc3dSmrg s = temp1 + temp2;
4491debfc3dSmrg if (s.ult (temp1)
4501debfc3dSmrg || s.ult (temp2))
4511debfc3dSmrg carry ++; /* Carry */
4521debfc3dSmrg
4531debfc3dSmrg temp1.low = high_low.high;
4541debfc3dSmrg temp1.high = 0;
4551debfc3dSmrg r = high_high + temp1;
4561debfc3dSmrg temp1.low = low_high.high;
4571debfc3dSmrg temp1.high = 0;
4581debfc3dSmrg r += temp1;
4591debfc3dSmrg temp1.low = carry;
4601debfc3dSmrg temp1.high = 0;
4611debfc3dSmrg r += temp1;
4621debfc3dSmrg
4631debfc3dSmrg /* We need to subtract b from r, if a < 0. */
4641debfc3dSmrg if (!unsigned_p && a->data.high < 0)
4651debfc3dSmrg r -= b->data;
4661debfc3dSmrg /* We need to subtract a from r, if b < 0. */
4671debfc3dSmrg if (!unsigned_p && b->data.high < 0)
4681debfc3dSmrg r -= a->data;
4691debfc3dSmrg
4701debfc3dSmrg /* Shift right the result by FBIT. */
4711debfc3dSmrg if (GET_MODE_FBIT (f->mode) == HOST_BITS_PER_DOUBLE_INT)
4721debfc3dSmrg {
4731debfc3dSmrg s.low = r.low;
4741debfc3dSmrg s.high = r.high;
4751debfc3dSmrg if (unsigned_p)
4761debfc3dSmrg {
4771debfc3dSmrg r.low = 0;
4781debfc3dSmrg r.high = 0;
4791debfc3dSmrg }
4801debfc3dSmrg else
4811debfc3dSmrg {
4821debfc3dSmrg r.low = -1;
4831debfc3dSmrg r.high = -1;
4841debfc3dSmrg }
4851debfc3dSmrg f->data.low = s.low;
4861debfc3dSmrg f->data.high = s.high;
4871debfc3dSmrg }
4881debfc3dSmrg else
4891debfc3dSmrg {
4901debfc3dSmrg s = s.llshift ((-GET_MODE_FBIT (f->mode)), HOST_BITS_PER_DOUBLE_INT);
4911debfc3dSmrg f->data = r.llshift ((HOST_BITS_PER_DOUBLE_INT
4921debfc3dSmrg - GET_MODE_FBIT (f->mode)),
4931debfc3dSmrg HOST_BITS_PER_DOUBLE_INT);
4941debfc3dSmrg f->data.low = f->data.low | s.low;
4951debfc3dSmrg f->data.high = f->data.high | s.high;
4961debfc3dSmrg s.low = f->data.low;
4971debfc3dSmrg s.high = f->data.high;
4981debfc3dSmrg r = r.lshift (-GET_MODE_FBIT (f->mode),
4991debfc3dSmrg HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
5001debfc3dSmrg }
5011debfc3dSmrg
5021debfc3dSmrg overflow_p = fixed_saturate2 (f->mode, r, s, &f->data, sat_p);
5031debfc3dSmrg }
5041debfc3dSmrg
5051debfc3dSmrg f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p);
5061debfc3dSmrg return overflow_p;
5071debfc3dSmrg }
5081debfc3dSmrg
5091debfc3dSmrg /* Calculate F = A / B.
5101debfc3dSmrg If SAT_P, saturate the result to the max or the min.
5111debfc3dSmrg Return true, if !SAT_P and overflow. */
5121debfc3dSmrg
5131debfc3dSmrg static bool
do_fixed_divide(FIXED_VALUE_TYPE * f,const FIXED_VALUE_TYPE * a,const FIXED_VALUE_TYPE * b,bool sat_p)5141debfc3dSmrg do_fixed_divide (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
5151debfc3dSmrg const FIXED_VALUE_TYPE *b, bool sat_p)
5161debfc3dSmrg {
5171debfc3dSmrg bool overflow_p = false;
5181debfc3dSmrg bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
5191debfc3dSmrg int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
5201debfc3dSmrg f->mode = a->mode;
5211debfc3dSmrg if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT)
5221debfc3dSmrg {
5231debfc3dSmrg f->data = a->data.lshift (GET_MODE_FBIT (f->mode),
5241debfc3dSmrg HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
5251debfc3dSmrg f->data = f->data.div (b->data, unsigned_p, TRUNC_DIV_EXPR);
5261debfc3dSmrg overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
5271debfc3dSmrg }
5281debfc3dSmrg else
5291debfc3dSmrg {
5301debfc3dSmrg double_int pos_a, pos_b, r, s;
5311debfc3dSmrg double_int quo_r, quo_s, mod, temp;
5321debfc3dSmrg int num_of_neg = 0;
5331debfc3dSmrg int i;
5341debfc3dSmrg
5351debfc3dSmrg /* If a < 0, negate a. */
5361debfc3dSmrg if (!unsigned_p && a->data.high < 0)
5371debfc3dSmrg {
5381debfc3dSmrg pos_a = -a->data;
5391debfc3dSmrg num_of_neg ++;
5401debfc3dSmrg }
5411debfc3dSmrg else
5421debfc3dSmrg pos_a = a->data;
5431debfc3dSmrg
5441debfc3dSmrg /* If b < 0, negate b. */
5451debfc3dSmrg if (!unsigned_p && b->data.high < 0)
5461debfc3dSmrg {
5471debfc3dSmrg pos_b = -b->data;
5481debfc3dSmrg num_of_neg ++;
5491debfc3dSmrg }
5501debfc3dSmrg else
5511debfc3dSmrg pos_b = b->data;
5521debfc3dSmrg
5531debfc3dSmrg /* Left shift pos_a to {r, s} by FBIT. */
5541debfc3dSmrg if (GET_MODE_FBIT (f->mode) == HOST_BITS_PER_DOUBLE_INT)
5551debfc3dSmrg {
5561debfc3dSmrg r = pos_a;
5571debfc3dSmrg s.high = 0;
5581debfc3dSmrg s.low = 0;
5591debfc3dSmrg }
5601debfc3dSmrg else
5611debfc3dSmrg {
5621debfc3dSmrg s = pos_a.llshift (GET_MODE_FBIT (f->mode), HOST_BITS_PER_DOUBLE_INT);
5631debfc3dSmrg r = pos_a.llshift (- (HOST_BITS_PER_DOUBLE_INT
5641debfc3dSmrg - GET_MODE_FBIT (f->mode)),
5651debfc3dSmrg HOST_BITS_PER_DOUBLE_INT);
5661debfc3dSmrg }
5671debfc3dSmrg
5681debfc3dSmrg /* Divide r by pos_b to quo_r. The remainder is in mod. */
5691debfc3dSmrg quo_r = r.divmod (pos_b, 1, TRUNC_DIV_EXPR, &mod);
5701debfc3dSmrg quo_s = double_int_zero;
5711debfc3dSmrg
5721debfc3dSmrg for (i = 0; i < HOST_BITS_PER_DOUBLE_INT; i++)
5731debfc3dSmrg {
5741debfc3dSmrg /* Record the leftmost bit of mod. */
5751debfc3dSmrg int leftmost_mod = (mod.high < 0);
5761debfc3dSmrg
5771debfc3dSmrg /* Shift left mod by 1 bit. */
5781debfc3dSmrg mod = mod.lshift (1);
5791debfc3dSmrg
5801debfc3dSmrg /* Test the leftmost bit of s to add to mod. */
5811debfc3dSmrg if (s.high < 0)
5821debfc3dSmrg mod.low += 1;
5831debfc3dSmrg
5841debfc3dSmrg /* Shift left quo_s by 1 bit. */
5851debfc3dSmrg quo_s = quo_s.lshift (1);
5861debfc3dSmrg
5871debfc3dSmrg /* Try to calculate (mod - pos_b). */
5881debfc3dSmrg temp = mod - pos_b;
5891debfc3dSmrg
5901debfc3dSmrg if (leftmost_mod == 1 || mod.ucmp (pos_b) != -1)
5911debfc3dSmrg {
5921debfc3dSmrg quo_s.low += 1;
5931debfc3dSmrg mod = temp;
5941debfc3dSmrg }
5951debfc3dSmrg
5961debfc3dSmrg /* Shift left s by 1 bit. */
5971debfc3dSmrg s = s.lshift (1);
5981debfc3dSmrg
5991debfc3dSmrg }
6001debfc3dSmrg
6011debfc3dSmrg if (num_of_neg == 1)
6021debfc3dSmrg {
6031debfc3dSmrg quo_s = -quo_s;
6041debfc3dSmrg if (quo_s.high == 0 && quo_s.low == 0)
6051debfc3dSmrg quo_r = -quo_r;
6061debfc3dSmrg else
6071debfc3dSmrg {
6081debfc3dSmrg quo_r.low = ~quo_r.low;
6091debfc3dSmrg quo_r.high = ~quo_r.high;
6101debfc3dSmrg }
6111debfc3dSmrg }
6121debfc3dSmrg
6131debfc3dSmrg f->data = quo_s;
6141debfc3dSmrg overflow_p = fixed_saturate2 (f->mode, quo_r, quo_s, &f->data, sat_p);
6151debfc3dSmrg }
6161debfc3dSmrg
6171debfc3dSmrg f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p);
6181debfc3dSmrg return overflow_p;
6191debfc3dSmrg }
6201debfc3dSmrg
6211debfc3dSmrg /* Calculate F = A << B if LEFT_P. Otherwise, F = A >> B.
6221debfc3dSmrg If SAT_P, saturate the result to the max or the min.
6231debfc3dSmrg Return true, if !SAT_P and overflow. */
6241debfc3dSmrg
6251debfc3dSmrg static bool
do_fixed_shift(FIXED_VALUE_TYPE * f,const FIXED_VALUE_TYPE * a,const FIXED_VALUE_TYPE * b,bool left_p,bool sat_p)6261debfc3dSmrg do_fixed_shift (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
6271debfc3dSmrg const FIXED_VALUE_TYPE *b, bool left_p, bool sat_p)
6281debfc3dSmrg {
6291debfc3dSmrg bool overflow_p = false;
6301debfc3dSmrg bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
6311debfc3dSmrg int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
6321debfc3dSmrg f->mode = a->mode;
6331debfc3dSmrg
6341debfc3dSmrg if (b->data.low == 0)
6351debfc3dSmrg {
6361debfc3dSmrg f->data = a->data;
6371debfc3dSmrg return overflow_p;
6381debfc3dSmrg }
6391debfc3dSmrg
6401debfc3dSmrg if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT || (!left_p))
6411debfc3dSmrg {
6421debfc3dSmrg f->data = a->data.lshift (left_p ? b->data.low : -b->data.low,
6431debfc3dSmrg HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
6441debfc3dSmrg if (left_p) /* Only left shift saturates. */
6451debfc3dSmrg overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
6461debfc3dSmrg }
6471debfc3dSmrg else /* We need two double_int to store the left-shift result. */
6481debfc3dSmrg {
6491debfc3dSmrg double_int temp_high, temp_low;
6501debfc3dSmrg if (b->data.low == HOST_BITS_PER_DOUBLE_INT)
6511debfc3dSmrg {
6521debfc3dSmrg temp_high = a->data;
6531debfc3dSmrg temp_low.high = 0;
6541debfc3dSmrg temp_low.low = 0;
6551debfc3dSmrg }
6561debfc3dSmrg else
6571debfc3dSmrg {
6581debfc3dSmrg temp_low = a->data.lshift (b->data.low,
6591debfc3dSmrg HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
6601debfc3dSmrg /* Logical shift right to temp_high. */
6611debfc3dSmrg temp_high = a->data.llshift (b->data.low - HOST_BITS_PER_DOUBLE_INT,
6621debfc3dSmrg HOST_BITS_PER_DOUBLE_INT);
6631debfc3dSmrg }
6641debfc3dSmrg if (!unsigned_p && a->data.high < 0) /* Signed-extend temp_high. */
6651debfc3dSmrg temp_high = temp_high.ext (b->data.low, unsigned_p);
6661debfc3dSmrg f->data = temp_low;
6671debfc3dSmrg overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data,
6681debfc3dSmrg sat_p);
6691debfc3dSmrg }
6701debfc3dSmrg f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p);
6711debfc3dSmrg return overflow_p;
6721debfc3dSmrg }
6731debfc3dSmrg
6741debfc3dSmrg /* Calculate F = -A.
6751debfc3dSmrg If SAT_P, saturate the result to the max or the min.
6761debfc3dSmrg Return true, if !SAT_P and overflow. */
6771debfc3dSmrg
6781debfc3dSmrg static bool
do_fixed_neg(FIXED_VALUE_TYPE * f,const FIXED_VALUE_TYPE * a,bool sat_p)6791debfc3dSmrg do_fixed_neg (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, bool sat_p)
6801debfc3dSmrg {
6811debfc3dSmrg bool overflow_p = false;
6821debfc3dSmrg bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
6831debfc3dSmrg int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
6841debfc3dSmrg f->mode = a->mode;
6851debfc3dSmrg f->data = -a->data;
6861debfc3dSmrg f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p);
6871debfc3dSmrg
6881debfc3dSmrg if (unsigned_p) /* Unsigned type. */
6891debfc3dSmrg {
6901debfc3dSmrg if (f->data.low != 0 || f->data.high != 0)
6911debfc3dSmrg {
6921debfc3dSmrg if (sat_p)
6931debfc3dSmrg {
6941debfc3dSmrg f->data.low = 0;
6951debfc3dSmrg f->data.high = 0;
6961debfc3dSmrg }
6971debfc3dSmrg else
6981debfc3dSmrg overflow_p = true;
6991debfc3dSmrg }
7001debfc3dSmrg }
7011debfc3dSmrg else /* Signed type. */
7021debfc3dSmrg {
7031debfc3dSmrg if (!(f->data.high == 0 && f->data.low == 0)
7041debfc3dSmrg && f->data.high == a->data.high && f->data.low == a->data.low )
7051debfc3dSmrg {
7061debfc3dSmrg if (sat_p)
7071debfc3dSmrg {
7081debfc3dSmrg /* Saturate to the maximum by subtracting f->data by one. */
7091debfc3dSmrg f->data.low = -1;
7101debfc3dSmrg f->data.high = -1;
7111debfc3dSmrg f->data = f->data.zext (i_f_bits);
7121debfc3dSmrg }
7131debfc3dSmrg else
7141debfc3dSmrg overflow_p = true;
7151debfc3dSmrg }
7161debfc3dSmrg }
7171debfc3dSmrg return overflow_p;
7181debfc3dSmrg }
7191debfc3dSmrg
7201debfc3dSmrg /* Perform the binary or unary operation described by CODE.
7211debfc3dSmrg Note that OP0 and OP1 must have the same mode for binary operators.
7221debfc3dSmrg For a unary operation, leave OP1 NULL.
7231debfc3dSmrg Return true, if !SAT_P and overflow. */
7241debfc3dSmrg
7251debfc3dSmrg bool
fixed_arithmetic(FIXED_VALUE_TYPE * f,int icode,const FIXED_VALUE_TYPE * op0,const FIXED_VALUE_TYPE * op1,bool sat_p)7261debfc3dSmrg fixed_arithmetic (FIXED_VALUE_TYPE *f, int icode, const FIXED_VALUE_TYPE *op0,
7271debfc3dSmrg const FIXED_VALUE_TYPE *op1, bool sat_p)
7281debfc3dSmrg {
7291debfc3dSmrg switch (icode)
7301debfc3dSmrg {
7311debfc3dSmrg case NEGATE_EXPR:
7321debfc3dSmrg return do_fixed_neg (f, op0, sat_p);
7331debfc3dSmrg
7341debfc3dSmrg case PLUS_EXPR:
7351debfc3dSmrg gcc_assert (op0->mode == op1->mode);
7361debfc3dSmrg return do_fixed_add (f, op0, op1, false, sat_p);
7371debfc3dSmrg
7381debfc3dSmrg case MINUS_EXPR:
7391debfc3dSmrg gcc_assert (op0->mode == op1->mode);
7401debfc3dSmrg return do_fixed_add (f, op0, op1, true, sat_p);
7411debfc3dSmrg
7421debfc3dSmrg case MULT_EXPR:
7431debfc3dSmrg gcc_assert (op0->mode == op1->mode);
7441debfc3dSmrg return do_fixed_multiply (f, op0, op1, sat_p);
7451debfc3dSmrg
7461debfc3dSmrg case TRUNC_DIV_EXPR:
7471debfc3dSmrg gcc_assert (op0->mode == op1->mode);
7481debfc3dSmrg return do_fixed_divide (f, op0, op1, sat_p);
7491debfc3dSmrg
7501debfc3dSmrg case LSHIFT_EXPR:
7511debfc3dSmrg return do_fixed_shift (f, op0, op1, true, sat_p);
7521debfc3dSmrg
7531debfc3dSmrg case RSHIFT_EXPR:
7541debfc3dSmrg return do_fixed_shift (f, op0, op1, false, sat_p);
7551debfc3dSmrg
7561debfc3dSmrg default:
7571debfc3dSmrg gcc_unreachable ();
7581debfc3dSmrg }
7591debfc3dSmrg return false;
7601debfc3dSmrg }
7611debfc3dSmrg
7621debfc3dSmrg /* Compare fixed-point values by tree_code.
7631debfc3dSmrg Note that OP0 and OP1 must have the same mode. */
7641debfc3dSmrg
7651debfc3dSmrg bool
fixed_compare(int icode,const FIXED_VALUE_TYPE * op0,const FIXED_VALUE_TYPE * op1)7661debfc3dSmrg fixed_compare (int icode, const FIXED_VALUE_TYPE *op0,
7671debfc3dSmrg const FIXED_VALUE_TYPE *op1)
7681debfc3dSmrg {
7691debfc3dSmrg enum tree_code code = (enum tree_code) icode;
7701debfc3dSmrg gcc_assert (op0->mode == op1->mode);
7711debfc3dSmrg
7721debfc3dSmrg switch (code)
7731debfc3dSmrg {
7741debfc3dSmrg case NE_EXPR:
7751debfc3dSmrg return op0->data != op1->data;
7761debfc3dSmrg
7771debfc3dSmrg case EQ_EXPR:
7781debfc3dSmrg return op0->data == op1->data;
7791debfc3dSmrg
7801debfc3dSmrg case LT_EXPR:
7811debfc3dSmrg return op0->data.cmp (op1->data,
7821debfc3dSmrg UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) == -1;
7831debfc3dSmrg
7841debfc3dSmrg case LE_EXPR:
7851debfc3dSmrg return op0->data.cmp (op1->data,
7861debfc3dSmrg UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) != 1;
7871debfc3dSmrg
7881debfc3dSmrg case GT_EXPR:
7891debfc3dSmrg return op0->data.cmp (op1->data,
7901debfc3dSmrg UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) == 1;
7911debfc3dSmrg
7921debfc3dSmrg case GE_EXPR:
7931debfc3dSmrg return op0->data.cmp (op1->data,
7941debfc3dSmrg UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) != -1;
7951debfc3dSmrg
7961debfc3dSmrg default:
7971debfc3dSmrg gcc_unreachable ();
7981debfc3dSmrg }
7991debfc3dSmrg }
8001debfc3dSmrg
8011debfc3dSmrg /* Extend or truncate to a new mode.
8021debfc3dSmrg If SAT_P, saturate the result to the max or the min.
8031debfc3dSmrg Return true, if !SAT_P and overflow. */
8041debfc3dSmrg
8051debfc3dSmrg bool
fixed_convert(FIXED_VALUE_TYPE * f,scalar_mode mode,const FIXED_VALUE_TYPE * a,bool sat_p)806a2dc1f3fSmrg fixed_convert (FIXED_VALUE_TYPE *f, scalar_mode mode,
8071debfc3dSmrg const FIXED_VALUE_TYPE *a, bool sat_p)
8081debfc3dSmrg {
8091debfc3dSmrg bool overflow_p = false;
8101debfc3dSmrg if (mode == a->mode)
8111debfc3dSmrg {
8121debfc3dSmrg *f = *a;
8131debfc3dSmrg return overflow_p;
8141debfc3dSmrg }
8151debfc3dSmrg
8161debfc3dSmrg if (GET_MODE_FBIT (mode) > GET_MODE_FBIT (a->mode))
8171debfc3dSmrg {
8181debfc3dSmrg /* Left shift a to temp_high, temp_low based on a->mode. */
8191debfc3dSmrg double_int temp_high, temp_low;
8201debfc3dSmrg int amount = GET_MODE_FBIT (mode) - GET_MODE_FBIT (a->mode);
8211debfc3dSmrg temp_low = a->data.lshift (amount,
8221debfc3dSmrg HOST_BITS_PER_DOUBLE_INT,
8231debfc3dSmrg SIGNED_FIXED_POINT_MODE_P (a->mode));
8241debfc3dSmrg /* Logical shift right to temp_high. */
8251debfc3dSmrg temp_high = a->data.llshift (amount - HOST_BITS_PER_DOUBLE_INT,
8261debfc3dSmrg HOST_BITS_PER_DOUBLE_INT);
8271debfc3dSmrg if (SIGNED_FIXED_POINT_MODE_P (a->mode)
8281debfc3dSmrg && a->data.high < 0) /* Signed-extend temp_high. */
8291debfc3dSmrg temp_high = temp_high.sext (amount);
8301debfc3dSmrg f->mode = mode;
8311debfc3dSmrg f->data = temp_low;
8321debfc3dSmrg if (SIGNED_FIXED_POINT_MODE_P (a->mode) ==
8331debfc3dSmrg SIGNED_FIXED_POINT_MODE_P (f->mode))
8341debfc3dSmrg overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data,
8351debfc3dSmrg sat_p);
8361debfc3dSmrg else
8371debfc3dSmrg {
8381debfc3dSmrg /* Take care of the cases when converting between signed and
8391debfc3dSmrg unsigned. */
8401debfc3dSmrg if (SIGNED_FIXED_POINT_MODE_P (a->mode))
8411debfc3dSmrg {
8421debfc3dSmrg /* Signed -> Unsigned. */
8431debfc3dSmrg if (a->data.high < 0)
8441debfc3dSmrg {
8451debfc3dSmrg if (sat_p)
8461debfc3dSmrg {
8471debfc3dSmrg f->data.low = 0; /* Set to zero. */
8481debfc3dSmrg f->data.high = 0; /* Set to zero. */
8491debfc3dSmrg }
8501debfc3dSmrg else
8511debfc3dSmrg overflow_p = true;
8521debfc3dSmrg }
8531debfc3dSmrg else
8541debfc3dSmrg overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low,
8551debfc3dSmrg &f->data, sat_p);
8561debfc3dSmrg }
8571debfc3dSmrg else
8581debfc3dSmrg {
8591debfc3dSmrg /* Unsigned -> Signed. */
8601debfc3dSmrg if (temp_high.high < 0)
8611debfc3dSmrg {
8621debfc3dSmrg if (sat_p)
8631debfc3dSmrg {
8641debfc3dSmrg /* Set to maximum. */
8651debfc3dSmrg f->data.low = -1; /* Set to all ones. */
8661debfc3dSmrg f->data.high = -1; /* Set to all ones. */
8671debfc3dSmrg f->data = f->data.zext (GET_MODE_FBIT (f->mode)
8681debfc3dSmrg + GET_MODE_IBIT (f->mode));
8691debfc3dSmrg /* Clear the sign. */
8701debfc3dSmrg }
8711debfc3dSmrg else
8721debfc3dSmrg overflow_p = true;
8731debfc3dSmrg }
8741debfc3dSmrg else
8751debfc3dSmrg overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low,
8761debfc3dSmrg &f->data, sat_p);
8771debfc3dSmrg }
8781debfc3dSmrg }
8791debfc3dSmrg }
8801debfc3dSmrg else
8811debfc3dSmrg {
8821debfc3dSmrg /* Right shift a to temp based on a->mode. */
8831debfc3dSmrg double_int temp;
8841debfc3dSmrg temp = a->data.lshift (GET_MODE_FBIT (mode) - GET_MODE_FBIT (a->mode),
8851debfc3dSmrg HOST_BITS_PER_DOUBLE_INT,
8861debfc3dSmrg SIGNED_FIXED_POINT_MODE_P (a->mode));
8871debfc3dSmrg f->mode = mode;
8881debfc3dSmrg f->data = temp;
8891debfc3dSmrg if (SIGNED_FIXED_POINT_MODE_P (a->mode) ==
8901debfc3dSmrg SIGNED_FIXED_POINT_MODE_P (f->mode))
8911debfc3dSmrg overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
8921debfc3dSmrg else
8931debfc3dSmrg {
8941debfc3dSmrg /* Take care of the cases when converting between signed and
8951debfc3dSmrg unsigned. */
8961debfc3dSmrg if (SIGNED_FIXED_POINT_MODE_P (a->mode))
8971debfc3dSmrg {
8981debfc3dSmrg /* Signed -> Unsigned. */
8991debfc3dSmrg if (a->data.high < 0)
9001debfc3dSmrg {
9011debfc3dSmrg if (sat_p)
9021debfc3dSmrg {
9031debfc3dSmrg f->data.low = 0; /* Set to zero. */
9041debfc3dSmrg f->data.high = 0; /* Set to zero. */
9051debfc3dSmrg }
9061debfc3dSmrg else
9071debfc3dSmrg overflow_p = true;
9081debfc3dSmrg }
9091debfc3dSmrg else
9101debfc3dSmrg overflow_p = fixed_saturate1 (f->mode, f->data, &f->data,
9111debfc3dSmrg sat_p);
9121debfc3dSmrg }
9131debfc3dSmrg else
9141debfc3dSmrg {
9151debfc3dSmrg /* Unsigned -> Signed. */
9161debfc3dSmrg if (temp.high < 0)
9171debfc3dSmrg {
9181debfc3dSmrg if (sat_p)
9191debfc3dSmrg {
9201debfc3dSmrg /* Set to maximum. */
9211debfc3dSmrg f->data.low = -1; /* Set to all ones. */
9221debfc3dSmrg f->data.high = -1; /* Set to all ones. */
9231debfc3dSmrg f->data = f->data.zext (GET_MODE_FBIT (f->mode)
9241debfc3dSmrg + GET_MODE_IBIT (f->mode));
9251debfc3dSmrg /* Clear the sign. */
9261debfc3dSmrg }
9271debfc3dSmrg else
9281debfc3dSmrg overflow_p = true;
9291debfc3dSmrg }
9301debfc3dSmrg else
9311debfc3dSmrg overflow_p = fixed_saturate1 (f->mode, f->data, &f->data,
9321debfc3dSmrg sat_p);
9331debfc3dSmrg }
9341debfc3dSmrg }
9351debfc3dSmrg }
9361debfc3dSmrg
9371debfc3dSmrg f->data = f->data.ext (SIGNED_FIXED_POINT_MODE_P (f->mode)
9381debfc3dSmrg + GET_MODE_FBIT (f->mode)
9391debfc3dSmrg + GET_MODE_IBIT (f->mode),
9401debfc3dSmrg UNSIGNED_FIXED_POINT_MODE_P (f->mode));
9411debfc3dSmrg return overflow_p;
9421debfc3dSmrg }
9431debfc3dSmrg
9441debfc3dSmrg /* Convert to a new fixed-point mode from an integer.
9451debfc3dSmrg If UNSIGNED_P, this integer is unsigned.
9461debfc3dSmrg If SAT_P, saturate the result to the max or the min.
9471debfc3dSmrg Return true, if !SAT_P and overflow. */
9481debfc3dSmrg
9491debfc3dSmrg bool
fixed_convert_from_int(FIXED_VALUE_TYPE * f,scalar_mode mode,double_int a,bool unsigned_p,bool sat_p)950a2dc1f3fSmrg fixed_convert_from_int (FIXED_VALUE_TYPE *f, scalar_mode mode,
9511debfc3dSmrg double_int a, bool unsigned_p, bool sat_p)
9521debfc3dSmrg {
9531debfc3dSmrg bool overflow_p = false;
9541debfc3dSmrg /* Left shift a to temp_high, temp_low. */
9551debfc3dSmrg double_int temp_high, temp_low;
9561debfc3dSmrg int amount = GET_MODE_FBIT (mode);
9571debfc3dSmrg if (amount == HOST_BITS_PER_DOUBLE_INT)
9581debfc3dSmrg {
9591debfc3dSmrg temp_high = a;
9601debfc3dSmrg temp_low.low = 0;
9611debfc3dSmrg temp_low.high = 0;
9621debfc3dSmrg }
9631debfc3dSmrg else
9641debfc3dSmrg {
9651debfc3dSmrg temp_low = a.llshift (amount, HOST_BITS_PER_DOUBLE_INT);
9661debfc3dSmrg
9671debfc3dSmrg /* Logical shift right to temp_high. */
9681debfc3dSmrg temp_high = a.llshift (amount - HOST_BITS_PER_DOUBLE_INT,
9691debfc3dSmrg HOST_BITS_PER_DOUBLE_INT);
9701debfc3dSmrg }
9711debfc3dSmrg if (!unsigned_p && a.high < 0) /* Signed-extend temp_high. */
9721debfc3dSmrg temp_high = temp_high.sext (amount);
9731debfc3dSmrg
9741debfc3dSmrg f->mode = mode;
9751debfc3dSmrg f->data = temp_low;
9761debfc3dSmrg
9771debfc3dSmrg if (unsigned_p == UNSIGNED_FIXED_POINT_MODE_P (f->mode))
9781debfc3dSmrg overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data,
9791debfc3dSmrg sat_p);
9801debfc3dSmrg else
9811debfc3dSmrg {
9821debfc3dSmrg /* Take care of the cases when converting between signed and unsigned. */
9831debfc3dSmrg if (!unsigned_p)
9841debfc3dSmrg {
9851debfc3dSmrg /* Signed -> Unsigned. */
9861debfc3dSmrg if (a.high < 0)
9871debfc3dSmrg {
9881debfc3dSmrg if (sat_p)
9891debfc3dSmrg {
9901debfc3dSmrg f->data.low = 0; /* Set to zero. */
9911debfc3dSmrg f->data.high = 0; /* Set to zero. */
9921debfc3dSmrg }
9931debfc3dSmrg else
9941debfc3dSmrg overflow_p = true;
9951debfc3dSmrg }
9961debfc3dSmrg else
9971debfc3dSmrg overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low,
9981debfc3dSmrg &f->data, sat_p);
9991debfc3dSmrg }
10001debfc3dSmrg else
10011debfc3dSmrg {
10021debfc3dSmrg /* Unsigned -> Signed. */
10031debfc3dSmrg if (temp_high.high < 0)
10041debfc3dSmrg {
10051debfc3dSmrg if (sat_p)
10061debfc3dSmrg {
10071debfc3dSmrg /* Set to maximum. */
10081debfc3dSmrg f->data.low = -1; /* Set to all ones. */
10091debfc3dSmrg f->data.high = -1; /* Set to all ones. */
10101debfc3dSmrg f->data = f->data.zext (GET_MODE_FBIT (f->mode)
10111debfc3dSmrg + GET_MODE_IBIT (f->mode));
10121debfc3dSmrg /* Clear the sign. */
10131debfc3dSmrg }
10141debfc3dSmrg else
10151debfc3dSmrg overflow_p = true;
10161debfc3dSmrg }
10171debfc3dSmrg else
10181debfc3dSmrg overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low,
10191debfc3dSmrg &f->data, sat_p);
10201debfc3dSmrg }
10211debfc3dSmrg }
10221debfc3dSmrg f->data = f->data.ext (SIGNED_FIXED_POINT_MODE_P (f->mode)
10231debfc3dSmrg + GET_MODE_FBIT (f->mode)
10241debfc3dSmrg + GET_MODE_IBIT (f->mode),
10251debfc3dSmrg UNSIGNED_FIXED_POINT_MODE_P (f->mode));
10261debfc3dSmrg return overflow_p;
10271debfc3dSmrg }
10281debfc3dSmrg
10291debfc3dSmrg /* Convert to a new fixed-point mode from a real.
10301debfc3dSmrg If SAT_P, saturate the result to the max or the min.
10311debfc3dSmrg Return true, if !SAT_P and overflow. */
10321debfc3dSmrg
10331debfc3dSmrg bool
fixed_convert_from_real(FIXED_VALUE_TYPE * f,scalar_mode mode,const REAL_VALUE_TYPE * a,bool sat_p)1034a2dc1f3fSmrg fixed_convert_from_real (FIXED_VALUE_TYPE *f, scalar_mode mode,
10351debfc3dSmrg const REAL_VALUE_TYPE *a, bool sat_p)
10361debfc3dSmrg {
10371debfc3dSmrg bool overflow_p = false;
10381debfc3dSmrg REAL_VALUE_TYPE real_value, fixed_value, base_value;
10391debfc3dSmrg bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode);
10401debfc3dSmrg int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode);
10411debfc3dSmrg unsigned int fbit = GET_MODE_FBIT (mode);
10421debfc3dSmrg enum fixed_value_range_code temp;
10431debfc3dSmrg bool fail;
10441debfc3dSmrg
10451debfc3dSmrg real_value = *a;
10461debfc3dSmrg f->mode = mode;
10471debfc3dSmrg real_2expN (&base_value, fbit, VOIDmode);
10481debfc3dSmrg real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value);
10491debfc3dSmrg
10501debfc3dSmrg wide_int w = real_to_integer (&fixed_value, &fail,
10511debfc3dSmrg GET_MODE_PRECISION (mode));
10521debfc3dSmrg f->data.low = w.ulow ();
10531debfc3dSmrg f->data.high = w.elt (1);
10541debfc3dSmrg temp = check_real_for_fixed_mode (&real_value, mode);
10551debfc3dSmrg if (temp == FIXED_UNDERFLOW) /* Minimum. */
10561debfc3dSmrg {
10571debfc3dSmrg if (sat_p)
10581debfc3dSmrg {
10591debfc3dSmrg if (unsigned_p)
10601debfc3dSmrg {
10611debfc3dSmrg f->data.low = 0;
10621debfc3dSmrg f->data.high = 0;
10631debfc3dSmrg }
10641debfc3dSmrg else
10651debfc3dSmrg {
10661debfc3dSmrg f->data.low = 1;
10671debfc3dSmrg f->data.high = 0;
10681debfc3dSmrg f->data = f->data.alshift (i_f_bits, HOST_BITS_PER_DOUBLE_INT);
10691debfc3dSmrg f->data = f->data.sext (1 + i_f_bits);
10701debfc3dSmrg }
10711debfc3dSmrg }
10721debfc3dSmrg else
10731debfc3dSmrg overflow_p = true;
10741debfc3dSmrg }
10751debfc3dSmrg else if (temp == FIXED_GT_MAX_EPS || temp == FIXED_MAX_EPS) /* Maximum. */
10761debfc3dSmrg {
10771debfc3dSmrg if (sat_p)
10781debfc3dSmrg {
10791debfc3dSmrg f->data.low = -1;
10801debfc3dSmrg f->data.high = -1;
10811debfc3dSmrg f->data = f->data.zext (i_f_bits);
10821debfc3dSmrg }
10831debfc3dSmrg else
10841debfc3dSmrg overflow_p = true;
10851debfc3dSmrg }
10861debfc3dSmrg f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p);
10871debfc3dSmrg return overflow_p;
10881debfc3dSmrg }
10891debfc3dSmrg
10901debfc3dSmrg /* Convert to a new real mode from a fixed-point. */
10911debfc3dSmrg
10921debfc3dSmrg void
real_convert_from_fixed(REAL_VALUE_TYPE * r,scalar_mode mode,const FIXED_VALUE_TYPE * f)1093a2dc1f3fSmrg real_convert_from_fixed (REAL_VALUE_TYPE *r, scalar_mode mode,
10941debfc3dSmrg const FIXED_VALUE_TYPE *f)
10951debfc3dSmrg {
10961debfc3dSmrg REAL_VALUE_TYPE base_value, fixed_value, real_value;
10971debfc3dSmrg
10981debfc3dSmrg signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f->mode) ? UNSIGNED : SIGNED;
10991debfc3dSmrg real_2expN (&base_value, GET_MODE_FBIT (f->mode), VOIDmode);
11001debfc3dSmrg real_from_integer (&fixed_value, VOIDmode,
11011debfc3dSmrg wide_int::from (f->data, GET_MODE_PRECISION (f->mode),
11021debfc3dSmrg sgn), sgn);
11031debfc3dSmrg real_arithmetic (&real_value, RDIV_EXPR, &fixed_value, &base_value);
11041debfc3dSmrg real_convert (r, mode, &real_value);
11051debfc3dSmrg }
11061debfc3dSmrg
11071debfc3dSmrg /* Determine whether a fixed-point value F is negative. */
11081debfc3dSmrg
11091debfc3dSmrg bool
fixed_isneg(const FIXED_VALUE_TYPE * f)11101debfc3dSmrg fixed_isneg (const FIXED_VALUE_TYPE *f)
11111debfc3dSmrg {
11121debfc3dSmrg if (SIGNED_FIXED_POINT_MODE_P (f->mode))
11131debfc3dSmrg {
11141debfc3dSmrg int i_f_bits = GET_MODE_IBIT (f->mode) + GET_MODE_FBIT (f->mode);
11151debfc3dSmrg int sign_bit = get_fixed_sign_bit (f->data, i_f_bits);
11161debfc3dSmrg if (sign_bit == 1)
11171debfc3dSmrg return true;
11181debfc3dSmrg }
11191debfc3dSmrg
11201debfc3dSmrg return false;
11211debfc3dSmrg }
1122