This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Armv7


The attached patch implements Armv7 binutils support. There are three 
different "profiles" in armv7: v7A, v7R and v7M. The A and R profiles are 
basically armv6T2 plus a handful of extra instructions.
The v7M profile removes the traditional Arm state (leaving only Thumb-2), and 
also removes some of the v5te and v6 instructions.

I'm not entirely sure what "-march=armv7" should mean. I can think of 2 
options:

a) Accept the common subset of the 3 profiles. For Thumb code this is fine. 
Unfortunately this definition also means all Arm state code is rejected by 
this switch, which seems less than ideal from a user POV.

b) Accept the common subset of Thumb instructions, as with (a), plus the 
common subset of A and R profile Arm state instructions. This is a bit harder 
to implement.

c) Accept the superset of all 3 profiles.

I've currently implemented (a), however I'm wondering if it's worth the effort 
to implement (b). I don't like (c) because it doesn't make sense for gcc. 
Having the same option with different semantics in gcc and gas seems a bad 
idea.

Any thoughts?

Tested with cross to arm-none-eabi.
Ok?

Paul

2006-02-23  Paul Brook  <paul@codesourcery.com>

gas/
	* config/arm/tc-arm.c (arm_ext_v6_notm, arm_ext_div, arm_ext_v7,
	arm_ext_v7a, arm_ext_v7r, arm_ext_v7m): New variables.
	(struct asm_barrier_opt): Define.
	(arm_v7m_psr_hsh, arm_barrier_opt_hsh): New variables.
	(parse_psr): Accept V7M psr names.
	(parse_barrier): New function.
	(enum operand_parse_code): Add OP_oBARRIER.
	(parse_operands): Implement OP_oBARRIER.
	(do_barrier): New function.
	(do_dbg, do_pli, do_t_barrier, do_t_dbg, do_t_div): New functions.
	(do_t_cpsi): Add V7M restrictions.
	(do_t_mrs, do_t_msr): Validate V7M variants.
	(md_assemble): Check for NULL variants.
	(v7m_psrs, barrier_opt_names): New tables.
	(insns): Add V7 instructions.  Mark V6 instructions absent from V7M.
	(md_begin): Initialize arm_v7m_psr_hsh and arm_barrier_opt_hsh.
	(arm_cpu_option_table): Add Cortex-M3, R4 and A8.
	(arm_arch_option_table): Add armv7, armv7a, armv7r and armv7m.
	(struct cpu_arch_ver_table): Define.
	(cpu_arch_ver): New.
	(aeabi_set_public_attributes): Use cpu_arch_ver.  Set
	Tag_CPU_arch_profile.
	* doc/c-arm.texi: Document new cpu and arch options.
gas/testsuite/
	* gas/arm/thumb32.d: Fix expected msr and mrs output.
	* gas/arm/arch7.d: New test.
	* gas/arm/arch7.s: New test.
	* gas/arm/arch7m-bad.l: New test.
	* gas/arm/arch7m-bad.d: New test.
	* gas/arm/arch7m-bad.s: New test.
include/opcode/
	* arm.h: Add V7 feature bits.
opcodes/
	* arm-dis.c (arm_opcodes): Add V7 instructions.
	(thumb32_opcodes): Ditto.  Handle V7M MSR/MRS variants.
	(print_arm_address): New function.
	(print_insn_arm): Use it.  Add 'P' and 'U' cases.
	(psr_name): New function.
	(print_insn_thumb32): Add 'U', 'C' and 'D' cases.
Index: gas/config/tc-arm.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/config/tc-arm.c,v
retrieving revision 1.242
diff -u -p -r1.242 tc-arm.c
--- gas/config/tc-arm.c	22 Feb 2006 15:03:29 -0000	1.242
+++ gas/config/tc-arm.c	23 Feb 2006 01:59:18 -0000
@@ -182,6 +182,12 @@ static const arm_feature_set arm_ext_v6 
 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_v6_notm = ARM_FEATURE (ARM_EXT_V6_NOTM, 0);
+static const arm_feature_set arm_ext_div = ARM_FEATURE (ARM_EXT_DIV, 0);
+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_arch_any = ARM_ANY;
 static const arm_feature_set arm_arch_full = ARM_FEATURE (-1, -1);
@@ -328,6 +334,12 @@ struct asm_psr
   unsigned long field;
 };
 
+struct asm_barrier_opt
+{
+  const char *template;
+  unsigned long value;
+};
+
 /* The bit that distinguishes CPSR and SPSR.  */
 #define SPSR_BIT   (1 << 22)
 
@@ -561,8 +573,10 @@ static struct hash_control *arm_ops_hsh;
 static struct hash_control *arm_cond_hsh;
 static struct hash_control *arm_shift_hsh;
 static struct hash_control *arm_psr_hsh;
+static struct hash_control *arm_v7m_psr_hsh;
 static struct hash_control *arm_reg_hsh;
 static struct hash_control *arm_reloc_hsh;
+static struct hash_control *arm_barrier_opt_hsh;
 
 /* Stuff needed to resolve the label ambiguity
    As:
@@ -3481,28 +3495,35 @@ parse_psr (char **str)
 {
   char *p;
   unsigned long psr_field;
+  const struct asm_psr *psr;
+  char *start;
 
   /* CPSR's and SPSR's can now be lowercase.  This is just a convenience
      feature for ease of use and backwards compatibility.  */
   p = *str;
-  if (*p == 's' || *p == 'S')
+  if (strncasecmp (p, "SPSR", 4) == 0)
     psr_field = SPSR_BIT;
-  else if (*p == 'c' || *p == 'C')
+  else if (strncasecmp (p, "CPSR", 4) == 0)
     psr_field = 0;
   else
-    goto error;
+    {
+      start = p;
+      do
+	p++;
+      while (ISALNUM (*p) || *p == '_');
+
+      psr = hash_find_n (arm_v7m_psr_hsh, start, p - start);
+      if (!psr)
+	return FAIL;
 
-  p++;
-  if (strncasecmp (p, "PSR", 3) != 0)
-    goto error;
-  p += 3;
+      *str = p;
+      return psr->field;
+    }
 
+  p += 4;
   if (*p == '_')
     {
       /* A suffix follows.  */
-      const struct asm_psr *psr;
-      char *start;
-
       p++;
       start = p;
 
@@ -3653,6 +3674,26 @@ parse_cond (char **str)
   return c->value;
 }
 
+/* Parse an option for a barrier instruction.  Returns the encoding for the
+   option, or FAIL.  */
+static int
+parse_barrier (char **str)
+{
+  char *p, *q;
+  const struct asm_barrier_opt *o;
+
+  p = q = *str;
+  while (ISALPHA (*q))
+    q++;
+
+  o = hash_find_n (arm_barrier_opt_hsh, p, q - p);
+  if (!o)
+    return FAIL;
+
+  *str = q;
+  return o->value;
+}
+
 /* Parse the operands of a table branch instruction.  Similar to a memory
    operand.  */
 static int
@@ -3777,6 +3818,7 @@ enum operand_parse_code
   OP_oSHar,	 /* ASR immediate */
   OP_oSHllar,	 /* LSL or ASR immediate */
   OP_oROR,	 /* ROR 0/8/16/24 */
+  OP_oBARRIER,	 /* Option argument for a barrier instruction.  */
 
   OP_FIRST_OPTIONAL = OP_oI7b
 };
