* gas/config/tc-arm.c (insns): Add DCPS instruction.
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
index 585f78e0a29ff9b00f2464aa9992600fab51e654..1c5eb3100dbcfa4932248ea3355724f530edb7f7 100644 (file)
@@ -195,6 +195,7 @@ static const arm_feature_set arm_ext_v7 = ARM_FEATURE (ARM_EXT_V7, 0);
 static const arm_feature_set arm_ext_v7a = ARM_FEATURE (ARM_EXT_V7A, 0);
 static const arm_feature_set arm_ext_v7r = ARM_FEATURE (ARM_EXT_V7R, 0);
 static const arm_feature_set arm_ext_v7m = ARM_FEATURE (ARM_EXT_V7M, 0);
 static const arm_feature_set arm_ext_v7a = ARM_FEATURE (ARM_EXT_V7A, 0);
 static const arm_feature_set arm_ext_v7r = ARM_FEATURE (ARM_EXT_V7R, 0);
 static const arm_feature_set arm_ext_v7m = ARM_FEATURE (ARM_EXT_V7M, 0);
+static const arm_feature_set arm_ext_v8 = ARM_FEATURE (ARM_EXT_V8, 0);
 static const arm_feature_set arm_ext_m =
   ARM_FEATURE (ARM_EXT_V6M | ARM_EXT_OS | ARM_EXT_V7M, 0);
 static const arm_feature_set arm_ext_mp = ARM_FEATURE (ARM_EXT_MP, 0);
 static const arm_feature_set arm_ext_m =
   ARM_FEATURE (ARM_EXT_V6M | ARM_EXT_OS | ARM_EXT_V7M, 0);
 static const arm_feature_set arm_ext_mp = ARM_FEATURE (ARM_EXT_MP, 0);
@@ -233,6 +234,12 @@ static const arm_feature_set fpu_vfp_v3_or_neon_ext =
 static const arm_feature_set fpu_vfp_fp16 = ARM_FEATURE (0, FPU_VFP_EXT_FP16);
 static const arm_feature_set fpu_neon_ext_fma = ARM_FEATURE (0, FPU_NEON_EXT_FMA);
 static const arm_feature_set fpu_vfp_ext_fma = ARM_FEATURE (0, FPU_VFP_EXT_FMA);
 static const arm_feature_set fpu_vfp_fp16 = ARM_FEATURE (0, FPU_VFP_EXT_FP16);
 static const arm_feature_set fpu_neon_ext_fma = ARM_FEATURE (0, FPU_NEON_EXT_FMA);
 static const arm_feature_set fpu_vfp_ext_fma = ARM_FEATURE (0, FPU_VFP_EXT_FMA);
+static const arm_feature_set fpu_vfp_ext_armv8 =
+  ARM_FEATURE (0, FPU_VFP_EXT_ARMV8);
+static const arm_feature_set fpu_neon_ext_armv8 =
+  ARM_FEATURE (0, FPU_NEON_EXT_ARMV8);
+static const arm_feature_set fpu_crypto_ext_armv8 =
+  ARM_FEATURE (0, FPU_CRYPTO_EXT_ARMV8);
 
 static int mfloat_abi_opt = -1;
 /* Record user cpu selection for object attributes.  */
 
 static int mfloat_abi_opt = -1;
 /* Record user cpu selection for object attributes.  */
@@ -454,8 +461,9 @@ struct asm_psr
 
 struct asm_barrier_opt
 {
 
 struct asm_barrier_opt
 {
-  const char *   template_name;
-  unsigned long  value;
+  const char *    template_name;
+  unsigned long   value;
+  const arm_feature_set arch;
 };
 
 /* The bit that distinguishes CPSR and SPSR.  */
 };
 
 /* The bit that distinguishes CPSR and SPSR.  */
@@ -622,6 +630,14 @@ struct asm_opcode
 #define T2_OPCODE_MASK 0xfe1fffff
 #define T2_DATA_OP_SHIFT 21
 
 #define T2_OPCODE_MASK 0xfe1fffff
 #define T2_DATA_OP_SHIFT 21
 
+#define A_COND_MASK         0xf0000000
+#define A_PUSH_POP_OP_MASK  0x0fff0000
+
+/* Opcodes for pushing/poping registers to/from the stack.  */
+#define A1_OPCODE_PUSH    0x092d0000
+#define A2_OPCODE_PUSH    0x052d0004
+#define A2_OPCODE_POP     0x049d0004
+
 /* Codes to distinguish the arithmetic instructions.  */
 #define OPCODE_AND     0
 #define OPCODE_EOR     1
 /* Codes to distinguish the arithmetic instructions.  */
 #define OPCODE_AND     0
 #define OPCODE_EOR     1
@@ -5751,6 +5767,25 @@ parse_cond (char **str)
   return c->value;
 }
 
   return c->value;
 }
 
+/* If the given feature available in the selected CPU, mark it as used.
+   Returns TRUE iff feature is available.  */
+static bfd_boolean
+mark_feature_used (const arm_feature_set *feature)
+{
+  /* Ensure the option is valid on the current architecture.  */
+  if (!ARM_CPU_HAS_FEATURE (cpu_variant, *feature))
+    return FALSE;
+
+  /* Add the appropriate architecture feature for the barrier option used.
+     */
+  if (thumb_mode)
+    ARM_MERGE_FEATURE_SETS (thumb_arch_used, thumb_arch_used, *feature);
+  else
+    ARM_MERGE_FEATURE_SETS (arm_arch_used, arm_arch_used, *feature);
+
+  return TRUE;
+}
+
 /* Parse an option for a barrier instruction.  Returns the encoding for the
    option, or FAIL.  */
 static int
 /* Parse an option for a barrier instruction.  Returns the encoding for the
    option, or FAIL.  */
 static int
