[PATCH v2] gas: Fix support for AL condition in Thumb-2 IT instruction
Brendan Fletcher <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> --- gas/config/tc-arm.c | 18 +++-- gas/testsuite/gas/arm/thumb2_it_always.d | 62 +++++++++++++++++ gas/testsuite/gas/arm/thumb2_it_always.s | 72 ++++++++++++++++++++ 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, 200 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..e18506258db 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,14 @@ do_t_it (void) } inst.instruction |= cond << 4; + + /* If unconditional, negative conditions are illegal. + The mask field of an IT AL with positive conditions + is 0x8, 0x4, 0x2, or 0x1 (and 0x0 is only used for + hint instructions, so not processed in this function). + So, verify the mask has at most one bit set. */ + 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 +22734,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..78274f998e4 --- /dev/null +++ b/gas/testsuite/gas/arm/thumb2_it_always.s @@ -0,0 +1,72 @@ + .text + .thumb + .syntax unified + .thumb_func +foo: + itttt al + add r0, r0, r2 @ 16-bit (3-operand lo regs + IT suppressed flags) + add r0, r0, r8 @ 16-bit (2-operand + no flags, allows hi regs) + add r0, r1, r2 @ 16-bit (IT suppressed flags) + adds r0, r1, r2 @ 32-bit (forced flags) + @ outside IT block + add r0, r0, r2 @ 16-bit (2-operand + no flags) + add r0, r0, r8 @ 16-bit (2-operand + no flags, allows hi regs) + adds r0, r0, r2 @ 16-bit (3-operand lo regs + flags) + adds r0, r0, r8 @ 32-bit (hi reg + flags) + adds r0, r1, r2 @ 16-bit (3-operand lo regs + flags) + + ittt al + orr r0, r0, r2 @ 16-bit (2-operand lo regs + IT suppressed flags) + orr r0, r0, r8 @ 32-bit (hi reg) + orrs r0, r0, r2 @ 32-bit (forced flags) + @ outside IT block + orr r0, r0, r2 @ 32-bit (no flags) + orr r0, r0, r8 @ 32-bit (hi reg) + orrs r0, r0, r2 @ 16-bit (2-operand lo regs + flags) + + itttt al + lsl r0, r0, r2 @ 16-bit (2-operand lo regs + IT suppressed flags) + lsl r0, r0, r8 @ 32-bit (hi reg) + lsl r0, r1, r2 @ 32-bit (3-operand) + lsls r0, r0, r2 @ 32-bit (forced flags) + ittt al + lsl r0, r1, #1 @ 16-bit (lo regs + IT suppressed flags) + lsl r0, r8, #1 @ 32-bit (hi reg) + lsls r0, r0, #1 @ 32-bit (forced flags) + @ outside IT block + lsl r0, r0, r2 @ 32-bit (no flags) + lsls r0, r0, r2 @ 16-bit (2-operand lo regs + flags) + lsl r0, r1, #1 @ 32-bit (no flags) + lsls r0, r1, #1 @ 16-bit (lo regs + flags) + + itttt al + cmp r0, r1 @ 16-bit (CMP always sets flags) + cmp r0, r8 @ 16-bit (CMP always sets flags, allows hi regs) + mov r0, r1 @ 16-bit (no-flag encoding) + movs r0, r1 @ 32-bit (forced flags) + it al + mov r0, r8 @ 16-bit (no-flag encoding, allows hi regs) + @ outside IT block + mov r0, r1 @ 16-bit (no-flag encoding) + movs r0, r1 @ 16-bit (lo regs + flags) + movs r0, r8 @ 32-bit (hi reg + flags) + + itttt al + mvn r0, r1 @ 16-bit (lo regs + IT suppressed flags) + mvn r0, r8 @ 32-bit (hi reg) + mvns r0, r1 @ 32-bit (forced flags) + cmn r0, r1 @ 16-bit (lo regs + CMN always sets flags) + @ outside IT block + mvn r0, r1 @ 32-bit (no flags) + mvns r0, r1 @ 16-bit (lo regs + flags) + + ittt al + neg r0, r1 @ 16-bit (lo regs + IT suppressed flags) + neg r0, r8 @ 32-bit (hi reg) + negs r0, r1 @ 32-bit (forced flags) + @ outside IT block + neg r0, r1 @ 32-bit (no flags) + negs r0, r1 @ 16-bit (lo regs + flags) + + it al + mul.n r0, r4 @ 16-bit (MULS encoding + IT suppressed flags) 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