bfd:
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
index 6101c41fd247a7277fa089b9fa8a6ab1cfc05a4a..8dd342bdeca29d89b1517691321a9c8052d2f25b 100644 (file)
@@ -184,8 +184,8 @@ static const arm_feature_set arm_ext_v5exp = ARM_FEATURE (ARM_EXT_V5ExP, 0);
 static const arm_feature_set arm_ext_v5j = ARM_FEATURE (ARM_EXT_V5J, 0);
 static const arm_feature_set arm_ext_v6 = ARM_FEATURE (ARM_EXT_V6, 0);
 static const arm_feature_set arm_ext_v6k = ARM_FEATURE (ARM_EXT_V6K, 0);
-static const arm_feature_set arm_ext_v6z = ARM_FEATURE (ARM_EXT_V6Z, 0);
 static const arm_feature_set arm_ext_v6t2 = ARM_FEATURE (ARM_EXT_V6T2, 0);
+static const arm_feature_set arm_ext_v6m = ARM_FEATURE (ARM_EXT_V6M, 0);
 static const arm_feature_set arm_ext_v6_notm = ARM_FEATURE (ARM_EXT_V6_NOTM, 0);
 static const arm_feature_set arm_ext_v6_dsp = ARM_FEATURE (ARM_EXT_V6_DSP, 0);
 static const arm_feature_set arm_ext_barrier = ARM_FEATURE (ARM_EXT_BARRIER, 0);
@@ -196,8 +196,12 @@ 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_m =
-  ARM_FEATURE (ARM_EXT_V6M | ARM_EXT_V7M, 0);
+  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_sec = ARM_FEATURE (ARM_EXT_SEC, 0);
+static const arm_feature_set arm_ext_os = ARM_FEATURE (ARM_EXT_OS, 0);
+static const arm_feature_set arm_ext_adiv = ARM_FEATURE (ARM_EXT_ADIV, 0);
+static const arm_feature_set arm_ext_virt = ARM_FEATURE (ARM_EXT_VIRT, 0);
 
 static const arm_feature_set arm_arch_any = ARM_ANY;
 static const arm_feature_set arm_arch_full = ARM_FEATURE (-1, -1);
@@ -503,6 +507,7 @@ enum arm_reg_type
   REG_TYPE_MMXWC,
   REG_TYPE_MMXWCG,
   REG_TYPE_XSCALE,
+  REG_TYPE_RNB
 };
 
 /* Structure for a hash table entry for a register.
@@ -512,7 +517,7 @@ enum arm_reg_type
 struct reg_entry
 {
   const char *               name;
-  unsigned char              number;
+  unsigned int               number;
   unsigned char              type;
   unsigned char              builtin;
   struct neon_typed_alias *  neon;
@@ -2059,7 +2064,7 @@ parse_reloc (char **str)
 /* Directives: register aliases.  */
 
 static struct reg_entry *
-insert_reg_alias (char *str, int number, int type)
+insert_reg_alias (char *str, unsigned number, int type)
 {
   struct reg_entry *new_reg;
   const char *name;
@@ -6377,9 +6382,18 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
          break;
 
         case OP_RVC_PSR:
-          po_reg_or_goto (REG_TYPE_VFC, try_psr);
+          po_reg_or_goto (REG_TYPE_VFC, try_banked_reg);
           inst.operands[i].isvec = 1;  /* Mark VFP control reg as vector.  */
           break;
+         try_banked_reg:
+         po_reg_or_goto (REG_TYPE_RNB, try_psr);
+         if (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_virt))
+           {
+             inst.error = _("Banked registers are not available with this "
+                            "architecture.");
+             goto failure;
+           }
+         break;
           try_psr:
           val = parse_psr (&str);
           break;
@@ -7271,9 +7285,7 @@ encode_branch (int default_reloc)
       inst.reloc.type  = BFD_RELOC_ARM_PLT32;
     }
   else
-    {
-      inst.reloc.type = (bfd_reloc_code_real_type) default_reloc;
-    }
+    inst.reloc.type = (bfd_reloc_code_real_type) default_reloc;
   inst.reloc.pc_rel = 1;
 }
 
@@ -7489,6 +7501,25 @@ do_dbg (void)
   inst.instruction |= inst.operands[0].imm;
 }
 
