AArch64: Wire through instr_sequence
[deliverable/binutils-gdb.git] / gas / config / tc-aarch64.c
index 660fa7c4d4e7e0d863cde5e058599af8d13d2542..206019b382b58f0929ea045e098f7dfd8d14e41f 100644 (file)
@@ -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
@@ -4661,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.  */
@@ -4809,7 +4819,7 @@ output_operand_error_report (char *str, bfd_boolean non_fatal_only)
       /* 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 && !head->detail.non_fatal))
+         || (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
@@ -5099,6 +5109,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;
@@ -5574,6 +5585,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:
@@ -6703,6 +6715,22 @@ 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;
     }
@@ -6720,7 +6748,7 @@ do_encode (const aarch64_opcode *opcode, aarch64_inst *instr,
   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;
 
@@ -6766,6 +6794,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");
@@ -7358,7 +7389,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;
@@ -7392,7 +7424,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;
@@ -7401,7 +7433,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;
@@ -7414,7 +7446,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;
@@ -7525,7 +7557,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,
@@ -7579,7 +7611,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;
This page took 0.037946 seconds and 4 git commands to generate.