aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2020-09-14 16:14:24 +0100
committerNick Clifton <nickc@redhat.com>2020-09-14 16:14:24 +0100
commitb1766e7ce88647c8002928aeb8a9f04048c494ae (patch)
tree33c8ecdce1a894dfba913c58e0b484991383be8c /gas
parent04f5bab24ba93562d5d14b6f26efbd407dbccaaf (diff)
downloadgdb-b1766e7ce88647c8002928aeb8a9f04048c494ae.zip
gdb-b1766e7ce88647c8002928aeb8a9f04048c494ae.tar.gz
gdb-b1766e7ce88647c8002928aeb8a9f04048c494ae.tar.bz2
Add a new ".nop" directive to the assembler to allow the creation of no-op instructions in an architeture neutral manner.
* read.c (s_nop): New function. Handles the .nop directive. (potable): Add entry for "nop". (s_nops): Code tidy. * read.h (s_nop): Add prototype. * config/tc-bpf.h (md_single_noop_insn): Define. * config/tc-mmix.h (md_single_noop_insn): Define. * config/tc-or1k.h (md_single_noop_insn): Define. * config/tc-s12z.c (md_assemble): Preserve the input line pointer, rather than corrupting it. * write.c (relax_segment): Update error message regarding non-absolute values passed to .fill and .nops. * NEWS: Mention the new directive. * doc/as.texi: Document the new directive. * doc/internals.texi: Document the new internal macros used to implement the new directive. * testsuite/gas/all/nop.s: New test. * testsuite/gas/all/nop.d: New test control file. * testsuite/gas/all/gas.exp: Run the new test. * testsuite/gas/elf/dwarf-5-nop-for-line-table.s: New test. * testsuite/gas/elf/dwarf-5-nop-for-line-table.d: New test control file. * testsuite/gas/elf/elf.exp: Run the new test. * testsuite/gas/i386/space1.l: Adjust expected output.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog26
-rw-r--r--gas/NEWS4
-rw-r--r--gas/config/tc-bpf.h1
-rw-r--r--gas/config/tc-mmix.h2
-rw-r--r--gas/config/tc-or1k.h2
-rw-r--r--gas/config/tc-s12z.c9
-rw-r--r--gas/doc/as.texi32
-rw-r--r--gas/doc/internals.texi10
-rw-r--r--gas/read.c76
-rw-r--r--gas/read.h1
-rw-r--r--gas/testsuite/gas/all/gas.exp3
-rw-r--r--gas/testsuite/gas/all/nop.d8
-rw-r--r--gas/testsuite/gas/all/nop.s2
-rw-r--r--gas/testsuite/gas/elf/dwarf-5-nop-for-line-table.d12
-rw-r--r--gas/testsuite/gas/elf/dwarf-5-nop-for-line-table.s3
-rw-r--r--gas/testsuite/gas/elf/elf.exp1
-rw-r--r--gas/testsuite/gas/i386/space1.l10
-rw-r--r--gas/write.c2
18 files changed, 165 insertions, 39 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 1d13940..a80cef2 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,29 @@
+2020-09-14 Nick Clifton <nickc@redhat.com>
+
+ * read.c (s_nop): New function. Handles the .nop directive.
+ (potable): Add entry for "nop".
+ (s_nops): Code tidy.
+ * read.h (s_nop): Add prototype.
+ * config/tc-bpf.h (md_single_noop_insn): Define.
+ * config/tc-mmix.h (md_single_noop_insn): Define.
+ * config/tc-or1k.h (md_single_noop_insn): Define.
+ * config/tc-s12z.c (md_assemble): Preserve the input line pointer,
+ rather than corrupting it.
+ * write.c (relax_segment): Update error message regarding
+ non-absolute values passed to .fill and .nops.
+ * NEWS: Mention the new directive.
+ * doc/as.texi: Document the new directive.
+ * doc/internals.texi: Document the new internal macros used to
+ implement the new directive.
+ * testsuite/gas/all/nop.s: New test.
+ * testsuite/gas/all/nop.d: New test control file.
+ * testsuite/gas/all/gas.exp: Run the new test.
+ * testsuite/gas/elf/dwarf-5-nop-for-line-table.s: New test.
+ * testsuite/gas/elf/dwarf-5-nop-for-line-table.d: New test
+ control file.
+ * testsuite/gas/elf/elf.exp: Run the new test.
+ * testsuite/gas/i386/space1.l: Adjust expected output.
+
2020-09-07 Mark Wielaard <mark@klomp.org>
* as.texi (-g): Explicitly mention when .debug_info and .debug_line
diff --git a/gas/NEWS b/gas/NEWS
index 66afd03..d709edf 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,9 @@
-*- text -*-
+* Added a .nop directive to generate a single no-op instruction in a target
+ neutral manner. This instruction does have an effect on DWARF line number
+ generation, if that is active.
+
* Removed --reduce-memory-overheads and --hash-size as gas now
uses hash tables that can be expand and shrink automatically.
diff --git a/gas/config/tc-bpf.h b/gas/config/tc-bpf.h
index 5765833..cb02d6c 100644
--- a/gas/config/tc-bpf.h
+++ b/gas/config/tc-bpf.h
@@ -48,3 +48,4 @@
/* Values passed to md_apply_fix don't include the symbol value. */
#define MD_APPLY_SYM_VALUE(FIX) 0
+#define md_single_noop_insn "mov %r1,%r1"
diff --git a/gas/config/tc-mmix.h b/gas/config/tc-mmix.h
index f7a54c1..2d8e226 100644
--- a/gas/config/tc-mmix.h
+++ b/gas/config/tc-mmix.h
@@ -228,3 +228,5 @@ extern void mmix_md_do_align (int, char *, int, int);
/* MMIX has global register symbols. */
#define TC_GLOBAL_REGISTER_SYMBOL_OK
+
+#define md_single_noop_insn "set $0, $0"
diff --git a/gas/config/tc-or1k.h b/gas/config/tc-or1k.h
index 0242dd4..b9aa00c 100644
--- a/gas/config/tc-or1k.h
+++ b/gas/config/tc-or1k.h
@@ -74,3 +74,5 @@ void or1k_elf_final_processing (void);
#define tc_cfi_frame_initial_instructions \
or1k_cfi_frame_initial_instructions
extern void or1k_cfi_frame_initial_instructions (void);
+
+#define md_single_noop_insn "l.nop"
diff --git a/gas/config/tc-s12z.c b/gas/config/tc-s12z.c
index d89fb0c..c79d2f4 100644
--- a/gas/config/tc-s12z.c
+++ b/gas/config/tc-s12z.c
@@ -3807,6 +3807,7 @@ md_assemble (char *str)
return;
}
+ char * saved_ilp = input_line_pointer;
input_line_pointer = skip_whites (op_end);
size_t i;
@@ -3816,15 +3817,17 @@ md_assemble (char *str)
if (0 == strcmp (name, opc->name))
{
if (opc->parse_operands (opc))
- return;
+ {
+ input_line_pointer = saved_ilp;
+ return;
+ }
continue;
}
}
as_bad (_("Invalid instruction: \"%s\""), str);
as_bad (_("First invalid token: \"%s\""), fail_line_pointer);
- while (*input_line_pointer++)
- ;
+ input_line_pointer = saved_ilp;
}
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index f2a0314..b88c1f9 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -4446,6 +4446,7 @@ Some machine configurations provide additional directives.
* MRI:: @code{.mri @var{val}}
* Noaltmacro:: @code{.noaltmacro}
* Nolist:: @code{.nolist}
+* Nop:: @code{.nop}
* Nops:: @code{.nops @var{size}[, @var{control}]}
* Octa:: @code{.octa @var{bignums}}
* Offset:: @code{.offset @var{loc}}
@@ -6157,22 +6158,31 @@ internal counter (which is zero initially). @code{.list} increments the
counter, and @code{.nolist} decrements it. Assembly listings are
generated whenever the counter is greater than zero.
+@node Nop
+@section @code{.nop}
+
+@cindex @code{nop} directive
+@cindex filling memory with no-op instructions
+This directive emits a single no-op instruction. It is provided on all
+architectures, allowing the creation of architecture neutral tests involving
+actual code. The size of the generated instruction is target specific. The
+instruction does affect the generation of DWARF debug line information.
+
@node Nops
@section @code{.nops @var{size}[, @var{control}]}
@cindex @code{nops} directive
@cindex filling memory with no-op instructions
-This directive emits @var{size} bytes filled with no-op instructions.
-@var{size} is absolute expression, which must be a positve value.
-@var{control} controls how no-op instructions should be generated. If
-the comma and @var{control} are omitted, @var{control} is assumed to be
-zero.
-
-Note: For Intel 80386 and AMD x86-64 targets, @var{control} specifies
-the size limit of a no-op instruction. The valid values of @var{control}
-are between 0 and 4 in 16-bit mode, between 0 and 7 when tuning for
-older processors in 32-bit mode, between 0 and 11 in 64-bit mode or when
-tuning for newer processors in 32-bit mode. When 0 is used, the no-op
+This directive emits no-op instructions. It is specific to the Intel 80386 and
+AMD x86-64 targets. It takes a @var{size} argument and generates @var{size}
+bytes of no-op instructions. @var{size} must be absolute and positive. These
+bytes do not affect the generation of DWARF debug line information.
+
+The optional @var{control} argument specifies a size limit for a single no-op
+instruction. If not provided then a value of 0 is assumed. The valid values
+of @var{control} are between 0 and 4 in 16-bit mode, between 0 and 7 when
+tuning for older processors in 32-bit mode, between 0 and 11 in 64-bit mode or
+when tuning for newer processors in 32-bit mode. When 0 is used, the no-op
instruction size limit is set to the maximum supported size.
@node Octa
diff --git a/gas/doc/internals.texi b/gas/doc/internals.texi
index a690d78..8afa283 100644
--- a/gas/doc/internals.texi
+++ b/gas/doc/internals.texi
@@ -1547,6 +1547,16 @@ The function should return the debug format that is preferred by the CPU
backend. This format will be used when generating assembler specific debug
information.
+@item md_emit_single_noop_insn
+@itemx md_single_noop_insn
+These macro facilitate the @var{.nop} directive. If defined the
+@var{md_emit_single_noop_insn) macro provides code to insert a single no-op
+instruction into the output stream. If this involves calling @var{md_assemble}
+with a fixed string then the alternative macro @var{md_single_noop_insn} can be
+defined, specifying the string to pass. If neither of these macros are defined
+then the @var{.nop} directive will call @var{md_assemble} with the string
+@option{nop}.
+
@item md_allow_local_subtract (@var{left}, @var{right}, @var{section})
If defined, GAS will call this macro when evaluating an expression which is the
difference of two symbols defined in the same section. It takes three
diff --git a/gas/read.c b/gas/read.c
index cd06ea5..97a9e66 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -465,6 +465,7 @@ static const pseudo_typeS potable[] = {
{"noformat", s_ignore, 0},
{"nolist", listing_list, 0}, /* Turn listing off. */
{"nopage", listing_nopage, 0},
+ {"nop", s_nop, 0},
{"nops", s_nops, 0},
{"octa", cons, 16},
{"offset", s_struct, 0},
@@ -3503,6 +3504,38 @@ s_space (int mult)
}
void
+s_nop (int ignore ATTRIBUTE_UNUSED)
+{
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+#ifdef md_cons_align
+ md_cons_align (1);
+#endif
+
+ SKIP_WHITESPACE ();
+ demand_empty_rest_of_line ();
+
+#ifdef md_emit_single_noop
+ md_emit_single_noop;
+#else
+ char * nop;
+
+#ifndef md_single_noop_insn
+#define md_single_noop_insn "nop"
+#endif
+ /* md_assemble might modify its argument, so
+ we must pass it a string that is writeable. */
+ if (asprintf (&nop, "%s", md_single_noop_insn) < 0)
+ as_fatal ("%s", xstrerror (errno));
+
+ md_assemble (nop);
+ free (nop);
+#endif
+}
+
+void
s_nops (int ignore ATTRIBUTE_UNUSED)
{
expressionS exp;
@@ -3516,8 +3549,12 @@ s_nops (int ignore ATTRIBUTE_UNUSED)
md_cons_align (1);
#endif
+ SKIP_WHITESPACE ();
expression (&exp);
+ /* Note - this expression is tested for an absolute value in
+ write.c:relax_segment(). */
+ SKIP_WHITESPACE ();
if (*input_line_pointer == ',')
{
++input_line_pointer;
@@ -3529,29 +3566,30 @@ s_nops (int ignore ATTRIBUTE_UNUSED)
val.X_add_number = 0;
}
- if (val.X_op == O_constant)
+ if (val.X_op != O_constant)
{
- if (val.X_add_number < 0)
- {
- as_warn (_("negative nop control byte, ignored"));
- val.X_add_number = 0;
- }
-
- if (!need_pass_2)
- {
- /* Store the no-op instruction control byte in the first byte
- of frag. */
- char *p;
- symbolS *sym = make_expr_symbol (&exp);
- p = frag_var (rs_space_nop, 1, 1, (relax_substateT) 0,
- sym, (offsetT) 0, (char *) 0);
- *p = val.X_add_number;
- }
+ as_bad (_("unsupported variable nop control in .nops directive"));
+ val.X_op = O_constant;
+ val.X_add_number = 0;
+ }
+ else if (val.X_add_number < 0)
+ {
+ as_warn (_("negative nop control byte, ignored"));
+ val.X_add_number = 0;
}
- else
- as_bad (_("unsupported variable nop control in .nops directive"));
demand_empty_rest_of_line ();
+
+ if (need_pass_2)
+ /* Ignore this directive if we are going to perform a second pass. */
+ return;
+
+ /* Store the no-op instruction control byte in the first byte of frag. */
+ char *p;
+ symbolS *sym = make_expr_symbol (&exp);
+ p = frag_var (rs_space_nop, 1, 1, (relax_substateT) 0,
+ sym, (offsetT) 0, (char *) 0);
+ *p = val.X_add_number;
}
/* This is like s_space, but the value is a floating point number with
diff --git a/gas/read.h b/gas/read.h
index ffcdbb6..b2f0d36 100644
--- a/gas/read.h
+++ b/gas/read.h
@@ -207,6 +207,7 @@ extern void s_purgem (int);
extern void s_rept (int);
extern void s_set (int);
extern void s_space (int mult);
+extern void s_nop (int);
extern void s_nops (int);
extern void s_stab (int what);
extern void s_struct (int);
diff --git a/gas/testsuite/gas/all/gas.exp b/gas/testsuite/gas/all/gas.exp
index a0158f3..af9cb61 100644
--- a/gas/testsuite/gas/all/gas.exp
+++ b/gas/testsuite/gas/all/gas.exp
@@ -443,6 +443,7 @@ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/err-*.s $srcdir/$subdir/warn
dg-finish
# Set $nop_type appropriately to indicate the NOP instruction mnemonic.
+# Note - this code is made obsolete by the new .nops pseudo-op.
switch -glob $target_triplet {
bpf-*-* {
set nop_type 6
@@ -470,3 +471,5 @@ run_dump_test "org-6"
run_dump_test "fill-1"
gas_test "pr23938.s" "" "" ".xstabs"
+
+run_dump_test "nop"
diff --git a/gas/testsuite/gas/all/nop.d b/gas/testsuite/gas/all/nop.d
new file mode 100644
index 0000000..81ac08d
--- /dev/null
+++ b/gas/testsuite/gas/all/nop.d
@@ -0,0 +1,8 @@
+#objdump: -s -j .text -j "\$TEXT\$"
+#name: Generate NOPs in an architecture neutral manner
+
+.*: +file format .*
+
+Contents of section (\.text|\$TEXT\$):
+ [^ ]* .*
+#pass
diff --git a/gas/testsuite/gas/all/nop.s b/gas/testsuite/gas/all/nop.s
new file mode 100644
index 0000000..bca3805
--- /dev/null
+++ b/gas/testsuite/gas/all/nop.s
@@ -0,0 +1,2 @@
+ .text
+ .nop
diff --git a/gas/testsuite/gas/elf/dwarf-5-nop-for-line-table.d b/gas/testsuite/gas/elf/dwarf-5-nop-for-line-table.d
new file mode 100644
index 0000000..651a1a2
--- /dev/null
+++ b/gas/testsuite/gas/elf/dwarf-5-nop-for-line-table.d
@@ -0,0 +1,12 @@
+#as: --gdwarf-5
+#name: Check line table is produced with .nops
+#readelf: -wL
+
+#...
+Contents of the .debug_line section:
+
+CU: .*
+File name.*
+#...
+.*[ ]+[1-8][ ]+0.*
+#pass
diff --git a/gas/testsuite/gas/elf/dwarf-5-nop-for-line-table.s b/gas/testsuite/gas/elf/dwarf-5-nop-for-line-table.s
new file mode 100644
index 0000000..e3712ff
--- /dev/null
+++ b/gas/testsuite/gas/elf/dwarf-5-nop-for-line-table.s
@@ -0,0 +1,3 @@
+ .text
+ .nop
+ .nop
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 8520421..135ade2 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -279,6 +279,7 @@ if { [is_elf_format] } then {
run_dump_test "dwarf-5-file0" $dump_opts
run_dump_test "dwarf-4-cu" $dump_opts
run_dump_test "dwarf-5-cu" $dump_opts
+ run_dump_test "dwarf-5-nop-for-line-table" $dump_opts
run_dump_test "pr25917"
run_dump_test "bss"
run_dump_test "bad-bss"
diff --git a/gas/testsuite/gas/i386/space1.l b/gas/testsuite/gas/i386/space1.l
index 5b0053e..bf446fa 100644
--- a/gas/testsuite/gas/i386/space1.l
+++ b/gas/testsuite/gas/i386/space1.l
@@ -1,9 +1,9 @@
.*: Assembler messages:
-.*:2: Error: .space specifies non-absolute value
-.*:3: Error: .space specifies non-absolute value
-.*:4: Error: .space specifies non-absolute value
-.*:5: Error: .space specifies non-absolute value
-.*:6: Error: .space specifies non-absolute value
+.*:2: Error: .space, .nops or .fill specifies non-absolute value
+.*:3: Error: .space, .nops or .fill specifies non-absolute value
+.*:4: Error: .space, .nops or .fill specifies non-absolute value
+.*:5: Error: .space, .nops or .fill specifies non-absolute value
+.*:6: Error: .space, .nops or .fill specifies non-absolute value
GAS LISTING .*
diff --git a/gas/write.c b/gas/write.c
index 0b43063..054f279 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -3017,7 +3017,7 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
|| ! S_IS_DEFINED (symbolP))
{
as_bad_where (fragP->fr_file, fragP->fr_line,
- _(".space specifies non-absolute value"));
+ _(".space, .nops or .fill specifies non-absolute value"));
/* Prevent repeat of this error message. */
fragP->fr_symbol = 0;
}