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]

Re: [PATCH] New option for automatically generating IT blocks


Hi,
 apologies again, this is the current version of the patch.

As I mentioned in the original post, with this patch the assembler allows use of conditional Thumb-2 instructions without requiring explicit IT instructions.

The patch adds the -mauto-it command-line option to enable this automatic generation of IT instructions. When not specified, the original behavior takes place.

I tested this by running the gas testsuite, plus the test cases I added.

Please commit it for me if accepted, since I don't have write access.

Thanks,
 Daniel.

Daniel Gutson wrote:
I just discovered that I submitted an old version of this patch.

My apologies, I'll resend the new one as soon as test finishes.

Thanks,
    Daniel.



2009-05-08 Daniel Gutson <dgutson@codesourcery.com>

	gas/
	* config/tc-arm.c (do_automatic_it): New variable.
	(it_instruction_type): New enum.
	(arm_it): New field.
	(it_state): New enum.
	(current_it): New struct and global variable.
	(current_it_compatible): New function.
	(conditional_insn): New function.
	(set_it_insn_type): New macro.
	(set_it_insn_type_last): New macro.
	(do_t_add_sub): Call automatic IT machinery functions.
	(do_t_arit3): Likewise.
	(do_t_arit3c): Likewise.
	(do_t_blx): Likewise.
	(do_t_branch): Likewise.
	(do_t_bkpt): Likewise.
	(do_t_branch23): Likewise.
	(do_t_bx): Likewise.
	(do_t_bxj): Likewise.
	(do_t_cps): Likewise.
	(do_t_cpsi): Likewise.
	(do_t_cbz): Likewise.
	(do_t_it): Likewise.
	(encode_thumb2_ldmstm): Likewise.
	(do_t_ldst): Likewise.
	(do_t_mov_cmp): Likewise.
	(do_t_mvn_tst): Likewise.
	(do_t_mul): Likewise.
	(do_t_neg): Likewise.
	(do_t_setend): Likewise.
	(do_t_shift): Likewise.
	(do_t_tb): Likewise.
	(output_it_inst): New function.
	(new_automatic_it_block): New function.
	(close_automatic_it_block): New function.
	(current_it_add_mask): New function.
	(it_fsm_pre_encode): New function.
	(handle_it_state): New function.
	(it_fsm_post_encode): New function.
	(force_automatic_it_block_close): New function.
	(in_it_block): New function.
	(md_assemble): Call automatic IT block machinery functions.
	(arm_frob_label): Likewise.
	(arm_opts): New element.
	* doc/c-arm.texi: New option -mauto-it.

	gas/testsuite/
	* gas/arm/arm-it-auto.d: New test.
	* gas/arm/arm-it-auto.s: New file.
	* gas/arm/arm-it-auto-2.d: New test case.
	* gas/arm/arm-it-auto-2.s: New file.
	* gas/arm/thumb2_it_auto.d: New test.
	* gas/arm/thumb2_it_bad.l: Error message updated.
	* gas/arm/thumb2_it_bad_auto.d: New test.
	* gas/arm/thumb2_it.d: Comment added.
	* gas/arm/thumb2_it_bad.d: Comment added.
? ChangeLog.csl
? auto_it.patch
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.384
diff -u -p -r1.384 tc-arm.c
--- gas/config/tc-arm.c	5 May 2009 11:41:31 -0000	1.384
+++ gas/config/tc-arm.c	8 May 2009 19:21:15 -0000
@@ -265,6 +265,9 @@ static int thumb_mode = 0;
    tc_frag_data field of a frag.  */
 #define MODE_RECORDED (1 << 4)
 
+/* Enables/disables automatic IT insn insertion mode. */
+static int do_automatic_it = 0;
+
 /* If unified_syntax is true, we are processing the new unified
    ARM/Thumb syntax.  Important differences from the old ARM mode:
 
@@ -315,6 +318,18 @@ struct neon_type
   unsigned elems;
 };
 
+enum it_instruction_type
+{
+   OUTSIDE_IT_INSN,
+   INSIDE_IT_INSN,
+   INSIDE_IT_LAST_INSN,
+   IF_INSIDE_IT_LAST_INSN, /* Either outside or inside;
+                              if inside, should be the last one.  */
+   NEUTRAL_IT_INSN,        /* This could be either inside or outside,
+                              i.e. BKPT and NOP.  */
+   IT_INSN                 /* The IT insn has been parsed.  */
+};
+
 struct arm_it
 {
   const char *	error;
@@ -337,6 +352,8 @@ struct arm_it
     int			     pc_rel;
   } reloc;
 
+  enum it_instruction_type it_insn_type;
+
   struct
   {
     unsigned reg;
@@ -674,6 +691,9 @@ struct asm_opcode
 #define BAD_BRANCH	_("branch must be last instruction in IT block")
 #define BAD_NOT_IT	_("instruction not allowed in IT block")
 #define BAD_FPU		_("selected FPU does not support instruction")
+#define BAD_OUT_IT  _("thumb conditional instruction should be in IT block")
+#define BAD_IT_COND _("incorrect condition in IT block")
+#define BAD_IT_IT   _("IT falling in the range of a previous IT block")
 
 static struct hash_control *arm_ops_hsh;
 static struct hash_control *arm_cond_hsh;
@@ -695,7 +715,7 @@ static struct hash_control *arm_barrier_
 
 symbolS *  last_label_seen;
 static int label_is_thumb_function_name = FALSE;
-
+
 /* Literal pool structure.  Held on a per-section
    and per-sub-section basis.  */
 
@@ -715,9 +735,55 @@ typedef struct literal_pool
 literal_pool * list_of_pools = NULL;
 
 /* State variables for IT block handling.  */
-static bfd_boolean current_it_mask = 0;
-static int current_cc;
-
+enum it_state
+{
+  OUTSIDE_IT_BLOCK, MANUAL_IT_BLOCK, AUTOMATIC_IT_BLOCK
+};
+struct current_it
+{
+  int mask;
+  enum it_state state;
+  int cc;
+  int block_length;
+  char *insn;
+  int state_handled;
+};
+
+static struct current_it current_it;
+
+static inline int
+current_it_compatible (int cond)
+{
+  return (cond & ~1) == (current_it.cc & ~1);
+}
+
+static inline int
+conditional_insn(void)
+{
+  return inst.cond != COND_ALWAYS;
+}
+
+static int in_it_block (void);
+
+static int handle_it_state (void);
+
+static void force_automatic_it_block_close (void);
+
+#define set_it_insn_type(type)      \
+  do{                               \
+    inst.it_insn_type = type;       \
+    if (handle_it_state () == FAIL) \
+      return;                       \
+  }while(0)
+
+#define set_it_insn_type_last()                     \
+  do{                                               \
+    if (inst.cond == COND_ALWAYS)                   \
+      set_it_insn_type (IF_INSIDE_IT_LAST_INSN);    \
+    else                                            \
+      set_it_insn_type (INSIDE_IT_LAST_INSN);       \
+  }while(0)
+
 /* Pure syntax.	 */
 
 /* This array holds the chars that always start a comment.  If the
@@ -6120,7 +6186,7 @@ parse_operands (char *str, const unsigne
 #undef po_reg_or_goto
 #undef po_imm_or_fail
 #undef po_scalar_or_fail
-
+
 /* Shorthand macro for instruction encoding functions issuing errors.  */
 #define constraint(expr, err) do {		\
   if (expr)					\
@@ -8482,6 +8548,9 @@ do_t_add_sub (void)
 	? inst.operands[1].reg    /* Rd, Rs, foo */
 	: inst.operands[0].reg);  /* Rd, foo -> Rd, Rd, foo */
 
