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] Thumb2 conditional execution


The attached patch implements assembly of thumb2 conditional instructions.

It verifies that instructions following an IT instruction have the correct 
conditional suffixes, and other instructions to not have conditional 
suffixes. It also ensures 16-bit instructions are used correctly.  These do 
not set the condition codes when used inside an IT block.

Tested on arm-none-eabi.
Ok?

Paul

2005-08-04  Paul Brook  <paul@codesourcery.com>

gas/
	* config/tc-arm.c (current_it_mask, current_cc): New variables.
	(do_t_add_sub): Use correct encodings inside IT block.
	(do_t_arit3c): Ditto.
	(do_t_it): Simplify logic.  Set current_it_mask and current_cc.
	(md_assemble): Verify conditional suffixes agains IT blocks.
gas/testsuite/
	* gas/arm/thumb32.s: Use correct conditional suffixes inside IT
	blocks.
	* gas/arm/thumb2_it.d, gas/arm/thumb2_it.s: New test.
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.216
diff -u -p -r1.216 tc-arm.c
--- gas/config/tc-arm.c	3 Aug 2005 09:50:42 -0000	1.216
+++ gas/config/tc-arm.c	3 Aug 2005 22:12:47 -0000
@@ -535,6 +535,11 @@ typedef struct literal_pool
 
 /* Pointer to a linked list of literal pools.  */
 literal_pool * list_of_pools = NULL;
+
+/* State variables for IT block handling.  */
+static bfd_boolean current_it_mask = 0;
+static int current_cc;
+
 
 /* Pure syntax.	 */
 
