return FAIL;
}
+#if defined BFD_HOST_64_BIT
/* Returns TRUE if double precision value V may be cast
to single precision without loss of accuracy. */
static bfd_boolean
-is_double_a_single (long int v)
+is_double_a_single (bfd_int64_t v)
{
- int exp = (int) (v >> 52) & 0x7FF;
- long int mantissa = (v & 0xFFFFFFFFFFFFFl);
+ int exp = (int)((v >> 52) & 0x7FF);
+ bfd_int64_t mantissa = (v & (bfd_int64_t)0xFFFFFFFFFFFFF);
return (exp == 0 || exp == 0x7FF
|| (exp >= 1023 - 126 && exp <= 1023 + 127))
(ignoring the least significant bits in exponent and mantissa). */
static int
-double_to_single (long int v)
+double_to_single (bfd_int64_t v)
{
int sign = (int) ((v >> 63) & 1l);
- int exp = (int) (v >> 52) & 0x7FF;
- long int mantissa = (v & 0xFFFFFFFFFFFFFl);
+ int exp = (int) ((v >> 52) & 0x7FF);
+ bfd_int64_t mantissa = (v & (bfd_int64_t)0xFFFFFFFFFFFFF);
if (exp == 0x7FF)
exp = 0xFF;
mantissa >>= 29;
return (sign << 31) | (exp << 23) | mantissa;
}
+#endif /* BFD_HOST_64_BIT */
enum lit_type
{
if (inst.reloc.exp.X_op == O_constant
|| inst.reloc.exp.X_op == O_big)
{
+#if defined BFD_HOST_64_BIT
+ bfd_int64_t v;
+#else
offsetT v;
-
+#endif
if (inst.reloc.exp.X_op == O_big)
{
LITTLENUM_TYPE w[X_PRECISION];
else
l = generic_bignum;
+#if defined BFD_HOST_64_BIT
+ v =
+ ((((((((bfd_int64_t) l[3] & LITTLENUM_MASK)
+ << LITTLENUM_NUMBER_OF_BITS)
+ | ((bfd_int64_t) l[2] & LITTLENUM_MASK))
+ << LITTLENUM_NUMBER_OF_BITS)
+ | ((bfd_int64_t) l[1] & LITTLENUM_MASK))
+ << LITTLENUM_NUMBER_OF_BITS)
+ | ((bfd_int64_t) l[0] & LITTLENUM_MASK));
+#else
v = ((l[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS)
| (l[0] & LITTLENUM_MASK);
+#endif
}
else
v = inst.reloc.exp.X_add_number;
if (!inst.operands[i].issingle)
{
- if (thumb_p && inst.reloc.exp.X_op == O_constant)
+ if (thumb_p)
{
- if (!unified_syntax && (v & ~0xFF) == 0)
+ if ((v & ~0xFF) == 0)
{
/* This can be done with a mov(1) instruction. */
inst.instruction = T_OPCODE_MOV_I8 | (inst.operands[i].reg << 8);
inst.instruction |= v;
return TRUE;
}
+
+ if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_arch_t2)
+ && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6t2))
+ {
+ /* Check if on thumb2 it can be done with a mov.w or mvn.w instruction. */
+ unsigned int newimm;
+ bfd_boolean isNegated;
+
+ newimm = encode_thumb32_immediate (v);
+ if (newimm != (unsigned int) FAIL)
+ isNegated = FALSE;
+ else
+ {
+ newimm = encode_thumb32_immediate (~ v);
+ if (newimm != (unsigned int) FAIL)
+ isNegated = TRUE;
+ }
+
+ if (newimm != (unsigned int) FAIL)
+ {
+ inst.instruction = 0xf04f0000 | (inst.operands[i].reg << 8);
+ inst.instruction |= (isNegated?0x200000:0);
+ inst.instruction |= (newimm & 0x800) << 15;
+ inst.instruction |= (newimm & 0x700) << 4;
+ inst.instruction |= (newimm & 0x0ff);
+ return TRUE;
+ }
+ else if ((v & ~0xFFFF) == 0 || (v & ~0xFFFF0000) == 0)
+ {
+ /* The number may be loaded with a movw/movt instruction. */
+ int imm;
+
+ if ((inst.reloc.exp.X_add_number & ~0xFFFF) == 0)
+ {
+ inst.instruction= 0xf2400000;
+ imm = v;
+ }
+ else
+ {
+ inst.instruction = 0xf2c00000;
+ imm = v >> 16;
+ }
+
+ inst.instruction |= (inst.operands[i].reg << 8);
+ inst.instruction |= (imm & 0xf000) << 4;
+ inst.instruction |= (imm & 0x0800) << 15;
+ inst.instruction |= (imm & 0x0700) << 4;
+ inst.instruction |= (imm & 0x00ff);
+ return TRUE;
+ }
+ }
}
- else if (arm_p && inst.reloc.exp.X_op == O_constant)
+ else if (arm_p)
{
int value = encode_arm_immediate (v);
+
if (value != FAIL)
{
/* This can be done with a mov instruction. */
do_vfp_nsyn_opcode ("fconsts");
return TRUE;
}
+
+ /* If our host does not support a 64-bit type then we cannot perform
+ the following optimization. This mean that there will be a
+ discrepancy between the output produced by an assembler built for
+ a 32-bit-only host and the output produced from a 64-bit host, but
+ this cannot be helped. */
+#if defined BFD_HOST_64_BIT
else if (!inst.operands[1].issingle
&& ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v3))
{
return TRUE;
}
}
+#endif
}
}
|| (thumb_mode == 1
&& !ARM_CPU_HAS_FEATURE (variant, *opcode->tvariant)))
{
- as_bad (_("selected processor does not support Thumb mode `%s'"), str);
+ as_bad (_("selected processor does not support `%s' in Thumb mode"), str);
return;
}
if (inst.cond != COND_ALWAYS && !unified_syntax
inst.size_req = 2;
else if (inst.size_req == 4)
{
- as_bad (_("selected processor does not support Thumb-2 mode `%s'"), str);
+ as_bad (_("selected processor does not support `%s' in Thumb-2 mode"), str);
return;
}
}
&& !(opcode->avariant &&
ARM_CPU_HAS_FEATURE (cpu_variant, *opcode->avariant)))
{
- as_bad (_("selected processor does not support ARM mode `%s'"), str);
+ as_bad (_("selected processor does not support `%s' in ARM mode"), str);
return;
}
if (inst.size_req)
if (rd == REG_SP)
{
- if (value & ~0x1fc)
+ if (value & ~0x1fc)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("invalid immediate for stack address calculation"));
newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
}
else if (rs == REG_PC || rs == REG_SP)
{
+ /* PR gas/18541. If the addition is for a defined symbol
+ within range of an ADR instruction then accept it. */
+ if (subtract
+ && value == 4
+ && fixP->fx_addsy != NULL)
+ {
+ subtract = 0;
+
+ if (! S_IS_DEFINED (fixP->fx_addsy)
+ || S_GET_SEGMENT (fixP->fx_addsy) != seg
+ || S_IS_WEAK (fixP->fx_addsy))
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("address calculation needs a strongly defined nearby symbol"));
+ }
+ else
+ {
+ offsetT v = fixP->fx_where + fixP->fx_frag->fr_address;
+
+ /* Round up to the next 4-byte boundary. */
+ if (v & 3)
+ v = (v + 3) & ~ 3;
+ else
+ v += 4;
+ v = S_GET_VALUE (fixP->fx_addsy) - v;
+
+ if (v & ~0x3fc)
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("symbol too far away"));
+ }
+ else
+ {
+ fixP->fx_done = 1;
+ value = v;
+ }
+ }
+ }
+
if (subtract || value & ~0x3fc)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("invalid immediate for address calculation (value = 0x%08lX)"),
- (unsigned long) value);
+ (unsigned long) (subtract ? - value : value));
newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
newval |= rd << 8;
newval |= value >> 2;
case BFD_RELOC_ARM_SBREL32:
case BFD_RELOC_ARM_PREL31:
case BFD_RELOC_ARM_TARGET2:
- case BFD_RELOC_ARM_TLS_LE32:
case BFD_RELOC_ARM_TLS_LDO32:
case BFD_RELOC_ARM_PCREL_CALL:
case BFD_RELOC_ARM_PCREL_JUMP:
case BFD_RELOC_ARM_TLS_GOTDESC:
case BFD_RELOC_ARM_TLS_GD32:
+ case BFD_RELOC_ARM_TLS_LE32:
case BFD_RELOC_ARM_TLS_IE32:
case BFD_RELOC_ARM_TLS_LDM32:
/* BFD will include the symbol's address in the addend.
{"crypto-neon-fp-armv8",
FPU_ARCH_CRYPTO_NEON_VFP_ARMV8},
{"neon-fp-armv8.1", FPU_ARCH_NEON_VFP_ARMV8_1},
+ {"crypto-neon-fp-armv8.1",
+ FPU_ARCH_CRYPTO_NEON_VFP_ARMV8_1},
{NULL, ARM_ARCH_NONE}
};