This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[patch] More Thumb2 condexec bugs
- From: Paul Brook <paul at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Mon, 8 Aug 2005 20:50:11 +0100
- Subject: [patch] More Thumb2 condexec bugs
The attached patch fixes some mode thumb2 conditional instruction encodings.
Specifically the 16-bit forms do not set the condition codes when inside an
IT block.
Tested on arm-none-eabi.
Ok?
Paul
2005-08-08 Paul Brook <paul@codesourcery.com>
gas/
* config/tc-arm.c (do_t_mov_cmp): Fix encoding of 16-bit conditional
instructions.
(do_t_mvn_tst, do_t_neg, do_t_shift): Ditto.
gas/testsuite/
* gas/arm/thumb2_it.s: Add more instruction variants.
* gas/arm/thumb2_it.d: Ditto.
Index: config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.218
diff -u -p -r1.218 tc-arm.c
--- config/tc-arm.c 5 Aug 2005 12:28:21 -0000 1.218
+++ config/tc-arm.c 5 Aug 2005 17:02:01 -0000
@@ -6699,6 +6699,18 @@ do_t_mov_cmp (void)
{
int r0off = (inst.instruction == T_MNEM_mov
|| inst.instruction == T_MNEM_movs) ? 8 : 16;
+ bfd_boolean narrow;
+ bfd_boolean low_regs;
+
+ low_regs = (inst.operands[0].reg <= 7 && inst.operands[1].reg <= 7);
+ if (current_it_mask)
+ narrow = inst.instruction != T_MNEM_movs;
+ else
+ narrow = inst.instruction != T_MNEM_movs || low_regs;
+ if (inst.size_req == 4
+ || inst.operands[1].shifted)
+ narrow = FALSE;
+
if (!inst.operands[1].isreg)
{
/* For an immediate, we always generate a 32-bit opcode;
@@ -6708,10 +6720,7 @@ do_t_mov_cmp (void)
inst.instruction |= inst.operands[0].reg << r0off;
inst.reloc.type = BFD_RELOC_ARM_T32_IMMEDIATE;
}
- else if (inst.size_req == 4
- || inst.operands[1].shifted
- || (inst.instruction == T_MNEM_movs
- && (inst.operands[0].reg > 7 || inst.operands[1].reg > 7)))
+ else if (!narrow)
{
inst.instruction = THUMB_OP32 (inst.instruction);
inst.instruction |= inst.operands[0].reg << r0off;
@@ -6736,7 +6745,7 @@ do_t_mov_cmp (void)
break;
case T_MNEM_cmp:
- if (inst.operands[0].reg <= 7 && inst.operands[1].reg <= 7)
+ if (low_regs)
{
inst.instruction = T_OPCODE_CMP_LR;
inst.instruction |= inst.operands[0].reg;
@@ -6804,6 +6813,20 @@ do_t_mvn_tst (void)
{
int r0off = (inst.instruction == T_MNEM_mvn
|| inst.instruction == T_MNEM_mvns) ? 8 : 16;
+ bfd_boolean narrow;
+
+ if (inst.size_req == 4
+ || inst.instruction > 0xffff
+ || inst.operands[1].shifted
+ || inst.operands[0].reg > 7 || inst.operands[1].reg > 7)
+ narrow = FALSE;
+ else if (inst.instruction == T_MNEM_cmn)
+ narrow = TRUE;
+ else if (THUMB_SETS_FLAGS (inst.instruction))
+ narrow = (current_it_mask == 0);
+ else
+ narrow = (current_it_mask != 0);
+
if (!inst.operands[1].isreg)
{
/* For an immediate, we always generate a 32-bit opcode;
@@ -6817,12 +6840,7 @@ do_t_mvn_tst (void)
else
{
/* See if we can do this with a 16-bit instruction. */
- if (inst.instruction < 0xffff
- && THUMB_SETS_FLAGS (inst.instruction)
- && !inst.operands[1].shifted
- && inst.operands[0].reg <= 7
- && inst.operands[1].reg <= 7
- && inst.size_req != 4)
+ if (narrow)
{
inst.instruction = THUMB_OP16 (inst.instruction);
inst.instruction |= inst.operands[0].reg;
@@ -6950,9 +6968,18 @@ do_t_neg (void)
{
if (unified_syntax)
{
- if (inst.operands[0].reg > 7 || inst.operands[1].reg > 7
- || !THUMB_SETS_FLAGS (inst.instruction)
- || inst.size_req == 4)
+ bfd_boolean narrow;
+
+ if (THUMB_SETS_FLAGS (inst.instruction))
+ narrow = (current_it_mask == 0);
+ else
+ narrow = (current_it_mask != 0);
+ if (inst.operands[0].reg > 7 || inst.operands[1].reg > 7)
+ narrow = FALSE;
+ if (inst.size_req == 4)
+ narrow = FALSE;
+
+ if (!narrow)
{
inst.instruction = THUMB_OP32 (inst.instruction);
inst.instruction |= inst.operands[0].reg << 8;
@@ -7130,12 +7157,38 @@ do_t_shift (void)
if (unified_syntax)
{
- if (inst.operands[0].reg > 7
- || inst.operands[1].reg > 7
- || !THUMB_SETS_FLAGS (inst.instruction)
- || (!inst.operands[2].isreg && inst.instruction == T_MNEM_rors)
- || (inst.operands[2].isreg && inst.operands[1].reg != inst.operands[0].reg)
- || inst.size_req == 4)
+ bfd_boolean narrow;
+ int shift_kind;
+
+ switch (inst.instruction)
+ {
+ case T_MNEM_asr:
+ case T_MNEM_asrs: shift_kind = SHIFT_ASR; break;
+ case T_MNEM_lsl:
+ case T_MNEM_lsls: shift_kind = SHIFT_LSL; break;
+ case T_MNEM_lsr:
+ case T_MNEM_lsrs: shift_kind = SHIFT_LSR; break;
+ case T_MNEM_ror:
+ case T_MNEM_rors: shift_kind = SHIFT_ROR; break;
+ default: abort ();
+ }
+
+ if (THUMB_SETS_FLAGS (inst.instruction))
+ narrow = (current_it_mask == 0);
+ else
+ narrow = (current_it_mask != 0);
+ if (inst.operands[0].reg > 7 || inst.operands[1].reg > 7)
+ narrow = FALSE;
+ if (!inst.operands[2].isreg && shift_kind == SHIFT_ROR)
+ narrow = FALSE;
+ if (inst.operands[2].isreg
+ && (inst.operands[1].reg != inst.operands[0].reg
+ || inst.operands[2].reg > 7))
+ narrow = FALSE;
+ if (inst.size_req == 4)
+ narrow = FALSE;
+
+ if (!narrow)
{
if (inst.operands[2].isreg)
{
@@ -7147,19 +7200,7 @@ do_t_shift (void)
else
{
inst.operands[1].shifted = 1;
- switch (inst.instruction)
- {
- case T_MNEM_asr:
- case T_MNEM_asrs: inst.operands[1].shift_kind = SHIFT_ASR; break;
- case T_MNEM_lsl:
- case T_MNEM_lsls: inst.operands[1].shift_kind = SHIFT_LSL; break;
- case T_MNEM_lsr:
- case T_MNEM_lsrs: inst.operands[1].shift_kind = SHIFT_LSR; break;
- case T_MNEM_ror:
- case T_MNEM_rors: inst.operands[1].shift_kind = SHIFT_ROR; break;
- default: abort ();
- }
-
+ inst.operands[1].shift_kind = shift_kind;
inst.instruction = THUMB_OP32 (THUMB_SETS_FLAGS (inst.instruction)
? T_MNEM_movs : T_MNEM_mov);
inst.instruction |= inst.operands[0].reg << 8;
@@ -7172,12 +7213,12 @@ do_t_shift (void)
{
if (inst.operands[2].isreg)
{
- switch (inst.instruction)
+ switch (shift_kind)
{
- case T_MNEM_asrs: inst.instruction = T_OPCODE_ASR_R; break;
- case T_MNEM_lsls: inst.instruction = T_OPCODE_LSL_R; break;
- case T_MNEM_lsrs: inst.instruction = T_OPCODE_LSR_R; break;
- case T_MNEM_rors: inst.instruction = T_OPCODE_ROR_R; break;
+ case SHIFT_ASR: inst.instruction = T_OPCODE_ASR_R; break;
+ case SHIFT_LSL: inst.instruction = T_OPCODE_LSL_R; break;
+ case SHIFT_LSR: inst.instruction = T_OPCODE_LSR_R; break;
+ case SHIFT_ROR: inst.instruction = T_OPCODE_ROR_R; break;
default: abort ();
}
@@ -7186,11 +7227,11 @@ do_t_shift (void)
}
else
{
- switch (inst.instruction)
+ switch (shift_kind)
{
- case T_MNEM_asrs: inst.instruction = T_OPCODE_ASR_I; break;
- case T_MNEM_lsls: inst.instruction = T_OPCODE_LSL_I; break;
- case T_MNEM_lsrs: inst.instruction = T_OPCODE_LSR_I; break;
+ case SHIFT_ASR: inst.instruction = T_OPCODE_ASR_I; break;
+ case SHIFT_LSL: inst.instruction = T_OPCODE_LSL_I; break;
+ case SHIFT_LSR: inst.instruction = T_OPCODE_LSR_I; break;
default: abort ();
}
inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
Index: testsuite/gas/arm/thumb2_it.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/thumb2_it.d,v
retrieving revision 1.1
diff -u -p -r1.1 thumb2_it.d
--- testsuite/gas/arm/thumb2_it.d 5 Aug 2005 14:29:38 -0000 1.1
+++ testsuite/gas/arm/thumb2_it.d 5 Aug 2005 17:02:01 -0000
@@ -22,3 +22,39 @@ Disassembly of section .text:
0+024 <[^>]+> ea40 0002 orr.* r0, r0, r2
0+028 <[^>]+> ea40 0008 orr.* r0, r0, r8
0+02c <[^>]+> 4310 orrs.* r0, r2
+0+02e <[^>]+> bf01 itttt eq
+0+030 <[^>]+> 4090 lsl.* r0, r2
+0+032 <[^>]+> fa00 f008 lsl.* r0, r0, r8
+0+036 <[^>]+> fa01 f002 lsl.* r0, r1, r2
+0+03a <[^>]+> fa10 f002 lsls.* r0, r0, r2
+0+03e <[^>]+> bf02 ittt eq
+0+040 <[^>]+> 0048 lsl.* r0, r1, #1
+0+042 <[^>]+> ea4f 0048 mov.* r0, r8, lsl #1
+0+046 <[^>]+> ea5f 0040 movs.* r0, r0, lsl #1
+0+04a <[^>]+> fa00 f002 lsl.* r0, r0, r2
+0+04e <[^>]+> 4090 lsls.* r0, r2
+0+050 <[^>]+> ea4f 0041 mov.* r0, r1, lsl #1
+0+054 <[^>]+> 0048 lsls.* r0, r1, #1
+0+056 <[^>]+> bf01 itttt eq
+0+058 <[^>]+> 4288 cmp.* r0, r1
+0+05a <[^>]+> 4540 cmp.* r0, r8
+0+05c <[^>]+> 4608 mov.* r0, r1
+0+05e <[^>]+> ea5f 0001 mov.* r0, r1
+0+062 <[^>]+> bf08 it eq
+0+064 <[^>]+> 4640 mov.* r0, r8
+0+066 <[^>]+> 4608 mov r0, r1
+0+068 <[^>]+> 1c08 adds r0, r1, #0
+0+06a <[^>]+> ea5f 0008 movs.* r0, r8
+0+06e <[^>]+> bf01 itttt eq
+0+070 <[^>]+> 43c8 mvn.* r0, r1
+0+072 <[^>]+> ea6f 0008 mvn.* r0, r8
+0+076 <[^>]+> ea7f 0001 mvns.* r0, r1
+0+07a <[^>]+> 42c8 cmn.* r0, r1
+0+07c <[^>]+> ea6f 0001 mvn.* r0, r1
+0+080 <[^>]+> 43c8 mvns.* r0, r1
+0+082 <[^>]+> bf02 ittt eq
+0+084 <[^>]+> 4248 neg.* r0, r1
+0+086 <[^>]+> f1c8 0000 rsb.* r0, r8, #0 ; 0x0
+0+08a <[^>]+> f1d1 0000 rsbs.* r0, r1, #0 ; 0x0
+0+08e <[^>]+> f1c1 0000 rsb.* r0, r1, #0 ; 0x0
+0+092 <[^>]+> 4248 negs.* r0, r1
Index: testsuite/gas/arm/thumb2_it.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/thumb2_it.s,v
retrieving revision 1.1
diff -u -p -r1.1 thumb2_it.s
--- testsuite/gas/arm/thumb2_it.s 5 Aug 2005 14:29:38 -0000 1.1
+++ testsuite/gas/arm/thumb2_it.s 5 Aug 2005 17:02:01 -0000
@@ -22,3 +22,43 @@ foo:
orr r0, r0, r8
orrs r0, r0, r2
+ itttt eq
+ lsleq r0, r0, r2
+ lsleq r0, r0, r8
+ lsleq r0, r1, r2
+ lslseq r0, r0, r2
+ ittt eq
+ lsleq r0, r1, #1
+ lsleq r0, r8, #1
+ lslseq r0, r0, #1
+ lsl r0, r0, r2
+ lsls r0, r0, r2
+ lsl r0, r1, #1
+ lsls r0, r1, #1
+
+ itttt eq
+ cmpeq r0, r1
+ cmpeq r0, r8
+ moveq r0, r1
+ movseq r0, r1
+ it eq
+ moveq r0, r8
+ mov r0, r1
+ movs r0, r1
+ movs r0, r8
+
+ itttt eq
+ mvneq r0, r1
+ mvneq r0, r8
+ mvnseq r0, r1
+ cmneq r0, r1
+ mvn r0, r1
+ mvns r0, r1
+
+ ittt eq
+ negeq r0, r1
+ negeq r0, r8
+ negseq r0, r1
+ neg r0, r1
+ negs r0, r1
+