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