Mon Jul 22 12:46:55 1996 Richard Henderson <rth@tamu.edu>

* tc-alpha.c: Patches to track current minimum alignment to reduce
	the number of fragments created with frag_align.
	(alpha_current_align): New static variable.
	(s_alpha_text): Reset alignment to 0.
	(s_alpha_data, s_alpha_rdata, s_alpha_sdata): Likewise.
	(s_alpha_stringer, s_alpha_space): New functions.
	(s_alpha_cons, alpha_flush_pending_output): Remove functions.
	(alpha_cons_align): New function to replace both of them.
	(emit_insn): Only align if alpha_current_align is less than 2;
	reset alpha_current_align to 2.
	(s_alpha_gprel32): Likewise.
	(s_alpha_section): New function.  Basically duplicate the other
	alpha section change hooks.  Only define for ELF.
	(s_alpha_float_cons): Simplify alignment handling.
	(md_pseudo_table): Only define "rdata" and "sdata" if OBJ_ECOFF.
	If OBJ_ELF, define "section", "section.s", "sect", and "sect.s".
	Don't define the s_alpha_cons pseudo-ops.  Do define
	s_alpha_stringer and s_alpha_space pseudo-ops.
	(alpha_align): Skip if less than current default alignment.  Set
	default alignment.
	* tc-alpha.h (md_flush_pending_output): Remove.
	(md_cons_align): Add.

	* tc-alpha.c: Add oodles of function description comments.
	(md_bignum_to_chars): Remove; there are no callers.
	(md_show_usage): Mention some more variants.
This commit is contained in:
Ian Lance Taylor 1996-07-22 17:04:04 +00:00
parent 47f0092437
commit 6543a7fb68
3 changed files with 334 additions and 144 deletions

View File

@ -1,3 +1,32 @@
Mon Jul 22 12:46:55 1996 Richard Henderson <rth@tamu.edu>
* tc-alpha.c: Patches to track current minimum alignment to reduce
the number of fragments created with frag_align.
(alpha_current_align): New static variable.
(s_alpha_text): Reset alignment to 0.
(s_alpha_data, s_alpha_rdata, s_alpha_sdata): Likewise.
(s_alpha_stringer, s_alpha_space): New functions.
(s_alpha_cons, alpha_flush_pending_output): Remove functions.
(alpha_cons_align): New function to replace both of them.
(emit_insn): Only align if alpha_current_align is less than 2;
reset alpha_current_align to 2.
(s_alpha_gprel32): Likewise.
(s_alpha_section): New function. Basically duplicate the other
alpha section change hooks. Only define for ELF.
(s_alpha_float_cons): Simplify alignment handling.
(md_pseudo_table): Only define "rdata" and "sdata" if OBJ_ECOFF.
If OBJ_ELF, define "section", "section.s", "sect", and "sect.s".
Don't define the s_alpha_cons pseudo-ops. Do define
s_alpha_stringer and s_alpha_space pseudo-ops.
(alpha_align): Skip if less than current default alignment. Set
default alignment.
* tc-alpha.h (md_flush_pending_output): Remove.
(md_cons_align): Add.
* tc-alpha.c: Add oodles of function description comments.
(md_bignum_to_chars): Remove; there are no callers.
(md_show_usage): Mention some more variants.
Thu Jul 18 15:54:54 1996 Ian Lance Taylor <ian@cygnus.com>
From Andrew Gierth <ANDREWG@microlise.co.uk>:

View File

