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]

Re: [PATCH] New GAS directives to encode instructions


My apologizes, wrong patch version.

I would fix myself if I would have my source code, but my brainware is not Free Software unfortunately.

ChangeLog is the same.

Daniel.

Daniel Gutson wrote:
Hi,
the attached patch adds a new .inst directives family to generate an instruction from its integer encoding.


The added directives are:
    .inst        (Thumb and ARM)
    .inst.w        (Thumb only)
    .inst.n        (Thumb only).

Please refer to the changes in c-arm.texi for further details.

I tested this with the gas test suite, including the test cases I added.

Please commit it for me since I don't have write access, if accepted.

Thanks!
    Daniel.

-----

2009-07-07 Daniel Gutson <dgutson@codesourcery.com>

       gas/
       * config/tc-arm.c (it_fsm_post_encode): New forward declaration.
       (set_it_insn_type_nonvoid): New macro.
       (emit_thumb32_expr): New function.
       (thumb_insn_size): New function.
       (emit_insn): New function.
       (s_arm_elf_inst): New function.
       (md_pseudo_table): New pseudo-opcode entries added.
       * doc/c-arm.texi: New directive added.
         gas/testsuite/
       * gas/arm/inst-po.d: New testcase.
       * gas/arm/inst-po.s: New file.
       * gas/arm/inst-po-2.d: New testcase.
       * gas/arm/inst-po-2.s: New file.
       * gas/arm/inst-po-2.l: New file.
       * gas/arm/inst-po-3.d: New testcase.
       * gas/arm/inst-po-3.s: New file.
       * gas/arm/inst-po-be.d: New testcase.


-- Daniel Gutson CodeSourcery dgutson@codesourcery.com
? inst_mailine_good.patch
? inst_mainline.patch
? inst_mainline_good.patch
? tcarm.patch
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.392
diff -u -p -r1.392 tc-arm.c
--- gas/config/tc-arm.c	7 Jul 2009 16:15:30 -0000	1.392
+++ gas/config/tc-arm.c	7 Jul 2009 21:59:12 -0000
@@ -766,6 +766,8 @@ static int handle_it_state (void);
 
 static void force_automatic_it_block_close (void);
 
+static void it_fsm_post_encode (void);
+
 #define set_it_insn_type(type)			\
   do						\
     {						\
@@ -775,6 +777,13 @@ static void force_automatic_it_block_clo
     }						\
   while (0)
 
+#define set_it_insn_type_nonvoid(type, failret) \
+  do{                                           \
+    inst.it_insn_type = type;                   \
+    if (handle_it_state () == FAIL)             \
+      return failret;                           \
+  }while(0)
+
 #define set_it_insn_type_last()				\
   do							\
     {							\
@@ -3108,6 +3117,129 @@ s_arm_elf_cons (int nbytes)
   demand_empty_rest_of_line ();
 }
 
