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]

[patch] Assembly of new thumb2 instructions.


The attached patch implements assembly of some new thumb2 instructions.
It also fixes a couple of related disassembler bugs.

Tested with cross to arm-none-eabi.
Ok?

Paul
2005-07-21  Paul Brook  <paul@codesourcery.com>

bfd/
	* reloc.c (BFD_RELOC_ARM_T32_IMM12): Add.
	* bfd-in2.h: Regeenrate.
	* libbfd.h: Regenerate.
gas/
	* config/tc-arm.c (parse_tb): New function.
	(enum operand_parse_code): Add OP_TB.
	(parse_operands): Handle OP_TB.
	(do_t_add_sub_w, do_t_tb): New functions.
	(insns): Add entries for addw, subw, tbb and tbh.
	(md_apply_fix): Handle BFD_RELOC_ARM_T32_IMM12.
gas/testsuite/
	* gas/arm/thumb32.s: Add tests for addw, subw, tbb and tbh.
	* gas/arm/thumb32.d: Ditto.
opcodes/
	* arm-dis.c (thumb32_opc): Fix addressing mode for tbh.
	(print_insn_thumb32): Fix decoding of thumb2 'I' operands.
Index: bfd/bfd-in2.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/bfd-in2.h,v
retrieving revision 1.353
diff -u -p -r1.353 bfd-in2.h
--- bfd/bfd-in2.h	18 Jul 2005 14:13:34 -0000	1.353
+++ bfd/bfd-in2.h	21 Jul 2005 14:51:54 -0000
@@ -2837,6 +2837,7 @@ pc-relative or some form of GOT-indirect
   BFD_RELOC_ARM_IMMEDIATE,
   BFD_RELOC_ARM_ADRL_IMMEDIATE,
   BFD_RELOC_ARM_T32_IMMEDIATE,
+  BFD_RELOC_ARM_T32_IMM12,
   BFD_RELOC_ARM_SHIFT_IMM,
   BFD_RELOC_ARM_SMI,
   BFD_RELOC_ARM_SWI,
Index: bfd/libbfd.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/libbfd.h,v
retrieving revision 1.151
diff -u -p -r1.151 libbfd.h
--- bfd/libbfd.h	18 Jul 2005 14:13:35 -0000	1.151
+++ bfd/libbfd.h	21 Jul 2005 14:51:54 -0000
@@ -1211,6 +1211,7 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_ARM_IMMEDIATE",
   "BFD_RELOC_ARM_ADRL_IMMEDIATE",
   "BFD_RELOC_ARM_T32_IMMEDIATE",
+  "BFD_RELOC_ARM_T32_IMM12",
   "BFD_RELOC_ARM_SHIFT_IMM",
   "BFD_RELOC_ARM_SMI",
   "BFD_RELOC_ARM_SWI",
Index: bfd/reloc.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/reloc.c,v
retrieving revision 1.132
diff -u -p -r1.132 reloc.c
--- bfd/reloc.c	18 Jul 2005 14:13:36 -0000	1.132
+++ bfd/reloc.c	21 Jul 2005 14:50:56 -0000
@@ -2736,6 +2736,8 @@ ENUMX
 ENUMX
   BFD_RELOC_ARM_T32_IMMEDIATE
 ENUMX
+  BFD_RELOC_ARM_T32_IMM12
+ENUMX
   BFD_RELOC_ARM_SHIFT_IMM
 ENUMX
   BFD_RELOC_ARM_SMI
Index: gas/config/tc-arm.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/config/tc-arm.c,v
retrieving revision 1.213
diff -u -p -r1.213 tc-arm.c
--- gas/config/tc-arm.c	21 Jul 2005 13:11:24 -0000	1.213
+++ gas/config/tc-arm.c	21 Jul 2005 20:29:27 -0000
@@ -3491,6 +3491,55 @@ parse_cond (char **str)
   return c->value;
 }
 
