/* Fixed-point arithmetic support.
- Copyright (C) 2006-2013 Free Software Foundation, Inc.
+ Copyright (C) 2006-2020 Free Software Foundation, Inc.
This file is part of GCC.
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;
- real_2expN (&max_value, GET_MODE_IBIT (mode), mode);
- real_2expN (&epsilon_value, -GET_MODE_FBIT (mode), mode);
+ real_2expN (&max_value, GET_MODE_IBIT (mode), VOIDmode);
+ real_2expN (&epsilon_value, -GET_MODE_FBIT (mode), VOIDmode);
if (SIGNED_FIXED_POINT_MODE_P (mode))
min_value = real_value_negate (&max_value);
The bits in PAYLOAD are sign-extended/zero-extended according to MODE. */
FIXED_VALUE_TYPE
-fixed_from_double_int (double_int payload, enum machine_mode mode)
+fixed_from_double_int (double_int payload, scalar_mode mode)
{
FIXED_VALUE_TYPE value;
else if (UNSIGNED_SCALAR_FIXED_POINT_MODE_P (mode))
value.data = payload.zext (GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode));
else
- gcc_unreachable();
+ gcc_unreachable ();
value.mode = mode;
/* 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, scalar_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);
|| (temp == FIXED_MAX_EPS && ALL_ACCUM_MODE_P (f->mode)))
warning (OPT_Woverflow,
"large fixed-point constant implicitly truncated to fixed-point type");
- real_2expN (&base_value, fbit, mode);
+ real_2expN (&base_value, fbit, VOIDmode);
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.ulow ();
+ f->data.high = w.elt (1);
if (temp == FIXED_MAX_EPS && ALL_FRACT_MODE_P (f->mode))
{
{
REAL_VALUE_TYPE real_value, base_value, fixed_value;
- 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));
+ signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode) ? UNSIGNED : SIGNED;
+ real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), VOIDmode);
+ 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);
}
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;
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;
{
case NEGATE_EXPR:
return do_fixed_neg (f, op0, sat_p);
- break;
case PLUS_EXPR:
gcc_assert (op0->mode == op1->mode);
return do_fixed_add (f, op0, op1, false, sat_p);
- break;
case MINUS_EXPR:
gcc_assert (op0->mode == op1->mode);
return do_fixed_add (f, op0, op1, true, sat_p);
- break;
case MULT_EXPR:
gcc_assert (op0->mode == op1->mode);
return do_fixed_multiply (f, op0, op1, sat_p);
- break;
case TRUNC_DIV_EXPR:
gcc_assert (op0->mode == op1->mode);
return do_fixed_divide (f, op0, op1, sat_p);
- break;
case LSHIFT_EXPR:
return do_fixed_shift (f, op0, op1, true, sat_p);
- break;
case RSHIFT_EXPR:
return do_fixed_shift (f, op0, op1, false, sat_p);
- break;
default:
gcc_unreachable ();
Return true, if !SAT_P and overflow. */
bool
-fixed_convert (FIXED_VALUE_TYPE *f, enum machine_mode mode,
+fixed_convert (FIXED_VALUE_TYPE *f, scalar_mode mode,
const FIXED_VALUE_TYPE *a, bool sat_p)
{
bool overflow_p = false;
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, scalar_mode mode,
double_int a, bool unsigned_p, bool sat_p)
{
bool overflow_p = false;
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, scalar_mode mode,
const REAL_VALUE_TYPE *a, bool sat_p)
{
bool overflow_p = false;
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_2expN (&base_value, fbit, VOIDmode);
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.ulow ();
+ f->data.high = w.elt (1);
temp = check_real_for_fixed_mode (&real_value, mode);
if (temp == FIXED_UNDERFLOW) /* Minimum. */
{
/* 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, scalar_mode mode,
const FIXED_VALUE_TYPE *f)
{
REAL_VALUE_TYPE base_value, fixed_value, real_value;
- 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));
+ signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f->mode) ? UNSIGNED : SIGNED;
+ real_2expN (&base_value, GET_MODE_FBIT (f->mode), VOIDmode);
+ 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);
}