+static void
+do_div (void)
+{
+  unsigned Rd, Rn, Rm;
+
+  Rd = inst.operands[0].reg;
+  Rn = (inst.operands[1].present
+       ? inst.operands[1].reg : Rd);
+  Rm = inst.operands[2].reg;
+
+  constraint ((Rd == REG_PC), BAD_PC);
+  constraint ((Rn == REG_PC), BAD_PC);
+  constraint ((Rm == REG_PC), BAD_PC);
+
+  inst.instruction |= Rd << 16;
+  inst.instruction |= Rn << 0;
+  inst.instruction |= Rm << 8;
+}
+
 static void
 do_it (void)
 {
@@ -7829,16 +7860,30 @@ do_vmsr (void)
 static void
 do_mrs (void)
 {
+  unsigned br;
+
   if (do_vfp_nsyn_mrs () == SUCCESS)
     return;
 
-  /* mrs only accepts CPSR/SPSR/CPSR_all/SPSR_all.  */
-  constraint ((inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f))
-             != (PSR_c|PSR_f),
-             _("'CPSR' or 'SPSR' expected"));
   constraint (inst.operands[0].reg == REG_PC, BAD_PC);
   inst.instruction |= inst.operands[0].reg << 12;
-  inst.instruction |= (inst.operands[1].imm & SPSR_BIT);
+
+  if (inst.operands[1].isreg)
+    {
+      br = inst.operands[1].reg;
+      if (((br & 0x200) == 0) && ((br & 0xf0000) != 0xf000))
+       as_bad (_("bad register for mrs"));
+    }
+  else
+    {
+      /* mrs only accepts CPSR/SPSR/CPSR_all/SPSR_all.  */
+      constraint ((inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f))
+                 != (PSR_c|PSR_f),
+                 _("'CPSR' or 'SPSR' expected"));
+      br = (15<<16) | (inst.operands[1].imm & SPSR_BIT);
+    }
+
+  inst.instruction |= br;
 }
 
 /* Two possible forms:
@@ -8099,6 +8144,13 @@ do_smc (void)
   inst.reloc.pc_rel = 0;
 }
 
+static void
+do_hvc (void)
+{
+  inst.reloc.type = BFD_RELOC_ARM_HVC;
+  inst.reloc.pc_rel = 0;
+}
+
 static void
 do_swi (void)
 {
@@ -9612,6 +9664,7 @@ do_t_branch (void)
 {
   int opcode;
   int cond;
+  int reloc;
 
   cond = inst.cond;
   set_it_insn_type (IF_INSIDE_IT_LAST_INSN);
@@ -9634,29 +9687,29 @@ do_t_branch (void)
     {
       inst.instruction = THUMB_OP32(opcode);
       if (cond == COND_ALWAYS)
-       inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH25;
+       reloc = BFD_RELOC_THUMB_PCREL_BRANCH25;
       else
        {
          gas_assert (cond != 0xF);
          inst.instruction |= cond << 22;
-         inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH20;
+         reloc = BFD_RELOC_THUMB_PCREL_BRANCH20;
        }
     }
   else
     {
       inst.instruction = THUMB_OP16(opcode);
       if (cond == COND_ALWAYS)
-       inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
+       reloc = BFD_RELOC_THUMB_PCREL_BRANCH12;
       else
        {
          inst.instruction |= cond << 8;
-         inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
+         reloc = BFD_RELOC_THUMB_PCREL_BRANCH9;
        }
       /* Allow section relaxation.  */
       if (unified_syntax && inst.size_req != 2)
        inst.relax = opcode;
     }
-
+  inst.reloc.type = reloc;
   inst.reloc.pc_rel = 1;
 }
 