@@ -3998,6 +4040,7 @@ parse_operands (char *str, const unsigne
 	case OP_oROR:	 val = parse_ror (&str);		break;
 	case OP_PSR:	 val = parse_psr (&str);		break;
 	case OP_COND:	 val = parse_cond (&str);		break;
+	case OP_oBARRIER:val = parse_barrier (&str);		break;
 
 	case OP_TB:
 	  po_misc_or_fail (parse_tb (&str));
@@ -4065,6 +4108,7 @@ parse_operands (char *str, const unsigne
 	case OP_oROR:
 	case OP_PSR:
 	case OP_COND:
+	case OP_oBARRIER:
 	case OP_REGLST:
 	case OP_VRSLST:
 	case OP_VRDLST:
@@ -4586,6 +4630,20 @@ do_arit (void)
 }
 
 static void
+do_barrier (void)
+{
+  if (inst.operands[0].present)
+    {
+      constraint ((inst.instruction & 0xf0) != 0x40
+		  && inst.operands[0].imm != 0xf,
+		  "bad barrier type");
+      inst.instruction |= inst.operands[0].imm;
+    }
+  else
+    inst.instruction |= 0xf;
+}
+
+static void
 do_bfc (void)
 {
   unsigned int msb = inst.operands[1].imm + inst.operands[2].imm;
@@ -4814,6 +4872,12 @@ do_cpsi (void)
 }
 
 static void
+do_dbg (void)
+{
+  inst.instruction |= inst.operands[0].imm;
+}
+
+static void
 do_it (void)
 {
   /* There is no IT instruction in ARM mode.  We
@@ -5184,6 +5248,22 @@ do_pld (void)
   encode_arm_addr_mode_2 (0, /*is_t=*/FALSE);
 }
 
+/* ARMv7: PLI <addr_mode>  */
+static void
+do_pli (void)
+{
+  constraint (!inst.operands[0].isreg,
+	      _("'[' expected after PLI mnemonic"));
+  constraint (inst.operands[0].postind,
+	      _("post-indexed expression used in preload instruction"));
+  constraint (inst.operands[0].writeback,
+	      _("writeback used in preload instruction"));
+  constraint (!inst.operands[0].preind,
+	      _("unindexed addressing used in preload instruction"));
+  encode_arm_addr_mode_2 (0, /*is_t=*/FALSE);
+  inst.instruction &= ~PRE_INDEX;
+}
+
 static void
 do_push_pop (void)
 {
@@ -6445,6 +6525,20 @@ do_t_arit3c (void)
 }
 
 static void
+do_t_barrier (void)
+{
+  if (inst.operands[0].present)
+    {
+      constraint ((inst.instruction & 0xf0) != 0x40
+		  && inst.operands[0].imm != 0xf,
+		  "bad barrier type");
+      inst.instruction |= inst.operands[0].imm;
+    }
+  else
+    inst.instruction |= 0xf;
+}
+
+static void
 do_t_bfc (void)
 {
   unsigned int msb = inst.operands[1].imm + inst.operands[2].imm;
@@ -6618,7 +6712,8 @@ static void
 do_t_cpsi (void)
 {
   if (unified_syntax
-      && (inst.operands[1].present || inst.size_req == 4))
+      && (inst.operands[1].present || inst.size_req == 4)
+      && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6_notm))
     {
       unsigned int imod = (inst.instruction & 0x0030) >> 4;
       inst.instruction = 0xf3af8000;
@@ -6629,7 +6724,11 @@ do_t_cpsi (void)
     }
   else
     {
-      constraint (inst.operands[1].present,
+      constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1)
+		  && (inst.operands[0].imm & 4),
+		  _("selected processor does not support 'A' form "
+		    "of this instruction"));
+      constraint (inst.operands[1].present || inst.size_req == 4,
 		  _("Thumb does not support the 2-argument "
 		    "form of this instruction"));
       inst.instruction |= inst.operands[0].imm;
@@ -6665,6 +6764,22 @@ do_t_czb (void)
 }
 
 static void
+do_t_dbg (void)
+{
+  inst.instruction |= inst.operands[0].imm;
+}
+
+static void
+do_t_div (void)
+{
+  if (!inst.operands[1].present)
+    inst.operands[1].reg = inst.operands[0].reg;
+  inst.instruction |= inst.operands[0].reg << 8;
+  inst.instruction |= inst.operands[1].reg << 16;
+  inst.instruction |= inst.operands[2].reg;
+}
+
+static void
 do_t_hint (void)
 {
   if (unified_syntax && inst.size_req == 4)
@@ -7211,21 +7326,53 @@ do_t_mvn_tst (void)
 static void
 do_t_mrs (void)
 {
-  /* 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"));
+  int flags;
+  flags = inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f|SPSR_BIT);
+  if (flags == 0)
+    {
+      constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v7m),
+		  _("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 %x"));
+      /* mrs only accepts CPSR/SPSR/CPSR_all/SPSR_all.  */
+      constraint ((flags & ~SPSR_BIT) != (PSR_c|PSR_f),
+		  _("'CPSR' or 'SPSR' expected"));
+    }
+    
   inst.instruction |= inst.operands[0].reg << 8;
-  inst.instruction |= (inst.operands[1].imm & SPSR_BIT) >> 2;
+  inst.instruction |= (flags & SPSR_BIT) >> 2;
+  inst.instruction |= inst.operands[1].imm & 0xff;
 }
 
 static void
 do_t_msr (void)
 {
+  int flags;
+
   constraint (!inst.operands[1].isreg,
 	      _("Thumb encoding does not support an immediate here"));
-  inst.instruction |= (inst.operands[0].imm & SPSR_BIT) >> 2;
-  inst.instruction |= (inst.operands[0].imm & ~SPSR_BIT) >> 8;
+  flags = inst.operands[0].imm;
+  if (flags & ~0xff)
+    {
+      constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1),
+		  _("selected processor does not support "
+		    "requested special purpose register"));
+    }
+  else
+    {
+      constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v7m),
+		  _("selected processor does not support "
+		    "requested special purpose register"));
+      flags |= PSR_f;
+    }
+  inst.instruction |= (flags & SPSR_BIT) >> 2;
+  inst.instruction |= (flags & ~SPSR_BIT) >> 8;
+  inst.instruction |= (flags & 0xff);
   inst.instruction |= inst.operands[1].reg << 16;
 }
 
@@ -8154,8 +8301,9 @@ md_assemble (char *str)
       if (!ARM_CPU_HAS_FEATURE (variant, arm_arch_t2))
 	ARM_CLEAR_FEATURE (variant, variant, fpu_any_hard);
       /* Check that this instruction is supported for this CPU.  */
