xref: /dragonfly/contrib/gcc-8.0/gcc/fixed-value.c (revision 38fd1498)
1*38fd1498Szrj /* Fixed-point arithmetic support.
2*38fd1498Szrj    Copyright (C) 2006-2018 Free Software Foundation, Inc.
3*38fd1498Szrj 
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj 
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
7*38fd1498Szrj the terms of the GNU General Public License as published by the Free
8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj version.
10*38fd1498Szrj 
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*38fd1498Szrj for more details.
15*38fd1498Szrj 
16*38fd1498Szrj You should have received a copy of the GNU General Public License
17*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
19*38fd1498Szrj 
20*38fd1498Szrj #include "config.h"
21*38fd1498Szrj #include "system.h"
22*38fd1498Szrj #include "coretypes.h"
23*38fd1498Szrj #include "tm.h"
24*38fd1498Szrj #include "tree.h"
25*38fd1498Szrj #include "diagnostic-core.h"
26*38fd1498Szrj 
27*38fd1498Szrj /* Compare two fixed objects for bitwise identity.  */
28*38fd1498Szrj 
29*38fd1498Szrj bool
fixed_identical(const FIXED_VALUE_TYPE * a,const FIXED_VALUE_TYPE * b)30*38fd1498Szrj fixed_identical (const FIXED_VALUE_TYPE *a, const FIXED_VALUE_TYPE *b)
31*38fd1498Szrj {
32*38fd1498Szrj   return (a->mode == b->mode
33*38fd1498Szrj 	  && a->data.high == b->data.high
34*38fd1498Szrj 	  && a->data.low == b->data.low);
35*38fd1498Szrj }
36*38fd1498Szrj 
37*38fd1498Szrj /* Calculate a hash value.  */
38*38fd1498Szrj 
39*38fd1498Szrj unsigned int
fixed_hash(const FIXED_VALUE_TYPE * f)40*38fd1498Szrj fixed_hash (const FIXED_VALUE_TYPE *f)
41*38fd1498Szrj {
42*38fd1498Szrj   return (unsigned int) (f->data.low ^ f->data.high);
43*38fd1498Szrj }
44*38fd1498Szrj 
45*38fd1498Szrj /* Define the enum code for the range of the fixed-point value.  */
46*38fd1498Szrj enum fixed_value_range_code {
47*38fd1498Szrj   FIXED_OK,		/* The value is within the range.  */
48*38fd1498Szrj   FIXED_UNDERFLOW,	/* The value is less than the minimum.  */
49*38fd1498Szrj   FIXED_GT_MAX_EPS,	/* The value is greater than the maximum, but not equal
50*38fd1498Szrj 			   to the maximum plus the epsilon.  */
51*38fd1498Szrj   FIXED_MAX_EPS		/* The value equals the maximum plus the epsilon.  */
52*38fd1498Szrj };
53*38fd1498Szrj 
54*38fd1498Szrj /* Check REAL_VALUE against the range of the fixed-point mode.
55*38fd1498Szrj    Return FIXED_OK, if it is within the range.
56*38fd1498Szrj           FIXED_UNDERFLOW, if it is less than the minimum.
57*38fd1498Szrj           FIXED_GT_MAX_EPS, if it is greater than the maximum, but not equal to
58*38fd1498Szrj 	    the maximum plus the epsilon.
59*38fd1498Szrj           FIXED_MAX_EPS, if it is equal to the maximum plus the epsilon.  */
60*38fd1498Szrj 
61*38fd1498Szrj static enum fixed_value_range_code
check_real_for_fixed_mode(REAL_VALUE_TYPE * real_value,machine_mode mode)62*38fd1498Szrj check_real_for_fixed_mode (REAL_VALUE_TYPE *real_value, machine_mode mode)
63*38fd1498Szrj {
64*38fd1498Szrj   REAL_VALUE_TYPE max_value, min_value, epsilon_value;
65*38fd1498Szrj 
66*38fd1498Szrj   real_2expN (&max_value, GET_MODE_IBIT (mode), VOIDmode);
67*38fd1498Szrj   real_2expN (&epsilon_value, -GET_MODE_FBIT (mode), VOIDmode);
68*38fd1498Szrj 
69*38fd1498Szrj   if (SIGNED_FIXED_POINT_MODE_P (mode))
70*38fd1498Szrj     min_value = real_value_negate (&max_value);
71*38fd1498Szrj   else
72*38fd1498Szrj     real_from_string (&min_value, "0.0");
73*38fd1498Szrj 
74*38fd1498Szrj   if (real_compare (LT_EXPR, real_value, &min_value))
75*38fd1498Szrj     return FIXED_UNDERFLOW;
76*38fd1498Szrj   if (real_compare (EQ_EXPR, real_value, &max_value))
77*38fd1498Szrj     return FIXED_MAX_EPS;
78*38fd1498Szrj   real_arithmetic (&max_value, MINUS_EXPR, &max_value, &epsilon_value);
79*38fd1498Szrj   if (real_compare (GT_EXPR, real_value, &max_value))
80*38fd1498Szrj     return FIXED_GT_MAX_EPS;
81*38fd1498Szrj   return FIXED_OK;
82*38fd1498Szrj }
83*38fd1498Szrj 
84*38fd1498Szrj 
85*38fd1498Szrj /* Construct a CONST_FIXED from a bit payload and machine mode MODE.
86*38fd1498Szrj    The bits in PAYLOAD are sign-extended/zero-extended according to MODE.  */
87*38fd1498Szrj 
88*38fd1498Szrj FIXED_VALUE_TYPE
fixed_from_double_int(double_int payload,scalar_mode mode)89*38fd1498Szrj fixed_from_double_int (double_int payload, scalar_mode mode)
90*38fd1498Szrj {
91*38fd1498Szrj   FIXED_VALUE_TYPE value;
92*38fd1498Szrj 
93*38fd1498Szrj   gcc_assert (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_DOUBLE_INT);
94*38fd1498Szrj 
95*38fd1498Szrj   if (SIGNED_SCALAR_FIXED_POINT_MODE_P (mode))
96*38fd1498Szrj     value.data = payload.sext (1 + GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode));
97*38fd1498Szrj   else if (UNSIGNED_SCALAR_FIXED_POINT_MODE_P (mode))
98*38fd1498Szrj     value.data = payload.zext (GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode));
99*38fd1498Szrj   else
100*38fd1498Szrj     gcc_unreachable ();
101*38fd1498Szrj 
102*38fd1498Szrj   value.mode = mode;
103*38fd1498Szrj 
104*38fd1498Szrj   return value;
105*38fd1498Szrj }
106*38fd1498Szrj 
107*38fd1498Szrj 
108*38fd1498Szrj /* Initialize from a decimal or hexadecimal string.  */
109*38fd1498Szrj 
110*38fd1498Szrj void
fixed_from_string(FIXED_VALUE_TYPE * f,const char * str,scalar_mode mode)111*38fd1498Szrj fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, scalar_mode mode)
112*38fd1498Szrj {
113*38fd1498Szrj   REAL_VALUE_TYPE real_value, fixed_value, base_value;
114*38fd1498Szrj   unsigned int fbit;
115*38fd1498Szrj   enum fixed_value_range_code temp;
116*38fd1498Szrj   bool fail;
117*38fd1498Szrj 
118*38fd1498Szrj   f->mode = mode;
119*38fd1498Szrj   fbit = GET_MODE_FBIT (mode);
120*38fd1498Szrj 
121*38fd1498Szrj   real_from_string (&real_value, str);
122*38fd1498Szrj   temp = check_real_for_fixed_mode (&real_value, f->mode);
123*38fd1498Szrj   /* We don't want to warn the case when the _Fract value is 1.0.  */
124*38fd1498Szrj   if (temp == FIXED_UNDERFLOW
125*38fd1498Szrj       || temp == FIXED_GT_MAX_EPS
126*38fd1498Szrj       || (temp == FIXED_MAX_EPS && ALL_ACCUM_MODE_P (f->mode)))
127*38fd1498Szrj     warning (OPT_Woverflow,
128*38fd1498Szrj 	     "large fixed-point constant implicitly truncated to fixed-point type");
129*38fd1498Szrj   real_2expN (&base_value, fbit, VOIDmode);
130*38fd1498Szrj   real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value);
131*38fd1498Szrj   wide_int w = real_to_integer (&fixed_value, &fail,
132*38fd1498Szrj 				GET_MODE_PRECISION (mode));
133*38fd1498Szrj   f->data.low = w.ulow ();
134*38fd1498Szrj   f->data.high = w.elt (1);
135*38fd1498Szrj 
136*38fd1498Szrj   if (temp == FIXED_MAX_EPS && ALL_FRACT_MODE_P (f->mode))
137*38fd1498Szrj     {
138*38fd1498Szrj       /* From the spec, we need to evaluate 1 to the maximal value.  */
139*38fd1498Szrj       f->data.low = -1;
140*38fd1498Szrj       f->data.high = -1;
141*38fd1498Szrj       f->data = f->data.zext (GET_MODE_FBIT (f->mode)
142*38fd1498Szrj 				+ GET_MODE_IBIT (f->mode));
143*38fd1498Szrj     }
144*38fd1498Szrj   else
145*38fd1498Szrj     f->data = f->data.ext (SIGNED_FIXED_POINT_MODE_P (f->mode)
146*38fd1498Szrj 			      + GET_MODE_FBIT (f->mode)
147*38fd1498Szrj 			      + GET_MODE_IBIT (f->mode),
148*38fd1498Szrj 			      UNSIGNED_FIXED_POINT_MODE_P (f->mode));
149*38fd1498Szrj }
150*38fd1498Szrj 
151*38fd1498Szrj /* Render F as a decimal floating point constant.  */
152*38fd1498Szrj 
153*38fd1498Szrj void
fixed_to_decimal(char * str,const FIXED_VALUE_TYPE * f_orig,size_t buf_size)154*38fd1498Szrj fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig,
155*38fd1498Szrj 		  size_t buf_size)
156*38fd1498Szrj {
157*38fd1498Szrj   REAL_VALUE_TYPE real_value, base_value, fixed_value;
158*38fd1498Szrj 
159*38fd1498Szrj   signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode) ? UNSIGNED : SIGNED;
160*38fd1498Szrj   real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), VOIDmode);
161*38fd1498Szrj   real_from_integer (&real_value, VOIDmode,
162*38fd1498Szrj 		     wide_int::from (f_orig->data,
163*38fd1498Szrj 				     GET_MODE_PRECISION (f_orig->mode), sgn),
164*38fd1498Szrj 		     sgn);
165*38fd1498Szrj   real_arithmetic (&fixed_value, RDIV_EXPR, &real_value, &base_value);
166*38fd1498Szrj   real_to_decimal (str, &fixed_value, buf_size, 0, 1);
167*38fd1498Szrj }
168*38fd1498Szrj 
169*38fd1498Szrj /* If SAT_P, saturate A to the maximum or the minimum, and save to *F based on
170*38fd1498Szrj    the machine mode MODE.
171*38fd1498Szrj    Do not modify *F otherwise.
172*38fd1498Szrj    This function assumes the width of double_int is greater than the width
173*38fd1498Szrj    of the fixed-point value (the sum of a possible sign bit, possible ibits,
174*38fd1498Szrj    and fbits).
175*38fd1498Szrj    Return true, if !SAT_P and overflow.  */
176*38fd1498Szrj 
177*38fd1498Szrj static bool
fixed_saturate1(machine_mode mode,double_int a,double_int * f,bool sat_p)178*38fd1498Szrj fixed_saturate1 (machine_mode mode, double_int a, double_int *f,
179*38fd1498Szrj 		 bool sat_p)
180*38fd1498Szrj {
181*38fd1498Szrj   bool overflow_p = false;
182*38fd1498Szrj   bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode);
183*38fd1498Szrj   int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode);
184*38fd1498Szrj 
185*38fd1498Szrj   if (unsigned_p) /* Unsigned type.  */
186*38fd1498Szrj     {
187*38fd1498Szrj       double_int max;
188*38fd1498Szrj       max.low = -1;
189*38fd1498Szrj       max.high = -1;
190*38fd1498Szrj       max = max.zext (i_f_bits);
191*38fd1498Szrj       if (a.ugt (max))
192*38fd1498Szrj 	{
193*38fd1498Szrj 	  if (sat_p)
194*38fd1498Szrj 	    *f = max;
195*38fd1498Szrj 	  else
196*38fd1498Szrj 	    overflow_p = true;
197*38fd1498Szrj 	}
198*38fd1498Szrj     }
199*38fd1498Szrj   else /* Signed type.  */
200*38fd1498Szrj     {
201*38fd1498Szrj       double_int max, min;
202*38fd1498Szrj       max.high = -1;
203*38fd1498Szrj       max.low = -1;
204*38fd1498Szrj       max = max.zext (i_f_bits);
205*38fd1498Szrj       min.high = 0;
206*38fd1498Szrj       min.low = 1;
207*38fd1498Szrj       min = min.alshift (i_f_bits, HOST_BITS_PER_DOUBLE_INT);
208*38fd1498Szrj       min = min.sext (1 + i_f_bits);
209*38fd1498Szrj       if (a.sgt (max))
210*38fd1498Szrj 	{
211*38fd1498Szrj 	  if (sat_p)
212*38fd1498Szrj 	    *f = max;
213*38fd1498Szrj 	  else
214*38fd1498Szrj 	    overflow_p = true;
215*38fd1498Szrj 	}
216*38fd1498Szrj       else if (a.slt (min))
217*38fd1498Szrj 	{
218*38fd1498Szrj 	  if (sat_p)
219*38fd1498Szrj 	    *f = min;
220*38fd1498Szrj 	  else
221*38fd1498Szrj 	    overflow_p = true;
222*38fd1498Szrj 	}
223*38fd1498Szrj     }
224*38fd1498Szrj   return overflow_p;
225*38fd1498Szrj }
226*38fd1498Szrj 
227*38fd1498Szrj /* If SAT_P, saturate {A_HIGH, A_LOW} to the maximum or the minimum, and
228*38fd1498Szrj    save to *F based on the machine mode MODE.
229*38fd1498Szrj    Do not modify *F otherwise.
230*38fd1498Szrj    This function assumes the width of two double_int is greater than the width
231*38fd1498Szrj    of the fixed-point value (the sum of a possible sign bit, possible ibits,
232*38fd1498Szrj    and fbits).
233*38fd1498Szrj    Return true, if !SAT_P and overflow.  */
234*38fd1498Szrj 
235*38fd1498Szrj static bool
fixed_saturate2(machine_mode mode,double_int a_high,double_int a_low,double_int * f,bool sat_p)236*38fd1498Szrj fixed_saturate2 (machine_mode mode, double_int a_high, double_int a_low,
237*38fd1498Szrj 		 double_int *f, bool sat_p)
238*38fd1498Szrj {
239*38fd1498Szrj   bool overflow_p = false;
240*38fd1498Szrj   bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode);
241*38fd1498Szrj   int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode);
242*38fd1498Szrj 
243*38fd1498Szrj   if (unsigned_p) /* Unsigned type.  */
244*38fd1498Szrj     {
245*38fd1498Szrj       double_int max_r, max_s;
246*38fd1498Szrj       max_r.high = 0;
247*38fd1498Szrj       max_r.low = 0;
248*38fd1498Szrj       max_s.high = -1;
249*38fd1498Szrj       max_s.low = -1;
250*38fd1498Szrj       max_s = max_s.zext (i_f_bits);
251*38fd1498Szrj       if (a_high.ugt (max_r)
252*38fd1498Szrj 	  || (a_high == max_r &&
253*38fd1498Szrj 	      a_low.ugt (max_s)))
254*38fd1498Szrj 	{
255*38fd1498Szrj 	  if (sat_p)
256*38fd1498Szrj 	    *f = max_s;
257*38fd1498Szrj 	  else
258*38fd1498Szrj 	    overflow_p = true;
259*38fd1498Szrj 	}
260*38fd1498Szrj     }
261*38fd1498Szrj   else /* Signed type.  */
262*38fd1498Szrj     {
263*38fd1498Szrj       double_int max_r, max_s, min_r, min_s;
264*38fd1498Szrj       max_r.high = 0;
265*38fd1498Szrj       max_r.low = 0;
266*38fd1498Szrj       max_s.high = -1;
267*38fd1498Szrj       max_s.low = -1;
268*38fd1498Szrj       max_s = max_s.zext (i_f_bits);
269*38fd1498Szrj       min_r.high = -1;
270*38fd1498Szrj       min_r.low = -1;
271*38fd1498Szrj       min_s.high = 0;
272*38fd1498Szrj       min_s.low = 1;
273*38fd1498Szrj       min_s = min_s.alshift (i_f_bits, HOST_BITS_PER_DOUBLE_INT);
274*38fd1498Szrj       min_s = min_s.sext (1 + i_f_bits);
275*38fd1498Szrj       if (a_high.sgt (max_r)
276*38fd1498Szrj 	  || (a_high == max_r &&
277*38fd1498Szrj 	      a_low.ugt (max_s)))
278*38fd1498Szrj 	{
279*38fd1498Szrj 	  if (sat_p)
280*38fd1498Szrj 	    *f = max_s;
281*38fd1498Szrj 	  else
282*38fd1498Szrj 	    overflow_p = true;
283*38fd1498Szrj 	}
284*38fd1498Szrj       else if (a_high.slt (min_r)
285*38fd1498Szrj 	       || (a_high == min_r &&
286*38fd1498Szrj 		   a_low.ult (min_s)))
287*38fd1498Szrj 	{
288*38fd1498Szrj 	  if (sat_p)
289*38fd1498Szrj 	    *f = min_s;
290*38fd1498Szrj 	  else
291*38fd1498Szrj 	    overflow_p = true;
292*38fd1498Szrj 	}
293*38fd1498Szrj     }
294*38fd1498Szrj   return overflow_p;
295*38fd1498Szrj }
296*38fd1498Szrj 
297*38fd1498Szrj /* Return the sign bit based on I_F_BITS.  */
298*38fd1498Szrj 
299*38fd1498Szrj static inline int
get_fixed_sign_bit(double_int a,int i_f_bits)300*38fd1498Szrj get_fixed_sign_bit (double_int a, int i_f_bits)
301*38fd1498Szrj {
302*38fd1498Szrj   if (i_f_bits < HOST_BITS_PER_WIDE_INT)
303*38fd1498Szrj     return (a.low >> i_f_bits) & 1;
304*38fd1498Szrj   else
305*38fd1498Szrj     return (a.high >> (i_f_bits - HOST_BITS_PER_WIDE_INT)) & 1;
306*38fd1498Szrj }
307*38fd1498Szrj 
308*38fd1498Szrj /* Calculate F = A + (SUBTRACT_P ? -B : B).
309*38fd1498Szrj    If SAT_P, saturate the result to the max or the min.
310*38fd1498Szrj    Return true, if !SAT_P and overflow.  */
311*38fd1498Szrj 
312*38fd1498Szrj 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)313*38fd1498Szrj do_fixed_add (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
314*38fd1498Szrj 	      const FIXED_VALUE_TYPE *b, bool subtract_p, bool sat_p)
315*38fd1498Szrj {
316*38fd1498Szrj   bool overflow_p = false;
317*38fd1498Szrj   bool unsigned_p;
318*38fd1498Szrj   double_int temp;
319*38fd1498Szrj   int i_f_bits;
320*38fd1498Szrj 
321*38fd1498Szrj   /* This was a conditional expression but it triggered a bug in
322*38fd1498Szrj      Sun C 5.5.  */
323*38fd1498Szrj   if (subtract_p)
324*38fd1498Szrj     temp = -b->data;
325*38fd1498Szrj   else
326*38fd1498Szrj     temp = b->data;
327*38fd1498Szrj 
328*38fd1498Szrj   unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
329*38fd1498Szrj   i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
330*38fd1498Szrj   f->mode = a->mode;
331*38fd1498Szrj   f->data = a->data + temp;
332*38fd1498Szrj   if (unsigned_p) /* Unsigned type.  */
333*38fd1498Szrj     {
334*38fd1498Szrj       if (subtract_p) /* Unsigned subtraction.  */
335*38fd1498Szrj 	{
336*38fd1498Szrj 	  if (a->data.ult (b->data))
337*38fd1498Szrj 	    {
338*38fd1498Szrj 	      if (sat_p)
339*38fd1498Szrj 		{
340*38fd1498Szrj 		  f->data.high = 0;
341*38fd1498Szrj 		  f->data.low = 0;
342*38fd1498Szrj 		 }
343*38fd1498Szrj 	      else
344*38fd1498Szrj 		overflow_p = true;
345*38fd1498Szrj 	    }
346*38fd1498Szrj 	}
347*38fd1498Szrj       else /* Unsigned addition.  */
348*38fd1498Szrj 	{
349*38fd1498Szrj 	  f->data = f->data.zext (i_f_bits);
350*38fd1498Szrj 	  if (f->data.ult (a->data)
351*38fd1498Szrj 	      || f->data.ult (b->data))
352*38fd1498Szrj 	    {
353*38fd1498Szrj 	      if (sat_p)
354*38fd1498Szrj 		{
355*38fd1498Szrj 		  f->data.high = -1;
356*38fd1498Szrj 		  f->data.low = -1;
357*38fd1498Szrj 		}
358*38fd1498Szrj 	      else
359*38fd1498Szrj 		overflow_p = true;
360*38fd1498Szrj 	    }
361*38fd1498Szrj 	}
362*38fd1498Szrj     }
363*38fd1498Szrj   else /* Signed type.  */
364*38fd1498Szrj     {
365*38fd1498Szrj       if ((!subtract_p
366*38fd1498Szrj 	   && (get_fixed_sign_bit (a->data, i_f_bits)
367*38fd1498Szrj 	       == get_fixed_sign_bit (b->data, i_f_bits))
368*38fd1498Szrj 	   && (get_fixed_sign_bit (a->data, i_f_bits)
369*38fd1498Szrj 	       != get_fixed_sign_bit (f->data, i_f_bits)))
370*38fd1498Szrj 	  || (subtract_p
371*38fd1498Szrj 	      && (get_fixed_sign_bit (a->data, i_f_bits)
372*38fd1498Szrj 		  != get_fixed_sign_bit (b->data, i_f_bits))
373*38fd1498Szrj 	      && (get_fixed_sign_bit (a->data, i_f_bits)
374*38fd1498Szrj 		  != get_fixed_sign_bit (f->data, i_f_bits))))
375*38fd1498Szrj 	{
376*38fd1498Szrj 	  if (sat_p)
377*38fd1498Szrj 	    {
378*38fd1498Szrj 	      f->data.low = 1;
379*38fd1498Szrj 	      f->data.high = 0;
380*38fd1498Szrj 	      f->data = f->data.alshift (i_f_bits, HOST_BITS_PER_DOUBLE_INT);
381*38fd1498Szrj 	      if (get_fixed_sign_bit (a->data, i_f_bits) == 0)
382*38fd1498Szrj 		{
383*38fd1498Szrj 		  --f->data;
384*38fd1498Szrj 		}
385*38fd1498Szrj 	    }
386*38fd1498Szrj 	  else
387*38fd1498Szrj 	    overflow_p = true;
388*38fd1498Szrj 	}
389*38fd1498Szrj     }
390*38fd1498Szrj   f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p);
391*38fd1498Szrj   return overflow_p;
392*38fd1498Szrj }
393*38fd1498Szrj 
394*38fd1498Szrj /* Calculate F = A * B.
395*38fd1498Szrj    If SAT_P, saturate the result to the max or the min.
396*38fd1498Szrj    Return true, if !SAT_P and overflow.  */
397*38fd1498Szrj 
398*38fd1498Szrj static bool
do_fixed_multiply(FIXED_VALUE_TYPE * f,const FIXED_VALUE_TYPE * a,const FIXED_VALUE_TYPE * b,bool sat_p)399*38fd1498Szrj do_fixed_multiply (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
400*38fd1498Szrj 		   const FIXED_VALUE_TYPE *b, bool sat_p)
401*38fd1498Szrj {
402*38fd1498Szrj   bool overflow_p = false;
403*38fd1498Szrj   bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
404*38fd1498Szrj   int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
405*38fd1498Szrj   f->mode = a->mode;
406*38fd1498Szrj   if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT)
407*38fd1498Szrj     {
408*38fd1498Szrj       f->data = a->data * b->data;
409*38fd1498Szrj       f->data = f->data.lshift (-GET_MODE_FBIT (f->mode),
410*38fd1498Szrj 				HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
411*38fd1498Szrj       overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
412*38fd1498Szrj     }
413*38fd1498Szrj   else
414*38fd1498Szrj     {
415*38fd1498Szrj       /* The result of multiplication expands to two double_int.  */
416*38fd1498Szrj       double_int a_high, a_low, b_high, b_low;
417*38fd1498Szrj       double_int high_high, high_low, low_high, low_low;
418*38fd1498Szrj       double_int r, s, temp1, temp2;
419*38fd1498Szrj       int carry = 0;
420*38fd1498Szrj 
421*38fd1498Szrj       /* Decompose a and b to four double_int.  */
422*38fd1498Szrj       a_high.low = a->data.high;
423*38fd1498Szrj       a_high.high = 0;
424*38fd1498Szrj       a_low.low = a->data.low;
425*38fd1498Szrj       a_low.high = 0;
426*38fd1498Szrj       b_high.low = b->data.high;
427*38fd1498Szrj       b_high.high = 0;
428*38fd1498Szrj       b_low.low = b->data.low;
429*38fd1498Szrj       b_low.high = 0;
430*38fd1498Szrj 
431*38fd1498Szrj       /* Perform four multiplications.  */
432*38fd1498Szrj       low_low = a_low * b_low;
433*38fd1498Szrj       low_high = a_low * b_high;
434*38fd1498Szrj       high_low = a_high * b_low;
435*38fd1498Szrj       high_high = a_high * b_high;
436*38fd1498Szrj 
437*38fd1498Szrj       /* Accumulate four results to {r, s}.  */
438*38fd1498Szrj       temp1.high = high_low.low;
439*38fd1498Szrj       temp1.low = 0;
440*38fd1498Szrj       s = low_low + temp1;
441*38fd1498Szrj       if (s.ult (low_low)
442*38fd1498Szrj 	  || s.ult (temp1))
443*38fd1498Szrj 	carry ++; /* Carry */
444*38fd1498Szrj       temp1.high = s.high;
445*38fd1498Szrj       temp1.low = s.low;
446*38fd1498Szrj       temp2.high = low_high.low;
447*38fd1498Szrj       temp2.low = 0;
448*38fd1498Szrj       s = temp1 + temp2;
449*38fd1498Szrj       if (s.ult (temp1)
450*38fd1498Szrj 	  || s.ult (temp2))
451*38fd1498Szrj 	carry ++; /* Carry */
452*38fd1498Szrj 
453*38fd1498Szrj       temp1.low = high_low.high;
454*38fd1498Szrj       temp1.high = 0;
455*38fd1498Szrj       r = high_high + temp1;
456*38fd1498Szrj       temp1.low = low_high.high;
457*38fd1498Szrj       temp1.high = 0;
458*38fd1498Szrj       r += temp1;
459*38fd1498Szrj       temp1.low = carry;
460*38fd1498Szrj       temp1.high = 0;
461*38fd1498Szrj       r += temp1;
462*38fd1498Szrj 
463*38fd1498Szrj       /* We need to subtract b from r, if a < 0.  */
464*38fd1498Szrj       if (!unsigned_p && a->data.high < 0)
465*38fd1498Szrj 	r -= b->data;
466*38fd1498Szrj       /* We need to subtract a from r, if b < 0.  */
467*38fd1498Szrj       if (!unsigned_p && b->data.high < 0)
468*38fd1498Szrj 	r -= a->data;
469*38fd1498Szrj 
470*38fd1498Szrj       /* Shift right the result by FBIT.  */
471*38fd1498Szrj       if (GET_MODE_FBIT (f->mode) == HOST_BITS_PER_DOUBLE_INT)
472*38fd1498Szrj 	{
473*38fd1498Szrj 	  s.low = r.low;
474*38fd1498Szrj 	  s.high = r.high;
475*38fd1498Szrj 	  if (unsigned_p)
476*38fd1498Szrj 	    {
477*38fd1498Szrj 	      r.low = 0;
478*38fd1498Szrj 	      r.high = 0;
479*38fd1498Szrj 	    }
480*38fd1498Szrj 	  else
481*38fd1498Szrj 	    {
482*38fd1498Szrj 	      r.low = -1;
483*38fd1498Szrj 	      r.high = -1;
484*38fd1498Szrj 	    }
485*38fd1498Szrj 	  f->data.low = s.low;
486*38fd1498Szrj 	  f->data.high = s.high;
487*38fd1498Szrj 	}
488*38fd1498Szrj       else
489*38fd1498Szrj 	{
490*38fd1498Szrj 	  s = s.llshift ((-GET_MODE_FBIT (f->mode)), HOST_BITS_PER_DOUBLE_INT);
491*38fd1498Szrj 	  f->data = r.llshift ((HOST_BITS_PER_DOUBLE_INT
492*38fd1498Szrj 			  - GET_MODE_FBIT (f->mode)),
493*38fd1498Szrj 			 HOST_BITS_PER_DOUBLE_INT);
494*38fd1498Szrj 	  f->data.low = f->data.low | s.low;
495*38fd1498Szrj 	  f->data.high = f->data.high | s.high;
496*38fd1498Szrj 	  s.low = f->data.low;
497*38fd1498Szrj 	  s.high = f->data.high;
498*38fd1498Szrj 	  r = r.lshift (-GET_MODE_FBIT (f->mode),
499*38fd1498Szrj 			HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
500*38fd1498Szrj 	}
501*38fd1498Szrj 
502*38fd1498Szrj       overflow_p = fixed_saturate2 (f->mode, r, s, &f->data, sat_p);
503*38fd1498Szrj     }
504*38fd1498Szrj 
505*38fd1498Szrj   f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p);
506*38fd1498Szrj   return overflow_p;
507*38fd1498Szrj }
508*38fd1498Szrj 
509*38fd1498Szrj /* Calculate F = A / B.
510*38fd1498Szrj    If SAT_P, saturate the result to the max or the min.
511*38fd1498Szrj    Return true, if !SAT_P and overflow.  */
512*38fd1498Szrj 
513*38fd1498Szrj static bool
do_fixed_divide(FIXED_VALUE_TYPE * f,const FIXED_VALUE_TYPE * a,const FIXED_VALUE_TYPE * b,bool sat_p)514*38fd1498Szrj do_fixed_divide (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
515*38fd1498Szrj 		 const FIXED_VALUE_TYPE *b, bool sat_p)
516*38fd1498Szrj {
517*38fd1498Szrj   bool overflow_p = false;
518*38fd1498Szrj   bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
519*38fd1498Szrj   int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
520*38fd1498Szrj   f->mode = a->mode;
521*38fd1498Szrj   if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT)
522*38fd1498Szrj     {
523*38fd1498Szrj       f->data = a->data.lshift (GET_MODE_FBIT (f->mode),
524*38fd1498Szrj 				HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
525*38fd1498Szrj       f->data = f->data.div (b->data, unsigned_p, TRUNC_DIV_EXPR);
526*38fd1498Szrj       overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
527*38fd1498Szrj     }
528*38fd1498Szrj   else
529*38fd1498Szrj     {
530*38fd1498Szrj       double_int pos_a, pos_b, r, s;
531*38fd1498Szrj       double_int quo_r, quo_s, mod, temp;
532*38fd1498Szrj       int num_of_neg = 0;
533*38fd1498Szrj       int i;
534*38fd1498Szrj 
535*38fd1498Szrj       /* If a < 0, negate a.  */
536*38fd1498Szrj       if (!unsigned_p && a->data.high < 0)
537*38fd1498Szrj 	{
538*38fd1498Szrj 	  pos_a = -a->data;
539*38fd1498Szrj 	  num_of_neg ++;
540*38fd1498Szrj 	}
541*38fd1498Szrj       else
542*38fd1498Szrj 	pos_a = a->data;
543*38fd1498Szrj 
544*38fd1498Szrj       /* If b < 0, negate b.  */
545*38fd1498Szrj       if (!unsigned_p && b->data.high < 0)
546*38fd1498Szrj 	{
547*38fd1498Szrj 	  pos_b = -b->data;
548*38fd1498Szrj 	  num_of_neg ++;
549*38fd1498Szrj 	}
550*38fd1498Szrj       else
551*38fd1498Szrj 	pos_b = b->data;
552*38fd1498Szrj 
553*38fd1498Szrj       /* Left shift pos_a to {r, s} by FBIT.  */
554*38fd1498Szrj       if (GET_MODE_FBIT (f->mode) == HOST_BITS_PER_DOUBLE_INT)
555*38fd1498Szrj 	{
556*38fd1498Szrj 	  r = pos_a;
557*38fd1498Szrj 	  s.high = 0;
558*38fd1498Szrj 	  s.low = 0;
559*38fd1498Szrj 	}
560*38fd1498Szrj       else
561*38fd1498Szrj  	{
562*38fd1498Szrj 	  s = pos_a.llshift (GET_MODE_FBIT (f->mode), HOST_BITS_PER_DOUBLE_INT);
563*38fd1498Szrj 	  r = pos_a.llshift (- (HOST_BITS_PER_DOUBLE_INT
564*38fd1498Szrj 			    - GET_MODE_FBIT (f->mode)),
565*38fd1498Szrj 			 HOST_BITS_PER_DOUBLE_INT);
566*38fd1498Szrj  	}
567*38fd1498Szrj 
568*38fd1498Szrj       /* Divide r by pos_b to quo_r.  The remainder is in mod.  */
569*38fd1498Szrj       quo_r = r.divmod (pos_b, 1, TRUNC_DIV_EXPR, &mod);
570*38fd1498Szrj       quo_s = double_int_zero;
571*38fd1498Szrj 
572*38fd1498Szrj       for (i = 0; i < HOST_BITS_PER_DOUBLE_INT; i++)
573*38fd1498Szrj 	{
574*38fd1498Szrj 	  /* Record the leftmost bit of mod.  */
575*38fd1498Szrj 	  int leftmost_mod = (mod.high < 0);
576*38fd1498Szrj 
577*38fd1498Szrj 	  /* Shift left mod by 1 bit.  */
578*38fd1498Szrj 	  mod = mod.lshift (1);
579*38fd1498Szrj 
580*38fd1498Szrj 	  /* Test the leftmost bit of s to add to mod.  */
581*38fd1498Szrj 	  if (s.high < 0)
582*38fd1498Szrj 	    mod.low += 1;
583*38fd1498Szrj 
584*38fd1498Szrj 	  /* Shift left quo_s by 1 bit.  */
585*38fd1498Szrj 	  quo_s = quo_s.lshift (1);
586*38fd1498Szrj 
587*38fd1498Szrj 	  /* Try to calculate (mod - pos_b).  */
588*38fd1498Szrj 	  temp = mod - pos_b;
589*38fd1498Szrj 
590*38fd1498Szrj 	  if (leftmost_mod == 1 || mod.ucmp (pos_b) != -1)
591*38fd1498Szrj 	    {
592*38fd1498Szrj 	      quo_s.low += 1;
593*38fd1498Szrj 	      mod = temp;
594*38fd1498Szrj 	    }
595*38fd1498Szrj 
596*38fd1498Szrj 	  /* Shift left s by 1 bit.  */
597*38fd1498Szrj 	  s = s.lshift (1);
598*38fd1498Szrj 
599*38fd1498Szrj 	}
600*38fd1498Szrj 
601*38fd1498Szrj       if (num_of_neg == 1)
602*38fd1498Szrj 	{
603*38fd1498Szrj 	  quo_s = -quo_s;
604*38fd1498Szrj 	  if (quo_s.high == 0 && quo_s.low == 0)
605*38fd1498Szrj 	    quo_r = -quo_r;
606*38fd1498Szrj 	  else
607*38fd1498Szrj 	    {
608*38fd1498Szrj 	      quo_r.low = ~quo_r.low;
609*38fd1498Szrj 	      quo_r.high = ~quo_r.high;
610*38fd1498Szrj 	    }
611*38fd1498Szrj 	}
612*38fd1498Szrj 
613*38fd1498Szrj       f->data = quo_s;
614*38fd1498Szrj       overflow_p = fixed_saturate2 (f->mode, quo_r, quo_s, &f->data, sat_p);
615*38fd1498Szrj     }
616*38fd1498Szrj 
617*38fd1498Szrj   f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p);
618*38fd1498Szrj   return overflow_p;
619*38fd1498Szrj }
620*38fd1498Szrj 
621*38fd1498Szrj /* Calculate F = A << B if LEFT_P.  Otherwise, F = A >> B.
622*38fd1498Szrj    If SAT_P, saturate the result to the max or the min.
623*38fd1498Szrj    Return true, if !SAT_P and overflow.  */
624*38fd1498Szrj 
625*38fd1498Szrj 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)626*38fd1498Szrj do_fixed_shift (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
627*38fd1498Szrj 	      const FIXED_VALUE_TYPE *b, bool left_p, bool sat_p)
628*38fd1498Szrj {
629*38fd1498Szrj   bool overflow_p = false;
630*38fd1498Szrj   bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
631*38fd1498Szrj   int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
632*38fd1498Szrj   f->mode = a->mode;
633*38fd1498Szrj 
634*38fd1498Szrj   if (b->data.low == 0)
635*38fd1498Szrj     {
636*38fd1498Szrj       f->data = a->data;
637*38fd1498Szrj       return overflow_p;
638*38fd1498Szrj     }
639*38fd1498Szrj 
640*38fd1498Szrj   if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT || (!left_p))
641*38fd1498Szrj     {
642*38fd1498Szrj       f->data = a->data.lshift (left_p ? b->data.low : -b->data.low,
643*38fd1498Szrj 				HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
644*38fd1498Szrj       if (left_p) /* Only left shift saturates.  */
645*38fd1498Szrj 	overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
646*38fd1498Szrj     }
647*38fd1498Szrj   else /* We need two double_int to store the left-shift result.  */
648*38fd1498Szrj     {
649*38fd1498Szrj       double_int temp_high, temp_low;
650*38fd1498Szrj       if (b->data.low == HOST_BITS_PER_DOUBLE_INT)
651*38fd1498Szrj 	{
652*38fd1498Szrj 	  temp_high = a->data;
653*38fd1498Szrj 	  temp_low.high = 0;
654*38fd1498Szrj 	  temp_low.low = 0;
655*38fd1498Szrj 	}
656*38fd1498Szrj       else
657*38fd1498Szrj 	{
658*38fd1498Szrj 	  temp_low = a->data.lshift (b->data.low,
659*38fd1498Szrj 				     HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
660*38fd1498Szrj 	  /* Logical shift right to temp_high.  */
661*38fd1498Szrj 	  temp_high = a->data.llshift (b->data.low - HOST_BITS_PER_DOUBLE_INT,
662*38fd1498Szrj 			 HOST_BITS_PER_DOUBLE_INT);
663*38fd1498Szrj 	}
664*38fd1498Szrj       if (!unsigned_p && a->data.high < 0) /* Signed-extend temp_high.  */
665*38fd1498Szrj 	temp_high = temp_high.ext (b->data.low, unsigned_p);
666*38fd1498Szrj       f->data = temp_low;
667*38fd1498Szrj       overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data,
668*38fd1498Szrj 				    sat_p);
669*38fd1498Szrj     }
670*38fd1498Szrj   f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p);
671*38fd1498Szrj   return overflow_p;
672*38fd1498Szrj }
673*38fd1498Szrj 
674*38fd1498Szrj /* Calculate F = -A.
675*38fd1498Szrj    If SAT_P, saturate the result to the max or the min.
676*38fd1498Szrj    Return true, if !SAT_P and overflow.  */
677*38fd1498Szrj 
678*38fd1498Szrj static bool
do_fixed_neg(FIXED_VALUE_TYPE * f,const FIXED_VALUE_TYPE * a,bool sat_p)679*38fd1498Szrj do_fixed_neg (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, bool sat_p)
680*38fd1498Szrj {
681*38fd1498Szrj   bool overflow_p = false;
682*38fd1498Szrj   bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
683*38fd1498Szrj   int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
684*38fd1498Szrj   f->mode = a->mode;
685*38fd1498Szrj   f->data = -a->data;
686*38fd1498Szrj   f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p);
687*38fd1498Szrj 
688*38fd1498Szrj   if (unsigned_p) /* Unsigned type.  */
689*38fd1498Szrj     {
690*38fd1498Szrj       if (f->data.low != 0 || f->data.high != 0)
691*38fd1498Szrj 	{
692*38fd1498Szrj 	  if (sat_p)
693*38fd1498Szrj 	    {
694*38fd1498Szrj 	      f->data.low = 0;
695*38fd1498Szrj 	      f->data.high = 0;
696*38fd1498Szrj 	    }
697*38fd1498Szrj 	  else
698*38fd1498Szrj 	    overflow_p = true;
699*38fd1498Szrj 	}
700*38fd1498Szrj     }
701*38fd1498Szrj   else /* Signed type.  */
702*38fd1498Szrj     {
703*38fd1498Szrj       if (!(f->data.high == 0 && f->data.low == 0)
704*38fd1498Szrj 	  && f->data.high == a->data.high && f->data.low == a->data.low )
705*38fd1498Szrj 	{
706*38fd1498Szrj 	  if (sat_p)
707*38fd1498Szrj 	    {
708*38fd1498Szrj 	      /* Saturate to the maximum by subtracting f->data by one.  */
709*38fd1498Szrj 	      f->data.low = -1;
710*38fd1498Szrj 	      f->data.high = -1;
711*38fd1498Szrj 	      f->data = f->data.zext (i_f_bits);
712*38fd1498Szrj 	    }
713*38fd1498Szrj 	  else
714*38fd1498Szrj 	    overflow_p = true;
715*38fd1498Szrj 	}
716*38fd1498Szrj     }
717*38fd1498Szrj   return overflow_p;
718*38fd1498Szrj }
719*38fd1498Szrj 
720*38fd1498Szrj /* Perform the binary or unary operation described by CODE.
721*38fd1498Szrj    Note that OP0 and OP1 must have the same mode for binary operators.
722*38fd1498Szrj    For a unary operation, leave OP1 NULL.
723*38fd1498Szrj    Return true, if !SAT_P and overflow.  */
724*38fd1498Szrj 
725*38fd1498Szrj bool
fixed_arithmetic(FIXED_VALUE_TYPE * f,int icode,const FIXED_VALUE_TYPE * op0,const FIXED_VALUE_TYPE * op1,bool sat_p)726*38fd1498Szrj fixed_arithmetic (FIXED_VALUE_TYPE *f, int icode, const FIXED_VALUE_TYPE *op0,
727*38fd1498Szrj 		  const FIXED_VALUE_TYPE *op1, bool sat_p)
728*38fd1498Szrj {
729*38fd1498Szrj   switch (icode)
730*38fd1498Szrj     {
731*38fd1498Szrj     case NEGATE_EXPR:
732*38fd1498Szrj       return do_fixed_neg (f, op0, sat_p);
733*38fd1498Szrj 
734*38fd1498Szrj     case PLUS_EXPR:
735*38fd1498Szrj       gcc_assert (op0->mode == op1->mode);
736*38fd1498Szrj       return do_fixed_add (f, op0, op1, false, sat_p);
737*38fd1498Szrj 
738*38fd1498Szrj     case MINUS_EXPR:
739*38fd1498Szrj       gcc_assert (op0->mode == op1->mode);
740*38fd1498Szrj       return do_fixed_add (f, op0, op1, true, sat_p);
741*38fd1498Szrj 
742*38fd1498Szrj     case MULT_EXPR:
743*38fd1498Szrj       gcc_assert (op0->mode == op1->mode);
744*38fd1498Szrj       return do_fixed_multiply (f, op0, op1, sat_p);
745*38fd1498Szrj 
746*38fd1498Szrj     case TRUNC_DIV_EXPR:
747*38fd1498Szrj       gcc_assert (op0->mode == op1->mode);
748*38fd1498Szrj       return do_fixed_divide (f, op0, op1, sat_p);
749*38fd1498Szrj 
750*38fd1498Szrj     case LSHIFT_EXPR:
751*38fd1498Szrj       return do_fixed_shift (f, op0, op1, true, sat_p);
752*38fd1498Szrj 
753*38fd1498Szrj     case RSHIFT_EXPR:
754*38fd1498Szrj       return do_fixed_shift (f, op0, op1, false, sat_p);
755*38fd1498Szrj 
756*38fd1498Szrj     default:
757*38fd1498Szrj       gcc_unreachable ();
758*38fd1498Szrj     }
759*38fd1498Szrj   return false;
760*38fd1498Szrj }
761*38fd1498Szrj 
762*38fd1498Szrj /* Compare fixed-point values by tree_code.
763*38fd1498Szrj    Note that OP0 and OP1 must have the same mode.  */
764*38fd1498Szrj 
765*38fd1498Szrj bool
fixed_compare(int icode,const FIXED_VALUE_TYPE * op0,const FIXED_VALUE_TYPE * op1)766*38fd1498Szrj fixed_compare (int icode, const FIXED_VALUE_TYPE *op0,
767*38fd1498Szrj 	       const FIXED_VALUE_TYPE *op1)
768*38fd1498Szrj {
769*38fd1498Szrj   enum tree_code code = (enum tree_code) icode;
770*38fd1498Szrj   gcc_assert (op0->mode == op1->mode);
771*38fd1498Szrj 
772*38fd1498Szrj   switch (code)
773*38fd1498Szrj     {
774*38fd1498Szrj     case NE_EXPR:
775*38fd1498Szrj       return op0->data != op1->data;
776*38fd1498Szrj 
777*38fd1498Szrj     case EQ_EXPR:
778*38fd1498Szrj       return op0->data == op1->data;
779*38fd1498Szrj 
780*38fd1498Szrj     case LT_EXPR:
781*38fd1498Szrj       return op0->data.cmp (op1->data,
782*38fd1498Szrj 			     UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) == -1;
783*38fd1498Szrj 
784*38fd1498Szrj     case LE_EXPR:
785*38fd1498Szrj       return op0->data.cmp (op1->data,
786*38fd1498Szrj 			     UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) != 1;
787*38fd1498Szrj 
788*38fd1498Szrj     case GT_EXPR:
789*38fd1498Szrj       return op0->data.cmp (op1->data,
790*38fd1498Szrj 			     UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) == 1;
791*38fd1498Szrj 
792*38fd1498Szrj     case GE_EXPR:
793*38fd1498Szrj       return op0->data.cmp (op1->data,
794*38fd1498Szrj 			     UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) != -1;
795*38fd1498Szrj 
796*38fd1498Szrj     default:
797*38fd1498Szrj       gcc_unreachable ();
798*38fd1498Szrj     }
799*38fd1498Szrj }
800*38fd1498Szrj 
801*38fd1498Szrj /* Extend or truncate to a new mode.
802*38fd1498Szrj    If SAT_P, saturate the result to the max or the min.
803*38fd1498Szrj    Return true, if !SAT_P and overflow.  */
804*38fd1498Szrj 
805*38fd1498Szrj bool
fixed_convert(FIXED_VALUE_TYPE * f,scalar_mode mode,const FIXED_VALUE_TYPE * a,bool sat_p)806*38fd1498Szrj fixed_convert (FIXED_VALUE_TYPE *f, scalar_mode mode,
807*38fd1498Szrj                const FIXED_VALUE_TYPE *a, bool sat_p)
808*38fd1498Szrj {
809*38fd1498Szrj   bool overflow_p = false;
810*38fd1498Szrj   if (mode == a->mode)
811*38fd1498Szrj     {
812*38fd1498Szrj       *f = *a;
813*38fd1498Szrj       return overflow_p;
814*38fd1498Szrj     }
815*38fd1498Szrj 
816*38fd1498Szrj   if (GET_MODE_FBIT (mode) > GET_MODE_FBIT (a->mode))
817*38fd1498Szrj     {
818*38fd1498Szrj       /* Left shift a to temp_high, temp_low based on a->mode.  */
819*38fd1498Szrj       double_int temp_high, temp_low;
820*38fd1498Szrj       int amount = GET_MODE_FBIT (mode) - GET_MODE_FBIT (a->mode);
821*38fd1498Szrj       temp_low = a->data.lshift (amount,
822*38fd1498Szrj 				 HOST_BITS_PER_DOUBLE_INT,
823*38fd1498Szrj 				 SIGNED_FIXED_POINT_MODE_P (a->mode));
824*38fd1498Szrj       /* Logical shift right to temp_high.  */
825*38fd1498Szrj       temp_high = a->data.llshift (amount - HOST_BITS_PER_DOUBLE_INT,
826*38fd1498Szrj 		     HOST_BITS_PER_DOUBLE_INT);
827*38fd1498Szrj       if (SIGNED_FIXED_POINT_MODE_P (a->mode)
828*38fd1498Szrj 	  && a->data.high < 0) /* Signed-extend temp_high.  */
829*38fd1498Szrj 	temp_high = temp_high.sext (amount);
830*38fd1498Szrj       f->mode = mode;
831*38fd1498Szrj       f->data = temp_low;
832*38fd1498Szrj       if (SIGNED_FIXED_POINT_MODE_P (a->mode) ==
833*38fd1498Szrj 	  SIGNED_FIXED_POINT_MODE_P (f->mode))
834*38fd1498Szrj 	overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data,
835*38fd1498Szrj 				      sat_p);
836*38fd1498Szrj       else
837*38fd1498Szrj 	{
838*38fd1498Szrj 	  /* Take care of the cases when converting between signed and
839*38fd1498Szrj 	     unsigned.  */
840*38fd1498Szrj 	  if (SIGNED_FIXED_POINT_MODE_P (a->mode))
841*38fd1498Szrj 	    {
842*38fd1498Szrj 	      /* Signed -> Unsigned.  */
843*38fd1498Szrj 	      if (a->data.high < 0)
844*38fd1498Szrj 		{
845*38fd1498Szrj 		  if (sat_p)
846*38fd1498Szrj 		    {
847*38fd1498Szrj 		      f->data.low = 0;  /* Set to zero.  */
848*38fd1498Szrj 		      f->data.high = 0;  /* Set to zero.  */
849*38fd1498Szrj 		    }
850*38fd1498Szrj 		  else
851*38fd1498Szrj 		    overflow_p = true;
852*38fd1498Szrj 		}
853*38fd1498Szrj 	      else
854*38fd1498Szrj 		overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low,
855*38fd1498Szrj 					      &f->data, sat_p);
856*38fd1498Szrj 	    }
857*38fd1498Szrj 	  else
858*38fd1498Szrj 	    {
859*38fd1498Szrj 	      /* Unsigned -> Signed.  */
860*38fd1498Szrj 	      if (temp_high.high < 0)
861*38fd1498Szrj 		{
862*38fd1498Szrj 		  if (sat_p)
863*38fd1498Szrj 		    {
864*38fd1498Szrj 		      /* Set to maximum.  */
865*38fd1498Szrj 		      f->data.low = -1;  /* Set to all ones.  */
866*38fd1498Szrj 		      f->data.high = -1;  /* Set to all ones.  */
867*38fd1498Szrj 		      f->data = f->data.zext (GET_MODE_FBIT (f->mode)
868*38fd1498Szrj 						+ GET_MODE_IBIT (f->mode));
869*38fd1498Szrj 						/* Clear the sign.  */
870*38fd1498Szrj 		    }
871*38fd1498Szrj 		  else
872*38fd1498Szrj 		    overflow_p = true;
873*38fd1498Szrj 		}
874*38fd1498Szrj 	      else
875*38fd1498Szrj 		overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low,
876*38fd1498Szrj 					      &f->data, sat_p);
877*38fd1498Szrj 	    }
878*38fd1498Szrj 	}
879*38fd1498Szrj     }
880*38fd1498Szrj   else
881*38fd1498Szrj     {
882*38fd1498Szrj       /* Right shift a to temp based on a->mode.  */
883*38fd1498Szrj       double_int temp;
884*38fd1498Szrj       temp = a->data.lshift (GET_MODE_FBIT (mode) - GET_MODE_FBIT (a->mode),
885*38fd1498Szrj 			     HOST_BITS_PER_DOUBLE_INT,
886*38fd1498Szrj 			     SIGNED_FIXED_POINT_MODE_P (a->mode));
887*38fd1498Szrj       f->mode = mode;
888*38fd1498Szrj       f->data = temp;
889*38fd1498Szrj       if (SIGNED_FIXED_POINT_MODE_P (a->mode) ==
890*38fd1498Szrj 	  SIGNED_FIXED_POINT_MODE_P (f->mode))
891*38fd1498Szrj 	overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
892*38fd1498Szrj       else
893*38fd1498Szrj 	{
894*38fd1498Szrj 	  /* Take care of the cases when converting between signed and
895*38fd1498Szrj 	     unsigned.  */
896*38fd1498Szrj 	  if (SIGNED_FIXED_POINT_MODE_P (a->mode))
897*38fd1498Szrj 	    {
898*38fd1498Szrj 	      /* Signed -> Unsigned.  */
899*38fd1498Szrj 	      if (a->data.high < 0)
900*38fd1498Szrj 		{
901*38fd1498Szrj 		  if (sat_p)
902*38fd1498Szrj 		    {
903*38fd1498Szrj 		      f->data.low = 0;  /* Set to zero.  */
904*38fd1498Szrj 		      f->data.high = 0;  /* Set to zero.  */
905*38fd1498Szrj 		    }
906*38fd1498Szrj 		  else
907*38fd1498Szrj 		    overflow_p = true;
908*38fd1498Szrj 		}
909*38fd1498Szrj 	      else
910*38fd1498Szrj 		overflow_p = fixed_saturate1 (f->mode, f->data, &f->data,
911*38fd1498Szrj 					      sat_p);
912*38fd1498Szrj 	    }
913*38fd1498Szrj 	  else
914*38fd1498Szrj 	    {
915*38fd1498Szrj 	      /* Unsigned -> Signed.  */
916*38fd1498Szrj 	      if (temp.high < 0)
917*38fd1498Szrj 		{
918*38fd1498Szrj 		  if (sat_p)
919*38fd1498Szrj 		    {
920*38fd1498Szrj 		      /* Set to maximum.  */
921*38fd1498Szrj 		      f->data.low = -1;  /* Set to all ones.  */
922*38fd1498Szrj 		      f->data.high = -1;  /* Set to all ones.  */
923*38fd1498Szrj 		      f->data = f->data.zext (GET_MODE_FBIT (f->mode)
924*38fd1498Szrj 						+ GET_MODE_IBIT (f->mode));
925*38fd1498Szrj 						/* Clear the sign.  */
926*38fd1498Szrj 		    }
927*38fd1498Szrj 		  else
928*38fd1498Szrj 		    overflow_p = true;
929*38fd1498Szrj 		}
930*38fd1498Szrj 	      else
931*38fd1498Szrj 		overflow_p = fixed_saturate1 (f->mode, f->data, &f->data,
932*38fd1498Szrj 					      sat_p);
933*38fd1498Szrj 	    }
934*38fd1498Szrj 	}
935*38fd1498Szrj     }
936*38fd1498Szrj 
937*38fd1498Szrj   f->data = f->data.ext (SIGNED_FIXED_POINT_MODE_P (f->mode)
938*38fd1498Szrj 			    + GET_MODE_FBIT (f->mode)
939*38fd1498Szrj 			    + GET_MODE_IBIT (f->mode),
940*38fd1498Szrj 			    UNSIGNED_FIXED_POINT_MODE_P (f->mode));
941*38fd1498Szrj   return overflow_p;
942*38fd1498Szrj }
943*38fd1498Szrj 
944*38fd1498Szrj /* Convert to a new fixed-point mode from an integer.
945*38fd1498Szrj    If UNSIGNED_P, this integer is unsigned.
946*38fd1498Szrj    If SAT_P, saturate the result to the max or the min.
947*38fd1498Szrj    Return true, if !SAT_P and overflow.  */
948*38fd1498Szrj 
949*38fd1498Szrj bool
fixed_convert_from_int(FIXED_VALUE_TYPE * f,scalar_mode mode,double_int a,bool unsigned_p,bool sat_p)950*38fd1498Szrj fixed_convert_from_int (FIXED_VALUE_TYPE *f, scalar_mode mode,
951*38fd1498Szrj 			double_int a, bool unsigned_p, bool sat_p)
952*38fd1498Szrj {
953*38fd1498Szrj   bool overflow_p = false;
954*38fd1498Szrj   /* Left shift a to temp_high, temp_low.  */
955*38fd1498Szrj   double_int temp_high, temp_low;
956*38fd1498Szrj   int amount = GET_MODE_FBIT (mode);
957*38fd1498Szrj   if (amount == HOST_BITS_PER_DOUBLE_INT)
958*38fd1498Szrj     {
959*38fd1498Szrj        temp_high = a;
960*38fd1498Szrj        temp_low.low = 0;
961*38fd1498Szrj        temp_low.high = 0;
962*38fd1498Szrj     }
963*38fd1498Szrj   else
964*38fd1498Szrj     {
965*38fd1498Szrj       temp_low = a.llshift (amount, HOST_BITS_PER_DOUBLE_INT);
966*38fd1498Szrj 
967*38fd1498Szrj       /* Logical shift right to temp_high.  */
968*38fd1498Szrj       temp_high = a.llshift (amount - HOST_BITS_PER_DOUBLE_INT,
969*38fd1498Szrj 		     HOST_BITS_PER_DOUBLE_INT);
970*38fd1498Szrj     }
971*38fd1498Szrj   if (!unsigned_p && a.high < 0) /* Signed-extend temp_high.  */
972*38fd1498Szrj     temp_high = temp_high.sext (amount);
973*38fd1498Szrj 
974*38fd1498Szrj   f->mode = mode;
975*38fd1498Szrj   f->data = temp_low;
976*38fd1498Szrj 
977*38fd1498Szrj   if (unsigned_p == UNSIGNED_FIXED_POINT_MODE_P (f->mode))
978*38fd1498Szrj     overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data,
979*38fd1498Szrj 				  sat_p);
980*38fd1498Szrj   else
981*38fd1498Szrj     {
982*38fd1498Szrj       /* Take care of the cases when converting between signed and unsigned.  */
983*38fd1498Szrj       if (!unsigned_p)
984*38fd1498Szrj 	{
985*38fd1498Szrj 	  /* Signed -> Unsigned.  */
986*38fd1498Szrj 	  if (a.high < 0)
987*38fd1498Szrj 	    {
988*38fd1498Szrj 	      if (sat_p)
989*38fd1498Szrj 		{
990*38fd1498Szrj 		  f->data.low = 0;  /* Set to zero.  */
991*38fd1498Szrj 		  f->data.high = 0;  /* Set to zero.  */
992*38fd1498Szrj 		}
993*38fd1498Szrj 	      else
994*38fd1498Szrj 		overflow_p = true;
995*38fd1498Szrj 	    }
996*38fd1498Szrj 	  else
997*38fd1498Szrj 	    overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low,
998*38fd1498Szrj 					  &f->data, sat_p);
999*38fd1498Szrj 	}
1000*38fd1498Szrj       else
1001*38fd1498Szrj 	{
1002*38fd1498Szrj 	  /* Unsigned -> Signed.  */
1003*38fd1498Szrj 	  if (temp_high.high < 0)
1004*38fd1498Szrj 	    {
1005*38fd1498Szrj 	      if (sat_p)
1006*38fd1498Szrj 		{
1007*38fd1498Szrj 		  /* Set to maximum.  */
1008*38fd1498Szrj 		  f->data.low = -1;  /* Set to all ones.  */
1009*38fd1498Szrj 		  f->data.high = -1;  /* Set to all ones.  */
1010*38fd1498Szrj 		  f->data = f->data.zext (GET_MODE_FBIT (f->mode)
1011*38fd1498Szrj 					    + GET_MODE_IBIT (f->mode));
1012*38fd1498Szrj 					    /* Clear the sign.  */
1013*38fd1498Szrj 		}
1014*38fd1498Szrj 	      else
1015*38fd1498Szrj 		overflow_p = true;
1016*38fd1498Szrj 	    }
1017*38fd1498Szrj 	  else
1018*38fd1498Szrj 	    overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low,
1019*38fd1498Szrj 					  &f->data, sat_p);
1020*38fd1498Szrj 	}
1021*38fd1498Szrj     }
1022*38fd1498Szrj   f->data = f->data.ext (SIGNED_FIXED_POINT_MODE_P (f->mode)
1023*38fd1498Szrj 			    + GET_MODE_FBIT (f->mode)
1024*38fd1498Szrj 			    + GET_MODE_IBIT (f->mode),
1025*38fd1498Szrj 			    UNSIGNED_FIXED_POINT_MODE_P (f->mode));
1026*38fd1498Szrj   return overflow_p;
1027*38fd1498Szrj }
1028*38fd1498Szrj 
1029*38fd1498Szrj /* Convert to a new fixed-point mode from a real.
1030*38fd1498Szrj    If SAT_P, saturate the result to the max or the min.
1031*38fd1498Szrj    Return true, if !SAT_P and overflow.  */
1032*38fd1498Szrj 
1033*38fd1498Szrj bool
fixed_convert_from_real(FIXED_VALUE_TYPE * f,scalar_mode mode,const REAL_VALUE_TYPE * a,bool sat_p)1034*38fd1498Szrj fixed_convert_from_real (FIXED_VALUE_TYPE *f, scalar_mode mode,
1035*38fd1498Szrj 			 const REAL_VALUE_TYPE *a, bool sat_p)
1036*38fd1498Szrj {
1037*38fd1498Szrj   bool overflow_p = false;
1038*38fd1498Szrj   REAL_VALUE_TYPE real_value, fixed_value, base_value;
1039*38fd1498Szrj   bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode);
1040*38fd1498Szrj   int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode);
1041*38fd1498Szrj   unsigned int fbit = GET_MODE_FBIT (mode);
1042*38fd1498Szrj   enum fixed_value_range_code temp;
1043*38fd1498Szrj   bool fail;
1044*38fd1498Szrj 
1045*38fd1498Szrj   real_value = *a;
1046*38fd1498Szrj   f->mode = mode;
1047*38fd1498Szrj   real_2expN (&base_value, fbit, VOIDmode);
1048*38fd1498Szrj   real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value);
1049*38fd1498Szrj 
1050*38fd1498Szrj   wide_int w = real_to_integer (&fixed_value, &fail,
1051*38fd1498Szrj 				GET_MODE_PRECISION (mode));
1052*38fd1498Szrj   f->data.low = w.ulow ();
1053*38fd1498Szrj   f->data.high = w.elt (1);
1054*38fd1498Szrj   temp = check_real_for_fixed_mode (&real_value, mode);
1055*38fd1498Szrj   if (temp == FIXED_UNDERFLOW) /* Minimum.  */
1056*38fd1498Szrj     {
1057*38fd1498Szrj       if (sat_p)
1058*38fd1498Szrj 	{
1059*38fd1498Szrj 	  if (unsigned_p)
1060*38fd1498Szrj 	    {
1061*38fd1498Szrj 	      f->data.low = 0;
1062*38fd1498Szrj 	      f->data.high = 0;
1063*38fd1498Szrj 	    }
1064*38fd1498Szrj 	  else
1065*38fd1498Szrj 	    {
1066*38fd1498Szrj 	      f->data.low = 1;
1067*38fd1498Szrj 	      f->data.high = 0;
1068*38fd1498Szrj 	      f->data = f->data.alshift (i_f_bits, HOST_BITS_PER_DOUBLE_INT);
1069*38fd1498Szrj 	      f->data = f->data.sext (1 + i_f_bits);
1070*38fd1498Szrj 	    }
1071*38fd1498Szrj 	}
1072*38fd1498Szrj       else
1073*38fd1498Szrj 	overflow_p = true;
1074*38fd1498Szrj     }
1075*38fd1498Szrj   else if (temp == FIXED_GT_MAX_EPS || temp == FIXED_MAX_EPS) /* Maximum.  */
1076*38fd1498Szrj     {
1077*38fd1498Szrj       if (sat_p)
1078*38fd1498Szrj 	{
1079*38fd1498Szrj 	  f->data.low = -1;
1080*38fd1498Szrj 	  f->data.high = -1;
1081*38fd1498Szrj 	  f->data = f->data.zext (i_f_bits);
1082*38fd1498Szrj 	}
1083*38fd1498Szrj       else
1084*38fd1498Szrj 	overflow_p = true;
1085*38fd1498Szrj     }
1086*38fd1498Szrj   f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p);
1087*38fd1498Szrj   return overflow_p;
1088*38fd1498Szrj }
1089*38fd1498Szrj 
1090*38fd1498Szrj /* Convert to a new real mode from a fixed-point.  */
1091*38fd1498Szrj 
1092*38fd1498Szrj void
real_convert_from_fixed(REAL_VALUE_TYPE * r,scalar_mode mode,const FIXED_VALUE_TYPE * f)1093*38fd1498Szrj real_convert_from_fixed (REAL_VALUE_TYPE *r, scalar_mode mode,
1094*38fd1498Szrj 			 const FIXED_VALUE_TYPE *f)
1095*38fd1498Szrj {
1096*38fd1498Szrj   REAL_VALUE_TYPE base_value, fixed_value, real_value;
1097*38fd1498Szrj 
1098*38fd1498Szrj   signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f->mode) ? UNSIGNED : SIGNED;
1099*38fd1498Szrj   real_2expN (&base_value, GET_MODE_FBIT (f->mode), VOIDmode);
1100*38fd1498Szrj   real_from_integer (&fixed_value, VOIDmode,
1101*38fd1498Szrj 		     wide_int::from (f->data, GET_MODE_PRECISION (f->mode),
1102*38fd1498Szrj 				     sgn), sgn);
1103*38fd1498Szrj   real_arithmetic (&real_value, RDIV_EXPR, &fixed_value, &base_value);
1104*38fd1498Szrj   real_convert (r, mode, &real_value);
1105*38fd1498Szrj }
1106*38fd1498Szrj 
1107*38fd1498Szrj /* Determine whether a fixed-point value F is negative.  */
1108*38fd1498Szrj 
1109*38fd1498Szrj bool
fixed_isneg(const FIXED_VALUE_TYPE * f)1110*38fd1498Szrj fixed_isneg (const FIXED_VALUE_TYPE *f)
1111*38fd1498Szrj {
1112*38fd1498Szrj   if (SIGNED_FIXED_POINT_MODE_P (f->mode))
1113*38fd1498Szrj     {
1114*38fd1498Szrj       int i_f_bits = GET_MODE_IBIT (f->mode) + GET_MODE_FBIT (f->mode);
1115*38fd1498Szrj       int sign_bit = get_fixed_sign_bit (f->data, i_f_bits);
1116*38fd1498Szrj       if (sign_bit == 1)
1117*38fd1498Szrj 	return true;
1118*38fd1498Szrj     }
1119*38fd1498Szrj 
1120*38fd1498Szrj   return false;
1121*38fd1498Szrj }
1122