@@ -5768,6 +5803,9 @@ parse_barrier (char **str)
   if (!o)
     return FAIL;
 
   if (!o)
     return FAIL;
 
+  if (!mark_feature_used (&o->arch))
+    return FAIL;
+
   *str = q;
   return o->value;
 }
   *str = q;
   return o->value;
 }
@@ -6194,7 +6232,7 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
   unsigned const int *upat = pattern;
   char *backtrack_pos = 0;
   const char *backtrack_error = 0;
   unsigned const int *upat = pattern;
   char *backtrack_pos = 0;
   const char *backtrack_error = 0;
-  int i, val, backtrack_index = 0;
+  int i, val = 0, backtrack_index = 0;
   enum arm_reg_type rtype;
   parse_operand_result result;
   unsigned int op_parse_code;
   enum arm_reg_type rtype;
   parse_operand_result result;
   unsigned int op_parse_code;
@@ -7034,7 +7072,11 @@ encode_arm_shifter_operand (int i)
 static void
 encode_arm_addr_mode_common (int i, bfd_boolean is_t)
 {
 static void
 encode_arm_addr_mode_common (int i, bfd_boolean is_t)
 {
-  gas_assert (inst.operands[i].isreg);
+  /* PR 14260:
+     Generate an error if the operand is not a register.  */
+  constraint (!inst.operands[i].isreg,
+             _("Instruction does not support =N addresses"));
+
   inst.instruction |= inst.operands[i].reg << 16;
 
   if (inst.operands[i].preind)
   inst.instruction |= inst.operands[i].reg << 16;
 
   if (inst.operands[i].preind)
@@ -7354,6 +7396,23 @@ do_rn_rd (void)
   inst.instruction |= inst.operands[1].reg << 12;
 }
 
   inst.instruction |= inst.operands[1].reg << 12;
 }
 
+static bfd_boolean
+check_obsolete (const arm_feature_set *feature, const char *msg)
+{
+  if (ARM_CPU_IS_ANY (cpu_variant))
+    {
+      as_warn ("%s", msg);
+      return TRUE;
+    }
+  else if (ARM_CPU_HAS_FEATURE (cpu_variant, *feature))
+    {
+      as_bad ("%s", msg);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
 static void
 do_rd_rm_rn (void)
 {
 static void
 do_rd_rm_rn (void)
 {
@@ -7364,12 +7423,15 @@ do_rd_rm_rn (void)
       constraint (Rn == inst.operands[0].reg || Rn == inst.operands[1].reg,
                  _("Rn must not overlap other operands"));
 
       constraint (Rn == inst.operands[0].reg || Rn == inst.operands[1].reg,
                  _("Rn must not overlap other operands"));
 
-      /* SWP{b} is deprecated for ARMv6* and ARMv7.  */
-      if (warn_on_deprecated
-         && ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v6))
-       as_warn (_("swp{b} use is deprecated for this architecture"));
-
+      /* SWP{b} is obsolete for ARMv8-A, and deprecated for ARMv6* and ARMv7.
+       */
+      if (!check_obsolete (&arm_ext_v8,
+                          _("swp{b} use is obsoleted for ARMv8 and later"))
+         && warn_on_deprecated
+         && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6))
+       as_warn (_("swp{b} use is deprecated for ARMv6 and ARMv7"));
     }
     }
+
   inst.instruction |= inst.operands[0].reg << 12;
   inst.instruction |= inst.operands[1].reg;
   inst.instruction |= Rn << 16;
   inst.instruction |= inst.operands[0].reg << 12;
   inst.instruction |= inst.operands[1].reg;
   inst.instruction |= Rn << 16;
@@ -7671,10 +7733,52 @@ do_cmp (void)
 
    No special properties.  */
 
 
    No special properties.  */
 
+struct deprecated_coproc_regs_s
+{
+  unsigned cp;
+  int opc1;
+  unsigned crn;
+  unsigned crm;
+  int opc2;
+  arm_feature_set deprecated;
+  arm_feature_set obsoleted;
+  const char *dep_msg;
+  const char *obs_msg;
+};
+
+#define DEPR_ACCESS_V8 \
+  N_("This coprocessor register access is deprecated in ARMv8")
+
+/* Table of all deprecated coprocessor registers.  */
+static struct deprecated_coproc_regs_s deprecated_coproc_regs[] =
+{
+    {15, 0, 7, 10, 5,                                  /* CP15DMB.  */
+     ARM_FEATURE (ARM_EXT_V8, 0), ARM_FEATURE (0, 0),
+     DEPR_ACCESS_V8, NULL},
+    {15, 0, 7, 10, 4,                                  /* CP15DSB.  */
+     ARM_FEATURE (ARM_EXT_V8, 0), ARM_FEATURE (0, 0),
+     DEPR_ACCESS_V8, NULL},
+    {15, 0, 7,  5, 4,                                  /* CP15ISB.  */
+     ARM_FEATURE (ARM_EXT_V8, 0), ARM_FEATURE (0, 0),
+     DEPR_ACCESS_V8, NULL},
+    {14, 6, 1,  0, 0,                                  /* TEEHBR.  */
+     ARM_FEATURE (ARM_EXT_V8, 0), ARM_FEATURE (0, 0),
+     DEPR_ACCESS_V8, NULL},
+    {14, 6, 0,  0, 0,                                  /* TEECR.  */
+     ARM_FEATURE (ARM_EXT_V8, 0), ARM_FEATURE (0, 0),
+     DEPR_ACCESS_V8, NULL},
+};
+
+#undef DEPR_ACCESS_V8
+
+static const size_t deprecated_coproc_reg_count =
+  sizeof (deprecated_coproc_regs) / sizeof (deprecated_coproc_regs[0]);
+
 static void
 do_co_reg (void)
 {
   unsigned Rd;
 static void
 do_co_reg (void)
 {
   unsigned Rd;
+  size_t i;
 
   Rd = inst.operands[2].reg;
   if (thumb_mode)
 
   Rd = inst.operands[2].reg;
   if (thumb_mode)
@@ -7694,6 +7798,23 @@ do_co_reg (void)
        constraint (Rd == REG_PC, BAD_PC);
     }
 
        constraint (Rd == REG_PC, BAD_PC);
     }
 
