Support for more portable alignment handling in assembly code, based on patches

from Bryan Ford <baford@schirf.cs.utah.edu>:
* read.c (potable): Added balign and p2align, for aligning by bytes or powers
of two independent of what ".align" does for a given target.
* doc/as.texinfo: Document them.
This commit is contained in:
Ken Raeburn 1995-04-26 20:02:18 +00:00
parent 094a7e4392
commit 931a8fab1b
3 changed files with 176 additions and 73 deletions

View File

@ -1,3 +1,12 @@
Wed Apr 26 15:54:10 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
Support for more portable alignment handling in assembly code,
based on patches from Bryan Ford <baford@schirf.cs.utah.edu>:
* read.c (potable): Added balign and p2align, for aligning by
bytes or powers of two independent of what ".align" does for a
given target.
* doc/as.texinfo: Document them.
Tue Apr 25 11:12:04 1995 Rob Savoye <rob@thepub.cygnus.com> Tue Apr 25 11:12:04 1995 Rob Savoye <rob@thepub.cygnus.com>
* configure, configure.in: Look for m68k-*-vxworks* rather than * configure, configure.in: Look for m68k-*-vxworks* rather than

View File

@ -208,7 +208,7 @@ Here is a brief summary of how to invoke @code{@value{AS}}. For details,
@c HPPA has no machine-dependent assembler options (yet). @c HPPA has no machine-dependent assembler options (yet).
@end ifset @end ifset
@ifset SPARC @ifset SPARC
[ -Av6 | -Av7 | -Av8 | -Asparclite | -bump ] [ -Av6 | -Av7 | -Av8 | -Av9 | -Asparclite | -bump ]
@end ifset @end ifset
@ifset Z8000 @ifset Z8000
@c Z8000 has no machine-dependent assembler options @c Z8000 has no machine-dependent assembler options
@ -367,7 +367,7 @@ The following options are available when @code{@value{AS}} is configured
for the SPARC architecture: for the SPARC architecture:
@table @code @table @code
@item -Av6 | -Av7 | -Av8 | -Asparclite @item -Av6 | -Av7 | -Av8 | -Av9 | -Asparclite
Explicitly select a variant of the SPARC architecture. Explicitly select a variant of the SPARC architecture.
@item -bump @item -bump
@ -2653,6 +2653,7 @@ Some machine configurations provide additional directives.
* App-File:: @code{.app-file @var{string}} * App-File:: @code{.app-file @var{string}}
* Ascii:: @code{.ascii "@var{string}"}@dots{} * Ascii:: @code{.ascii "@var{string}"}@dots{}
* Asciz:: @code{.asciz "@var{string}"}@dots{} * Asciz:: @code{.asciz "@var{string}"}@dots{}
* Balign:: @code{.balign @var{abs-expr} , @var{abs-expr}}
* Byte:: @code{.byte @var{expressions}} * Byte:: @code{.byte @var{expressions}}
* Comm:: @code{.comm @var{symbol} , @var{length} } * Comm:: @code{.comm @var{symbol} , @var{length} }
* Data:: @code{.data @var{subsection}} * Data:: @code{.data @var{subsection}}
@ -2704,6 +2705,7 @@ Some machine configurations provide additional directives.
* Nolist:: @code{.nolist} * Nolist:: @code{.nolist}
* Octa:: @code{.octa @var{bignums}} * Octa:: @code{.octa @var{bignums}}
* Org:: @code{.org @var{new-lc} , @var{fill}} * Org:: @code{.org @var{new-lc} , @var{fill}}
* P2align:: @code{.p2align @var{abs-expr} , @var{abs-expr}}
* Psize:: @code{.psize @var{lines}, @var{columns}} * Psize:: @code{.psize @var{lines}, @var{columns}}
* Quad:: @code{.quad @var{bignums}} * Quad:: @code{.quad @var{bignums}}
* Sbttl:: @code{.sbttl "@var{subheading}"} * Sbttl:: @code{.sbttl "@var{subheading}"}
@ -2774,21 +2776,29 @@ but ignores it.
@cindex @code{align} directive @cindex @code{align} directive
Pad the location counter (in the current subsection) to a particular Pad the location counter (in the current subsection) to a particular
storage boundary. The first expression (which must be absolute) is the storage boundary. The first expression (which must be absolute) is the
alignment required, as described below.
The second expression (also absolute) gives the value to be stored in
the padding bytes. It (and the comma) may be omitted. If it is
omitted, the padding bytes are zero.
The way the required alignment is specified varies from system to system.
For the a29k, HPPA, m86k, m88k, w65, sparc, and i386 using ELF format,
the first expression is the
alignment request in bytes. For example @samp{.align 8} advances
the location counter until it is a multiple of 8. If the location counter
is already a multiple of 8, no change is needed.
For other systems, including the i386 using a.out format, it is the
number of low-order zero bits the location counter must have after number of low-order zero bits the location counter must have after
advancement. For example @samp{.align 3} advances the location advancement. For example @samp{.align 3} advances the location
counter until it a multiple of 8. If the location counter is already a counter until it a multiple of 8. If the location counter is already a
multiple of 8, no change is needed. multiple of 8, no change is needed.
@ifset HPPA This inconsistency is due to the different behaviors of the various
For the HPPA, the first expression (which must be absolute) is the native assemblers for these systems which GAS must emulate.
alignment request in bytes. For example @samp{.align 8} advances GAS also provides @code{.balign} and @code{.p2align} directives,
the location counter until it is a multiple of 8. If the location counter described later, which have a consistent behavior across all
is already a multiple of 8, no change is needed. architectures (but are specific to GAS).
@end ifset
The second expression (also absolute) gives the value to be stored in
the padding bytes. It (and the comma) may be omitted. If it is
omitted, the padding bytes are zero.
@node App-File @node App-File
@section @code{.app-file @var{string}} @section @code{.app-file @var{string}}
@ -2826,6 +2836,21 @@ trailing zero byte) into consecutive addresses.
@code{.asciz} is just like @code{.ascii}, but each string is followed by @code{.asciz} is just like @code{.ascii}, but each string is followed by
a zero byte. The ``z'' in @samp{.asciz} stands for ``zero''. a zero byte. The ``z'' in @samp{.asciz} stands for ``zero''.
@node Balign
@section @code{.balign @var{abs-expr} , @var{abs-expr}}
@cindex padding the location counter given number of bytes
@cindex @code{balign} directive
Pad the location counter (in the current subsection) to a particular
storage boundary. The first expression (which must be absolute) is the
alignment request in bytes. For example @samp{.balign 8} advances
the location counter until it is a multiple of 8. If the location counter
is already a multiple of 8, no change is needed.
The second expression (also absolute) gives the value to be stored in
the padding bytes. It (and the comma) may be omitted. If it is
omitted, the padding bytes are zero.
@node Byte @node Byte
@section @code{.byte @var{expressions}} @section @code{.byte @var{expressions}}
@ -3378,6 +3403,22 @@ intervening bytes are filled with @var{fill} which should be an
absolute expression. If the comma and @var{fill} are omitted, absolute expression. If the comma and @var{fill} are omitted,
@var{fill} defaults to zero. @var{fill} defaults to zero.
@node P2align
@section @code{.p2align @var{abs-expr} , @var{abs-expr}}
@cindex padding the location counter given a power of two
@cindex @code{p2align} directive
Pad the location counter (in the current subsection) to a particular
storage boundary. The first expression (which must be absolute) is the
number of low-order zero bits the location counter must have after
advancement. For example @samp{.p2align 3} advances the location
counter until it a multiple of 8. If the location counter is already a
multiple of 8, no change is needed.
The second expression (also absolute) gives the value to be stored in
the padding bytes. It (and the comma) may be omitted. If it is
omitted, the padding bytes are zero.
@node Psize @node Psize
@section @code{.psize @var{lines} , @var{columns}} @section @code{.psize @var{lines} , @var{columns}}
@ -5912,42 +5953,42 @@ The following addressing modes are understood:
@samp{#@var{digits}} @samp{#@var{digits}}
@item Data Register @item Data Register
@samp{d0} through @samp{d7} @samp{%d0} through @samp{%d7}
@item Address Register @item Address Register
@samp{a0} through @samp{a7}@* @samp{%a0} through @samp{%a7}@*
@samp{a7} is also known as @samp{sp}, i.e. the Stack Pointer. @code{a6} @samp{%a7} is also known as @samp{%sp}, i.e. the Stack Pointer. @code{%a6}
is also known as @samp{fp}, the Frame Pointer. is also known as @samp{%fp}, the Frame Pointer.
@item Address Register Indirect @item Address Register Indirect
@samp{a0@@} through @samp{a7@@} @samp{%a0@@} through @samp{%a7@@}
@item Address Register Postincrement @item Address Register Postincrement
@samp{a0@@+} through @samp{a7@@+} @samp{%a0@@+} through @samp{%a7@@+}
@item Address Register Predecrement @item Address Register Predecrement
@samp{a0@@-} through @samp{a7@@-} @samp{%a0@@-} through @samp{%a7@@-}
@item Indirect Plus Offset @item Indirect Plus Offset
@samp{@var{apc}@@(@var{digits})} @samp{%@var{apc}@@(@var{digits})}
@item Index @item Index
@samp{@var{apc}@@(@var{digits},@var{register}:@var{size}:@var{scale})} @samp{%@var{apc}@@(@var{digits},%@var{register}:@var{size}:@var{scale})}
or @samp{@var{apc}@@(@var{register}:@var{size}:@var{scale})} or @samp{%@var{apc}@@(%@var{register}:@var{size}:@var{scale})}
@item Postindex @item Postindex
@samp{@var{apc}@@(@var{digits})@@(@var{digits},@var{register}:@var{size}:@var{scale})} @samp{%@var{apc}@@(@var{digits})@@(@var{digits},%@var{register}:@var{size}:@var{scale})}
or @samp{@var{apc}@@(@var{digits})@@(@var{register}:@var{size}:@var{scale})} or @samp{%@var{apc}@@(@var{digits})@@(%@var{register}:@var{size}:@var{scale})}
@item Preindex @item Preindex
@samp{@var{apc}@@(@var{digits},@var{register}:@var{size}:@var{scale})@@(@var{digits})} @samp{%@var{apc}@@(@var{digits},%@var{register}:@var{size}:@var{scale})@@(@var{digits})}
or @samp{@var{apc}@@(@var{register}:@var{size}:@var{scale})@@(@var{digits})} or @samp{%@var{apc}@@(%@var{register}:@var{size}:@var{scale})@@(@var{digits})}
@item Memory Indirect @item Memory Indirect
@samp{@var{apc}@@(@var{digits})@@(@var{digits})} @samp{%@var{apc}@@(@var{digits})@@(@var{digits})}
@item Absolute @item Absolute
@samp{@var{symbol}}, or @samp{@var{digits}} @samp{@var{symbol}}, or @samp{@var{digits}}
@ -5959,13 +6000,12 @@ by @samp{:b}, @samp{:w}, or @samp{:l}.
@end ignore @end ignore
@end table @end table
For some configurations, especially those where the compiler normally For some configurations, especially those where the compiler normally does not
does not prepend an underscore to the names of user variables, the prepend an underscore to the names of user variables, the assembler requires a
assembler requires a @samp{%} before any use of a register name. This @samp{%} before any use of a register name. This is intended to let the
is intended to let the assembler distinguish between user variables and assembler distinguish between C variables and registers named @samp{a0} through
registers named @samp{a0} through @samp{a7}, and so on. The @samp{%} is @samp{a7}, and so on. The @samp{%} is always accepted, but is not required for
always accepted, but is only required for some configurations, notably certain configurations, notably @samp{sun3}.
@samp{m68k-coff}.
@node M68K-Moto-Syntax @node M68K-Moto-Syntax
@section Motorola Syntax @section Motorola Syntax
@ -5973,53 +6013,43 @@ always accepted, but is only required for some configurations, notably
@cindex Motorola syntax for the 680x0 @cindex Motorola syntax for the 680x0
@cindex alternate syntax for the 680x0 @cindex alternate syntax for the 680x0
The standard Motorola syntax for this chip differs from the syntax The standard Motorola syntax for this chip differs from the syntax already
already discussed (@pxref{M68K-Syntax,,Syntax}). @code{@value{AS}} can discussed (@pxref{M68K-Syntax,,Syntax}). @code{@value{AS}} can accept some
accept some forms of Motorola syntax for operands, even if @sc{mit} syntax is forms of Motorola syntax for operands, even if @sc{mit} syntax is used for
used for other operands in the same instruction. The other operands in the same instruction. The two kinds of syntax are fully
two kinds of syntax are fully compatible; our support for Motorola syntax is compatible; our support for Motorola syntax is simply incomplete at present.
simply incomplete at present.
@ignore
@c FIXME! I can't figure out what this means. Surely the "always" is in some
@c restricted context, for instance. It's not necessary for the preceding text
@c to explain this, so just ignore it for now; re-enable someday when someone
@c has time to explain it better.
, because the Motorola syntax never uses
the @samp{@@} character and the @sc{mit} syntax always does, except in
cases where the syntaxes are identical.
@end ignore
@cindex M680x0 syntax @cindex M680x0 syntax
@cindex syntax, M680x0 @cindex syntax, M680x0
In particular, you may write or generate M68K assembler with the In particular, you may write or generate M68K assembler with the
following conventions: following conventions:
(In the following table @dfn{apc} stands for any of the address (In the following table @dfn{%apc} stands for any of the address registers
registers (@samp{a0} through @samp{a7}), nothing, (@samp{}), the (@samp{%a0} through @samp{%a7}), nothing (@samp{}), the Program Counter
Program Counter (@samp{pc}), or the zero-address relative to the (@samp{%pc}), or the zero-address relative to the program counter
program counter (@samp{zpc}).) (@samp{%zpc}).)
@cindex M680x0 addressing modes @cindex M680x0 addressing modes
@cindex addressing modes, M680x0 @cindex addressing modes, M680x0
The following additional addressing modes are understood: The following additional addressing modes are understood:
@table @dfn @table @dfn
@item Address Register Indirect @item Address Register Indirect
@samp{a0} through @samp{a7}@* @samp{%a0} through @samp{%a7}@*
@samp{a7} is also known as @samp{sp}, i.e. the Stack Pointer. @code{a6} @samp{%a7} is also known as @samp{%sp}, i.e. the Stack Pointer. @code{%a6}
is also known as @samp{fp}, the Frame Pointer. is also known as @samp{%fp}, the Frame Pointer.
@item Address Register Postincrement @item Address Register Postincrement
@samp{(a0)+} through @samp{(a7)+} @samp{(%a0)+} through @samp{(%a7)+}
@item Address Register Predecrement @item Address Register Predecrement
@samp{-(a0)} through @samp{-(a7)} @samp{-(%a0)} through @samp{-(%a7)}
@item Indirect Plus Offset @item Indirect Plus Offset
@samp{@var{digits}(@var{apc})} @samp{@var{digits}(%@var{apc})}
@item Index @item Index
@samp{@var{digits}(@var{apc},(@var{register}.@var{size}*@var{scale}))}@* @samp{@var{digits}(%@var{apc},(%@var{register}.@var{size}*@var{scale}))}@*
or @samp{(@var{apc},@var{register}.@var{size}*@var{scale})}@* or @samp{(%@var{apc},%@var{register}.@var{size}*@var{scale})}@*
In either case, @var{size} and @var{scale} are optional In either case, @var{size} and @var{scale} are optional
(@var{scale} defaults to @samp{1}, @var{size} defaults to @samp{l}). (@var{scale} defaults to @samp{1}, @var{size} defaults to @samp{l}).
@var{scale} can be @samp{1}, @samp{2}, @samp{4}, or @samp{8}. @var{scale} can be @samp{1}, @samp{2}, @samp{4}, or @samp{8}.
@ -6284,10 +6314,11 @@ successively higher architectures as it encounters instructions that
only exist in the higher levels. only exist in the higher levels.
@table @code @table @code
@item -Av6 | -Av7 | -Av8 | -Asparclite @item -Av6 | -Av7 | -Av8 | -Av9 | -Asparclite
@kindex -Av6 @kindex -Av6
@kindex Av7 @kindex Av7
@kindex -Av8 @kindex -Av8
@kindex -Av9
@kindex -Asparclite @kindex -Asparclite
Use one of the @samp{-A} options to select one of the SPARC Use one of the @samp{-A} options to select one of the SPARC
architectures explicitly. If you select an architecture explicitly, architectures explicitly. If you select an architecture explicitly,
@ -6322,6 +6353,10 @@ The Sparc version of @code{@value{AS}} supports the following additional
machine directives: machine directives:
@table @code @table @code
@item .align
@cindex @code{align} directive, SPARC
This must be followed by the desired alignment in bytes.
@item .common @item .common
@cindex @code{common} directive, SPARC @cindex @code{common} directive, SPARC
This must be followed by a symbol name, a positive number, and This must be followed by a symbol name, a positive number, and
@ -6355,8 +6390,13 @@ This is functionally identical to the @code{.space} directive.
@item .word @item .word
@cindex @code{word} directive, SPARC @cindex @code{word} directive, SPARC
On the Sparc, the .word directive produces 32 bit values, On the Sparc, the @code{.word} directive produces 32 bit values,
instead of the 16 bit values it produces on many other machines. instead of the 16 bit values it produces on many other machines.
@item .xword
@cindex @code{xword} directive, SPARC
On the Sparc V9 processor, the @code{.xword} directive produces
64 bit values.
@end table @end table
@end ifset @end ifset
@ -6382,6 +6422,7 @@ instead of the 16 bit values it produces on many other machines.
* i386-Memory:: Memory References * i386-Memory:: Memory References
* i386-jumps:: Handling of Jump Instructions * i386-jumps:: Handling of Jump Instructions
* i386-Float:: Floating Point * i386-Float:: Floating Point
* i386-16bit:: Writing 16-bit Code
* i386-Notes:: Notes * i386-Notes:: Notes
@end menu @end menu
@ -6758,6 +6799,51 @@ of the @samp{fn@dots{}} instructions. For example, @samp{fsave} and
instructions are made equivalent to @samp{f@dots{}} instructions. If instructions are made equivalent to @samp{f@dots{}} instructions. If
@samp{fwait} is desired it must be explicitly coded. @samp{fwait} is desired it must be explicitly coded.
@node i386-16bit
@section Writing 16-bit Code
@cindex i386 16-bit code
@cindex 16-bit code, i386
@cindex real-mode code, i386
@cindex @code{code16} directive, i386
@cindex @code{code32} directive, i386
While GAS normally writes only ``pure'' 32-bit i386 code, it has limited
support for writing code to run in real mode or in 16-bit protected mode
code segments. To do this, insert a @samp{.code16} directive before the
assembly language instructions to be run in 16-bit mode. You can switch
GAS back to writing normal 32-bit code with the @samp{.code32} directive.
GAS understands exactly the same assembly language syntax in 16-bit mode as
in 32-bit mode. The function of any given instruction is exactly the same
regardless of mode, as long as the resulting object code is executed in the
mode for which GAS wrote it. So, for example, the @samp{ret} mnemonic
produces a 32-bit return instruction regardless of whether it is to be run
in 16-bit or 32-bit mode. (If GAS is in 16-bit mode, it will add an
operand size prefix to the instruction to force it to be a 32-bit return.)
This means, for one thing, that you can use GNU CC to write code to be run
in real mode or 16-bit protected mode. Just insert the statement
@samp{asm(".code16");} at the beginning of your C source file, and while
GNU CC will still be generating 32-bit code, GAS will automatically add all
the necessary size prefixes to make that code run in 16-bit mode. Of
course, since GNU CC only writes small-model code (it doesn't know how to
attach segment selectors to pointers like native x86 compilers do), any
16-bit code you write with GNU CC will essentially be limited to a 64K
address space. Also, there will be a code size and performance penalty
due to all the extra address and operand size prefixes GAS has to add to
the instructions.
Note that placing GAS in 16-bit mode does not mean that the resulting
code will necessarily run on a 16-bit pre-80386 processor. To write code
that runs on such a processor, you would have to refrain from using
@emph{any} 32-bit constructs which require GAS to output address or
operand size prefixes. At the moment this would be rather difficult,
because GAS currently supports @emph{only} 32-bit addressing modes: when
writing 16-bit code, it @emph{always} outputs address size prefixes for any
instruction that uses a non-register addressing mode. So you can write
code that runs on 16-bit processors, but only if that code never references
memory.
@node i386-Notes @node i386-Notes
@section Notes @section Notes

View File

@ -195,6 +195,7 @@ static const pseudo_typeS potable[] =
{"align", s_align_ptwo, 0}, {"align", s_align_ptwo, 0},
{"ascii", stringer, 0}, {"ascii", stringer, 0},
{"asciz", stringer, 1}, {"asciz", stringer, 1},
{"balign", s_align_bytes, 0},
/* block */ /* block */
{"byte", cons, 1}, {"byte", cons, 1},
{"comm", s_comm, 0}, {"comm", s_comm, 0},
@ -238,6 +239,7 @@ static const pseudo_typeS potable[] =
{"nolist", listing_list, 0}, /* Turn listing off */ {"nolist", listing_list, 0}, /* Turn listing off */
{"octa", cons, 16}, {"octa", cons, 16},
{"org", s_org, 0}, {"org", s_org, 0},
{"p2align", s_align_ptwo, 0},
{"psize", listing_psize, 0}, /* set paper size */ {"psize", listing_psize, 0}, /* set paper size */
/* print */ /* print */
{"quad", cons, 8}, {"quad", cons, 8},
@ -988,11 +990,18 @@ s_app_line (ignore)
/* The given number is that of the next line. */ /* The given number is that of the next line. */
l = get_absolute_expression () - 1; l = get_absolute_expression () - 1;
new_logical_line ((char *) NULL, l); if (l < 0)
/* Some of the back ends can't deal with non-positive line numbers.
Besides, it's silly. */
as_warn ("Line numbers must be positive; line number %d rejected.", l+1);
else
{
new_logical_line ((char *) NULL, l);
#ifdef LISTING #ifdef LISTING
if (listing) if (listing)
listing_source_line (l); listing_source_line (l);
#endif #endif
}
demand_empty_rest_of_line (); demand_empty_rest_of_line ();
} }
@ -1426,14 +1435,12 @@ s_space (mult)
int mult; int mult;
{ {
expressionS exp; expressionS exp;
long temp_repeat, temp_fill; long temp_fill;
char *p = 0; char *p = 0;
/* Just like .fill, but temp_size = 1 */ /* Just like .fill, but temp_size = 1 */
expression (&exp); expression (&exp);
if (exp.X_op == O_constant if (exp.X_op == O_constant)
/* for testing purposes */
&& 0)
{ {
long repeat; long repeat;
@ -1450,7 +1457,7 @@ s_space (mult)
if (!need_pass_2) if (!need_pass_2)
p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0, p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
temp_repeat, (char *) 0); repeat, (char *) 0);
} }
else else
{ {
@ -1458,13 +1465,14 @@ s_space (mult)
p = frag_var (rs_space, 1, 1, (relax_substateT) 0, p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
make_expr_symbol (&exp), 0L, (char *) 0); make_expr_symbol (&exp), 0L, (char *) 0);
} }
if (get_absolute_expression_and_terminator (&temp_repeat) == ',') SKIP_WHITESPACE ();
if (*input_line_pointer == ',')
{ {
input_line_pointer++;
temp_fill = get_absolute_expression (); temp_fill = get_absolute_expression ();
} }
else else
{ {
input_line_pointer--; /* Backup over what was not a ','. */
temp_fill = 0; temp_fill = 0;
} }
if (p) if (p)