aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog29
-rw-r--r--gas/config/tc-alpha.c427
-rw-r--r--gas/config/tc-alpha.h22
3 files changed, 334 insertions, 144 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 74adff5..50d266a 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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>:
diff --git a/gas/config/tc-alpha.c b/gas/config/tc-alpha.c
index ad89063..17e865f 100644
--- a/gas/config/tc-alpha.c
+++ b/gas/config/tc-alpha.c
@@ -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)
- {
- default:
- case 'f':
- case 'F':
- log_size = 2;
- break;
+ int log_size;
- case 'd':
- case 'D':
- case 'G':
- log_size = 3;
- break;
+ switch (type)
+ {
+ default:
+ case 'f':
+ case 'F':
+ log_size = 2;
+ break;
- case 'x':
- case 'X':
- case 'p':
- case 'P':
- log_size = 4;
- break;
- }
+ case 'd':
+ case 'D':
+ case 'G':
+ log_size = 3;
+ 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);
diff --git a/gas/config/tc-alpha.h b/gas/config/tc-alpha.h
index 837b4fe..200cf96 100644
--- a/gas/config/tc-alpha.h
+++ b/gas/config/tc-alpha.h
@@ -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));
+