+/* Emit an expression containing a 32-bit thumb instruction.
+   Implementation based on put_thumb32_insn.  */
+static void
+emit_thumb32_expr (expressionS *exp)
+{
+  expressionS exp_high = *exp;
+  exp_high.X_add_number = (unsigned long)exp_high.X_add_number
+			  >> 16;
+  emit_expr (&exp_high, (unsigned int) THUMB_SIZE);
+  exp->X_add_number &= 0xffff;
+  emit_expr (exp, (unsigned int) THUMB_SIZE);
+}
+
+/*  Guess the instruction size based on the opcode.  */
+static int
+thumb_insn_size(int opcode)
+{
+  if ((unsigned int)opcode < 0xe800u)
+    return 2;
+  else if ((unsigned int) opcode >= 0xe8000000u)
+    return 4;
+  else
+    return 0;
+}
+
+static int
+emit_insn (expressionS *exp, int nbytes)
+{
+  int size = 0;
+
+  if (exp->X_op == O_constant)
+    {
+      size = nbytes;
+
+      if (size == 0)
+	size = thumb_insn_size (exp->X_add_number);
+
+      if (size != 0)
+	{
+	  if (size == 2 && (unsigned int)exp->X_add_number > 0xffffu)
+	    {
+	      as_bad (_(".inst.n operand too big. "\
+			"Use .inst.w instead"));
+	      size = 0;
+	    }
+	  else
+	    {
+	      if (now_it.state == AUTOMATIC_IT_BLOCK)
+		set_it_insn_type_nonvoid (OUTSIDE_IT_INSN, 0);
+	      else
+		set_it_insn_type_nonvoid (NEUTRAL_IT_INSN, 0);
+
+	      if (thumb_mode && (size > THUMB_SIZE) && !target_big_endian)
+		emit_thumb32_expr (exp);
+	      else
+		emit_expr (exp, (unsigned int) size);
+
+	      it_fsm_post_encode ();
+	    }
+	}
+      else
+	{
+	  as_bad (_("cannot determine Thumb instruction size. "\
+		    "Use .inst.n/.inst.w instead"));
+	}
+    }
+  else
+    {
+      as_bad (_("constant expression required"));
+    }
+
+  return (size != 0);
+}
+
+/* Like s_arm_elf_cons but do not use md_cons_align and
+   set the mapping state to MAP_ARM/MAP_THUMB.  */
+
+static void
+s_arm_elf_inst (int nbytes)
+{
+  if (is_it_end_of_statement ())
+    {
+      demand_empty_rest_of_line ();
+      return;
+    }
+
+  /* Calling mappint_state () here will not change ARM/THUMB, but
+     will ensure not to be in DATA state.  */
+
+  if (thumb_mode)
+    mapping_state (MAP_THUMB);
+  else
+    {
+      if (nbytes != 0)
+	{
+	  as_bad (_("width suffixes are invalid in ARM mode"));
+	  ignore_rest_of_line ();
+	  return;
+	}
+
+      nbytes = 4;
+
+      mapping_state (MAP_ARM);
+    }
+
+  do
+    {
+      expressionS exp;
+
+      expression (&exp);
+
+      if (!emit_insn (&exp, nbytes))
+	{
+	  ignore_rest_of_line ();
+	  return;
+	}
+    }
+  while (*input_line_pointer++ == ',');
+
+  /* Put terminator back into stream.  */
+  input_line_pointer --;
+  demand_empty_rest_of_line ();
+}
 
 /* Parse a .rel31 directive.  */
 
@@ -4067,9 +4199,12 @@ const pseudo_typeS md_pseudo_table[] =
   { "object_arch", s_arm_object_arch,	0 },
   { "fpu",	   s_arm_fpu,	  0 },
 #ifdef OBJ_ELF
-  { "word",	   s_arm_elf_cons, 4 },
-  { "long",	   s_arm_elf_cons, 4 },
-  { "rel31",	   s_arm_rel31,	  0 },
+  { "word",	        s_arm_elf_cons, 4 },
+  { "long",	        s_arm_elf_cons, 4 },
+  { "inst.n",           s_arm_elf_inst, 2 },
+  { "inst.w",           s_arm_elf_inst, 4 },
+  { "inst",             s_arm_elf_inst, 0 },
+  { "rel31",	        s_arm_rel31,	  0 },
   { "fnstart",		s_arm_unwind_fnstart,	0 },
   { "fnend",		s_arm_unwind_fnend,	0 },
   { "cantunwind",	s_arm_unwind_cantunwind, 0 },
