IA MCU psABI support: changes to libraries
[gcc.git] / gcc / fixed-value.c
index 9a34bc53de1784a53d763dfefd99c6271cdb89cc..151b6a10ba142739c863bb19a71239122d3f9c73 100644 (file)
@@ -1,5 +1,5 @@
 /* Fixed-point arithmetic support.
-   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2006-2015 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "alias.h"
+#include "symtab.h"
 #include "tree.h"
 #include "diagnostic-core.h"
 
@@ -59,7 +61,7 @@ enum fixed_value_range_code {
           FIXED_MAX_EPS, if it is equal to the maximum plus the epsilon.  */
 
 static enum fixed_value_range_code
-check_real_for_fixed_mode (REAL_VALUE_TYPE *real_value, enum machine_mode mode)
+check_real_for_fixed_mode (REAL_VALUE_TYPE *real_value, machine_mode mode)
 {
   REAL_VALUE_TYPE max_value, min_value, epsilon_value;
 
@@ -81,14 +83,39 @@ check_real_for_fixed_mode (REAL_VALUE_TYPE *real_value, enum machine_mode mode)
   return FIXED_OK;
 }
 
+
+/* Construct a CONST_FIXED from a bit payload and machine mode MODE.
+   The bits in PAYLOAD are sign-extended/zero-extended according to MODE.  */
+
+FIXED_VALUE_TYPE
+fixed_from_double_int (double_int payload, machine_mode mode)
+{
+  FIXED_VALUE_TYPE value;
+
+  gcc_assert (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_DOUBLE_INT);
+
+  if (SIGNED_SCALAR_FIXED_POINT_MODE_P (mode))
+    value.data = payload.sext (1 + GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode));
+  else if (UNSIGNED_SCALAR_FIXED_POINT_MODE_P (mode))
+    value.data = payload.zext (GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode));
+  else
+    gcc_unreachable ();
+
+  value.mode = mode;
+
+  return value;
+}
+
+
 /* Initialize from a decimal or hexadecimal string.  */
 
 void
-fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, enum machine_mode mode)
+fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, machine_mode mode)
 {
   REAL_VALUE_TYPE real_value, fixed_value, base_value;
   unsigned int fbit;
   enum fixed_value_range_code temp;
+  bool fail;
 
   f->mode = mode;
   fbit = GET_MODE_FBIT (mode);
@@ -103,8 +130,10 @@ fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, enum machine_mode mode)
             "large fixed-point constant implicitly truncated to fixed-point type");
   real_2expN (&base_value, fbit, mode);
   real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value);
-  real_to_integer2 ((HOST_WIDE_INT *)&f->data.low, &f->data.high,
-                   &fixed_value);
+  wide_int w = real_to_integer (&fixed_value, &fail,
+                               GET_MODE_PRECISION (mode));
+  f->data.low = w.elt (0);
+  f->data.high = w.elt (1);
 
   if (temp == FIXED_MAX_EPS && ALL_FRACT_MODE_P (f->mode))
     {
@@ -129,9 +158,12 @@ fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig,
 {
   REAL_VALUE_TYPE real_value, base_value, fixed_value;
 
+  signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode) ? UNSIGNED : SIGNED;
   real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), f_orig->mode);
-  real_from_integer (&real_value, VOIDmode, f_orig->data.low, f_orig->data.high,
-                    UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode));
+  real_from_integer (&real_value, VOIDmode,
+                    wide_int::from (f_orig->data,
+                                    GET_MODE_PRECISION (f_orig->mode), sgn),
+                    sgn);
   real_arithmetic (&fixed_value, RDIV_EXPR, &real_value, &base_value);
   real_to_decimal (str, &fixed_value, buf_size, 0, 1);
 }
@@ -145,7 +177,7 @@ fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig,
    Return true, if !SAT_P and overflow.  */
 
 static bool
