Add .nop assembler directive
Implement the '.nop SIZE[, CONTROL]' assembler directive, which emits SIZE bytes filled with no-op instructions. SIZE is absolute expression. The optional CONTROL byte controls how no-op instructions should be generated. If the comma and @var{control} are omitted, CONTROL is assumed to be zero. For Intel 80386 and AMD x86-64 targets, CONTROL byte specifies the size limit of a single no-op instruction. The valid values of CONTROL byte are between 0 and 8 for 16-bit mode, between 0 and 10 for 32-bit mode, between 0 and 11 for 64-bit mode. When 0 is used, the no-op size limit is set to the maximum supported size. 2 new relax states, rs_space_nop and rs_fill_nop, are added to enum _relax_state, which are similar to rs_space and rs_fill, respectively, but they fill with no-op instructions, instead of a single byte. A target backend must override the default md_generate_nops to generate proper no-op instructions. Otherwise, an error of unimplemented .nop directive will be issued whenever .nop directive is used. * NEWS: Mention .nop directive. * as.h (_relax_state): Add rs_space_nop and rs_fill_nop. * read.c (potable): Add .nop. (s_nop): New function. * read.h (s_nop): New prototype. * write.c (cvt_frag_to_fill): Handle rs_space_nop and rs_fill_nop. (md_generate_nops): New function. (relax_segment): Likewise. (write_contents): Use md_generate_nops for rs_fill_nop. * config/tc-i386.c (alt64_11): New. (alt64_patt): Likewise. (md_convert_frag): Handle rs_space_nop. (i386_output_nops): New function. (i386_generate_nops): Likewise. (i386_align_code): Call i386_output_nops. * config/tc-i386.h (i386_generate_nops): New. (md_generate_nops): Likewise. * doc/as.texinfo: Document .nop directive. * testsuite/gas/i386/i386.exp: Run .nop directive tests. * testsuite/gas/i386/nop-1.d: New file. * testsuite/gas/i386/nop-1.s: Likewise. * testsuite/gas/i386/nop-2.d: Likewise. * testsuite/gas/i386/nop-2.s: Likewise. * testsuite/gas/i386/nop-3.d: Likewise. * testsuite/gas/i386/nop-3.s: Likewise. * testsuite/gas/i386/nop-4.d: Likewise. * testsuite/gas/i386/nop-4.s: Likewise. * testsuite/gas/i386/nop-5.d: Likewise. * testsuite/gas/i386/nop-5.s: Likewise. * testsuite/gas/i386/nop-6.d: Likewise. * testsuite/gas/i386/nop-6.s: Likewise. * testsuite/gas/i386/nop-bad-1.l: Likewise. * testsuite/gas/i386/nop-bad-1.s: Likewise. * testsuite/gas/i386/x86-64-nop-1.d: Likewise. * testsuite/gas/i386/x86-64-nop-2.d: Likewise. * testsuite/gas/i386/x86-64-nop-3.d: Likewise. * testsuite/gas/i386/x86-64-nop-4.d: Likewise. * testsuite/gas/i386/x86-64-nop-5.d: Likewise. * testsuite/gas/i386/x86-64-nop-6.d: Likewise.
This commit is contained in:
parent
bb57c12e55
commit
62a02d25b6
@ -1,3 +1,46 @@
|
||||
2018-02-17 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* NEWS: Mention .nop directive.
|
||||
* as.h (_relax_state): Add rs_space_nop and rs_fill_nop.
|
||||
* read.c (potable): Add .nop.
|
||||
(s_nop): New function.
|
||||
* read.h (s_nop): New prototype.
|
||||
* write.c (cvt_frag_to_fill): Handle rs_space_nop and
|
||||
rs_fill_nop.
|
||||
(md_generate_nops): New function.
|
||||
(relax_segment): Likewise.
|
||||
(write_contents): Use md_generate_nops for rs_fill_nop.
|
||||
* config/tc-i386.c (alt64_11): New.
|
||||
(alt64_patt): Likewise.
|
||||
(md_convert_frag): Handle rs_space_nop.
|
||||
(i386_output_nops): New function.
|
||||
(i386_generate_nops): Likewise.
|
||||
(i386_align_code): Call i386_output_nops.
|
||||
* config/tc-i386.h (i386_generate_nops): New.
|
||||
(md_generate_nops): Likewise.
|
||||
* doc/as.texinfo: Document .nop directive.
|
||||
* testsuite/gas/i386/i386.exp: Run .nop directive tests.
|
||||
* testsuite/gas/i386/nop-1.d: New file.
|
||||
* testsuite/gas/i386/nop-1.s: Likewise.
|
||||
* testsuite/gas/i386/nop-2.d: Likewise.
|
||||
* testsuite/gas/i386/nop-2.s: Likewise.
|
||||
* testsuite/gas/i386/nop-3.d: Likewise.
|
||||
* testsuite/gas/i386/nop-3.s: Likewise.
|
||||
* testsuite/gas/i386/nop-4.d: Likewise.
|
||||
* testsuite/gas/i386/nop-4.s: Likewise.
|
||||
* testsuite/gas/i386/nop-5.d: Likewise.
|
||||
* testsuite/gas/i386/nop-5.s: Likewise.
|
||||
* testsuite/gas/i386/nop-6.d: Likewise.
|
||||
* testsuite/gas/i386/nop-6.s: Likewise.
|
||||
* testsuite/gas/i386/nop-bad-1.l: Likewise.
|
||||
* testsuite/gas/i386/nop-bad-1.s: Likewise.
|
||||
* testsuite/gas/i386/x86-64-nop-1.d: Likewise.
|
||||
* testsuite/gas/i386/x86-64-nop-2.d: Likewise.
|
||||
* testsuite/gas/i386/x86-64-nop-3.d: Likewise.
|
||||
* testsuite/gas/i386/x86-64-nop-4.d: Likewise.
|
||||
* testsuite/gas/i386/x86-64-nop-5.d: Likewise.
|
||||
* testsuite/gas/i386/x86-64-nop-6.d: Likewise.
|
||||
|
||||
2018-02-15 Tamar Christina <tamar.christina@arm.com>
|
||||
|
||||
* config/tc-arm.c (cpu_arch_ver): Renumber ARM_ARCH_V8_4A.
|
||||
|
3
gas/NEWS
3
gas/NEWS
@ -1,5 +1,8 @@
|
||||
-*- text -*-
|
||||
|
||||
* Add support for .nop directive. It is currently supported only for
|
||||
x86 targets.
|
||||
|
||||
Changes in 2.30:
|
||||
|
||||
* Add support for loaction views in DWARF debug line information.
|
||||
|
10
gas/as.h
10
gas/as.h
@ -279,6 +279,16 @@ enum _relax_state
|
||||
1 variable char: fill character */
|
||||
rs_space,
|
||||
|
||||
/* .nop directive with expression operand that needs to be computed
|
||||
later. Similar to rs_space, but different. It fills with no-op
|
||||
instructions.
|
||||
fr_symbol: operand
|
||||
1 constant byte: no-op fill control byte. */
|
||||
rs_space_nop,
|
||||
|
||||
/* Similar to rs_fill. It is used to implement .nop directive . */
|
||||
rs_fill_nop,
|
||||
|
||||
/* A DWARF leb128 value; only ELF uses this. The subtype is 0 for
|
||||
unsigned, 1 for signed. */
|
||||
rs_leb128,
|
||||
|
@ -1146,105 +1146,174 @@ static struct hash_control *op_hash;
|
||||
/* Hash table for register lookup. */
|
||||
static struct hash_control *reg_hash;
|
||||
|
||||
void
|
||||
i386_align_code (fragS *fragP, int count)
|
||||
{
|
||||
/* Various efficient no-op patterns for aligning code labels.
|
||||
Note: Don't try to assemble the instructions in the comments.
|
||||
0L and 0w are not legal. */
|
||||
static const unsigned char f32_1[] =
|
||||
{0x90}; /* nop */
|
||||
static const unsigned char f32_2[] =
|
||||
{0x66,0x90}; /* xchg %ax,%ax */
|
||||
static const unsigned char f32_3[] =
|
||||
{0x8d,0x76,0x00}; /* leal 0(%esi),%esi */
|
||||
static const unsigned char f32_4[] =
|
||||
{0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */
|
||||
static const unsigned char f32_5[] =
|
||||
{0x90, /* nop */
|
||||
0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */
|
||||
static const unsigned char f32_6[] =
|
||||
{0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */
|
||||
static const unsigned char f32_7[] =
|
||||
{0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */
|
||||
static const unsigned char f32_8[] =
|
||||
{0x90, /* nop */
|
||||
0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */
|
||||
static const unsigned char f32_9[] =
|
||||
{0x89,0xf6, /* movl %esi,%esi */
|
||||
0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
|
||||
static const unsigned char f32_10[] =
|
||||
{0x8d,0x76,0x00, /* leal 0(%esi),%esi */
|
||||
0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
|
||||
static const unsigned char f32_11[] =
|
||||
{0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */
|
||||
0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
|
||||
static const unsigned char f32_12[] =
|
||||
{0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */
|
||||
0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */
|
||||
static const unsigned char f32_13[] =
|
||||
{0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */
|
||||
0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
|
||||
static const unsigned char f32_14[] =
|
||||
{0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */
|
||||
0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
|
||||
static const unsigned char f16_3[] =
|
||||
{0x8d,0x74,0x00}; /* lea 0(%esi),%esi */
|
||||
static const unsigned char f16_4[] =
|
||||
{0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */
|
||||
static const unsigned char f16_5[] =
|
||||
{0x90, /* nop */
|
||||
0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */
|
||||
static const unsigned char f16_6[] =
|
||||
{0x89,0xf6, /* mov %si,%si */
|
||||
0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */
|
||||
static const unsigned char f16_7[] =
|
||||
{0x8d,0x74,0x00, /* lea 0(%si),%si */
|
||||
0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */
|
||||
static const unsigned char f16_8[] =
|
||||
{0x8d,0xb4,0x00,0x00, /* lea 0w(%si),%si */
|
||||
0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */
|
||||
static const unsigned char jump_31[] =
|
||||
{0xeb,0x1d,0x90,0x90,0x90,0x90,0x90, /* jmp .+31; lotsa nops */
|
||||
0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,
|
||||
0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,
|
||||
0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};
|
||||
static const unsigned char *const f32_patt[] = {
|
||||
f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8,
|
||||
f32_9, f32_10, f32_11, f32_12, f32_13, f32_14
|
||||
};
|
||||
static const unsigned char *const f16_patt[] = {
|
||||
f32_1, f32_2, f16_3, f16_4, f16_5, f16_6, f16_7, f16_8
|
||||
};
|
||||
/* nopl (%[re]ax) */
|
||||
static const unsigned char alt_3[] =
|
||||
{0x0f,0x1f,0x00};
|
||||
/* nopl 0(%[re]ax) */
|
||||
static const unsigned char alt_4[] =
|
||||
{0x0f,0x1f,0x40,0x00};
|
||||
/* nopl 0(%[re]ax,%[re]ax,1) */
|
||||
static const unsigned char alt_5[] =
|
||||
{0x0f,0x1f,0x44,0x00,0x00};
|
||||
/* nopw 0(%[re]ax,%[re]ax,1) */
|
||||
static const unsigned char alt_6[] =
|
||||
{0x66,0x0f,0x1f,0x44,0x00,0x00};
|
||||
/* nopl 0L(%[re]ax) */
|
||||
static const unsigned char alt_7[] =
|
||||
{0x0f,0x1f,0x80,0x00,0x00,0x00,0x00};
|
||||
/* nopl 0L(%[re]ax,%[re]ax,1) */
|
||||
static const unsigned char alt_8[] =
|
||||
{0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
|
||||
/* nopw 0L(%[re]ax,%[re]ax,1) */
|
||||
static const unsigned char alt_9[] =
|
||||
{0x66,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
|
||||
/* nopw %cs:0L(%[re]ax,%[re]ax,1) */
|
||||
static const unsigned char alt_10[] =
|
||||
{0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
|
||||
static const unsigned char *const alt_patt[] = {
|
||||
f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8,
|
||||
alt_9, alt_10
|
||||
};
|
||||
static const unsigned char f32_1[] =
|
||||
{0x90}; /* nop */
|
||||
static const unsigned char f32_2[] =
|
||||
{0x66,0x90}; /* xchg %ax,%ax */
|
||||
static const unsigned char f32_3[] =
|
||||
{0x8d,0x76,0x00}; /* leal 0(%esi),%esi */
|
||||
static const unsigned char f32_4[] =
|
||||
{0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */
|
||||
static const unsigned char f32_5[] =
|
||||
{0x90, /* nop */
|
||||
0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */
|
||||
static const unsigned char f32_6[] =
|
||||
{0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */
|
||||
static const unsigned char f32_7[] =
|
||||
{0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */
|
||||
static const unsigned char f32_8[] =
|
||||
{0x90, /* nop */
|
||||
0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */
|
||||
static const unsigned char f32_9[] =
|
||||
{0x89,0xf6, /* movl %esi,%esi */
|
||||
0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
|
||||
static const unsigned char f32_10[] =
|
||||
{0x8d,0x76,0x00, /* leal 0(%esi),%esi */
|
||||
0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
|
||||
static const unsigned char f32_11[] =
|
||||
{0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */
|
||||
0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
|
||||
static const unsigned char f32_12[] =
|
||||
{0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */
|
||||
0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */
|
||||
static const unsigned char f32_13[] =
|
||||
{0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */
|
||||
0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
|
||||
static const unsigned char f32_14[] =
|
||||
{0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */
|
||||
0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
|
||||
static const unsigned char f16_3[] =
|
||||
{0x8d,0x74,0x00}; /* lea 0(%esi),%esi */
|
||||
static const unsigned char f16_4[] =
|
||||
{0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */
|
||||
static const unsigned char f16_5[] =
|
||||
{0x90, /* nop */
|
||||
0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */
|
||||
static const unsigned char f16_6[] =
|
||||
{0x89,0xf6, /* mov %si,%si */
|
||||
0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */
|
||||
static const unsigned char f16_7[] =
|
||||
{0x8d,0x74,0x00, /* lea 0(%si),%si */
|
||||
0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */
|
||||
static const unsigned char f16_8[] =
|
||||
{0x8d,0xb4,0x00,0x00, /* lea 0w(%si),%si */
|
||||
0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */
|
||||
static const unsigned char jump_31[] =
|
||||
{0xeb,0x1d,0x90,0x90,0x90,0x90,0x90, /* jmp .+31; lotsa nops */
|
||||
0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,
|
||||
0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,
|
||||
0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};
|
||||
/* 32-bit NOPs patterns. */
|
||||
static const unsigned char *const f32_patt[] = {
|
||||
f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8,
|
||||
f32_9, f32_10, f32_11, f32_12, f32_13, f32_14
|
||||
};
|
||||
/* 16-bit NOPs patterns. */
|
||||
static const unsigned char *const f16_patt[] = {
|
||||
f32_1, f32_2, f16_3, f16_4, f16_5, f16_6, f16_7, f16_8
|
||||
};
|
||||
/* nopl (%[re]ax) */
|
||||
static const unsigned char alt_3[] =
|
||||
{0x0f,0x1f,0x00};
|
||||
/* nopl 0(%[re]ax) */
|
||||
static const unsigned char alt_4[] =
|
||||
{0x0f,0x1f,0x40,0x00};
|
||||
/* nopl 0(%[re]ax,%[re]ax,1) */
|
||||
static const unsigned char alt_5[] =
|
||||
{0x0f,0x1f,0x44,0x00,0x00};
|
||||
/* nopw 0(%[re]ax,%[re]ax,1) */
|
||||
static const unsigned char alt_6[] =
|
||||
{0x66,0x0f,0x1f,0x44,0x00,0x00};
|
||||
/* nopl 0L(%[re]ax) */
|
||||
static const unsigned char alt_7[] =
|
||||
{0x0f,0x1f,0x80,0x00,0x00,0x00,0x00};
|
||||
/* nopl 0L(%[re]ax,%[re]ax,1) */
|
||||
static const unsigned char alt_8[] =
|
||||
{0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
|
||||
/* nopw 0L(%[re]ax,%[re]ax,1) */
|
||||
static const unsigned char alt_9[] =
|
||||
{0x66,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
|
||||
/* nopw %cs:0L(%[re]ax,%[re]ax,1) */
|
||||
static const unsigned char alt_10[] =
|
||||
{0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
|
||||
/* 32-bit and 64-bit NOPs patterns. */
|
||||
static const unsigned char *const alt_patt[] = {
|
||||
f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8,
|
||||
alt_9, alt_10
|
||||
};
|
||||
/* 64-bit only: nopw %cs:0L(%eax,%eax,1) */
|
||||
static const unsigned char alt64_11[] =
|
||||
{0x67,0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
|
||||
/* 64-bit NOPs patterns. */
|
||||
static const unsigned char *const alt64_patt[] = {
|
||||
f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8,
|
||||
alt_9, alt_10, alt64_11
|
||||
};
|
||||
|
||||
/* Genenerate COUNT bytes of NOPs to WHERE from PATT with the maximum
|
||||
size of a single NOP instruction MAX_SINGLE_NOP_SIZE. */
|
||||
|
||||
static void
|
||||
i386_output_nops (char *where, const unsigned char *const *patt,
|
||||
int count, int max_single_nop_size)
|
||||
|
||||
{
|
||||
while (count > max_single_nop_size)
|
||||
{
|
||||
count -= max_single_nop_size;
|
||||
memcpy (where + count, patt[max_single_nop_size - 1],
|
||||
max_single_nop_size);
|
||||
}
|
||||
|
||||
if (count)
|
||||
memcpy (where, patt[count - 1], count);
|
||||
}
|
||||
|
||||
|
||||
/* Genenerate COUNT bytes of NOPs to WHERE with the maximum size of a
|
||||
single NOP instruction LIMIT. */
|
||||
|
||||
void
|
||||
i386_generate_nops (fragS *f, char *where, offsetT count, int limit)
|
||||
{
|
||||
/* Output NOPs for .nop directive. */
|
||||
int max_single_nop_size;
|
||||
const unsigned char *const *patt;
|
||||
|
||||
if (flag_code == CODE_16BIT)
|
||||
{
|
||||
patt = f16_patt;
|
||||
max_single_nop_size = sizeof (f16_patt) / sizeof (f16_patt[0]);
|
||||
}
|
||||
else if (flag_code == CODE_64BIT)
|
||||
{
|
||||
patt = alt64_patt;
|
||||
max_single_nop_size = sizeof (alt64_patt) / sizeof (alt64_patt[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
patt = alt_patt;
|
||||
max_single_nop_size = sizeof (alt_patt) / sizeof (alt_patt[0]);
|
||||
}
|
||||
if (limit == 0)
|
||||
limit = max_single_nop_size;
|
||||
else if (limit > max_single_nop_size)
|
||||
{
|
||||
as_bad_where (f->fr_file, f->fr_line,
|
||||
_("invalide single nop size: %d (expect within [0, %d])"),
|
||||
limit, max_single_nop_size);
|
||||
return;
|
||||
}
|
||||
|
||||
i386_output_nops (where, patt, count, limit);
|
||||
}
|
||||
|
||||
void
|
||||
i386_align_code (fragS *fragP, int count)
|
||||
{
|
||||
/* Only align for at least a positive non-zero boundary. */
|
||||
if (count <= 0 || count > MAX_MEM_FOR_RS_ALIGN_CODE)
|
||||
return;
|
||||
@ -1397,17 +1466,8 @@ i386_align_code (fragS *fragP, int count)
|
||||
/* Maximum length of an instruction is 10 byte. If the
|
||||
padding is greater than 10 bytes and we don't use jump,
|
||||
we have to break it into smaller pieces. */
|
||||
int padding = count;
|
||||
while (padding > 10)
|
||||
{
|
||||
padding -= 10;
|
||||
memcpy (fragP->fr_literal + fragP->fr_fix + padding,
|
||||
patt [9], 10);
|
||||
}
|
||||
|
||||
if (padding)
|
||||
memcpy (fragP->fr_literal + fragP->fr_fix,
|
||||
patt [padding - 1], padding);
|
||||
i386_output_nops (fragP->fr_literal + fragP->fr_fix,
|
||||
patt, count, 10);
|
||||
}
|
||||
}
|
||||
fragP->fr_var = count;
|
||||
|
@ -281,6 +281,11 @@ extern void sco_id (void);
|
||||
|
||||
#define WORKING_DOT_WORD 1
|
||||
|
||||
/* How to generate NOPs for .nop direct directive. */
|
||||
extern void i386_generate_nops (fragS *, char *, offsetT, int);
|
||||
#define md_generate_nops(frag, where, amount, control) \
|
||||
i386_generate_nops ((frag), (where), (amount), (control))
|
||||
|
||||
/* We want .cfi_* pseudo-ops for generating unwind info. */
|
||||
#define TARGET_USE_CFIPOP 1
|
||||
|
||||
|
@ -4479,6 +4479,7 @@ Some machine configurations provide additional directives.
|
||||
* MRI:: @code{.mri @var{val}}
|
||||
* Noaltmacro:: @code{.noaltmacro}
|
||||
* Nolist:: @code{.nolist}
|
||||
* Nop:: @code{.nop @var{size}[, @var{control}]}
|
||||
* Octa:: @code{.octa @var{bignums}}
|
||||
* Offset:: @code{.offset @var{loc}}
|
||||
* Org:: @code{.org @var{new-lc}, @var{fill}}
|
||||
@ -6101,6 +6102,23 @@ 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 @var{size}[, @var{control}]}
|
||||
|
||||
@cindex @code{nop} 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 8 for 16-bit mode, between 0 and 10 for 32-bit mode,
|
||||
between 0 and 11 for 64-bit mode. When 0 is used, the no-op instruction
|
||||
size limit is set to the maximum supported size.
|
||||
|
||||
@node Octa
|
||||
@section @code{.octa @var{bignums}}
|
||||
|
||||
|
53
gas/read.c
53
gas/read.c
@ -442,6 +442,7 @@ static const pseudo_typeS potable[] = {
|
||||
/* size */
|
||||
{"space", s_space, 0},
|
||||
{"skip", s_space, 0},
|
||||
{"nop", s_nop, 0},
|
||||
{"sleb128", s_leb128, 1},
|
||||
{"spc", s_ignore, 0},
|
||||
{"stabd", s_stab, 'd'},
|
||||
@ -3508,6 +3509,58 @@ s_space (int mult)
|
||||
mri_comment_end (stop, stopc);
|
||||
}
|
||||
|
||||
void
|
||||
s_nop (int ignore ATTRIBUTE_UNUSED)
|
||||
{
|
||||
expressionS exp;
|
||||
expressionS val;
|
||||
|
||||
#ifdef md_flush_pending_output
|
||||
md_flush_pending_output ();
|
||||
#endif
|
||||
|
||||
#ifdef md_cons_align
|
||||
md_cons_align (1);
|
||||
#endif
|
||||
|
||||
expression (&exp);
|
||||
|
||||
if (*input_line_pointer == ',')
|
||||
{
|
||||
++input_line_pointer;
|
||||
expression (&val);
|
||||
}
|
||||
else
|
||||
{
|
||||
val.X_op = O_constant;
|
||||
val.X_add_number = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
as_bad (_("unsupported variable nop control in .nop directive"));
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
/* This is like s_space, but the value is a floating point number with
|
||||
the given precision. This is for the MRI dcb.s pseudo-op and
|
||||
friends. */
|
||||
|
@ -206,6 +206,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_stab (int what);
|
||||
extern void s_struct (int);
|
||||
extern void s_text (int);
|
||||
|
@ -431,6 +431,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]]
|
||||
run_dump_test "align-1a"
|
||||
run_dump_test "align-1b"
|
||||
run_list_test "inval-pseudo" "-al"
|
||||
run_dump_test "nop-1"
|
||||
run_dump_test "nop-2"
|
||||
|
||||
# These tests require support for 8 and 16 bit relocs,
|
||||
# so we only run them for ELF and COFF targets.
|
||||
@ -494,6 +496,10 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]]
|
||||
run_dump_test "got-no-relax"
|
||||
|
||||
run_dump_test "addend"
|
||||
run_dump_test "nop-3"
|
||||
run_dump_test "nop-4"
|
||||
run_dump_test "nop-5"
|
||||
run_dump_test "nop-6"
|
||||
|
||||
if { [gas_64_check] } then {
|
||||
run_dump_test "att-regs"
|
||||
@ -538,6 +544,7 @@ if [expr [istarget "i*86-*-*"] || [istarget "x86_64-*-*"]] then {
|
||||
run_list_test "space1" "-al"
|
||||
run_dump_test rept
|
||||
run_dump_test pr19498
|
||||
run_list_test "nop-bad-1" ""
|
||||
if [is_elf_format] then {
|
||||
run_list_test_stdin "list-1" "-al"
|
||||
run_list_test_stdin "list-2" "-al"
|
||||
@ -904,6 +911,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t
|
||||
run_list_test "x86-64-notrackbad" "-al"
|
||||
run_dump_test "x86-64-movd"
|
||||
run_dump_test "x86-64-movd-intel"
|
||||
run_dump_test "x86-64-nop-1"
|
||||
run_dump_test "x86-64-nop-2"
|
||||
|
||||
if { ![istarget "*-*-aix*"]
|
||||
&& ![istarget "*-*-beos*"]
|
||||
@ -961,6 +970,10 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t
|
||||
run_dump_test "x86-64-gotpcrel-no-relax"
|
||||
|
||||
run_dump_test "x86-64-addend"
|
||||
run_dump_test "x86-64-nop-3"
|
||||
run_dump_test "x86-64-nop-4"
|
||||
run_dump_test "x86-64-nop-5"
|
||||
run_dump_test "x86-64-nop-6"
|
||||
}
|
||||
|
||||
set ASFLAGS "$old_ASFLAGS"
|
||||
|
31
gas/testsuite/gas/i386/nop-1.d
Normal file
31
gas/testsuite/gas/i386/nop-1.d
Normal file
@ -0,0 +1,31 @@
|
||||
#objdump: -drw
|
||||
#name: i386 .nop 1
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+ <single>:
|
||||
+[a-f0-9]+: 90 nop
|
||||
|
||||
0+1 <pseudo_1>:
|
||||
+[a-f0-9]+: 90 nop
|
||||
|
||||
0+2 <pseudo_8>:
|
||||
+[a-f0-9]+: 0f 1f 84 00 00 00 00 00 nopl 0x0\(%eax,%eax,1\)
|
||||
|
||||
0+a <pseudo_8_4>:
|
||||
+[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%eax\)
|
||||
+[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%eax\)
|
||||
|
||||
0+12 <pseudo_20>:
|
||||
+[a-f0-9]+: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0\(%eax,%eax,1\)
|
||||
+[a-f0-9]+: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0\(%eax,%eax,1\)
|
||||
|
||||
0+26 <pseudo_30>:
|
||||
+[a-f0-9]+: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0\(%eax,%eax,1\)
|
||||
+[a-f0-9]+: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0\(%eax,%eax,1\)
|
||||
+[a-f0-9]+: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0\(%eax,%eax,1\)
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
#pass
|
21
gas/testsuite/gas/i386/nop-1.s
Normal file
21
gas/testsuite/gas/i386/nop-1.s
Normal file
@ -0,0 +1,21 @@
|
||||
.text
|
||||
single:
|
||||
.nop 0
|
||||
nop
|
||||
|
||||
pseudo_1:
|
||||
.nop 1
|
||||
|
||||
pseudo_8:
|
||||
.nop 8
|
||||
|
||||
pseudo_8_4:
|
||||
.nop 8, 4
|
||||
|
||||
pseudo_20:
|
||||
.nop 20
|
||||
|
||||
pseudo_30:
|
||||
.nop 30
|
||||
|
||||
xor %eax, %eax
|
40
gas/testsuite/gas/i386/nop-2.d
Normal file
40
gas/testsuite/gas/i386/nop-2.d
Normal file
@ -0,0 +1,40 @@
|
||||
#objdump: -drw -Mi8086
|
||||
#name: i386 .nop 2
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+ <single>:
|
||||
+[a-f0-9]+: 90 nop
|
||||
|
||||
0+1 <pseudo_1>:
|
||||
+[a-f0-9]+: 90 nop
|
||||
|
||||
0+2 <pseudo_8>:
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
|
||||
0+a <pseudo_8_4>:
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
|
||||
0+12 <pseudo_20>:
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
|
||||
0+26 <pseudo_30>:
|
||||
+[a-f0-9]+: 89 f6 mov %si,%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
+[a-f0-9]+: 66 31 c0 xor %eax,%eax
|
||||
#pass
|
22
gas/testsuite/gas/i386/nop-2.s
Normal file
22
gas/testsuite/gas/i386/nop-2.s
Normal file
@ -0,0 +1,22 @@
|
||||
.text
|
||||
.code16
|
||||
single:
|
||||
.nop 0
|
||||
nop
|
||||
|
||||
pseudo_1:
|
||||
.nop 1
|
||||
|
||||
pseudo_8:
|
||||
.nop 8
|
||||
|
||||
pseudo_8_4:
|
||||
.nop 8, 4
|
||||
|
||||
pseudo_20:
|
||||
.nop 20
|
||||
|
||||
pseudo_30:
|
||||
.nop 30
|
||||
|
||||
xor %eax, %eax
|
20
gas/testsuite/gas/i386/nop-3.d
Normal file
20
gas/testsuite/gas/i386/nop-3.d
Normal file
@ -0,0 +1,20 @@
|
||||
#objdump: -drw
|
||||
#name: i386 .nop 3
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+ <_start>:
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
+[a-f0-9]+: 85 c0 test %eax,%eax
|
||||
+[a-f0-9]+: 0f 1f 00 nopl \(%eax\)
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
|
||||
Disassembly of section .altinstr_replacement:
|
||||
|
||||
0+ <.altinstr_replacement>:
|
||||
+[a-f0-9]+: e9 fc ff ff ff jmp 1 <.altinstr_replacement\+0x1> 1: (R_386_PC)?(DISP)?32 foo
|
||||
#pass
|
15
gas/testsuite/gas/i386/nop-3.s
Normal file
15
gas/testsuite/gas/i386/nop-3.s
Normal file
@ -0,0 +1,15 @@
|
||||
.text
|
||||
_start:
|
||||
xor %eax, %eax
|
||||
140:
|
||||
testl %eax, %eax
|
||||
141:
|
||||
.nop -(((144f-143f)-(141b-140b)) > 0)*((144f-143f)-(141b-140b)),7
|
||||
142:
|
||||
xor %eax, %eax
|
||||
.pushsection .altinstr_replacement,"ax"
|
||||
143:
|
||||
jmp foo
|
||||
144:
|
||||
.popsection
|
||||
xor %eax, %eax
|
23
gas/testsuite/gas/i386/nop-4.d
Normal file
23
gas/testsuite/gas/i386/nop-4.d
Normal file
@ -0,0 +1,23 @@
|
||||
#objdump: -drw
|
||||
#name: i386 .nop 4
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+ <_start>:
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
+[a-f0-9]+: 85 c0 test %eax,%eax
|
||||
+[a-f0-9]+: 66 0f 1f 84 00 00 00 00 00 nopw 0x0\(%eax,%eax,1\)
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
|
||||
Disassembly of section .altinstr_replacement:
|
||||
|
||||
0+ <.altinstr_replacement>:
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: e9 fc ff ff ff jmp 7 <.altinstr_replacement\+0x7> 7: (R_386_PC)?(DISP)?32 foo
|
||||
#pass
|
18
gas/testsuite/gas/i386/nop-4.s
Normal file
18
gas/testsuite/gas/i386/nop-4.s
Normal file
@ -0,0 +1,18 @@
|
||||
.text
|
||||
_start:
|
||||
xor %eax, %eax
|
||||
140:
|
||||
testl %eax, %eax
|
||||
141:
|
||||
.nop -(((144f-143f)-(141b-140b)) > 0)*((144f-143f)-(141b-140b))
|
||||
142:
|
||||
xor %eax, %eax
|
||||
.pushsection .altinstr_replacement,"ax"
|
||||
143:
|
||||
mov %eax, %eax
|
||||
mov %eax, %eax
|
||||
mov %eax, %eax
|
||||
jmp foo
|
||||
144:
|
||||
.popsection
|
||||
xor %eax, %eax
|
25
gas/testsuite/gas/i386/nop-5.d
Normal file
25
gas/testsuite/gas/i386/nop-5.d
Normal file
@ -0,0 +1,25 @@
|
||||
#objdump: -drw
|
||||
#name: i386 .nop 5
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+ <_start>:
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
+[a-f0-9]+: 85 c0 test %eax,%eax
|
||||
+[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%eax,%eax,1\)
|
||||
+[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%eax,%eax,1\)
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
|
||||
Disassembly of section .altinstr_replacement:
|
||||
|
||||
0+ <.altinstr_replacement>:
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: e9 fc ff ff ff jmp 9 <.altinstr_replacement\+0x9> 9: (R_386_PC)?(DISP)?32 foo
|
||||
#pass
|
19
gas/testsuite/gas/i386/nop-5.s
Normal file
19
gas/testsuite/gas/i386/nop-5.s
Normal file
@ -0,0 +1,19 @@
|
||||
.text
|
||||
_start:
|
||||
xor %eax, %eax
|
||||
140:
|
||||
testl %eax, %eax
|
||||
141:
|
||||
.nop -(((144f-143f)-(141b-140b)) > 0)*((144f-143f)-(141b-140b)),6
|
||||
142:
|
||||
xor %eax, %eax
|
||||
.pushsection .altinstr_replacement,"ax"
|
||||
143:
|
||||
mov %eax, %eax
|
||||
mov %eax, %eax
|
||||
mov %eax, %eax
|
||||
mov %eax, %eax
|
||||
jmp foo
|
||||
144:
|
||||
.popsection
|
||||
xor %eax, %eax
|
17
gas/testsuite/gas/i386/nop-6.d
Normal file
17
gas/testsuite/gas/i386/nop-6.d
Normal file
@ -0,0 +1,17 @@
|
||||
#objdump: -drw
|
||||
#name: i386 .nop 6
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+ <_start>:
|
||||
+[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%eax\)
|
||||
|
||||
Disassembly of section .altinstr_replacement:
|
||||
|
||||
0+ <.altinstr_replacement>:
|
||||
+[a-f0-9]+: 75 fe jne 0 <_start>
|
||||
+[a-f0-9]+: 89 c4 mov %eax,%esp
|
||||
#pass
|
25
gas/testsuite/gas/i386/nop-6.s
Normal file
25
gas/testsuite/gas/i386/nop-6.s
Normal file
@ -0,0 +1,25 @@
|
||||
.macro mknops nr_bytes
|
||||
.nop \nr_bytes, 9
|
||||
.endm
|
||||
|
||||
.macro ALTERNATIVE
|
||||
.L\@_orig_s:
|
||||
.L\@_orig_e:
|
||||
mknops (-(((.L\@_repl_e\()1 - .L\@_repl_s\()1) - (.L\@_orig_e - .L\@_orig_s)) > 0) * ((.L\@_repl_e\()1 - .L\@_repl_s\()1) - (.L\@_orig_e - .L\@_orig_s)))
|
||||
.L\@_orig_p:
|
||||
|
||||
.section .discard, "a", @progbits
|
||||
.byte (.L\@_orig_p - .L\@_orig_s)
|
||||
.byte 0xff + (.L\@_repl_e\()1 - .L\@_repl_s\()1) - (.L\@_orig_p - .L\@_orig_s)
|
||||
|
||||
.section .altinstr_replacement, "ax", @progbits
|
||||
.L\@_repl_s\()1:
|
||||
.L\@_fill_rsb_loop:
|
||||
jnz .L\@_fill_rsb_loop
|
||||
mov %eax, %esp
|
||||
.L\@_repl_e\()1:
|
||||
.endm
|
||||
|
||||
.text
|
||||
_start:
|
||||
ALTERNATIVE
|
4
gas/testsuite/gas/i386/nop-bad-1.l
Normal file
4
gas/testsuite/gas/i386/nop-bad-1.l
Normal file
@ -0,0 +1,4 @@
|
||||
.*: Assembler messages:
|
||||
.*:2: Warning: negative nop control byte, ignored
|
||||
.*:4: Warning: \.space, \.nop or \.fill with negative value, ignored
|
||||
.*:3: Error: invalide single nop size: 20 \(expect within \[0, [0-9]+\]\)
|
4
gas/testsuite/gas/i386/nop-bad-1.s
Normal file
4
gas/testsuite/gas/i386/nop-bad-1.s
Normal file
@ -0,0 +1,4 @@
|
||||
.text
|
||||
.nop 100, -2
|
||||
.nop 100, 20
|
||||
.nop -1
|
32
gas/testsuite/gas/i386/x86-64-nop-1.d
Normal file
32
gas/testsuite/gas/i386/x86-64-nop-1.d
Normal file
@ -0,0 +1,32 @@
|
||||
#source: nop-1.s
|
||||
#objdump: -drw
|
||||
#name: x86-64 .nop 1
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+ <single>:
|
||||
+[a-f0-9]+: 90 nop
|
||||
|
||||
0+1 <pseudo_1>:
|
||||
+[a-f0-9]+: 90 nop
|
||||
|
||||
0+2 <pseudo_8>:
|
||||
+[a-f0-9]+: 0f 1f 84 00 00 00 00 00 nopl 0x0\(%rax,%rax,1\)
|
||||
|
||||
0+a <pseudo_8_4>:
|
||||
+[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%rax\)
|
||||
+[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%rax\)
|
||||
|
||||
0+12 <pseudo_20>:
|
||||
+[a-f0-9]+: 66 0f 1f 84 00 00 00 00 00 nopw 0x0\(%rax,%rax,1\)
|
||||
+[a-f0-9]+: 67 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0\(%eax,%eax,1\)
|
||||
|
||||
0+26 <pseudo_30>:
|
||||
+[a-f0-9]+: 0f 1f 84 00 00 00 00 00 nopl 0x0\(%rax,%rax,1\)
|
||||
+[a-f0-9]+: 67 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0\(%eax,%eax,1\)
|
||||
+[a-f0-9]+: 67 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0\(%eax,%eax,1\)
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
#pass
|
41
gas/testsuite/gas/i386/x86-64-nop-2.d
Normal file
41
gas/testsuite/gas/i386/x86-64-nop-2.d
Normal file
@ -0,0 +1,41 @@
|
||||
#source: nop-2.s
|
||||
#objdump: -drw -Mi8086
|
||||
#name: x86-64 .nop 2
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+ <single>:
|
||||
+[a-f0-9]+: 90 nop
|
||||
|
||||
0+1 <pseudo_1>:
|
||||
+[a-f0-9]+: 90 nop
|
||||
|
||||
0+2 <pseudo_8>:
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
|
||||
0+a <pseudo_8_4>:
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
|
||||
0+12 <pseudo_20>:
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
|
||||
0+26 <pseudo_30>:
|
||||
+[a-f0-9]+: 89 f6 mov %si,%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
+[a-f0-9]+: 8d b4 00 00 lea 0x0\(%si\),%si
|
||||
+[a-f0-9]+: 8d bd 00 00 lea 0x0\(%di\),%di
|
||||
+[a-f0-9]+: 66 31 c0 xor %eax,%eax
|
||||
#pass
|
21
gas/testsuite/gas/i386/x86-64-nop-3.d
Normal file
21
gas/testsuite/gas/i386/x86-64-nop-3.d
Normal file
@ -0,0 +1,21 @@
|
||||
#source: nop-3.s
|
||||
#objdump: -drw
|
||||
#name: x86-64 .nop 3
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+ <_start>:
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
+[a-f0-9]+: 85 c0 test %eax,%eax
|
||||
+[a-f0-9]+: 0f 1f 00 nopl \(%rax\)
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
|
||||
Disassembly of section .altinstr_replacement:
|
||||
|
||||
0+ <.altinstr_replacement>:
|
||||
+[a-f0-9]+: e9 00 00 00 00 jmpq 5 <_start\+0x5> 1: R_X86_64_PLT32 foo-0x4
|
||||
#pass
|
24
gas/testsuite/gas/i386/x86-64-nop-4.d
Normal file
24
gas/testsuite/gas/i386/x86-64-nop-4.d
Normal file
@ -0,0 +1,24 @@
|
||||
#source: nop-4.s
|
||||
#objdump: -drw
|
||||
#name: x86-64 .nop 4
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+ <_start>:
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
+[a-f0-9]+: 85 c0 test %eax,%eax
|
||||
+[a-f0-9]+: 66 0f 1f 84 00 00 00 00 00 nopw 0x0\(%rax,%rax,1\)
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
|
||||
Disassembly of section .altinstr_replacement:
|
||||
|
||||
0+ <.altinstr_replacement>:
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: e9 00 00 00 00 jmpq b <_start\+0xb> 7: R_X86_64_PLT32 foo-0x4
|
||||
#pass
|
26
gas/testsuite/gas/i386/x86-64-nop-5.d
Normal file
26
gas/testsuite/gas/i386/x86-64-nop-5.d
Normal file
@ -0,0 +1,26 @@
|
||||
#source: nop-5.s
|
||||
#objdump: -drw
|
||||
#name: x86-64 .nop 5
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+ <_start>:
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
+[a-f0-9]+: 85 c0 test %eax,%eax
|
||||
+[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\)
|
||||
+[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\)
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
+[a-f0-9]+: 31 c0 xor %eax,%eax
|
||||
|
||||
Disassembly of section .altinstr_replacement:
|
||||
|
||||
0+ <.altinstr_replacement>:
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: 89 c0 mov %eax,%eax
|
||||
+[a-f0-9]+: e9 00 00 00 00 jmpq d <_start\+0xd> 9: R_X86_64_PLT32 foo-0x4
|
||||
#pass
|
18
gas/testsuite/gas/i386/x86-64-nop-6.d
Normal file
18
gas/testsuite/gas/i386/x86-64-nop-6.d
Normal file
@ -0,0 +1,18 @@
|
||||
#source: nop-6.s
|
||||
#objdump: -drw
|
||||
#name: x86-64 .nop 6
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+ <_start>:
|
||||
+[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%rax\)
|
||||
|
||||
Disassembly of section .altinstr_replacement:
|
||||
|
||||
0+ <.altinstr_replacement>:
|
||||
+[a-f0-9]+: 75 fe jne 0 <_start>
|
||||
+[a-f0-9]+: 89 c4 mov %eax,%esp
|
||||
#pass
|
59
gas/write.c
59
gas/write.c
@ -435,6 +435,8 @@ cvt_frag_to_fill (segT sec ATTRIBUTE_UNUSED, fragS *fragP)
|
||||
{
|
||||
switch (fragP->fr_type)
|
||||
{
|
||||
case rs_space_nop:
|
||||
goto skip_align;
|
||||
case rs_align:
|
||||
case rs_align_code:
|
||||
case rs_align_test:
|
||||
@ -443,6 +445,7 @@ cvt_frag_to_fill (segT sec ATTRIBUTE_UNUSED, fragS *fragP)
|
||||
#ifdef HANDLE_ALIGN
|
||||
HANDLE_ALIGN (fragP);
|
||||
#endif
|
||||
skip_align:
|
||||
know (fragP->fr_next != NULL);
|
||||
fragP->fr_offset = (fragP->fr_next->fr_address
|
||||
- fragP->fr_address
|
||||
@ -450,14 +453,18 @@ cvt_frag_to_fill (segT sec ATTRIBUTE_UNUSED, fragS *fragP)
|
||||
if (fragP->fr_offset < 0)
|
||||
{
|
||||
as_bad_where (fragP->fr_file, fragP->fr_line,
|
||||
_("attempt to .org/.space backwards? (%ld)"),
|
||||
_("attempt to .org/.space/.nop backwards? (%ld)"),
|
||||
(long) fragP->fr_offset);
|
||||
fragP->fr_offset = 0;
|
||||
}
|
||||
fragP->fr_type = rs_fill;
|
||||
if (fragP->fr_type == rs_space_nop)
|
||||
fragP->fr_type = rs_fill_nop;
|
||||
else
|
||||
fragP->fr_type = rs_fill;
|
||||
break;
|
||||
|
||||
case rs_fill:
|
||||
case rs_fill_nop:
|
||||
break;
|
||||
|
||||
case rs_leb128:
|
||||
@ -1570,6 +1577,20 @@ compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef md_generate_nops
|
||||
/* Genenerate COUNT bytes of no-op instructions to WHERE. A target
|
||||
backend must override this with proper no-op instructions. */
|
||||
|
||||
static void
|
||||
md_generate_nops (fragS *f ATTRIBUTE_UNUSED,
|
||||
char *where ATTRIBUTE_UNUSED,
|
||||
offsetT count ATTRIBUTE_UNUSED,
|
||||
int control ATTRIBUTE_UNUSED)
|
||||
{
|
||||
as_bad (_("unimplemented .nop directive"));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
write_contents (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
asection *sec,
|
||||
@ -1593,7 +1614,7 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
char *fill_literal;
|
||||
offsetT count;
|
||||
|
||||
gas_assert (f->fr_type == rs_fill);
|
||||
gas_assert (f->fr_type == rs_fill || f->fr_type == rs_fill_nop);
|
||||
if (f->fr_fix)
|
||||
{
|
||||
x = bfd_set_section_contents (stdoutput, sec,
|
||||
@ -1610,9 +1631,35 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
bfd_errmsg (bfd_get_error ()));
|
||||
offset += f->fr_fix;
|
||||
}
|
||||
fill_literal = f->fr_literal + f->fr_fix;
|
||||
|
||||
fill_size = f->fr_var;
|
||||
count = f->fr_offset;
|
||||
fill_literal = f->fr_literal + f->fr_fix;
|
||||
|
||||
if (f->fr_type == rs_fill_nop)
|
||||
{
|
||||
gas_assert (count >= 0 && fill_size == 1);
|
||||
if (count > 0)
|
||||
{
|
||||
char *buf = xmalloc (count);
|
||||
md_generate_nops (f, buf, count, *fill_literal);
|
||||
x = bfd_set_section_contents
|
||||
(stdoutput, sec, buf, (file_ptr) offset,
|
||||
(bfd_size_type) count);
|
||||
if (!x)
|
||||
as_fatal (ngettext ("can't fill %ld byte "
|
||||
"in section %s of %s: '%s'",
|
||||
"can't fill %ld bytes "
|
||||
"in section %s of %s: '%s'",
|
||||
(long) count), (long) count,
|
||||
sec->name, stdoutput->filename,
|
||||
bfd_errmsg (bfd_get_error ()));
|
||||
offset += count;
|
||||
free (buf);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
gas_assert (count >= 0);
|
||||
if (fill_size && count)
|
||||
{
|
||||
@ -2461,6 +2508,7 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
|
||||
break;
|
||||
|
||||
case rs_space:
|
||||
case rs_space_nop:
|
||||
break;
|
||||
|
||||
case rs_machine_dependent:
|
||||
@ -2765,6 +2813,7 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
|
||||
break;
|
||||
|
||||
case rs_space:
|
||||
case rs_space_nop:
|
||||
growth = 0;
|
||||
if (symbolP)
|
||||
{
|
||||
@ -2791,7 +2840,7 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
|
||||
}
|
||||
|
||||
as_warn_where (fragP->fr_file, fragP->fr_line,
|
||||
_(".space or .fill with negative value, ignored"));
|
||||
_(".space, .nop or .fill with negative value, ignored"));
|
||||
fragP->fr_symbol = 0;
|
||||
}
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user