+ /* Much like unsigned, except no trimming with addrmask. In
+ addition, the sum overflows if there is a carry out of
+ the bfd_vma, i.e., the sum is less than either input
+ operand. */
+ a >>= rightshift;
+ b >>= bitpos;
+
+ /* Bitfields are sometimes used for signed numbers; for
+ example, a 13-bit field sometimes represents values in
+ 0..8191 and sometimes represents values in -4096..4095.
+ If the field is signed and a is -4095 (0x1001) and b is
+ -1 (0x1fff), the sum is -4096 (0x1000), but (0x1001 +
+ 0x1fff is 0x3000). It's not clear how to handle this
+ everywhere, since there is not way to know how many bits
+ are significant in the relocation, but the original code
+ assumed that it was fully sign extended, and we will keep
+ that assumption. */
+ signmask = (fieldmask >> 1) + 1;
+
+ if ((a & ~ fieldmask) != 0)
+ {
+ /* Some bits out of the field are set. This might not
+ be a problem: if this is a signed bitfield, it is OK
+ iff all the high bits are set, including the sign
+ bit. We'll try setting all but the most significant
+ bit in the original relocation value: if this is all
+ ones, we are OK, assuming a signed bitfield. */
+ ss = (signmask << rightshift) - 1;
+ if ((ss | relocation) != ~ (bfd_vma) 0)
+ overflow = true;
+ a &= fieldmask;
+ }
+
+ /* We just assume (b & ~ fieldmask) == 0. */
+
+ /* We explicitly permit wrap around if this relocation
+ covers the high bit of an address. The Linux kernel
+ relies on it, and it is the only way to write assembler
+ code which can run when loaded at a location 0x80000000
+ away from the location at which it is linked. */
+ if (howto->bitsize + rightshift
+ == bfd_arch_bits_per_address (input_bfd))
+ break;
+
+ sum = a + b;
+ if (sum < a || (sum & ~ fieldmask) != 0)
+ {
+ /* There was a carry out, or the field overflow. Test
+ for signed operands again. Here is the overflow test
+ is as for complain_overflow_signed. */
+ if (((~ (a ^ b)) & (a ^ sum)) & signmask)
+ overflow = true;
+ }
+