* config/tc-alpha.c (struct alpha_insn): Make sequence scalar long.
authorRichard Henderson <rth@redhat.com>
Wed, 5 Sep 2001 02:39:43 +0000 (02:39 +0000)
committerRichard Henderson <rth@redhat.com>
Wed, 5 Sep 2001 02:39:43 +0000 (02:39 +0000)
  (MACRO_LITERAL, MACRO_BASE, MACRO_BYTOFF, MACRO_JSR): Remove.
  (alpha_macros): Remove occurrences of same.
  (O_lituse_addr, O_gprel): New.
  (DUMMY_RELOC_LITUSE_*): New.
  (s_alpha_ucons, s_alpha_arch): Prototype.
  (alpha_reloc_op): Construct elements via DEF macro.
  (ALPHA_RELOC_SEQUENCE_OK): Remove.
  (struct alpha_reloc_tag): Rename from alpha_literal_tag; rename
  members to not be literal specific.
  (next_sequence_num): New.
  (md_apply_fix3): Cope with missing GPDISP_LO16.  Adjust for
  added/removed BFD relocations.
  (alpha_force_relocation, alpha_fix_adjustable): Likewise.
  (alpha_adjust_symtab_relocs): Handle GPDISP relocs as well.
  (tokenize_arguments): Parse ! relocations properly.
  (find_macro_match): Delete unused macro argument types.
  (assemble_insn): Add reloc parameter; emit that instead of the
  default as appropriate.
  (get_alpha_reloc_tag): New.  Split from ...
  (emit_insn): ... here.  Allocate a reloc tag for GPDISP.
  (assemble_tokens): Don't search macros if user relocation present.
  Copy reloc sequence number to insn struct.
  (emit_ldgp): Remove user reloc handling.
  (load_expression, emit_lda, emit_ldah, emit_ir_load): Likewise.
  (emit_loadstore, emit_ldXu, emit_ldil, emit_stX): Likewise.
  (emit_sextX, emit_division, emit_jsrjmp, emit_retjcr): Likewise.
  * config/tc-alpha.h (tc_adjust_symtab): Always define.
  (struct alpha_fix_tag): Name members less literal specific.

  * gas/alpha/alpha.exp: New file.
  * gas/alpha/elf-reloc-1.[sd]: New test.
  * gas/alpha/elf-reloc-2.[sl]: New test.
  * gas/alpha/elf-reloc-3.[sl]: New test.
  * gas/alpha/elf-reloc-4.[sd]: New test.
  * gas/alpha/fp.exp: Remove file.
  * gas/alpha/fp.s: Output to .data not .rdata.
  * gas/alpha/fp.d: Adjust to match.

16 files changed:
gas/ChangeLog
gas/config/tc-alpha.c
gas/config/tc-alpha.h
gas/testsuite/ChangeLog
gas/testsuite/gas/alpha/alpha.exp [new file with mode: 0644]
gas/testsuite/gas/alpha/elf-reloc-1.d [new file with mode: 0644]
gas/testsuite/gas/alpha/elf-reloc-1.s [new file with mode: 0644]
gas/testsuite/gas/alpha/elf-reloc-2.l [new file with mode: 0644]
gas/testsuite/gas/alpha/elf-reloc-2.s [new file with mode: 0644]
gas/testsuite/gas/alpha/elf-reloc-3.l [new file with mode: 0644]
gas/testsuite/gas/alpha/elf-reloc-3.s [new file with mode: 0644]
gas/testsuite/gas/alpha/elf-reloc-4.d [new file with mode: 0644]
gas/testsuite/gas/alpha/elf-reloc-4.s [new file with mode: 0644]
gas/testsuite/gas/alpha/fp.d
gas/testsuite/gas/alpha/fp.exp [deleted file]
gas/testsuite/gas/alpha/fp.s

index 0e61a6b..65232cc 100644 (file)
@@ -1,3 +1,35 @@
+2001-08-04  Richard Henderson  <rth@redhat.com>
+
+       * config/tc-alpha.c (struct alpha_insn): Make sequence scalar long.
+       (MACRO_LITERAL, MACRO_BASE, MACRO_BYTOFF, MACRO_JSR): Remove.
+       (alpha_macros): Remove occurrences of same.
+       (O_lituse_addr, O_gprel): New.
+       (DUMMY_RELOC_LITUSE_*): New.
+       (s_alpha_ucons, s_alpha_arch): Prototype.
+       (alpha_reloc_op): Construct elements via DEF macro.
+       (ALPHA_RELOC_SEQUENCE_OK): Remove.
+       (struct alpha_reloc_tag): Rename from alpha_literal_tag; rename
+       members to not be literal specific.
+       (next_sequence_num): New.
+       (md_apply_fix3): Cope with missing GPDISP_LO16.  Adjust for
+       added/removed BFD relocations.
+       (alpha_force_relocation, alpha_fix_adjustable): Likewise.
+       (alpha_adjust_symtab_relocs): Handle GPDISP relocs as well.
+       (tokenize_arguments): Parse ! relocations properly.
+       (find_macro_match): Delete unused macro argument types.
+       (assemble_insn): Add reloc parameter; emit that instead of the
+       default as appropriate.
+       (get_alpha_reloc_tag): New.  Split from ...
+       (emit_insn): ... here.  Allocate a reloc tag for GPDISP.
+       (assemble_tokens): Don't search macros if user relocation present.
+       Copy reloc sequence number to insn struct.
+       (emit_ldgp): Remove user reloc handling.
+       (load_expression, emit_lda, emit_ldah, emit_ir_load): Likewise.
+       (emit_loadstore, emit_ldXu, emit_ldil, emit_stX): Likewise.
+       (emit_sextX, emit_division, emit_jsrjmp, emit_retjcr): Likewise.
+       * config/tc-alpha.h (tc_adjust_symtab): Always define.
+       (struct alpha_fix_tag): Name members less literal specific.
+
 Tue Sep  4 20:01:19 2001  Jeffrey A Law  (law@cygnus.com)
 
        * tc-h8300.c (tc_gen_reloc): Give an error if we try to take the
