diff options
author | Nick Clifton <nickc@redhat.com> | 2020-09-14 16:14:24 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2020-09-14 16:14:24 +0100 |
commit | b1766e7ce88647c8002928aeb8a9f04048c494ae (patch) | |
tree | 33c8ecdce1a894dfba913c58e0b484991383be8c /gas/read.c | |
parent | 04f5bab24ba93562d5d14b6f26efbd407dbccaaf (diff) | |
download | gdb-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/read.c')
-rw-r--r-- | gas/read.c | 76 |
1 files changed, 57 insertions, 19 deletions
@@ -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 |