@@ -5860,6 +5868,8 @@ do_t_add_sub (void)
     {
       if (!inst.operands[2].isreg)
 	{
+	  /* ??? Convert large immediates to addw/subw.  */
+	  /* ??? 16-bit adds with small immediates.  */
 	  /* For an immediate, we always generate a 32-bit opcode;
 	     section relaxation will shrink it later if possible.  */
 	  inst.instruction = THUMB_OP32 (inst.instruction);
@@ -5874,11 +5884,20 @@ do_t_add_sub (void)
 	  /* See if we can do this with a 16-bit instruction.  */
 	  if (!inst.operands[2].shifted && inst.size_req != 4)
 	    {
-	      if (Rd <= 7 && Rn <= 7 && Rn <= 7
-		  && (inst.instruction == T_MNEM_adds
-		      || inst.instruction == T_MNEM_subs))
+	      bfd_boolean narrow;
+
+	      if (inst.instruction == T_MNEM_adds
+		  || inst.instruction == T_MNEM_subs)
+		narrow = (current_it_mask == 0);
+	      else
+		narrow = (current_it_mask != 0);
+	      if (Rd > 7 || Rs > 7 || Rn > 7)
+		narrow = FALSE;
+
+	      if (narrow)
 		{
-		  inst.instruction = (inst.instruction == T_MNEM_adds
+		  inst.instruction = ((inst.instruction == T_MNEM_adds
+				       || inst.instruction == T_MNEM_add)
 				      ? T_OPCODE_ADD_R3
 				      : T_OPCODE_SUB_R3);
 		  inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
@@ -6015,10 +6034,22 @@ do_t_arit3 (void)
 	}
       else
 	{
+	  bfd_boolean narrow;
+
 	  /* See if we can do this with a 16-bit instruction.  */
-	  if (THUMB_SETS_FLAGS (inst.instruction)
-	      && !inst.operands[2].shifted
-	      && inst.size_req != 4
+	  if (THUMB_SETS_FLAGS (inst.instruction))
+	    narrow = current_it_mask == 0;
+	  else
+	    narrow = current_it_mask != 0;
+
+	  if (Rd > 7 || Rn > 7 || Rs > 7)
+	    narrow = FALSE;
+	  if (inst.operands[2].shifted)
+	    narrow = FALSE;
+	  if (inst.size_req == 4)
+	    narrow = FALSE;
+
+	  if (narrow
 	      && Rd == Rs)
 	    {
 	      inst.instruction = THUMB_OP16 (inst.instruction);
@@ -6086,10 +6117,22 @@ do_t_arit3c (void)
 	}
       else
 	{
+	  bfd_boolean narrow;
+
 	  /* See if we can do this with a 16-bit instruction.  */
-	  if (THUMB_SETS_FLAGS (inst.instruction)
-	      && !inst.operands[2].shifted
-	      && inst.size_req != 4)
+	  if (THUMB_SETS_FLAGS (inst.instruction))
+	    narrow = current_it_mask == 0;
+	  else
+	    narrow = current_it_mask != 0;
+
+	  if (Rd > 7 || Rn > 7 || Rs > 7)
+	    narrow = FALSE;
+	  if (inst.operands[2].shifted)
+	    narrow = FALSE;
+	  if (inst.size_req == 4)
+	    narrow = FALSE;
+
+	  if (narrow)
 	    {
 	      if (Rd == Rs)
 		{
@@ -6360,21 +6403,26 @@ static void
 do_t_it (void)
 {
   unsigned int cond = inst.operands[0].imm;
+
+  current_it_mask = (inst.instruction & 0xf) | 0x10;
+  current_cc = cond;
+
+  /* If the condition is a negative condition, invert the mask.  */
   if ((cond & 0x1) == 0x0)
     {
       unsigned int mask = inst.instruction & 0x000f;
-      inst.instruction &= 0xfff0;
 
       if ((mask & 0x7) == 0)
 	/* no conversion needed */;
       else if ((mask & 0x3) == 0)
-	mask = (~(mask & 0x8) & 0x8) | 0x4;
-      else if ((mask & 1) == 0)
-	mask = (~(mask & 0xC) & 0xC) | 0x2;
+	mask ^= 0x8;
+      else if ((mask & 0x1) == 0)
+	mask ^= 0xC;
       else
-	mask = (~(mask & 0xE) & 0xE) | 0x1;
+	mask ^= 0xE;
 
-      inst.instruction |= (mask & 0xF);
+      inst.instruction &= 0xfff0;
+      inst.instruction |= mask;
     }
 
   inst.instruction |= cond << 4;
@@ -7684,12 +7732,35 @@ md_assemble (char *str)
 	  return;
 	}
 
+      /* Check conditional suffixes.  */
+      if (current_it_mask)
+	{
+	  int cond;
+	  cond = current_cc ^ ((current_it_mask >> 4) & 1) ^ 1;
+	  if (cond != inst.cond)
+	    {
+	      as_bad (_("incorrect condition in IT block"));
+	      return;
+	    }
+	  current_it_mask <<= 1;
+	  current_it_mask &= 0x1f;
+	}
+      else if (inst.cond != COND_ALWAYS && opcode->tencode != do_t_branch)
+	{
+	  as_bad (_("thumb conditional instrunction not in IT block"));
+	  return;
+	}
+
       mapping_state (MAP_THUMB);
       inst.instruction = opcode->tvalue;
 
       if (!parse_operands (p, opcode->operands))
 	opcode->tencode ();
 
+      /* Clear current_it_mask at the end of an IT block.  */
+      if (current_it_mask == 0x10)
+	current_it_mask = 0;
+
       if (!inst.error)
 	{
 	  assert (inst.instruction < 0xe800 || inst.instruction > 0xffff);
Index: gas/testsuite/gas/arm/thumb32.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/thumb32.s,v
retrieving revision 1.5
diff -u -p -r1.5 thumb32.s
--- gas/testsuite/gas/arm/thumb32.s	29 Jul 2005 17:39:38 -0000	1.5
+++ gas/testsuite/gas/arm/thumb32.s	3 Aug 2005 22:12:47 -0000
@@ -275,62 +275,76 @@ nop_hint:
 	nop {129}
 
 it:
-	.macro	itx opc cond n
-	\opc	\cond
-	.rept	\n
-	nop
-	.endr
+	.macro nop1 cond ncond a
+	.ifc \a,t
+	nop\cond
+	.else
+	nop\ncond
+	.endif
+	.endm
+	.macro it0 cond m=
+	it\m \cond
+	nop\cond
+	.endm
+	.macro it1 cond ncond a m=
+	it0 \cond \a\m
+	nop1 \cond \ncond \a
+	.endm
+	.macro it2 cond ncond a b m=
+	it1 \cond \ncond \a \b\m
+	nop1 \cond \ncond \b
+	.endm
+	.macro it3 cond ncond a b c
+	it2 \cond \ncond \a \b \c
+	nop1 \cond \ncond \c
 	.endm
 
-	itx	it eq 1
-	itx	it ne 1
-	itx	it cs 1
-	itx	it hs 1
-	itx	it cc 1
-	itx	it ul 1
-	itx	it lo 1
-	itx	it mi 1
-	itx	it pl 1
-	itx	it vs 1
-	itx	it vc 1
-	itx	it hi 1
-	itx	it ge 1
-	itx	it lt 1
-	itx	it gt 1
-	itx	it le 1
-	itx	it al 1
-
-	itx	itt eq 2
-	itx	ite eq 2
-	itx	ittt eq 3
-	itx	itet eq 3
-	itx	itte eq 3
-	itx	itee eq 3
-	itx	itttt eq 4
-	itx	itett eq 4
-	itx	ittet eq 4
-	itx	ittte eq 4
-	itx	ittee eq 4
-	itx	itete eq 4
-	itx	iteet eq 4
-	itx	iteee eq 4
-	
-	itx	itt ne 2
-	itx	ite ne 2
-	itx	ittt ne 3
-	itx	itet ne 3
-	itx	itte ne 3
-	itx	itee ne 3
-	itx	itttt ne 4
-	itx	itett ne 4
-	itx	ittet ne 4
-	itx	ittte ne 4
-	itx	ittee ne 4
-	itx	itete ne 4
-	itx	iteet ne 4
-	itx	iteee ne 4
-
-	.purgem itx
+	it0	eq
+	it0	ne
+	it0	cs
+	it0	hs
+	it0	cc
+	it0	ul
+	it0	lo
+	it0	mi
+	it0	pl
+	it0	vs
+	it0	vc
+	it0	hi
+	it0	ge
+	it0	lt
+	it0	gt
+	it0	le
+	it0	al
+	it1 eq ne t
+	it1 eq ne e
+	it2 eq ne t t
+	it2 eq ne e t
+	it2 eq ne t e
+	it2 eq ne e e
+	it3 eq ne t t t
+	it3 eq ne e t t
+	it3 eq ne t e t
+	it3 eq ne t t e
+	it3 eq ne t e e
+	it3 eq ne e t e
+	it3 eq ne e e t
+	it3 eq ne e e e
+
+	it1 ne eq t
+	it1 ne eq e
+	it2 ne eq t t
+	it2 ne eq e t
+	it2 ne eq t e
+	it2 ne eq e e
+	it3 ne eq t t t
+	it3 ne eq e t t
+	it3 ne eq t e t
+	it3 ne eq t t e
+	it3 ne eq t e e
+	it3 ne eq e t e
+	it3 ne eq e e t
+	it3 ne eq e e e
 
 ldst:
 	.macro	ls op
Index: gas/testsuite/gas/arm/thumb2_it.d
===================================================================
RCS file: gas/testsuite/gas/arm/thumb2_it.d
diff -N gas/testsuite/gas/arm/thumb2_it.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/thumb2_it.d	4 Aug 2005 14:27:58 -0000
@@ -0,0 +1,24 @@
+# name: Mixed 16 and 32-bit Thumb conditional instructions
+# as: -march=armv6kt2
+# objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0+000 <[^>]+> bf05      	ittet	eq
+0+002 <[^>]+> 1880      	add.*	r0, r0, r2
+0+004 <[^>]+> 4440      	add.*	r0, r8
+0+006 <[^>]+> 1888      	add.*	r0, r1, r2
+0+008 <[^>]+> eb11 0002 	adds.*	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.*	r0, r0, r8
+0+016 <[^>]+> 1888      	adds.*	r0, r1, r2
+0+018 <[^>]+> bf0a      	itet	eq
+0+01a <[^>]+> 4310      	orr.*	r0, r2
+0+01c <[^>]+> ea40 0008 	orr.*	r0, r0, r8
+0+020 <[^>]+> ea50 0002 	orrs.*	r0, r0, r2
+0+024 <[^>]+> ea40 0002 	orr.*	r0, r0, r2
+0+028 <[^>]+> ea40 0008 	orr.*	r0, r0, r8
+0+02c <[^>]+> 4310      	orrs.*	r0, r2
Index: gas/testsuite/gas/arm/thumb2_it.s
===================================================================
RCS file: gas/testsuite/gas/arm/thumb2_it.s
diff -N gas/testsuite/gas/arm/thumb2_it.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/thumb2_it.s	4 Aug 2005 14:27:58 -0000
@@ -0,0 +1,24 @@
+	.text
+	.thumb
+	.syntax unified
+	.thumb_func
+foo:
+	ittet eq
+	addeq r0, r0, r2
+	addeq r0, r0, r8
+	addne r0, r1, r2
+	addseq r0, r1, r2
+	add r0, r0, r2
+	add r0, r0, r8
+	adds r0, r0, r2
+	adds r0, r0, r8
+	adds r0, r1, r2
+
+	itet eq
+	orreq r0, r0, r2
+	orrne r0, r0, r8
+	orrseq r0, r0, r2
+	orr r0, r0, r2
+	orr r0, r0, r8
+	orrs r0, r0, r2
+

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