#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
+#include "tm.h" /* For SHIFT_COUNT_TRUNCATED. */
#include "tree.h"
/* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
*hi = words[2] + words[3] * BASE;
}
-/* Force the double-word integer L1, H1 to be within the range of the
- integer type TYPE. Stores the properly truncated and sign-extended
- double-word integer in *LV, *HV. Returns true if the operation
- overflows, that is, argument and result are different. */
-
-int
-fit_double_type (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, const_tree type)
-{
- unsigned HOST_WIDE_INT low0 = l1;
- HOST_WIDE_INT high0 = h1;
- unsigned int prec = TYPE_PRECISION (type);
- int sign_extended_type;
-
- /* Size types *are* sign extended. */
- sign_extended_type = (!TYPE_UNSIGNED (type)
- || (TREE_CODE (type) == INTEGER_TYPE
- && TYPE_IS_SIZETYPE (type)));
-
- /* First clear all bits that are beyond the type's precision. */
- if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
- ;
- else if (prec > HOST_BITS_PER_WIDE_INT)
- h1 &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
- else
- {
- h1 = 0;
- if (prec < HOST_BITS_PER_WIDE_INT)
- l1 &= ~((HOST_WIDE_INT) (-1) << prec);
- }
-
- /* Then do sign extension if necessary. */
- if (!sign_extended_type)
- /* No sign extension */;
- else if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
- /* Correct width already. */;
- else if (prec > HOST_BITS_PER_WIDE_INT)
- {
- /* Sign extend top half? */
- if (h1 & ((unsigned HOST_WIDE_INT)1
- << (prec - HOST_BITS_PER_WIDE_INT - 1)))
- h1 |= (HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT);
- }
- else if (prec == HOST_BITS_PER_WIDE_INT)
- {
- if ((HOST_WIDE_INT)l1 < 0)
- h1 = -1;
- }
- else
- {
- /* Sign extend bottom half? */
- if (l1 & ((unsigned HOST_WIDE_INT)1 << (prec - 1)))
- {
- h1 = -1;
- l1 |= (HOST_WIDE_INT)(-1) << prec;
- }
- }
-
- *lv = l1;
- *hv = h1;
-
- /* If the value didn't fit, signal overflow. */
- return l1 != low0 || h1 != high0;
-}
-
-/* We force the double-int HIGH:LOW to the range of the type TYPE by
- sign or zero extending it.
- OVERFLOWABLE indicates if we are interested
- in overflow of the value, when >0 we are only interested in signed
- overflow, for <0 we are interested in any overflow. OVERFLOWED
- indicates whether overflow has already occurred. CONST_OVERFLOWED
- indicates whether constant overflow has already occurred. We force
- T's value to be within range of T's type (by setting to 0 or 1 all
- the bits outside the type's range). We set TREE_OVERFLOWED if,
- OVERFLOWED is nonzero,
- or OVERFLOWABLE is >0 and signed overflow occurs
- or OVERFLOWABLE is <0 and any overflow occurs
- We return a new tree node for the extended double-int. The node
- is shared if no overflow flags are set. */
-
-tree
-force_fit_type_double (tree type, unsigned HOST_WIDE_INT low,
- HOST_WIDE_INT high, int overflowable,
- bool overflowed)
-{
- int sign_extended_type;
- bool overflow;
-
- /* Size types *are* sign extended. */
- sign_extended_type = (!TYPE_UNSIGNED (type)
- || (TREE_CODE (type) == INTEGER_TYPE
- && TYPE_IS_SIZETYPE (type)));
-
- overflow = fit_double_type (low, high, &low, &high, type);
-
- /* If we need to set overflow flags, return a new unshared node. */
- if (overflowed || overflow)
- {
- if (overflowed
- || overflowable < 0
- || (overflowable > 0 && sign_extended_type))
- {
- tree t = make_node (INTEGER_CST);
- TREE_INT_CST_LOW (t) = low;
- TREE_INT_CST_HIGH (t) = high;
- TREE_TYPE (t) = type;
- TREE_OVERFLOW (t) = 1;
- return t;
- }
- }
-
- /* Else build a shared node. */
- return build_int_cst_wide (type, low, high);
-}
-
/* Add two doubleword integers with doubleword result.
Return nonzero if the operation overflows according to UNSIGNED_P.
Each argument is given as two `HOST_WIDE_INT' pieces.
}
}
-/* Rotate the doubleword integer in L1, H1 left by COUNT places
- keeping only PREC bits of result.
- Rotate right if COUNT is negative.
- Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-
-void
-lrotate_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- HOST_WIDE_INT count, unsigned int prec,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
-{
- unsigned HOST_WIDE_INT s1l, s2l;
- HOST_WIDE_INT s1h, s2h;
-
- count %= prec;
- if (count < 0)
- count += prec;
-
- lshift_double (l1, h1, count, prec, &s1l, &s1h, 0);
- rshift_double (l1, h1, prec - count, prec, &s2l, &s2h, 0);
- *lv = s1l | s2l;
- *hv = s1h | s2h;
-}
-
-/* Rotate the doubleword integer in L1, H1 left by COUNT places
- keeping only PREC bits of result. COUNT must be positive.
- Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-
-void
-rrotate_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- HOST_WIDE_INT count, unsigned int prec,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
-{
- unsigned HOST_WIDE_INT s1l, s2l;
- HOST_WIDE_INT s1h, s2h;
-
- count %= prec;
- if (count < 0)
- count += prec;
-
- rshift_double (l1, h1, count, prec, &s1l, &s1h, 0);
- lshift_double (l1, h1, prec - count, prec, &s2l, &s2h, 0);
- *lv = s1l | s2l;
- *hv = s1h | s2h;
-}
-
/* Divide doubleword integer LNUM, HNUM by doubleword integer LDEN, HDEN
for a quotient (stored in *LQUO, *HQUO) and remainder (in *LREM, *HREM).
CODE is a tree code for a kind of division, one of
return r;
}
-/* Constructs long integer from tree CST. The extra bits over the precision of
- the number are filled with sign bit if CST is signed, and with zeros if it
- is unsigned. */
-
-double_int
-tree_to_double_int (const_tree cst)
-{
- /* We do not need to call double_int_restrict here to ensure the semantics as
- described, as this is the default one for trees. */
- return TREE_INT_CST (cst);
-}
-
-/* Returns true if CST fits in unsigned HOST_WIDE_INT. */
-
-bool
-double_int_fits_in_uhwi_p (double_int cst)
-{
- return cst.high == 0;
-}
-
/* Returns true if CST fits in signed HOST_WIDE_INT. */
bool
return double_int_fits_in_shwi_p (cst);
}
-/* Returns value of CST as a signed number. CST must satisfy
- double_int_fits_in_shwi_p. */
+/* Returns A * B. */
-HOST_WIDE_INT
-double_int_to_shwi (double_int cst)
+double_int
+double_int_mul (double_int a, double_int b)
{
- return (HOST_WIDE_INT) cst.low;
+ double_int ret;
+ mul_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
+ return ret;
}
-/* Returns value of CST as an unsigned number. CST must satisfy
- double_int_fits_in_uhwi_p. */
+/* Returns A * B. If the operation overflows according to UNSIGNED_P,
+ *OVERFLOW is set to nonzero. */
-unsigned HOST_WIDE_INT
-double_int_to_uhwi (double_int cst)
+double_int
+double_int_mul_with_sign (double_int a, double_int b,
+ bool unsigned_p, int *overflow)
{
- return cst.low;
+ double_int ret;
+ *overflow = mul_double_with_sign (a.low, a.high, b.low, b.high,
+ &ret.low, &ret.high, unsigned_p);
+ return ret;
}
-/* Returns A * B. */
+/* Returns A + B. */
double_int
-double_int_mul (double_int a, double_int b)
+double_int_add (double_int a, double_int b)
{
double_int ret;
- mul_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
+ add_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
return ret;
}
-/* Returns A + B. */
+/* Returns A - B. */
double_int
-double_int_add (double_int a, double_int b)
+double_int_sub (double_int a, double_int b)
{
double_int ret;
+ neg_double (b.low, b.high, &b.low, &b.high);
add_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
return ret;
}
return double_int_mod (a, b, true, code);
}
+/* Set BITPOS bit in A. */
+double_int
+double_int_setbit (double_int a, unsigned bitpos)
+{
+ if (bitpos < HOST_BITS_PER_WIDE_INT)
+ a.low |= (unsigned HOST_WIDE_INT) 1 << bitpos;
+ else
+ a.high |= (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
+
+ return a;
+}
+
+/* Count trailing zeros in A. */
+int
+double_int_ctz (double_int a)
+{
+ unsigned HOST_WIDE_INT w = a.low ? a.low : (unsigned HOST_WIDE_INT) a.high;
+ unsigned bits = a.low ? 0 : HOST_BITS_PER_WIDE_INT;
+ if (!w)
+ return HOST_BITS_PER_DOUBLE_INT;
+ bits += ctz_hwi (w);
+ return bits;
+}
+
/* Shift A left by COUNT places keeping only PREC bits of result. Shift
right if COUNT is negative. ARITH true specifies arithmetic shifting;
otherwise use logical shift. */
return ret;
}
-/* Constructs tree in type TYPE from with value given by CST. Signedness of CST
- is assumed to be the same as the signedness of TYPE. */
+/* Rotate A left by COUNT places keeping only PREC bits of result.
+ Rotate right if COUNT is negative. */
-tree
-double_int_to_tree (tree type, double_int cst)
+double_int
+double_int_lrotate (double_int a, HOST_WIDE_INT count, unsigned int prec)
{
- cst = double_int_ext (cst, TYPE_PRECISION (type), TYPE_UNSIGNED (type));
+ double_int t1, t2;
+
+ count %= prec;
+ if (count < 0)
+ count += prec;
- return build_int_cst_wide (type, cst.low, cst.high);
+ t1 = double_int_lshift (a, count, prec, false);
+ t2 = double_int_rshift (a, prec - count, prec, false);
+
+ return double_int_ior (t1, t2);
}
-/* Returns true if CST fits into range of TYPE. Signedness of CST is assumed
- to be the same as the signedness of TYPE. */
+/* Rotate A rigth by COUNT places keeping only PREC bits of result.
+ Rotate right if COUNT is negative. */
-bool
-double_int_fits_to_tree_p (const_tree type, double_int cst)
+double_int
+double_int_rrotate (double_int a, HOST_WIDE_INT count, unsigned int prec)
{
- double_int ext = double_int_ext (cst,
- TYPE_PRECISION (type),
- TYPE_UNSIGNED (type));
+ double_int t1, t2;
+
+ count %= prec;
+ if (count < 0)
+ count += prec;
- return double_int_equal_p (cst, ext);
+ t1 = double_int_rshift (a, count, prec, false);
+ t2 = double_int_lshift (a, prec - count, prec, false);
+
+ return double_int_ior (t1, t2);
}
/* Returns -1 if A < B, 0 if A == B and 1 if A > B. Signedness of the
return 0;
}
+/* Compares two values A and B. Returns max value. Signedness of the
+ comparison is given by UNS. */
+
+double_int
+double_int_max (double_int a, double_int b, bool uns)
+{
+ return (double_int_cmp (a, b, uns) == 1) ? a : b;
+}
+
+/* Compares two signed values A and B. Returns max value. */
+
+double_int double_int_smax (double_int a, double_int b)
+{
+ return (double_int_scmp (a, b) == 1) ? a : b;
+}
+
+/* Compares two unsigned values A and B. Returns max value. */
+
+double_int double_int_umax (double_int a, double_int b)
+{
+ return (double_int_ucmp (a, b) == 1) ? a : b;
+}
+
+/* Compares two values A and B. Returns mix value. Signedness of the
+ comparison is given by UNS. */
+
+double_int double_int_min (double_int a, double_int b, bool uns)
+{
+ return (double_int_cmp (a, b, uns) == -1) ? a : b;
+}
+
+/* Compares two signed values A and B. Returns min value. */
+
+double_int double_int_smin (double_int a, double_int b)
+{
+ return (double_int_scmp (a, b) == -1) ? a : b;
+}
+
+/* Compares two unsigned values A and B. Returns min value. */
+
+double_int double_int_umin (double_int a, double_int b)
+{
+ return (double_int_ucmp (a, b) == -1) ? a : b;
+}
+
/* Splits last digit of *CST (taken as unsigned) in BASE and returns it. */
static unsigned