[PATCH] arm: .inst support for arm-wince-pe

Ezra.Sitorus@arm.com Ezra.Sitorus@arm.com
Fri Apr 4 17:46:57 GMT 2025


From: Ezra Sitorus <ezra.sitorus@arm.com>

The .inst directive was only supported for ELF target. In
gas/config/tc-arm.c, this was gated by #ifdef OBJ_ELF. However, there is
no reason why this shouldn't be supported for COFF/PE, such as
arm-wince-pe[1]. For more information about the directive, see [2].

This patch allows the .inst pseudo-op to be supported for non-ELF targets, such
as arm-wince-pe. An example file is /gas/arm/mve-vmla.d - the original file had
is_elf_format, but this has been removed to highlight the change.

Furthermore, a new test - inst-pe.s/d - has been added to show how .inst
now works on arm-wince-pe. inst-po.s/d couldn't be used because coff/pe
doesn't use mapping symbols, which causes errors in deciphering whether
or not an instruction is in arm mode or thumb mode.

[1] https://sourceware.org/pipermail/binutils/2024-April/133823.html
[2] https://sourceware.org/binutils/docs/as/ARM-Directives.html

Tested on arm-none-eabi and arm-wince-pe.
---
 gas/config/tc-arm.c              | 220 +++++++++++++++----------------
 gas/testsuite/gas/arm/inst-pe.d  |  18 +++
 gas/testsuite/gas/arm/inst-pe.s  |  27 ++++
 gas/testsuite/gas/arm/mve-vmla.d |   1 -
 4 files changed, 155 insertions(+), 111 deletions(-)
 create mode 100644 gas/testsuite/gas/arm/inst-pe.d
 create mode 100644 gas/testsuite/gas/arm/inst-pe.s

diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index add9b77ab17..3a920b98aa0 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -3789,112 +3789,6 @@ s_ltorg (int ignored ATTRIBUTE_UNUSED)
   pool->symbol = NULL;
 }
 
