Fix #69 by making the NASM preproc and parser use the yasm built-in

alignment bytecode rather than just times'ing a NOP.  This generates better
NOP code.

The new align only triggers when the NASM align directive is used unadorned
or with nop as the parameter (e.g. "align 16" or "align 16, nop").  Other
uses, including all uses of balign, maintain their old NASM behavior.  This
is somewhat useful if you still want a string of NOPs rather than more
optimized instruction patterns: just use "balign X, nop" rather than
"align X".  The new align also follows the GAS behavior of increasing the
section's alignment to be the specified alignment (if not already larger).

While I was in here, I found and fixed a bug in 16-bit alignment generation
(typo).  I also changed the x86 32-bit code alignment fill pattern per
suggestions in the AMD x86 code optimization manual.

* nasm-bison.y: Implement a new [align] directive that can take a single
parameter (the alignment) and generate a nop-generating align bytecode.
* standard.mac: Change align macro to generate [align] if the second
macro parameter is nonexistent or "nop".
* x86arch.c (x86_get_fill): Update 32-bit fill pattern and fix bug in 16-bit
fill pattern.

svn path=/trunk/yasm/; revision=1389
0.5.0rc2
Peter Johnson 19 years ago
parent b6f90d8191
commit f908f39d0f
  1. 138
      modules/arch/x86/tests/gas32/align32.hex
  2. 19
      modules/arch/x86/x86arch.c
  3. 572
      modules/objfmts/coff/tests/x86id.hex
  4. 588
      modules/objfmts/elf/tests/elf-x86id.hex
  5. 39
      modules/parsers/nasm/nasm-bison.y
  6. 6
      modules/parsers/nasm/tests/Makefile.inc
  7. 4
      modules/parsers/nasm/tests/alignnop16.asm
  8. 0
      modules/parsers/nasm/tests/alignnop16.errwarn
  9. 17
      modules/parsers/nasm/tests/alignnop16.hex
  10. 4
      modules/parsers/nasm/tests/alignnop32.asm
  11. 0
      modules/parsers/nasm/tests/alignnop32.errwarn
  12. 17
      modules/parsers/nasm/tests/alignnop32.hex
  13. 4
      modules/preprocs/nasm/standard.mac

@ -80,84 +80,84 @@ eb
90
ff
ff
8d
b4
26
00
00
00
00
8d
bc
27
00
00
00
00
eb
0c
90
90
90
90
90
90
90
90
90
90
90
90
ff
ff
ff
8d
b6
00
00
00
00
8d
bc
27
00
00
00
00
eb
0b
90
90
90
90
90
90
90
90
90
90
90
ff
ff
ff
ff
8d
b6
00
00
00
00
8d
bf
00
00
00
00
eb
0a
90
90
90
90
90
90
90
90
90
90
ff
ff
ff
ff
ff
8d
74
26
00
8d
bc
27
00
00
00
00
eb
09
90
90
90
90
90
90
90
90
90
ff
ff
ff
ff
ff
ff
8d
76
00
8d
bc
27
00
00
00
00
eb
08
90
90
90
90
90
90
90
90
ff
ff
ff
@ -165,15 +165,15 @@ ff
ff
ff
ff
89
f6
8d
bc
27
00
00
00
00
eb
07
90
90
90
90
90
90
90
ff
ff
ff

