This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] New option for automatically generating IT blocks
- From: Daniel Gutson <dgutson at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Thu, 07 May 2009 22:23:08 -0300
- Subject: [PATCH] New option for automatically generating IT blocks
Hi,
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 some test cases I added.
Please note that I don't have write access, so please commit this for me if accepted.
Thanks,
Daniel.
2009-05-07 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/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 01:20:10 -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,58 @@ 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 +6189,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 +8551,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 +8563,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 +8817,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 +8905,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 +9060,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 +9083,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 +9140,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 +9168,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 +9180,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 +9206,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 +9260,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 +9306,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 +9343,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 +9525,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 +9752,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 +9765,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 +9820,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 +9846,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 +9902,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 +10064,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 +10205,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 +10273,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 +10311,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 +10537,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 +10573,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 +10603,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 +10891,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 +14528,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 +14795,304 @@ 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))
+ {
+ close_automatic_it_block ();
+ if (inst.it_insn_type != IF_INSIDE_IT_LAST_INSN)
+ new_automatic_it_block (inst.cond);
+ }
+ else
+ {
+ current_it_add_mask (inst.cond);
+ }
+
+ if (inst.it_insn_type == INSIDE_IT_LAST_INSN
+ || inst.it_insn_type == IF_INSIDE_IT_LAST_INSN)
+ close_automatic_it_block (); /* This can be called twice. */
+ break;
+
+ case NEUTRAL_IT_INSN:
+ current_it.block_length++;
+
+ if (current_it.block_length > 4)
+ close_automatic_it_block ();
+ 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 +15162,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 +15270,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 +21097,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 01:20:10 -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.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 01:20:10 -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 01:20:10 -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 01:20:10 -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 01:20:10 -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 01:20:10 -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 01:20:10 -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 01:20:10 -0000
@@ -0,0 +1,4 @@
+#name: Invalid IT instructions
+#as: -mauto-it
+#source: thumb2_it_bad.s
+#error-output: thumb2_it_bad.l