@ -184,15 +184,21 @@ static void s_alpha_data PARAMS((int));
#ifndef OBJ_ELF
static void s_alpha_comm PARAMS((int));
#endif
#ifdef OBJ_ECOFF
static void s_alpha_rdata PARAMS((int));
static void s_alpha_sdata PARAMS((int));
#endif
#ifdef OBJ_ELF
static void s_alpha_section PARAMS((int));
#endif
static void s_alpha_gprel32 PARAMS((int));
static void s_alpha_float_cons PARAMS((int));
static void s_alpha_proc PARAMS((int));
static void s_alpha_set PARAMS((int));
static void s_alpha_base PARAMS((int));
static void s_alpha_align PARAMS((int));
static void s_alpha_cons PARAMS((int));
static void s_alpha_stringer PARAMS((int));
static void s_alpha_space PARAMS((int));
static void create_literal_section PARAMS((const char *, segT*, symbolS**));
#ifndef OBJ_ELF
@ -308,17 +314,18 @@ static symbolS *alpha_insn_label;
.align 0 will turn this off. */
static int alpha_auto_align_on = 1;
/* The known current alignment of the current section. */
static int alpha_current_align;
/* These are exported to ECOFF code. */
unsigned long alpha_gprmask, alpha_fprmask;
/* Public interface functions */
/*
* This function is called once, at assembler startup time. It sets up
* all the tables, etc. that the MD part of the assembler will need,
* that can be determined before arguments are parsed.
*/
/* This function is called once, at assembler startup time. It sets
up all the tables, etc. that the MD part of the assembler will
need, that can be determined before arguments are parsed. */
void
md_begin ()
@ -439,9 +446,7 @@ md_begin ()
subseg_set(text_section, 0);
}
/*
* The public interface to the instruction assembler.
*/
/* The public interface to the instruction assembler. */
void
md_assemble (str)
@ -470,6 +475,8 @@ md_assemble (str)
assemble_tokens (opname, tok, ntok, alpha_macros_on);
}
/* Round up a section's size to the appropriate boundary. */
valueT
md_section_align (seg, size)
segT seg;
@ -481,12 +488,10 @@ md_section_align (seg, size)
return (size + mask) & ~mask;
}
/*
* Turn a string in input_line_pointer into a floating point constant
* of type type, and store the appropriate bytes in *litP. The number
* of LITTLENUMS emitted is stored in *sizeP. An error message is
* returned, or NULL on OK.
*/
/* Turn a string in input_line_pointer into a floating point constant
of type type, and store the appropriate bytes in *litP. The number
of LITTLENUMS emitted is stored in *sizeP. An error message is
returned, or NULL on OK. */
/* Equal to MAX_PRECISION in atof-ieee.c */
#define MAX_LITTLENUMS 6
@ -550,27 +555,7 @@ md_atof (type, litP, sizeP)
return 0;
}
void
md_bignum_to_chars (buf, bignum, nchars)
char *buf;
LITTLENUM_TYPE *bignum;
int nchars;
{
while (nchars)
{
LITTLENUM_TYPE work = *bignum++;
int nb = CHARS_PER_LITTLENUM;
do
{
*buf++ = work & ((1 << BITS_PER_CHAR) - 1);
if (--nchars == 0)
return;
work >>= BITS_PER_CHAR;
}
while (--nb);
}
}
/* Take care of the target-specific command-line options. */
int
md_parse_option (c, arg)
@ -631,6 +616,8 @@ md_parse_option (c, arg)
return 1;
}
/* Print a description of the command-line options that we accept. */
void
md_show_usage (stream)
FILE *stream;
@ -639,12 +626,14 @@ md_show_usage (stream)
Alpha options:\n\
-32addr treat addresses as 32-bit values\n\
-F lack floating point instructions support\n\
-m21064 | -m21066 | -m21164 | -m21164a | -m21264\n\
-m21064 | -m21066 | -m21164 | -m21164a\n\
-mev4 | -mev45 | -mev5 | -mev56 | -mall\n\
specify variant of Alpha architecture\n",
stream);
}
/* FIXME (inherited): @@ Is this right?? */
/* Decide from what point a pc-relative relocation is relative to,
relative to the pc-relative fixup. Er, relatively speaking. */
long
md_pcrel_from (fixP)
@ -662,6 +651,16 @@ md_pcrel_from (fixP)
}
}
/* Attempt to simplify or even eliminate a fixup. The return value is
ignored; perhaps it was once meaningful, but now it is historical.
To indicate that a fixup has been eliminated, set fixP->fx_done.
For ELF, here it is that we transform the GPDISP_HI16 reloc we used
internally into the GPDISP reloc used externally. We had to do
this so that we'd have the GPDISP_LO16 reloc as a tag to compute
the distance to the "lda" instruction for setting the addend to
GPDISP. */
int
md_apply_fix (fixP, valueP)
fixS *fixP;
@ -875,6 +874,8 @@ md_undefined_symbol(name)
}
#ifdef OBJ_ECOFF
/* @@@ Magic ECOFF bits. */
void
alpha_frob_ecoff_data ()
{
@ -885,11 +886,9 @@ alpha_frob_ecoff_data ()
}
#endif
void
alpha_flush_pending_output ()
{
alpha_insn_label = NULL;
}
/* Hook to remember a recently defined label so that the auto-align
code can adjust the symbol after we know what alignment will be
required. */
void
alpha_define_label (sym)
@ -898,6 +897,9 @@ alpha_define_label (sym)
alpha_insn_label = sym;
}
/* Return true if we must always emit a reloc for a type and false if
there is some hope of resolving it a assembly time. */
int
alpha_force_relocation (f)
fixS *f;
@ -925,6 +927,8 @@ alpha_force_relocation (f)
}
}
/* Return true if we can partially resolve a relocation now. */
int
alpha_fix_adjustable (f)
fixS *f;
@ -947,6 +951,9 @@ alpha_fix_adjustable (f)
/*NOTREACHED*/
}
/* Generate the BFD reloc to be stuck in the object file from the
fixup used internally in the assembler. */
arelent *
tc_gen_reloc (sec, fixp)
asection *sec;
@ -958,7 +965,10 @@ tc_gen_reloc (sec, fixp)
reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
/* Make sure none of our internal relocations make it this far.
They'd better have been fully resolved by this point. */
assert (fixp->fx_r_type < BFD_RELOC_UNUSED);
reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
if (reloc->howto == NULL)
{
@ -1000,6 +1010,12 @@ tc_gen_reloc (sec, fixp)
return reloc;
}
/* Parse a register name off of the input_line and return a register
number. Gets md_undefined_symbol above to do the register name
matching for us.
Only called as a part of processing the ECOFF .frame directive. */
int
tc_get_register (frame)
int frame;
@ -1010,12 +1026,12 @@ tc_get_register (frame)
if (*input_line_pointer == '$')
{
char *s = input_line_pointer;
char c = get_symbol_end();
symbolS *sym = md_undefined_symbol(s);
char c = get_symbol_end ();
symbolS *sym = md_undefined_symbol (s);
*strchr(s, '\0') = c;
if (sym && (framereg = S_GET_VALUE(sym)) <= 31)
goto found;
if (sym && (framereg = S_GET_VALUE (sym)) <= 31)
goto found;
}
as_warn ("frame reg expected, using $%d.", framereg);
@ -1025,9 +1041,7 @@ found:
}
/*
* Parse the arguments to an opcode
*/
/* Parse the arguments to an opcode. */
static int
tokenize_arguments (str, tok, ntok)
@ -1105,10 +1119,8 @@ err:
return -1;
}
/*
* Search forward through all variants of an opcode
* looking for a syntax match.
*/
/* Search forward through all variants of an opcode looking for a
syntax match. */
static const struct alpha_opcode *
find_opcode_match(first_opcode, tok, pntok, pcpumatch)
@ -1211,10 +1223,8 @@ find_opcode_match(first_opcode, tok, pntok, pcpumatch)
return NULL;
}
/*
* Search forward through all variants of a macro
* looking for a syntax match.
*/
/* Search forward through all variants of a macro looking for a syntax
match. */
static const struct alpha_macro *
find_macro_match(first_macro, tok, pntok)
@ -1296,9 +1306,7 @@ find_macro_match(first_macro, tok, pntok)
return NULL;
}
/*
* Insert an operand value into an instruction.
*/
/* Insert an operand value into an instruction. */
static unsigned
insert_operand(insn, operand, val, file, line)
@ -1442,15 +1450,17 @@ assemble_insn(opcode, tok, ntok, insn)
*/
static void
emit_insn(insn)
emit_insn (insn)
struct alpha_insn *insn;
{
char *f;
int i;
/* Take care of alignment duties */
if (alpha_auto_align_on)
if (alpha_auto_align_on && alpha_current_align < 2)
alpha_align (2, (char *) NULL, alpha_insn_label);
if (alpha_current_align > 2)
alpha_current_align = 2;
alpha_insn_label = NULL;
/* Write out the instruction. */
@ -1503,10 +1513,11 @@ emit_insn(insn)
}
}
/*
* Given an opcode name and a pre-tokenized set of arguments,
* assemble the insn, but do not emit it.
*/
/* Given an opcode name and a pre-tokenized set of arguments, assemble
the insn, but do not emit it.
Note that this implies no macros allowed, since we can't store more
than one insn in an insn structure. */
static void
assemble_tokens_to_insn(opname, tok, ntok, insn)
@ -1538,10 +1549,8 @@ assemble_tokens_to_insn(opname, tok, ntok, insn)
as_bad ("unknown opcode `%s'", opname);
}
/*
* Given an opcode name and a pre-tokenized set of arguments,
* take the opcode all the way through emission.
*/
/* Given an opcode name and a pre-tokenized set of arguments, take the
opcode all the way through emission. */
static void
assemble_tokens (opname, tok, ntok, local_macros_on)
@ -1607,6 +1616,8 @@ static const char * const extXh_op[] = { NULL, "extwh", "extlh", "extqh" };
static const char * const mskXl_op[] = { "mskbl", "mskwl", "mskll", "mskql" };
static const char * const mskXh_op[] = { NULL, "mskwh", "msklh", "mskqh" };
/* Implement the ldgp macro. */
static void
emit_ldgp (tok, ntok, unused)
const expressionS *tok;
@ -1667,6 +1678,23 @@ FIXME
#endif /* OBJ_ECOFF || OBJ_ELF */
}
/* Load a (partial) expression into a target register.
If poffset is not null, after the call it will either contain
O_constant 0, or a 16-bit offset appropriate for any MEM format
instruction. In addition, pbasereg will be modified to point to
the base register to use in that MEM format instruction.
In any case, *pbasereg should contain a base register to add to the
expression. This will normally be either AXP_REG_ZERO or
alpha_gp_register. Symbol addresses will always be loaded via $gp,
so "foo($0)" is interpreted as adding the address of foo to $0;
i.e. "ldq $targ, LIT($gp); addq $targ, $0, $targ". Odd, perhaps,
but this is what OSF/1 does.
Finally, the return value is true if the calling macro may emit a
LITUSE reloc if otherwise appropriate. */
static int
load_expression (targreg, exp, pbasereg, poffset)
int targreg;
@ -1900,6 +1928,10 @@ load_expression (targreg, exp, pbasereg, poffset)
return emit_lituse;
}
/* The lda macro differs from the lda instruction in that it handles
most simple expressions, particualrly symbol address loads and
large constants. */
static void
emit_lda (tok, ntok, unused)
const expressionS *tok;
@ -1916,6 +1948,9 @@ emit_lda (tok, ntok, unused)
(void) load_expression (tok[0].X_add_number, &tok[1], &basereg, NULL);
}
/* The ldah macro differs from the ldah instruction in that it has $31
as an implied base register. */
static void
emit_ldah (tok, ntok, unused)
const expressionS *tok;
@ -1931,6 +1966,10 @@ emit_ldah (tok, ntok, unused)
assemble_tokens ("ldah", newtok, 3, 0);
}
/* Handle all "simple" integer register loads -- ldq, ldq_l, ldq_u,
etc. They differ from the real instructions in that they do simple
expressions like the lda macro. */
static void
emit_ir_load (tok, ntok, opname)
const expressionS *tok;
@ -1971,6 +2010,9 @@ emit_ir_load (tok, ntok, opname)
emit_insn (&insn);
}
/* Handle fp register loads, and both integer and fp register stores.
Again, we handle simple expressions. */
static void
emit_loadstore (tok, ntok, opname)
const expressionS *tok;
@ -2021,6 +2063,8 @@ emit_loadstore (tok, ntok, opname)
emit_insn (&insn);
}
/* Load a half-word or byte as an unsigned value. */
static void
emit_ldXu (tok, ntok, vlgsize)
const expressionS *tok;
@ -2052,6 +2096,8 @@ emit_ldXu (tok, ntok, vlgsize)
assemble_tokens (extXl_op[(long)vlgsize], newtok, 3, 1);
}
/* Load a half-word or byte as a signed value. */
static void
emit_ldX (tok, ntok, vlgsize)
const expressionS *tok;
@ -2062,6 +2108,9 @@ emit_ldX (tok, ntok, vlgsize)
assemble_tokens (sextX_op[(long)vlgsize], tok, 1, 1);
}
/* Load an integral value from an unaligned address as an unsigned
value. */
static void
emit_uldXu (tok, ntok, vlgsize)
const expressionS *tok;
@ -2114,6 +2163,10 @@ emit_uldXu (tok, ntok, vlgsize)
assemble_tokens ("or", newtok, 3, 1);
}
/* Load an integral value from an unaligned address as a signed value.
Note that quads should get funneled to the unsigned load since we
don't have to do the sign extension. */
static void
emit_uldX (tok, ntok, vlgsize)
const expressionS *tok;
@ -2124,6 +2177,8 @@ emit_uldX (tok, ntok, vlgsize)
assemble_tokens (sextX_op[(long)vlgsize], tok, 1, 1);
}
/* Implement the ldil macro. */
static void
emit_ldil (tok, ntok, unused)
const expressionS *tok;
@ -2138,6 +2193,8 @@ emit_ldil (tok, ntok, unused)
assemble_tokens ("lda", newtok, ntok, 1);
}
/* Store a half-word or byte. */
static void
emit_stX (tok, ntok, vlgsize)
const expressionS *tok;
@ -2187,6 +2244,8 @@ emit_stX (tok, ntok, vlgsize)
assemble_tokens ("stq_u", newtok, 3, 1);
}
/* Store an integer to an unaligned address. */
static void
emit_ustX (tok, ntok, vlgsize)
const expressionS *tok;
@ -2267,6 +2326,9 @@ emit_ustX (tok, ntok, vlgsize)
assemble_tokens ("stq_u", newtok, 3, 1);
}
/* Sign extend a half-word or byte. The 32-bit sign extend is
implemented as "addl $31, $r, $t" in the opcode table. */
static void
emit_sextX (tok, ntok, vlgsize)
const expressionS *tok;
@ -2289,6 +2351,8 @@ emit_sextX (tok, ntok, vlgsize)
assemble_tokens ("sra", newtok, 3, 1);
}
/* Implement the division and modulus macros. */
static void
emit_division (tok, ntok, symname)
const expressionS *tok;
@ -2392,6 +2456,10 @@ FIXME
}
}
/* The jsr and jmp macros differ from their instruction counterparts
in that they can load the target address and default most
everything. */
static void
emit_jsrjmp (tok, ntok, vopname)
const expressionS *tok;
@ -2446,6 +2514,9 @@ emit_jsrjmp (tok, ntok, vopname)
emit_insn (&insn);
}
/* The ret and jcr instructions differ from their instruction
counterparts in that everything can be defaulted. */
static void
emit_retjcr (tok, ntok, vopname)
const expressionS *tok;
@ -2481,10 +2552,8 @@ emit_retjcr (tok, ntok, vopname)
/* Assembler directives */
/*
* Handle the .text pseudo-op. This is like the usual one, but it
* clears alpha_insn_label and restores auto alignment.
*/
/* Handle the .text pseudo-op. This is like the usual one, but it
clears alpha_insn_label and restores auto alignment. */
static void
s_alpha_text (i)
@ -2494,12 +2563,11 @@ s_alpha_text (i)
s_text (i);
alpha_insn_label = NULL;
alpha_auto_align_on = 1;
alpha_current_align = 0;
}
/*
* Handle the .data pseudo-op. This is like the usual one, but it
* clears alpha_insn_label and restores auto alignment.
*/
/* Handle the .data pseudo-op. This is like the usual one, but it
clears alpha_insn_label and restores auto alignment. */
static void
s_alpha_data (i)
@ -2508,10 +2576,13 @@ s_alpha_data (i)
s_data (i);
alpha_insn_label = NULL;
alpha_auto_align_on = 1;
alpha_current_align = 0;
}
#ifndef OBJ_ELF
/* Handle the OSF/1 .comm pseudo quirks. */
static void
s_alpha_comm (ignore)
int ignore;
@ -2572,7 +2643,12 @@ s_alpha_comm (ignore)
demand_empty_rest_of_line ();
}
#endif
#endif /* ! OBJ_ELF */
#ifdef OBJ_ECOFF
/* Handle the .rdata pseudo-op. This is like the usual one, but it
clears alpha_insn_label and restores auto alignment. */
static void
s_alpha_rdata (ignore)
@ -2585,8 +2661,12 @@ s_alpha_rdata (ignore)
demand_empty_rest_of_line ();
alpha_insn_label = NULL;
alpha_auto_align_on = 1;
alpha_current_align = 0;
}
/* Handle the .sdata pseudo-op. This is like the usual one, but it
clears alpha_insn_label and restores auto alignment. */
static void
s_alpha_sdata (ignore)
int ignore;
@ -2598,7 +2678,29 @@ s_alpha_sdata (ignore)
demand_empty_rest_of_line ();
alpha_insn_label = NULL;
alpha_auto_align_on = 1;
alpha_current_align = 0;
}
#endif
#ifdef OBJ_ELF
/* Handle the .section pseudo-op. This is like the usual one, but it
clears alpha_insn_label and restores auto alignment. */
static void
s_alpha_section (ignore)
int ignore;
{
obj_elf_section (ignore);
alpha_insn_label = NULL;
alpha_auto_align_on = 1;
alpha_current_align = 0;
}
#endif
/* Handle the .gprel32 pseudo op. */
static void
s_alpha_gprel32 (ignore)
@ -2637,8 +2739,10 @@ s_alpha_gprel32 (ignore)
}
#endif
if (alpha_auto_align_on)
if (alpha_auto_align_on && alpha_current_align < 2)
alpha_align (2, (char *) NULL, alpha_insn_label);
if (alpha_current_align > 2)
alpha_current_align = 2;
alpha_insn_label = NULL;
p = frag_more (4);
@ -2647,54 +2751,54 @@ s_alpha_gprel32 (ignore)
&e, 0, BFD_RELOC_GPREL32);
}
/*
* Handle floating point allocation pseudo-ops. This is like the
* generic vresion, but it makes sure the current label, if any, is
* correctly aligned.
*/
/* Handle floating point allocation pseudo-ops. This is like the
generic vresion, but it makes sure the current label, if any, is
correctly aligned. */
static void
s_alpha_float_cons (type)
int type;
{
if (alpha_auto_align_on)
int log_size;
switch (type)
{
int log_size;
default:
case 'f':
case 'F':
log_size = 2;
break;
switch (type)
{
default:
case 'f':
case 'F':
log_size = 2;
break;
case 'd':
case 'D':
case 'G':
log_size = 3;
break;
case 'd':
case 'D':
case 'G':
log_size = 3;
break;
case 'x':
case 'X':
case 'p':
case 'P':
log_size = 4;
break;
}
alpha_align (log_size, (char *) NULL, alpha_insn_label);
case 'x':
case 'X':
case 'p':
case 'P':
log_size = 4;
break;
}
if (alpha_auto_align_on && alpha_current_align < log_size)
alpha_align (log_size, (char *) NULL, alpha_insn_label);
if (alpha_current_align > log_size)
alpha_current_align = log_size;
alpha_insn_label = NULL;
float_cons (type);
}
/* Handle the .proc pseudo op. We don't really do much with it except
parse it. */
static void
s_alpha_proc (is_static)
int is_static;
{
/* XXXX Align to cache linesize XXXXX */
char *name;
char c;
char *p;
@ -2726,6 +2830,9 @@ s_alpha_proc (is_static)
demand_empty_rest_of_line ();
}
/* Handle the .set pseudo op. This is used to turn on and off most of
the assembler features. */
static void
s_alpha_set (x)
int x;
@ -2761,6 +2868,9 @@ s_alpha_set (x)
demand_empty_rest_of_line ();
}
/* Handle the .base pseudo op. This changes the assembler's notion of
the $gp register. */
static void
s_alpha_base (ignore)
int ignore;
@ -2792,11 +2902,9 @@ s_alpha_base (ignore)
demand_empty_rest_of_line ();
}
/*
* Handle the .align pseudo-op. This aligns to a power of two. It
* also adjusts any current instruction label. We treat this the same
* way the MIPS port does: .align 0 turns off auto alignment.
*/
/* Handle the .align pseudo-op. This aligns to a power of two. It
also adjusts any current instruction label. We treat this the same
way the MIPS port does: .align 0 turns off auto alignment. */
static void
s_alpha_align (ignore)
@ -2840,22 +2948,46 @@ s_alpha_align (ignore)
demand_empty_rest_of_line ();
}
/*
* Handle data allocation pseudo-ops. This is like the generic
* version, but it makes sure the current label, if any, is correctly
* aligned.
*/
/* Hook the normal string processor to reset known alignment. */
static void
s_alpha_cons (log_size)
int log_size;
s_alpha_stringer (terminate)
int terminate;
{
if (alpha_auto_align_on && log_size > 0)
alpha_align (log_size, (char *) NULL, alpha_insn_label);
alpha_current_align = 0;
alpha_insn_label = NULL;
cons (1 << log_size);
stringer (terminate);
}
/* Hook the normal space processing to reset known alignment. */
static void
s_alpha_space (ignore)
int ignore;
{
alpha_current_align = 0;
alpha_insn_label = NULL;
s_space (ignore);
}
/* Hook into cons for auto-alignment. */
void
alpha_cons_align (size)
int size;
{
int log_size;
log_size = 0;
while ((size >>= 1) != 0)
++log_size;
if (alpha_auto_align_on && alpha_current_align < log_size)
alpha_align (log_size, (char *) NULL, alpha_insn_label);
if (alpha_current_align > log_size)
alpha_current_align = log_size;
alpha_insn_label = NULL;
}
/* The macro table */
@ -3096,8 +3228,16 @@ const pseudo_typeS md_pseudo_table[] =
#endif
{"text", s_alpha_text, 0},
{"data", s_alpha_data, 0},
#ifdef OBJ_ECOFF
{"rdata", s_alpha_rdata, 0},
{"sdata", s_alpha_sdata, 0},
#endif
#ifdef OBJ_ELF
{"section", s_alpha_section, 0},
{"section.s", s_alpha_section, 0},
{"sect", s_alpha_section, 0},
{"sect.s", s_alpha_section, 0},
#endif
{"gprel32", s_alpha_gprel32, 0},
{"t_floating", s_alpha_float_cons, 'd'},
{"s_floating", s_alpha_float_cons, 'f'},
@ -3118,17 +3258,15 @@ const pseudo_typeS md_pseudo_table[] =
{"eflag", s_ignore, 0},
{"align", s_alpha_align, 0},
{"byte", s_alpha_cons, 0},
{"hword", s_alpha_cons, 1},
{"int", s_alpha_cons, 2},
{"long", s_alpha_cons, 2},
{"octa", s_alpha_cons, 4},
{"quad", s_alpha_cons, 3},
{"short", s_alpha_cons, 1},
{"word", s_alpha_cons, 1},
{"double", s_alpha_float_cons, 'd'},
{"float", s_alpha_float_cons, 'f'},
{"single", s_alpha_float_cons, 'f'},
{"ascii", s_alpha_stringer, 0},
{"asciz", s_alpha_stringer, 1},
{"string", s_alpha_stringer, 1},
{"space", s_alpha_space, 0},
{"skip", s_alpha_space, 0},
{"zero", s_alpha_space, 0},
/* We don't do any optimizing, so we can safely ignore these. */
{"noalias", s_ignore, 0},
@ -3138,6 +3276,8 @@ const pseudo_typeS md_pseudo_table[] =
};
/* Build a BFD section with its flags set appropriately for the .lita,
.lit8, or .lit4 sections. */
static void
create_literal_section (name, secp, symp)
@ -3161,6 +3301,9 @@ create_literal_section (name, secp, symp)
#ifndef OBJ_ELF
/* @@@ GP selection voodoo. All of this seems overly complicated and
unnecessary; which is the primary reason I nixed it for ELF. */
static inline void
maybe_set_gp (sec)
asection *sec;
@ -3183,8 +3326,9 @@ select_gp_value ()
/* Select the smallest VMA of these existing sections. */
maybe_set_gp (alpha_lita_section);
/* maybe_set_gp (sdata); Was disabled before -- should we use it? */
#if 0
/* These were disabled before -- should we use them? */
maybe_set_gp (sdata);
maybe_set_gp (lit8_sec);
maybe_set_gp (lit4_sec);
#endif
@ -3202,12 +3346,20 @@ select_gp_value ()
}
#endif /* !OBJ_ELF */
/* Called internally to handle all alignment needs. This takes care
of eliding calls to frag_align if'n the cached current alignment
says we've already got it, as well as taking care of the auto-align
feature wrt labels. */
static void
alpha_align (n, pfill, label)
int n;
char *pfill;
symbolS *label;
{
if (alpha_current_align >= n)
return;
if (pfill == NULL)
{
if (n > 2
@ -3220,7 +3372,8 @@ alpha_align (n, pfill, label)
section. The DEC assembler silently fills with unaligned
no-op instructions. This will zero-fill, then nop-fill
with proper alignment. */
frag_align (2, 0);
if (alpha_current_align < 2)
frag_align (2, 0);
frag_align_pattern (n, nop, sizeof nop);
}
else
@ -3229,6 +3382,8 @@ alpha_align (n, pfill, label)
else
frag_align (n, *pfill);
alpha_current_align = n;
if (label != NULL)
{
assert (S_GET_SEGMENT (label) == now_seg);

View File

@ -1,5 +1,5 @@
/* This file is tc-alpha.h
Copyright (C) 1994 Free Software Foundation, Inc.
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
Written by Ken Raeburn <raeburn@cygnus.com>.
This file is part of GAS, the GNU Assembler.
@ -15,8 +15,9 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
along with GAS; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
#define TC_ALPHA
@ -49,9 +50,13 @@ extern valueT alpha_gp_value;
(as_fatal("estimate_size_before_relax called"),1)
#define md_operand(x) ((void) (0))
#define md_undefined_symbol(name) (0)
#define LOCAL_LABEL(name) ((name)[0] == 'L')
#ifdef OBJ_ECOFF
#define LOCAL_LABEL(name) ((name)[0] == 'L')
#endif
#ifdef OBJ_ELF
#define LOCAL_LABEL(name) ((name)[0] == '$')
#define FAKE_LABEL_NAME "$L0\001"
#endif
#define md_number_to_chars number_to_chars_littleendian
@ -61,5 +66,6 @@ extern void alpha_frob_ecoff_data PARAMS ((void));
#define tc_frob_label(sym) alpha_define_label (sym)
extern void alpha_define_label PARAMS ((struct symbol *));
#define md_flush_pending_output alpha_flush_pending_output
extern void alpha_flush_pending_output PARAMS ((void));
#define md_cons_align(nbytes) alpha_cons_align (nbytes)
extern void alpha_cons_align PARAMS ((int));