mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
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.
This commit is contained in:
parent
04f5bab24b
commit
b1766e7ce8
@ -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
|
||||
|
4
gas/NEWS
4
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.
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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.
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
|
@ -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
|
||||
|
76
gas/read.c
76
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},
|
||||
@ -3502,6 +3503,38 @@ s_space (int mult)
|
||||
mri_comment_end (stop, stopc);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
8
gas/testsuite/gas/all/nop.d
Normal file
8
gas/testsuite/gas/all/nop.d
Normal file
@ -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
|
2
gas/testsuite/gas/all/nop.s
Normal file
2
gas/testsuite/gas/all/nop.s
Normal file
@ -0,0 +1,2 @@
|
||||
.text
|
||||
.nop
|
12
gas/testsuite/gas/elf/dwarf-5-nop-for-line-table.d
Normal file
12
gas/testsuite/gas/elf/dwarf-5-nop-for-line-table.d
Normal file
@ -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
|
3
gas/testsuite/gas/elf/dwarf-5-nop-for-line-table.s
Normal file
3
gas/testsuite/gas/elf/dwarf-5-nop-for-line-table.s
Normal file
@ -0,0 +1,3 @@
|
||||
.text
|
||||
.nop
|
||||
.nop
|
@ -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"
|
||||
|
@ -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 .*
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user