Mon Jul 22 12:46:55 1996 Richard Henderson <rth@tamu.edu>
authorIan Lance Taylor <ian@airs.com>
Mon, 22 Jul 1996 17:04:04 +0000 (17:04 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 22 Jul 1996 17:04:04 +0000 (17:04 +0000)
* 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.

gas/ChangeLog
gas/config/tc-alpha.c
gas/config/tc-alpha.h

index 74adff5..50d266a 100644 (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>:
index ad89063..17e865f 100644 (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;
 
 \f
 /* 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:
 }
 
 \f
-/* 
- * 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)
 \f
 /* 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;
+}
 \f
 /* 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[] =
 };
 
 \f
+/* 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);
index 837b4fe..200cf96 100644 (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));
+