static const arm_feature_set arm_ext_v7 = ARM_FEATURE_CORE_LOW (ARM_EXT_V7);
static const arm_feature_set arm_ext_v7a = ARM_FEATURE_CORE_LOW (ARM_EXT_V7A);
static const arm_feature_set arm_ext_v7r = ARM_FEATURE_CORE_LOW (ARM_EXT_V7R);
+static const arm_feature_set arm_ext_v8r = ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8R);
#ifdef OBJ_ELF
static const arm_feature_set ATTRIBUTE_UNUSED arm_ext_v7m = ARM_FEATURE_CORE_LOW (ARM_EXT_V7M);
#endif
MVE_OUTSIDE_PRED_INSN , /* Instruction to indicate a MVE instruction without
a predication code. */
MVE_UNPREDICABLE_INSN, /* MVE instruction that is non-predicable. */
- NEUTRAL_IT_NO_VPT_INSN, /* Instruction that can be either inside or outside
- an IT block, but must not be in a VPT block. */
};
/* The maximum number of operands we need. */
[REG_TYPE_MMXWCG] = N_("iWMMXt scalar register expected"),
[REG_TYPE_XSCALE] = N_("XScale accumulator register expected"),
[REG_TYPE_MQ] = N_("MVE vector register expected"),
- [REG_TYPE_RNB] = N_("")
+ [REG_TYPE_RNB] = ""
};
/* Some well known registers that we refer to directly elsewhere. */
hash_delete (arm_reg_hsh, name, FALSE);
free ((char *) reg->name);
- if (reg->neon)
- free (reg->neon);
+ free (reg->neon);
free (reg);
/* Also locate the all upper case and all lower case versions.
{
hash_delete (arm_reg_hsh, nbuf, FALSE);
free ((char *) reg->name);
- if (reg->neon)
- free (reg->neon);
+ free (reg->neon);
free (reg);
}
{
hash_delete (arm_reg_hsh, nbuf, FALSE);
free ((char *) reg->name);
- if (reg->neon)
- free (reg->neon);
+ free (reg->neon);
free (reg);
}
}
return;
-error:
+ error:
ignore_rest_of_line ();
}
op = 0xc700 | mask;
add_unwind_opcode (op, 2);
return;
-error:
+ error:
ignore_rest_of_line ();
}
as_warn (_("float16 format cannot be set more than once, ignoring."));
}
-cleanup:
+ cleanup:
*input_line_pointer = saved_char;
ignore_rest_of_line ();
}
goto unsupported_psr;
p += 4;
-check_suffix:
+ check_suffix:
if (*p == '_')
{
/* A suffix follows. */
OP_RNDMQ, /* Neon double precision (0..31) or MVE vector register. */
OP_RNDMQR, /* Neon double precision (0..31), MVE vector or ARM register.
*/
+ OP_RNSDMQR, /* Neon single or double precision, MVE vector or ARM register.
+ */
OP_RNQ, /* Neon quad precision register */
OP_RNQMQ, /* Neon quad or MVE vector register. */
OP_RVSD, /* VFP single or double precision register */
OP_oRNSDQ, /* Optional single, double or quad precision vector register */
OP_oRNSDQMQ, /* Optional single, double or quad register or MVE vector
register. */
+ OP_oRNSDMQ, /* Optional single, double register or MVE vector
+ register. */
OP_oSHll, /* LSL immediate */
OP_oSHar, /* ASR immediate */
OP_oSHllar, /* LSL or ASR immediate */
case OP_RVS: po_reg_or_fail (REG_TYPE_VFS); break;
case OP_RVD: po_reg_or_fail (REG_TYPE_VFD); break;
case OP_oRND:
+ case OP_RNSDMQR:
+ po_reg_or_goto (REG_TYPE_VFS, try_rndmqr);
+ break;
+ try_rndmqr:
case OP_RNDMQR:
po_reg_or_goto (REG_TYPE_RN, try_rndmq);
break;
case OP_RVSD_COND:
po_reg_or_goto (REG_TYPE_VFSD, try_cond);
break;
+ case OP_oRNSDMQ:
case OP_RNSDMQ:
po_reg_or_goto (REG_TYPE_NSD, try_mq2);
break;
enum neon_shape rs = neon_select_shape (NS_HHH, NS_FFF, NS_DDD, NS_DDS,
NS_QQS, NS_QQQ, NS_QQR, NS_NULL);
- if (!ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext)
- && inst.cond == COND_ALWAYS
+ if (inst.cond == COND_ALWAYS
&& ((unsigned)inst.instruction) == M_MNEM_vmullt)
{
+
if (rs == NS_QQQ)
{
-
- struct neon_type_el et = neon_check_type (3, rs, N_EQK , N_EQK,
- N_SUF_32 | N_F64 | N_P8
- | N_P16 | N_I_MVE | N_KEY);
- if (((et.type == NT_poly) && et.size == 8
- && ARM_CPU_IS_ANY (cpu_variant))
- || (et.type == NT_integer) || (et.type == NT_float))
+ if (!ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext))
goto neon_vmul;
}
else
return;
-neon_vmul:
+ neon_vmul:
inst.instruction = N_MNEM_vmul;
inst.cond = 0xb;
if (thumb_mode)
static void
do_neon_dyadic_long (void)
{
- enum neon_shape rs = neon_select_shape (NS_QDD, NS_QQQ, NS_QQR, NS_NULL);
+ enum neon_shape rs = neon_select_shape (NS_QDD, NS_HHH, NS_FFF, NS_DDD, NS_NULL);
if (rs == NS_QDD)
{
if (vfp_or_neon_is_neon (NEON_CHECK_ARCH | NEON_CHECK_CC) == FAIL)
| ((elno & 0x1) << 3));
}
-bad_scalar:
+ bad_scalar:
first_error (_("scalar out of range for multiply instruction"));
return 0;
}
static void
cxn_handle_predication (bfd_boolean is_accum)
{
- /* This function essentially checks for a suffix, not whether the instruction
- is inside an IT block or not.
- The CX* instructions should never have a conditional suffix -- this is not
- mentioned in the syntax. */
- if (conditional_insn ())
+ if (is_accum && conditional_insn ())
+ set_pred_insn_type (INSIDE_IT_INSN);
+ else if (conditional_insn ())
+ /* conditional_insn essentially checks for a suffix, not whether the
+ instruction is inside an IT block or not.
+ The non-accumulator versions should not have suffixes. */
inst.error = BAD_SYNTAX;
- /* Here we ensure that if the current element */
- else if (is_accum)
- set_pred_insn_type (NEUTRAL_IT_NO_VPT_INSN);
else
set_pred_insn_type (OUTSIDE_PRED_INSN);
}
vcx_handle_register_arguments (unsigned num_registers,
enum vcx_reg_type reg_type)
{
- unsigned R;
+ unsigned R, i;
unsigned reg_mult = vcx_handle_shape (reg_type);
- for (unsigned i = 0; i < num_registers; i++)
+ for (i = 0; i < num_registers; i++)
{
R = inst.operands[i+1].reg;
vcx_ensure_register_in_range (R, reg_type);
gas_assert (0);
case IF_INSIDE_IT_LAST_INSN:
case NEUTRAL_IT_INSN:
- case NEUTRAL_IT_NO_VPT_INSN:
break;
case VPT_INSN:
close_automatic_it_block ();
break;
- case NEUTRAL_IT_NO_VPT_INSN:
- if (now_pred.type == VECTOR_PRED)
- {
- inst.error = BAD_NO_VPT;
- break;
- }
/* Fallthrough. */
case NEUTRAL_IT_INSN:
now_pred.block_length++;
}
break;
- case NEUTRAL_IT_NO_VPT_INSN:
- if (now_pred.type == VECTOR_PRED)
- {
- inst.error = BAD_NO_VPT;
- break;
- }
- /* Fallthrough. */
case NEUTRAL_IT_INSN:
/* The BKPT instruction is unconditional even in a IT or VPT
block. */
&& warn_on_restrict_it
&& !now_pred.warn_deprecated
&& warn_on_deprecated
- && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v8)
+ && (ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v8)
+ || ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v8r))
&& !ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_m))
{
if (inst.instruction >= 0x10000)
#define ARM_VARIANT & fpu_neon_ext_v1
mnUF(vabd, _vabd, 3, (RNDQMQ, oRNDQMQ, RNDQMQ), neon_dyadic_if_su),
mnUF(vabdl, _vabdl, 3, (RNQMQ, RNDMQ, RNDMQ), neon_dyadic_long),
- mnUF(vaddl, _vaddl, 3, (RNQMQ, RNDMQ, RNDMQR), neon_dyadic_long),
- mnUF(vsubl, _vsubl, 3, (RNQMQ, RNDMQ, RNDMQR), neon_dyadic_long),
+ mnUF(vaddl, _vaddl, 3, (RNSDQMQ, oRNSDMQ, RNSDMQR), neon_dyadic_long),
+ mnUF(vsubl, _vsubl, 3, (RNSDQMQ, oRNSDMQ, RNSDMQR), neon_dyadic_long),
mnUF(vand, _vand, 3, (RNDQMQ, oRNDQMQ, RNDQMQ_Ibig), neon_logic),
mnUF(vbic, _vbic, 3, (RNDQMQ, oRNDQMQ, RNDQMQ_Ibig), neon_logic),
mnUF(vorr, _vorr, 3, (RNDQMQ, oRNDQMQ, RNDQMQ_Ibig), neon_logic),
(((unsigned long) fixP->fx_frag->fr_address
+ (unsigned long) fixP->fx_where) & ~3)
+ (unsigned long) value);
+ else if (get_recorded_alignment (seg) < 2)
+ as_warn_where (fixP->fx_file, fixP->fx_line,
+ _("section does not have enough alignment to ensure safe PC-relative loads"));
if (value & ~0x3fc)
as_bad_where (fixP->fx_file, fixP->fx_line,
if (p_ver_ret == NULL)
return -1;
-found:
+ found:
/* Tag_CPU_arch_profile. */
- if (ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v7a)
- || ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v8)
- || (ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_atomics)
- && !ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v8m_m_only)))
+ if (!ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v8r)
+ && (ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v7a)
+ || ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v8)
+ || (ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_atomics)
+ && !ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v8m_m_only))))
*profile = 'A';
- else if (ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v7r))
+ else if (ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v7r)
+ || ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_v8r))
*profile = 'R';
else if (ARM_CPU_HAS_FEATURE (p_ver_ret->flags, arm_ext_m))
*profile = 'M';