[PATCH] gas: Fix support for AL condition in Thumb-2 IT instruction

Brendan Fletcher calc84maniac@gmail.com
Thu Jun 4 22:43:12 GMT 2026


Using the AL condition in the IT instruction is designed to allow
encoding unconditional 16-bit instructions which do not affect flags.
GAS currently allows specifying the AL condition, but rejects any
following unconditional instructions because they are not considered
to be part of an IT block.

This change makes unconditional instructions allowed inside a
manually-specified IT AL block. Note, implicit IT AL blocks are still
intentionally never emitted.

This change also emits an error if any Else conditions are specified
in an IT AL, which would be an illegal encoding.

Signed-off-by: Brendan Fletcher <calc84maniac@gmail.com>
---
 gas/config/tc-arm.c                          | 14 +++--
 gas/testsuite/gas/arm/thumb2_it_always.d     | 62 ++++++++++++++++++
 gas/testsuite/gas/arm/thumb2_it_always.s     | 66 ++++++++++++++++++++
 gas/testsuite/gas/arm/thumb2_it_bad_always.d |  3 +
 gas/testsuite/gas/arm/thumb2_it_bad_always.l | 18 ++++++
 gas/testsuite/gas/arm/thumb2_it_bad_always.s | 32 ++++++++++
 6 files changed, 190 insertions(+), 5 deletions(-)
 create mode 100644 gas/testsuite/gas/arm/thumb2_it_always.d
 create mode 100644 gas/testsuite/gas/arm/thumb2_it_always.s
 create mode 100644 gas/testsuite/gas/arm/thumb2_it_bad_always.d
 create mode 100644 gas/testsuite/gas/arm/thumb2_it_bad_always.l
 create mode 100644 gas/testsuite/gas/arm/thumb2_it_bad_always.s

diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 3ff29542411..8e1b8327db9 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -12232,9 +12232,10 @@ static void
 do_t_it (void)
 {
   unsigned int cond = inst.operands[0].imm;
+  unsigned int mask = inst.instruction & 0x000f;
 
   set_pred_insn_type (IT_INSN);
-  now_pred.mask = (inst.instruction & 0xf) | 0x10;
+  now_pred.mask = mask | 0x10;
   now_pred.cc = cond;
   now_pred.warn_deprecated = false;
   now_pred.type = SCALAR_PRED;
@@ -12242,8 +12243,6 @@ do_t_it (void)
   /* If the condition is a negative condition, invert the mask.  */
   if ((cond & 0x1) == 0x0)
     {
-      unsigned int mask = inst.instruction & 0x000f;
-
       if ((mask & 0x7) == 0)
 	{
 	  /* No conversion needed.  */
@@ -12270,6 +12269,10 @@ do_t_it (void)
     }
 
   inst.instruction |= cond << 4;
+
+  /* If unconditional, negative conditions are illegal. */
+  if (cond == COND_ALWAYS && (mask & (mask - 1)) != 0)
+    inst.error = BAD_IT_COND;
 }
 
 /* Helper function used for both push/pop and ldm/stm.  */
@@ -22727,8 +22730,9 @@ now_pred_add_mask (int cond)
 static void
 it_fsm_pre_encode (void)
 {
-  if (inst.cond != COND_ALWAYS)
-    inst.pred_insn_type =  INSIDE_IT_INSN;
+  if (inst.cond != COND_ALWAYS
+      || (now_pred.state == MANUAL_PRED_BLOCK && now_pred.cc == COND_ALWAYS))
+    inst.pred_insn_type = INSIDE_IT_INSN;
   else
     inst.pred_insn_type = OUTSIDE_PRED_INSN;
 
diff --git a/gas/testsuite/gas/arm/thumb2_it_always.d b/gas/testsuite/gas/arm/thumb2_it_always.d
new file mode 100644
index 00000000000..bb220f51e68
--- /dev/null
+++ b/gas/testsuite/gas/arm/thumb2_it_always.d
@@ -0,0 +1,62 @@
+# name: 16-bit Thumb unconditional instructions without flag-setting
+# as: -march=armv6kt2
+# objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0+000 <[^>]+> bfe1      	itttt	al
+0+002 <[^>]+> 1880      	addal	r0, r0, r2
+0+004 <[^>]+> 4440      	addal	r0, r8
+0+006 <[^>]+> 1888      	addal	r0, r1, r2
+0+008 <[^>]+> eb11 0002 	addsal.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 <[^>]+> bfe2      	ittt	al
+0+01a <[^>]+> 4310      	orral	r0, r2
+0+01c <[^>]+> ea40 0008 	orral.w	r0, r0, r8
+0+020 <[^>]+> ea50 0002 	orrsal.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 <[^>]+> bfe1      	itttt	al
+0+030 <[^>]+> 4090      	lslal	r0, r2
+0+032 <[^>]+> fa00 f008 	lslal.w	r0, r0, r8
+0+036 <[^>]+> fa01 f002 	lslal.w	r0, r1, r2
+0+03a <[^>]+> fa10 f002 	lslsal.w	r0, r0, r2
+0+03e <[^>]+> bfe2      	ittt	al
+0+040 <[^>]+> 0048      	lslal	r0, r1, #1
+0+042 <[^>]+> ea4f 0048 	moval.w	r0, r8, lsl #1
+0+046 <[^>]+> ea5f 0040 	movsal.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 <[^>]+> bfe1      	itttt	al
+0+058 <[^>]+> 4288      	cmpal	r0, r1
+0+05a <[^>]+> 4540      	cmpal	r0, r8
+0+05c <[^>]+> 4608      	moval	r0, r1
+0+05e <[^>]+> ea5f 0001 	movsal.w	r0, r1
+0+062 <[^>]+> bfe8      	it	al
+0+064 <[^>]+> 4640      	moval	r0, r8
+0+066 <[^>]+> 4608      	mov	r0, r1
+0+068 <[^>]+> 0008      	movs	r0, r1
+0+06a <[^>]+> ea5f 0008 	movs.w	r0, r8
+0+06e <[^>]+> bfe1      	itttt	al
+0+070 <[^>]+> 43c8      	mvnal	r0, r1
+0+072 <[^>]+> ea6f 0008 	mvnal.w	r0, r8
+0+076 <[^>]+> ea7f 0001 	mvnsal.w	r0, r1
+0+07a <[^>]+> 42c8      	cmnal	r0, r1
+0+07c <[^>]+> ea6f 0001 	mvn.w	r0, r1
+0+080 <[^>]+> 43c8      	mvns	r0, r1
+0+082 <[^>]+> bfe2      	ittt	al
+0+084 <[^>]+> 4248      	negal	r0, r1
+0+086 <[^>]+> f1c8 0000 	rsbal	r0, r8, #0
+0+08a <[^>]+> f1d1 0000 	rsbsal	r0, r1, #0
+0+08e <[^>]+> f1c1 0000 	rsb	r0, r1, #0
+0+092 <[^>]+> 4248      	negs	r0, r1
+0+094 <[^>]+> bfe8      	it	al
+0+096 <[^>]+> 4360      	mulal	r0, r4
diff --git a/gas/testsuite/gas/arm/thumb2_it_always.s b/gas/testsuite/gas/arm/thumb2_it_always.s
new file mode 100644
index 00000000000..ba25c1ac2c3
--- /dev/null
+++ b/gas/testsuite/gas/arm/thumb2_it_always.s
@@ -0,0 +1,66 @@
+	.text
+	.thumb
+	.syntax unified
+	.thumb_func
+foo:
+	itttt al
+	add r0, r0, r2
+	add r0, r0, r8
+	add r0, r1, r2
+	adds r0, r1, r2
+	add r0, r0, r2
+	add r0, r0, r8
+	adds r0, r0, r2
+	adds r0, r0, r8
+	adds r0, r1, r2
+
+	ittt al
+	orr r0, r0, r2
+	orr r0, r0, r8
+	orrs r0, r0, r2
+	orr r0, r0, r2
+	orr r0, r0, r8
+	orrs r0, r0, r2
+
+	itttt al
+	lsl r0, r0, r2
+	lsl r0, r0, r8
+	lsl r0, r1, r2
+	lsls r0, r0, r2
+	ittt al
+	lsl r0, r1, #1
+	lsl r0, r8, #1
+	lsls r0, r0, #1
+	lsl r0, r0, r2
+	lsls r0, r0, r2
+	lsl r0, r1, #1
+	lsls r0, r1, #1
+
+	itttt al
+	cmp r0, r1
+	cmp r0, r8
+	mov r0, r1
+	movs r0, r1
+	it al
+	mov r0, r8
+	mov r0, r1
+	movs r0, r1
+	movs r0, r8
+
+	itttt al
+	mvn r0, r1
+	mvn r0, r8
+	mvns r0, r1
+	cmn r0, r1
+	mvn r0, r1
+	mvns r0, r1
+
+	ittt al
+	neg r0, r1
+	neg r0, r8
+	negs r0, r1
+	neg r0, r1
+	negs r0, r1
+
+	it al
+	mul.n r0, r4
diff --git a/gas/testsuite/gas/arm/thumb2_it_bad_always.d b/gas/testsuite/gas/arm/thumb2_it_bad_always.d
new file mode 100644
index 00000000000..4d412d1b482
--- /dev/null
+++ b/gas/testsuite/gas/arm/thumb2_it_bad_always.d
@@ -0,0 +1,3 @@
+#name: Invalid unconditional IT instructions
+#as:
+#error_output: thumb2_it_bad_always.l
diff --git a/gas/testsuite/gas/arm/thumb2_it_bad_always.l b/gas/testsuite/gas/arm/thumb2_it_bad_always.l
new file mode 100644
index 00000000000..8e0b86cb556
--- /dev/null
+++ b/gas/testsuite/gas/arm/thumb2_it_bad_always.l
@@ -0,0 +1,18 @@
+[^:]*: Assembler messages:
+[^:]*:8: Error: branch must be last instruction in IT block -- `b foo'
+[^:]*:9: Error: branch must be last instruction in IT block -- `bl foo'
+[^:]*:10: Error: branch must be last instruction in IT block -- `blx r0'
+[^:]*:11: Error: instruction not allowed in IT block -- `cbz r0,foo'
+[^:]*:13: Error: branch must be last instruction in IT block -- `bx r0'
+[^:]*:14: Error: branch must be last instruction in IT block -- `tbb \[r0,r1\]'
+[^:]*:15: Error: instruction not allowed in IT block -- `cpsie f'
+[^:]*:17: Error: instruction not allowed in IT block -- `cps #0x10'
+[^:]*:20: Error: instruction not allowed in IT block -- `setend le'
+[^:]*:22: Error: IT falling in the range of a previous IT block -- `ital al'
+[^:]*:25: Error: instruction not allowed in IT block -- `csdb'
+[^:]*:26: Error: instruction not allowed in IT block -- `ssbb'
+[^:]*:27: Error: instruction not allowed in IT block -- `pssbb'
+[^:]*:28: Error: incorrect condition in IT block -- `itet al'
+[^:]*:29: Error: Thumb-2 MUL must not set flags -- `muls r0,r1'
+[^:]*:30: Error: incorrect condition in IT block -- `mul.n r0,r1'
+[^:]*:31: Error: cannot honor width suffix -- `movs.n r0,r1'
diff --git a/gas/testsuite/gas/arm/thumb2_it_bad_always.s b/gas/testsuite/gas/arm/thumb2_it_bad_always.s
new file mode 100644
index 00000000000..356f1ca5ca8
--- /dev/null
+++ b/gas/testsuite/gas/arm/thumb2_it_bad_always.s
@@ -0,0 +1,32 @@
+	.text
+	.syntax unified
+	.arch armv7a
+	.thumb
+	.thumb_func
+thumb2_it_bad:
+	itttt	al
+	b	foo
+	bl	foo
+	blx	r0
+	cbz	r0, foo
+	ittt	al
+	bx	r0
+	tbb	[r0, r1]
+	cpsie	f
+	it	al
+	cps	#0x10
+	itt	al
+	bkpt	0
+	setend	le
+	it	al
+	ital	al
+	nop
+	ittt	al
+	csdb
+	ssbb
+	pssbb
+	itet	al
+	muls	r0, r1
+	mul.n	r0, r1
+	movs.n	r0, r1
+foo:
-- 
2.43.0



More information about the Binutils mailing list