+/* Parse the operands of a table branch instruction.  Similar to a memory
+   operand.  */
+static int
+parse_tb (char **str)
+{
+  char * p = *str;
+  int reg;
+
+  if (skip_past_char (&p, '[') == FAIL)
+    return FAIL;
+
+  if ((reg = arm_reg_parse (&p, REG_TYPE_RN)) == FAIL)
+    {
+      inst.error = _(reg_expected_msgs[REG_TYPE_RN]);
+      return FAIL;
+    }
+  inst.operands[0].reg = reg;
+
+  if (skip_past_comma (&p) == FAIL)
+    return FAIL;
+  
+  if ((reg = arm_reg_parse (&p, REG_TYPE_RN)) == FAIL)
+    {
+      inst.error = _(reg_expected_msgs[REG_TYPE_RN]);
+      return FAIL;
+    }
+  inst.operands[0].imm = reg;
+
+  if (skip_past_comma (&p) == SUCCESS)
+    {
+      if (parse_shift (&p, 0, SHIFT_LSL_IMMEDIATE) == FAIL)
+	return FAIL;
+      if (inst.reloc.exp.X_add_number != 1)
+	{
+	  inst.error = _("invalid shift");
+	  return FAIL;
+	}
+      inst.operands[0].shifted = 1;
+    }
+
+  if (skip_past_char (&p, ']') == FAIL)
+    {
+      inst.error = _("']' expected");
+      return FAIL;
+    }
+  *str = p;
+  return SUCCESS;
+}
+
 /* Matcher codes for parse_operands.  */
 enum operand_parse_code
 {
@@ -3546,6 +3595,7 @@ enum operand_parse_code
   OP_ENDI,	/* Endianness specifier */
   OP_PSR,	/* CPSR/SPSR mask for msr */
   OP_COND,	/* conditional code */
+  OP_TB,	/* Table branch.  */
 
   OP_RRnpc_I0,	/* ARM register or literal 0 */
   OP_RR_EXr,	/* ARM register or expression with opt. reloc suff. */
@@ -3787,6 +3837,10 @@ parse_operands (char *str, const unsigne
 	case OP_PSR:	 val = parse_psr (&str);		break;
 	case OP_COND:	 val = parse_cond (&str);		break;
 
+	case OP_TB:
+	  po_misc_or_fail (parse_tb (&str));
+	  break;
+
 	  /* Register lists */
 	case OP_REGLST:
 	  val = parse_reg_list (&str);
@@ -5774,6 +5828,20 @@ static const unsigned int thumb_op32[] =
 
 /* Thumb instruction encoders, in alphabetical order.  */
 
+/* ADDW or SUBW.  */
+static void
+do_t_add_sub_w (void)
+{
+  int Rd, Rn;
+
+  Rd = inst.operands[0].reg;
+  Rn = inst.operands[1].reg;
+
+  constraint (Rd == 15, _("PC not allowed as destination"));
+  inst.instruction |= (Rn << 16) | (Rd << 8);
+  inst.reloc.type = BFD_RELOC_ARM_T32_IMM12;
+}
+
 /* Parse an add or subtract instruction.  We get here with inst.instruction
    equalling any of THUMB_OPCODE_add, adds, sub, or subs.  */
 
@@ -7224,6 +7292,21 @@ do_t_swi (void)
 }
 
 static void
+do_t_tb (void)
+{
+  int half;
+
+  half = (inst.instruction & 0x10) != 0;
+  constraint (inst.operands[0].imm == 15,
+	      _("PC is not a valid index register"));
+  constraint (!half && inst.operands[0].shifted,
+	      _("instruction does not allow shifted index"));
+  constraint (half && !inst.operands[0].shifted,
+	      _("instruction requires shifted index"));
+  inst.instruction |= (inst.operands[0].reg << 16) | inst.operands[0].imm;
+}
+
+static void
 do_t_usat (void)
 {
   inst.instruction |= inst.operands[0].reg << 8;
@@ -8464,6 +8547,15 @@ static const struct asm_opcode insns[] =
  TUE(ittee,     0, bf09, 1, (COND),    it, t_it),
  TUE(iteee,     0, bf01, 1, (COND),    it, t_it),
 
+ /* Thumb2 only instructions.  */
+#undef ARM_VARIANT
+#define ARM_VARIANT 0
+
+ TCE(addw,	0, f2000000, 3, (RR, RR, EXPi), 0, t_add_sub_w),
+ TCE(subw,	0, f2a00000, 3, (RR, RR, EXPi), 0, t_add_sub_w),
+ TCE(tbb,       0, e8d0f000, 1, (TB), 0, t_tb),
+ TCE(tbh,       0, e8d0f010, 1, (TB), 0, t_tb),
+
 #undef ARM_VARIANT
 #define ARM_VARIANT FPU_FPA_EXT_V1  /* Core FPA instruction set (V1).  */
   CE(wfs,	e200110, 1, (RR),	     rd),
@@ -10439,6 +10531,7 @@ md_apply_fix (fixS *	fixP,
       break;
 
     case BFD_RELOC_ARM_T32_IMMEDIATE:
+    case BFD_RELOC_ARM_T32_IMM12:
       /* We claim that this fixup has been processed here,
 	 even if in fact we generate an error because we do
 	 not have a reloc for it, so tc_gen_reloc will reject it.  */
@@ -10457,7 +10550,15 @@ md_apply_fix (fixS *	fixP,
       newval <<= 16;
       newval |= md_chars_to_number (buf+2, THUMB_SIZE);
 
-      newimm = encode_thumb32_immediate (value);
+      if (fixP->fx_r_type == BFD_RELOC_ARM_T32_IMM12)
+	{
+	  if (value > 0xfff)
+	    newimm = (unsigned int) FAIL;
+	  else
+	    newimm = value;
+	}
+      else
+	newimm = encode_thumb32_immediate (value);
 
       /* FUTURE: Implement analogue of negate_data_op for T32.  */
       if (newimm == (unsigned int)FAIL)
Index: gas/testsuite/gas/arm/thumb32.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/testsuite/gas/arm/thumb32.d,v
retrieving revision 1.7
diff -u -p -r1.7 thumb32.d
--- gas/testsuite/gas/arm/thumb32.d	21 Jul 2005 13:11:28 -0000	1.7
+++ gas/testsuite/gas/arm/thumb32.d	21 Jul 2005 18:45:48 -0000
@@ -1011,3 +1011,11 @@ Disassembly of section .text:
 0+cf4 <[^>]+> f8df 1155 	ldr\.w	r1, \[pc, #341\]	; 0+e4d <[^>]+>
 0+cf8 <[^>]+> f85f 12aa 	ldr\.w	r1, \[pc, #-682\]	; 0+a52 <[^>]+>
 0+cfc <[^>]+> f85f 1155 	ldr\.w	r1, \[pc, #-341\]	; 0+bab <[^>]+>
+0+d00 <[^>]+> f200 0900 	addw	r9, r0, #0	; 0x0
+0+d04 <[^>]+> f60f 76ff 	addw	r6, pc, #4095	; 0xfff
+0+d08 <[^>]+> f6a9 2685 	subw	r6, r9, #2693	; 0xa85
+0+d0c <[^>]+> f2a9 567a 	subw	r6, r9, #1402	; 0x57a
+0+d10 <[^>]+> e8df f006 	tbb	\[pc, r6\]
+0+d14 <[^>]+> e8d0 f009 	tbb	\[r0, r9\]
+0+d18 <[^>]+> e8df f017 	tbh	\[pc, r7, lsl #1\]
+0+d1c <[^>]+> e8d0 f018 	tbh	\[r0, r8, lsl #1\]
Index: gas/testsuite/gas/arm/thumb32.s
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/testsuite/gas/arm/thumb32.s,v
retrieving revision 1.3
diff -u -p -r1.3 thumb32.s
--- gas/testsuite/gas/arm/thumb32.s	21 Jul 2005 13:11:28 -0000	1.3
+++ gas/testsuite/gas/arm/thumb32.s	21 Jul 2005 18:41:01 -0000
@@ -745,3 +745,11 @@ xta:	
 	ldpcimm	ldrh
 	ldpcimm	ldrsh
 	ldpcimm	ldr
+	addw r9, r0, #0
+	addw r6, pc, #0xfff
+	subw r6, r9, #0xa85
+	subw r6, r9, #0x57a
+	tbb [pc, r6]
+	tbb [r0, r9]
+	tbh [pc, r7, lsl #1]
+	tbh [r0, r8, lsl #1]
Index: opcodes/arm-dis.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/opcodes/arm-dis.c,v
retrieving revision 1.50
diff -u -p -r1.50 arm-dis.c
--- opcodes/arm-dis.c	7 Jul 2005 19:27:48 -0000	1.50
+++ opcodes/arm-dis.c	21 Jul 2005 18:45:26 -0000
@@ -839,7 +839,7 @@ static const struct opcode32 thumb32_opc
   {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff0ff, "mrs\t%8-11r, %20?CSPSR"},
   {ARM_EXT_V6T2, 0xf3af8100, 0xffffffe0, "cps\t#%0-4d"},
   {ARM_EXT_V6T2, 0xe8d0f000, 0xfff0fff0, "tbb\t[%16-19r, %0-3r]"},
-  {ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh\t[%16-19r, %0-3r]"},
+  {ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh\t[%16-19r, %0-3r, lsl #1]"},
   {ARM_EXT_V6T2, 0xf3af8500, 0xffffff00, "cpsie\t%7'a%6'i%5'f, #%0-4d"},
   {ARM_EXT_V6T2, 0xf3af8700, 0xffffff00, "cpsid\t%7'a%6'i%5'f, #%0-4d"},
   {ARM_EXT_V6T2, 0xf3de8f00, 0xffffff00, "subs\tpc, lr, #%0-7d"},
@@ -2132,7 +2132,7 @@ print_insn_thumb32 (bfd_vma pc, struct d
 		  unsigned int imm12 = 0;
 		  imm12 |= (given & 0x000000ffu);
 		  imm12 |= (given & 0x00007000u) >> 4;
-		  imm12 |= (given & 0x04000000u) >> 12;
+		  imm12 |= (given & 0x04000000u) >> 15;
 		  func (stream, "#%u\t; 0x%x", imm12, imm12);
 		}
 		break;

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