+    for (i = 0; i < deprecated_coproc_reg_count; ++i)
+      {
+       const struct deprecated_coproc_regs_s *r =
+         deprecated_coproc_regs + i;
+
+       if (inst.operands[0].reg == r->cp
+           && inst.operands[1].imm == r->opc1
+           && inst.operands[3].reg == r->crn
+           && inst.operands[4].reg == r->crm
+           && inst.operands[5].imm == r->opc2)
+         {
+           if (!check_obsolete (&r->obsoleted, r->obs_msg)
+               && warn_on_deprecated
+               && ARM_CPU_HAS_FEATURE (cpu_variant, r->deprecated))
+             as_warn ("%s", r->dep_msg);
+         }
+      }
 
   inst.instruction |= inst.operands[0].reg << 8;
   inst.instruction |= inst.operands[1].imm << 21;
 
   inst.instruction |= inst.operands[0].reg << 8;
   inst.instruction |= inst.operands[1].imm << 21;
@@ -7795,11 +7916,21 @@ do_it (void)
     }
 }
 
     }
 }
 
+/* If there is only one register in the register list,
+   then return its register number.  Otherwise return -1.  */
+static int
+only_one_reg_in_list (int range)
+{
+  int i = ffs (range) - 1;
+  return (i > 15 || range != (1 << i)) ? -1 : i;
+}
+
 static void
 static void
-do_ldmstm (void)
+encode_ldmstm(int from_push_pop_mnem)
 {
   int base_reg = inst.operands[0].reg;
   int range = inst.operands[1].imm;
 {
   int base_reg = inst.operands[0].reg;
   int range = inst.operands[1].imm;
+  int one_reg;
 
   inst.instruction |= base_reg << 16;
   inst.instruction |= range;
 
   inst.instruction |= base_reg << 16;
   inst.instruction |= range;
@@ -7832,6 +7963,23 @@ do_ldmstm (void)
            as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
        }
     }
            as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
        }
     }
+
+  /* If PUSH/POP has only one register, then use the A2 encoding.  */
+  one_reg = only_one_reg_in_list (range);
+  if (from_push_pop_mnem && one_reg >= 0)
+    {
+      int is_push = (inst.instruction & A_PUSH_POP_OP_MASK) == A1_OPCODE_PUSH;
+
+      inst.instruction &= A_COND_MASK;
+      inst.instruction |= is_push ? A2_OPCODE_PUSH : A2_OPCODE_POP;
+      inst.instruction |= one_reg << 12;
+    }
+}
+
+static void
+do_ldmstm (void)
+{
+  encode_ldmstm (/*from_push_pop_mnem=*/FALSE);
 }
 
 /* ARMv5TE load-consecutive (argument parse)
 }
 
 /* ARMv5TE load-consecutive (argument parse)
@@ -8333,7 +8481,7 @@ do_push_pop (void)
   inst.operands[0].isreg = 1;
   inst.operands[0].writeback = 1;
   inst.operands[0].reg = REG_SP;
   inst.operands[0].isreg = 1;
   inst.operands[0].writeback = 1;
   inst.operands[0].reg = REG_SP;
-  do_ldmstm ();
+  encode_ldmstm (/*from_push_pop_mnem=*/TRUE);
 }
 
 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
 }
 
 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
@@ -8403,6 +8551,10 @@ do_usat16 (void)
 static void
 do_setend (void)
 {
 static void
 do_setend (void)
 {
+  if (warn_on_deprecated
+      && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v8))
+      as_warn (_("setend use is deprecated for ARMv8"));
+
   if (inst.operands[0].imm)
     inst.instruction |= 0x200;
 }
   if (inst.operands[0].imm)
     inst.instruction |= 0x200;
 }
@@ -9397,7 +9549,8 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
   X(_yield, bf10, f3af8001),                   \
   X(_wfe,   bf20, f3af8002),                   \
   X(_wfi,   bf30, f3af8003),                   \
   X(_yield, bf10, f3af8001),                   \
   X(_wfe,   bf20, f3af8002),                   \
   X(_wfi,   bf30, f3af8003),                   \
-  X(_sev,   bf40, f3af8004),
+  X(_sev,   bf40, f3af8004),                    \
+  X(_sevl,  bf50, f3af8005)
 
 /* To catch errors in encoding functions, the codes are all offset by
    0xF800, putting them in one of the 32-bit prefix ranges, ergo undefined
 
 /* To catch errors in encoding functions, the codes are all offset by
    0xF800, putting them in one of the 32-bit prefix ranges, ergo undefined
@@ -10231,6 +10384,7 @@ do_t_it (void)
   set_it_insn_type (IT_INSN);
   now_it.mask = (inst.instruction & 0xf) | 0x10;
   now_it.cc = cond;
   set_it_insn_type (IT_INSN);
   now_it.mask = (inst.instruction & 0xf) | 0x10;
   now_it.cc = cond;
+  now_it.warn_deprecated = FALSE;
 
   /* If the condition is a negative condition, invert the mask.  */
   if ((cond & 0x1) == 0x0)
 
   /* If the condition is a negative condition, invert the mask.  */
   if ((cond & 0x1) == 0x0)
@@ -10238,13 +10392,25 @@ do_t_it (void)
       unsigned int mask = inst.instruction & 0x000f;
 
       if ((mask & 0x7) == 0)
       unsigned int mask = inst.instruction & 0x000f;
 
       if ((mask & 0x7) == 0)
