[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