X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-aarch64.c;h=045ad52d25740fa8a64c8e724f67fe8a86dbec4a;hb=68dfbb92ef5f013a315d652c88ede2082c16a88e;hp=3a0cde95196df91392558577d8a8b20b48946794;hpb=322474019df79a1305e83ff7620a72f31a5c7b55;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index 3a0cde9519..045ad52d25 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -55,6 +55,9 @@ static const aarch64_feature_set *march_cpu_opt = NULL; /* 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; @@ -146,6 +149,13 @@ static aarch64_instruction inst; 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 @@ -2279,7 +2289,6 @@ parse_aarch64_imm_float (char **ccp, int *immed, bfd_boolean dp_p, 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; @@ -2309,26 +2318,10 @@ parse_aarch64_imm_float (char **ccp, int *immed, bfd_boolean dp_p, 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) @@ -2902,7 +2895,7 @@ static struct reloc_table_entry reloc_table[] = { 0, 0, BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12, - 0, + BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12, 0}, /* Get tp offset for a symbol. */ @@ -2920,7 +2913,7 @@ static struct reloc_table_entry reloc_table[] = { 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. */ @@ -3695,6 +3688,7 @@ parse_address_main (char **str, aarch64_opnd_info *operand, set_syntax_error (_("missing offset in the pre-indexed address")); return FALSE; } + operand->addr.preind = 1; inst.reloc.exp.X_op = O_constant; inst.reloc.exp.X_add_number = 0; @@ -3950,7 +3944,8 @@ parse_barrier_psb (char **str, 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]; @@ -3981,6 +3976,8 @@ parse_sys_reg (char **str, struct hash_control *sys_regs, 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 @@ -3995,6 +3992,8 @@ parse_sys_reg (char **str, struct hash_control *sys_regs, 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; @@ -4411,6 +4410,7 @@ record_operand_error (const aarch64_opcode *opcode, int idx, info.index = idx; info.kind = kind; info.error = error; + info.non_fatal = FALSE; record_operand_error_info (opcode, &info); } @@ -4426,6 +4426,7 @@ record_operand_error_with_data (const aarch64_opcode *opcode, int idx, 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); } @@ -4544,7 +4545,8 @@ print_operands (char *buf, const aarch64_opcode *opcode, 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') @@ -4590,12 +4592,14 @@ output_operand_error_record (const operand_error_record *record, char *str) 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: @@ -4605,21 +4609,21 @@ output_operand_error_record (const operand_error_record *record, char *str) 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 @@ -4667,7 +4671,7 @@ output_operand_error_record (const operand_error_record *record, char *str) && 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. */ @@ -4716,36 +4720,36 @@ output_operand_error_record (const operand_error_record *record, char *str) 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: @@ -4759,10 +4763,15 @@ output_operand_error_record (const operand_error_record *record, char *str) 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; @@ -4780,9 +4789,14 @@ output_operand_error_report (char *str) /* 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; } @@ -4793,16 +4807,21 @@ output_operand_error_report (char *str) { 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 @@ -4818,6 +4837,17 @@ output_operand_error_report (char *str) } } + /* 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]); @@ -5081,6 +5111,7 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode, 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; @@ -5253,7 +5284,7 @@ ldst_lo12_determine_real_reloc_type (void) 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, @@ -5274,13 +5305,31 @@ ldst_lo12_determine_real_reloc_type (void) 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) @@ -5291,7 +5340,9 @@ ldst_lo12_determine_real_reloc_type (void) 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); @@ -5536,6 +5587,7 @@ parse_operands (char *str, const aarch64_opcode *opcode) 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: @@ -6167,7 +6219,11 @@ parse_operands (char *str, const aarch64_opcode *opcode) || (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; @@ -6233,6 +6289,25 @@ parse_operands (char *str, const aarch64_opcode *opcode) info->addr.offset.imm = inst.reloc.exp.X_add_number; break; + case AARCH64_OPND_SVE_ADDR_R: + /* [{, }] + but recognizing SVE registers. */ + po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier, + &offset_qualifier)); + if (offset_qualifier == AARCH64_OPND_QLF_NIL) + { + offset_qualifier = AARCH64_OPND_QLF_X; + info->addr.offset.is_reg = 1; + info->addr.offset.regno = 31; + } + else if (base_qualifier != AARCH64_OPND_QLF_X + || offset_qualifier != AARCH64_OPND_QLF_X) + { + set_syntax_error (_("invalid addressing mode")); + goto failure; + } + goto regoff_addr; + case AARCH64_OPND_SVE_ADDR_RR: case AARCH64_OPND_SVE_ADDR_RR_LSL1: case AARCH64_OPND_SVE_ADDR_RR_LSL2: @@ -6320,17 +6395,21 @@ parse_operands (char *str, const aarch64_opcode *opcode) 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")); @@ -6638,11 +6717,38 @@ warn_unpredictable_ldst (aarch64_instruction *instr, char *str) && 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. @@ -6653,15 +6759,15 @@ do_encode (const aarch64_opcode *opcode, aarch64_inst *instr, 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 @@ -6701,6 +6807,9 @@ md_assemble (char *str) 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"); @@ -6798,6 +6907,9 @@ md_assemble (char *str) memcpy (copy, &inst.base, sizeof (struct aarch64_inst)); output_inst (copy); } + + /* Issue non-fatal messages if any. */ + output_operand_error_report (str, TRUE); return; } @@ -6811,7 +6923,7 @@ md_assemble (char *str) 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. */ @@ -6830,6 +6942,13 @@ aarch64_frob_label (symbolS * sym) 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) { @@ -7290,7 +7409,8 @@ try_to_encode_as_unscaled_ldst (aarch64_inst *instr) 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; @@ -7324,7 +7444,7 @@ fix_mov_imm_insn (fixS *fixP, char *buf, aarch64_inst *instr, offsetT value) 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; @@ -7333,7 +7453,7 @@ fix_mov_imm_insn (fixS *fixP, char *buf, aarch64_inst *instr, offsetT value) 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; @@ -7346,7 +7466,7 @@ fix_mov_imm_insn (fixS *fixP, char *buf, aarch64_inst *instr, offsetT value) 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; @@ -7457,7 +7577,7 @@ fix_insn (fixS *fixP, uint32_t flags, offsetT value) 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, @@ -7511,7 +7631,7 @@ fix_insn (fixS *fixP, uint32_t flags, offsetT value) /* 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; @@ -7841,6 +7961,14 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg) 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: @@ -8075,6 +8203,14 @@ aarch64_force_relocation (struct fix *fixp) 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: @@ -8508,6 +8644,9 @@ static const struct aarch64_cpu_option_table aarch64_cpus[] = { {"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"}, @@ -8519,7 +8658,7 @@ static const struct aarch64_cpu_option_table aarch64_cpus[] = { 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, @@ -8555,6 +8694,7 @@ static const struct aarch64_arch_option_table aarch64_archs[] = { {"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} }; @@ -8607,6 +8747,8 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = { AARCH64_ARCH_NONE}, {"sha2", AARCH64_FEATURE (AARCH64_FEATURE_SHA2, 0), AARCH64_ARCH_NONE}, + {"sb", AARCH64_FEATURE (AARCH64_FEATURE_SB, 0), + AARCH64_ARCH_NONE}, {"aes", AARCH64_FEATURE (AARCH64_FEATURE_AES, 0), AARCH64_ARCH_NONE}, {"sm4", AARCH64_FEATURE (AARCH64_FEATURE_SM4, 0),