-       /* no conversion needed */;
+       {
+         /* No conversion needed.  */
+         now_it.block_length = 1;
+       }
       else if ((mask & 0x3) == 0)
       else if ((mask & 0x3) == 0)
-       mask ^= 0x8;
+       {
+         mask ^= 0x8;
+         now_it.block_length = 2;
+       }
       else if ((mask & 0x1) == 0)
       else if ((mask & 0x1) == 0)
-       mask ^= 0xC;
+       {
+         mask ^= 0xC;
+         now_it.block_length = 3;
+       }
       else
       else
-       mask ^= 0xE;
+       {
+         mask ^= 0xE;
+         now_it.block_length = 4;
+       }
 
       inst.instruction &= 0xfff0;
       inst.instruction |= mask;
 
       inst.instruction &= 0xfff0;
       inst.instruction |= mask;
@@ -11166,8 +11332,14 @@ do_t_mrs (void)
       int flags = inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f|SPSR_BIT);
 
       if (ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_m))
       int flags = inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f|SPSR_BIT);
 
       if (ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_m))
-       constraint (flags != 0, _("selected processor does not support "
-                   "requested special purpose register"));
+       {
+         /* PR gas/12698:  The constraint is only applied for m_profile.
+            If the user has specified -march=all, we want to ignore it as
+            we are building for any CPU type, including non-m variants.  */
+         bfd_boolean m_profile = selected_cpu.core != arm_arch_any.core;
+         constraint ((flags != 0) && m_profile, _("selected processor does "
+                                                  "not support requested special purpose register"));
+       }
       else
        /* mrs only accepts APSR/CPSR/SPSR/CPSR_all/SPSR_all (for non-M profile
           devices).  */
       else
        /* mrs only accepts APSR/CPSR/SPSR/CPSR_all/SPSR_all (for non-M profile
           devices).  */
