xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/fixed-value.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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