Index: gas/doc/c-arm.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-arm.texi,v
retrieving revision 1.57
diff -u -p -r1.57 c-arm.texi
--- gas/doc/c-arm.texi	22 Jun 2009 14:40:27 -0000	1.57
+++ gas/doc/c-arm.texi	7 Jul 2009 21:59:12 -0000
@@ -569,6 +569,15 @@ Must be preceded by a @code{.personality
 directive.
 
 @c IIIIIIIIIIIIIIIIIIIIIIIIII
+
+@cindex @code{.inst} directive, ARM
+@item .inst @var{opcode} [ , @dots{} ]
+@item .inst.n @var{opcode} [ , @dots{} ]
+@item .inst.w @var{opcode} [ , @dots{} ]
+Generates the instruction corresponding to the @var{opcode}.
+@code{.inst.n} and @code{.inst.w} allow the Thumb instruction size to be
+specified explicitly, overriding the normal encoding rules.
+
 @c JJJJJJJJJJJJJJJJJJJJJJJJJJ
 @c KKKKKKKKKKKKKKKKKKKKKKKKKK
 @c LLLLLLLLLLLLLLLLLLLLLLLLLL
Index: gas/testsuite/gas/arm/inst-po-2.d
===================================================================
RCS file: gas/testsuite/gas/arm/inst-po-2.d
diff -N gas/testsuite/gas/arm/inst-po-2.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/inst-po-2.d	7 Jul 2009 21:59:12 -0000
@@ -0,0 +1,4 @@
+#name: .inst pseudo-opcode validations test
+#objdump: -d --prefix-addresses --show-raw-insn
+#skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
+#error-output: inst-po-2.l
Index: gas/testsuite/gas/arm/inst-po-2.l
===================================================================
RCS file: gas/testsuite/gas/arm/inst-po-2.l
diff -N gas/testsuite/gas/arm/inst-po-2.l
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/inst-po-2.l	7 Jul 2009 21:59:12 -0000
@@ -0,0 +1,6 @@
+[^:]*: Assembler messages:
+[^:]*:7: Error: constant expression required
+[^:]*:10: Error: width suffixes are invalid in ARM mode
+[^:]*:11: Error: width suffixes are invalid in ARM mode
+[^:]*:14: Error: cannot determine Thumb instruction size. Use .inst.n/.inst.w instead
+[^:]*:15: Error: .inst.n operand too big. Use .inst.w instead
Index: gas/testsuite/gas/arm/inst-po-2.s
===================================================================
RCS file: gas/testsuite/gas/arm/inst-po-2.s
diff -N gas/testsuite/gas/arm/inst-po-2.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/inst-po-2.s	7 Jul 2009 21:59:12 -0000
@@ -0,0 +1,16 @@
+.syntax unified
+.arch armv7a
+.arm
+.L1:
+
+moveq r1, r9
+.inst .L1
+
+.arm
+.inst.w 1
+.inst.n 1
+
+.thumb
+.inst 0xf000
+.inst.n 1<<31
+
Index: gas/testsuite/gas/arm/inst-po-3.d
===================================================================
RCS file: gas/testsuite/gas/arm/inst-po-3.d
diff -N gas/testsuite/gas/arm/inst-po-3.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/inst-po-3.d	7 Jul 2009 21:59:12 -0000
@@ -0,0 +1,16 @@
+#name: .inst pseudo-opcode with automatic IT blocks test
+#as: -mimplicit-it=always
+#objdump: -d --prefix-addresses --show-raw-insn
+#skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+00000000 <.text> bf08      	it	eq
+00000002 <.text\+0x2> 4649      	moveq	r1, r9
+00000004 <.text\+0x4> 4649      	mov	r1, r9
+00000006 <.text\+0x6> 4649      	mov	r1, r9
+00000008 <.text\+0x8> 00001234 	.word	0x00001234
+0000000c <.text\+0xc> bf0c      	ite	eq
+0000000e <.text\+0xe> 4649      	moveq	r1, r9
+00000010 <.text\+0x10> 4649      	movne	r1, r9
Index: gas/testsuite/gas/arm/inst-po-3.s
===================================================================
RCS file: gas/testsuite/gas/arm/inst-po-3.s
diff -N gas/testsuite/gas/arm/inst-po-3.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/inst-po-3.s	7 Jul 2009 21:59:12 -0000
@@ -0,0 +1,17 @@
+.syntax unified
+.arch armv7a
+.thumb
+
+@ it eq
+@ mov r1, r9
+@ mov r1, r9
+moveq r1, r9
+.inst 0x4649
+.inst 0x4649
+
+.word 0x1234
+
+@ ite eq
+@ moveq r1, r9
+@ movne r1, r9
+.inst 0xbf0b + 1, 0x4649, 0x4649
Index: gas/testsuite/gas/arm/inst-po-be.d
===================================================================
RCS file: gas/testsuite/gas/arm/inst-po-be.d
diff -N gas/testsuite/gas/arm/inst-po-be.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/inst-po-be.d	7 Jul 2009 21:59:12 -0000
@@ -0,0 +1,21 @@
+#name: .inst pseudo-opcode test 1 - big endian version
+#as: -mbig-endian
+#objdump: -d --prefix-addresses --show-raw-insn
+#skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
+#source: inst-po.s
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+00000000 <.text> 11a01009 	movne	r1, r9
+00000004 <.text\+0x4> bf0c      	ite	eq
+00000006 <.text\+0x6> 4649      	moveq	r1, r9
+00000008 <.text\+0x8> 4649      	movne	r1, r9
+0000000a <.text\+0xa> 0000      	.short	0x0000
+0000000c <.text\+0xc> 1234      	.short	0x1234
+0000000e <.text\+0xe> bf0c      	ite	eq
+00000010 <.text\+0x10> 4649      	moveq	r1, r9
+00000012 <.text\+0x12> 4649      	movne	r1, r9
+00000014 <.text\+0x14> 4649      	mov	r1, r9
+00000016 <.text\+0x16> ea4f 0109 	mov.w	r1, r9
+0000001a <.text\+0x1a> ea4f 0109 	mov.w	r1, r9
Index: gas/testsuite/gas/arm/inst-po.d
===================================================================
RCS file: gas/testsuite/gas/arm/inst-po.d
diff -N gas/testsuite/gas/arm/inst-po.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/inst-po.d	7 Jul 2009 21:59:12 -0000
@@ -0,0 +1,19 @@
+#name: .inst pseudo-opcode test 1
+#objdump: -d --prefix-addresses --show-raw-insn
+#skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+00000000 <.text> 11a01009 	movne	r1, r9
+00000004 <.text\+0x4> bf0c      	ite	eq
+00000006 <.text\+0x6> 4649      	moveq	r1, r9
+00000008 <.text\+0x8> 4649      	movne	r1, r9
+0000000a <.text\+0xa> 1234      	.short	0x1234
+0000000c <.text\+0xc> 0000      	.short	0x0000
+0000000e <.text\+0xe> bf0c      	ite	eq
+00000010 <.text\+0x10> 4649      	moveq	r1, r9
+00000012 <.text\+0x12> 4649      	movne	r1, r9
+00000014 <.text\+0x14> 4649      	mov	r1, r9
+00000016 <.text\+0x16> ea4f 0109 	mov.w	r1, r9
+0000001a <.text\+0x1a> ea4f 0109 	mov.w	r1, r9
Index: gas/testsuite/gas/arm/inst-po.s
===================================================================
RCS file: gas/testsuite/gas/arm/inst-po.s
diff -N gas/testsuite/gas/arm/inst-po.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/inst-po.s	7 Jul 2009 21:59:12 -0000
@@ -0,0 +1,27 @@
+.syntax unified
+.arch armv7a
+.arm
+@ movne r1,r9
+.inst 0x11a01009
+
+.thumb
+
+@ ite eq
+@ moveq r1, r9
+@ movne r1, r9
+.inst 0xbf0b + 1, 0x4649
+.inst 0x4649
+
+.word 0x1234
+
+@ ite eq
+@ moveq r1, r9
+@ movne r1, r9
+.inst.n 0xbf0b + 1, 0x4649, 0x4649
+
+.inst.n 0x4649
+
+@ mov.w r1, r9
+@ mov.w r1, r9
+.inst 0xea4f0109
+.inst.w 0xea4f0109

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