[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