This is the mail archive of the binutils@sources.redhat.com 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]

Thumb32 assembler (66/69)


Finally we get to implement some new instructions in the assembler!
This adds the new 16-bit Thumb instructions CZB and IT.  Now you see
what I kept the conditions table around for.

zw

gas:
	* config/tc-arm.c (parse_cond): New operand parser function.
	(OP_COND): New operand parser code.
	(parse_operands): Handle it.
	(do_t_czb, do_t_it): New encoding functions.
	(conds): Remove offsets from values.
	(UT): New notational macro for insns.
	(insns): Add CZB (2 variants) and IT (15 variants).
	(md_apply_fix3): Add support for BFD_RELOC_THUMB_PCREL_BRANCH7.
	(tc_gen_reloc): Add support for BFD_RELOC_THUMB_PCREL_BRANCH7,
	BFD_RELOC_PCREL_BRANCH20, and BFD_RELOC_PCREL_BRANCH25.
opcodes:
	* arm-dis.c (thumb_opcodes): Add CZB (2 variants) and IT (7 variants).
	Use %8-11c, not %T, for conditional branch.
	(print_insn_thumb16): Remove %T support.  Add %b and %<bitfield>c
	support.

===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c	(revision 76)
+++ gas/config/tc-arm.c	(revision 77)
@@ -3400,6 +3400,29 @@
     }
 }
 
+/* Parse a conditional code (from conds[] below).  The value returned is in the
+   range 0 .. 14, or FAIL.  */
+static int
+parse_cond (char **str)
+{
+  char *p, *q;
+  const struct asm_cond *c;
+
+  p = q = *str;
+  while (ISALPHA (*q))
+    q++;
+
+  c = hash_find_n (arm_cond_hsh, p, q - p);
+  if (!c)
+    {
+      inst.error = _("condition required");
+      return FAIL;
+    }
+
+  *str = q;
+  return c->value;
+}
+
 /* Matcher codes for parse_operands.  */
 enum operand_parse_code
 {
@@ -3454,6 +3477,7 @@
   OP_CPSF,	/* CPS flags */
   OP_ENDI,	/* Endianness specifier */
   OP_PSR,	/* CPSR/SPSR mask for msr */
+  OP_COND,	/* conditional code */
 
   OP_RRnpc_I0,	/* ARM register or literal 0 */
   OP_RR_EXr,	/* ARM register or expression with opt. reloc suff. */
@@ -3689,6 +3713,7 @@
 	case OP_ENDI:	 val = parse_endian_specifier (&str);	break;
 	case OP_oROR:	 val = parse_ror (&str);		break;
 	case OP_PSR:	 val = parse_psr (&str);		break;
+	case OP_COND:	 val = parse_cond (&str);		break;
 
 	  /* Register lists */
 	case OP_REGLST:
@@ -3750,6 +3775,7 @@
 	case OP_ENDI:
 	case OP_oROR:
 	case OP_PSR:
+	case OP_COND:
 	case OP_REGLST:
 	case OP_VRSLST:
 	case OP_VRDLST:
@@ -5540,6 +5566,39 @@
 }
 
 static void
+do_t_czb (void)
+{
+  constraint (inst.operands[0].reg > 7, BAD_HIREG);
+  inst.instruction |= inst.operands[0].reg;
+  inst.reloc.pc_rel = 1;
+  inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH7;
+}
+
+static void
+do_t_it (void)
+{
+  unsigned int cond = inst.operands[0].imm;
+  if (cond & 0x1)
+    {
+      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;
+      else
+	mask = (~(mask & 0xE) & 0xE) | 0x1;
+
+      inst.instruction |= (mask & 0xF);
+    }
+
+  inst.instruction |= cond << 4;
+}
+
+static void
 do_t_ldmstm (void)
 {
   /* This really doesn't seem worth it.  */
@@ -6246,25 +6305,24 @@
 #endif
 };
 
