-/* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
- overflow. Suppose A, B and SUM have the same respective signs as A1, B1,
- and SUM1. Then this yields nonzero if overflow occurred during the
- addition.
-
- Overflow occurs if A and B have the same sign, but A and SUM differ in
- sign. Use `^' to test whether signs differ, and `< 0' to isolate the
- sign. */
-#define OVERFLOW_SUM_SIGN(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0)
-\f
-/* To do constant folding on INTEGER_CST nodes requires two-word arithmetic.
- We do that by representing the two-word integer in 4 words, with only
- HOST_BITS_PER_WIDE_INT / 2 bits stored in each word, as a positive
- number. The value of the word is LOWPART + HIGHPART * BASE. */
-
-#define LOWPART(x) \
- ((x) & (((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)) - 1))
-#define HIGHPART(x) \
- ((unsigned HOST_WIDE_INT) (x) >> HOST_BITS_PER_WIDE_INT / 2)
-#define BASE ((unsigned HOST_WIDE_INT) 1 << HOST_BITS_PER_WIDE_INT / 2)
-
-/* Unpack a two-word integer into 4 words.
- LOW and HI are the integer, as two `HOST_WIDE_INT' pieces.
- WORDS points to the array of HOST_WIDE_INTs. */
-
-static void
-encode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
-{
- words[0] = LOWPART (low);
- words[1] = HIGHPART (low);
- words[2] = LOWPART (hi);
- words[3] = HIGHPART (hi);
-}
-
-/* Pack an array of 4 words into a two-word integer.
- WORDS points to the array of words.
- The integer is stored into *LOW and *HI as two `HOST_WIDE_INT' pieces. */
-
-static void
-decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low,
- HOST_WIDE_INT *hi)
-{
- *low = words[0] + words[1] * BASE;
- *hi = words[2] + words[3] * BASE;
-}
-\f
-/* 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;
- int sign_extended_type;
-
- if (POINTER_TYPE_P (type)
- || TREE_CODE (type) == OFFSET_TYPE)
- prec = POINTER_SIZE;
- else
- prec = TYPE_PRECISION (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);
-}
-\f
-/* 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.
- One argument is L1 and H1; the other, L2 and H2.
- The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-
-int
-add_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
- bool unsigned_p)
-{
- unsigned HOST_WIDE_INT l;
- HOST_WIDE_INT h;
-
- l = l1 + l2;
- h = h1 + h2 + (l < l1);
-
- *lv = l;
- *hv = h;
-
- if (unsigned_p)
- return (unsigned HOST_WIDE_INT) h < (unsigned HOST_WIDE_INT) h1;
- else
- return OVERFLOW_SUM_SIGN (h1, h2, h);
-}
-
-/* Negate a doubleword integer with doubleword result.
- Return nonzero if the operation overflows, assuming it's signed.
- The argument is given as two `HOST_WIDE_INT' pieces in L1 and H1.
- The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-
-int
-neg_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
-{
- if (l1 == 0)
- {
- *lv = 0;
- *hv = - h1;
- return (*hv & h1) < 0;
- }
- else
- {
- *lv = -l1;
- *hv = ~h1;
- return 0;
- }
-}
-\f
-/* Multiply 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.
- One argument is L1 and H1; the other, L2 and H2.
- The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-
-int
-mul_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
- unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
- unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
- bool unsigned_p)
-{
- HOST_WIDE_INT arg1[4];
- HOST_WIDE_INT arg2[4];
- HOST_WIDE_INT prod[4 * 2];
- unsigned HOST_WIDE_INT carry;
- int i, j, k;
- unsigned HOST_WIDE_INT toplow, neglow;
- HOST_WIDE_INT tophigh, neghigh;
-
- encode (arg1, l1, h1);
- encode (arg2, l2, h2);
-
- memset (prod, 0, sizeof prod);
-
- for (i = 0; i < 4; i++)
- {
- carry = 0;
- for (j = 0; j < 4; j++)
- {
- k = i + j;
- /* This product is <= 0xFFFE0001, the sum <= 0xFFFF0000. */
- carry += arg1[i] * arg2[j];
- /* Since prod[p] < 0xFFFF, this sum <= 0xFFFFFFFF. */
- carry += prod[k];
- prod[k] = LOWPART (carry);
- carry = HIGHPART (carry);
- }
- prod[i + 4] = carry;
- }
-
- decode (prod, lv, hv);
- decode (prod + 4, &toplow, &tophigh);
-
- /* Unsigned overflow is immediate. */
- if (unsigned_p)
- return (toplow | tophigh) != 0;
-
- /* Check for signed overflow by calculating the signed representation of the
- top half of the result; it should agree with the low half's sign bit. */
- if (h1 < 0)
- {
- neg_double (l2, h2, &neglow, &neghigh);
- add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);
- }
- if (h2 < 0)
- {
- neg_double (l1, h1, &neglow, &neghigh);
- add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);
- }
- return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0;
-}
-\f
-/* Shift the doubleword integer in L1, H1 left by COUNT places
- keeping only PREC bits of result.
- Shift right if COUNT is negative.
- ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
- Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */
-
-void
-lshift_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, int arith)