index add17c8..9c62923 100644 (file)
@@ -81,7 +81,7 @@ struct alpha_insn {
   unsigned insn;
   int nfixups;
   struct alpha_fixup fixups[MAX_INSN_FIXUPS];
-  unsigned sequence[MAX_INSN_FIXUPS];
+  long sequence;
 };
 
 enum alpha_macro_arg {
@@ -92,10 +92,6 @@ enum alpha_macro_arg {
   MACRO_CPIR,
   MACRO_FPR,
   MACRO_EXP,
-  MACRO_LITERAL,
-  MACRO_BASE,
-  MACRO_BYTOFF,
-  MACRO_JSR
 };
 
 struct alpha_macro {
@@ -110,19 +106,29 @@ struct alpha_macro {
 #define O_pregister    O_md1   /* O_register, in parentheses */
 #define O_cpregister   O_md2   /* + a leading comma */
 
-#ifdef RELOC_OP_P
 /* Note, the alpha_reloc_op table below depends on the ordering
-   of O_literal .. O_gprelow.  */
+   of O_literal .. O_gpre16.  */
 #define O_literal      O_md3   /* !literal relocation */
-#define O_lituse_base  O_md4   /* !lituse_base relocation */
-#define O_lituse_bytoff        O_md5   /* !lituse_bytoff relocation */
-#define O_lituse_jsr   O_md6   /* !lituse_jsr relocation */
-#define O_gpdisp       O_md7   /* !gpdisp relocation */
-#define O_gprelhigh    O_md8   /* !gprelhigh relocation */
-#define O_gprellow     O_md9   /* !gprellow relocation */
-
-#define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_gprellow)
-#endif
+#define O_lituse_addr  O_md4   /* !lituse_addr relocation */
+#define O_lituse_base  O_md5   /* !lituse_base relocation */
+#define O_lituse_bytoff        O_md6   /* !lituse_bytoff relocation */
+#define O_lituse_jsr   O_md7   /* !lituse_jsr relocation */
+#define O_gpdisp       O_md8   /* !gpdisp relocation */
+#define O_gprelhigh    O_md9   /* !gprelhigh relocation */
+#define O_gprellow     O_md10  /* !gprellow relocation */
+#define O_gprel                O_md11  /* !gprel relocation */
+
+#define DUMMY_RELOC_LITUSE_ADDR                (BFD_RELOC_UNUSED + 1)
+#define DUMMY_RELOC_LITUSE_BASE                (BFD_RELOC_UNUSED + 2)
+#define DUMMY_RELOC_LITUSE_BYTOFF      (BFD_RELOC_UNUSED + 3)
+#define DUMMY_RELOC_LITUSE_JSR         (BFD_RELOC_UNUSED + 4)
+
+#define LITUSE_ADDR    0
+#define LITUSE_BASE    1
+#define LITUSE_BYTOFF  2
+#define LITUSE_JSR     3
+
+#define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_gprel)
 
 /* Macros for extracting the type and number of encoded register tokens */
 
@@ -188,6 +194,9 @@ struct alpha_macro {
 \f
 /* Prototypes for all local functions */
 
+static struct alpha_reloc_tag *get_alpha_reloc_tag PARAMS ((long));
+static void alpha_adjust_symtab_relocs PARAMS ((bfd *, asection *, PTR));
+
 static int tokenize_arguments PARAMS ((char *, expressionS *, int));
 static const struct alpha_opcode *find_opcode_match
   PARAMS ((const struct alpha_opcode *, const expressionS *, int *, int *));
@@ -197,16 +206,15 @@ static unsigned insert_operand
   PARAMS ((unsigned, const struct alpha_operand *, offsetT, char *, unsigned));
 static void assemble_insn
   PARAMS ((const struct alpha_opcode *, const expressionS *, int,
-          struct alpha_insn *));
+          struct alpha_insn *, bfd_reloc_code_real_type));
 static void emit_insn PARAMS ((struct alpha_insn *));
 static void assemble_tokens_to_insn
   PARAMS ((const char *, const expressionS *, int, struct alpha_insn *));
 static void assemble_tokens
   PARAMS ((const char *, const expressionS *, int, int));
 
-static int load_expression
-  PARAMS ((int, const expressionS *, int *, expressionS *,
-          const expressionS *));
+static long load_expression
+  PARAMS ((int, const expressionS *, int *, expressionS *));
 
 static void emit_ldgp PARAMS ((const expressionS *, int, const PTR));
 static void emit_division PARAMS ((const expressionS *, int, const PTR));
@@ -257,16 +265,14 @@ static void s_alpha_base PARAMS ((int));
 static void s_alpha_align PARAMS ((int));
 static void s_alpha_stringer PARAMS ((int));
 static void s_alpha_space PARAMS ((int));
+static void s_alpha_ucons PARAMS ((int));
+static void s_alpha_arch PARAMS ((int));
 
 static void create_literal_section PARAMS ((const char *, segT *, symbolS **));
 #ifndef OBJ_ELF
 static void select_gp_value PARAMS ((void));
 #endif
 static void alpha_align PARAMS ((int, char *, symbolS *, int));
-
-#ifdef RELOC_OP_P
-static void alpha_adjust_symtab_relocs PARAMS ((bfd *, asection *, PTR));
-#endif
 \f
 /* Generic assembler global variables which must be defined by all
    targets.  */
@@ -469,103 +475,57 @@ static int alpha_flag_show_after_trunc = 0;              /* -H */
    that op-O_literal indexes into it.  */
 
 #define ALPHA_RELOC_TABLE(op)                                          \
-&alpha_reloc_op[ ((!USER_RELOC_P (op))                                 \
+(&alpha_reloc_op[ ((!USER_RELOC_P (op))                                        \
                  ? (abort (), 0)                                       \
-                 : (int) (op) - (int) O_literal) ]
+                 : (int) (op) - (int) O_literal) ])
 
-#define LITUSE_BASE    1
-#define LITUSE_BYTOFF  2
-#define LITUSE_JSR     3
+#define DEF(NAME, RELOC, NEED_SEQ) \
+ { #NAME, sizeof(#NAME)-1, O_##NAME, RELOC, NEED_SEQ }
 
 static const struct alpha_reloc_op_tag {
   const char *name;                            /* string to lookup */
   size_t length;                               /* size of the string */
-  bfd_reloc_code_real_type reloc;              /* relocation before frob */
   operatorT op;                                        /* which operator to use */
-  int lituse;                                  /* addened to specify lituse */
+  bfd_reloc_code_real_type reloc;              /* relocation before frob */
+  unsigned int need_seq : 1;                   /* require a sequence number */
 } alpha_reloc_op[] = {
-
-  {
-    "literal",                                 /* name */
-    sizeof ("literal")-1,                      /* length */
-    BFD_RELOC_ALPHA_USER_LITERAL,              /* reloc */
-    O_literal,                                 /* op */
-    0,                                         /* lituse */
-  },
-
-  {
-    "lituse_base",                             /* name */
-    sizeof ("lituse_base")-1,                  /* length */
-    BFD_RELOC_ALPHA_USER_LITUSE_BASE,          /* reloc */
-    O_lituse_base,                             /* op */
-    LITUSE_BASE,                               /* lituse */
-  },
-
-  {
-    "lituse_bytoff",                           /* name */
-    sizeof ("lituse_bytoff")-1,                        /* length */
-    BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF,                /* reloc */
-    O_lituse_bytoff,                           /* op */
-    LITUSE_BYTOFF,                             /* lituse */
-  },
-
-  {
-    "lituse_jsr",                              /* name */
-    sizeof ("lituse_jsr")-1,                   /* length */
-    BFD_RELOC_ALPHA_USER_LITUSE_JSR,           /* reloc */
-    O_lituse_jsr,                              /* op */
-    LITUSE_JSR,                                        /* lituse */
-  },
-
-  {
-    "gpdisp",                                  /* name */
-    sizeof ("gpdisp")-1,                       /* length */
-    BFD_RELOC_ALPHA_USER_GPDISP,               /* reloc */
-    O_gpdisp,                                  /* op */
-    0,                                         /* lituse */
-  },
-
-  {
-    "gprelhigh",                               /* name */
-    sizeof ("gprelhigh")-1,                    /* length */
-    BFD_RELOC_ALPHA_USER_GPRELHIGH,            /* reloc */
-    O_gprelhigh,                               /* op */
-    0,                                         /* lituse */
-  },
-
-  {
-    "gprellow",                                        /* name */
-    sizeof ("gprellow")-1,                     /* length */
-    BFD_RELOC_ALPHA_USER_GPRELLOW,             /* reloc */
-    O_gprellow,                                        /* op */
-    0,                                         /* lituse */
-  },
+  DEF(literal, BFD_RELOC_ALPHA_ELF_LITERAL, 1),
+  DEF(lituse_addr, DUMMY_RELOC_LITUSE_ADDR, 1),
+  DEF(lituse_base, DUMMY_RELOC_LITUSE_BASE, 1),
+  DEF(lituse_bytoff, DUMMY_RELOC_LITUSE_BYTOFF, 1),
+  DEF(lituse_jsr, DUMMY_RELOC_LITUSE_JSR, 1),
+  DEF(gpdisp, BFD_RELOC_ALPHA_GPDISP, 1),
+  DEF(gprelhigh, BFD_RELOC_ALPHA_GPREL_HI16, 0),
+  DEF(gprellow, BFD_RELOC_ALPHA_GPREL_LO16, 0),
+  DEF(gprel, BFD_RELOC_GPREL16, 0)
 };
 
+#undef DEF
+
 static const int alpha_num_reloc_op
   = sizeof (alpha_reloc_op) / sizeof (*alpha_reloc_op);
+#endif /* RELOC_OP_P */
 
 /* Maximum # digits needed to hold the largest sequence # */
 #define ALPHA_RELOC_DIGITS 25
 
-/* Whether a sequence number is valid.  */
-#define ALPHA_RELOC_SEQUENCE_OK(X) ((X) > 0 && ((unsigned) (X)) == (X))
-
 /* Structure to hold explict sequence information.  */
-struct alpha_literal_tag
+struct alpha_reloc_tag
 {
-  fixS *lituse;                        /* head of linked list of !literals */
+  fixS *slaves;                        /* head of linked list of !literals */
   segT segment;                        /* segment relocs are in or undefined_section*/
-  int multi_section_p;         /* True if more than one section was used */
-  unsigned sequence;           /* sequence # */
-  unsigned n_literals;         /* # of literals */
-  unsigned n_lituses;          /* # of lituses */
+  long sequence;               /* sequence # */
+  unsigned n_master;           /* # of literals */
+  unsigned n_slaves;           /* # of lituses */
+  char multi_section_p;                /* True if more than one section was used */
   char string[1];              /* printable form of sequence to hash with */
 };
 
 /* Hash table to link up literals with the appropriate lituse */
 static struct hash_control *alpha_literal_hash;
-#endif
+
+/* Sequence numbers for internal use by macros.  */
+static long next_sequence_num = -1;
 \f
 /* A table of CPU names and opcode sets.  */
 
@@ -606,48 +566,48 @@ static const struct cpu_type {
 static const struct alpha_macro alpha_macros[] = {
 /* Load/Store macros */
   { "lda",     emit_lda, NULL,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_LITERAL, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ldah",    emit_ldah, NULL,
     { MACRO_IR, MACRO_EXP, MACRO_EOA } },
 
   { "ldl",     emit_ir_load, "ldl",
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ldl_l",   emit_ir_load, "ldl_l",
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ldq",     emit_ir_load, "ldq",
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_LITERAL, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ldq_l",   emit_ir_load, "ldq_l",
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ldq_u",   emit_ir_load, "ldq_u",
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ldf",     emit_loadstore, "ldf",
-    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ldg",     emit_loadstore, "ldg",
-    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "lds",     emit_loadstore, "lds",
-    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ldt",     emit_loadstore, "ldt",
-    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
 
   { "ldb",     emit_ldX, (PTR) 0,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ldbu",    emit_ldXu, (PTR) 0,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ldw",     emit_ldX, (PTR) 1,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ldwu",    emit_ldXu, (PTR) 1,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
 
   { "uldw",    emit_uldX, (PTR) 1,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "uldwu",   emit_uldXu, (PTR) 1,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "uldl",    emit_uldX, (PTR) 2,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "uldlu",   emit_uldXu, (PTR) 2,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "uldq",    emit_uldXu, (PTR) 3,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
 
   { "ldgp",    emit_ldgp, NULL,
     { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA } },
@@ -672,34 +632,34 @@ static const struct alpha_macro alpha_macros[] = {
 #endif
 
   { "stl",     emit_loadstore, "stl",
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "stl_c",   emit_loadstore, "stl_c",
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "stq",     emit_loadstore, "stq",
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "stq_c",   emit_loadstore, "stq_c",
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "stq_u",   emit_loadstore, "stq_u",
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "stf",     emit_loadstore, "stf",
-    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "stg",     emit_loadstore, "stg",
-    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "sts",     emit_loadstore, "sts",
-    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "stt",     emit_loadstore, "stt",
-    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
 
   { "stb",     emit_stX, (PTR) 0,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "stw",     emit_stX, (PTR) 1,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ustw",    emit_ustX, (PTR) 1,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ustl",    emit_ustX, (PTR) 2,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
   { "ustq",    emit_ustX, (PTR) 3,
-    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },
+    { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
 
 /* Arithmetic macros */
 #if 0
@@ -762,15 +722,15 @@ static const struct alpha_macro alpha_macros[] = {
       MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
 
   { "jsr",     emit_jsrjmp, "jsr",
-    { MACRO_PIR, MACRO_EXP, MACRO_JSR, MACRO_EOA,
-      MACRO_PIR, MACRO_JSR, MACRO_EOA,
-      MACRO_IR,  MACRO_EXP, MACRO_JSR, MACRO_EOA,
-      MACRO_EXP, MACRO_JSR, MACRO_EOA } },
+    { MACRO_PIR, MACRO_EXP, MACRO_EOA,
+      MACRO_PIR, MACRO_EOA,
+      MACRO_IR,  MACRO_EXP, MACRO_EOA,
+      MACRO_EXP, MACRO_EOA } },
   { "jmp",     emit_jsrjmp, "jmp",
-    { MACRO_PIR, MACRO_EXP, MACRO_JSR, MACRO_EOA,
-      MACRO_PIR, MACRO_JSR, MACRO_EOA,
-      MACRO_IR,  MACRO_EXP, MACRO_JSR, MACRO_EOA,
-      MACRO_EXP, MACRO_JSR, MACRO_EOA } },
+    { MACRO_PIR, MACRO_EXP, MACRO_EOA,
+      MACRO_PIR, MACRO_EOA,
+      MACRO_IR,  MACRO_EXP, MACRO_EOA,
+      MACRO_EXP, MACRO_EOA } },
   { "ret",     emit_retjcr, "ret",
     { MACRO_IR, MACRO_EXP, MACRO_EOA,
       MACRO_IR, MACRO_EOA,
@@ -825,7 +785,8 @@ md_begin ()
       name = alpha_opcodes[i].name;
       retval = hash_insert (alpha_opcode_hash, name, (PTR) &alpha_opcodes[i]);
       if (retval)
-       as_fatal (_("internal error: can't hash opcode `%s': %s"), name, retval);
+       as_fatal (_("internal error: can't hash opcode `%s': %s"),
+                 name, retval);
 
       /* Some opcodes include modifiers of various sorts with a "/mod"
         syntax, like the architecture manual suggests.  However, for
@@ -912,12 +873,10 @@ md_begin ()
     }
 #endif /* OBJ_ELF */
 
-  subseg_set (text_section, 0);
-
-#ifdef RELOC_OP_P
   /* Create literal lookup hash table.  */
   alpha_literal_hash = hash_new ();
-#endif
+
+  subseg_set (text_section, 0);
 }
 
 /* The public interface to the instruction assembler.  */
@@ -1177,10 +1136,13 @@ md_apply_fix3 (fixP, valueP, seg)
     case BFD_RELOC_ALPHA_GPDISP_HI16:
       {
        fixS *next = fixP->fx_next;
-       assert (next->fx_r_type == BFD_RELOC_ALPHA_GPDISP_LO16);
 
-       fixP->fx_offset = (next->fx_frag->fr_address + next->fx_where
-                          - fixP->fx_frag->fr_address - fixP->fx_where);
+       /* With user-specified !gpdisp relocations, we can be missing
+          the matching LO16 reloc.  We will have already issued an
+          error message.  */
+       if (next)
+         fixP->fx_offset = (next->fx_frag->fr_address + next->fx_where
+                            - fixP->fx_frag->fr_address - fixP->fx_where);
 
        value = (value - sign_extend_16 (value)) >> 16;
       }
@@ -1230,11 +1192,13 @@ md_apply_fix3 (fixP, valueP, seg)
       /* FIXME: inherited this obliviousness of `value' -- why? */
       md_number_to_chars (fixpos, -alpha_gp_value, 4);
       break;
-#endif
-#ifdef OBJ_ELF
+#else
     case BFD_RELOC_GPREL32:
-      return 1;
 #endif
+    case BFD_RELOC_GPREL16:
+    case BFD_RELOC_ALPHA_GPREL_HI16:
+    case BFD_RELOC_ALPHA_GPREL_LO16:
+      return 1;
 
     case BFD_RELOC_23_PCREL_S2:
       if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
@@ -1258,33 +1222,12 @@ md_apply_fix3 (fixP, valueP, seg)
     case BFD_RELOC_ALPHA_LITERAL:
       md_number_to_chars (fixpos, value, 2);
       return 1;
-
-    case BFD_RELOC_ALPHA_LITUSE:
-      return 1;
 #endif
-#ifdef OBJ_ELF
     case BFD_RELOC_ALPHA_ELF_LITERAL:
     case BFD_RELOC_ALPHA_LITUSE:
-      return 1;
-#endif
-#ifdef OBJ_EVAX
     case BFD_RELOC_ALPHA_LINKAGE:
     case BFD_RELOC_ALPHA_CODEADDR:
       return 1;
-#endif
-
-#ifdef RELOC_OP_P
-    case BFD_RELOC_ALPHA_USER_LITERAL:
-    case BFD_RELOC_ALPHA_USER_LITUSE_BASE:
-    case BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF:
-    case BFD_RELOC_ALPHA_USER_LITUSE_JSR:
-      return 1;
-
-    case BFD_RELOC_ALPHA_USER_GPDISP:
-    case BFD_RELOC_ALPHA_USER_GPRELHIGH:
-    case BFD_RELOC_ALPHA_USER_GPRELLOW:
-      abort ();
-#endif
 
     case BFD_RELOC_VTABLE_INHERIT:
     case BFD_RELOC_VTABLE_ENTRY:
@@ -1438,27 +1381,15 @@ alpha_force_relocation (f)
     case BFD_RELOC_ALPHA_GPDISP_HI16:
     case BFD_RELOC_ALPHA_GPDISP_LO16:
     case BFD_RELOC_ALPHA_GPDISP:
-#ifdef OBJ_ECOFF
     case BFD_RELOC_ALPHA_LITERAL:
-#endif
-#ifdef OBJ_ELF
     case BFD_RELOC_ALPHA_ELF_LITERAL:
-#endif
     case BFD_RELOC_ALPHA_LITUSE:
+    case BFD_RELOC_GPREL16:
     case BFD_RELOC_GPREL32:
-#ifdef OBJ_EVAX
+    case BFD_RELOC_ALPHA_GPREL_HI16:
+    case BFD_RELOC_ALPHA_GPREL_LO16:
     case BFD_RELOC_ALPHA_LINKAGE:
     case BFD_RELOC_ALPHA_CODEADDR:
-#endif
-#ifdef RELOC_OP_P
-    case BFD_RELOC_ALPHA_USER_LITERAL:
-    case BFD_RELOC_ALPHA_USER_LITUSE_BASE:
-    case BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF:
-    case BFD_RELOC_ALPHA_USER_LITUSE_JSR:
-    case BFD_RELOC_ALPHA_USER_GPDISP:
-    case BFD_RELOC_ALPHA_USER_GPRELHIGH:
-    case BFD_RELOC_ALPHA_USER_GPRELLOW:
-#endif
     case BFD_RELOC_VTABLE_INHERIT:
     case BFD_RELOC_VTABLE_ENTRY:
       return 1;
@@ -1497,35 +1428,21 @@ alpha_fix_adjustable (f)
     case BFD_RELOC_ALPHA_GPDISP:
       return 0;
 
-#ifdef OBJ_ECOFF
     case BFD_RELOC_ALPHA_LITERAL:
-#endif
-#ifdef OBJ_ELF
     case BFD_RELOC_ALPHA_ELF_LITERAL:
-#endif
-#ifdef RELOC_OP_P
-    case BFD_RELOC_ALPHA_USER_LITERAL:
-#endif
-#ifdef OBJ_EVAX
+    case BFD_RELOC_ALPHA_LITUSE:
     case BFD_RELOC_ALPHA_LINKAGE:
     case BFD_RELOC_ALPHA_CODEADDR:
-#endif
       return 1;
 
-    case BFD_RELOC_ALPHA_LITUSE:
-#ifdef RELOC_OP_P
-    case BFD_RELOC_ALPHA_USER_LITUSE_BASE:
-    case BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF:
-    case BFD_RELOC_ALPHA_USER_LITUSE_JSR:
-    case BFD_RELOC_ALPHA_USER_GPDISP:
-    case BFD_RELOC_ALPHA_USER_GPRELHIGH:
-    case BFD_RELOC_ALPHA_USER_GPRELLOW:
-#endif
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
       return 0;
 
+    case BFD_RELOC_GPREL16:
     case BFD_RELOC_GPREL32:
+    case BFD_RELOC_ALPHA_GPREL_HI16:
+    case BFD_RELOC_ALPHA_GPREL_LO16:
     case BFD_RELOC_23_PCREL_S2:
     case BFD_RELOC_32:
     case BFD_RELOC_64:
@@ -1651,31 +1568,45 @@ alpha_frob_file_before_adjust ()
 
 #endif /* OBJ_ECOFF */
 \f
-#ifdef RELOC_OP_P
+static struct alpha_reloc_tag *
+get_alpha_reloc_tag (sequence)
+     long sequence;
+{
+  char buffer[ALPHA_RELOC_DIGITS];
+  struct alpha_reloc_tag *info;
+
+  sprintf (buffer, "!%ld", sequence);
+
+  info = (struct alpha_reloc_tag *) hash_find (alpha_literal_hash, buffer);
+  if (! info)
+    {
+      size_t len = strlen (buffer);
+      const char *errmsg;
+
+      info = (struct alpha_reloc_tag *)
+       xcalloc (sizeof (struct alpha_reloc_tag) + len, 1);
+
+      info->segment = now_seg;
+      info->sequence = sequence;
+      strcpy (info->string, buffer);
+      errmsg = hash_insert (alpha_literal_hash, info->string, (PTR) info);
+      if (errmsg)
+       as_fatal (errmsg);
+    }
+
+  return info;
+}
 
 /* Before the relocations are written, reorder them, so that user
    supplied !lituse relocations follow the appropriate !literal
-   relocations.  Also convert the gas-internal relocations to the
-   appropriate linker relocations.  */
+   relocations, and similarly for !gpdisp relocations.  */
 
 void
 alpha_adjust_symtab ()
 {
   if (alpha_literal_hash)
-    {
-#ifdef DEBUG2_ALPHA
-      fprintf (stderr, "alpha_adjust_symtab called\n");
-#endif
-
-      /* Go over each section, reordering the relocations so that all
-         of the explicit LITUSE's are adjacent to the explicit
-         LITERAL's.  */
-      bfd_map_over_sections (stdoutput, alpha_adjust_symtab_relocs,
-                            (char *) 0);
-    }
+    bfd_map_over_sections (stdoutput, alpha_adjust_symtab_relocs, NULL);
 }
-\f
-/* Inner function to move LITUSE's next to the LITERAL.  */
 
 static void
 alpha_adjust_symtab_relocs (abfd, sec, ptr)
@@ -1687,14 +1618,8 @@ alpha_adjust_symtab_relocs (abfd, sec, ptr)
   fixS **prevP;
   fixS *fixp;
   fixS *next;
-  fixS *lituse;
-  int n_lituses = 0;
-
-#ifdef DEBUG2_ALPHA
-  int n = 0;
-  int n_literals = 0;
-  int n_dup_literals = 0;
-#endif
+  fixS *slave;
+  unsigned long n_slaves = 0;
 
   /* If seginfo is NULL, we did not create this section; don't do
      anything with it.  By using a pointer to a pointer, we can update
@@ -1706,121 +1631,94 @@ alpha_adjust_symtab_relocs (abfd, sec, ptr)
   if (! seginfo->fix_root)
     return;
 
-  /* First rebuild the fixup chain without the expicit lituse's.  */
-  prevP = &(seginfo->fix_root);
+  /* First rebuild the fixup chain without the expicit lituse and
+     gpdisp_lo16 relocs.  */
+  prevP = &seginfo->fix_root;
   for (fixp = seginfo->fix_root; fixp; fixp = next)
     {
       next = fixp->fx_next;
       fixp->fx_next = (fixS *) 0;
-#ifdef DEBUG2_ALPHA
-      n++;
-#endif
 
       switch (fixp->fx_r_type)
        {
-       default:
-         *prevP = fixp;
-         prevP = &(fixp->fx_next);
-#ifdef DEBUG2_ALPHA
-         fprintf (stderr,
-                  "alpha_adjust_symtab_relocs: 0x%lx, other relocation %s\n",
-                  (long) fixp,
-                  bfd_get_reloc_code_name (fixp->fx_r_type));
-#endif
-         break;
-
-       case BFD_RELOC_ALPHA_USER_LITERAL:
-         *prevP = fixp;
-         prevP = &(fixp->fx_next);
-         /* prevent assembler from trying to adjust the offset */
-#ifdef DEBUG2_ALPHA
-         n_literals++;
-         if (fixp->tc_fix_data.info->n_literals != 1)
-           n_dup_literals++;
-         fprintf (stderr,
-                  "alpha_adjust_symtab_relocs: 0x%lx, !literal!%.6d, # literals = %2d\n",
-                  (long) fixp,
-                  fixp->tc_fix_data.info->sequence,
-                  fixp->tc_fix_data.info->n_literals);
-#endif
+       case BFD_RELOC_ALPHA_LITUSE:
+         n_slaves++;
+         if (fixp->tc_fix_data.info->n_master == 0)
+           as_bad_where (fixp->fx_file, fixp->fx_line,
+                         _("No !literal!%ld was found"),
+                         fixp->tc_fix_data.info->sequence);
          break;
 
-         /* do not link in lituse's */
-       case BFD_RELOC_ALPHA_USER_LITUSE_BASE:
-       case BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF:
-       case BFD_RELOC_ALPHA_USER_LITUSE_JSR:
-         n_lituses++;
-         if (fixp->tc_fix_data.info->n_literals == 0)
+       case BFD_RELOC_ALPHA_GPDISP_LO16:
+         n_slaves++;
+         if (fixp->tc_fix_data.info->n_master == 0)
            as_bad_where (fixp->fx_file, fixp->fx_line,
-                         _("No !literal!%d was found"),
+                         _("No ldah !gpdisp!%ld was found"),
                          fixp->tc_fix_data.info->sequence);
-#ifdef DEBUG2_ALPHA
-         fprintf (stderr,
-                  "alpha_adjust_symtab_relocs: 0x%lx, !lituse !%.6d, # lituses  = %2d, next_lituse = 0x%lx\n",
-                  (long) fixp,
-                  fixp->tc_fix_data.info->sequence,
-                  fixp->tc_fix_data.info->n_lituses,
-                  (long) fixp->tc_fix_data.next_lituse);
-#endif
+         break;
+
+       default:
+         *prevP = fixp;
+         prevP = &fixp->fx_next;
          break;
        }
     }
 
-  /* If there were any lituses, go and add them to the chain, unless there is
-     more than one !literal for a given sequence number.  They are linked
-     through the next_lituse field in reverse order, so as we go through the
-     next_lituse chain, we effectively reverse the chain once again.  If there
-     was more than one !literal, we fall back to loading up the address w/o
-     optimization.  Also, if the !literals/!lituses are spread in different
-     segments (happens in the Linux kernel semaphores), suppress the
-     optimization.  */
-  if (n_lituses)
+  /* If there were any dependent relocations, go and add them back to
+     the chain.  They are linked through the next_reloc field in
+     reverse order, so as we go through the next_reloc chain, we
+     effectively reverse the chain once again.
+
+     Except if there is more than one !literal for a given sequence
+     number.  In that case, the programmer and/or compiler is not sure
+     how control flows from literal to lituse, and we can't be sure to
+     get the relaxation correct.
+
+     ??? Well, actually we could, if there are enough lituses such that
+     we can make each literal have at least one of each lituse type
+     present.  Not implemented.
+
+     Also suppress the optimization if the !literals/!lituses are spread
+     in different segments.  This can happen with "intersting" uses of
+     inline assembly; examples are present in the Linux kernel semaphores.  */
+
+  for (fixp = seginfo->fix_root; fixp; fixp = next)
     {
-      for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
+      next = fixp->fx_next;
+      switch (fixp->fx_r_type)
        {
-         switch (fixp->fx_r_type)
+       case BFD_RELOC_ALPHA_ELF_LITERAL:
+         if (fixp->tc_fix_data.info->n_master == 1
+             && ! fixp->tc_fix_data.info->multi_section_p)
            {
-           default:
-             break;
-
-           case BFD_RELOC_ALPHA_USER_LITERAL:
-#ifdef OBJ_ELF
-             fixp->fx_r_type = BFD_RELOC_ALPHA_ELF_LITERAL;
-#else
-             fixp->fx_r_type = BFD_RELOC_ALPHA_LITERAL;        /* XXX check this */
-#endif
-             if (fixp->tc_fix_data.info->n_literals == 1
-                 && ! fixp->tc_fix_data.info->multi_section_p)
+             for (slave = fixp->tc_fix_data.info->slaves;
+                  slave != (fixS *) 0;
+                  slave = slave->tc_fix_data.next_reloc)
                {
-                 for (lituse = fixp->tc_fix_data.info->lituse;
-                      lituse != (fixS *) 0;
-                      lituse = lituse->tc_fix_data.next_lituse)
-                   {
-                     lituse->fx_next = fixp->fx_next;
-                     fixp->fx_next = lituse;
-                   }
+                 slave->fx_next = fixp->fx_next;
+                 fixp->fx_next = slave;
                }
-             break;
+           }
+         break;
 
-           case BFD_RELOC_ALPHA_USER_LITUSE_BASE:
-           case BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF:
-           case BFD_RELOC_ALPHA_USER_LITUSE_JSR:
-             fixp->fx_r_type = BFD_RELOC_ALPHA_LITUSE;
-             break;
+       case BFD_RELOC_ALPHA_GPDISP_HI16:
+         if (fixp->tc_fix_data.info->n_slaves == 0)
+           as_bad_where (fixp->fx_file, fixp->fx_line,
+                         _("No lda !gpdisp!%ld was found"),
+                         fixp->tc_fix_data.info->sequence);
+         else
+           {
+             slave = fixp->tc_fix_data.info->slaves;
+             slave->fx_next = next;
+             fixp->fx_next = slave;
            }
+         break;
+
+       default:
+         break;
        }
     }
-
-#ifdef DEBUG2_ALPHA
-  fprintf (stderr, "alpha_adjust_symtab_relocs: %s, %d literal%s, %d duplicate literal%s, %d lituse%s\n\n",
-          sec->name,
-          n_literals, (n_literals == 1) ? "" : "s",
-          n_dup_literals, (n_dup_literals == 1) ? "" : "s",
-          n_lituses, (n_lituses == 1) ? "" : "s");
-#endif
 }
-
-#endif /* RELOC_OP_P */
 \f
 #ifdef DEBUG_ALPHA
 static void
@@ -1877,7 +1775,7 @@ debug_exp (tok, ntok)
        case O_gpdisp:                  name = "O_gpdisp";              break;
        case O_gprelhigh:               name = "O_gprelhigh";           break;
        case O_gprellow:                name = "O_gprellow";            break;
-       case O_md10:                    name = "O_md10";                break;
+       case O_gprel:                   name = "O_gprel";               break;
        case O_md11:                    name = "O_md11";                break;
        case O_md12:                    name = "O_md12";                break;
        case O_md13:                    name = "O_md13";                break;
@@ -1910,13 +1808,11 @@ tokenize_arguments (str, tok, ntok)
 #ifdef DEBUG_ALPHA
   expressionS *orig_tok = tok;
 #endif
-#ifdef RELOC_OP_P
   char *p;
   const struct alpha_reloc_op_tag *r;
   int c, i;
   size_t len;
   int reloc_found_p = 0;
-#endif
 
   memset (tok, 0, sizeof (*tok) * ntok);
 
@@ -1924,6 +1820,11 @@ tokenize_arguments (str, tok, ntok)
   old_input_line_pointer = input_line_pointer;
   input_line_pointer = str;
 
+#ifdef RELOC_OP_P
+  /* ??? Wrest control of ! away from the regular expression parser.  */
+  is_end_of_line[(unsigned char) '!'] = 1;
+#endif
+
   while (tok < end_tok && *input_line_pointer)
     {
       SKIP_WHITESPACE ();
@@ -1946,48 +1847,52 @@ tokenize_arguments (str, tok, ntok)
          if (!saw_arg)
            goto err;
 
-         for (p = ++input_line_pointer;
-              ((c = *p) != '!' && c != ';' && c != '#' && c != ','
-               && !is_end_of_line[c]);
-              p++)
-           ;
+         ++input_line_pointer;
+          SKIP_WHITESPACE ();
+         p = input_line_pointer;
+         c = get_symbol_end ();
 
          /* Parse !relocation_type */
-         len = p - input_line_pointer;
+         len = input_line_pointer - p;
          if (len == 0)
            {
              as_bad (_("No relocation operand"));
              goto err_report;
            }
 
-         if (c != '!')
-           {
-             as_bad (_("No !sequence-number after !%s"), input_line_pointer);
-             goto err_report;
-           }
-
          r = &alpha_reloc_op[0];
          for (i = alpha_num_reloc_op - 1; i >= 0; i--, r++)
-           {
-             if (len == r->length
-                 && memcmp (input_line_pointer, r->name, len) == 0)
-               break;
-           }
+           if (len == r->length && memcmp (p, r->name, len) == 0)
+             break;
          if (i < 0)
            {
-             as_bad (_("Unknown relocation operand: !%s"),
-                     input_line_pointer);
+             as_bad (_("Unknown relocation operand: !%s"), p);
              goto err_report;
            }
 
-         input_line_pointer = ++p;
+         *input_line_pointer = c;
+          SKIP_WHITESPACE ();
+         if (*input_line_pointer != '!')
+           {
+             if (r->need_seq)
+               {
+                 as_bad (_("No !sequence-number after !%s"),
+                         input_line_pointer);
+                 goto err_report;
+               }
+
+             tok->X_op = r->op;
+             tok->X_add_number = 0;
+             reloc_found_p = 1;
+             ++tok;
+             break;
+           }
+
+         input_line_pointer++;
 
          /* Parse !sequence_number */
-         memset (tok, '\0', sizeof (expressionS));
          expression (tok);
-
-         if (tok->X_op != O_constant
-             || ! ALPHA_RELOC_SEQUENCE_OK (tok->X_add_number))
+         if (tok->X_op != O_constant || tok->X_add_number <= 0)
            {
              as_bad (_("Bad sequence number: !%s!%s"),
                      r->name, input_line_pointer);
@@ -1998,7 +1903,7 @@ tokenize_arguments (str, tok, ntok)
          reloc_found_p = 1;
          ++tok;
          break;
-#endif
+#endif /* RELOC_OP_P */
 
        case ',':
          ++input_line_pointer;
@@ -2050,18 +1955,25 @@ fini:
 #ifdef DEBUG_ALPHA
   debug_exp (orig_tok, ntok - (end_tok - tok));
 #endif
+#ifdef RELOC_OP_P
+  is_end_of_line[(unsigned char) '!'] = 0;
+#endif
 
   return ntok - (end_tok - tok);
 
 err:
+#ifdef RELOC_OP_P
+  is_end_of_line[(unsigned char) '!'] = 0;
+#endif
   input_line_pointer = old_input_line_pointer;
   return TOKENIZE_ERROR;
 
-#ifdef RELOC_OP_P
 err_report:
+#ifdef RELOC_OP_P
+  is_end_of_line[(unsigned char) '!'] = 0;
+#endif
   input_line_pointer = old_input_line_pointer;
   return TOKENIZE_ERROR_REPORT;
-#endif
 }
 
 /* Search forward through all variants of an opcode looking for a
@@ -2249,7 +2161,6 @@ find_macro_match (first_macro, tok, pntok)
                case O_register:
                case O_pregister:
                case O_cpregister:
-#ifdef RELOC_OP_P
                case O_literal:
                case O_lituse_base:
                case O_lituse_bytoff:
@@ -2257,7 +2168,7 @@ find_macro_match (first_macro, tok, pntok)
                case O_gpdisp:
                case O_gprelhigh:
                case O_gprellow:
-#endif
+               case O_gprel:
                  goto match_failed;
 
                default:
@@ -2266,38 +2177,6 @@ find_macro_match (first_macro, tok, pntok)
              ++tokidx;
              break;
 
-             /* optional !literal!<number> */
-           case MACRO_LITERAL:
-#ifdef RELOC_OP_P
-             if (tokidx < ntok && tok[tokidx].X_op == O_literal)
-               tokidx++;
-#endif
-             break;
-
-             /* optional !lituse_base!<number> */
-           case MACRO_BASE:
-#ifdef RELOC_OP_P
-             if (tokidx < ntok && tok[tokidx].X_op == O_lituse_base)
-               tokidx++;
-#endif
-             break;
-
-             /* optional !lituse_bytoff!<number> */
-           case MACRO_BYTOFF:
-#ifdef RELOC_OP_P
-             if (tokidx < ntok && tok[tokidx].X_op == O_lituse_bytoff)
-               tokidx++;
-#endif
-             break;
-
-             /* optional !lituse_jsr!<number> */
-           case MACRO_JSR:
-#ifdef RELOC_OP_P
-             if (tokidx < ntok && tok[tokidx].X_op == O_lituse_jsr)
-               tokidx++;
-#endif
-             break;
-
            match_failed:
              while (*arg != MACRO_EOA)
                ++arg;
@@ -2372,12 +2251,15 @@ insert_operand (insn, operand, val, file, line)
  */
 
 static void
-assemble_insn (opcode, tok, ntok, insn)
+assemble_insn (opcode, tok, ntok, insn, reloc)
      const struct alpha_opcode *opcode;
      const expressionS *tok;
      int ntok;
      struct alpha_insn *insn;
+     bfd_reloc_code_real_type reloc;
 {
+  const struct alpha_operand *reloc_operand = NULL;
+  const expressionS *reloc_exp = NULL;
   const unsigned char *argidx;
   unsigned image;
   int tokidx = 0;
@@ -2433,24 +2315,85 @@ assemble_insn (opcode, tok, ntok, insn)
 
        case O_constant:
          image = insert_operand (image, operand, t->X_add_number, NULL, 0);
+         assert (reloc_operand == NULL);
+         reloc_operand = operand;
+         reloc_exp = t;
          break;
 
        default:
-         {
-           struct alpha_fixup *fixup;
+         /* This is only 0 for fields that should contain registers,
+            which means this pattern shouldn't have matched.  */
+         if (operand->default_reloc == 0)
+           abort ();
 
-           if (insn->nfixups >= MAX_INSN_FIXUPS)
-             as_fatal (_("too many fixups"));
+         /* There is one special case for which an insn receives two
+            relocations, and thus the user-supplied reloc does not 
+            override the operand reloc.  */
+         if (operand->default_reloc == BFD_RELOC_ALPHA_HINT)
+           {
+             struct alpha_fixup *fixup;
 
-           fixup = &insn->fixups[insn->nfixups++];
+             if (insn->nfixups >= MAX_INSN_FIXUPS)
+               as_fatal (_("too many fixups"));
 
-           fixup->exp = *t;
-           fixup->reloc = operand->default_reloc;
-         }
+             fixup = &insn->fixups[insn->nfixups++];
+             fixup->exp = *t;
+             fixup->reloc = BFD_RELOC_ALPHA_HINT;
+           }
+         else
+           {
+             if (reloc == BFD_RELOC_UNUSED)
+               reloc = operand->default_reloc;
+
+             assert (reloc_operand == NULL);
+             reloc_operand = operand;
+             reloc_exp = t;
+           }
          break;
        }
     }
 
+  if (reloc != BFD_RELOC_UNUSED)
+    {
+      struct alpha_fixup *fixup;
+
+      if (insn->nfixups >= MAX_INSN_FIXUPS)
+       as_fatal (_("too many fixups"));
+
+      /* ??? My but this is hacky.  But the OSF/1 assembler uses the same
+        relocation tag for both ldah and lda with gpdisp.  Choose the
+        correct internal relocation based on the opcode.  */
+      if (reloc == BFD_RELOC_ALPHA_GPDISP)
+       {
+         if (strcmp (opcode->name, "ldah") == 0)
+           reloc = BFD_RELOC_ALPHA_GPDISP_HI16;
+         else if (strcmp (opcode->name, "lda") == 0)
+           reloc = BFD_RELOC_ALPHA_GPDISP_LO16;
+         else
+           as_bad (_("invalid relocation for instruction"));
+       }
+
+      /* If this is a real relocation (as opposed to a lituse hint), then
+        the relocation width should match the operand width.  */
+      else if (reloc < BFD_RELOC_UNUSED)
+       {
+         reloc_howto_type *reloc_howto
+           = bfd_reloc_type_lookup (stdoutput, reloc);
+         if (reloc_howto->bitsize != reloc_operand->bits)
+           {
+             as_bad (_("invalid relocation for field"));
+             return;
+           }
+       }
+
+      fixup = &insn->fixups[insn->nfixups++];
+      if (reloc_exp)
+       fixup->exp = *reloc_exp;
+      else
+       fixup->exp.X_op = O_absent;
+      fixup->reloc = reloc;
+    }
+
   insn->insn = image;
 }
 
@@ -2485,12 +2428,9 @@ emit_insn (insn)
     {
       const struct alpha_operand *operand = (const struct alpha_operand *) 0;
       struct alpha_fixup *fixup = &insn->fixups[i];
+      struct alpha_reloc_tag *info;
       int size, pcrel;
       fixS *fixP;
-#ifdef RELOC_OP_P
-      char buffer[ALPHA_RELOC_DIGITS];
-      struct alpha_literal_tag *info;
-#endif
 
       /* Some fixups are only used internally and so have no howto */
       if ((int) fixup->reloc < 0)
@@ -2499,43 +2439,24 @@ emit_insn (insn)
          size = 4;
          pcrel = ((operand->flags & AXP_OPERAND_RELATIVE) != 0);
        }
+      else if (fixup->reloc > BFD_RELOC_UNUSED
+              || fixup->reloc == BFD_RELOC_ALPHA_GPDISP_HI16
+              || fixup->reloc == BFD_RELOC_ALPHA_GPDISP_LO16)
+       {
+         size = 2;
+         pcrel = 0;
+       }
       else
-       switch (fixup->reloc)
-         {
-#ifdef OBJ_ELF
-           /* These relocation types are only used internally.  */
-         case BFD_RELOC_ALPHA_GPDISP_HI16:
-         case BFD_RELOC_ALPHA_GPDISP_LO16:
-           size = 2;
-           pcrel = 0;
-           break;
-#endif
-#ifdef RELOC_OP_P
-           /* and these also are internal only relocations */
-         case BFD_RELOC_ALPHA_USER_LITERAL:
-         case BFD_RELOC_ALPHA_USER_LITUSE_BASE:
-         case BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF:
-         case BFD_RELOC_ALPHA_USER_LITUSE_JSR:
-         case BFD_RELOC_ALPHA_USER_GPDISP:
-         case BFD_RELOC_ALPHA_USER_GPRELHIGH:
-         case BFD_RELOC_ALPHA_USER_GPRELLOW:
-           size = 2;
-           pcrel = 0;
-           break;
-#endif
+       {
+         reloc_howto_type *reloc_howto
+           = bfd_reloc_type_lookup (stdoutput, fixup->reloc);
+         assert (reloc_howto);
 
-         default:
-           {
-             reloc_howto_type *reloc_howto
-               = bfd_reloc_type_lookup (stdoutput, fixup->reloc);
-             assert (reloc_howto);
+         size = bfd_get_reloc_size (reloc_howto);
+         assert (size >= 1 && size <= 4);
 
-             size = bfd_get_reloc_size (reloc_howto);
-             pcrel = reloc_howto->pc_relative;
-           }
-           assert (size >= 1 && size <= 4);
-           break;
-         }
+         pcrel = reloc_howto->pc_relative;
+       }
 
       fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, size,
                          &fixup->exp, pcrel, fixup->reloc);
@@ -2544,79 +2465,75 @@ emit_insn (insn)
          and copy in the sequence number for the explicit relocations.  */
       switch (fixup->reloc)
        {
-       case BFD_RELOC_ALPHA_GPDISP_LO16:
-#ifdef OBJ_ECOFF
-       case BFD_RELOC_ALPHA_LITERAL:
-#endif
-#ifdef OBJ_ELF
-       case BFD_RELOC_ALPHA_ELF_LITERAL:
-#endif
+       case BFD_RELOC_ALPHA_HINT:
        case BFD_RELOC_GPREL32:
+       case BFD_RELOC_GPREL16:
+       case BFD_RELOC_ALPHA_GPREL_HI16:
+       case BFD_RELOC_ALPHA_GPREL_LO16:
          fixP->fx_no_overflow = 1;
          break;
 
-#ifdef RELOC_OP_P
-       case BFD_RELOC_ALPHA_USER_LITERAL:
+       case BFD_RELOC_ALPHA_GPDISP_HI16:
          fixP->fx_no_overflow = 1;
-         sprintf (buffer, "!%u", insn->sequence[i]);
-         info = ((struct alpha_literal_tag *)
-                 hash_find (alpha_literal_hash, buffer));
+         fixP->fx_addsy = section_symbol (now_seg);
+         fixP->fx_offset = 0;
 
-         if (! info)
-           {
-             size_t len = strlen (buffer);
-             const char *errmsg;
-
-             info = ((struct alpha_literal_tag *)
-                     xcalloc (sizeof (struct alpha_literal_tag) + len, 1));
-
-             info->segment = now_seg;
-             info->sequence = insn->sequence[i];
-             strcpy (info->string, buffer);
-             errmsg = hash_insert (alpha_literal_hash, info->string, (PTR) info);
-             if (errmsg)
-               as_bad (errmsg);
-           }
+         info = get_alpha_reloc_tag (insn->sequence);
+         if (++info->n_master > 1)
+           as_bad (_("too many ldah insns for !gpdisp!%ld"), insn->sequence);
+         if (info->segment != now_seg)
+           as_bad (_("both insns for !gpdisp!%ld must be in the same section"),
+                   insn->sequence);
+         fixP->tc_fix_data.info = info;
+         break;
 
-         ++info->n_literals;
+       case BFD_RELOC_ALPHA_GPDISP_LO16:
+         fixP->fx_no_overflow = 1;
 
+         info = get_alpha_reloc_tag (insn->sequence);
+         if (++info->n_slaves > 1)
+           as_bad (_("too many lda insns for !gpdisp!%ld"), insn->sequence);
          if (info->segment != now_seg)
-           info->multi_section_p = 1;
-
+           as_bad (_("both insns for !gpdisp!%ld must be in the same section"),
+                   insn->sequence);
          fixP->tc_fix_data.info = info;
+         info->slaves = fixP;
          break;
 
-       case BFD_RELOC_ALPHA_USER_LITUSE_BASE:
-       case BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF:
-       case BFD_RELOC_ALPHA_USER_LITUSE_JSR:
-         sprintf (buffer, "!%u", insn->sequence[i]);
-         info = ((struct alpha_literal_tag *)
-                 hash_find (alpha_literal_hash, buffer));
+       case BFD_RELOC_ALPHA_LITERAL:
+       case BFD_RELOC_ALPHA_ELF_LITERAL:
+         fixP->fx_no_overflow = 1;
 
-         if (! info)
-           {
-             size_t len = strlen (buffer);
-             const char *errmsg;
-
-             info = ((struct alpha_literal_tag *)
-                     xcalloc (sizeof (struct alpha_literal_tag) + len, 1));
-
-             info->segment = now_seg;
-             info->sequence = insn->sequence[i];
-             strcpy (info->string, buffer);
-             errmsg = hash_insert (alpha_literal_hash, info->string, (PTR) info);
-             if (errmsg)
-               as_bad (errmsg);
-           }
-         info->n_lituses++;
-         fixP->tc_fix_data.info = info;
-         fixP->tc_fix_data.next_lituse = info->lituse;
-         info->lituse = fixP;
+         info = get_alpha_reloc_tag (insn->sequence);
+         info->n_master++;
          if (info->segment != now_seg)
            info->multi_section_p = 1;
+         fixP->tc_fix_data.info = info;
+         break;
 
+       case DUMMY_RELOC_LITUSE_ADDR:
+         fixP->fx_offset = LITUSE_ADDR;
+         goto do_lituse;
+       case DUMMY_RELOC_LITUSE_BASE:
+         fixP->fx_offset = LITUSE_BASE;
+         goto do_lituse;
+       case DUMMY_RELOC_LITUSE_BYTOFF:
+         fixP->fx_offset = LITUSE_BYTOFF;
+         goto do_lituse;
+       case DUMMY_RELOC_LITUSE_JSR:
+         fixP->fx_offset = LITUSE_JSR;
+       do_lituse:
+         fixP->fx_addsy = section_symbol (now_seg);
+         fixP->fx_r_type = BFD_RELOC_ALPHA_LITUSE;
+
+         info = get_alpha_reloc_tag (insn->sequence);
+         info->n_slaves++;
+         fixP->tc_fix_data.info = info;
+         fixP->tc_fix_data.next_reloc = info->slaves;
+         info->slaves = fixP;
+         if (info->segment != now_seg)
+           info->multi_section_p = 1;
          break;
-#endif
 
        default:
          if ((int) fixup->reloc < 0)
@@ -2652,7 +2569,7 @@ assemble_tokens_to_insn (opname, tok, ntok, insn)
       opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch);
       if (opcode)
        {
-         assemble_insn (opcode, tok, ntok, insn);
+         assemble_insn (opcode, tok, ntok, insn, BFD_RELOC_UNUSED);
          return;
        }
       else if (cpumatch)
@@ -2679,9 +2596,15 @@ assemble_tokens (opname, tok, ntok, local_macros_on)
   const struct alpha_opcode *opcode;
   const struct alpha_macro *macro;
   int cpumatch = 1;
+  bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
 
-  /* search macros */
-  if (local_macros_on)
+  /* If a user-specified relocation is present, this is not a macro.  */
+  if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
+    {
+      reloc = ALPHA_RELOC_TABLE (tok[ntok - 1].X_op)->reloc;
+      ntok--;
+    }
+  else if (local_macros_on)
     {
       macro = ((const struct alpha_macro *)
               hash_find (alpha_macro_hash, opname));
@@ -2697,17 +2620,6 @@ assemble_tokens (opname, tok, ntok, local_macros_on)
        }
     }
 
-#ifdef RELOC_OP_P
-  if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
-    {
-      const expressionS *reloc_exp = &tok[ntok - 1];
-      const struct alpha_reloc_op_tag *r = ALPHA_RELOC_TABLE (reloc_exp->X_op);
-      as_bad (_("Cannot use !%s!%d with %s"), r->name,
-             (int) reloc_exp->X_add_number, opname);
-      ntok--;
-    }
-#endif
-
   /* search opcodes */
   opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname);
   if (opcode)
@@ -2717,18 +2629,25 @@ assemble_tokens (opname, tok, ntok, local_macros_on)
       if (opcode)
        {
          struct alpha_insn insn;
-         assemble_insn (opcode, tok, ntok, &insn);
+         assemble_insn (opcode, tok, ntok, &insn, reloc);
+
+         /* Copy the sequence number for the reloc from the reloc token.  */
+         if (reloc != BFD_RELOC_UNUSED)
+           insn.sequence = tok[ntok].X_add_number;
+
          emit_insn (&insn);
          return;
        }
     }
 
   if (found_something)
-    if (cpumatch)
-      as_bad (_("inappropriate arguments for opcode `%s'"), opname);
-    else
-      as_bad (_("opcode `%s' not supported for target %s"), opname,
-             alpha_target_name);
+    {
+      if (cpumatch)
+       as_bad (_("inappropriate arguments for opcode `%s'"), opname);
+      else
+       as_bad (_("opcode `%s' not supported for target %s"), opname,
+               alpha_target_name);
+    }
   else
     as_bad (_("unknown opcode `%s'"), opname);
 }
@@ -2763,17 +2682,6 @@ FIXME
   expressionS newtok[3];
   expressionS addend;
 
-#ifdef RELOC_OP_P
-  if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
-    {
-      const expressionS *reloc_exp = &tok[ntok - 1];
-      const struct alpha_reloc_op_tag *r = ALPHA_RELOC_TABLE (reloc_exp->X_op);
-      as_bad (_("Cannot use !%s!%d with %s"), r->name,
-             (int) reloc_exp->X_add_number, "ldgp");
-      ntok--;
-    }
-#endif
-
 #ifdef OBJ_ECOFF
   if (regno (tok[2].X_add_number) == AXP_REG_PV)
     ecoff_set_gp_prolog_size (0);
@@ -2797,6 +2705,7 @@ FIXME
   insn.nfixups = 1;
   insn.fixups[0].exp = addend;
   insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_HI16;
+  insn.sequence = next_sequence_num;
 
   emit_insn (&insn);
 
@@ -2811,6 +2720,7 @@ FIXME
   insn.nfixups = 1;
   insn.fixups[0].exp = addend;
   insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_LO16;
+  insn.sequence = next_sequence_num--;
 
   emit_insn (&insn);
 #endif /* OBJ_ECOFF || OBJ_ELF */
@@ -2890,18 +2800,18 @@ add_to_link_pool (basesym, sym, addend)
    If explicit relocations of the form !literal!<number> are allowed,
    and used, then explict_reloc with be an expression pointer.
 
-   Finally, the return value is true if the calling macro may emit a
-   LITUSE reloc if otherwise appropriate.  */
+   Finally, the return value is nonzero if the calling macro may emit
+   a LITUSE reloc if otherwise appropriate; the return value is the
+   sequence number to use.  */
 
-static int
-load_expression (targreg, exp, pbasereg, poffset, explicit_reloc)
+static long
+load_expression (targreg, exp, pbasereg, poffset)
      int targreg;
      const expressionS *exp;
      int *pbasereg;
      expressionS *poffset;
-     const expressionS *explicit_reloc;
 {
-  int emit_lituse = 0;
+  long emit_lituse = 0;
   offsetT addend = exp->X_add_number;
   int basereg = *pbasereg;
   struct alpha_insn insn;
@@ -2951,9 +2861,9 @@ load_expression (targreg, exp, pbasereg, poffset, explicit_reloc)
 
        assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
 
-       assert (explicit_reloc == (const expressionS *) 0);
        assert (insn.nfixups == 1);
        insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL;
+       insn.sequence = emit_lituse = next_sequence_num--;
 #endif /* OBJ_ECOFF */
 #ifdef OBJ_ELF
        /* emit "ldq r, gotoff(gp)" */
@@ -2990,25 +2900,14 @@ load_expression (targreg, exp, pbasereg, poffset, explicit_reloc)
        assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
 
        assert (insn.nfixups == 1);
-       if (!explicit_reloc)
-         insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL;
-       else
-         {
-#ifdef RELOC_OP_P
-           insn.fixups[0].reloc
-             = (ALPHA_RELOC_TABLE (explicit_reloc->X_op))->reloc;
-           insn.sequence[0] = explicit_reloc->X_add_number;
-#else
-           abort ();
-#endif
-         }
+       insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL;
+       insn.sequence = emit_lituse = next_sequence_num--;
 #endif /* OBJ_ELF */
 #ifdef OBJ_EVAX
        offsetT link;
 
        /* Find symbol or symbol pointer in link section.  */
 
-       assert (explicit_reloc == (const expressionS *) 0);
        if (exp->X_add_symbol == alpha_evax_proc.symbol)
          {
            if (range_signed_16 (addend))
@@ -3050,8 +2949,6 @@ load_expression (targreg, exp, pbasereg, poffset, explicit_reloc)
        emit_insn (&insn);
 
 #ifndef OBJ_EVAX
-       emit_lituse = 1;
-
        if (basereg != alpha_gp_register && basereg != AXP_REG_ZERO)
          {
            /* emit "addq r, base, r" */
@@ -3067,14 +2964,12 @@ load_expression (targreg, exp, pbasereg, poffset, explicit_reloc)
       break;
 
     case O_constant:
-      assert (explicit_reloc == (const expressionS *) 0);
       break;
 
     case O_subtract:
       /* Assume that this difference expression will be resolved to an
         absolute value and that that value will fit in 16 bits.  */
 
-      assert (explicit_reloc == (const expressionS *) 0);
       set_tok_reg (newtok[0], targreg);
       newtok[1] = *exp;
       set_tok_preg (newtok[2], basereg);
@@ -3101,8 +2996,9 @@ load_expression (targreg, exp, pbasereg, poffset, explicit_reloc)
   if (!range_signed_32 (addend))
     {
       offsetT lit;
+      long seq_num = next_sequence_num--;
 
-      /* for 64-bit addends, just put it in the literal pool */
+      /* For 64-bit addends, just put it in the literal pool.  */
 
 #ifdef OBJ_EVAX
       /* emit "ldq targreg, lit(basereg)"  */
@@ -3162,6 +3058,7 @@ load_expression (targreg, exp, pbasereg, poffset, explicit_reloc)
 #ifdef OBJ_ELF
       insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL;
 #endif
+      insn.sequence = seq_num;
 
       emit_insn (&insn);
 
@@ -3173,16 +3070,10 @@ load_expression (targreg, exp, pbasereg, poffset, explicit_reloc)
       assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
 
       assert (insn.nfixups < MAX_INSN_FIXUPS);
-      if (insn.nfixups > 0)
-       {
-         memmove (&insn.fixups[1], &insn.fixups[0],
-                  sizeof (struct alpha_fixup) * insn.nfixups);
-       }
+      insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
+      insn.fixups[insn.nfixups].exp.X_op = O_absent;
       insn.nfixups++;
-      insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE;
-      insn.fixups[0].exp.X_op = O_symbol;
-      insn.fixups[0].exp.X_add_symbol = section_symbol (now_seg);
-      insn.fixups[0].exp.X_add_number = LITUSE_BASE;
+      insn.sequence = seq_num;
       emit_lituse = 0;
 
       emit_insn (&insn);
@@ -3262,66 +3153,19 @@ load_expression (targreg, exp, pbasereg, poffset, explicit_reloc)
    large constants.  */
 
 static void
-emit_lda (tok, ntok, opname)
+emit_lda (tok, ntok, unused)
      const expressionS *tok;
      int ntok;
-     const PTR opname;
+     const PTR unused ATTRIBUTE_UNUSED;
 {
   int basereg;
-  const expressionS *reloc = (const expressionS *) 0;
-
-#ifdef RELOC_OP_P
-  if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
-    {
-      const struct alpha_reloc_op_tag *r;
-
-      reloc = &tok[ntok - 1];
-      r = ALPHA_RELOC_TABLE (reloc->X_op);
-      switch (reloc->X_op)
-       {
-       default:
-         as_bad (_("Cannot use !%s!%d with %s"), r->name,
-                 (int) reloc->X_add_number, (const char *) opname);
-
-         reloc = (const expressionS *) 0;
-         ntok--;
-         break;
-
-       case O_literal:
-         ntok--;
-         break;
-
-         /* For lda $x,0($x)!lituse_base!y, don't use load_expression, since
-            it is really too general for our needs.  Instead just generate the
-            lda directly.  */
-       case O_lituse_base:
-         if (ntok != 4
-             || tok[0].X_op != O_register
-             || !is_ir_num (tok[0].X_add_number)
-             || tok[1].X_op != O_constant
-             || tok[2].X_op != O_pregister
-             || !is_ir_num (tok[2].X_add_number))
-           {
-             as_bad (_("bad instruction format for lda !%s!%ld"), r->name,
-                     (long) reloc->X_add_number);
-
-             reloc = (const expressionS *) 0;
-             ntok--;
-             break;
-           }
-
-         emit_loadstore (tok, ntok, "lda");
-         return;
-       }
-    }
-#endif
 
   if (ntok == 2)
     basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
   else
     basereg = tok[2].X_add_number;
 
-  (void) load_expression (tok[0].X_add_number, &tok[1], &basereg, NULL, reloc);
+  (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
@@ -3335,17 +3179,6 @@ emit_ldah (tok, ntok, unused)
 {
   expressionS newtok[3];
 
-#ifdef RELOC_OP_P
-  if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
-    {
-      const expressionS *reloc_exp = &tok[ntok - 1];
-      const struct alpha_reloc_op_tag *r = ALPHA_RELOC_TABLE (reloc_exp->X_op);
-      as_bad (_("Cannot use !%s!%d with %s"), r->name,
-             (int) reloc_exp->X_add_number, "ldah");
-      ntok--;
-    }
-#endif
-
   newtok[0] = tok[0];
   newtok[1] = tok[1];
   set_tok_preg (newtok[2], AXP_REG_ZERO);
@@ -3363,83 +3196,31 @@ emit_ir_load (tok, ntok, opname)
      int ntok;
      const PTR opname;
 {
-  int basereg, lituse;
+  int basereg;
+  long lituse;
   expressionS newtok[3];
   struct alpha_insn insn;
 
-#ifdef RELOC_OP_P
-  const expressionS *reloc = (const expressionS *) 0;
-
-  if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
-    {
-      const struct alpha_reloc_op_tag *r;
-
-      reloc = &tok[ntok - 1];
-      switch (reloc->X_op)
-       {
-       case O_lituse_base:
-         ntok--;
-         break;
-
-       case O_literal:
-         if (strcmp ((const char *) opname, "ldq") == 0)
-           {
-             emit_lda (tok, ntok, opname);
-             return;
-           }
-
-         /* fall through */
-       default:
-         ntok--;
-         r = ALPHA_RELOC_TABLE (reloc->X_op);
-         as_bad (_("Cannot use !%s!%d with %s"), r->name,
-                 (int) reloc->X_add_number, (const char *) opname);
-       }
-    }
-#endif
-
   if (ntok == 2)
     basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
   else
     basereg = tok[2].X_add_number;
 
   lituse = load_expression (tok[0].X_add_number, &tok[1], &basereg,
-                           &newtok[1], (const expressionS *) 0);
+                           &newtok[1]);
 
   newtok[0] = tok[0];
   set_tok_preg (newtok[2], basereg);
 
   assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn);
 
-#ifdef RELOC_OP_P
-  if (reloc)
-    {
-      int nfixups = insn.nfixups;
-      const struct alpha_reloc_op_tag *r = ALPHA_RELOC_TABLE (reloc->X_op);
-
-      assert (nfixups < MAX_INSN_FIXUPS);
-      insn.fixups[nfixups].reloc = r->reloc;
-      insn.fixups[nfixups].exp.X_op = O_symbol;
-      insn.fixups[nfixups].exp.X_add_symbol = section_symbol (now_seg);
-      insn.fixups[nfixups].exp.X_add_number = r->lituse;
-      insn.sequence[nfixups] = reloc->X_add_number;
-      insn.nfixups++;
-    }
-#endif
-
   if (lituse)
     {
       assert (insn.nfixups < MAX_INSN_FIXUPS);
-      if (insn.nfixups > 0)
-       {
-         memmove (&insn.fixups[1], &insn.fixups[0],
-                  sizeof (struct alpha_fixup) * insn.nfixups);
-       }
+      insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
+      insn.fixups[insn.nfixups].exp.X_op = O_absent;
       insn.nfixups++;
-      insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE;
-      insn.fixups[0].exp.X_op = O_symbol;
-      insn.fixups[0].exp.X_add_symbol = section_symbol (now_seg);
-      insn.fixups[0].exp.X_add_number = LITUSE_BASE;
+      insn.sequence = lituse;
     }
 
   emit_insn (&insn);
@@ -3454,25 +3235,11 @@ emit_loadstore (tok, ntok, opname)
      int ntok;
      const PTR opname;
 {
-  int basereg, lituse;
+  int basereg;
+  long lituse;
   expressionS newtok[3];
   struct alpha_insn insn;
 
-#ifdef RELOC_OP_P
-  const expressionS *reloc = (const expressionS *) 0;
-
-  if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
-    {
-      reloc = &tok[--ntok];
-      if (reloc->X_op != O_lituse_base)
-       {
-         const struct alpha_reloc_op_tag *r = &alpha_reloc_op[reloc->X_md];
-         as_bad (_("Cannot use !%s!%d with %s"), r->name,
-                 (int) reloc->X_add_number, (const char *) opname);
-       }
-    }
-#endif
-
   if (ntok == 2)
     basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
   else
@@ -3483,8 +3250,7 @@ emit_loadstore (tok, ntok, opname)
       if (alpha_noat_on)
        as_bad (_("macro requires $at register while noat in effect"));
 
-      lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, &newtok[1],
-                               (const expressionS *) 0);
+      lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, &newtok[1]);
     }
   else
     {
@@ -3497,35 +3263,13 @@ emit_loadstore (tok, ntok, opname)
 
   assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn);
 
-#ifdef RELOC_OP_P
-  if (reloc)
-    {
-      int nfixups = insn.nfixups;
-      const struct alpha_reloc_op_tag *r = ALPHA_RELOC_TABLE (reloc->X_op);
-
-      assert (nfixups < MAX_INSN_FIXUPS);
-      insn.fixups[nfixups].reloc = r->reloc;
-      insn.fixups[nfixups].exp.X_op = O_symbol;
-      insn.fixups[nfixups].exp.X_add_symbol = section_symbol (now_seg);
-      insn.fixups[nfixups].exp.X_add_number = r->lituse;
-      insn.sequence[nfixups] = reloc->X_add_number;
-      insn.nfixups++;
-    }
-#endif
-
   if (lituse)
     {
       assert (insn.nfixups < MAX_INSN_FIXUPS);
-      if (insn.nfixups > 0)
-       {
-         memmove (&insn.fixups[1], &insn.fixups[0],
-                  sizeof (struct alpha_fixup) * insn.nfixups);
-       }
+      insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
+      insn.fixups[insn.nfixups].exp.X_op = O_absent;
       insn.nfixups++;
-      insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE;
-      insn.fixups[0].exp.X_op = O_symbol;
-      insn.fixups[0].exp.X_add_symbol = section_symbol (now_seg);
-      insn.fixups[0].exp.X_add_number = LITUSE_BASE;
+      insn.sequence = lituse;
     }
 
   emit_insn (&insn);
@@ -3544,41 +3288,57 @@ emit_ldXu (tok, ntok, vlgsize)
   else
     {
       expressionS newtok[3];
-
-#ifdef RELOC_OP_P
-      if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
-       {
-         const expressionS *reloc_exp = &tok[ntok - 1];
-         const struct alpha_reloc_op_tag *r
-           = ALPHA_RELOC_TABLE (reloc_exp->X_op);
-
-         as_bad (_("Cannot use !%s!%d with %s"), r->name,
-                 (int) reloc_exp->X_add_number, "ldbu/ldwu");
-         ntok--;
-       }
-#endif
+      struct alpha_insn insn;
+      int basereg;
+      long lituse;
 
       if (alpha_noat_on)
        as_bad (_("macro requires $at register while noat in effect"));
 
+      if (ntok == 2)
+       basereg = (tok[1].X_op == O_constant
+                  ? AXP_REG_ZERO : alpha_gp_register);
+      else
+       basereg = tok[2].X_add_number;
+
       /* emit "lda $at, exp" */
 
-      memcpy (newtok, tok, sizeof (expressionS) * ntok);
-      newtok[0].X_add_number = AXP_REG_AT;
-      assemble_tokens ("lda", newtok, ntok, 1);
+      lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL);
 
       /* emit "ldq_u targ, 0($at)" */
 
       newtok[0] = tok[0];
       set_tok_const (newtok[1], 0);
-      set_tok_preg (newtok[2], AXP_REG_AT);
-      assemble_tokens ("ldq_u", newtok, 3, 1);
+      set_tok_preg (newtok[2], basereg);
+      assemble_tokens_to_insn ("ldq_u", newtok, 3, &insn);
+
+      if (lituse)
+       {
+         assert (insn.nfixups < MAX_INSN_FIXUPS);
+         insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
+         insn.fixups[insn.nfixups].exp.X_op = O_absent;
+         insn.nfixups++;
+         insn.sequence = lituse;
+       }
+
+      emit_insn (&insn);
 
       /* emit "extXl targ, $at, targ" */
 
-      set_tok_reg (newtok[1], AXP_REG_AT);
+      set_tok_reg (newtok[1], basereg);
       newtok[2] = newtok[0];
-      assemble_tokens (extXl_op[(long) vlgsize], newtok, 3, 1);
+      assemble_tokens_to_insn (extXl_op[(long) vlgsize], newtok, 3, &insn);
+
+      if (lituse)
+       {
+         assert (insn.nfixups < MAX_INSN_FIXUPS);
+         insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF;
+         insn.fixups[insn.nfixups].exp.X_op = O_absent;
+         insn.nfixups++;
+         insn.sequence = lituse;
+       }
+
+      emit_insn (&insn);
     }
 }
 
@@ -3673,17 +3433,6 @@ emit_ldil (tok, ntok, unused)
 {
   expressionS newtok[2];
 
-#ifdef RELOC_OP_P
-  if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
-    {
-      const expressionS *reloc_exp = &tok[ntok - 1];
-      const struct alpha_reloc_op_tag *r = ALPHA_RELOC_TABLE (reloc_exp->X_op);
-      as_bad (_("Cannot use !%s!%d with %s"), r->name,
-             (int) reloc_exp->X_add_number, "ldil");
-      ntok--;
-    }
-#endif
-
   memcpy (newtok, tok, sizeof (newtok));
   newtok[1].X_add_number = sign_extend_32 (tok[1].X_add_number);
 
@@ -3705,35 +3454,75 @@ emit_stX (tok, ntok, vlgsize)
   else
     {
       expressionS newtok[3];
+      struct alpha_insn insn;
+      int basereg;
+      long lituse;
 
       if (alpha_noat_on)
        as_bad (_("macro requires $at register while noat in effect"));
 
+      if (ntok == 2)
+       basereg = (tok[1].X_op == O_constant
+                  ? AXP_REG_ZERO : alpha_gp_register);
+      else
+       basereg = tok[2].X_add_number;
+
       /* emit "lda $at, exp" */
 
-      memcpy (newtok, tok, sizeof (expressionS) * ntok);
-      newtok[0].X_add_number = AXP_REG_AT;
-      assemble_tokens ("lda", newtok, ntok, 1);
+      lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL);
 
       /* emit "ldq_u $t9, 0($at)" */
 
       set_tok_reg (newtok[0], AXP_REG_T9);
       set_tok_const (newtok[1], 0);
-      set_tok_preg (newtok[2], AXP_REG_AT);
-      assemble_tokens ("ldq_u", newtok, 3, 1);
+      set_tok_preg (newtok[2], basereg);
+      assemble_tokens_to_insn ("ldq_u", newtok, 3, &insn);
+
+      if (lituse)
+       {
+         assert (insn.nfixups < MAX_INSN_FIXUPS);
+         insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
+         insn.fixups[insn.nfixups].exp.X_op = O_absent;
+         insn.nfixups++;
+         insn.sequence = lituse;
+       }
+
+      emit_insn (&insn);
 
       /* emit "insXl src, $at, $t10" */
 
       newtok[0] = tok[0];
-      set_tok_reg (newtok[1], AXP_REG_AT);
+      set_tok_reg (newtok[1], basereg);
       set_tok_reg (newtok[2], AXP_REG_T10);
-      assemble_tokens (insXl_op[lgsize], newtok, 3, 1);
+      assemble_tokens_to_insn (insXl_op[lgsize], newtok, 3, &insn);
+
+      if (lituse)
+       {
+         assert (insn.nfixups < MAX_INSN_FIXUPS);
+         insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF;
+         insn.fixups[insn.nfixups].exp.X_op = O_absent;
+         insn.nfixups++;
+         insn.sequence = lituse;
+       }
+
+      emit_insn (&insn);
 
       /* emit "mskXl $t9, $at, $t9" */
 
       set_tok_reg (newtok[0], AXP_REG_T9);
       newtok[2] = newtok[0];
-      assemble_tokens (mskXl_op[lgsize], newtok, 3, 1);
+      assemble_tokens_to_insn (mskXl_op[lgsize], newtok, 3, &insn);
+
+      if (lituse)
+       {
+         assert (insn.nfixups < MAX_INSN_FIXUPS);
+         insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF;
+         insn.fixups[insn.nfixups].exp.X_op = O_absent;
+         insn.nfixups++;
+         insn.sequence = lituse;
+       }
+
+      emit_insn (&insn);
 
       /* emit "or $t9, $t10, $t9" */
 
@@ -3742,9 +3531,20 @@ emit_stX (tok, ntok, vlgsize)
 
       /* emit "stq_u $t9, 0($at) */
 
-      set_tok_const (newtok[1], 0);
+      set_tok_const(newtok[1], 0);
       set_tok_preg (newtok[2], AXP_REG_AT);
-      assemble_tokens ("stq_u", newtok, 3, 1);
+      assemble_tokens_to_insn ("stq_u", newtok, 3, &insn);
+
+      if (lituse)
+       {
+         assert (insn.nfixups < MAX_INSN_FIXUPS);
+         insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
+         insn.fixups[insn.nfixups].exp.X_op = O_absent;
+         insn.nfixups++;
+         insn.sequence = lituse;
+       }
+
+      emit_insn (&insn);
     }
 }
 
@@ -3848,19 +3648,6 @@ emit_sextX (tok, ntok, vlgsize)
       int bitshift = 64 - 8 * (1 << lgsize);
       expressionS newtok[3];
 
-#ifdef RELOC_OP_P
-      if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
-       {
-         const expressionS *reloc_exp = &tok[ntok - 1];
-         const struct alpha_reloc_op_tag *r
-           = ALPHA_RELOC_TABLE (reloc_exp->X_op);
-
-         as_bad (_("Cannot use !%s!%d with %s"), r->name,
-                 (int) reloc_exp->X_add_number, "setxt");
-         ntok--;
-       }
-#endif
-
       /* emit "sll src,bits,dst" */
 
       newtok[0] = tok[0];
@@ -3907,17 +3694,6 @@ emit_division (tok, ntok, symname)
   symbolS *sym;
   expressionS newtok[3];
 
-#ifdef RELOC_OP_P
-  if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
-    {
-      const expressionS *reloc_exp = &tok[ntok - 1];
-      const struct alpha_reloc_op_tag *r = ALPHA_RELOC_TABLE (reloc_exp->X_op);
-      as_bad (_("Cannot use !%s!%d with %s"), r->name,
-             (int) reloc_exp->X_add_number, (char char *) symname);
-      ntok--;
-    }
-#endif
-
   xr = regno (tok[0].X_add_number);
   yr = regno (tok[1].X_add_number);
 
@@ -4017,17 +3793,6 @@ emit_division (tok, ntok, symname)
   symbolS *sym;
   expressionS newtok[3];
 
-#ifdef RELOC_OP_P
-  if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
-    {
-      const expressionS *reloc_exp = &tok[ntok - 1];
-      const struct alpha_reloc_op_tag *r = ALPHA_RELOC_TABLE (reloc_exp->X_op);
-      as_bad (_("Cannot use !%s!%d with %s"), r->name,
-             (int) reloc_exp->X_add_number, (const char *) symname);
-      ntok--;
-    }
-#endif
-
   xr = regno (tok[0].X_add_number);
   yr = regno (tok[1].X_add_number);
 
@@ -4122,18 +3887,8 @@ emit_jsrjmp (tok, ntok, vopname)
   const char *opname = (const char *) vopname;
   struct alpha_insn insn;
   expressionS newtok[3];
-  int r, tokidx = 0, lituse = 0;
-
-#ifdef RELOC_OP_P
-  if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
-    {
-      const expressionS *reloc_exp = &tok[ntok - 1];
-      const struct alpha_reloc_op_tag *r = ALPHA_RELOC_TABLE (reloc_exp->X_op);
-      as_bad (_("Cannot use !%s!%d with %s"), r->name,
-             (int) reloc_exp->X_add_number, opname);
-      ntok--;
-    }
-#endif
+  int r, tokidx = 0;
+  long lituse = 0;
 
   if (tokidx < ntok && tok[tokidx].X_op == O_register)
     r = regno (tok[tokidx++].X_add_number);
@@ -4151,8 +3906,7 @@ emit_jsrjmp (tok, ntok, vopname)
   else
     {
       int basereg = alpha_gp_register;
-      lituse = load_expression (r = AXP_REG_PV, &tok[tokidx], &basereg, NULL,
-                               (const expressionS *) 0);
+      lituse = load_expression (r = AXP_REG_PV, &tok[tokidx], &basereg, NULL);
     }
 #endif
 
@@ -4169,20 +3923,13 @@ emit_jsrjmp (tok, ntok, vopname)
 
   assemble_tokens_to_insn (opname, newtok, 3, &insn);
 
-  /* add the LITUSE fixup */
   if (lituse)
     {
       assert (insn.nfixups < MAX_INSN_FIXUPS);
-      if (insn.nfixups > 0)
-       {
-         memmove (&insn.fixups[1], &insn.fixups[0],
-                  sizeof (struct alpha_fixup) * insn.nfixups);
-       }
+      insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_JSR;
+      insn.fixups[insn.nfixups].exp.X_op = O_absent;
       insn.nfixups++;
-      insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE;
-      insn.fixups[0].exp.X_op = O_symbol;
-      insn.fixups[0].exp.X_add_symbol = section_symbol (now_seg);
-      insn.fixups[0].exp.X_add_number = LITUSE_JSR;
+      insn.sequence = lituse;
     }
 
   emit_insn (&insn);
@@ -4201,17 +3948,6 @@ emit_retjcr (tok, ntok, vopname)
   expressionS newtok[3];
   int r, tokidx = 0;
 
-#ifdef RELOC_OP_P
-  if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
-    {
-      const expressionS *reloc_exp = &tok[ntok - 1];
-      const struct alpha_reloc_op_tag *r = ALPHA_RELOC_TABLE (reloc_exp->X_op);
-      as_bad (_("Cannot use !%s!%d with %s"), r->name,
-             (int) reloc_exp->X_add_number, opname);
-      ntok--;
-    }
-#endif
-
   if (tokidx < ntok && tok[tokidx].X_op == O_register)
     r = regno (tok[tokidx++].X_add_number);
   else
index 26739f1..1eabfd0 100644 (file)
@@ -117,11 +117,10 @@ extern void alpha_frob_file_before_adjust PARAMS ((void));
 #define RELOC_OP_P
 #endif
 
-#ifdef RELOC_OP_P
-/* Before the relocations are written, reorder them, so that user supplied
-   !lituse relocations follow the appropriate !literal relocations.  Also
-   convert the gas-internal relocations to the appropriate linker relocations.
-   */
+/* Before the relocations are written, reorder them, so that user
+   supplied !lituse relocations follow the appropriate !literal
+   relocations.  Also convert the gas-internal relocations to the
+   appropriate linker relocations.  */
 #define tc_adjust_symtab() alpha_adjust_symtab ()
 extern void alpha_adjust_symtab PARAMS ((void));
 
@@ -133,14 +132,14 @@ extern void alpha_adjust_symtab PARAMS ((void));
 
 struct alpha_fix_tag
 {
-  struct fix *next_lituse;             /* next !lituse */
-  struct alpha_literal_tag *info;      /* other members with same sequence */
+  struct fix *next_reloc;              /* next !lituse or !gpdisp */
+  struct alpha_reloc_tag *info;                /* other members with same sequence */
 };
 
 /* Initialize the TC_FIX_TYPE field.  */
 #define TC_INIT_FIX_DATA(fixP)                                         \
 do {                                                                   \
-  fixP->tc_fix_data.next_lituse = (struct fix *)0;                     \
+  fixP->tc_fix_data.next_reloc = (struct fix *)0;                      \
   fixP->tc_fix_data.info = (struct alpha_literal_tag *)0;              \
 } while (0)
 
@@ -148,10 +147,9 @@ do {                                                                       \
 #define TC_FIX_DATA_PRINT(stream,fixP)                                 \
 do {                                                                   \
   if (fixP->tc_fix_data.info)                                          \
-    fprintf (stderr, "\tinfo = 0x%lx, next_lituse = 0x%lx\n", \
+    fprintf (stderr, "\tinfo = 0x%lx, next_reloc = 0x%lx\n", \
             (long)fixP->tc_fix_data.info,                              \
-            (long)fixP->tc_fix_data.next_lituse);                      \
+            (long)fixP->tc_fix_data.next_reloc);                       \
 } while (0)
-#endif
 
 #define DWARF2_LINE_MIN_INSN_LENGTH 4
index 11f0a0a..6398610 100644 (file)
@@ -1,3 +1,14 @@
+2001-08-04  Richard Henderson  <rth@redhat.com>
+
+       * gas/alpha/alpha.exp: New file.
+       * gas/alpha/elf-reloc-1.[sd]: New test.
+       * gas/alpha/elf-reloc-2.[sl]: New test.
+       * gas/alpha/elf-reloc-3.[sl]: New test.
+       * gas/alpha/elf-reloc-4.[sd]: New test.
+       * gas/alpha/fp.exp: Remove file.
+       * gas/alpha/fp.s: Output to .data not .rdata.
+       * gas/alpha/fp.d: Adjust to match.
+
 Tue Sep  4 20:06:09 2001  Jeffrey A Law  (law@cygnus.com)
 
        * gas/all/gas.exp (930509a): Expect failure on the H8/300 ELF port.
diff --git a/gas/testsuite/gas/alpha/alpha.exp b/gas/testsuite/gas/alpha/alpha.exp
new file mode 100644 (file)
index 0000000..4bc54f4
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# Some generic alpha tests
+#
+
+proc run_list_test { name opts } {
+    global srcdir subdir
+    set testname "alpha $name"
+    set file $srcdir/$subdir/$name
+    gas_run ${name}.s $opts ">&dump.out"
+    if { [regexp_diff "dump.out" "${file}.l"] } then {
+       fail $testname
+       verbose "output is [file_contents "dump.out"]" 2
+       return
+    }
+    pass $testname
+}
+
+if { [istarget alpha*-*-*] } then {
+
+    set elf [expr [istarget *-*-elf*] \
+                 || [istarget *-*-linux*] \
+                 || [istarget *-*-freebsd*] \
+                 || [istarget *-*-netbsd*] ]
+
+    if $elf {
+       run_dump_test "elf-reloc-1"
+       run_list_test "elf-reloc-2" ""
+       run_list_test "elf-reloc-3" ""
+       run_dump_test "elf-reloc-4"
+    }
+
+    run_dump_test "fp"
+}
diff --git a/gas/testsuite/gas/alpha/elf-reloc-1.d b/gas/testsuite/gas/alpha/elf-reloc-1.d
new file mode 100644 (file)
index 0000000..660f393
--- /dev/null
@@ -0,0 +1,21 @@
+#objdump: -r
+#name: alpha elf-reloc-1
+
+.*:     file format elf64-alpha
+
+RELOCATION RECORDS FOR \[\.text\]:
+OFFSET           TYPE              VALUE 
+0*0000004 ELF_LITERAL       a
+0*0000000 LITUSE            \.text\+0x0*0000002
+0*000000c LITUSE            \.text\+0x0*0000001
+0*0000008 ELF_LITERAL       b
+0*0000010 ELF_LITERAL       f
+0*0000014 LITUSE            \.text\+0x0*0000003
+0*0000014 HINT              f
+0*0000018 GPREL16           c
+0*000001c GPRELHIGH         d
+0*0000020 GPRELLOW          e
+0*0000024 GPDISP            \.text\+0x0*0000008
+0*0000030 GPDISP            \.text\+0xf*ffffff8
+
+
diff --git a/gas/testsuite/gas/alpha/elf-reloc-1.s b/gas/testsuite/gas/alpha/elf-reloc-1.s
new file mode 100644 (file)
index 0000000..7114f57
--- /dev/null
@@ -0,0 +1,16 @@
+       .set nomacro
+       extbl   $3, $2, $3      ! lituse_bytoff  !   1
+       ldq     $2, a($29)      !literal!1
+       ldq     $4, b($29)      !literal!2
+       ldq_u   $3, 0($2)       !lituse_base!1
+       ldq     $27, f($29)     !literal!5
+       jsr     $26, ($27), f   !lituse_jsr!5
+
+       lda     $0, c($29)      !gprel
+       ldah    $1, d($29)      !gprelhigh
+       lda     $1, e($1)       !gprellow
+
+       ldah    $29, 0($26)     !gpdisp!3
+       lda     $29, 0($29)     !gpdisp!4
+       lda     $29, 0($29)     !gpdisp!3
+       ldah    $29, 0($26)     !gpdisp!4
diff --git a/gas/testsuite/gas/alpha/elf-reloc-2.l b/gas/testsuite/gas/alpha/elf-reloc-2.l
new file mode 100644 (file)
index 0000000..8353a7e
--- /dev/null
@@ -0,0 +1,4 @@
+.*: Assembler messages:
+.*:4: Error: too many ldah insns for !gpdisp!3
+.*:5: Error: too many lda insns for !gpdisp!3
+.*:8: Error: both insns for !gpdisp!4 must be in the same section
diff --git a/gas/testsuite/gas/alpha/elf-reloc-2.s b/gas/testsuite/gas/alpha/elf-reloc-2.s
new file mode 100644 (file)
index 0000000..b53b7eb
--- /dev/null
@@ -0,0 +1,8 @@
+       .text
+       ldah    $29,0($26)      !gpdisp!3
+       lda     $29,0($26)      !gpdisp!3
+       ldah    $29,0($26)      !gpdisp!3
+       lda     $29,0($26)      !gpdisp!3
+       ldah    $29,0($26)      !gpdisp!4
+       .section .text2
+       lda     $29,0($26)      !gpdisp!4
diff --git a/gas/testsuite/gas/alpha/elf-reloc-3.l b/gas/testsuite/gas/alpha/elf-reloc-3.l
new file mode 100644 (file)
index 0000000..764dfb7
--- /dev/null
@@ -0,0 +1,3 @@
+.*: Assembler messages:
+.*:2: Error: No ldah !gpdisp!2 was found
+.*:1: Error: No lda !gpdisp!1 was found
diff --git a/gas/testsuite/gas/alpha/elf-reloc-3.s b/gas/testsuite/gas/alpha/elf-reloc-3.s
new file mode 100644 (file)
index 0000000..c3d959e
--- /dev/null
@@ -0,0 +1,2 @@
+       ldah    $29,0($26)      !gpdisp!1
+       lda     $29,0($26)      !gpdisp!2
diff --git a/gas/testsuite/gas/alpha/elf-reloc-4.d b/gas/testsuite/gas/alpha/elf-reloc-4.d
new file mode 100644 (file)
index 0000000..f149298
--- /dev/null
@@ -0,0 +1,25 @@
+#objdump: -r
+#name: alpha elf-reloc-4
+
+.*:     file format elf64-alpha
+
+RELOCATION RECORDS FOR \[\.text\]:
+OFFSET           TYPE              VALUE 
+0*0000000 ELF_LITERAL       a
+0*0000004 LITUSE            \.text\+0x0*0000001
+0*0000008 LITUSE            \.text\+0x0*0000002
+0*000000c ELF_LITERAL       b
+0*0000010 LITUSE            \.text\+0x0*0000001
+0*0000014 LITUSE            \.text\+0x0*0000002
+0*0000018 ELF_LITERAL       c
+0*000001c LITUSE            \.text\+0x0*0000001
+0*0000020 LITUSE            \.text\+0x0*0000002
+0*0000024 LITUSE            \.text\+0x0*0000002
+0*000002c LITUSE            \.text\+0x0*0000001
+0*0000030 ELF_LITERAL       d
+0*0000034 LITUSE            \.text\+0x0*0000001
+0*0000038 LITUSE            \.text\+0x0*0000002
+0*000003c LITUSE            \.text\+0x0*0000002
+0*0000044 LITUSE            \.text\+0x0*0000001
+
+
diff --git a/gas/testsuite/gas/alpha/elf-reloc-4.s b/gas/testsuite/gas/alpha/elf-reloc-4.s
new file mode 100644 (file)
index 0000000..dfd2eeb
--- /dev/null
@@ -0,0 +1,4 @@
+       ldbu    $1, a
+       ldwu    $2, b
+       stb     $3, c
+       stw     $4, d
index 9e6f7e9..06f6c8e 100644 (file)
@@ -1,7 +1,9 @@
+#objdump: -s -j .data
+#name: alpha fp
 
-.*:     file format ecoff-littlealpha
+.*:     file format .*
 
-Contents of section .rdata:
+Contents of section .data:
  0000 71a37909 4f930a40 5441789a cd4b881b  q.y.O..@TAx..K..
  0010 2a404f93 790971a3 789a5440 5441789a  .@O.y.q.x.T@TAx.
  0020 00000000 00000000 00000000 00000000  ................
diff --git a/gas/testsuite/gas/alpha/fp.exp b/gas/testsuite/gas/alpha/fp.exp
deleted file mode 100644 (file)
index 05ec881..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# Alpha OSF/1 tests
-#
-
-if [istarget alpha-*-osf*] then {
-    set testname "fp constants (part 2)"
-    if [gas_test_old "fp.s" "" "fp constants (part 1)"] then {
-       objdump "-s -j .rdata > a.dump"
-       if { [regexp_diff "a.dump" "$srcdir/$subdir/fp.d"] == 0 } then {
-           pass $testname
-       } else {
-           fail $testname
-       }
-    }
-}
index 7cebbbe..e29393e 100644 (file)
@@ -1,4 +1,4 @@
-       .rdata
+       .data
 # These three formats are 8 bytes each.
        .t_floating 3.32192809488736218171e0
 #      .byte 0x71, 0xa3, 0x79, 0x09, 0x4f, 0x93, 0x0a, 0x40