-      if (thumb_mode == 1
-	  && !ARM_CPU_HAS_FEATURE (variant, *opcode->tvariant))
+      if (!opcode->tvariant
+	  || (thumb_mode == 1
+	      && !ARM_CPU_HAS_FEATURE (variant, *opcode->tvariant)))
 	{
 	  as_bad (_("selected processor does not support `%s'"), str);
 	  return;
@@ -8220,7 +8368,8 @@ md_assemble (char *str)
   else
     {
       /* Check that this instruction is supported for this CPU.  */
-      if (!ARM_CPU_HAS_FEATURE (cpu_variant, *opcode->avariant))
+      if (!opcode->avariant ||
+	  !ARM_CPU_HAS_FEATURE (cpu_variant, *opcode->avariant))
 	{
 	  as_bad (_("selected processor does not support `%s'"), str);
 	  return;
@@ -8526,6 +8675,25 @@ static const struct asm_psr psrs[] =
   {"cxsf", PSR_c | PSR_x | PSR_s | PSR_f},
 };
 
+/* Table of V7M psr names.  */
+static const struct asm_psr v7m_psrs[] =
+{
+  {"apsr",	0 },
+  {"iapsr",	1 },
+  {"eapsr",	2 },
+  {"psr",	3 },
+  {"ipsr",	5 },
+  {"epsr",	6 },
+  {"iepsr",	7 },
+  {"msp",	8 },
+  {"psp",	9 },
+  {"primask",	16},
+  {"basepri",	17},
+  {"basepri_max", 18},
+  {"faultmask",	19},
+  {"control",	20}
+};
+
 /* Table of all shift-in-operand names.	 */
 static const struct asm_shift_name shift_names [] =
 {
@@ -8575,6 +8743,14 @@ static const struct asm_cond conds[] =
   {"al", 0xe}
 };
 
+static struct asm_barrier_opt barrier_opt_names[] =
+{
+  { "sy",   0xf },
+  { "un",   0x7 },
+  { "st",   0xe },
+  { "unst", 0x6 }
+};
+
 /* Table of ARM-format instructions.	*/
 
 /* Macros for gluing together operand strings.  N.B. In all cases
@@ -8971,10 +9147,17 @@ static const struct asm_opcode insns[] =
 
 #undef THUMB_VARIANT
 #define THUMB_VARIANT &arm_ext_v6t2
- TUF(cps,	1020000, f3af8100, 1, (I31b),			  imm0, imm0),
  TCE(ldrex,	1900f9f, e8500f00, 2, (RRnpc, ADDR),		  ldrex, t_ldrex),
  TUF(mcrr2,	c400000, fc400000, 5, (RCP, I15b, RRnpc, RRnpc, RCN), co_reg2c, co_reg2c),
  TUF(mrrc2,	c500000, fc500000, 5, (RCP, I15b, RRnpc, RRnpc, RCN), co_reg2c, co_reg2c),
+
+ TCE(ssat,	6a00010, f3000000, 4, (RRnpc, I32, RRnpc, oSHllar),ssat,   t_ssat),
+ TCE(usat,	6e00010, f3800000, 4, (RRnpc, I31, RRnpc, oSHllar),usat,   t_usat),
+
+/*  ARM V6 not included in V7M (eg. integer SIMD).  */
+#undef THUMB_VARIANT
+#define THUMB_VARIANT &arm_ext_v6_notm
+ TUF(cps,	1020000, f3af8100, 1, (I31b),			  imm0, imm0),
  TCE(pkhbt,	6800010, eac00000, 4, (RRnpc, RRnpc, RRnpc, oSHll),   pkhbt, t_pkhbt),
  TCE(pkhtb,	6800050, eac00020, 4, (RRnpc, RRnpc, RRnpc, oSHar),   pkhtb, t_pkhtb),
  TCE(qadd16,	6200f10, fa90f010, 3, (RRnpc, RRnpc, RRnpc),	   rd_rn_rm, t_simd),
@@ -9052,13 +9235,11 @@ static const struct asm_opcode insns[] =
   UF(srsib,	9cd0500,           1, (I31w),			   srs),
   UF(srsda,	84d0500,	   1, (I31w),			   srs),
  TUF(srsdb,	94d0500, e800c000, 1, (I31w),			   srs,  srs),
- TCE(ssat,	6a00010, f3000000, 4, (RRnpc, I32, RRnpc, oSHllar),ssat,   t_ssat),
  TCE(ssat16,	6a00f30, f3200000, 3, (RRnpc, I16, RRnpc),	   ssat16, t_ssat16),
  TCE(strex,	1800f90, e8400000, 3, (RRnpc, RRnpc, ADDR),	   strex,  t_strex),
  TCE(umaal,	0400090, fbe00060, 4, (RRnpc, RRnpc, RRnpc, RRnpc),smlal,  t_mlal),
  TCE(usad8,	780f010, fb70f000, 3, (RRnpc, RRnpc, RRnpc),	   smul,   t_simd),
  TCE(usada8,	7800010, fb700000, 4, (RRnpc, RRnpc, RRnpc, RRnpc),smla,   t_mla),
- TCE(usat,	6e00010, f3800000, 4, (RRnpc, I31, RRnpc, oSHllar),usat,   t_usat),
  TCE(usat16,	6e00f30, f3a00000, 3, (RRnpc, I15, RRnpc),	   usat16, t_usat16),
 
 #undef ARM_VARIANT
@@ -9074,12 +9255,15 @@ static const struct asm_opcode insns[] =
 #define THUMB_VARIANT &arm_ext_v6t2
  TCE(ldrexb,	1d00f9f, e8d00f4f, 2, (RRnpc, RRnpcb),	              rd_rn,  rd_rn),
  TCE(ldrexh,	1f00f9f, e8d00f5f, 2, (RRnpc, RRnpcb),	              rd_rn,  rd_rn),
- TCE(ldrexd,	1b00f9f, e8d0007f, 3, (RRnpc, oRRnpc, RRnpcb),        ldrexd, t_ldrexd),
  TCE(strexb,	1c00f90, e8c00f40, 3, (RRnpc, RRnpc, ADDR),           strex,  rm_rd_rn),
  TCE(strexh,	1e00f90, e8c00f50, 3, (RRnpc, RRnpc, ADDR),           strex,  rm_rd_rn),
- TCE(strexd,	1a00f90, e8c00070, 4, (RRnpc, RRnpc, oRRnpc, RRnpcb), strexd, t_strexd),
  TUF(clrex,	57ff01f, f3bf8f2f, 0, (),			      noargs, noargs),
 
+#undef THUMB_VARIANT
+#define THUMB_VARIANT &arm_ext_v6_notm
+ TCE(ldrexd,	1b00f9f, e8d0007f, 3, (RRnpc, oRRnpc, RRnpcb),        ldrexd, t_ldrexd),
+ TCE(strexd,	1a00f90, e8c00070, 4, (RRnpc, RRnpc, oRRnpc, RRnpcb), strexd, t_strexd),
+
 #undef ARM_VARIANT
 #define ARM_VARIANT &arm_ext_v6z
  TCE(smc,	1600070, f7f08000, 1, (EXPi), smc, t_smc),
@@ -9129,6 +9313,23 @@ 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).  */
+#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),
+
+ /* ARM V7 instructions.  */
+#undef ARM_VARIANT
+#define ARM_VARIANT &arm_ext_v7
+#undef THUMB_VARIANT
+#define THUMB_VARIANT &arm_ext_v7
+ TUF(pli,	450f000, f910f000, 1, (ADDR),	  pli,	    t_pld),
+ TCE(dbg,	320f0f0, f3af80f0, 1, (I15),	  dbg,	    t_dbg),
+ TUF(dmb,	57ff050, f3bf8f50, 1, (oBARRIER), barrier,  t_barrier),
+ TUF(dsb,	57ff040, f3bf8f40, 1, (oBARRIER), barrier,  t_barrier),
+ TUF(isb,	57ff060, f3bf8f60, 1, (oBARRIER), barrier,  t_barrier),
+
 #undef ARM_VARIANT
 #define ARM_VARIANT &fpu_fpa_ext_v1  /* Core FPA instruction set (V1).  */
  cCE(wfs,	e200110, 1, (RR),	     rd),
@@ -12503,8 +12704,10 @@ md_begin (void)
       || (arm_cond_hsh = hash_new ()) == NULL
       || (arm_shift_hsh = hash_new ()) == NULL
       || (arm_psr_hsh = hash_new ()) == NULL
+      || (arm_v7m_psr_hsh = hash_new ()) == NULL
       || (arm_reg_hsh = hash_new ()) == NULL
-      || (arm_reloc_hsh = hash_new ()) == NULL)
+      || (arm_reloc_hsh = hash_new ()) == NULL
+      || (arm_barrier_opt_hsh = hash_new ()) == NULL)
     as_fatal (_("virtual memory exhausted"));
 
   for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
@@ -12515,8 +12718,15 @@ md_begin (void)
     hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
   for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
     hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
+  for (i = 0; i < sizeof (v7m_psrs) / sizeof (struct asm_psr); i++)
+    hash_insert (arm_v7m_psr_hsh, v7m_psrs[i].template, (PTR) (v7m_psrs + i));
   for (i = 0; i < sizeof (reg_names) / sizeof (struct reg_entry); i++)
     hash_insert (arm_reg_hsh, reg_names[i].name, (PTR) (reg_names + i));