-/* Table of all conditional suffixes.  0xF... is for special-case,
-   unconditional instructions.	*/
+/* Table of all conditional suffixes.  0xF is not defined as a condition code.  */
 static const struct asm_cond conds[] =
 {
-  {"eq", 0x00000000},
-  {"ne", 0x10000000},
-  {"cs", 0x20000000}, {"hs", 0x20000000},
-  {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
-  {"mi", 0x40000000},
-  {"pl", 0x50000000},
-  {"vs", 0x60000000},
-  {"vc", 0x70000000},
-  {"hi", 0x80000000},
-  {"ls", 0x90000000},
-  {"ge", 0xa0000000},
-  {"lt", 0xb0000000},
-  {"gt", 0xc0000000},
-  {"le", 0xd0000000},
-  {"al", 0xe0000000}
+  {"eq", 0x0},
+  {"ne", 0x1},
+  {"cs", 0x2}, {"hs", 0x2},
+  {"cc", 0x3}, {"ul", 0x3}, {"lo", 0x3},
+  {"mi", 0x4},
+  {"pl", 0x5},
+  {"vs", 0x6},
+  {"vc", 0x7},
+  {"hi", 0x8},
+  {"ls", 0x9},
+  {"ge", 0xa},
+  {"lt", 0xb},
+  {"gt", 0xc},
+  {"le", 0xd},
+  {"al", 0xe}
 };
 
 /* Table of ARM-format instructions.	*/
@@ -6356,6 +6414,11 @@
 #define UF(mnem,  op, nops, ops, ae) TUF(mnem,  op, 0, nops, ops, ae, 0)
 #define do_0 0
 
+/* unconditional Thumb-only */
+#define UT(mnem,  op, nops, ops, te) \
+  { #mnem, OPS##nops ops, 0, 0x##op, 0, THUMB_VARIANT, 0, do_##te }
+
+
 static const struct asm_opcode insns[] =
 {
 #define ARM_VARIANT ARM_EXT_V1 /* Core ARM Instructions.  */
@@ -6714,6 +6777,24 @@
   CM(ldr,sbt,	03000d0, 2, (RR, ADDR),			    ldsttv4),
   CM(str,ht,	02000b0, 2, (RR, ADDR),			    ldsttv4),
 
+  UT(czbne,     b900,    2, (RR, EXP), t_czb),
+  UT(czbeq,     b100,    2, (RR, EXP), t_czb),
+  UT(it,        bf08,    1, (COND),    t_it),
+  UT(itt,       bf0c,    1, (COND),    t_it),
+  UT(ite,       bf04,    1, (COND),    t_it),
+  UT(ittt,      bf0e,    1, (COND),    t_it),
+  UT(itet,      bf06,    1, (COND),    t_it),
+  UT(itte,      bf0a,    1, (COND),    t_it),
+  UT(itee,      bf02,    1, (COND),    t_it),
+  UT(itttt,     bf0f,    1, (COND),    t_it),
+  UT(itett,     bf07,    1, (COND),    t_it),
+  UT(ittet,     bf0b,    1, (COND),    t_it),
+  UT(iteet,     bf03,    1, (COND),    t_it),
+  UT(ittte,     bf0d,    1, (COND),    t_it),
+  UT(itete,     bf05,    1, (COND),    t_it),
+  UT(ittee,     bf09,    1, (COND),    t_it),
+  UT(iteee,     bf01,    1, (COND),    t_it),
+
 #undef ARM_VARIANT
 #define ARM_VARIANT FPU_FPA_EXT_V1  /* Core FPA instruction set (V1).  */
   CE(wfs,	e200110, 1, (RR),	     rd),
@@ -7542,6 +7623,7 @@
 #undef CM
 #undef UE
 #undef UF
+#undef UT
 #undef OPS0
 #undef OPS1
 #undef OPS2
@@ -8664,6 +8746,32 @@
       }
       break;
 
+    case BFD_RELOC_THUMB_PCREL_BRANCH7: /* CZB */
+      newval = md_chars_to_number (buf, THUMB_SIZE);
+      {
+	addressT diff = ((newval & 0x00f8) >> 2) | (newval & 0x0200) >> 3;
+	fprintf (stderr, "%lx %lx\n", value, diff);
+	value = value + diff;
+	/* CZB can only branch forward.  */
+	if (value & ~0x3f)
+	  as_bad_where (fixP->fx_file, fixP->fx_line,
+			_("branch out of range"));
+	if (seg->use_rela_p && !fixP->fx_done)
+	  {
+#ifdef OBJ_ELF
+	    fixP->fx_offset = value;
+#endif
+	    fixP->fx_addnumber = value;
+	    newval = newval & 0xfd07;
+	  }
+	else
+	  newval = ((newval & 0xfd07)
+		    | ((value & 0x1e) << 2)
+		    | ((value & 0x20) << 3));
+      }
+      md_number_to_chars (buf, newval, THUMB_SIZE);
+      break;
+
     case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch.	*/
       newval = md_chars_to_number (buf, THUMB_SIZE);
       {
@@ -9105,9 +9213,12 @@
     case BFD_RELOC_ARM_PCREL_BRANCH:
     case BFD_RELOC_ARM_PCREL_BLX:
     case BFD_RELOC_RVA:
+    case BFD_RELOC_THUMB_PCREL_BRANCH7:
     case BFD_RELOC_THUMB_PCREL_BRANCH9:
     case BFD_RELOC_THUMB_PCREL_BRANCH12:
+    case BFD_RELOC_THUMB_PCREL_BRANCH20:
     case BFD_RELOC_THUMB_PCREL_BRANCH23:
+    case BFD_RELOC_THUMB_PCREL_BRANCH25:
     case BFD_RELOC_THUMB_PCREL_BLX:
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
===================================================================
Index: opcodes/arm-dis.c
--- opcodes/arm-dis.c	(revision 76)
+++ opcodes/arm-dis.c	(revision 77)
@@ -98,12 +98,12 @@
    %M                   print Thumb register mask
    %N                   print Thumb register mask (with LR)
    %O                   print Thumb register mask (with PC)
-   %T                   print Thumb condition code (always bits 8-11)
    %I                   print cirrus signed shift immediate: bits 0..3|4..6
    %<bitfield>B         print Thumb branch destination (signed displacement)
    %<bitfield>W         print (bitfield * 4) as a decimal
    %<bitfield>H         print (bitfield * 2) as a decimal
    %<bitfield>a         print (bitfield * 4) as a pc-rel offset + decoded symbol
+   %<bitfield>c         print bitfield as a condition code
    %e                   print arm SMI operand (bits 0..7,8..19).
    %s			print Thumb right-shift immediate (6..10; 0 == 32). */
 
@@ -643,6 +643,17 @@
   {ARM_EXT_V6K, 0xbf30, 0xffff, "wfi"},
   {ARM_EXT_V6K, 0xbf40, 0xffff, "sev"},
 
+  /* ARM V6T2 instructions.  */
+  {ARM_EXT_V6T2, 0xb900, 0xfd00, "czbne\t%0-2r, %b"},
+  {ARM_EXT_V6T2, 0xb100, 0xfd00, "czbeq\t%0-2r, %b"},
+  {ARM_EXT_V6T2, 0xbf08, 0xff0f, "it\t%4-7c"},
+  {ARM_EXT_V6T2, 0xbf14, 0xff17, "it%3?te\t%4-7c"},
+  {ARM_EXT_V6T2, 0xbf04, 0xff17, "it%3?et\t%4-7c"},
+  {ARM_EXT_V6T2, 0xbf12, 0xff13, "it%3?te%2?te\t%4-7c"},
+  {ARM_EXT_V6T2, 0xbf02, 0xff13, "it%3?et%2?et\t%4-7c"},
+  {ARM_EXT_V6T2, 0xbf11, 0xff11, "it%3?te%2?te%1?te\t%4-7c"},
+  {ARM_EXT_V6T2, 0xbf01, 0xff11, "it%3?et%2?et%1?et\t%4-7c"},
+
   /* ARM V6.  */
   {ARM_EXT_V6, 0xb660, 0xfff8, "cpsie\t%2'a%1'i%0'f"},
   {ARM_EXT_V6, 0xb670, 0xfff8, "cpsid\t%2'a%1'i%0'f"},
@@ -733,7 +744,7 @@
   /* format 17 */
   {ARM_EXT_V4T, 0xDF00, 0xFF00, "swi\t%0-7d"},
   /* format 16 */
-  {ARM_EXT_V4T, 0xD000, 0xF000, "b%T.n\t%0-7B"},
+  {ARM_EXT_V4T, 0xD000, 0xF000, "b%8-11c.n\t%0-7B"},
   /* format 18 */
   {ARM_EXT_V4T, 0xE000, 0xF800, "b.n\t%0-10B"},
 
@@ -1952,18 +1963,6 @@
 		}
 		break;
 
-	      case 'T':
-		{
-		  long cc = (given >> 8) & 0xf;
-		  /* Must print 0xE as 'al' to distinguish
-		     unconditional B from conditional BAL.  */
-		  if (cc == 0xE)
-		    func (stream, "al");
-		  else
-		    func (stream, "%s", arm_conditional [cc]);
-		}
-		break;
-
 	      case 'N':
 		if (given & (1 << 8))
 		  domasklr = 1;
@@ -2009,6 +2008,16 @@
 		}
 		break;
 
+	      case 'b':
+		/* Print ARM V6T2 CZB address: pc+4+6 bits.  */
+		{
+		  bfd_vma address = (pc + 4
+				     + ((given & 0x00f8) >> 2)
+				     + ((given & 0x0200) >> 3));
+		  info->print_address_func (address, info);
+		}
+		break;
+
 	      case 's':
 		/* Right shift immediate -- bits 6..10; 1-31 print
 		   as themselves, 0 prints as 32.  */
@@ -2083,6 +2092,17 @@
 			      (reg * 2 + pc + 4, info);
 			    break;
 
+			  case 'c':
+			    {
+			      /* Must print 0xE as 'al' to distinguish
+				 unconditional B from conditional BAL.  */
+			      if (reg == 0xE)
+				func (stream, "al");
+			      else
+				func (stream, "%s", arm_conditional [reg]);
+			    }
+			    break;
+
 			  default:
 			    abort ();
 			  }

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