@@ -11201,12 +11373,16 @@ do_t_msr (void)
     {
       int bits = inst.operands[0].imm & (PSR_c|PSR_x|PSR_s|PSR_f|SPSR_BIT);
 
     {
       int bits = inst.operands[0].imm & (PSR_c|PSR_x|PSR_s|PSR_f|SPSR_BIT);
 
-      constraint ((ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v6_dsp)
-                  && (bits & ~(PSR_s | PSR_f)) != 0)
-                 || (!ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v6_dsp)
-                     && bits != PSR_f),
-                 _("selected processor does not support requested special "
-                   "purpose register"));
+      /* PR gas/12698:  The constraint is only applied for m_profile.
+         If the user has specified -march=all, we want to ignore it as
+         we are building for any CPU type, including non-m variants.  */
+      bfd_boolean m_profile = selected_cpu.core != arm_arch_any.core;
+      constraint (((ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v6_dsp)
+           && (bits & ~(PSR_s | PSR_f)) != 0)
+          || (!ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v6_dsp)
+              && bits != PSR_f)) && m_profile,
+          _("selected processor does not support requested special "
+            "purpose register"));
     }
   else
      constraint ((flags & 0xff) != 0, _("selected processor does not support "
     }
   else
      constraint ((flags & 0xff) != 0, _("selected processor does not support "
@@ -11621,6 +11797,10 @@ do_t_rsb (void)
 static void
 do_t_setend (void)
 {
 static void
 do_t_setend (void)
 {
+  if (warn_on_deprecated
+      && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v8))
+      as_warn (_("setend use is deprecated for ARMv8"));
+
   set_it_insn_type (OUTSIDE_IT_INSN);
   if (inst.operands[0].imm)
     inst.instruction |= 0x8;
   set_it_insn_type (OUTSIDE_IT_INSN);
   if (inst.operands[0].imm)
     inst.instruction |= 0x8;
@@ -16052,6 +16232,8 @@ new_automatic_it_block (int cond)
   now_it.block_length = 1;
   mapping_state (MAP_THUMB);
   now_it.insn = output_it_inst (cond, now_it.mask, NULL);
   now_it.block_length = 1;
   mapping_state (MAP_THUMB);
   now_it.insn = output_it_inst (cond, now_it.mask, NULL);
+  now_it.warn_deprecated = FALSE;
+  now_it.insn_cond = TRUE;
 }
 
 /* Close an automatic IT block.
 }
 
 /* Close an automatic IT block.
@@ -16159,6 +16341,7 @@ static int
 handle_it_state (void)
 {
   now_it.state_handled = 1;
 handle_it_state (void)
 {
   now_it.state_handled = 1;
+  now_it.insn_cond = FALSE;
 
   switch (now_it.state)
     {
 
   switch (now_it.state)
     {
@@ -16236,6 +16419,7 @@ handle_it_state (void)
            }
          else
            {
            }
          else
            {
+             now_it.insn_cond = TRUE;
              now_it_add_mask (inst.cond);
            }
 
              now_it_add_mask (inst.cond);
            }
 
@@ -16247,6 +16431,7 @@ handle_it_state (void)
 
        case NEUTRAL_IT_INSN:
          now_it.block_length++;
 
        case NEUTRAL_IT_INSN:
          now_it.block_length++;
+         now_it.insn_cond = TRUE;
 
          if (now_it.block_length > 4)
            force_automatic_it_block_close ();
 
          if (now_it.block_length > 4)
            force_automatic_it_block_close ();
@@ -16269,6 +16454,7 @@ handle_it_state (void)
        now_it.mask <<= 1;
        now_it.mask &= 0x1f;
        is_last = (now_it.mask == 0x10);
        now_it.mask <<= 1;
        now_it.mask &= 0x1f;
        is_last = (now_it.mask == 0x10);
+       now_it.insn_cond = TRUE;
 
        switch (inst.it_insn_type)
          {
 
        switch (inst.it_insn_type)
          {
@@ -16313,6 +16499,25 @@ handle_it_state (void)
   return SUCCESS;
 }
 
   return SUCCESS;
 }
 
+struct depr_insn_mask
+{
+  unsigned long pattern;
+  unsigned long mask;
+  const char* description;
+};
+
+/* List of 16-bit instruction patterns deprecated in an IT block in
+   ARMv8.  */
+static const struct depr_insn_mask depr_it_insns[] = {
+  { 0xc000, 0xc000, N_("Short branches, Undefined, SVC, LDM/STM") },
+  { 0xb000, 0xb000, N_("Miscellaneous 16-bit instructions") },
+  { 0xa000, 0xb800, N_("ADR") },
+  { 0x4800, 0xf800, N_("Literal loads") },
+  { 0x4478, 0xf478, N_("Hi-register ADD, MOV, CMP, BX, BLX using pc") },
+  { 0x4487, 0xfc87, N_("Hi-register ADD, MOV, CMP using pc") },
+  { 0, 0, NULL }
+};
+
 static void
 it_fsm_post_encode (void)
 {
 static void
 it_fsm_post_encode (void)
 {
@@ -16321,6 +16526,44 @@ it_fsm_post_encode (void)
   if (!now_it.state_handled)
     handle_it_state ();
 
   if (!now_it.state_handled)
     handle_it_state ();
 
+  if (now_it.insn_cond
+      && !now_it.warn_deprecated
+      && warn_on_deprecated
+      && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v8))
+    {
+      if (inst.instruction >= 0x10000)
+       {
+         as_warn (_("it blocks containing wide Thumb instructions are "
+                    "deprecated in ARMv8"));
+         now_it.warn_deprecated = TRUE;
+       }
+      else
+       {
+         const struct depr_insn_mask *p = depr_it_insns;
+
+         while (p->mask != 0)
+           {
+             if ((inst.instruction & p->mask) == p->pattern)
+               {
+                 as_warn (_("it blocks containing 16-bit Thumb intsructions "
+                            "of the following class are deprecated in ARMv8: "
+                            "%s"), p->description);
+                 now_it.warn_deprecated = TRUE;
+                 break;
+               }
+
+             ++p;
+           }
+       }
+
+      if (now_it.block_length > 1)
+       {
+         as_warn (_("it blocks of more than one conditional instruction are "
+                    "deprecated in ARMv8"));
+         now_it.warn_deprecated = TRUE;
+       }
+    }
+
   is_last = (now_it.mask == 0x10);
   if (is_last)
     {
   is_last = (now_it.mask == 0x10);
   if (is_last)
     {
@@ -16951,22 +17194,32 @@ static const struct asm_cond conds[] =
   {"al", 0xe}
 };
 
   {"al", 0xe}
 };
 
+#define UL_BARRIER(L,U,CODE,FEAT) \
+  { L, CODE, ARM_FEATURE (FEAT, 0) }, \
+  { U, CODE, ARM_FEATURE (FEAT, 0) }
+
 static struct asm_barrier_opt barrier_opt_names[] =
 {
 static struct asm_barrier_opt barrier_opt_names[] =
 {
-  { "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 }
+  UL_BARRIER ("sy",    "SY",    0xf, ARM_EXT_BARRIER),
+  UL_BARRIER ("st",    "ST",    0xe, ARM_EXT_BARRIER),
+  UL_BARRIER ("ld",    "LD",    0xd, ARM_EXT_V8),
+  UL_BARRIER ("ish",   "ISH",   0xb, ARM_EXT_BARRIER),
+  UL_BARRIER ("sh",    "SH",    0xb, ARM_EXT_BARRIER),
+  UL_BARRIER ("ishst", "ISHST", 0xa, ARM_EXT_BARRIER),
+  UL_BARRIER ("shst",  "SHST",  0xa, ARM_EXT_BARRIER),
+  UL_BARRIER ("ishld", "ISHLD", 0x9, ARM_EXT_V8),
+  UL_BARRIER ("un",    "UN",    0x7, ARM_EXT_BARRIER),
+  UL_BARRIER ("nsh",   "NSH",   0x7, ARM_EXT_BARRIER),
+  UL_BARRIER ("unst",  "UNST",  0x6, ARM_EXT_BARRIER),
+  UL_BARRIER ("nshst", "NSHST", 0x6, ARM_EXT_BARRIER),
+  UL_BARRIER ("nshld", "NSHLD", 0x5, ARM_EXT_V8),
+  UL_BARRIER ("osh",   "OSH",   0x3, ARM_EXT_BARRIER),
+  UL_BARRIER ("oshst", "OSHST", 0x2, ARM_EXT_BARRIER),
+  UL_BARRIER ("oshld", "OSHLD", 0x1, ARM_EXT_V8)
 };
 
 };
 
+#undef UL_BARRIER
+
 /* Table of ARM-format instructions.   */
 
 /* Macros for gluing together operand strings.  N.B. In all cases
 /* Table of ARM-format instructions.   */
 
 /* Macros for gluing together operand strings.  N.B. In all cases
@@ -17714,8 +17967,24 @@ static const struct asm_opcode insns[] =
 
  TUF("pldw",   410f000, f830f000, 1, (ADDR),   pld,    t_pld),
 
 
  TUF("pldw",   410f000, f830f000, 1, (ADDR),   pld,    t_pld),
 
+ /* AArchv8 instructions.  */
+#undef  ARM_VARIANT
+#define ARM_VARIANT   & arm_ext_v8
+#undef  THUMB_VARIANT
+#define THUMB_VARIANT & arm_ext_v8
+
+ tCE("sevl",   320f005, _sevl,    0, (),               noargs, t_hint),
+
+#undef ARM_VARIANT
+#define ARM_VARIANT  NULL
+ TUF("dcps1",  0,       f78f8001, 0, (),       noargs, noargs),
+ TUF("dcps2",  0,       f78f8002, 0, (),       noargs, noargs),
+ TUF("dcps3",  0,       f78f8003, 0, (),       noargs, noargs),
+
 #undef  ARM_VARIANT
 #define ARM_VARIANT  & fpu_fpa_ext_v1  /* Core FPA instruction set (V1).  */
 #undef  ARM_VARIANT
 #define ARM_VARIANT  & fpu_fpa_ext_v1  /* Core FPA instruction set (V1).  */
+#undef  THUMB_VARIANT
+#define THUMB_VARIANT NULL
 
  cCE("wfs",    e200110, 1, (RR),            rd),
  cCE("rfs",    e300110, 1, (RR),            rd),
 
  cCE("wfs",    e200110, 1, (RR),            rd),
  cCE("rfs",    e300110, 1, (RR),            rd),
@@ -20588,13 +20857,22 @@ md_apply_fix (fixS *  fixP,
            }
        }
 
            }
        }
 
-      newimm = encode_arm_immediate (value);
       temp = md_chars_to_number (buf, INSN_SIZE);
 
       temp = md_chars_to_number (buf, INSN_SIZE);
 
-      /* If the instruction will fail, see if we can fix things up by
-        changing the opcode.  */
-      if (newimm == (unsigned int) FAIL
-         && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
+      /* If the offset is negative, we should use encoding A2 for ADR.  */
+      if ((temp & 0xfff0000) == 0x28f0000 && value < 0)
+       newimm = negate_data_op (&temp, value);
+      else
+       {
+         newimm = encode_arm_immediate (value);
+
+         /* If the instruction will fail, see if we can fix things up by
+            changing the opcode.  */
+         if (newimm == (unsigned int) FAIL)
+           newimm = negate_data_op (&temp, value);
+       }
+
+      if (newimm == (unsigned int) FAIL)
        {
          as_bad_where (fixP->fx_file, fixP->fx_line,
                        _("invalid constant (%lx) after fixup"),
        {
          as_bad_where (fixP->fx_file, fixP->fx_line,
                        _("invalid constant (%lx) after fixup"),
@@ -21224,8 +21502,8 @@ md_apply_fix (fixS *    fixP,
     thumb_bl_common:
 
 #ifdef OBJ_ELF
     thumb_bl_common:
 
 #ifdef OBJ_ELF
-       if (EF_ARM_EABI_VERSION (meabi_flags) >= EF_ARM_EABI_VER4 &&
-          fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
+       if (EF_ARM_EABI_VERSION (meabi_flags) >= EF_ARM_EABI_VER4
+          && fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
         fixP->fx_r_type = BFD_RELOC_THUMB_PCREL_BRANCH23;
 #endif
 
         fixP->fx_r_type = BFD_RELOC_THUMB_PCREL_BRANCH23;
 #endif
 
@@ -21236,15 +21514,15 @@ md_apply_fix (fixS *  fixP,
           1 of the base address.  */
        value = (value + 1) & ~ 1;
 
           1 of the base address.  */
        value = (value + 1) & ~ 1;
 
-       if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
-        {
-          if (!(ARM_CPU_HAS_FEATURE (cpu_variant, arm_arch_t2)))
-            as_bad_where (fixP->fx_file, fixP->fx_line, BAD_RANGE);
-          else if ((value & ~0x1ffffff)
-                   && ((value & ~0x1ffffff) != ~0x1ffffff))
-            as_bad_where (fixP->fx_file, fixP->fx_line,
-                          _("Thumb2 branch out of range"));
-        }
+      if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
+       {
+         if (!(ARM_CPU_HAS_FEATURE (cpu_variant, arm_arch_t2)))
+           as_bad_where (fixP->fx_file, fixP->fx_line, BAD_RANGE);
+         else if ((value & ~0x1ffffff)
+                  && ((value & ~0x1ffffff) != ~0x1ffffff))
+           as_bad_where (fixP->fx_file, fixP->fx_line,
+                         _("Thumb2 branch out of range"));
+       }
 
       if (fixP->fx_done || !seg->use_rela_p)
        encode_thumb2_b_bl_offset (buf, value);
 
       if (fixP->fx_done || !seg->use_rela_p)
        encode_thumb2_b_bl_offset (buf, value);
@@ -22249,6 +22527,10 @@ elf32_arm_target_format (void)
   return (target_big_endian
          ? "elf32-bigarm-vxworks"
          : "elf32-littlearm-vxworks");
   return (target_big_endian
          ? "elf32-bigarm-vxworks"
          : "elf32-littlearm-vxworks");
+#elif defined (TE_NACL)
+  return (target_big_endian
+         ? "elf32-bigarm-nacl"
+         : "elf32-littlearm-nacl");
 #else
   if (target_big_endian)
     return "elf32-bigarm";
 #else
   if (target_big_endian)
     return "elf32-bigarm";
@@ -23126,6 +23408,7 @@ static const struct arm_arch_option_table arm_archs[] =
   ARM_ARCH_OPT ("armv7-r",     ARM_ARCH_V7R,    FPU_ARCH_VFP),
   ARM_ARCH_OPT ("armv7-m",     ARM_ARCH_V7M,    FPU_ARCH_VFP),
   ARM_ARCH_OPT ("armv7e-m",    ARM_ARCH_V7EM,   FPU_ARCH_VFP),
   ARM_ARCH_OPT ("armv7-r",     ARM_ARCH_V7R,    FPU_ARCH_VFP),
   ARM_ARCH_OPT ("armv7-m",     ARM_ARCH_V7M,    FPU_ARCH_VFP),
   ARM_ARCH_OPT ("armv7e-m",    ARM_ARCH_V7EM,   FPU_ARCH_VFP),
+  ARM_ARCH_OPT ("armv8-a",     ARM_ARCH_V8A,    FPU_ARCH_VFP),
   ARM_ARCH_OPT ("xscale",      ARM_ARCH_XSCALE, FPU_ARCH_VFP),
   ARM_ARCH_OPT ("iwmmxt",      ARM_ARCH_IWMMXT, FPU_ARCH_VFP),
   ARM_ARCH_OPT ("iwmmxt2",     ARM_ARCH_IWMMXT2,FPU_ARCH_VFP),
   ARM_ARCH_OPT ("xscale",      ARM_ARCH_XSCALE, FPU_ARCH_VFP),
   ARM_ARCH_OPT ("iwmmxt",      ARM_ARCH_IWMMXT, FPU_ARCH_VFP),
   ARM_ARCH_OPT ("iwmmxt2",     ARM_ARCH_IWMMXT2,FPU_ARCH_VFP),
@@ -23147,6 +23430,10 @@ struct arm_option_extension_value_table
 #define ARM_EXT_OPT(N, V, AA) { N, sizeof (N) - 1, V, AA }
 static const struct arm_option_extension_value_table arm_extensions[] =
 {
 #define ARM_EXT_OPT(N, V, AA) { N, sizeof (N) - 1, V, AA }
 static const struct arm_option_extension_value_table arm_extensions[] =
 {
+  ARM_EXT_OPT ("crypto", FPU_ARCH_CRYPTO_NEON_VFP_ARMV8,
+                                  ARM_FEATURE (ARM_EXT_V8, 0)),
+  ARM_EXT_OPT ("fp",     FPU_ARCH_VFP_ARMV8,
+                                  ARM_FEATURE (ARM_EXT_V8, 0)),
   ARM_EXT_OPT ("idiv", ARM_FEATURE (ARM_EXT_ADIV | ARM_EXT_DIV, 0),
                                   ARM_FEATURE (ARM_EXT_V7A | ARM_EXT_V7R, 0)),
   ARM_EXT_OPT ("iwmmxt",ARM_FEATURE (0, ARM_CEXT_IWMMXT),      ARM_ANY),
   ARM_EXT_OPT ("idiv", ARM_FEATURE (ARM_EXT_ADIV | ARM_EXT_DIV, 0),
                                   ARM_FEATURE (ARM_EXT_V7A | ARM_EXT_V7R, 0)),
   ARM_EXT_OPT ("iwmmxt",ARM_FEATURE (0, ARM_CEXT_IWMMXT),      ARM_ANY),
@@ -23156,6 +23443,8 @@ static const struct arm_option_extension_value_table arm_extensions[] =
                         ARM_FEATURE (0, ARM_CEXT_MAVERICK),    ARM_ANY),
   ARM_EXT_OPT ("mp",   ARM_FEATURE (ARM_EXT_MP, 0),
                                   ARM_FEATURE (ARM_EXT_V7A | ARM_EXT_V7R, 0)),
                         ARM_FEATURE (0, ARM_CEXT_MAVERICK),    ARM_ANY),
   ARM_EXT_OPT ("mp",   ARM_FEATURE (ARM_EXT_MP, 0),
                                   ARM_FEATURE (ARM_EXT_V7A | ARM_EXT_V7R, 0)),
+  ARM_EXT_OPT ("simd",   FPU_ARCH_NEON_VFP_ARMV8,
+                                  ARM_FEATURE (ARM_EXT_V8, 0)),
   ARM_EXT_OPT ("os",   ARM_FEATURE (ARM_EXT_OS, 0),
                                   ARM_FEATURE (ARM_EXT_V6M, 0)),
   ARM_EXT_OPT ("sec",  ARM_FEATURE (ARM_EXT_SEC, 0),
   ARM_EXT_OPT ("os",   ARM_FEATURE (ARM_EXT_OS, 0),
                                   ARM_FEATURE (ARM_EXT_V6M, 0)),
   ARM_EXT_OPT ("sec",  ARM_FEATURE (ARM_EXT_SEC, 0),
@@ -23213,6 +23502,10 @@ static const struct arm_option_fpu_value_table arm_fpus[] =
   {"vfpv4-d16",                FPU_ARCH_VFP_V4D16},
   {"fpv4-sp-d16",      FPU_ARCH_VFP_V4_SP_D16},
   {"neon-vfpv4",       FPU_ARCH_NEON_VFP_V4},
   {"vfpv4-d16",                FPU_ARCH_VFP_V4D16},
   {"fpv4-sp-d16",      FPU_ARCH_VFP_V4_SP_D16},
   {"neon-vfpv4",       FPU_ARCH_NEON_VFP_V4},
+  {"fp-armv8",         FPU_ARCH_VFP_ARMV8},
+  {"neon-fp-armv8",    FPU_ARCH_NEON_VFP_ARMV8},
+  {"crypto-neon-fp-armv8",
+                       FPU_ARCH_CRYPTO_NEON_VFP_ARMV8},
   {NULL,               ARM_ARCH_NONE}
 };
 
   {NULL,               ARM_ARCH_NONE}
 };
 
@@ -23687,9 +23980,10 @@ static const cpu_arch_ver_table cpu_arch_ver[] =
     {11, ARM_ARCH_V6M},
     {12, ARM_ARCH_V6SM},
     {8, ARM_ARCH_V6T2},
     {11, ARM_ARCH_V6M},
     {12, ARM_ARCH_V6SM},
     {8, ARM_ARCH_V6T2},
-    {10, ARM_ARCH_V7A},
+    {10, ARM_ARCH_V7A_IDIV_MP_SEC_VIRT},
     {10, ARM_ARCH_V7R},
     {10, ARM_ARCH_V7M},
     {10, ARM_ARCH_V7R},
     {10, ARM_ARCH_V7M},
+    {14, ARM_ARCH_V8A},
     {0, ARM_ARCH_NONE}
 };
 
     {0, ARM_ARCH_NONE}
 };
 
@@ -23719,6 +24013,7 @@ aeabi_set_public_attributes (void)
   int arch;
   char profile;
   int virt_sec = 0;
   int arch;
   char profile;
   int virt_sec = 0;
+  int fp16_optional = 0;
   arm_feature_set flags;
   arm_feature_set tmp;
   const cpu_arch_ver_table *p;
   arm_feature_set flags;
   arm_feature_set tmp;
   const cpu_arch_ver_table *p;
@@ -23818,14 +24113,22 @@ aeabi_set_public_attributes (void)
        ARM_CPU_HAS_FEATURE (flags, arm_arch_t2) ? 2 : 1);
 
   /* Tag_VFP_arch.  */
        ARM_CPU_HAS_FEATURE (flags, arm_arch_t2) ? 2 : 1);
 
   /* Tag_VFP_arch.  */
-  if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_fma))
+  if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_armv8))
+    aeabi_set_attribute_int (Tag_VFP_arch, 7);
+  else if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_fma))
     aeabi_set_attribute_int (Tag_VFP_arch,
                             ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_d32)
                             ? 5 : 6);
   else if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_d32))
     aeabi_set_attribute_int (Tag_VFP_arch,
                             ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_d32)
                             ? 5 : 6);
   else if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_d32))
