}
}
+ /* If TC_CASE_SENSITIVE is defined, then newname already points to
+ the desired alias name, and p points to its end. If not, then
+ the desired alias name is in the global original_case_string. */
+#ifdef TC_CASE_SENSITIVE
namelen = nameend - newname;
+#else
+ newname = original_case_string;
+ namelen = strlen (newname);
+#endif
+
namebuf = (char *) alloca (namelen + 1);
strncpy (namebuf, newname, namelen);
namebuf[namelen] = '\0';
}
}
else if (exp.X_op == O_big
- && LITTLENUM_NUMBER_OF_BITS * exp.X_add_number > 32
- && LITTLENUM_NUMBER_OF_BITS * exp.X_add_number <= 64)
+ && LITTLENUM_NUMBER_OF_BITS * exp.X_add_number > 32)
{
unsigned parts = 32 / LITTLENUM_NUMBER_OF_BITS, j, idx = 0;
+
/* Bignums have their least significant bits in
generic_bignum[0]. Make sure we put 32 bits in imm and
32 bits in reg, in a (hopefully) portable way. */
gas_assert (parts != 0);
+
+ /* Make sure that the number is not too big.
+ PR 11972: Bignums can now be sign-extended to the
+ size of a .octa so check that the out of range bits
+ are all zero or all one. */
+ if (LITTLENUM_NUMBER_OF_BITS * exp.X_add_number > 64)
+ {
+ LITTLENUM_TYPE m = -1;
+
+ if (generic_bignum[parts * 2] != 0
+ && generic_bignum[parts * 2] != m)
+ return FAIL;
+
+ for (j = parts * 2 + 1; j < (unsigned) exp.X_add_number; j++)
+ if (generic_bignum[j] != generic_bignum[j-1])
+ return FAIL;
+ }
+
inst.operands[i].imm = 0;
for (j = 0; j < parts; j++, idx++)
inst.operands[i].imm |= generic_bignum[idx]
OP_oSHar, /* ASR immediate */
OP_oSHllar, /* LSL or ASR immediate */
OP_oROR, /* ROR 0/8/16/24 */
- OP_oBARRIER, /* Option argument for a barrier instruction. */
+ OP_oBARRIER_I15, /* Option argument for a barrier instruction. */
/* Some pre-defined mixed (ARM/THUMB) operands. */
OP_RR_npcsp = MIX_ARM_THUMB_OPERANDS (OP_RR, OP_RRnpcsp),
} \
while (0)
+#define po_barrier_or_imm(str) \
+ do \
+ { \
+ val = parse_barrier (&str); \
+ if (val == FAIL) \
+ { \
+ if (ISALPHA (*str)) \
+ goto failure; \
+ else \
+ goto immediate; \
+ } \
+ else \
+ { \
+ if ((inst.instruction & 0xf0) == 0x60 \
+ && val != 0xf) \
+ { \
+ /* ISB can only take SY as an option. */ \
+ inst.error = _("invalid barrier type"); \
+ goto failure; \
+ } \
+ } \
+ } \
+ while (0)
+
skip_whitespace (str);
for (i = 0; upat[i] != OP_stop; i++)
case OP_oROR: val = parse_ror (&str); break;
case OP_PSR: val = parse_psr (&str); break;
case OP_COND: val = parse_cond (&str); break;
- case OP_oBARRIER:val = parse_barrier (&str); break;
+ case OP_oBARRIER_I15:
+ po_barrier_or_imm (str); break;
+ immediate:
+ if (parse_immediate (&str, &val, 0, 15, TRUE) == FAIL)
+ goto failure;
+ break;
case OP_RVC_PSR:
po_reg_or_goto (REG_TYPE_VFC, try_psr);
case OP_PSR:
case OP_RVC_PSR:
case OP_COND:
- case OP_oBARRIER:
+ case OP_oBARRIER_I15:
case OP_REGLST:
case OP_VRSLST:
case OP_VRDLST:
#undef po_reg_or_goto
#undef po_imm_or_fail
#undef po_scalar_or_fail
+#undef po_barrier_or_imm
/* Shorthand macro for instruction encoding functions issuing errors. */
#define constraint(expr, err) \
if (is_pc && !inst.reloc.pc_rel)
{
const bfd_boolean is_load = ((inst.instruction & LOAD_BIT) != 0);
- /* BAD_PC_ADDRESSING Condition =
- is_load => is_t
- which becomes !is_load || is_t. */
- constraint ((!is_load || is_t),
+
+ /* If is_t is TRUE, it's called from do_ldstt. ldrt/strt
+ cannot use PC in addressing.
+ PC cannot be used in writeback addressing, either. */
+ constraint ((is_t || inst.operands[i].writeback),
BAD_PC_ADDRESSING);
+
+ /* Use of PC in str is deprecated for ARMv7. */
+ if (warn_on_deprecated
+ && !is_load
+ && ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v7))
+ as_warn (_("use of PC in this instruction is deprecated"));
}
if (inst.reloc.type == BFD_RELOC_UNUSED)
if (inst.operands[0].present)
{
constraint ((inst.instruction & 0xf0) != 0x40
- && inst.operands[0].imm != 0xf,
+ && inst.operands[0].imm > 0xf
+ && inst.operands[0].imm < 0x0,
_("bad barrier type"));
inst.instruction |= inst.operands[0].imm;
}
if (inst.operands[0].present)
{
constraint ((inst.instruction & 0xf0) != 0x40
- && inst.operands[0].imm != 0xf,
+ && inst.operands[0].imm > 0xf
+ && inst.operands[0].imm < 0x0,
_("bad barrier type"));
inst.instruction |= inst.operands[0].imm;
}
reject_bad_reg (Rn);
reject_bad_reg (Rm);
}
- else if ((Rn == REG_SP || Rn == REG_PC)
- && (Rm == REG_SP || Rm == REG_PC))
- reject_bad_reg (Rm);
+ else if (narrow)
+ {
+ /* This is mov.n. */
+ if ((Rn == REG_SP || Rn == REG_PC)
+ && (Rm == REG_SP || Rm == REG_PC))
+ {
+ as_warn (_("Use of r%u as a source register is "
+ "deprecated when r%u is the destination "
+ "register."), Rm, Rn);
+ }
+ }
+ else
+ {
+ /* This is mov.w. */
+ constraint (Rn == REG_PC, BAD_PC);
+ constraint (Rm == REG_PC, BAD_PC);
+ constraint (Rn == REG_SP && Rm == REG_SP, BAD_SP);
+ }
}
else
reject_bad_reg (Rn);
static struct asm_barrier_opt barrier_opt_names[] =
{
- { "sy", 0xf },
- { "un", 0x7 },
- { "st", 0xe },
- { "unst", 0x6 }
+ { "sy", 0xf }, { "SY", 0xf },
+ { "un", 0x7 }, { "UN", 0x7 },
+ { "st", 0xe }, { "ST", 0xe },
+ { "unst", 0x6 }, { "UNST", 0x6 },
+ { "ish", 0xb }, { "ISH", 0xb },
+ { "sh", 0xb }, { "SH", 0xb },
+ { "ishst", 0xa }, { "ISHST", 0xa },
+ { "shst", 0xa }, { "SHST", 0xa },
+ { "nsh", 0x7 }, { "NSH", 0x7 },
+ { "nshst", 0x6 }, { "NSHST", 0x6 },
+ { "osh", 0x3 }, { "OSH", 0x3 },
+ { "oshst", 0x2 }, { "OSHST", 0x2 }
};
/* Table of ARM-format instructions. */
#undef THUMB_VARIANT
#define THUMB_VARIANT & arm_ext_barrier
- TUF("dmb", 57ff050, f3bf8f50, 1, (oBARRIER), barrier, t_barrier),
- TUF("dsb", 57ff040, f3bf8f40, 1, (oBARRIER), barrier, t_barrier),
- TUF("isb", 57ff060, f3bf8f60, 1, (oBARRIER), barrier, t_barrier),
+ TUF("dmb", 57ff050, f3bf8f50, 1, (oBARRIER_I15), barrier, t_barrier),
+ TUF("dsb", 57ff040, f3bf8f40, 1, (oBARRIER_I15), barrier, t_barrier),
+ TUF("isb", 57ff060, f3bf8f60, 1, (oBARRIER_I15), barrier, t_barrier),
/* ARM V7 instructions. */
#undef ARM_VARIANT
/* Turn add/sum into addw/subw. */
if (fixP->fx_r_type == BFD_RELOC_ARM_T32_ADD_IMM)
newval = (newval & 0xfeffffff) | 0x02000000;
-
- /* 12 bit immediate for addw/subw. */
- if (value < 0)
+ /* No flat 12-bit imm encoding for addsw/subsw. */
+ if ((newval & 0x00100000) == 0)
{
- value = -value;
- newval ^= 0x00a00000;
+ /* 12 bit immediate for addw/subw. */
+ if (value < 0)
+ {
+ value = -value;
+ newval ^= 0x00a00000;
+ }
+ if (value > 0xfff)
+ newimm = (unsigned int) FAIL;
+ else
+ newimm = value;
}
- if (value > 0xfff)
- newimm = (unsigned int) FAIL;
- else
- newimm = value;
}
if (newimm == (unsigned int)FAIL)
case BFD_RELOC_ARM_SWI: type = "SWI"; break;
case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
+ case BFD_RELOC_ARM_T32_OFFSET_IMM: type = "T32_OFFSET_IMM"; break;
case BFD_RELOC_ARM_T32_CP_OFF_IMM: type = "T32_CP_OFF_IMM"; break;
case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
{"cortex-a9", ARM_ARCH_V7A, ARM_FEATURE (0, FPU_VFP_V3
| FPU_NEON_EXT_V1),
NULL},
+ {"cortex-a15", ARM_ARCH_V7A, FPU_ARCH_NEON_VFP_V4,
+ "Cortex-A15"},
{"cortex-r4", ARM_ARCH_V7R, FPU_NONE, NULL},
{"cortex-r4f", ARM_ARCH_V7R, FPU_ARCH_VFP_V3D16, NULL},
{"cortex-m4", ARM_ARCH_V7EM, FPU_NONE, NULL},