@@ -10712,34 +10765,48 @@ static void
 do_t_mrs (void)
 {
   unsigned Rd;
-  int flags;
 
   if (do_vfp_nsyn_mrs () == SUCCESS)
     return;
 
-  flags = inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f|SPSR_BIT);
-  if (flags == 0)
+  Rd = inst.operands[0].reg;
+  reject_bad_reg (Rd);
+  inst.instruction |= Rd << 8;
+
+  if (inst.operands[1].isreg)
     {
-      constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_m),
-                 _("selected processor does not support "
-                   "requested special purpose register"));
+      unsigned br = inst.operands[1].reg;
+      if (((br & 0x200) == 0) && ((br & 0xf000) != 0xf000))
+       as_bad (_("bad register for mrs"));
+
+      inst.instruction |= br & (0xf << 16);
+      inst.instruction |= (br & 0x300) >> 4;
+      inst.instruction |= (br & SPSR_BIT) >> 2;
     }
   else
     {
-      constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1),
-                 _("selected processor does not support "
-                   "requested special purpose register"));
-      /* mrs only accepts CPSR/SPSR/CPSR_all/SPSR_all.  */
-      constraint ((flags & ~SPSR_BIT) != (PSR_c|PSR_f),
-                 _("'CPSR' or 'SPSR' expected"));
-    }
+      int flags = inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f|SPSR_BIT);
 
-  Rd = inst.operands[0].reg;
-  reject_bad_reg (Rd);
+      if (flags == 0)
+       {
+         constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_m),
+                     _("selected processor does not support "
+                       "requested special purpose register"));
+       }
+      else
+       {
+         constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1),
+                     _("selected processor does not support "
+                       "requested special purpose register"));
+         /* mrs only accepts CPSR/SPSR/CPSR_all/SPSR_all.  */
+         constraint ((flags & ~SPSR_BIT) != (PSR_c|PSR_f),
+                     _("'CPSR' or 'SPSR' expected"));
+       }
 
-  inst.instruction |= Rd << 8;
-  inst.instruction |= (flags & SPSR_BIT) >> 2;
-  inst.instruction |= inst.operands[1].imm & 0xff;
+      inst.instruction |= (flags & SPSR_BIT) >> 2;
+      inst.instruction |= inst.operands[1].imm & 0xff;
+      inst.instruction |= 0xf0000;
+    }
 }
 
 static void
@@ -10753,7 +10820,12 @@ do_t_msr (void)
 
   constraint (!inst.operands[1].isreg,
              _("Thumb encoding does not support an immediate here"));
-  flags = inst.operands[0].imm;
+
+  if (inst.operands[0].isreg)
+    flags = (int)(inst.operands[0].reg);
+  else
+    flags = inst.operands[0].imm;
+
   if (flags & ~0xff)
     {
       constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1),
@@ -10772,7 +10844,8 @@ do_t_msr (void)
   reject_bad_reg (Rn);
 
   inst.instruction |= (flags & SPSR_BIT) >> 2;
-  inst.instruction |= (flags & ~SPSR_BIT) >> 8;
+  inst.instruction |= (flags & 0xf0000) >> 8;
+  inst.instruction |= (flags & 0x300) >> 4;
   inst.instruction |= (flags & 0xff);
   inst.instruction |= Rn << 16;
 }
@@ -11357,6 +11430,8 @@ static void
 do_t_smc (void)
 {
   unsigned int value = inst.reloc.exp.X_add_number;
+  constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v7a),
+             _("SMC is not permitted on this architecture"));
   constraint (inst.reloc.exp.X_op != O_constant,
              _("expression too complex"));
   inst.reloc.type = BFD_RELOC_UNUSED;
@@ -11365,6 +11440,16 @@ do_t_smc (void)
   inst.instruction |= (value & 0x000f) << 16;
 }
 
+static void
+do_t_hvc (void)
+{
+  unsigned int value = inst.reloc.exp.X_add_number;
+
+  inst.reloc.type = BFD_RELOC_UNUSED;
+  inst.instruction |= (value & 0x0fff);
+  inst.instruction |= (value & 0xf000) << 4;
+}
+
 static void
 do_t_ssat_usat (int bias)
 {
@@ -11517,6 +11602,15 @@ do_t_sxth (void)
 static void
 do_t_swi (void)
 {
+  /* We have to do the following check manually as ARM_EXT_OS only applies
+     to ARM_EXT_V6M.  */
+  if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6m))
+    {
+      if (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_os))
+       as_bad (_("SVC is not permitted on this architecture"));
+      ARM_MERGE_FEATURE_SETS (thumb_arch_used, thumb_arch_used, arm_ext_os);
+    }
+
   inst.reloc.type = BFD_RELOC_ARM_SWI;
 }
 