-    aeabi_set_attribute_int (Tag_VFP_arch, 3);
+    {
+      fp16_optional = 1;
+      aeabi_set_attribute_int (Tag_VFP_arch, 3);
+    }
   else if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_v3xd))
   else if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_v3xd))
-    aeabi_set_attribute_int (Tag_VFP_arch, 4);
+    {
+      aeabi_set_attribute_int (Tag_VFP_arch, 4);
+      fp16_optional = 1;
+    }
   else if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_v2))
     aeabi_set_attribute_int (Tag_VFP_arch, 2);
   else if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_v1)
   else if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_v2))
     aeabi_set_attribute_int (Tag_VFP_arch, 2);
   else if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_v1)
@@ -23844,13 +24147,23 @@ aeabi_set_public_attributes (void)
     aeabi_set_attribute_int (Tag_WMMX_arch, 1);
 
   /* Tag_Advanced_SIMD_arch (formerly Tag_NEON_arch).  */
     aeabi_set_attribute_int (Tag_WMMX_arch, 1);
 
   /* Tag_Advanced_SIMD_arch (formerly Tag_NEON_arch).  */
-  if (ARM_CPU_HAS_FEATURE (flags, fpu_neon_ext_v1))
-    aeabi_set_attribute_int
-      (Tag_Advanced_SIMD_arch, (ARM_CPU_HAS_FEATURE (flags, fpu_neon_ext_fma)
-                               ? 2 : 1));
+  if (ARM_CPU_HAS_FEATURE (flags, fpu_neon_ext_armv8))
+    aeabi_set_attribute_int (Tag_Advanced_SIMD_arch, 3);
+  else if (ARM_CPU_HAS_FEATURE (flags, fpu_neon_ext_v1))
+    {
+      if (ARM_CPU_HAS_FEATURE (flags, fpu_neon_ext_fma))
+       {
+         aeabi_set_attribute_int (Tag_Advanced_SIMD_arch, 2);
+       }
+      else
+       {
+         aeabi_set_attribute_int (Tag_Advanced_SIMD_arch, 1);
+         fp16_optional = 1;
+       }
+    }
 
   /* Tag_VFP_HP_extension (formerly Tag_NEON_FP16_arch).  */
 
   /* Tag_VFP_HP_extension (formerly Tag_NEON_FP16_arch).  */