+  if (Rd == REG_PC)
+    set_it_insn_type_last ();
+
   if (unified_syntax)
     {
       bfd_boolean flags;
@@ -8491,9 +8560,9 @@ do_t_add_sub (void)
       flags = (inst.instruction == T_MNEM_adds
 	       || inst.instruction == T_MNEM_subs);
       if (flags)
-	narrow = (current_it_mask == 0);
+	narrow = !in_it_block ();
       else
-	narrow = (current_it_mask != 0);
+	narrow = in_it_block ();
       if (!inst.operands[2].isreg)
 	{
 	  int add;
@@ -8745,9 +8814,9 @@ do_t_arit3 (void)
 
 	  /* See if we can do this with a 16-bit instruction.  */
 	  if (THUMB_SETS_FLAGS (inst.instruction))
-	    narrow = current_it_mask == 0;
+	    narrow = !in_it_block ();
 	  else
-	    narrow = current_it_mask != 0;
+	    narrow = in_it_block ();
 
 	  if (Rd > 7 || Rn > 7 || Rs > 7)
 	    narrow = FALSE;
@@ -8833,9 +8902,9 @@ do_t_arit3c (void)
 
 	  /* See if we can do this with a 16-bit instruction.  */
 	  if (THUMB_SETS_FLAGS (inst.instruction))
-	    narrow = current_it_mask == 0;
+	    narrow = !in_it_block ();
 	  else
-	    narrow = current_it_mask != 0;
+	    narrow = in_it_block ();
 
 	  if (Rd > 7 || Rn > 7 || Rs > 7)
 	    narrow = FALSE;
@@ -8988,7 +9057,8 @@ do_t_bfx (void)
 static void
 do_t_blx (void)
 {
-  constraint (current_it_mask && current_it_mask != 0x10, BAD_BRANCH);
+  set_it_insn_type_last ();
+
   if (inst.operands[0].isreg)
     {
       constraint (inst.operands[0].reg == REG_PC, BAD_PC);
@@ -9010,13 +9080,14 @@ do_t_branch (void)
   int opcode;
   int cond;
 
-  if (current_it_mask)
+  cond = inst.cond;
+  set_it_insn_type (IF_INSIDE_IT_LAST_INSN);
+
+  if (in_it_block ())
     {
       /* Conditional branches inside IT blocks are encoded as unconditional
          branches.  */
       cond = COND_ALWAYS;
-      /* A branch must be the last instruction in an IT block.  */
-      constraint (current_it_mask != 0x10, BAD_BRANCH);
     }
   else
     cond = inst.cond;
@@ -9066,13 +9137,14 @@ do_t_bkpt (void)
       constraint (inst.operands[0].imm > 255,
 		  _("immediate value out of range"));
       inst.instruction |= inst.operands[0].imm;
+      set_it_insn_type (NEUTRAL_IT_INSN);
     }
 }
 
 static void
 do_t_branch23 (void)
 {
-  constraint (current_it_mask && current_it_mask != 0x10, BAD_BRANCH);
+  set_it_insn_type_last ();
   inst.reloc.type   = BFD_RELOC_THUMB_PCREL_BRANCH23;
   inst.reloc.pc_rel = 1;
 
@@ -9093,7 +9165,7 @@ do_t_branch23 (void)
 static void
 do_t_bx (void)
 {
-  constraint (current_it_mask && current_it_mask != 0x10, BAD_BRANCH);
+  set_it_insn_type_last ();
   inst.instruction |= inst.operands[0].reg << 3;
   /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC.	 The reloc
      should cause the alignment to be checked once it is known.	 This is
@@ -9105,7 +9177,7 @@ do_t_bxj (void)
 {
   int Rm;
 
-  constraint (current_it_mask && current_it_mask != 0x10, BAD_BRANCH);
+  set_it_insn_type_last ();
   Rm = inst.operands[0].reg;
   reject_bad_reg (Rm);
   inst.instruction |= Rm << 16;
@@ -9131,14 +9203,14 @@ do_t_clz (void)
 static void
 do_t_cps (void)
 {
-  constraint (current_it_mask, BAD_NOT_IT);
+  set_it_insn_type (OUTSIDE_IT_INSN);
   inst.instruction |= inst.operands[0].imm;
 }
 
 static void
 do_t_cpsi (void)
 {
-  constraint (current_it_mask, BAD_NOT_IT);
+  set_it_insn_type (OUTSIDE_IT_INSN);
   if (unified_syntax
       && (inst.operands[1].present || inst.size_req == 4)
       && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6_notm))
@@ -9185,7 +9257,7 @@ do_t_cpy (void)
 static void
 do_t_cbz (void)
 {
-  constraint (current_it_mask, BAD_NOT_IT);
+  set_it_insn_type (OUTSIDE_IT_INSN);
   constraint (inst.operands[0].reg > 7, BAD_HIREG);
   inst.instruction |= inst.operands[0].reg;
   inst.reloc.pc_rel = 1;
@@ -9231,9 +9303,9 @@ do_t_it (void)
 {
   unsigned int cond = inst.operands[0].imm;
 
-  constraint (current_it_mask, BAD_NOT_IT);
-  current_it_mask = (inst.instruction & 0xf) | 0x10;
-  current_cc = cond;
+  set_it_insn_type (IT_INSN);
+  current_it.mask = (inst.instruction & 0xf) | 0x10;
+  current_it.cc = cond;
 
   /* If the condition is a negative condition, invert the mask.  */
   if ((cond & 0x1) == 0x0)
@@ -9268,9 +9340,13 @@ encode_thumb2_ldmstm (int base, unsigned
     inst.error =  _("SP not allowed in register list");
   if (load)
     {
-      if (mask & (1 << 14)
-	  && mask & (1 << 15))
-	inst.error = _("LR and PC should not both be in register list");
+      if (mask & (1 << 15))
+        {
+          if (mask & (1 << 14))
+            inst.error = _("LR and PC should not both be in register list");
+          else
+            set_it_insn_type_last ();
+        }
 
       if ((mask & (1 << base)) != 0
 	  && writeback)
@@ -9446,6 +9522,13 @@ do_t_ldst (void)
   unsigned long opcode;
   int Rn;
 
+  if (inst.operands[0].isreg
+      && !inst.operands[0].preind
+      && inst.operands[0].reg == REG_PC)
+    {
+      set_it_insn_type_last ();
+    }
+
   opcode = inst.instruction;
   if (unified_syntax)
     {
@@ -9666,6 +9749,9 @@ do_t_mov_cmp (void)
   Rn = inst.operands[0].reg;
   Rm = inst.operands[1].reg;
 
+  if (Rn == REG_PC)
+    set_it_insn_type_last ();
+
   if (unified_syntax)
     {
       int r0off = (inst.instruction == T_MNEM_mov
@@ -9676,7 +9762,7 @@ do_t_mov_cmp (void)
 
       low_regs = (Rn <= 7 && Rm <= 7);
       opcode = inst.instruction;
-      if (current_it_mask)
+      if (in_it_block ())
 	narrow = opcode != T_MNEM_movs;
       else
 	narrow = opcode != T_MNEM_movs || low_regs;
@@ -9731,7 +9817,7 @@ do_t_mov_cmp (void)
       if (!inst.operands[1].isreg)
 	{
 	  /* Immediate operand.  */
-	  if (current_it_mask == 0 && opcode == T_MNEM_mov)
+	  if (!in_it_block () && opcode == T_MNEM_mov)
 	    narrow = 0;
 	  if (low_regs && narrow)
 	    {
@@ -9757,7 +9843,7 @@ do_t_mov_cmp (void)
 	  /* Register shifts are encoded as separate shift instructions.  */
 	  bfd_boolean flags = (inst.instruction == T_MNEM_movs);
 
-	  if (current_it_mask)
+	  if (in_it_block ())
 	    narrow = !flags;
 	  else
 	    narrow = flags;
@@ -9813,7 +9899,7 @@ do_t_mov_cmp (void)
 	      && (inst.instruction == T_MNEM_mov
 		  || inst.instruction == T_MNEM_movs))
 	    {
-	      if (current_it_mask)
+	      if (in_it_block ())
 		narrow = (inst.instruction == T_MNEM_mov);
 	      else
 		narrow = (inst.instruction == T_MNEM_movs);
@@ -9975,9 +10061,9 @@ do_t_mvn_tst (void)
       else if (inst.instruction == T_MNEM_cmn)
 	narrow = TRUE;
       else if (THUMB_SETS_FLAGS (inst.instruction))
-	narrow = (current_it_mask == 0);
+	narrow = !in_it_block ();
       else
-	narrow = (current_it_mask != 0);
+	narrow = in_it_block ();
 
       if (!inst.operands[1].isreg)
 	{
@@ -10116,9 +10202,9 @@ do_t_mul (void)
 	  || Rm > 7)
 	narrow = FALSE;
       else if (inst.instruction == T_MNEM_muls)
-	narrow = (current_it_mask == 0);
+	narrow = !in_it_block ();
       else
-	narrow = (current_it_mask != 0);
+	narrow = in_it_block ();
     }
   else
     {
@@ -10184,6 +10270,8 @@ do_t_mull (void)
 static void
 do_t_nop (void)
 {
+  set_it_insn_type(NEUTRAL_IT_INSN);
+
   if (unified_syntax)
     {
       if (inst.size_req == 4 || inst.operands[0].imm > 15)
@@ -10220,9 +10308,9 @@ do_t_neg (void)
       bfd_boolean narrow;
 
       if (THUMB_SETS_FLAGS (inst.instruction))
-	narrow = (current_it_mask == 0);
+	narrow = !in_it_block ();
       else
-	narrow = (current_it_mask != 0);
+	narrow = in_it_block ();
       if (inst.operands[0].reg > 7 || inst.operands[1].reg > 7)
 	narrow = FALSE;
       if (inst.size_req == 4)
@@ -10446,9 +10534,9 @@ do_t_rsb (void)
       bfd_boolean narrow;
 
       if ((inst.instruction & 0x00100000) != 0)
-	narrow = (current_it_mask == 0);
+	narrow = !in_it_block ();
       else
-	narrow = (current_it_mask != 0);
+	narrow = in_it_block ();
 
       if (Rd > 7 || Rs > 7)
 	narrow = FALSE;
@@ -10482,7 +10570,7 @@ do_t_rsb (void)
 static void
 do_t_setend (void)
 {
-  constraint (current_it_mask, BAD_NOT_IT);
+  set_it_insn_type (OUTSIDE_IT_INSN);
   if (inst.operands[0].imm)
     inst.instruction |= 0x8;
 }
@@ -10512,9 +10600,9 @@ do_t_shift (void)
 	}
 
       if (THUMB_SETS_FLAGS (inst.instruction))
-	narrow = (current_it_mask == 0);
+	narrow = !in_it_block ();
       else
-	narrow = (current_it_mask != 0);
+	narrow = in_it_block ();
       if (inst.operands[0].reg > 7 || inst.operands[1].reg > 7)
 	narrow = FALSE;
       if (!inst.operands[2].isreg && shift_kind == SHIFT_ROR)
@@ -10800,7 +10888,7 @@ do_t_tb (void)
   int half;
 
   half = (inst.instruction & 0x10) != 0;
-  constraint (current_it_mask && current_it_mask != 0x10, BAD_BRANCH);
+  set_it_insn_type_last ();
   constraint (inst.operands[0].immisreg,
 	      _("instruction requires register index"));
 
@@ -14437,6 +14525,28 @@ output_inst (const char * str)
   dwarf2_emit_insn (inst.size);
 }
 
+static char*
+output_it_inst (int cond, int mask, char* to)
+{
+  unsigned long instruction = 0xbf00;
+
+  mask &= 0xf;
+  instruction |= mask;
+  instruction |= cond << 4;
+
+  if (to == NULL)
+    {
+      to = frag_more (2);
+#ifdef OBJ_ELF
+      dwarf2_emit_insn (2);
+#endif
+    }
+
+  md_number_to_chars (to, instruction, 2);
+
+  return to;
+}
+
 /* Tag values used in struct asm_opcode's tag field.  */
 enum opcode_tag
 {
@@ -14682,6 +14792,305 @@ opcode_lookup (char **str)
   return 0;
 }
 
+/* This function generates an initial IT instruction, leaving its block
+   virtually open for the new instructions. Eventually,
+   the mask will be updated by current_it_add_mask () each time
+   a new instruction needs to be included in the IT block.
+   Finally, the block is closed with close_automatic_it_block ().
+   The block closure can be requested either from md_assemble (),
+   a tencode (), or due to a label hook.  */
+static void
+new_automatic_it_block (int cond)
+{
+  current_it.state = AUTOMATIC_IT_BLOCK;
+  current_it.mask = 0x18;
+  current_it.cc = cond;
+  current_it.block_length = 1;
+  current_it.insn = output_it_inst(cond, current_it.mask, NULL);
+}
+
+/* Close an automatic IT block.
+   See comments in new_automatic_it_block ().  */
+static void
+close_automatic_it_block (void)
+{
+  current_it.mask = 0x10;
+  current_it.block_length = 0;
+}
+
+/* Update the mask of the current automatically-generated IT
+   instruction. See comments in new_automatic_it_block ().  */
+static void
+current_it_add_mask (int cond)
+{
+#define CLEAR_BIT(value, nbit)  ((value) & ~(1 << (nbit)))
+#define SET_BIT_VALUE(value, bitvalue, nbit)  (CLEAR_BIT(value, nbit) \
+                                              | ((bitvalue) << (nbit)))
+
+  const int resulting_bit = (cond & 1);
+  current_it.mask &= 0xf;
+  current_it.mask = SET_BIT_VALUE (current_it.mask,
+                                   resulting_bit,
+                                  (5 - current_it.block_length));
+  current_it.mask = SET_BIT_VALUE (current_it.mask,
+                                   1,
+                                   ((5 - current_it.block_length) - 1) );
+  output_it_inst (current_it.cc, current_it.mask, current_it.insn);
+
+#undef CLEAR_BIT
+#undef SET_BIT_VALUE
+
+}
+
+/* The IT blocks handling machinery is accessed through the these functions:
+     it_fsm_pre_encode ()               from md_assemble ()
+     set_it_insn_type ()                optional, from the tencode functions
+     set_it_insn_type_last ()           ditto
+     in_it_block ()                     ditto
+     it_fsm_post_encode ()              from md_assemble ()
+     force_automatic_it_block_close ()  from label habdling functions
+
+   Rationale:
+     1) md_assemble () calls it_fsm_pre_encode () before calling tencode (),
+        initializing the IT insn type with a generic initial value depending
+        on the inst.condition.
+     2) During the tencode function, two things may happen:
+        a) The tencode function overrides the IT insn type by
+           calling either set_it_insn_type (type) or set_it_insn_type_last ().
+        b) The tencode function queries the IT block state by
+           calling in_it_block () (i.e. to determine narrow/not narrow mode).
+
+        Both set_it_insn_type and in_it_block run the internal FSM state
+        handling function (handle_it_state), because: a) setting the IT insn
+        type may incur in an invalid state (exiting the function),
+        and b) querying the state requires the FSM to be updated.
+        Specifically we want to avoid creating an IT block for conditional
+        branches, so it_fsm_pre_encode is actually a guess and we can't
+        determine whether an IT block is required until the tencode () routine
+        has decided what type of instruction this actually it.
+        Because of this, if set_it_insn_type and in_it_block have to be used,
+        set_it_insn_type has to be called first.
+
+        set_it_insn_type_last () is a wrapper of set_it_insn_type (type), that
+        determines the insn IT type depending on the inst.cond code.
+        When a tencode () routine encodes an instruction that can be
+        either outside an IT block, or, in the case of being inside, has to be
+        the last one, set_it_insn_type_last () will determine the proper
+        IT instruction type based on the inst.cond code. Otherwise,
+        set_it_insn_type can be called for overriding that logic or
+        for covering other cases.
+
+        Calling handle_it_state () may not transition the IT block state to
+        OUTSIDE_IT_BLOCK immediatelly, since the (current) state could be
+        still queried. Instead, if the FSM determines that the state should
+        be transitioned to OUTSIDE_IT_BLOCK, a flag is marked to be closed
+        after the tencode () function: that's what it_fsm_post_encode () does.
+
+        Since in_it_block () calls the state handling function to get an
+        updated state, an error may occur (due to invalid insns combination).
+        In that case, inst.error is set.
+        Therefore, inst.error has to be checked after the execution of
+        the tencode () routine.
+
+     3) Back in md_assemble(), it_fsm_post_encode () is called to commit
+        any pending state change (if any) that didn't take place in
+        handle_it_state () as explained above.  */
+
+static void
+it_fsm_pre_encode (void)
+{
+  if (inst.cond != COND_ALWAYS)
+    inst.it_insn_type = INSIDE_IT_INSN;
+  else
+    inst.it_insn_type = OUTSIDE_IT_INSN;
+
+  current_it.state_handled = 0;
+}
+
+/* IT state FSM handling function.  */
+static int
+handle_it_state (void)
+{
+  current_it.state_handled = 1;
+
+  switch(current_it.state)
+    {
+      case OUTSIDE_IT_BLOCK:
+        switch (inst.it_insn_type)
+          {
+            case OUTSIDE_IT_INSN:
+              break;
+
+            case INSIDE_IT_INSN:
+            case INSIDE_IT_LAST_INSN:
+              if (do_automatic_it)
+                {
+                  /* Automatically generate the IT instruction.  */
+                  new_automatic_it_block (inst.cond);
+                  if (inst.it_insn_type == INSIDE_IT_LAST_INSN)
+                    close_automatic_it_block ();
+                }
+              else
+                {
+                  inst.error = BAD_OUT_IT;
+                  return FAIL;
+                }
+              break;
+
+            case IF_INSIDE_IT_LAST_INSN:
+            case NEUTRAL_IT_INSN:
+              break;
+
+            case IT_INSN:
+              current_it.state = MANUAL_IT_BLOCK;
+              current_it.block_length = 0;
+              break;
+          }
+      break;
+
+      case AUTOMATIC_IT_BLOCK:
+          /* Three things may happen now:
+              a) We should increment current it block size;
+              b) We should close current it block (closing insn or 4 insns);
+              c) We should close current it block and start a new one (due
+                 to incompatible conditions or
+                 4 insns-length block reached).  */
+
+        switch (inst.it_insn_type)
+          {
+            case OUTSIDE_IT_INSN:
+              /* The closure of the block shall happen immediatelly,
+                 so any in_it_block () call reports the block as closed.  */
+              force_automatic_it_block_close ();
+              break;
+
+            case INSIDE_IT_INSN:
+            case INSIDE_IT_LAST_INSN:
+            case IF_INSIDE_IT_LAST_INSN:
+              current_it.block_length++;
+
+              if (current_it.block_length > 4
+                  || !current_it_compatible (inst.cond))
+                {
+                  force_automatic_it_block_close ();
+                  if (inst.it_insn_type != IF_INSIDE_IT_LAST_INSN)
+                    new_automatic_it_block (inst.cond);
+                }
+              else
+                {
+                  current_it_add_mask (inst.cond);
+                }
+
+              if (current_it.state == AUTOMATIC_IT_BLOCK
+		  && (inst.it_insn_type == INSIDE_IT_LAST_INSN
+		      || inst.it_insn_type == IF_INSIDE_IT_LAST_INSN))
+                close_automatic_it_block ();
+              break;
+
+            case NEUTRAL_IT_INSN:
+              current_it.block_length++;
+
+              if (current_it.block_length > 4)
+                  force_automatic_it_block_close ();
+              else
+                  current_it_add_mask (current_it.cc & 1);
+              break;
+
+            case IT_INSN:
+              close_automatic_it_block ();
+              current_it.state = MANUAL_IT_BLOCK;
+              break;
+          }
+        break;
+
+      case MANUAL_IT_BLOCK:
+        {
+          /* Check conditional suffixes.  */
+          const int cond = current_it.cc ^ ((current_it.mask >> 4) & 1) ^ 1;
+          int is_last;
+          current_it.mask <<= 1;
+          current_it.mask &= 0x1f;
+          is_last = (current_it.mask == 0x10);
+
+          switch (inst.it_insn_type)
+            {
+              case OUTSIDE_IT_INSN:
+                inst.error = BAD_NOT_IT;
+                return FAIL;
+
+              case INSIDE_IT_INSN:
+                if (cond != inst.cond)
+                  {
+                    inst.error = BAD_IT_COND;
+                    return FAIL;
+                  }
+                break;
+
+              case INSIDE_IT_LAST_INSN:
+              case IF_INSIDE_IT_LAST_INSN:
+                if (cond != inst.cond)
+                  {
+                    inst.error = BAD_IT_COND;
+                    return FAIL;
+                  }
+                if (!is_last)
+                  {
+                    inst.error = BAD_BRANCH;
+                    return FAIL;
+                  }
+                break;
+
+              case NEUTRAL_IT_INSN:
+                /* The BKPT instruction is unconditional even in an IT block.  */
+                break;
+
+              case IT_INSN:
+                inst.error = BAD_IT_IT;
+                return FAIL;
+            }
+        }
+      break;
+    }
+
+  return SUCCESS;
+}
+
+static void
+it_fsm_post_encode (void)
+{
+  int is_last;
+
+  if (!current_it.state_handled)
+    handle_it_state ();
+
+  is_last = (current_it.mask == 0x10);
+  if (is_last)
+    {
+      current_it.state = OUTSIDE_IT_BLOCK;
+      current_it.mask = 0;
+    }
+}
+
+static void
+force_automatic_it_block_close (void)
+{
+  if (current_it.state == AUTOMATIC_IT_BLOCK)
+    {
+      close_automatic_it_block ();
+      current_it.state = OUTSIDE_IT_BLOCK;
+      current_it.mask = 0;
+    }
+}
+
+static int
+in_it_block (void)
+{
+  if (!current_it.state_handled)
+    handle_it_state ();
+
+  return current_it.state != OUTSIDE_IT_BLOCK;
+}
+
 void
 md_assemble (char *str)
 {
@@ -14751,36 +15160,19 @@ md_assemble (char *str)
 	    inst.size_req = 2;
 	}
 
-      /* Check conditional suffixes.  */
-      if (current_it_mask)
-	{
-	  int cond;
-	  cond = current_cc ^ ((current_it_mask >> 4) & 1) ^ 1;
-	  current_it_mask <<= 1;
-	  current_it_mask &= 0x1f;
-	  /* The BKPT instruction is unconditional even in an IT block.  */
-	  if (!inst.error
-	      && cond != inst.cond && opcode->tencode != do_t_bkpt)
-	    {
-	      as_bad (_("incorrect condition in IT block"));
-	      return;
-	    }
-	}
-      else if (inst.cond != COND_ALWAYS && opcode->tencode != do_t_branch)
-	{
-	  as_bad (_("thumb conditional instruction not in IT block"));
-	  return;
-	}
-
       mapping_state (MAP_THUMB);
       inst.instruction = opcode->tvalue;
 
       if (!parse_operands (p, opcode->operands))
-	opcode->tencode ();
+        {
+          /* Prepare the it_insn_type for those encodings that don't set
+             it.  */
+          it_fsm_pre_encode ();
+
+          opcode->tencode ();
 
-      /* Clear current_it_mask at the end of an IT block.  */
-      if (current_it_mask == 0x10)
-	current_it_mask = 0;
+          it_fsm_post_encode ();
+        }
 
       if (!(inst.error || inst.relax))
 	{
@@ -14876,6 +15268,8 @@ arm_frob_label (symbolS * sym)
   ARM_SET_INTERWORK (sym, support_interwork);
 #endif
 
+  force_automatic_it_block_close ();
+
   /* Note - do not allow local symbols (.Lxxx) to be labelled
      as Thumb functions.  This is because these labels, whilst
      they exist inside Thumb code, are not the entry points for
@@ -20701,6 +21095,8 @@ struct arm_option_table arm_opts[] =
   {"mthumb", N_("assemble Thumb code"),	   &thumb_mode,	 1, NULL},
   {"mthumb-interwork", N_("support ARM/Thumb interworking"),
    &support_interwork, 1, NULL},
+  {"mauto-it", N_("Enables/disables automatic IT insn insertion mode"),
+   &do_automatic_it, 1, NULL},
   {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
   {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
   {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
Index: gas/doc/c-arm.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-arm.texi,v
retrieving revision 1.56
diff -u -p -r1.56 c-arm.texi
--- gas/doc/c-arm.texi	2 Apr 2009 09:43:56 -0000	1.56
+++ gas/doc/c-arm.texi	8 May 2009 19:21:15 -0000
@@ -227,6 +227,11 @@ instructions; that is, it should behave 
 This option specifies that the output generated by the assembler should
 be marked as supporting interworking.
 
+@cindex @code{-mauto-it} command line option, ARM
+@item -mauto-it
+This option enables the automatic generation of IT instructions for
+conditional instructions not covered by an IT block.
+
 @cindex @code{-mapcs} command line option, ARM
 @item -mapcs @code{[26|32]}
 This option specifies that the output generated by the assembler should
Index: gas/testsuite/gas/arm/arm-it-auto-2.d
===================================================================
RCS file: gas/testsuite/gas/arm/arm-it-auto-2.d
diff -N gas/testsuite/gas/arm/arm-it-auto-2.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/arm-it-auto-2.d	8 May 2009 19:21:15 -0000
@@ -0,0 +1,15 @@
+#name: ARM IT automatic instruction generation 2
+#as: -mthumb -march=armv7a -mauto-it
+#objdump: -d --prefix-addresses --show-raw-insn
+#skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+00000000 <.text> 3a40      	subs	r2, #64
+00000002 <.text\+0x2> bfa1      	itttt	ge
+00000004 <.text\+0x4> e8a0 500a 	stmiage.w	r0!, {r1, r3, ip, lr}
+00000008 <.text\+0x8> e8a0 500a 	stmiage.w	r0!, {r1, r3, ip, lr}
+0000000c <.text\+0xc> e8a0 500a 	stmiage.w	r0!, {r1, r3, ip, lr}
+00000010 <.text\+0x10> e8a0 500a 	stmiage.w	r0!, {r1, r3, ip, lr}
+00000014 <.text\+0x14> dcf4      	bgt.n	00000000 <.text>
Index: gas/testsuite/gas/arm/arm-it-auto-2.s
===================================================================
RCS file: gas/testsuite/gas/arm/arm-it-auto-2.s
diff -N gas/testsuite/gas/arm/arm-it-auto-2.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/arm-it-auto-2.s	8 May 2009 19:21:15 -0000
@@ -0,0 +1,8 @@
+.syntax unified
+2:	subs	r2, r2, #64
+					@ IT generated automatically
+	stmge	r0!, {r1, r3, ip, lr}	@ 64 bytes at a time.
+	stmge	r0!, {r1, r3, ip, lr}
+	stmge	r0!, {r1, r3, ip, lr}
+	stmge	r0!, {r1, r3, ip, lr}
+	bgt	2b
Index: gas/testsuite/gas/arm/arm-it-auto.d
===================================================================
RCS file: gas/testsuite/gas/arm/arm-it-auto.d
diff -N gas/testsuite/gas/arm/arm-it-auto.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/arm-it-auto.d	8 May 2009 19:21:15 -0000
@@ -0,0 +1,81 @@
+#name: ARM IT automatic instruction generation
+#as: -mthumb -march=armv7 -mauto-it
+#objdump: -d --prefix-addresses --show-raw-insn
+#skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+00000000 <main> f000 f821 	bl	00000046 <main\+0x46>
+00000004 <main\+0x4> f000 f80c 	bl	00000020 <main\+0x20>
+00000008 <main\+0x8> f000 f813 	bl	00000032 <main\+0x32>
+0000000c <main\+0xc> d142      	bne.n	00000094 <main\+0x94>
+0000000e <main\+0xe> bf18      	it	ne
+00000010 <main\+0x10> 4487      	addne	pc, r0
+00000012 <main\+0x12> bf18      	it	ne
+00000014 <main\+0x14> e8d0 f001 	tbbne	\[r0, r1\]
+00000018 <main\+0x18> bf08      	it	eq
+0000001a <main\+0x1a> e8d1 f010 	tbheq	\[r1, r0, lsl #1\]
+0000001e <main\+0x1e> bf0a      	itet	eq
+00000020 <main\+0x20> 2002      	moveq	r0, #2
+00000022 <main\+0x22> 2003      	movne	r0, #3
+00000024 <main\+0x24> 2004      	moveq	r0, #4
+00000026 <main\+0x26> bf16      	itet	ne
+00000028 <main\+0x28> 2002      	movne	r0, #2
+0000002a <main\+0x2a> 2003      	moveq	r0, #3
+0000002c <main\+0x2c> 2004      	movne	r0, #4
+0000002e <main\+0x2e> bf18      	it	ne
+00000030 <main\+0x30> 2001      	movne	r0, #1
+00000032 <main\+0x32> bf0c      	ite	eq
+00000034 <main\+0x34> 2002      	moveq	r0, #2
+00000036 <main\+0x36> f8d1 f000 	ldrne.w	pc, \[r1\]
+0000003a <main\+0x3a> bf18      	it	ne
+0000003c <main\+0x3c> f000 f82a 	blne	00000094 <main\+0x94>
+00000040 <main\+0x40> bfb8      	it	lt
+00000042 <main\+0x42> f000 f828 	bllt	00000096 <main\+0x96>
+00000046 <main\+0x46> bf17      	itett	ne
+00000048 <main\+0x48> 202d      	movne	r0, #45
+0000004a <main\+0x4a> 2005      	moveq	r0, #5
+0000004c <main\+0x4c> 2006      	movne	r0, #6
+0000004e <main\+0x4e> 4487      	addne	pc, r0
+00000050 <main\+0x50> bf0d      	iteet	eq
+00000052 <main\+0x52> 2007      	moveq	r0, #7
+00000054 <main\+0x54> 2008      	movne	r0, #8
+00000056 <main\+0x56> 2003      	movne	r0, #3
+00000058 <main\+0x58> 2004      	moveq	r0, #4
+0000005a <main\+0x5a> bf0b      	itete	eq
+0000005c <main\+0x5c> 2005      	moveq	r0, #5
+0000005e <main\+0x5e> 2006      	movne	r0, #6
+00000060 <main\+0x60> 2007      	moveq	r0, #7
+00000062 <main\+0x62> 2008      	movne	r0, #8
+00000064 <main\+0x64> bf0c      	ite	eq
+00000066 <main\+0x66> 2005      	moveq	r0, #5
+00000068 <main\+0x68> 2006      	movne	r0, #6
+0000006a <main\+0x6a> 4687      	mov	pc, r0
+0000006c <main\+0x6c> bf0b      	itete	eq
+0000006e <main\+0x6e> 2007      	moveq	r0, #7
+00000070 <main\+0x70> 2008      	movne	r0, #8
+00000072 <main\+0x72> 2005      	moveq	r0, #5
+00000074 <main\+0x74> 2006      	movne	r0, #6
+00000076 <main\+0x76> 4487      	add	pc, r0
+00000078 <main\+0x78> bf0c      	ite	eq
+0000007a <main\+0x7a> 2007      	moveq	r0, #7
+0000007c <main\+0x7c> 2008      	movne	r0, #8
+0000007e <main\+0x7e> bfcc      	ite	gt
+00000080 <main\+0x80> 2009      	movgt	r0, #9
+00000082 <main\+0x82> 200a      	movle	r0, #10
+00000084 <main\+0x84> bf08      	it	eq
+00000086 <main\+0x86> 200b      	moveq	r0, #11
+00000088 <main\+0x88> bfd8      	it	le
+0000008a <main\+0x8a> 200c      	movle	r0, #12
+0000008c <main\+0x8c> bf18      	it	ne
+0000008e <main\+0x8e> 200d      	movne	r0, #13
+00000090 <main\+0x90> f7ff fffe 	bl	00000000 <f>
+00000094 <f\+0x94> bd10      	pop	{r4, pc}
+00000096 <f\+0x96> f7ff fffe 	bl	00000000 <f>
+0000009a <f\+0x9a> bfb8      	it	lt
+0000009c <f\+0x9c> 2000      	movlt	r0, #0
+0000009e <f\+0x9e> 4348      	muls	r0, r1
+000000a0 <f\+0xa0> bfb8      	it	lt
+000000a2 <f\+0xa2> 2000      	movlt	r0, #0
+000000a4 <f\+0xa4> 4348      	muls	r0, r1
Index: gas/testsuite/gas/arm/arm-it-auto.s
===================================================================
RCS file: gas/testsuite/gas/arm/arm-it-auto.s
diff -N gas/testsuite/gas/arm/arm-it-auto.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/arm-it-auto.s	8 May 2009 19:21:15 -0000
@@ -0,0 +1,110 @@
+	.syntax unified
+	.arch armv7
+	.thumb
+main:
+
+@These branches are to see the labels in the generated file
+	bl .L888
+	bl .L111
+	bl .L777
+
+@No IT block here:
+	bne .L4
+
+@The following groups should be an IT block each.
+@it ne
+	addne.n   pc, r0
+
+@it ne
+	tbbne [r0, r1]
+
+@it eq
+	tbheq [r1, r0]
+
+@The following group should be left as is:
+	itet	eq
+.L111:	moveq	r0, #2
+	movne   r0, #3
+	moveq   r0, #4
+
+@Same, reverted condition:
+	itet	ne
+	movne	r0, #2
+	moveq   r0, #3
+	movne   r0, #4
+
+
+@Two groups shall be generated, due to the label:
+    movne   r0, #1
+@ second group, the label should be at the IT insn
+.L777:	moveq	r0, #2
+	ldrne   pc, [r1]
+
+@it ne
+	blne .L4
+    
+@it lt
+	bllt .L9
+
+@itett ne
+.L888:	movne   r0, #45
+	moveq   r0, #5
+	movne	r0, #6
+	addne.n pc, r0
+
+@iteet eq
+	moveq   r0, #7
+	movne	r0, #8
+	movne   r0, #3
+	moveq	r0, #4
+
+@itete eq
+	moveq   r0, #5
+	movne	r0, #6
+	moveq   r0, #7
+	movne	r0, #8
+
+@ite eq - this group finishes due to the mov.n pc, rn
+	moveq   r0, #5
+	movne	r0, #6
+	mov.n   pc, r0
+
+@itete eq
+	moveq   r0, #7
+	movne	r0, #8
+	moveq   r0, #5
+	movne	r0, #6
+
+@this shall not generate an IT block
+	add.n   pc, r0
+
+@ite eq - testing condition change (eq -> gt)
+	moveq   r0, #7
+	movne	r0, #8
+
+@ite gt (group shall finish due to another condition change)
+	movgt	r0, #9
+	movle	r0, #10
+
+@it eq
+	moveq	r0, #11
+
+@it le
+	movle	r0, #12
+
+@it ne
+	movne	r0, #13
+
+	bl	f
+.L4:
+	pop	{r4, pc}
+.L9:
+	bl	f
+
+@Only the movlt shall be enclosed in the IT block
+movlt r0, #0
+muls r0, r0, r1
+
+@Same here:
+movlt r0, #0
+muls r0, r0, r1
Index: gas/testsuite/gas/arm/thumb2_it.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/thumb2_it.d,v
retrieving revision 1.2
diff -u -p -r1.2 thumb2_it.d
--- gas/testsuite/gas/arm/thumb2_it.d	15 Aug 2005 19:19:55 -0000	1.2
+++ gas/testsuite/gas/arm/thumb2_it.d	8 May 2009 19:21:15 -0000
@@ -1,62 +1,61 @@
 # name: Mixed 16 and 32-bit Thumb conditional instructions
 # as: -march=armv6kt2
 # objdump: -dr --prefix-addresses --show-raw-insn
-# Many of these patterns use "(eq|s)". These should be changed to just "eq"
-# once the disassembler is fixed. Likewise for "(eq)?"
+# Modifications to this file shall be mirrored to thumb2_it_auto.d
 
 .*: +file format .*arm.*
 
 Disassembly of section .text:
 0+000 <[^>]+> bf05      	ittet	eq
-0+002 <[^>]+> 1880      	add(eq|s)	r0, r0, r2
-0+004 <[^>]+> 4440      	add(eq)?	r0, r8
-0+006 <[^>]+> 1888      	add(ne|s)	r0, r1, r2
-0+008 <[^>]+> eb11 0002 	adds(eq)?.w	r0, r1, r2
+0+002 <[^>]+> 1880      	addeq	r0, r0, r2
+0+004 <[^>]+> 4440      	addeq	r0, r8
+0+006 <[^>]+> 1888      	addne	r0, r1, r2
+0+008 <[^>]+> eb11 0002 	addseq.w	r0, r1, r2
 0+00c <[^>]+> 4410      	add	r0, r2
 0+00e <[^>]+> 4440      	add	r0, r8
 0+010 <[^>]+> 1880      	adds	r0, r0, r2
 0+012 <[^>]+> eb10 0008 	adds.w	r0, r0, r8
 0+016 <[^>]+> 1888      	adds	r0, r1, r2
 0+018 <[^>]+> bf0a      	itet	eq
-0+01a <[^>]+> 4310      	orr(eq|s)	r0, r2
-0+01c <[^>]+> ea40 0008 	orr(ne)?.w	r0, r0, r8
-0+020 <[^>]+> ea50 0002 	orrs(eq)?.w	r0, r0, r2
+0+01a <[^>]+> 4310      	orreq	r0, r2
+0+01c <[^>]+> ea40 0008 	orrne.w	r0, r0, r8
+0+020 <[^>]+> ea50 0002 	orrseq.w	r0, r0, r2
 0+024 <[^>]+> ea40 0002 	orr.w	r0, r0, r2
 0+028 <[^>]+> ea40 0008 	orr.w	r0, r0, r8
 0+02c <[^>]+> 4310      	orrs	r0, r2
 0+02e <[^>]+> bf01      	itttt	eq
-0+030 <[^>]+> 4090      	lsl(eq|s)	r0, r2
-0+032 <[^>]+> fa00 f008 	lsl(eq)?.w	r0, r0, r8
-0+036 <[^>]+> fa01 f002 	lsl(eq)?.w	r0, r1, r2
-0+03a <[^>]+> fa10 f002 	lsls(eq)?.w	r0, r0, r2
+0+030 <[^>]+> 4090      	lsleq	r0, r2
+0+032 <[^>]+> fa00 f008 	lsleq.w	r0, r0, r8
+0+036 <[^>]+> fa01 f002 	lsleq.w	r0, r1, r2
+0+03a <[^>]+> fa10 f002 	lslseq.w	r0, r0, r2
 0+03e <[^>]+> bf02      	ittt	eq
-0+040 <[^>]+> 0048      	lsl(eq|s)	r0, r1, #1
-0+042 <[^>]+> ea4f 0048 	mov(eq)?.w	r0, r8, lsl #1
-0+046 <[^>]+> ea5f 0040 	movs(eq)?.w	r0, r0, lsl #1
+0+040 <[^>]+> 0048      	lsleq	r0, r1, #1
+0+042 <[^>]+> ea4f 0048 	moveq.w	r0, r8, lsl #1
+0+046 <[^>]+> ea5f 0040 	movseq.w	r0, r0, lsl #1
 0+04a <[^>]+> fa00 f002 	lsl.w	r0, r0, r2
 0+04e <[^>]+> 4090      	lsls	r0, r2
 0+050 <[^>]+> ea4f 0041 	mov.w	r0, r1, lsl #1
 0+054 <[^>]+> 0048      	lsls	r0, r1, #1
 0+056 <[^>]+> bf01      	itttt	eq
-0+058 <[^>]+> 4288      	cmp(eq)?	r0, r1
-0+05a <[^>]+> 4540      	cmp(eq)?	r0, r8
-0+05c <[^>]+> 4608      	mov(eq)?	r0, r1
-0+05e <[^>]+> ea5f 0001 	movs(eq)?.w	r0, r1
+0+058 <[^>]+> 4288      	cmpeq	r0, r1
+0+05a <[^>]+> 4540      	cmpeq	r0, r8
+0+05c <[^>]+> 4608      	moveq	r0, r1
+0+05e <[^>]+> ea5f 0001 	movseq.w	r0, r1
 0+062 <[^>]+> bf08      	it	eq
-0+064 <[^>]+> 4640      	mov(eq)?	r0, r8
-0+066 <[^>]+> 4608      	mov(eq)?	r0, r1
+0+064 <[^>]+> 4640      	moveq	r0, r8
+0+066 <[^>]+> 4608      	mov	r0, r1
 0+068 <[^>]+> 1c08      	adds	r0, r1, #0
 0+06a <[^>]+> ea5f 0008 	movs.w	r0, r8
 0+06e <[^>]+> bf01      	itttt	eq
-0+070 <[^>]+> 43c8      	mvn(eq|s)	r0, r1
-0+072 <[^>]+> ea6f 0008 	mvn(eq)?.w	r0, r8
-0+076 <[^>]+> ea7f 0001 	mvns(eq)?.w	r0, r1
-0+07a <[^>]+> 42c8      	cmn(eq)?	r0, r1
+0+070 <[^>]+> 43c8      	mvneq	r0, r1
+0+072 <[^>]+> ea6f 0008 	mvneq.w	r0, r8
+0+076 <[^>]+> ea7f 0001 	mvnseq.w	r0, r1
+0+07a <[^>]+> 42c8      	cmneq	r0, r1
 0+07c <[^>]+> ea6f 0001 	mvn.w	r0, r1
 0+080 <[^>]+> 43c8      	mvns	r0, r1
 0+082 <[^>]+> bf02      	ittt	eq
-0+084 <[^>]+> 4248      	neg(eq|s)	r0, r1
-0+086 <[^>]+> f1c8 0000 	rsb(eq)?	r0, r8, #0	; 0x0
-0+08a <[^>]+> f1d1 0000 	rsbs(eq)?	r0, r1, #0	; 0x0
+0+084 <[^>]+> 4248      	negeq	r0, r1
+0+086 <[^>]+> f1c8 0000 	rsbeq	r0, r8, #0	; 0x0
+0+08a <[^>]+> f1d1 0000 	rsbseq	r0, r1, #0	; 0x0
 0+08e <[^>]+> f1c1 0000 	rsb	r0, r1, #0	; 0x0
 0+092 <[^>]+> 4248      	negs	r0, r1
Index: gas/testsuite/gas/arm/thumb2_it_auto.d
===================================================================
RCS file: gas/testsuite/gas/arm/thumb2_it_auto.d
diff -N gas/testsuite/gas/arm/thumb2_it_auto.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/thumb2_it_auto.d	8 May 2009 19:21:15 -0000
@@ -0,0 +1,61 @@
+# name: Mixed 16 and 32-bit Thumb conditional instructions
+# as: -march=armv6kt2 -mauto-it
+# source: thumb2_it.s
+# objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0+000 <[^>]+> bf05      	ittet	eq
+0+002 <[^>]+> 1880      	addeq	r0, r0, r2
+0+004 <[^>]+> 4440      	addeq	r0, r8
+0+006 <[^>]+> 1888      	addne	r0, r1, r2
+0+008 <[^>]+> eb11 0002 	addseq.w	r0, r1, r2
+0+00c <[^>]+> 4410      	add	r0, r2
+0+00e <[^>]+> 4440      	add	r0, r8
+0+010 <[^>]+> 1880      	adds	r0, r0, r2
+0+012 <[^>]+> eb10 0008 	adds.w	r0, r0, r8
+0+016 <[^>]+> 1888      	adds	r0, r1, r2
+0+018 <[^>]+> bf0a      	itet	eq
+0+01a <[^>]+> 4310      	orreq	r0, r2
+0+01c <[^>]+> ea40 0008 	orrne.w	r0, r0, r8
+0+020 <[^>]+> ea50 0002 	orrseq.w	r0, r0, r2
+0+024 <[^>]+> ea40 0002 	orr.w	r0, r0, r2
+0+028 <[^>]+> ea40 0008 	orr.w	r0, r0, r8
+0+02c <[^>]+> 4310      	orrs	r0, r2
+0+02e <[^>]+> bf01      	itttt	eq
+0+030 <[^>]+> 4090      	lsleq	r0, r2
+0+032 <[^>]+> fa00 f008 	lsleq.w	r0, r0, r8
+0+036 <[^>]+> fa01 f002 	lsleq.w	r0, r1, r2
+0+03a <[^>]+> fa10 f002 	lslseq.w	r0, r0, r2
+0+03e <[^>]+> bf02      	ittt	eq
+0+040 <[^>]+> 0048      	lsleq	r0, r1, #1
+0+042 <[^>]+> ea4f 0048 	moveq.w	r0, r8, lsl #1
+0+046 <[^>]+> ea5f 0040 	movseq.w	r0, r0, lsl #1
+0+04a <[^>]+> fa00 f002 	lsl.w	r0, r0, r2
+0+04e <[^>]+> 4090      	lsls	r0, r2
+0+050 <[^>]+> ea4f 0041 	mov.w	r0, r1, lsl #1
+0+054 <[^>]+> 0048      	lsls	r0, r1, #1
+0+056 <[^>]+> bf01      	itttt	eq
+0+058 <[^>]+> 4288      	cmpeq	r0, r1
+0+05a <[^>]+> 4540      	cmpeq	r0, r8
+0+05c <[^>]+> 4608      	moveq	r0, r1
+0+05e <[^>]+> ea5f 0001 	movseq.w	r0, r1
+0+062 <[^>]+> bf08      	it	eq
+0+064 <[^>]+> 4640      	moveq	r0, r8
+0+066 <[^>]+> 4608      	mov	r0, r1
+0+068 <[^>]+> 1c08      	adds	r0, r1, #0
+0+06a <[^>]+> ea5f 0008 	movs.w	r0, r8
+0+06e <[^>]+> bf01      	itttt	eq
+0+070 <[^>]+> 43c8      	mvneq	r0, r1
+0+072 <[^>]+> ea6f 0008 	mvneq.w	r0, r8
+0+076 <[^>]+> ea7f 0001 	mvnseq.w	r0, r1
+0+07a <[^>]+> 42c8      	cmneq	r0, r1
+0+07c <[^>]+> ea6f 0001 	mvn.w	r0, r1
+0+080 <[^>]+> 43c8      	mvns	r0, r1
+0+082 <[^>]+> bf02      	ittt	eq
+0+084 <[^>]+> 4248      	negeq	r0, r1
+0+086 <[^>]+> f1c8 0000 	rsbeq	r0, r8, #0	; 0x0
+0+08a <[^>]+> f1d1 0000 	rsbseq	r0, r1, #0	; 0x0
+0+08e <[^>]+> f1c1 0000 	rsb	r0, r1, #0	; 0x0
+0+092 <[^>]+> 4248      	negs	r0, r1
Index: gas/testsuite/gas/arm/thumb2_it_bad.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/thumb2_it_bad.d,v
retrieving revision 1.3
diff -u -p -r1.3 thumb2_it_bad.d
--- gas/testsuite/gas/arm/thumb2_it_bad.d	20 Apr 2006 12:39:51 -0000	1.3
+++ gas/testsuite/gas/arm/thumb2_it_bad.d	8 May 2009 19:21:15 -0000
@@ -1,3 +1,4 @@
 #name: Invalid IT instructions
 #as:
 #error-output: thumb2_it_bad.l
+# Modifications to this test shall be mirrored to thumb2_it_bad_auto.d.
Index: gas/testsuite/gas/arm/thumb2_it_bad.l
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/thumb2_it_bad.l,v
retrieving revision 1.1
diff -u -p -r1.1 thumb2_it_bad.l
--- gas/testsuite/gas/arm/thumb2_it_bad.l	20 Mar 2006 15:38:02 -0000	1.1
+++ gas/testsuite/gas/arm/thumb2_it_bad.l	8 May 2009 19:21:15 -0000
@@ -9,4 +9,4 @@
 [^:]*:17: Error: instruction not allowed in IT block -- `cpseq #0x10'
 [^:]*:19: Error: instruction is always unconditional -- `bkpteq 0'
 [^:]*:20: Error: instruction not allowed in IT block -- `setendeq le'
-[^:]*:22: Error: instruction not allowed in IT block -- `iteq eq'
+[^:]*:22: Error: IT falling in the range of a previous IT block -- `iteq eq'
Index: gas/testsuite/gas/arm/thumb2_it_bad_auto.d
===================================================================
RCS file: gas/testsuite/gas/arm/thumb2_it_bad_auto.d
diff -N gas/testsuite/gas/arm/thumb2_it_bad_auto.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/thumb2_it_bad_auto.d	8 May 2009 19:21:15 -0000
@@ -0,0 +1,4 @@
+#name: Invalid IT instructions
+#as: -mauto-it
+#source: thumb2_it_bad.s
+#error-output: thumb2_it_bad.l

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