@ -159,7 +159,7 @@ x86_get_fill(const yasm_arch *arch)
"\x8d\x74\x00" /* 7 - lea si, [si+byte 0] */
"\x8d\xbd\x00\x00", /* lea di, [di+word 0] */
"\x8d\xb4\x00\x00" /* 8 - lea si, [si+word 0] */
"\x8d\xbd\x00\x00" /* lea di, [di+word 0] */
"\x8d\xbd\x00\x00", /* lea di, [di+word 0] */
"\xeb\x07\x90\x90\x90\x90\x90" /* 9 - jmp $+9; nop fill */
"\x90\x90",
"\xeb\x08\x90\x90\x90\x90\x90" /* 10 - jmp $+10; nop fill */
@ -187,6 +187,8 @@ x86_get_fill(const yasm_arch *arch)
"\x8d\xb4\x26\x00\x00\x00\x00", /* 7 - lea esi, [esi*1+dword 0] */
"\x90" /* 8 - nop */
"\x8d\xb4\x26\x00\x00\x00\x00", /* lea esi, [esi*1+dword 0] */
#if 0
/* GAS uses these */
"\x89\xf6" /* 9 - mov esi, esi */
"\x8d\xbc\x27\x00\x00\x00\x00", /* lea edi, [edi*1+dword 0] */
"\x8d\x76\x00" /* 10 - lea esi, [esi+byte 0] */
@ -199,6 +201,21 @@ x86_get_fill(const yasm_arch *arch)
"\x8d\xbc\x27\x00\x00\x00\x00", /* lea edi, [edi*1+dword 0]*/
"\x8d\xb4\x26\x00\x00\x00\x00" /* 14 - lea esi, [esi*1+dword 0]*/
"\x8d\xbc\x27\x00\x00\x00\x00", /* lea edi, [edi*1+dword 0]*/
#else
/* But on newer processors, these are recommended */
"\xeb\x07\x90\x90\x90\x90\x90" /* 9 - jmp $+9; nop fill */
"\x90\x90",
"\xeb\x08\x90\x90\x90\x90\x90" /* 10 - jmp $+10; nop fill */
"\x90\x90\x90",
"\xeb\x09\x90\x90\x90\x90\x90" /* 11 - jmp $+11; nop fill */
"\x90\x90\x90\x90",
"\xeb\x0a\x90\x90\x90\x90\x90" /* 12 - jmp $+12; nop fill */
"\x90\x90\x90\x90\x90",
"\xeb\x0b\x90\x90\x90\x90\x90" /* 13 - jmp $+13; nop fill */
"\x90\x90\x90\x90\x90\x90",
"\xeb\x0c\x90\x90\x90\x90\x90" /* 14 - jmp $+14; nop fill */
"\x90\x90\x90\x90\x90\x90\x90",
#endif
"\xeb\x0d\x90\x90\x90\x90\x90" /* 15 - jmp $+15; nop fill */
"\x90\x90\x90\x90\x90\x90\x90\x90"
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -596,6 +596,45 @@ nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
vp->param = NULL;
}
parser_nasm->prev_bc = yasm_section_bcs_last(parser_nasm->cur_section);
} else if (yasm__strcasecmp(name, "align") == 0) {
/*@only@*/ yasm_expr *boundval;
/*@depedent@*/ yasm_intnum *boundintn;
/* it can be just an ID or a complete expression, so handle both. */
vp = yasm_vps_first(valparams);
if (vp->val)
boundval = p_expr_new_ident(yasm_expr_sym(
yasm_symtab_use(p_symtab, vp->val, line)));
else if (vp->param) {
boundval = vp->param;
vp->param = NULL;
}
/* Largest .align in the section specifies section alignment.
* Note: this doesn't match NASM behavior, but is a lot more
* intelligent!
*/
boundintn = yasm_expr_get_intnum(&boundval, NULL);
if (boundintn) {
unsigned long boundint = yasm_intnum_get_uint(boundintn);
/* Alignments must be a power of two. */
if ((boundint & (boundint - 1)) == 0) {
if (boundint > yasm_section_get_align(parser_nasm->cur_section))
yasm_section_set_align(parser_nasm->cur_section, boundint,
cur_line);
}
}
/* As this directive is called only when nop is used as fill, always
* use arch (nop) fill.
*/
parser_nasm->prev_bc =
yasm_section_bcs_append(parser_nasm->cur_section,
yasm_bc_create_align(boundval, NULL, NULL,
/*yasm_section_is_code(parser_nasm->cur_section) ?*/
yasm_arch_get_fill(parser_nasm->arch)/* : NULL*/,
cur_line));
} else if (yasm__strcasecmp(name, "cpu") == 0) {
yasm_vps_foreach(vp, valparams) {
if (vp->val)

@ -3,6 +3,12 @@
TESTS += modules/parsers/nasm/tests/nasm_test.sh
EXTRA_DIST += modules/parsers/nasm/tests/nasm_test.sh
EXTRA_DIST += modules/parsers/nasm/tests/alignnop16.asm
EXTRA_DIST += modules/parsers/nasm/tests/alignnop16.errwarn
EXTRA_DIST += modules/parsers/nasm/tests/alignnop16.hex
EXTRA_DIST += modules/parsers/nasm/tests/alignnop32.asm
EXTRA_DIST += modules/parsers/nasm/tests/alignnop32.errwarn
EXTRA_DIST += modules/parsers/nasm/tests/alignnop32.hex
EXTRA_DIST += modules/parsers/nasm/tests/endcomma.asm
EXTRA_DIST += modules/parsers/nasm/tests/endcomma.errwarn
EXTRA_DIST += modules/parsers/nasm/tests/endcomma.hex

@ -0,0 +1,4 @@
bits 16
mov eax,32
align 16
ret

@ -0,0 +1,17 @@
66
b8
20
00
00
00
eb
08
90
90
90
90
90
90
90
90
c3

@ -0,0 +1,4 @@
bits 32
mov eax,32
align 16
ret

@ -0,0 +1,17 @@
b8
20
00
00
00
eb
09
90
90
90
90
90
90
90
90
90
c3

@ -65,7 +65,11 @@ __SECT__
%endmacro
%imacro align 1-2+.nolist nop
%ifidni %2,nop
[align %1]
%else
times ($$-$) & ((%1)-1) %2
%endif
%endmacro
%imacro alignb 1-2+.nolist resb 1
times ($$-$) & ((%1)-1) %2

Loading…
Cancel
Save