-  if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_fp16))
+  if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_fp16) && fp16_optional)
     aeabi_set_attribute_int (Tag_VFP_HP_extension, 1);
 
   /* Tag_DIV_use.
     aeabi_set_attribute_int (Tag_VFP_HP_extension, 1);
 
   /* Tag_DIV_use.
@@ -23859,12 +24172,17 @@ aeabi_set_public_attributes (void)
      in ARM state, or when Thumb integer divide instructions have been used,
      but we have no architecture profile set, nor have we any ARM instructions.
 
      in ARM state, or when Thumb integer divide instructions have been used,
      but we have no architecture profile set, nor have we any ARM instructions.
 
+     For ARMv8 we set the tag to 0 as integer divide is implied by the base
+     architecture.
+
      For new architectures we will have to check these tests.  */
      For new architectures we will have to check these tests.  */
-  gas_assert (arch <= TAG_CPU_ARCH_V7E_M);
-  if (ARM_CPU_HAS_FEATURE (flags, arm_ext_adiv)
-      || (profile == '\0'
-         && ARM_CPU_HAS_FEATURE (flags, arm_ext_div)
-         && !ARM_CPU_HAS_FEATURE (arm_arch_used, arm_arch_any)))
+  gas_assert (arch <= TAG_CPU_ARCH_V8);
+  if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v8))
+    aeabi_set_attribute_int (Tag_DIV_use, 0);
+  else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_adiv)
+          || (profile == '\0'
+              && ARM_CPU_HAS_FEATURE (flags, arm_ext_div)
+              && !ARM_CPU_HAS_FEATURE (arm_arch_used, arm_arch_any)))
     aeabi_set_attribute_int (Tag_DIV_use, 2);
 
   /* Tag_MP_extension_use.  */
     aeabi_set_attribute_int (Tag_DIV_use, 2);
 
   /* Tag_MP_extension_use.  */
This page took 0.05215 seconds and 4 git commands to generate.