+  for (i = 0;
+       i < sizeof (barrier_opt_names) / sizeof (struct asm_barrier_opt);
+       i++)
+    hash_insert (arm_barrier_opt_hsh, barrier_opt_names[i].template,
+		 (PTR) (barrier_opt_names + i));
 #ifdef OBJ_ELF
   for (i = 0; i < sizeof (reloc_names) / sizeof (struct reloc_entry); i++)
     hash_insert (arm_reloc_hsh, reloc_names[i].name, (PTR) (reloc_names + i));
@@ -13028,6 +13238,9 @@ static const struct arm_cpu_option_table
   {"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-a8",		ARM_ARCH_V7A,	 FPU_ARCH_VFP_V2, NULL},
+  {"cortex-r4",		ARM_ARCH_V7R,	 FPU_NONE,	  NULL},
+  {"cortex-m3",		ARM_ARCH_V7M,	 FPU_NONE,	  NULL},
   /* ??? XSCALE is really an architecture.  */
   {"xscale",		ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2, NULL},
   /* ??? iwmmxt is not a processor.  */
@@ -13075,6 +13288,10 @@ static const struct arm_arch_option_tabl
   {"armv6kt2",		ARM_ARCH_V6KT2,	 FPU_ARCH_VFP},
   {"armv6zt2",		ARM_ARCH_V6ZT2,	 FPU_ARCH_VFP},
   {"armv6zkt2",		ARM_ARCH_V6ZKT2, FPU_ARCH_VFP},
+  {"armv7",		ARM_ARCH_V7,	 FPU_ARCH_VFP},
+  {"armv7a",		ARM_ARCH_V7A,	 FPU_ARCH_VFP},
+  {"armv7r",		ARM_ARCH_V7R,	 FPU_ARCH_VFP},
+  {"armv7m",		ARM_ARCH_V7M,	 FPU_ARCH_VFP},
   {"xscale",		ARM_ARCH_XSCALE, FPU_ARCH_VFP},
   {"iwmmxt",		ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
   {NULL,		ARM_ARCH_NONE,	 ARM_ARCH_NONE}
@@ -13474,37 +13691,56 @@ md_show_usage (FILE * fp)
 
 
 #ifdef OBJ_ELF
+typedef struct
+{
+  int val;
+  arm_feature_set flags;
+} cpu_arch_ver_table;
+
+/* Mapping from CPU features to EABI CPU arch values.  Table must be sorted
+   least features first.  */
+static const cpu_arch_ver_table cpu_arch_ver[] =
+{
+    {1, ARM_ARCH_V4},
+    {2, ARM_ARCH_V4T},
+    {3, ARM_ARCH_V5},
+    {4, ARM_ARCH_V5TE},
+    {5, ARM_ARCH_V5TEJ},
+    {6, ARM_ARCH_V6},
+    {7, ARM_ARCH_V6Z},
+    {8, ARM_ARCH_V6K},
+    {9, ARM_ARCH_V6T2},
+    {10, ARM_ARCH_V7A},
+    {10, ARM_ARCH_V7R},
+    {10, ARM_ARCH_V7M},
+    {0, ARM_ARCH_NONE}
+};
+
 /* Set the public EABI object attributes.  */
 static void
 aeabi_set_public_attributes (void)
 {
   int arch;
   arm_feature_set flags;
+  arm_feature_set tmp;
+  const cpu_arch_ver_table *p;
 
   /* Choose the architecture based on the capabilities of the requested cpu
      (if any) and/or the instructions actually used.  */
   ARM_MERGE_FEATURE_SETS (flags, arm_arch_used, thumb_arch_used);
   ARM_MERGE_FEATURE_SETS (flags, flags, *mfpu_opt);
   ARM_MERGE_FEATURE_SETS (flags, flags, selected_cpu);
-  if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v6t2))
-    arch = 8;
-  else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v6z))
-    arch = 7;
-  else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v6k))
-    arch = 9;
-  else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v6))
-    arch = 6;
-  else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v5e))
-    arch = 4;
-  else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v5)
-	   || ARM_CPU_HAS_FEATURE (flags, arm_ext_v5t))
-    arch = 3;
-  else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v4t))
-    arch = 2;
-  else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v4))
-    arch = 1;
-  else
-    arch = 0;
+  
+  tmp = flags;
+  arch = 0;
+  for (p = cpu_arch_ver; p->val; p++)
+    {
+      if (ARM_CPU_HAS_FEATURE (tmp, p->flags))
+	{
+	  arch = p->val;
+	  ARM_CLEAR_FEATURE (tmp, tmp, p->flags);
+	}
+    }
 
   /* Tag_CPU_name.  */
   if (selected_cpu_name[0])
@@ -13524,6 +13760,13 @@ aeabi_set_public_attributes (void)
     }
   /* Tag_CPU_arch.  */
   elf32_arm_add_eabi_attr_int (stdoutput, 6, arch);
+  /* Tag_CPU_arch_profile.  */
+  if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v7a))
+    elf32_arm_add_eabi_attr_int (stdoutput, 7, 'A');
+  else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v7r))
+    elf32_arm_add_eabi_attr_int (stdoutput, 7, 'R');
+  else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v7m))
+    elf32_arm_add_eabi_attr_int (stdoutput, 7, 'M');
   /* Tag_ARM_ISA_use.  */
   if (ARM_CPU_HAS_FEATURE (arm_arch_used, arm_arch_full))
     elf32_arm_add_eabi_attr_int (stdoutput, 8, 1);