-#ifdef OBJ_ELF
-/* Forward declarations for functions below, in the MD interface
-   section.  */
-static void fix_new_arm (fragS *, int, short, expressionS *, int, int);
-static valueT create_unwind_entry (int);
-static void start_unwind_section (const segT, int);
-static void add_unwind_opcode (valueT, int);
-static void flush_pending_unwind (void);
-
-/* Directives: Data.  */
-
-static void
-s_arm_elf_cons (int nbytes)
-{
-  expressionS exp;
-
-#ifdef md_flush_pending_output
-  md_flush_pending_output ();
-#endif
-
-  if (is_it_end_of_statement ())
-    {
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-#ifdef md_cons_align
-  md_cons_align (nbytes);
-#endif
-
-  mapping_state (MAP_DATA);
-  do
-    {
-      int reloc;
-      char *base = input_line_pointer;
-
-      expression (& exp);
-
-      if (exp.X_op != O_symbol)
-	emit_expr (&exp, (unsigned int) nbytes);
-      else
-	{
-	  char *before_reloc = input_line_pointer;
-	  reloc = parse_reloc (&input_line_pointer);
-	  if (reloc == -1)
-	    {
-	      as_bad (_("unrecognized relocation suffix"));
-	      ignore_rest_of_line ();
-	      return;
-	    }
-	  else if (reloc == BFD_RELOC_UNUSED)
-	    emit_expr (&exp, (unsigned int) nbytes);
-	  else
-	    {
-	      reloc_howto_type *howto = (reloc_howto_type *)
-		  bfd_reloc_type_lookup (stdoutput,
-					 (bfd_reloc_code_real_type) reloc);
-	      int size = bfd_get_reloc_size (howto);
-
-	      if (reloc == BFD_RELOC_ARM_PLT32)
-		{
-		  as_bad (_("(plt) is only valid on branch targets"));
-		  reloc = BFD_RELOC_UNUSED;
-		  size = 0;
-		}
-
-	      if (size > nbytes)
-		as_bad (ngettext ("%s relocations do not fit in %d byte",
-				  "%s relocations do not fit in %d bytes",
-				  nbytes),
-			howto->name, nbytes);
-	      else
-		{
-		  /* We've parsed an expression stopping at O_symbol.
-		     But there may be more expression left now that we
-		     have parsed the relocation marker.  Parse it again.
-		     XXX Surely there is a cleaner way to do this.  */
-		  char *p = input_line_pointer;
-		  int offset;
-		  char *save_buf = XNEWVEC (char, input_line_pointer - base);
-
-		  memcpy (save_buf, base, input_line_pointer - base);
-		  memmove (base + (input_line_pointer - before_reloc),
-			   base, before_reloc - base);
-
-		  input_line_pointer = base + (input_line_pointer-before_reloc);
-		  expression (&exp);
-		  memcpy (base, save_buf, p - base);
-
-		  offset = nbytes - size;
-		  p = frag_more (nbytes);
-		  memset (p, 0, nbytes);
-		  fix_new_exp (frag_now, p - frag_now->fr_literal + offset,
-			       size, &exp, 0, (enum bfd_reloc_code_real) reloc);
-		  free (save_buf);
-		}
-	    }
-	}
-    }
-  while (*input_line_pointer++ == ',');
-
-  /* Put terminator back into stream.  */
-  input_line_pointer --;
-  demand_empty_rest_of_line ();
-}
-
 /* Emit an expression containing a 32-bit thumb instruction.
    Implementation based on put_thumb32_insn.  */
 
@@ -3971,7 +3865,7 @@ emit_insn (expressionS *exp, int nbytes)
    set the mapping state to MAP_ARM/MAP_THUMB.  */
 
 static void
-s_arm_elf_inst (int nbytes)
+s_arm_inst (int nbytes)
 {
   if (is_it_end_of_statement ())
     {
@@ -4019,6 +3913,112 @@ s_arm_elf_inst (int nbytes)
   demand_empty_rest_of_line ();
 }
 
+#ifdef OBJ_ELF
+/* Forward declarations for functions below, in the MD interface
+   section.  */
+static void fix_new_arm (fragS *, int, short, expressionS *, int, int);
+static valueT create_unwind_entry (int);
+static void start_unwind_section (const segT, int);
+static void add_unwind_opcode (valueT, int);
+static void flush_pending_unwind (void);
+
+/* Directives: Data.  */
+
+static void
+s_arm_elf_cons (int nbytes)
+{
+  expressionS exp;
+
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
+
+  if (is_it_end_of_statement ())
+    {
+      demand_empty_rest_of_line ();
+      return;
+    }
+
+#ifdef md_cons_align
+  md_cons_align (nbytes);
+#endif
+
+  mapping_state (MAP_DATA);
+  do
+    {
+      int reloc;
+      char *base = input_line_pointer;
+
+      expression (& exp);
+
+      if (exp.X_op != O_symbol)
+	emit_expr (&exp, (unsigned int) nbytes);
+      else
+	{
+	  char *before_reloc = input_line_pointer;
+	  reloc = parse_reloc (&input_line_pointer);
+	  if (reloc == -1)
+	    {
+	      as_bad (_("unrecognized relocation suffix"));
+	      ignore_rest_of_line ();
+	      return;
+	    }
+	  else if (reloc == BFD_RELOC_UNUSED)
+	    emit_expr (&exp, (unsigned int) nbytes);
+	  else
+	    {
+	      reloc_howto_type *howto = (reloc_howto_type *)
+		  bfd_reloc_type_lookup (stdoutput,
+					 (bfd_reloc_code_real_type) reloc);
+	      int size = bfd_get_reloc_size (howto);
+
+	      if (reloc == BFD_RELOC_ARM_PLT32)
+		{
+		  as_bad (_("(plt) is only valid on branch targets"));
+		  reloc = BFD_RELOC_UNUSED;
+		  size = 0;
+		}
+
+	      if (size > nbytes)
+		as_bad (ngettext ("%s relocations do not fit in %d byte",
+				  "%s relocations do not fit in %d bytes",
+				  nbytes),
+			howto->name, nbytes);
+	      else
+		{
+		  /* We've parsed an expression stopping at O_symbol.
+		     But there may be more expression left now that we
+		     have parsed the relocation marker.  Parse it again.
+		     XXX Surely there is a cleaner way to do this.  */
+		  char *p = input_line_pointer;
+		  int offset;
+		  char *save_buf = XNEWVEC (char, input_line_pointer - base);
+
+		  memcpy (save_buf, base, input_line_pointer - base);
+		  memmove (base + (input_line_pointer - before_reloc),
+			   base, before_reloc - base);
+
+		  input_line_pointer = base + (input_line_pointer-before_reloc);
+		  expression (&exp);
+		  memcpy (base, save_buf, p - base);
+
+		  offset = nbytes - size;
+		  p = frag_more (nbytes);
+		  memset (p, 0, nbytes);
+		  fix_new_exp (frag_now, p - frag_now->fr_literal + offset,
+			       size, &exp, 0, (enum bfd_reloc_code_real) reloc);
+		  free (save_buf);
+		}
+	    }
+	}
+    }
+  while (*input_line_pointer++ == ',');
+
+  /* Put terminator back into stream.  */
+  input_line_pointer --;
+  demand_empty_rest_of_line ();
+}
+
 /* Parse a .rel31 directive.  */
 
 static void
@@ -5118,12 +5118,12 @@ const pseudo_typeS md_pseudo_table[] =
   { "object_arch", s_arm_object_arch,	0 },
   { "fpu",	   s_arm_fpu,	  0 },
   { "arch_extension", s_arm_arch_extension, 0 },
+  { "inst",             s_arm_inst, 0 },
+  { "inst.n",           s_arm_inst, 2 },
+  { "inst.w",           s_arm_inst, 4 },
 #ifdef OBJ_ELF
   { "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 },
diff --git a/gas/testsuite/gas/arm/inst-pe.d b/gas/testsuite/gas/arm/inst-pe.d
new file mode 100644
index 00000000000..f8baff9daa5
--- /dev/null
+++ b/gas/testsuite/gas/arm/inst-pe.d
@@ -0,0 +1,18 @@
+#name: .inst pe/coff test
+#objdump: -d --prefix-addresses --show-raw-insn
+#target: [is_coff_format]
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+00000000 <arm> 11a01009 	movne	r1, r9
+00000004 <thumb> bf0c      	ite	eq
+00000006 <thumb\+0x2> 4649      	moveq	r1, r9
+00000008 <thumb\+0x4> 4649      	movne	r1, r9
+0000000a <thumb\+0x6> bf0c      	ite	eq
+0000000c <thumb\+0x8> 4649      	moveq	r1, r9
+0000000e <thumb\+0xa> 4649      	movne	r1, r9
+00000010 <thumb\+0xc> 4649      	mov	r1, r9
+00000012 <thumb\+0xe> ea4f 0109 	mov.w	r1, r9
+00000016 <thumb\+0x12> ea4f 0109 	mov.w	r1, r9
+0000001a <thumb\+0x16> bf00      	nop
diff --git a/gas/testsuite/gas/arm/inst-pe.s b/gas/testsuite/gas/arm/inst-pe.s
new file mode 100644
index 00000000000..fe6f0648812
--- /dev/null
+++ b/gas/testsuite/gas/arm/inst-pe.s
@@ -0,0 +1,27 @@
+.syntax unified
+.arch armv7a
+
+.arm
+arm:
+        @ movne r1,r9
+        .inst 0x11a01009
+
+.thumb
+thumb:
+        @ ite eq
+        @ moveq r1, r9
+        @ movne r1, r9
+        .inst 0xbf0b + 1, 0x4649
+        .inst 0x4649
+
+        @ 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
diff --git a/gas/testsuite/gas/arm/mve-vmla.d b/gas/testsuite/gas/arm/mve-vmla.d
index 9ea738f22f5..fc85da24c1d 100644
--- a/gas/testsuite/gas/arm/mve-vmla.d
+++ b/gas/testsuite/gas/arm/mve-vmla.d
@@ -1,7 +1,6 @@
 # name: MVE vmla instructions
 # as: -march=armv8.1-m.main+mve.fp
 # objdump: -dr --prefix-addresses --show-raw-insn -marmv8.1-m.main
-# target: [is_elf_format]
 
 .*: +file format .*arm.*
 
-- 
2.45.2



More information about the Binutils mailing list