@@ -14790,6 +14884,18 @@ do_neon_ldr_str (void)
 {
   int is_ldr = (inst.instruction & (1 << 20)) != 0;
 
+  /* Use of PC in vstr in ARM mode is deprecated in ARMv7.
+     And is UNPREDICTABLE in thumb mode.  */
+  if (!is_ldr 
+      && inst.operands[1].reg == REG_PC
+      && ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v7))
+    {
+      if (!thumb_mode && warn_on_deprecated)
+       as_warn (_("Use of PC here is deprecated"));
+      else
+       inst.error = _("Use of PC here is UNPREDICTABLE");
+    }
+
   if (inst.operands[0].issingle)
     {
       if (is_ldr)
@@ -16152,6 +16258,13 @@ arm_canonicalize_symbol_name (char * name)
   REGNUM2(p, 4,t), REGNUM2(p, 5,t), REGNUM2(p, 6,t), REGNUM2(p, 7,t), \
   REGNUM2(p, 8,t), REGNUM2(p, 9,t), REGNUM2(p,10,t), REGNUM2(p,11,t), \
   REGNUM2(p,12,t), REGNUM2(p,13,t), REGNUM2(p,14,t), REGNUM2(p,15,t)
+#define SPLRBANK(base,bank,t) \
+  REGDEF(lr_##bank, 768|((base+0)<<16), t), \
+  REGDEF(sp_##bank, 768|((base+1)<<16), t), \
+  REGDEF(spsr_##bank, 768|(base<<16)|SPSR_BIT, t), \
+  REGDEF(LR_##bank, 768|((base+0)<<16), t), \
+  REGDEF(SP_##bank, 768|((base+1)<<16), t), \
+  REGDEF(SPSR_##bank, 768|(base<<16)|SPSR_BIT, t)
 
 static const struct reg_entry reg_names[] =
 {
@@ -16182,6 +16295,34 @@ static const struct reg_entry reg_names[] =
   REGSET(c,  CN), REGSET(C, CN),
   REGSET(cr, CN), REGSET(CR, CN),
 
+  /* ARM banked registers.  */
+  REGDEF(R8_usr,512|(0<<16),RNB), REGDEF(r8_usr,512|(0<<16),RNB),
+  REGDEF(R9_usr,512|(1<<16),RNB), REGDEF(r9_usr,512|(1<<16),RNB),
+  REGDEF(R10_usr,512|(2<<16),RNB), REGDEF(r10_usr,512|(2<<16),RNB),
+  REGDEF(R11_usr,512|(3<<16),RNB), REGDEF(r11_usr,512|(3<<16),RNB),
+  REGDEF(R12_usr,512|(4<<16),RNB), REGDEF(r12_usr,512|(4<<16),RNB),
+  REGDEF(SP_usr,512|(5<<16),RNB), REGDEF(sp_usr,512|(5<<16),RNB),
+  REGDEF(LR_usr,512|(6<<16),RNB), REGDEF(lr_usr,512|(6<<16),RNB),
+
+  REGDEF(R8_fiq,512|(8<<16),RNB), REGDEF(r8_fiq,512|(8<<16),RNB),
+  REGDEF(R9_fiq,512|(9<<16),RNB), REGDEF(r9_fiq,512|(9<<16),RNB),
+  REGDEF(R10_fiq,512|(10<<16),RNB), REGDEF(r10_fiq,512|(10<<16),RNB),
+  REGDEF(R11_fiq,512|(11<<16),RNB), REGDEF(r11_fiq,512|(11<<16),RNB),
+  REGDEF(R12_fiq,512|(12<<16),RNB), REGDEF(r12_fiq,512|(12<<16),RNB),
+  REGDEF(SP_fiq,512|(13<<16),RNB), REGDEF(SP_fiq,512|(13<<16),RNB),
+  REGDEF(LR_fiq,512|(14<<16),RNB), REGDEF(lr_fiq,512|(14<<16),RNB),
+  REGDEF(SPSR_fiq,512|(14<<16)|SPSR_BIT,RNB), REGDEF(spsr_fiq,512|(14<<16)|SPSR_BIT,RNB),
+
+  SPLRBANK(0,IRQ,RNB), SPLRBANK(0,irq,RNB),
+  SPLRBANK(2,SVC,RNB), SPLRBANK(2,svc,RNB),
+  SPLRBANK(4,ABT,RNB), SPLRBANK(4,abt,RNB),
+  SPLRBANK(6,UND,RNB), SPLRBANK(6,und,RNB),
+  SPLRBANK(12,MON,RNB), SPLRBANK(12,mon,RNB),
+  REGDEF(elr_hyp,768|(14<<16),RNB), REGDEF(ELR_hyp,768|(14<<16),RNB),
+  REGDEF(sp_hyp,768|(15<<16),RNB), REGDEF(SP_hyp,768|(15<<16),RNB),
+  REGDEF(spsr_hyp,768|(14<<16)|SPSR_BIT,RNB), 
+  REGDEF(SPSR_hyp,768|(14<<16)|SPSR_BIT,RNB),
+
   /* FPA registers.  */
   REGNUM(f,0,FN), REGNUM(f,1,FN), REGNUM(f,2,FN), REGNUM(f,3,FN),
   REGNUM(f,4,FN), REGNUM(f,5,FN), REGNUM(f,6,FN), REGNUM(f,7, FN),
@@ -16767,7 +16908,7 @@ static const struct asm_opcode insns[] =
 #undef  THUMB_VARIANT
 #define THUMB_VARIANT  & arm_ext_msr
 
- TCE("mrs",    10f0000, f3ef8000, 2, (APSR_RR, RVC_PSR), mrs, t_mrs),
+ TCE("mrs",    1000000, f3e08000, 2, (APSR_RR, RVC_PSR), mrs, t_mrs),
  TCE("msr",    120f000, f3808000, 2, (RVC_PSR, RR_EXi), msr, t_msr),
 
 #undef  ARM_VARIANT
@@ -17049,12 +17190,24 @@ static const struct asm_opcode insns[] =
  TUF("clrex",  57ff01f, f3bf8f2f, 0, (),                             noargs, noargs),
 
 #undef  ARM_VARIANT
-#define ARM_VARIANT  & arm_ext_v6z
+#define ARM_VARIANT    & arm_ext_sec
+#undef THUMB_VARIANT
+#define THUMB_VARIANT  & arm_ext_sec
 
  TCE("smc",    1600070, f7f08000, 1, (EXPi), smc, t_smc),
 
+#undef ARM_VARIANT
+#define        ARM_VARIANT    & arm_ext_virt
+#undef THUMB_VARIANT
+#define        THUMB_VARIANT    & arm_ext_virt
+
+ TCE("hvc",    1400070, f7e08000, 1, (EXPi), hvc, t_hvc),
+ TCE("eret",   160006e, f3de8f00, 0, (), noargs, noargs),
+
 #undef  ARM_VARIANT
 #define ARM_VARIANT  & arm_ext_v6t2
+#undef  THUMB_VARIANT
+#define THUMB_VARIANT  & arm_ext_v6t2
 
  TCE("bfc",    7c0001f, f36f0000, 3, (RRnpc, I31, I32),           bfc, t_bfc),
  TCE("bfi",    7c00010, f3600000, 4, (RRnpc, RRnpc_I0, I31, I32), bfi, t_bfi),
@@ -17113,12 +17266,14 @@ static const struct asm_opcode insns[] =
  TCE("tbb",       0, e8d0f000, 1, (TB), 0, t_tb),
  TCE("tbh",       0, e8d0f010, 1, (TB), 0, t_tb),
 
- /* Thumb-2 hardware division instructions (R and M profiles only).  */
+ /* Hardware division instructions.  */
+#undef  ARM_VARIANT
+#define ARM_VARIANT    & arm_ext_adiv
 #undef  THUMB_VARIANT
 #define THUMB_VARIANT  & arm_ext_div
 
- TCE("sdiv",   0, fb90f0f0, 3, (RR, oRR, RR), 0, t_div),
- TCE("udiv",   0, fbb0f0f0, 3, (RR, oRR, RR), 0, t_div),
+ TCE("sdiv",   710f010, fb90f0f0, 3, (RR, oRR, RR), div, t_div),
+ TCE("udiv",   730f010, fbb0f0f0, 3, (RR, oRR, RR), div, t_div),
 
  /* ARM V6M/V7 instructions.  */
 #undef  ARM_VARIANT
@@ -20350,6 +20505,15 @@ md_apply_fix (fixS *   fixP,
       md_number_to_chars (buf, newval, INSN_SIZE);
       break;
 
+    case BFD_RELOC_ARM_HVC:
+      if (((unsigned long) value) > 0xffff)
+       as_bad_where (fixP->fx_file, fixP->fx_line,
+                     _("invalid hvc expression"));
+      newval = md_chars_to_number (buf, INSN_SIZE);
+      newval |= (value & 0xf) | ((value & 0xfff0) << 4);
+      md_number_to_chars (buf, newval, INSN_SIZE);
+      break;
+
     case BFD_RELOC_ARM_SWI:
       if (fixP->tc_fix_data != 0)
        {
@@ -21793,6 +21957,8 @@ arm_adjust_symtab (void)
 
   /* Remove any overlapping mapping symbols generated by alignment frags.  */
   bfd_map_over_sections (stdoutput, check_mapping_symbols, (char *) 0);
+  /* Now do generic ELF adjustments.  */
+  elf_adjust_symtab ();
 #endif
 }
 
@@ -22381,22 +22547,26 @@ static const struct arm_cpu_option_table arm_cpus[] =
   {"arm1156t2f-s",     ARM_ARCH_V6T2,   FPU_ARCH_VFP_V2, NULL},
   {"arm1176jz-s",      ARM_ARCH_V6ZK,   FPU_NONE,        NULL},
   {"arm1176jzf-s",     ARM_ARCH_V6ZK,   FPU_ARCH_VFP_V2, NULL},
-  {"cortex-a5",                ARM_ARCH_V7A_MP, FPU_NONE,        "Cortex-A5"},
-  {"cortex-a8",                ARM_ARCH_V7A,    ARM_FEATURE (0, FPU_VFP_V3
+  {"cortex-a5",                ARM_ARCH_V7A_MP_SEC, 
+                                        FPU_NONE,        "Cortex-A5"},
+  {"cortex-a8",                ARM_ARCH_V7A_SEC,
+                                        ARM_FEATURE (0, FPU_VFP_V3
                                                         | FPU_NEON_EXT_V1),
                                                           "Cortex-A8"},
-  {"cortex-a9",                ARM_ARCH_V7A_MP, ARM_FEATURE (0, FPU_VFP_V3
+  {"cortex-a9",                ARM_ARCH_V7A_MP_SEC,
+                                        ARM_FEATURE (0, FPU_VFP_V3
                                                         | FPU_NEON_EXT_V1),
                                                           "Cortex-A9"},
-  {"cortex-a15",       ARM_ARCH_V7A_MP, FPU_ARCH_NEON_VFP_V4,
+  {"cortex-a15",       ARM_ARCH_V7A_IDIV_MP_SEC_VIRT,
+                                        FPU_ARCH_NEON_VFP_V4,
                                                           "Cortex-A15"},
   {"cortex-r4",                ARM_ARCH_V7R,    FPU_NONE,        "Cortex-R4"},
   {"cortex-r4f",       ARM_ARCH_V7R,    FPU_ARCH_VFP_V3D16,
                                                          "Cortex-R4F"},
   {"cortex-m4",                ARM_ARCH_V7EM,   FPU_NONE,        "Cortex-M4"},
   {"cortex-m3",                ARM_ARCH_V7M,    FPU_NONE,        "Cortex-M3"},
-  {"cortex-m1",                ARM_ARCH_V6M,    FPU_NONE,        "Cortex-M1"},
-  {"cortex-m0",                ARM_ARCH_V6M,    FPU_NONE,        "Cortex-M0"},
+  {"cortex-m1",                ARM_ARCH_V6SM,   FPU_NONE,        "Cortex-M1"},
+  {"cortex-m0",                ARM_ARCH_V6SM,   FPU_NONE,        "Cortex-M0"},
   /* ??? XSCALE is really an architecture.  */
   {"xscale",           ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2, NULL},
   /* ??? iwmmxt is not a processor.  */
@@ -22446,6 +22616,7 @@ static const struct arm_arch_option_table arm_archs[] =
   {"armv6zt2",         ARM_ARCH_V6ZT2,  FPU_ARCH_VFP},
   {"armv6zkt2",                ARM_ARCH_V6ZKT2, FPU_ARCH_VFP},
   {"armv6-m",          ARM_ARCH_V6M,    FPU_ARCH_VFP},
+  {"armv6s-m",         ARM_ARCH_V6SM,   FPU_ARCH_VFP},
   {"armv7",            ARM_ARCH_V7,     FPU_ARCH_VFP},
   /* The official spelling of the ARMv7 profile variants is the dashed form.
      Accept the non-dashed form for compatibility with old toolchains.  */
@@ -22474,11 +22645,19 @@ struct arm_option_extension_value_table
    */
 static const struct arm_option_extension_value_table arm_extensions[] =
 {
+  {"idiv",     ARM_FEATURE (ARM_EXT_ADIV | ARM_EXT_DIV, 0),
+                                  ARM_FEATURE (ARM_EXT_V7A, 0)},
   {"iwmmxt",   ARM_FEATURE (0, ARM_CEXT_IWMMXT),       ARM_ANY},
   {"iwmmxt2",  ARM_FEATURE (0, ARM_CEXT_IWMMXT2),      ARM_ANY},
   {"maverick", ARM_FEATURE (0, ARM_CEXT_MAVERICK),     ARM_ANY},
   {"mp",       ARM_FEATURE (ARM_EXT_MP, 0),
                     ARM_FEATURE (ARM_EXT_V7A | ARM_EXT_V7R, 0)},
+  {"os",       ARM_FEATURE (ARM_EXT_OS, 0),
+                                  ARM_FEATURE (ARM_EXT_V6M, 0)},
+  {"sec",      ARM_FEATURE (ARM_EXT_SEC, 0),
+                    ARM_FEATURE (ARM_EXT_V6K | ARM_EXT_V7A, 0)},
+  {"virt",     ARM_FEATURE (ARM_EXT_VIRT | ARM_EXT_ADIV | ARM_EXT_DIV, 0),
+                                  ARM_FEATURE (ARM_EXT_V7A, 0)},
   {"xscale",   ARM_FEATURE (0, ARM_CEXT_XSCALE),       ARM_ANY},
   {NULL,       ARM_ARCH_NONE,                    ARM_ARCH_NONE}
 };
@@ -22999,9 +23178,10 @@ static const cpu_arch_ver_table cpu_arch_ver[] =
     {4, ARM_ARCH_V5TE},
     {5, ARM_ARCH_V5TEJ},
     {6, ARM_ARCH_V6},
-    {7, ARM_ARCH_V6Z},
     {9, ARM_ARCH_V6K},
+    {7, ARM_ARCH_V6Z},
     {11, ARM_ARCH_V6M},
+    {12, ARM_ARCH_V6SM},
     {8, ARM_ARCH_V6T2},
     {10, ARM_ARCH_V7A},
     {10, ARM_ARCH_V7R},
@@ -23033,6 +23213,7 @@ static void
 aeabi_set_public_attributes (void)
 {
   int arch;
+  int virt_sec = 0;
   arm_feature_set flags;
   arm_feature_set tmp;
   const cpu_arch_ver_table *p;
@@ -23150,17 +23331,24 @@ aeabi_set_public_attributes (void)
     aeabi_set_attribute_int (Tag_VFP_HP_extension, 1);
 
   /* Tag_DIV_use.  */
-  if (ARM_CPU_HAS_FEATURE (flags, arm_ext_div))
+  if (ARM_CPU_HAS_FEATURE (flags, arm_ext_adiv))
+    aeabi_set_attribute_int (Tag_DIV_use, 2);
+  else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_div))
     aeabi_set_attribute_int (Tag_DIV_use, 0);
-  /* Fill this in when gas supports v7a sdiv/udiv.
-    else if (... v7a with div extension used ...)
-      aeabi_set_attribute_int (Tag_DIV_use, 2);  */
   else
     aeabi_set_attribute_int (Tag_DIV_use, 1);
 
   /* Tag_MP_extension_use.  */
   if (ARM_CPU_HAS_FEATURE (flags, arm_ext_mp))
     aeabi_set_attribute_int (Tag_MPextension_use, 1);
+
+  /* Tag Virtualization_use.  */
+  if (ARM_CPU_HAS_FEATURE (flags, arm_ext_sec))
+    virt_sec |= 1;
+  if (ARM_CPU_HAS_FEATURE (flags, arm_ext_virt))
+    virt_sec |= 2;
+  if (virt_sec != 0)
+    aeabi_set_attribute_int (Tag_Virtualization_use, virt_sec);
 }
 
 /* Add the default contents for the .ARM.attributes section.  */
This page took 0.035522 seconds and 4 git commands to generate.