This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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
+

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]