This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[patch] Thumb2 conditional execution
- From: Paul Brook <paul at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Thu, 4 Aug 2005 16:08:03 +0100
- Subject: [patch] Thumb2 conditional execution
The attached patch implements assembly of thumb2 conditional instructions.
It verifies that instructions following an IT instruction have the correct
conditional suffixes, and other instructions to not have conditional
suffixes. It also ensures 16-bit instructions are used correctly. These do
not set the condition codes when used inside an IT block.
Tested on arm-none-eabi.
Ok?
Paul
2005-08-04 Paul Brook <paul@codesourcery.com>
gas/
* config/tc-arm.c (current_it_mask, current_cc): New variables.
(do_t_add_sub): Use correct encodings inside IT block.
(do_t_arit3c): Ditto.
(do_t_it): Simplify logic. Set current_it_mask and current_cc.
(md_assemble): Verify conditional suffixes agains IT blocks.
gas/testsuite/
* gas/arm/thumb32.s: Use correct conditional suffixes inside IT
blocks.
* gas/arm/thumb2_it.d, gas/arm/thumb2_it.s: New test.
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.216
diff -u -p -r1.216 tc-arm.c
--- gas/config/tc-arm.c 3 Aug 2005 09:50:42 -0000 1.216
+++ gas/config/tc-arm.c 3 Aug 2005 22:12:47 -0000
@@ -535,6 +535,11 @@ typedef struct literal_pool
/* Pointer to a linked list of literal pools. */
literal_pool * list_of_pools = NULL;
+
+/* State variables for IT block handling. */
+static bfd_boolean current_it_mask = 0;
+static int current_cc;
+
/* Pure syntax. */
@@ -5860,6 +5868,8 @@ do_t_add_sub (void)
{
if (!inst.operands[2].isreg)
{
+ /* ??? Convert large immediates to addw/subw. */
+ /* ??? 16-bit adds with small immediates. */
/* For an immediate, we always generate a 32-bit opcode;
section relaxation will shrink it later if possible. */
inst.instruction = THUMB_OP32 (inst.instruction);
@@ -5874,11 +5884,20 @@ do_t_add_sub (void)
/* See if we can do this with a 16-bit instruction. */
if (!inst.operands[2].shifted && inst.size_req != 4)
{
- if (Rd <= 7 && Rn <= 7 && Rn <= 7
- && (inst.instruction == T_MNEM_adds
- || inst.instruction == T_MNEM_subs))
+ bfd_boolean narrow;
+
+ if (inst.instruction == T_MNEM_adds
+ || inst.instruction == T_MNEM_subs)
+ narrow = (current_it_mask == 0);
+ else
+ narrow = (current_it_mask != 0);
+ if (Rd > 7 || Rs > 7 || Rn > 7)
+ narrow = FALSE;
+
+ if (narrow)
{
- inst.instruction = (inst.instruction == T_MNEM_adds
+ inst.instruction = ((inst.instruction == T_MNEM_adds
+ || inst.instruction == T_MNEM_add)
? T_OPCODE_ADD_R3
: T_OPCODE_SUB_R3);
inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
@@ -6015,10 +6034,22 @@ do_t_arit3 (void)
}
else
{
+ bfd_boolean narrow;
+
/* See if we can do this with a 16-bit instruction. */
- if (THUMB_SETS_FLAGS (inst.instruction)
- && !inst.operands[2].shifted
- && inst.size_req != 4
+ if (THUMB_SETS_FLAGS (inst.instruction))
+ narrow = current_it_mask == 0;
+ else
+ narrow = current_it_mask != 0;
+
+ if (Rd > 7 || Rn > 7 || Rs > 7)
+ narrow = FALSE;
+ if (inst.operands[2].shifted)
+ narrow = FALSE;
+ if (inst.size_req == 4)
+ narrow = FALSE;
+
+ if (narrow
&& Rd == Rs)
{
inst.instruction = THUMB_OP16 (inst.instruction);
@@ -6086,10 +6117,22 @@ do_t_arit3c (void)
}
else
{
+ bfd_boolean narrow;
+
/* See if we can do this with a 16-bit instruction. */
- if (THUMB_SETS_FLAGS (inst.instruction)
- && !inst.operands[2].shifted
- && inst.size_req != 4)
+ if (THUMB_SETS_FLAGS (inst.instruction))
+ narrow = current_it_mask == 0;
+ else
+ narrow = current_it_mask != 0;
+
+ if (Rd > 7 || Rn > 7 || Rs > 7)
+ narrow = FALSE;
+ if (inst.operands[2].shifted)
+ narrow = FALSE;
+ if (inst.size_req == 4)
+ narrow = FALSE;
+
+ if (narrow)
{
if (Rd == Rs)
{
@@ -6360,21 +6403,26 @@ static void
do_t_it (void)
{
unsigned int cond = inst.operands[0].imm;
+
+ current_it_mask = (inst.instruction & 0xf) | 0x10;
+ current_cc = cond;
+
+ /* If the condition is a negative condition, invert the mask. */
if ((cond & 0x1) == 0x0)
{
unsigned int mask = inst.instruction & 0x000f;
- inst.instruction &= 0xfff0;
if ((mask & 0x7) == 0)
/* no conversion needed */;
else if ((mask & 0x3) == 0)
- mask = (~(mask & 0x8) & 0x8) | 0x4;
- else if ((mask & 1) == 0)
- mask = (~(mask & 0xC) & 0xC) | 0x2;
+ mask ^= 0x8;
+ else if ((mask & 0x1) == 0)
+ mask ^= 0xC;
else
- mask = (~(mask & 0xE) & 0xE) | 0x1;
+ mask ^= 0xE;
- inst.instruction |= (mask & 0xF);
+ inst.instruction &= 0xfff0;
+ inst.instruction |= mask;
}
inst.instruction |= cond << 4;
@@ -7684,12 +7732,35 @@ md_assemble (char *str)
return;
}
+ /* Check conditional suffixes. */
+ if (current_it_mask)
+ {
+ int cond;
+ cond = current_cc ^ ((current_it_mask >> 4) & 1) ^ 1;
+ if (cond != inst.cond)
+ {
+ as_bad (_("incorrect condition in IT block"));
+ return;
+ }
+ current_it_mask <<= 1;
+ current_it_mask &= 0x1f;
+ }
+ else if (inst.cond != COND_ALWAYS && opcode->tencode != do_t_branch)
+ {
+ as_bad (_("thumb conditional instrunction not in IT block"));
+ return;
+ }
+
mapping_state (MAP_THUMB);
inst.instruction = opcode->tvalue;
if (!parse_operands (p, opcode->operands))
opcode->tencode ();
+ /* Clear current_it_mask at the end of an IT block. */
+ if (current_it_mask == 0x10)
+ current_it_mask = 0;
+
if (!inst.error)
{
assert (inst.instruction < 0xe800 || inst.instruction > 0xffff);
Index: gas/testsuite/gas/arm/thumb32.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/thumb32.s,v
retrieving revision 1.5
diff -u -p -r1.5 thumb32.s
--- gas/testsuite/gas/arm/thumb32.s 29 Jul 2005 17:39:38 -0000 1.5
+++ gas/testsuite/gas/arm/thumb32.s 3 Aug 2005 22:12:47 -0000
@@ -275,62 +275,76 @@ nop_hint:
nop {129}
it:
- .macro itx opc cond n
- \opc \cond
- .rept \n
- nop
- .endr
+ .macro nop1 cond ncond a
+ .ifc \a,t
+ nop\cond
+ .else
+ nop\ncond
+ .endif
+ .endm
+ .macro it0 cond m=
+ it\m \cond
+ nop\cond
+ .endm
+ .macro it1 cond ncond a m=
+ it0 \cond \a\m
+ nop1 \cond \ncond \a
+ .endm
+ .macro it2 cond ncond a b m=
+ it1 \cond \ncond \a \b\m
+ nop1 \cond \ncond \b
+ .endm
+ .macro it3 cond ncond a b c
+ it2 \cond \ncond \a \b \c
+ nop1 \cond \ncond \c
.endm
- itx it eq 1
- itx it ne 1
- itx it cs 1
- itx it hs 1
- itx it cc 1
- itx it ul 1
- itx it lo 1
- itx it mi 1
- itx it pl 1
- itx it vs 1
- itx it vc 1
- itx it hi 1
- itx it ge 1
- itx it lt 1
- itx it gt 1
- itx it le 1
- itx it al 1
-
- itx itt eq 2
- itx ite eq 2
- itx ittt eq 3
- itx itet eq 3
- itx itte eq 3
- itx itee eq 3
- itx itttt eq 4
- itx itett eq 4
- itx ittet eq 4
- itx ittte eq 4
- itx ittee eq 4
- itx itete eq 4
- itx iteet eq 4
- itx iteee eq 4
-
- itx itt ne 2
- itx ite ne 2
- itx ittt ne 3
- itx itet ne 3
- itx itte ne 3
- itx itee ne 3
- itx itttt ne 4
- itx itett ne 4
- itx ittet ne 4
- itx ittte ne 4
- itx ittee ne 4
- itx itete ne 4
- itx iteet ne 4
- itx iteee ne 4
-
- .purgem itx
+ it0 eq
+ it0 ne
+ it0 cs
+ it0 hs
+ it0 cc
+ it0 ul
+ it0 lo
+ it0 mi
+ it0 pl
+ it0 vs
+ it0 vc
+ it0 hi
+ it0 ge
+ it0 lt
+ it0 gt
+ it0 le
+ it0 al
+ it1 eq ne t
+ it1 eq ne e
+ it2 eq ne t t
+ it2 eq ne e t
+ it2 eq ne t e
+ it2 eq ne e e
+ it3 eq ne t t t
+ it3 eq ne e t t
+ it3 eq ne t e t
+ it3 eq ne t t e
+ it3 eq ne t e e
+ it3 eq ne e t e
+ it3 eq ne e e t
+ it3 eq ne e e e
+
+ it1 ne eq t
+ it1 ne eq e
+ it2 ne eq t t
+ it2 ne eq e t
+ it2 ne eq t e
+ it2 ne eq e e
+ it3 ne eq t t t
+ it3 ne eq e t t
+ it3 ne eq t e t
+ it3 ne eq t t e
+ it3 ne eq t e e
+ it3 ne eq e t e
+ it3 ne eq e e t
+ it3 ne eq e e e
ldst:
.macro ls op
Index: gas/testsuite/gas/arm/thumb2_it.d
===================================================================
RCS file: gas/testsuite/gas/arm/thumb2_it.d
diff -N gas/testsuite/gas/arm/thumb2_it.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/thumb2_it.d 4 Aug 2005 14:27:58 -0000
@@ -0,0 +1,24 @@
+# name: Mixed 16 and 32-bit Thumb conditional instructions
+# as: -march=armv6kt2
+# objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0+000 <[^>]+> bf05 ittet eq
+0+002 <[^>]+> 1880 add.* r0, r0, r2
+0+004 <[^>]+> 4440 add.* r0, r8
+0+006 <[^>]+> 1888 add.* r0, r1, r2
+0+008 <[^>]+> eb11 0002 adds.* 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.* r0, r0, r8
+0+016 <[^>]+> 1888 adds.* r0, r1, r2
+0+018 <[^>]+> bf0a itet eq
+0+01a <[^>]+> 4310 orr.* r0, r2
+0+01c <[^>]+> ea40 0008 orr.* r0, r0, r8
+0+020 <[^>]+> ea50 0002 orrs.* r0, r0, r2
+0+024 <[^>]+> ea40 0002 orr.* r0, r0, r2
+0+028 <[^>]+> ea40 0008 orr.* r0, r0, r8
+0+02c <[^>]+> 4310 orrs.* r0, r2
Index: gas/testsuite/gas/arm/thumb2_it.s
===================================================================
RCS file: gas/testsuite/gas/arm/thumb2_it.s
diff -N gas/testsuite/gas/arm/thumb2_it.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/thumb2_it.s 4 Aug 2005 14:27:58 -0000
@@ -0,0 +1,24 @@
+ .text
+ .thumb
+ .syntax unified
+ .thumb_func
+foo:
+ ittet eq
+ addeq r0, r0, r2
+ addeq r0, r0, r8
+ addne r0, r1, r2
+ addseq r0, r1, r2
+ add r0, r0, r2
+ add r0, r0, r8
+ adds r0, r0, r2
+ adds r0, r0, r8
+ adds r0, r1, r2
+
+ itet eq
+ orreq r0, r0, r2
+ orrne r0, r0, r8
+ orrseq r0, r0, r2
+ orr r0, r0, r2
+ orr r0, r0, r8
+ orrs r0, r0, r2
+