Index: gas/testsuite/gas/arm/arch7.d
===================================================================
RCS file: gas/testsuite/gas/arm/arch7.d
diff -N gas/testsuite/gas/arm/arch7.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/arch7.d	22 Feb 2006 23:19:04 -0000
@@ -0,0 +1,76 @@
+#name: ARM V7 instructions
+#as: -march=armv7r
+#objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0+000 <[^>]*> f6d6f008 	pli	\[r6, r8\]
+0+004 <[^>]*> f6d9f007 	pli	\[r9, r7\]
+0+008 <[^>]*> f6d0f101 	pli	\[r0, r1, lsl #2\]
+0+00c <[^>]*> f4d5f000 	pli	\[r5\]
+0+010 <[^>]*> f4d5ffff 	pli	\[r5, #4095\]
+0+014 <[^>]*> f455ffff 	pli	\[r5, #-4095\]
+0+018 <[^>]*> e320f0f0 	dbg	#0
+0+01c <[^>]*> e320f0ff 	dbg	#15
+0+020 <[^>]*> f57ff05f 	dmb	sy
+0+024 <[^>]*> f57ff05f 	dmb	sy
+0+028 <[^>]*> f57ff04f 	dsb	sy
+0+02c <[^>]*> f57ff04f 	dsb	sy
+0+030 <[^>]*> f57ff047 	dsb	un
+0+034 <[^>]*> f57ff04e 	dsb	st
+0+038 <[^>]*> f57ff046 	dsb	unst
+0+03c <[^>]*> f57ff06f 	isb	sy
+0+040 <[^>]*> f57ff06f 	isb	sy
+0+044 <[^>]*> f916 f008 	pli	\[r6, r8\]
+0+048 <[^>]*> f919 f007 	pli	\[r9, r7\]
+0+04c <[^>]*> f910 f021 	pli	\[r0, r1, lsl #2\]
+0+050 <[^>]*> f995 f000 	pli	\[r5\]
+0+054 <[^>]*> f995 ffff 	pli	\[r5, #4095\]
+0+058 <[^>]*> f915 fcff 	pli	\[r5, #-255\]
+0+05c <[^>]*> f99f ffff 	pli	\[pc, #4095\]	; 0000105f <[^>]*>
+0+060 <[^>]*> f91f ffff 	pli	\[pc, #-4095\]	; fffff065 <[^>]*>
+0+064 <[^>]*> f3af 80f0 	dbg	#0
+0+068 <[^>]*> f3af 80ff 	dbg	#15
+0+06c <[^>]*> f3bf 8f5f 	dmb	sy
+0+070 <[^>]*> f3bf 8f5f 	dmb	sy
+0+074 <[^>]*> f3bf 8f4f 	dsb	sy
+0+078 <[^>]*> f3bf 8f4f 	dsb	sy
+0+07c <[^>]*> f3bf 8f47 	dsb	un
+0+080 <[^>]*> f3bf 8f4e 	dsb	st
+0+084 <[^>]*> f3bf 8f46 	dsb	unst
+0+088 <[^>]*> f3bf 8f6f 	isb	sy
+0+08c <[^>]*> f3bf 8f6f 	isb	sy
+0+090 <[^>]*> fb99 f6fc 	sdiv	r6, r9, ip
+0+094 <[^>]*> fb96 f9f3 	sdiv	r9, r6, r3
+0+098 <[^>]*> fbb6 f9f3 	udiv	r9, r6, r3
+0+09c <[^>]*> fbb9 f6fc 	udiv	r6, r9, ip
+# V7M APSR has the same encoding as V7A CPSR_f
+0+0a0 <[^>]*> f3ef 8000 	mrs	r0, (CPSR|APSR)
+0+0a4 <[^>]*> f3ef 8001 	mrs	r0, IAPSR
+0+0a8 <[^>]*> f3ef 8002 	mrs	r0, EAPSR
+0+0ac <[^>]*> f3ef 8003 	mrs	r0, PSR
+0+0b0 <[^>]*> f3ef 8005 	mrs	r0, IPSR
+0+0b4 <[^>]*> f3ef 8006 	mrs	r0, EPSR
+0+0b8 <[^>]*> f3ef 8007 	mrs	r0, IEPSR
+0+0bc <[^>]*> f3ef 8008 	mrs	r0, MSP
+0+0c0 <[^>]*> f3ef 8009 	mrs	r0, PSP
+0+0c4 <[^>]*> f3ef 8010 	mrs	r0, PRIMASK
+0+0c8 <[^>]*> f3ef 8011 	mrs	r0, BASEPRI
+0+0cc <[^>]*> f3ef 8012 	mrs	r0, BASEPRI_MASK
+0+0d0 <[^>]*> f3ef 8013 	mrs	r0, FAULTMASK
+0+0d4 <[^>]*> f3ef 8014 	mrs	r0, CONTROL
+0+0d8 <[^>]*> f380 8800 	msr	(CPSR_f|APSR), r0
+0+0dc <[^>]*> f380 8801 	msr	IAPSR, r0
+0+0e0 <[^>]*> f380 8802 	msr	EAPSR, r0
+0+0e4 <[^>]*> f380 8803 	msr	PSR, r0
+0+0e8 <[^>]*> f380 8805 	msr	IPSR, r0
+0+0ec <[^>]*> f380 8806 	msr	EPSR, r0
+0+0f0 <[^>]*> f380 8807 	msr	IEPSR, r0
+0+0f4 <[^>]*> f380 8808 	msr	MSP, r0
+0+0f8 <[^>]*> f380 8809 	msr	PSP, r0
+0+0fc <[^>]*> f380 8810 	msr	PRIMASK, r0
+0+100 <[^>]*> f380 8811 	msr	BASEPRI, r0
+0+104 <[^>]*> f380 8812 	msr	BASEPRI_MASK, r0
+0+108 <[^>]*> f380 8813 	msr	FAULTMASK, r0
+0+10c <[^>]*> f380 8814 	msr	CONTROL, r0
Index: gas/testsuite/gas/arm/arch7.s
===================================================================
RCS file: gas/testsuite/gas/arm/arch7.s
diff -N gas/testsuite/gas/arm/arch7.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/arch7.s	22 Feb 2006 21:16:44 -0000
@@ -0,0 +1,79 @@
+	# ARMV7 instructions
+	.text
+	.arch armv7r
+label1:
+	pli	[r6, r8]
+	pli	[r9, r7]
+	pli	[r0, r1, lsl #2]
+	pli	[r5]
+	pli	[r5, #4095]
+	pli	[r5, #-4095]
+
+	dbg	#0
+	dbg	#15
+	dmb
+	dmb	sy
+	dsb
+	dsb	sy
+	dsb	un
+	dsb	st
+	dsb	unst
+	isb
+	isb	sy
+	.thumb
+	.thumb_func
+label2:
+	pli	[r6, r8]
+	pli	[r9, r7]
+	pli	[r0, r1, lsl #2]
+	pli	[r5]
+	pli	[r5, #4095]
+	pli	[r5, #-255]
+	pli	[pc, #4095]
+	pli	[pc, #-4095]
+
+	dbg	#0
+	dbg	#15
+	dmb
+	dmb	sy
+	dsb
+	dsb	sy
+	dsb	un
+	dsb	st
+	dsb	unst
+	isb
+	isb	sy
+
+	sdiv	r6, r9, r12
+	sdiv	r9, r6, r3
+	udiv	r9, r6, r3
+	udiv	r6, r9, r12
+	.arch armv7m
+	mrs	r0, apsr
+	mrs	r0, iapsr
+	mrs	r0, eapsr
+	mrs	r0, psr
+	mrs	r0, ipsr
+	mrs	r0, epsr
+	mrs	r0, iepsr
+	mrs	r0, msp
+	mrs	r0, psp
+	mrs	r0, primask
+	mrs	r0, basepri
+	mrs	r0, basepri_max
+	mrs	r0, faultmask
+	mrs	r0, control
+	msr	apsr, r0
+	msr	iapsr, r0
+	msr	eapsr, r0
+	msr	psr, r0
+	msr	ipsr, r0
+	msr	epsr, r0
+	msr	iepsr, r0
+	msr	msp, r0
+	msr	psp, r0
+	msr	primask, r0
+	msr	basepri, r0
+	msr	basepri_max, r0
+	msr	faultmask, r0
+	msr	control, r0
Index: gas/testsuite/gas/arm/arch7m-bad.d
===================================================================
RCS file: gas/testsuite/gas/arm/arch7m-bad.d
diff -N gas/testsuite/gas/arm/arch7m-bad.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/arch7m-bad.d	22 Feb 2006 15:43:42 -0000
@@ -0,0 +1,4 @@
+#name: Invalid V7M instructions
+#as: -march=armv7m
+#error-output: arch7m-bad.l
+
Index: gas/testsuite/gas/arm/arch7m-bad.l
===================================================================
RCS file: gas/testsuite/gas/arm/arch7m-bad.l
diff -N gas/testsuite/gas/arm/arch7m-bad.l
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/arch7m-bad.l	22 Feb 2006 16:14:43 -0000
@@ -0,0 +1,5 @@
+[^:]*: Assembler messages:
+[^:]*:5: Error: selected processor does not support 'A' form of this instruction -- `cpsie a'
+[^:]*:6: Error: Thumb does not support the 2-argument form of this instruction -- `cpsie i,#0x10'
+[^:]*:7: Error: selected processor does not support `cps #0x10'
+
Index: gas/testsuite/gas/arm/arch7m-bad.s
===================================================================
RCS file: gas/testsuite/gas/arm/arch7m-bad.s
diff -N gas/testsuite/gas/arm/arch7m-bad.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/arch7m-bad.s	22 Feb 2006 15:41:19 -0000
@@ -0,0 +1,7 @@
+	.text
+	.thumb
+	.thumb_func
+label:
+	cpsie a
+	cpsie i, #0x10
+	cps #0x10
Index: gas/testsuite/gas/arm/thumb32.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/testsuite/gas/arm/thumb32.d,v
retrieving revision 1.14
diff -u -p -r1.14 thumb32.d
--- gas/testsuite/gas/arm/thumb32.d	22 Feb 2006 15:03:30 -0000	1.14
+++ gas/testsuite/gas/arm/thumb32.d	23 Feb 2006 01:59:22 -0000
@@ -631,16 +631,16 @@ Disassembly of section .text:
 0[0-9a-f]+ <[^>]+> f240 5000 	movw	r0, #1280	; 0x500
 0[0-9a-f]+ <[^>]+> f240 0081 	movw	r0, #129	; 0x81
 0[0-9a-f]+ <[^>]+> f64f 70ff 	movw	r0, #65535	; 0xffff
-0[0-9a-f]+ <[^>]+> f3ef 8000 	mrs	r0, SPSR
-0[0-9a-f]+ <[^>]+> f3ff 8000 	mrs	r0, CPSR
-0[0-9a-f]+ <[^>]+> f3ef 8900 	mrs	r9, SPSR
-0[0-9a-f]+ <[^>]+> f3ff 8900 	mrs	r9, CPSR
-0[0-9a-f]+ <[^>]+> f380 8100 	msr	SPSR_c, r0
-0[0-9a-f]+ <[^>]+> f390 8100 	msr	CPSR_c, r0
-0[0-9a-f]+ <[^>]+> f389 8100 	msr	SPSR_c, r9
-0[0-9a-f]+ <[^>]+> f380 8200 	msr	SPSR_x, r0
-0[0-9a-f]+ <[^>]+> f380 8400 	msr	SPSR_s, r0
-0[0-9a-f]+ <[^>]+> f380 8800 	msr	SPSR_f, r0
+0[0-9a-f]+ <[^>]+> f3ef 8000 	mrs	r0, CPSR
+0[0-9a-f]+ <[^>]+> f3ff 8000 	mrs	r0, SPSR
+0[0-9a-f]+ <[^>]+> f3ef 8900 	mrs	r9, CPSR
+0[0-9a-f]+ <[^>]+> f3ff 8900 	mrs	r9, SPSR
+0[0-9a-f]+ <[^>]+> f380 8100 	msr	CPSR_c, r0
+0[0-9a-f]+ <[^>]+> f390 8100 	msr	SPSR_c, r0
+0[0-9a-f]+ <[^>]+> f389 8100 	msr	CPSR_c, r9
+0[0-9a-f]+ <[^>]+> f380 8200 	msr	CPSR_x, r0
+0[0-9a-f]+ <[^>]+> f380 8400 	msr	CPSR_s, r0
+0[0-9a-f]+ <[^>]+> f380 8800 	msr	CPSR_f, r0
 0[0-9a-f]+ <[^>]+> fb00 f000 	mul\.w	r0, r0, r0
 0[0-9a-f]+ <[^>]+> fb09 f000 	mul\.w	r0, r9, r0
 0[0-9a-f]+ <[^>]+> fb00 f009 	mul\.w	r0, r0, r9
Index: include/opcode/arm.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/include/opcode/arm.h,v
retrieving revision 1.7
diff -u -p -r1.7 arm.h
--- include/opcode/arm.h	31 Jan 2006 14:11:13 -0000	1.7
+++ include/opcode/arm.h	23 Feb 2006 03:06:43 -0000
@@ -35,6 +35,15 @@
 #define ARM_EXT_V6K      0x00002000     /* ARM V6K.                */
 #define ARM_EXT_V6Z      0x00004000     /* ARM V6Z.                */
 #define ARM_EXT_V6T2	 0x00008000	/* Thumb-2.                */
+#define ARM_EXT_DIV	 0x00010000	/* Integer division.       */
+/* The 'M' in Arm V7M stands for Microprocessor.
+   On earlier architecture variants it stands for Multiply.  */
+#define ARM_EXT_V5E_NOTM 0x00020000	/* Arm V5E but not Arm V7M. */
+#define ARM_EXT_V6_NOTM	 0x00040000	/* Arm V6 but not Arm V7M. */
+#define ARM_EXT_V7	 0x00080000	/* Arm V7.                 */
+#define ARM_EXT_V7A	 0x00100000	/* Arm V7A.                */
+#define ARM_EXT_V7R	 0x00200000	/* Arm V7R.                */
+#define ARM_EXT_V7M	 0x00400000	/* Arm V7M.                */
 
 /* Co-processor space extensions.  */
 #define ARM_CEXT_XSCALE   0x00000001	/* Allow MIA etc.          */
@@ -75,10 +84,18 @@
 #define ARM_AEXT_V6K    (ARM_AEXT_V6    | ARM_EXT_V6K)
 #define ARM_AEXT_V6Z    (ARM_AEXT_V6    | ARM_EXT_V6Z)
 #define ARM_AEXT_V6ZK   (ARM_AEXT_V6    | ARM_EXT_V6K | ARM_EXT_V6Z)
-#define ARM_AEXT_V6T2   (ARM_AEXT_V6    | ARM_EXT_V6T2)
-#define ARM_AEXT_V6KT2  (ARM_AEXT_V6    | ARM_EXT_V6T2 | ARM_EXT_V6K)
-#define ARM_AEXT_V6ZT2  (ARM_AEXT_V6    | ARM_EXT_V6T2 | ARM_EXT_V6Z)
-#define ARM_AEXT_V6ZKT2 (ARM_AEXT_V6    | ARM_EXT_V6T2 | ARM_EXT_V6K | ARM_EXT_V6Z)
+#define ARM_AEXT_V6T2   (ARM_AEXT_V6    | ARM_EXT_V6T2 | ARM_EXT_V6_NOTM)
+#define ARM_AEXT_V6KT2  (ARM_AEXT_V6T2 | ARM_EXT_V6K)
+#define ARM_AEXT_V6ZT2  (ARM_AEXT_V6T2 | ARM_EXT_V6Z)
+#define ARM_AEXT_V6ZKT2 (ARM_AEXT_V6T2 | ARM_EXT_V6K | ARM_EXT_V6Z)
+#define ARM_AEXT_V7_ARM	(ARM_AEXT_V6T2 | ARM_EXT_V7)
+#define ARM_AEXT_V7A	(ARM_AEXT_V7_ARM | ARM_EXT_V7A)
+#define ARM_AEXT_V7R	(ARM_AEXT_V7_ARM | ARM_EXT_V7R | ARM_EXT_DIV)
+#define ARM_AEXT_NOTM \
+  (ARM_AEXT_V4 | ARM_EXT_V5ExP | ARM_EXT_V5J | ARM_EXT_V6_NOTM)
+#define ARM_AEXT_V7M \
+  ((ARM_AEXT_V7_ARM | ARM_EXT_V7M | ARM_EXT_DIV) & ~(ARM_AEXT_NOTM))
+#define ARM_AEXT_V7 (ARM_AEXT_V7A & ARM_AEXT_V7R & ARM_AEXT_V7M)
 
 /* Processors with specific extensions in the co-processor space.  */
 #define ARM_ARCH_XSCALE	ARM_FEATURE (ARM_AEXT_V5TE, ARM_CEXT_XSCALE)
@@ -130,13 +147,17 @@
 #define ARM_ARCH_V6KT2	ARM_FEATURE (ARM_AEXT_V6KT2, 0)
 #define ARM_ARCH_V6ZT2	ARM_FEATURE (ARM_AEXT_V6ZT2, 0)
 #define ARM_ARCH_V6ZKT2	ARM_FEATURE (ARM_AEXT_V6ZKT2, 0)
+#define ARM_ARCH_V7	ARM_FEATURE (ARM_AEXT_V7, 0)
+#define ARM_ARCH_V7A	ARM_FEATURE (ARM_AEXT_V7A, 0)
+#define ARM_ARCH_V7R	ARM_FEATURE (ARM_AEXT_V7R, 0)
+#define ARM_ARCH_V7M	ARM_FEATURE (ARM_AEXT_V7M, 0)
 
 /* Some useful combinations:  */
 #define ARM_ARCH_NONE	ARM_FEATURE (0, 0)
 #define FPU_NONE	ARM_FEATURE (0, 0)
 #define ARM_ANY		ARM_FEATURE (-1, 0)	/* Any basic core.  */
 #define FPU_ANY_HARD	ARM_FEATURE (0, FPU_FPA | FPU_VFP_HARD | FPU_MAVERICK)
-#define ARM_ARCH_THUMB2 ARM_FEATURE (ARM_EXT_V6T2, 0)
+#define ARM_ARCH_THUMB2 ARM_FEATURE (ARM_EXT_V6T2 | ARM_EXT_V7 | ARM_EXT_V7A | ARM_EXT_V7R | ARM_EXT_V7M | ARM_EXT_DIV, 0)
 
 /* There are too many feature bits to fit in a single word, so use a
    structure.  For simplicity we put all core features in one word and
Index: opcodes/arm-dis.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/opcodes/arm-dis.c,v
retrieving revision 1.60
diff -u -p -r1.60 arm-dis.c
--- opcodes/arm-dis.c	2 Nov 2005 16:53:11 -0000	1.60
+++ opcodes/arm-dis.c	22 Feb 2006 23:20:56 -0000
@@ -402,6 +402,8 @@ static const struct opcode32 coprocessor
    %t			print 't' iff bit 21 set and bit 24 clear
    %B			print arm BLX(1) destination
    %C			print the PSR sub type.
+   %U			print barrier type.
+   %P			print address for pli instruction.
 
    %<bitfield>r		print as an ARM register
    %<bitfield>d		print the bitfield in decimal
@@ -428,6 +430,13 @@ static const struct opcode32 arm_opcodes
   {ARM_EXT_V3M, 0x00800090, 0x0fa000f0, "%22?sumull%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
   {ARM_EXT_V3M, 0x00a00090, 0x0fa000f0, "%22?sumlal%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
 
+  /* V7 instructions.  */
+  {ARM_EXT_V7, 0xf450f000, 0xfd70f000, "pli\t%P"},
+  {ARM_EXT_V7, 0x0320f0f0, 0x0ffffff0, "dbg%c\t#%0-3d"},
+  {ARM_EXT_V7, 0xf57ff050, 0xfffffff0, "dmb\t%U"},
+  {ARM_EXT_V7, 0xf57ff040, 0xfffffff0, "dsb\t%U"},
+  {ARM_EXT_V7, 0xf57ff060, 0xfffffff0, "isb\t%U"},
+
   /* ARM V6T2 instructions.  */
   {ARM_EXT_V6T2, 0x07c0001f, 0x0fe0007f, "bfc%c\t%12-15r, %E"},
   {ARM_EXT_V6T2, 0x07c00010, 0x0fe00070, "bfi%c\t%12-15r, %0-3r, %E"},
@@ -827,6 +836,8 @@ static const struct opcode16 thumb_opcod
        %B		print an unconditional branch offset
        %s		print the shift field of an SSAT instruction
        %R		print the rotation field of an SXT instruction
+       %U		print barrier type.
+       %P		print address for pli instruction.
 
        %<bitfield>d	print bitfield in decimal
        %<bitfield>W	print bitfield*4 in decimal
@@ -847,6 +858,15 @@ static const struct opcode16 thumb_opcod
    makes heavy use of special-case bit patterns.  */
 static const struct opcode32 thumb32_opcodes[] =
 {
+  /* V7 instructions.  */
+  {ARM_EXT_V7, 0xf910f000, 0xff70f000, "pli\t%a"},
+  {ARM_EXT_V7, 0xf3af80f0, 0xfffffff0, "dbg\t#%0-3d"},
+  {ARM_EXT_V7, 0xf3bf8f50, 0xfffffff0, "dmb\t%U"},
+  {ARM_EXT_V7, 0xf3bf8f40, 0xfffffff0, "dsb\t%U"},
+  {ARM_EXT_V7, 0xf3bf8f60, 0xfffffff0, "isb\t%U"},
+  {ARM_EXT_DIV, 0xfb90f0f0, 0xfff0f0f0, "sdiv\t%8-11r, %16-19r, %0-3r"},
+  {ARM_EXT_DIV, 0xfbb0f0f0, 0xfff0f0f0, "udiv\t%8-11r, %16-19r, %0-3r"},
+
   /* Instructions defined in the basic V6T2 set.  */
   {ARM_EXT_V6T2, 0xf3af8000, 0xffffffff, "nop.w"},
   {ARM_EXT_V6T2, 0xf3af8001, 0xffffffff, "yield.w"},
@@ -861,14 +881,14 @@ static const struct opcode32 thumb32_opc
   {ARM_EXT_V6T2, 0xf3c08f00, 0xfff0ffff, "bxj\t%16-19r"},
   {ARM_EXT_V6T2, 0xe810c000, 0xffd0ffff, "rfedb\t%16-19r%21'!"},
   {ARM_EXT_V6T2, 0xe990c000, 0xffd0ffff, "rfeia\t%16-19r%21'!"},
-  {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff0ff, "mrs\t%8-11r, %20?CSPSR"},
+  {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff000, "mrs\t%8-11r, %D"},
   {ARM_EXT_V6T2, 0xf3af8100, 0xffffffe0, "cps\t#%0-4d"},
   {ARM_EXT_V6T2, 0xe8d0f000, 0xfff0fff0, "tbb\t[%16-19r, %0-3r]"},
   {ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh\t[%16-19r, %0-3r, lsl #1]"},
   {ARM_EXT_V6T2, 0xf3af8500, 0xffffff00, "cpsie\t%7'a%6'i%5'f, #%0-4d"},
   {ARM_EXT_V6T2, 0xf3af8700, 0xffffff00, "cpsid\t%7'a%6'i%5'f, #%0-4d"},
   {ARM_EXT_V6T2, 0xf3de8f00, 0xffffff00, "subs\tpc, lr, #%0-7d"},
-  {ARM_EXT_V6T2, 0xf3808000, 0xffe0f0ff, "msr\t%20?CSPSR_%8'c%9'x%10's%11'f, %16-19r"},
+  {ARM_EXT_V6T2, 0xf3808000, 0xffe0f000, "msr\t%C, %16-19r"},
   {ARM_EXT_V6T2, 0xe8500f00, 0xfff00fff, "ldrex\t%12-15r, [%16-19r]"},
   {ARM_EXT_V6T2, 0xe8d00f4f, 0xfff00fef, "ldrex%4?hb\t%12-15r, [%16-19r]"},
   {ARM_EXT_V6T2, 0xe800c000, 0xffd0ffe0, "srsdb\t#%0-4d%21'!"},
@@ -1602,6 +1622,96 @@ print_insn_coprocessor (struct disassemb
   return FALSE;
 }
 
+static void
+print_arm_address (bfd_vma pc, struct disassemble_info *info, long given)
+{
+  void *stream = info->stream;
+  fprintf_ftype func = info->fprintf_func;
+
+  if (((given & 0x000f0000) == 0x000f0000)
+      && ((given & 0x02000000) == 0))
+    {
+      int offset = given & 0xfff;
+
+      func (stream, "[pc");
+
+      if (given & 0x01000000)
+	{
+	  if ((given & 0x00800000) == 0)
+	    offset = - offset;
+
+	  /* Pre-indexed.  */
+	  func (stream, ", #%d]", offset);
+
+	  offset += pc + 8;
+
+	  /* Cope with the possibility of write-back
+	     being used.  Probably a very dangerous thing
+	     for the programmer to do, but who are we to
+	     argue ?  */
+	  if (given & 0x00200000)
+	    func (stream, "!");
+	}
+      else
+	{
+	  /* Post indexed.  */
+	  func (stream, "], #%d", offset);
+
+	  /* ie ignore the offset.  */
+	  offset = pc + 8;
+	}
+
+      func (stream, "\t; ");
+      info->print_address_func (offset, info);
+    }
+  else
+    {
+      func (stream, "[%s",
+	    arm_regnames[(given >> 16) & 0xf]);
+      if ((given & 0x01000000) != 0)
+	{
+	  if ((given & 0x02000000) == 0)
+	    {
+	      int offset = given & 0xfff;
+	      if (offset)
+		func (stream, ", #%s%d",
+		      (((given & 0x00800000) == 0)
+		       ? "-" : ""), offset);
+	    }
+	  else
+	    {
+	      func (stream, ", %s",
+		    (((given & 0x00800000) == 0)
+		     ? "-" : ""));
+	      arm_decode_shift (given, func, stream);
+	    }
+
+	  func (stream, "]%s",
+		((given & 0x00200000) != 0) ? "!" : "");
+	}
+      else
+	{
+	  if ((given & 0x02000000) == 0)
+	    {
+	      int offset = given & 0xfff;
+	      if (offset)
+		func (stream, "], #%s%d",
+		      (((given & 0x00800000) == 0)
+		       ? "-" : ""), offset);
+	      else
+		func (stream, "]");
+	    }
+	  else
+	    {
+	      func (stream, "], %s",
+		    (((given & 0x00800000) == 0)
+		     ? "-" : ""));
+	      arm_decode_shift (given, func, stream);
+	    }
+	}
+    }
+}
+
 /* Print one ARM instruction from PC on INFO->STREAM.  */
 
 static void
@@ -1642,88 +1752,13 @@ print_insn_arm (bfd_vma pc, struct disas
 		      break;
 
 		    case 'a':
-		      if (((given & 0x000f0000) == 0x000f0000)
-			  && ((given & 0x02000000) == 0))
-			{
-			  int offset = given & 0xfff;
-
-			  func (stream, "[pc");
-
-			  if (given & 0x01000000)
-			    {
-			      if ((given & 0x00800000) == 0)
-				offset = - offset;
-
-			      /* Pre-indexed.  */
-			      func (stream, ", #%d]", offset);
-
-			      offset += pc + 8;
-
-			      /* Cope with the possibility of write-back
-				 being used.  Probably a very dangerous thing
-				 for the programmer to do, but who are we to
-				 argue ?  */
-			      if (given & 0x00200000)
-				func (stream, "!");
-			    }
-			  else
-			    {
-			      /* Post indexed.  */
-			      func (stream, "], #%d", offset);
-
-			      /* ie ignore the offset.  */
-			      offset = pc + 8;
-			    }
-
-			  func (stream, "\t; ");
-			  info->print_address_func (offset, info);
-			}
-		      else
-			{
-			  func (stream, "[%s",
-				arm_regnames[(given >> 16) & 0xf]);
-			  if ((given & 0x01000000) != 0)
-			    {
-			      if ((given & 0x02000000) == 0)
-				{
-				  int offset = given & 0xfff;
-				  if (offset)
-				    func (stream, ", #%s%d",
-					  (((given & 0x00800000) == 0)
-					   ? "-" : ""), offset);
-				}
-			      else
-				{
-				  func (stream, ", %s",
-					(((given & 0x00800000) == 0)
-					 ? "-" : ""));
-				  arm_decode_shift (given, func, stream);
-				}
+		      print_arm_address (pc, info, given);
+		      break;
 
-			      func (stream, "]%s",
-				    ((given & 0x00200000) != 0) ? "!" : "");
-			    }
-			  else
-			    {
-			      if ((given & 0x02000000) == 0)
-				{
-				  int offset = given & 0xfff;
-				  if (offset)
-				    func (stream, "], #%s%d",
-					  (((given & 0x00800000) == 0)
-					   ? "-" : ""), offset);
-				  else
-				    func (stream, "]");
-				}
-			      else
-				{
-				  func (stream, "], %s",
-					(((given & 0x00800000) == 0)
-					 ? "-" : ""));
-				  arm_decode_shift (given, func, stream);
-				}
-			    }
-			}
+		    case 'P':
+		      /* Set P address bit and use normal address
+			 printing routine.  */
+		      print_arm_address (pc, info, given | (1 << 24));
 		      break;
 
 		    case 's':
@@ -1913,6 +1948,19 @@ print_insn_arm (bfd_vma pc, struct disas
 			func (stream, "c");
 		      break;
 
+		    case 'U':
+		      switch (given & 0xf)
+			{
+			case 0xf: func(stream, "sy"); break;
+			case 0x7: func(stream, "un"); break;
+			case 0xe: func(stream, "st"); break;
+			case 0x6: func(stream, "unst"); break;
+			default:
+			  func(stream, "#%d", (int)given & 0xf);
+			  break;
+			}
+		      break;
+
 		    case '0': case '1': case '2': case '3': case '4':
 		    case '5': case '6': case '7': case '8': case '9':
 		      {
@@ -2292,6 +2340,30 @@ print_insn_thumb16 (bfd_vma pc, struct d
   abort ();
 }
 
+/* Return the name of an V7M special register.  */
+static const char *
+psr_name (int regno)
+{
+  switch (regno)
+    {
+    case 0: return "APSR";
+    case 1: return "IAPSR";
+    case 2: return "EAPSR";
+    case 3: return "PSR";
+    case 5: return "IPSR";
+    case 6: return "EPSR";
+    case 7: return "IEPSR";
+    case 8: return "MSP";
+    case 9: return "PSP";
+    case 16: return "PRIMASK";
+    case 17: return "BASEPRI";
+    case 18: return "BASEPRI_MASK";
+    case 19: return "FAULTMASK";
+    case 20: return "CONTROL";
+    default: return "<unknown>";
+    }
+}
+
 /* Print one 32-bit Thumb instruction from PC on INFO->STREAM.  */
 
 static void
@@ -2638,6 +2710,45 @@ print_insn_thumb32 (bfd_vma pc, struct d
 		}
 		break;
 
+	      case 'U':
+		switch (given & 0xf)
+		  {
+		  case 0xf: func(stream, "sy"); break;
+		  case 0x7: func(stream, "un"); break;
+		  case 0xe: func(stream, "st"); break;
+		  case 0x6: func(stream, "unst"); break;
+		  default:
+		    func(stream, "#%d", (int)given & 0xf);
+		    break;
+		  }
+		break;
+
+	      case 'C':
+		if ((given & 0xff) == 0)
+		  {
+		    func (stream, "%cPSR_", (given & 0x100000) ? 'S' : 'C');
+		    if (given & 0x800)
+		      func (stream, "f");
+		    if (given & 0x400)
+		      func (stream, "s");
+		    if (given & 0x200)
+		      func (stream, "x");
+		    if (given & 0x100)
+		      func (stream, "c");
+		  }
+		else
+		  {
+		    func (stream, psr_name (given & 0xff));
+		  }
+		break;
+
+	      case 'D':
+		if ((given & 0xff) == 0)
+		  func (stream, "%cPSR", (given & 0x100000) ? 'S' : 'C');
+		else
+		  func (stream, psr_name (given & 0xff));
+		break;
+
 	      case '0': case '1': case '2': case '3': case '4':
 	      case '5': case '6': case '7': case '8': case '9':
 		{
Index: gas/doc/c-arm.texi
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/doc/c-arm.texi,v
retrieving revision 1.35
diff -u -p -r1.35 c-arm.texi
--- gas/doc/c-arm.texi	8 Oct 2005 17:07:16 -0000	1.35
+++ gas/doc/c-arm.texi	23 Feb 2006 02:47:28 -0000
@@ -107,6 +107,9 @@ recognized: 
 @code{arm1176jzf-s},
 @code{mpcore},
 @code{mpcorenovfp},
+@code{cortex-a8},
+@code{cortex-r4},
+@code{cortex-m3},
 @code{ep9312} (ARM920 with Cirrus Maverick coprocessor),
 @code{i80200} (Intel XScale processor)
 @code{iwmmxt} (Intel(r) XScale processor with Wireless MMX(tm) technology coprocessor)
@@ -151,6 +154,10 @@ names are recognized: 
 @code{armv6k},
 @code{armv6z},
 @code{armv6zk},
+@code{armv7},
+@code{armv7a},
+@code{armv7r},
+@code{armv7m},
 @code{iwmmxt}
 and
 @code{xscale}.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]