IA MCU psABI support: changes to libraries
[gcc.git] / gcc / fixed-value.c
index b74a60e29f25d13afa9ebde617f822688fdfaf64..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;
@@ -545,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;
@@ -564,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);
 
        }
 
@@ -780,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;
@@ -924,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;
@@ -1008,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;
@@ -1017,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.  */
     {
@@ -1062,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);
 }