/* Constants for known architecture features. */
static const aarch64_feature_set cpu_default = CPU_DEFAULT;
+/* Currently active instruction sequence. */
+static aarch64_instr_sequence *insn_sequence = NULL;
+
#ifdef OBJ_ELF
/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
static symbolS *GOT_symbol;
static bfd_boolean parse_operands (char *, const aarch64_opcode *);
static bfd_boolean programmer_friendly_fixup (aarch64_instruction *);
+#ifdef OBJ_ELF
+# define now_instr_sequence seg_info \
+ (now_seg)->tc_segment_info_data.insn_sequence
+#else
+static struct aarch64_instr_sequence now_instr_sequence;
+#endif
+
/* Diagnostics inline function utilities.
These are lightweight utilities which should only be called by parse_operands
static struct hash_control *aarch64_sys_regs_dc_hsh;
static struct hash_control *aarch64_sys_regs_at_hsh;
static struct hash_control *aarch64_sys_regs_tlbi_hsh;
+static struct hash_control *aarch64_sys_regs_sr_hsh;
static struct hash_control *aarch64_reg_hsh;
static struct hash_control *aarch64_barrier_opt_hsh;
static struct hash_control *aarch64_nzcv_hsh;
char *str = *ccp;
char *fpnum;
LITTLENUM_TYPE words[MAX_LITTLENUMS];
- int found_fpchar = 0;
int64_t val = 0;
unsigned fpword = 0;
bfd_boolean hex_p = FALSE;
hex_p = TRUE;
}
- else
- {
- if (reg_name_p (str, reg_type))
- {
- set_recoverable_error (_("immediate operand required"));
- return FALSE;
- }
-
- /* We must not accidentally parse an integer as a floating-point number.
- Make sure that the value we parse is not an integer by checking for
- special characters '.' or 'e'. */
- for (; *fpnum != '\0' && *fpnum != ' ' && *fpnum != '\n'; fpnum++)
- if (*fpnum == '.' || *fpnum == 'e' || *fpnum == 'E')
- {
- found_fpchar = 1;
- break;
- }
-
- if (!found_fpchar)
- return FALSE;
+ else if (reg_name_p (str, reg_type))
+ {
+ set_recoverable_error (_("immediate operand required"));
+ return FALSE;
}
if (! hex_p)
0,
0,
BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12,
- 0,
+ BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12,
0},
/* Get tp offset for a symbol. */
0,
0,
BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC,
- 0,
+ BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC,
0},
/* Most significant bits 32-47 of address/value: MOVZ. */
return 0;
}
+/* Parse an operand for BTI. Set *HINT_OPT to the hint-option record
+ return 0 if successful. Otherwise return PARSE_FAIL. */
+
+static int
+parse_bti_operand (char **str,
+ const struct aarch64_name_value_pair ** hint_opt)
+{
+ char *p, *q;
+ const struct aarch64_name_value_pair *o;
+
+ p = q = *str;
+ while (ISALPHA (*q))
+ q++;
+
+ o = hash_find_n (aarch64_hint_opt_hsh, p, q - p);
+ if (!o)
+ {
+ set_fatal_syntax_error
+ ( _("unknown option to BTI"));
+ return PARSE_FAIL;
+ }
+
+ switch (o->value)
+ {
+ /* Valid BTI operands. */
+ case HINT_OPD_C:
+ case HINT_OPD_J:
+ case HINT_OPD_JC:
+ break;
+
+ default:
+ set_syntax_error
+ (_("unknown option to BTI"));
+ return PARSE_FAIL;
+ }
+
+ *str = q;
+ *hint_opt = o;
+ return 0;
+}
+
/* Parse a system register or a PSTATE field name for an MSR/MRS instruction.
Returns the encoding for the option, or PARSE_FAIL.
static int
parse_sys_reg (char **str, struct hash_control *sys_regs,
- int imple_defined_p, int pstatefield_p)
+ int imple_defined_p, int pstatefield_p,
+ uint32_t* flags)
{
char *p, *q;
char buf[32];
if (op0 > 3 || op1 > 7 || cn > 15 || cm > 15 || op2 > 7)
return PARSE_FAIL;
value = (op0 << 14) | (op1 << 11) | (cn << 7) | (cm << 3) | op2;
+ if (flags)
+ *flags = 0;
}
}
else
as_warn (_("system register name '%s' is deprecated and may be "
"removed in a future release"), buf);
value = o->value;
+ if (flags)
+ *flags = o->flags;
}
*str = q;
info.index = idx;
info.kind = kind;
info.error = error;
+ info.non_fatal = FALSE;
record_operand_error_info (opcode, &info);
}
info.data[0] = extra_data[0];
info.data[1] = extra_data[1];
info.data[2] = extra_data[2];
+ info.non_fatal = FALSE;
record_operand_error_info (opcode, &info);
}
break;
/* Generate the operand string in STR. */
- aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL);
+ aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL,
+ NULL);
/* Delimiter. */
if (str[0] != '\0')
enum aarch64_opnd opd_code = (idx >= 0 ? opcode->operands[idx]
: AARCH64_OPND_NIL);
+ typedef void (*handler_t)(const char *format, ...);
+ handler_t handler = detail->non_fatal ? as_warn : as_bad;
+
switch (detail->kind)
{
case AARCH64_OPDE_NIL:
gas_assert (0);
break;
-
case AARCH64_OPDE_SYNTAX_ERROR:
case AARCH64_OPDE_RECOVERABLE:
case AARCH64_OPDE_FATAL_SYNTAX_ERROR:
if (detail->error != NULL)
{
if (idx < 0)
- as_bad (_("%s -- `%s'"), detail->error, str);
+ handler (_("%s -- `%s'"), detail->error, str);
else
- as_bad (_("%s at operand %d -- `%s'"),
- detail->error, idx + 1, str);
+ handler (_("%s at operand %d -- `%s'"),
+ detail->error, idx + 1, str);
}
else
{
gas_assert (idx >= 0);
- as_bad (_("operand %d must be %s -- `%s'"), idx + 1,
- aarch64_get_operand_desc (opd_code), str);
+ handler (_("operand %d must be %s -- `%s'"), idx + 1,
+ aarch64_get_operand_desc (opd_code), str);
}
break;
case AARCH64_OPDE_INVALID_VARIANT:
- as_bad (_("operand mismatch -- `%s'"), str);
+ handler (_("operand mismatch -- `%s'"), str);
if (verbose_error_p)
{
/* We will try to correct the erroneous instruction and also provide
&& programmer_friendly_fixup (&inst);
gas_assert (result);
result = aarch64_opcode_encode (opcode, inst_base, &inst_base->value,
- NULL, NULL);
+ NULL, NULL, insn_sequence);
gas_assert (!result);
/* Find the most matched qualifier sequence. */
break;
case AARCH64_OPDE_UNTIED_OPERAND:
- as_bad (_("operand %d must be the same register as operand 1 -- `%s'"),
- detail->index + 1, str);
+ handler (_("operand %d must be the same register as operand 1 -- `%s'"),
+ detail->index + 1, str);
break;
case AARCH64_OPDE_OUT_OF_RANGE:
if (detail->data[0] != detail->data[1])
- as_bad (_("%s out of range %d to %d at operand %d -- `%s'"),
- detail->error ? detail->error : _("immediate value"),
- detail->data[0], detail->data[1], idx + 1, str);
+ handler (_("%s out of range %d to %d at operand %d -- `%s'"),
+ detail->error ? detail->error : _("immediate value"),
+ detail->data[0], detail->data[1], idx + 1, str);
else
- as_bad (_("%s must be %d at operand %d -- `%s'"),
- detail->error ? detail->error : _("immediate value"),
- detail->data[0], idx + 1, str);
+ handler (_("%s must be %d at operand %d -- `%s'"),
+ detail->error ? detail->error : _("immediate value"),
+ detail->data[0], idx + 1, str);
break;
case AARCH64_OPDE_REG_LIST:
if (detail->data[0] == 1)
- as_bad (_("invalid number of registers in the list; "
- "only 1 register is expected at operand %d -- `%s'"),
- idx + 1, str);
+ handler (_("invalid number of registers in the list; "
+ "only 1 register is expected at operand %d -- `%s'"),
+ idx + 1, str);
else
- as_bad (_("invalid number of registers in the list; "
- "%d registers are expected at operand %d -- `%s'"),
- detail->data[0], idx + 1, str);
+ handler (_("invalid number of registers in the list; "
+ "%d registers are expected at operand %d -- `%s'"),
+ detail->data[0], idx + 1, str);
break;
case AARCH64_OPDE_UNALIGNED:
- as_bad (_("immediate value must be a multiple of "
- "%d at operand %d -- `%s'"),
- detail->data[0], idx + 1, str);
+ handler (_("immediate value must be a multiple of "
+ "%d at operand %d -- `%s'"),
+ detail->data[0], idx + 1, str);
break;
default:
When this function is called, the operand error information had
been collected for an assembly line and there will be multiple
errors in the case of multiple instruction templates; output the
- error message that most closely describes the problem. */
+ error message that most closely describes the problem.
+
+ The errors to be printed can be filtered on printing all errors
+ or only non-fatal errors. This distinction has to be made because
+ the error buffer may already be filled with fatal errors we don't want to
+ print due to the different instruction templates. */
static void
-output_operand_error_report (char *str)
+output_operand_error_report (char *str, bfd_boolean non_fatal_only)
{
int largest_error_pos;
const char *msg = NULL;
/* Only one error. */
if (head == operand_error_report.tail)
{
- DEBUG_TRACE ("single opcode entry with error kind: %s",
- operand_mismatch_kind_names[head->detail.kind]);
- output_operand_error_record (head, str);
+ /* If the only error is a non-fatal one and we don't want to print it,
+ just exit. */
+ if (!non_fatal_only || head->detail.non_fatal)
+ {
+ DEBUG_TRACE ("single opcode entry with error kind: %s",
+ operand_mismatch_kind_names[head->detail.kind]);
+ output_operand_error_record (head, str);
+ }
return;
}
{
gas_assert (curr->detail.kind != AARCH64_OPDE_NIL);
DEBUG_TRACE ("\t%s", operand_mismatch_kind_names[curr->detail.kind]);
- if (operand_error_higher_severity_p (curr->detail.kind, kind))
+ if (operand_error_higher_severity_p (curr->detail.kind, kind)
+ && (!non_fatal_only || (non_fatal_only && curr->detail.non_fatal)))
kind = curr->detail.kind;
}
- gas_assert (kind != AARCH64_OPDE_NIL);
+
+ gas_assert (kind != AARCH64_OPDE_NIL || non_fatal_only);
/* Pick up one of errors of KIND to report. */
largest_error_pos = -2; /* Index can be -1 which means unknown index. */
for (curr = head; curr != NULL; curr = curr->next)
{
- if (curr->detail.kind != kind)
+ /* If we don't want to print non-fatal errors then don't consider them
+ at all. */
+ if (curr->detail.kind != kind
+ || (non_fatal_only && !curr->detail.non_fatal))
continue;
/* If there are multiple errors, pick up the one with the highest
mismatching operand index. In the case of multiple errors with
}
}
+ /* The way errors are collected in the back-end is a bit non-intuitive. But
+ essentially, because each operand template is tried recursively you may
+ always have errors collected from the previous tried OPND. These are
+ usually skipped if there is one successful match. However now with the
+ non-fatal errors we have to ignore those previously collected hard errors
+ when we're only interested in printing the non-fatal ones. This condition
+ prevents us from printing errors that are not appropriate, since we did
+ match a condition, but it also has warnings that it wants to print. */
+ if (non_fatal_only && !record)
+ return;
+
gas_assert (largest_error_pos != -2 && record != NULL);
DEBUG_TRACE ("Pick up error kind %s to report",
operand_mismatch_kind_names[record->detail.kind]);
case AARCH64_OPND_Ed:
case AARCH64_OPND_En:
case AARCH64_OPND_Em:
+ case AARCH64_OPND_Em16:
case AARCH64_OPND_SM3_IMM2:
operand->reglane.regno = default_value;
break;
case AARCH64_OPND_BARRIER_ISB:
operand->barrier = aarch64_barrier_options + default_value;
+ break;
+
+ case AARCH64_OPND_BTI_TARGET:
+ operand->hint_option = aarch64_hint_options + default_value;
+ break;
default:
break;
enum aarch64_opnd_qualifier opd0_qlf = inst.base.operands[0].qualifier;
enum aarch64_opnd_qualifier opd1_qlf = inst.base.operands[1].qualifier;
- const bfd_reloc_code_real_type reloc_ldst_lo12[3][5] = {
+ const bfd_reloc_code_real_type reloc_ldst_lo12[5][5] = {
{
BFD_RELOC_AARCH64_LDST8_LO12,
BFD_RELOC_AARCH64_LDST16_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_NONE
+ },
+ {
+ BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12,
+ BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12,
+ BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12,
+ BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12,
+ BFD_RELOC_AARCH64_NONE
+ },
+ {
+ BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_NC,
+ BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC,
+ BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC,
+ BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC,
+ BFD_RELOC_AARCH64_NONE
}
};
gas_assert (inst.reloc.type == BFD_RELOC_AARCH64_LDST_LO12
|| inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12
|| (inst.reloc.type
- == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC));
+ == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC)
+ || (inst.reloc.type
+ == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12)
+ || (inst.reloc.type
+ == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC));
gas_assert (inst.base.opcode->operands[1] == AARCH64_OPND_ADDR_UIMM12);
if (opd1_qlf == AARCH64_OPND_QLF_NIL)
logsz = get_logsz (aarch64_get_qualifier_esize (opd1_qlf));
if (inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12
- || inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC)
+ || inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC
+ || inst.reloc.type == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12
+ || inst.reloc.type == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC)
gas_assert (logsz <= 3);
else
gas_assert (logsz <= 4);
case AARCH64_OPND_Ed:
case AARCH64_OPND_En:
case AARCH64_OPND_Em:
+ case AARCH64_OPND_Em16:
case AARCH64_OPND_SM3_IMM2:
reg_type = REG_TYPE_VN;
vector_reg_index:
|| (inst.reloc.type
== BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12)
|| (inst.reloc.type
- == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC))
+ == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC)
+ || (inst.reloc.type
+ == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12)
+ || (inst.reloc.type
+ == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC))
inst.reloc.type = ldst_lo12_determine_real_reloc_type ();
/* Leave qualifier to be determined by libopcodes. */
break;
goto regoff_addr;
case AARCH64_OPND_SYSREG:
- if ((val = parse_sys_reg (&str, aarch64_sys_regs_hsh, 1, 0))
- == PARSE_FAIL)
- {
- set_syntax_error (_("unknown or missing system register name"));
- goto failure;
- }
- inst.base.operands[i].sysreg = val;
- break;
+ {
+ uint32_t sysreg_flags;
+ if ((val = parse_sys_reg (&str, aarch64_sys_regs_hsh, 1, 0,
+ &sysreg_flags)) == PARSE_FAIL)
+ {
+ set_syntax_error (_("unknown or missing system register name"));
+ goto failure;
+ }
+ inst.base.operands[i].sysreg.value = val;
+ inst.base.operands[i].sysreg.flags = sysreg_flags;
+ break;
+ }
case AARCH64_OPND_PSTATEFIELD:
- if ((val = parse_sys_reg (&str, aarch64_pstatefield_hsh, 0, 1))
+ if ((val = parse_sys_reg (&str, aarch64_pstatefield_hsh, 0, 1, NULL))
== PARSE_FAIL)
{
set_syntax_error (_("unknown or missing PSTATE field name"));
inst.base.operands[i].sysins_op =
parse_sys_ins_reg (&str, aarch64_sys_regs_ic_hsh);
goto sys_reg_ins;
+
case AARCH64_OPND_SYSREG_DC:
inst.base.operands[i].sysins_op =
parse_sys_ins_reg (&str, aarch64_sys_regs_dc_hsh);
goto sys_reg_ins;
+
case AARCH64_OPND_SYSREG_AT:
inst.base.operands[i].sysins_op =
parse_sys_ins_reg (&str, aarch64_sys_regs_at_hsh);
goto sys_reg_ins;
+
+ case AARCH64_OPND_SYSREG_SR:
+ inst.base.operands[i].sysins_op =
+ parse_sys_ins_reg (&str, aarch64_sys_regs_sr_hsh);
+ goto sys_reg_ins;
+
case AARCH64_OPND_SYSREG_TLBI:
inst.base.operands[i].sysins_op =
parse_sys_ins_reg (&str, aarch64_sys_regs_tlbi_hsh);
goto failure;
break;
+ case AARCH64_OPND_BTI_TARGET:
+ val = parse_bti_operand (&str, &(info->hint_option));
+ if (val == PARSE_FAIL)
+ goto failure;
+ break;
+
default:
as_fatal (_("unhandled operand code %d"), operands[i]);
}
&& opnds[0].reg.regno == opnds[1].reg.regno)
as_warn (_("unpredictable load of register pair -- `%s'"), str);
break;
+
+ case ldstexcl:
+ /* It is unpredictable if the destination and status registers are the
+ same. */
+ if ((aarch64_get_operand_class (opnds[0].type)
+ == AARCH64_OPND_CLASS_INT_REG)
+ && (aarch64_get_operand_class (opnds[1].type)
+ == AARCH64_OPND_CLASS_INT_REG)
+ && (opnds[0].reg.regno == opnds[1].reg.regno
+ || opnds[0].reg.regno == opnds[2].reg.regno))
+ as_warn (_("unpredictable: identical transfer and status registers"
+ " --`%s'"),
+ str);
+
+ break;
+
default:
break;
}
}
+static void
+force_automatic_sequence_close (void)
+{
+ if (now_instr_sequence.instr)
+ {
+ as_warn (_("previous `%s' sequence has not been closed"),
+ now_instr_sequence.instr->opcode->name);
+ init_insn_sequence (NULL, &now_instr_sequence);
+ }
+}
+
/* A wrapper function to interface with libopcodes on encoding and
record the error message if there is any.
aarch64_insn *code)
{
aarch64_operand_error error_info;
+ memset (&error_info, '\0', sizeof (error_info));
error_info.kind = AARCH64_OPDE_NIL;
- if (aarch64_opcode_encode (opcode, instr, code, NULL, &error_info))
+ if (aarch64_opcode_encode (opcode, instr, code, NULL, &error_info, insn_sequence)
+ && !error_info.non_fatal)
return TRUE;
- else
- {
- gas_assert (error_info.kind != AARCH64_OPDE_NIL);
- record_operand_error_info (opcode, &error_info);
- return FALSE;
- }
+
+ gas_assert (error_info.kind != AARCH64_OPDE_NIL);
+ record_operand_error_info (opcode, &error_info);
+ return error_info.non_fatal;
}
#ifdef DEBUG_AARCH64
S_SET_SEGMENT (last_label_seen, now_seg);
}
+ /* Update the current insn_sequence from the segment. */
+ insn_sequence = &seg_info (now_seg)->tc_segment_info_data.insn_sequence;
+
inst.reloc.type = BFD_RELOC_UNUSED;
DEBUG_TRACE ("\n\n");
memcpy (copy, &inst.base, sizeof (struct aarch64_inst));
output_inst (copy);
}
+
+ /* Issue non-fatal messages if any. */
+ output_operand_error_report (str, TRUE);
return;
}
while (template != NULL);
/* Issue the error messages if any. */
- output_operand_error_report (str);
+ output_operand_error_report (str, FALSE);
}
/* Various frobbings of labels and their addresses. */
dwarf2_emit_label (sym);
}
+void
+aarch64_frob_section (asection *sec ATTRIBUTE_UNUSED)
+{
+ /* Check to see if we have a block to close. */
+ force_automatic_sequence_close ();
+}
+
int
aarch64_data_in_code (void)
{
DEBUG_TRACE ("Found LDURB entry to encode programmer-friendly LDRB");
- if (!aarch64_opcode_encode (instr->opcode, instr, &instr->value, NULL, NULL))
+ if (!aarch64_opcode_encode (instr->opcode, instr, &instr->value, NULL, NULL,
+ insn_sequence))
return FALSE;
return TRUE;
opcode = aarch64_get_opcode (OP_MOV_IMM_WIDE);
aarch64_replace_opcode (instr, opcode);
if (aarch64_opcode_encode (instr->opcode, instr,
- &instr->value, NULL, NULL))
+ &instr->value, NULL, NULL, insn_sequence))
{
put_aarch64_insn (buf, instr->value);
return;
opcode = aarch64_get_opcode (OP_MOV_IMM_WIDEN);
aarch64_replace_opcode (instr, opcode);
if (aarch64_opcode_encode (instr->opcode, instr,
- &instr->value, NULL, NULL))
+ &instr->value, NULL, NULL, insn_sequence))
{
put_aarch64_insn (buf, instr->value);
return;
opcode = aarch64_get_opcode (OP_MOV_IMM_LOG);
aarch64_replace_opcode (instr, opcode);
if (aarch64_opcode_encode (instr->opcode, instr,
- &instr->value, NULL, NULL))
+ &instr->value, NULL, NULL, insn_sequence))
{
put_aarch64_insn (buf, instr->value);
return;
idx = aarch64_operand_index (new_inst->opcode->operands, opnd);
new_inst->operands[idx].imm.value = value;
if (aarch64_opcode_encode (new_inst->opcode, new_inst,
- &new_inst->value, NULL, NULL))
+ &new_inst->value, NULL, NULL, insn_sequence))
put_aarch64_insn (buf, new_inst->value);
else
as_bad_where (fixP->fx_file, fixP->fx_line,
/* Encode/fix-up. */
if (aarch64_opcode_encode (new_inst->opcode, new_inst,
- &new_inst->value, NULL, NULL))
+ &new_inst->value, NULL, NULL, insn_sequence))
{
put_aarch64_insn (buf, new_inst->value);
break;
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
+ case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
+ case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
|| (aarch64_sys_regs_dc_hsh = hash_new ()) == NULL
|| (aarch64_sys_regs_at_hsh = hash_new ()) == NULL
|| (aarch64_sys_regs_tlbi_hsh = hash_new ()) == NULL
+ || (aarch64_sys_regs_sr_hsh = hash_new ()) == NULL
|| (aarch64_reg_hsh = hash_new ()) == NULL
|| (aarch64_barrier_opt_hsh = hash_new ()) == NULL
|| (aarch64_nzcv_hsh = hash_new ()) == NULL
aarch64_sys_regs_tlbi[i].name,
(void *) (aarch64_sys_regs_tlbi + i));
+ for (i = 0; aarch64_sys_regs_sr[i].name != NULL; i++)
+ checked_hash_insert (aarch64_sys_regs_sr_hsh,
+ aarch64_sys_regs_sr[i].name,
+ (void *) (aarch64_sys_regs_sr + i));
+
for (i = 0; i < ARRAY_SIZE (reg_names); i++)
checked_hash_insert (aarch64_reg_hsh, reg_names[i].name,
(void *) (reg_names + i));
{"cortex-a75", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16 | AARCH64_FEATURE_DOTPROD),
"Cortex-A75"},
+ {"cortex-a76", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
+ AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16 | AARCH64_FEATURE_DOTPROD),
+ "Cortex-A76"},
{"exynos-m1", AARCH64_FEATURE (AARCH64_ARCH_V8,
AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO),
"Samsung Exynos M1"},
AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO
| AARCH64_FEATURE_RDMA),
"Qualcomm QDF24XX"},
- {"saphira", AARCH64_FEATURE (AARCH64_ARCH_V8_3,
+ {"saphira", AARCH64_FEATURE (AARCH64_ARCH_V8_4,
AARCH64_FEATURE_CRYPTO | AARCH64_FEATURE_PROFILE),
"Qualcomm Saphira"},
{"thunderx", AARCH64_FEATURE (AARCH64_ARCH_V8,
{"armv8.2-a", AARCH64_ARCH_V8_2},
{"armv8.3-a", AARCH64_ARCH_V8_3},
{"armv8.4-a", AARCH64_ARCH_V8_4},
+ {"armv8.5-a", AARCH64_ARCH_V8_5},
{NULL, AARCH64_ARCH_NONE}
};
AARCH64_ARCH_NONE},
{"sha2", AARCH64_FEATURE (AARCH64_FEATURE_SHA2, 0),
AARCH64_ARCH_NONE},
+ {"sb", AARCH64_FEATURE (AARCH64_FEATURE_SB, 0),
+ AARCH64_ARCH_NONE},
+ {"predres", AARCH64_FEATURE (AARCH64_FEATURE_PREDRES, 0),
+ AARCH64_ARCH_NONE},
{"aes", AARCH64_FEATURE (AARCH64_FEATURE_AES, 0),
AARCH64_ARCH_NONE},
{"sm4", AARCH64_FEATURE (AARCH64_FEATURE_SM4, 0),
{"sha3", AARCH64_FEATURE (AARCH64_FEATURE_SHA2
| AARCH64_FEATURE_SHA3, 0),
AARCH64_ARCH_NONE},
+ {"rng", AARCH64_FEATURE (AARCH64_FEATURE_RNG, 0),
+ AARCH64_ARCH_NONE},
+ {"ssbs", AARCH64_FEATURE (AARCH64_FEATURE_SSBS, 0),
+ AARCH64_ARCH_NONE},
+ {"memtag", AARCH64_FEATURE (AARCH64_FEATURE_MEMTAG, 0),
+ AARCH64_ARCH_NONE},
{NULL, AARCH64_ARCH_NONE, AARCH64_ARCH_NONE},
};