-fixed_saturate1 (enum machine_mode mode, double_int a, double_int *f,
+fixed_saturate1 (machine_mode mode, double_int a, double_int *f,
                 bool sat_p)
 {
   bool overflow_p = false;
@@ -203,7 +235,7 @@ fixed_saturate1 (enum machine_mode mode, double_int a, double_int *f,
    Return true, if !SAT_P and overflow.  */
 
 static bool
-fixed_saturate2 (enum machine_mode mode, double_int a_high, double_int a_low,
+fixed_saturate2 (machine_mode mode, double_int a_high, double_int a_low,
                 double_int *f, bool sat_p)
 {
   bool overflow_p = false;
@@ -376,9 +408,8 @@ do_fixed_multiply (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
   if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT)
     {
       f->data = a->data * b->data;
-      f->data = f->data.lshift ((-GET_MODE_FBIT (f->mode)),
-                    HOST_BITS_PER_DOUBLE_INT,
-                    !unsigned_p);
+      f->data = f->data.lshift (-GET_MODE_FBIT (f->mode),
+                               HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
       overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
     }
   else
@@ -466,9 +497,8 @@ do_fixed_multiply (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
          f->data.high = f->data.high | s.high;
          s.low = f->data.low;
          s.high = f->data.high;
-         r = r.lshift ((-GET_MODE_FBIT (f->mode)),
-                        HOST_BITS_PER_DOUBLE_INT,
-                        !unsigned_p);
+         r = r.lshift (-GET_MODE_FBIT (f->mode),
+                       HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
        }
 
       overflow_p = fixed_saturate2 (f->mode, r, s, &f->data, sat_p);
@@ -493,8 +523,7 @@ do_fixed_divide (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
   if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT)
     {
       f->data = a->data.lshift (GET_MODE_FBIT (f->mode),
-                    HOST_BITS_PER_DOUBLE_INT,
-                    !unsigned_p);
+                               HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
       f->data = f->data.div (b->data, unsigned_p, TRUNC_DIV_EXPR);
       overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
     }
@@ -548,14 +577,14 @@ do_fixed_divide (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
          int leftmost_mod = (mod.high < 0);
 
          /* Shift left mod by 1 bit.  */
-         mod = mod.llshift (1, HOST_BITS_PER_DOUBLE_INT);
+         mod = mod.lshift (1);
 
          /* Test the leftmost bit of s to add to mod.  */
          if (s.high < 0)
            mod.low += 1;
 
          /* Shift left quo_s by 1 bit.  */
-         quo_s = quo_s.llshift (1, HOST_BITS_PER_DOUBLE_INT);
+         quo_s = quo_s.lshift (1);
 
          /* Try to calculate (mod - pos_b).  */
          temp = mod - pos_b;
@@ -567,7 +596,7 @@ do_fixed_divide (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
            }
 
          /* Shift left s by 1 bit.  */
-         s = s.llshift (1, HOST_BITS_PER_DOUBLE_INT);
+         s = s.lshift (1);
 
        }
 
@@ -612,9 +641,8 @@ do_fixed_shift (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
 
   if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT || (!left_p))
     {
-      f->data = a->data.lshift (left_p ? b->data.low : (-b->data.low),
-                    HOST_BITS_PER_DOUBLE_INT,
-                    !unsigned_p);
+      f->data = a->data.lshift (left_p ? b->data.low : -b->data.low,
+                               HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
       if (left_p) /* Only left shift saturates.  */
        overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
     }
@@ -630,8 +658,7 @@ do_fixed_shift (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
       else
        {
          temp_low = a->data.lshift (b->data.low,
-                        HOST_BITS_PER_DOUBLE_INT,
-                        !unsigned_p);
+                                    HOST_BITS_PER_DOUBLE_INT, !unsigned_p);
          /* Logical shift right to temp_high.  */
          temp_high = a->data.llshift (b->data.low - HOST_BITS_PER_DOUBLE_INT,
                         HOST_BITS_PER_DOUBLE_INT);
@@ -785,7 +812,7 @@ fixed_compare (int icode, const FIXED_VALUE_TYPE *op0,
    Return true, if !SAT_P and overflow.  */
 
 bool
-fixed_convert (FIXED_VALUE_TYPE *f, enum machine_mode mode,
+fixed_convert (FIXED_VALUE_TYPE *f, machine_mode mode,
                const FIXED_VALUE_TYPE *a, bool sat_p)
 {
   bool overflow_p = false;
@@ -801,8 +828,8 @@ fixed_convert (FIXED_VALUE_TYPE *f, enum machine_mode mode,
       double_int temp_high, temp_low;
       int amount = GET_MODE_FBIT (mode) - GET_MODE_FBIT (a->mode);
       temp_low = a->data.lshift (amount,
-                    HOST_BITS_PER_DOUBLE_INT,
-                    SIGNED_FIXED_POINT_MODE_P (a->mode));
+                                HOST_BITS_PER_DOUBLE_INT,
+                                SIGNED_FIXED_POINT_MODE_P (a->mode));
       /* Logical shift right to temp_high.  */
       temp_high = a->data.llshift (amount - HOST_BITS_PER_DOUBLE_INT,
                     HOST_BITS_PER_DOUBLE_INT);
@@ -864,8 +891,8 @@ fixed_convert (FIXED_VALUE_TYPE *f, enum machine_mode mode,
       /* Right shift a to temp based on a->mode.  */
       double_int temp;
       temp = a->data.lshift (GET_MODE_FBIT (mode) - GET_MODE_FBIT (a->mode),
-                    HOST_BITS_PER_DOUBLE_INT,
-                    SIGNED_FIXED_POINT_MODE_P (a->mode));
+                            HOST_BITS_PER_DOUBLE_INT,
+                            SIGNED_FIXED_POINT_MODE_P (a->mode));
       f->mode = mode;
       f->data = temp;
       if (SIGNED_FIXED_POINT_MODE_P (a->mode) ==
@@ -929,7 +956,7 @@ fixed_convert (FIXED_VALUE_TYPE *f, enum machine_mode mode,
    Return true, if !SAT_P and overflow.  */
 
 bool
-fixed_convert_from_int (FIXED_VALUE_TYPE *f, enum machine_mode mode,
+fixed_convert_from_int (FIXED_VALUE_TYPE *f, machine_mode mode,
                        double_int a, bool unsigned_p, bool sat_p)
 {
   bool overflow_p = false;
@@ -1013,7 +1040,7 @@ fixed_convert_from_int (FIXED_VALUE_TYPE *f, enum machine_mode mode,
    Return true, if !SAT_P and overflow.  */
 
 bool
-fixed_convert_from_real (FIXED_VALUE_TYPE *f, enum machine_mode mode,
+fixed_convert_from_real (FIXED_VALUE_TYPE *f, machine_mode mode,
                         const REAL_VALUE_TYPE *a, bool sat_p)
 {
   bool overflow_p = false;
@@ -1022,12 +1049,17 @@ fixed_convert_from_real (FIXED_VALUE_TYPE *f, enum machine_mode mode,
   int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode);
   unsigned int fbit = GET_MODE_FBIT (mode);
   enum fixed_value_range_code temp;
+  bool fail;
 
   real_value = *a;
   f->mode = mode;
   real_2expN (&base_value, fbit, mode);
   real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value);
-  real_to_integer2 ((HOST_WIDE_INT *)&f->data.low, &f->data.high, &fixed_value);
+
+  wide_int w = real_to_integer (&fixed_value, &fail,
+                               GET_MODE_PRECISION (mode));
+  f->data.low = w.elt (0);
+  f->data.high = w.elt (1);
   temp = check_real_for_fixed_mode (&real_value, mode);
   if (temp == FIXED_UNDERFLOW) /* Minimum.  */
     {
@@ -1067,14 +1099,16 @@ fixed_convert_from_real (FIXED_VALUE_TYPE *f, enum machine_mode mode,
 /* Convert to a new real mode from a fixed-point.  */
 
 void
-real_convert_from_fixed (REAL_VALUE_TYPE *r, enum machine_mode mode,
+real_convert_from_fixed (REAL_VALUE_TYPE *r, machine_mode mode,
                         const FIXED_VALUE_TYPE *f)
 {
   REAL_VALUE_TYPE base_value, fixed_value, real_value;
 
+  signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f->mode) ? UNSIGNED : SIGNED;
   real_2expN (&base_value, GET_MODE_FBIT (f->mode), f->mode);
-  real_from_integer (&fixed_value, VOIDmode, f->data.low, f->data.high,
-                    UNSIGNED_FIXED_POINT_MODE_P (f->mode));
+  real_from_integer (&fixed_value, VOIDmode,
+                    wide_int::from (f->data, GET_MODE_PRECISION (f->mode),
+                                    sgn), sgn);
   real_arithmetic (&real_value, RDIV_EXPR, &fixed_value, &base_value);
   real_convert (r, mode, &real_value);
 }