From: Ian Lance Taylor Date: Mon, 22 Jul 1996 17:04:04 +0000 (+0000) Subject: Mon Jul 22 12:46:55 1996 Richard Henderson X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6543a7fb6830635408114c81fb4c160d59e93c3e;p=binutils-gdb.git Mon Jul 22 12:46:55 1996 Richard Henderson * 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. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 74adff5c46f..50d266a38b1 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,32 @@ +Mon Jul 22 12:46:55 1996 Richard Henderson + + * 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 From Andrew Gierth : diff --git a/gas/config/tc-alpha.c b/gas/config/tc-alpha.c index ad890631331..17e865f81b2 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 837b4fe63e6..200cf961843 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 . 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)); +