aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2001-09-05 02:39:43 +0000
committerRichard Henderson <rth@redhat.com>2001-09-05 02:39:43 +0000
commit19f785835e5e97a7c666e8f942cb4ec8e543aebc (patch)
tree2449f5d4aa18964c87052a617c6f0af5b3191e54 /gas
parentb8720f9d577e623c5e7203ec586f19a06b5e7399 (diff)
downloadgdb-19f785835e5e97a7c666e8f942cb4ec8e543aebc.zip
gdb-19f785835e5e97a7c666e8f942cb4ec8e543aebc.tar.gz
gdb-19f785835e5e97a7c666e8f942cb4ec8e543aebc.tar.bz2
* 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. * 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.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog32
-rw-r--r--gas/config/tc-alpha.c1380
-rw-r--r--gas/config/tc-alpha.h20
-rw-r--r--gas/testsuite/ChangeLog11
-rw-r--r--gas/testsuite/gas/alpha/alpha.exp33
-rw-r--r--gas/testsuite/gas/alpha/elf-reloc-1.d21
-rw-r--r--gas/testsuite/gas/alpha/elf-reloc-1.s16
-rw-r--r--gas/testsuite/gas/alpha/elf-reloc-2.l4
-rw-r--r--gas/testsuite/gas/alpha/elf-reloc-2.s8
-rw-r--r--gas/testsuite/gas/alpha/elf-reloc-3.l3
-rw-r--r--gas/testsuite/gas/alpha/elf-reloc-3.s2
-rw-r--r--gas/testsuite/gas/alpha/elf-reloc-4.d25
-rw-r--r--gas/testsuite/gas/alpha/elf-reloc-4.s4
-rw-r--r--gas/testsuite/gas/alpha/fp.d6
-rw-r--r--gas/testsuite/gas/alpha/fp.exp15
-rw-r--r--gas/testsuite/gas/alpha/fp.s2
16 files changed, 731 insertions, 851 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 0e61a6b..65232cc 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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
diff --git a/gas/config/tc-alpha.c b/gas/config/tc-alpha.c
index add17c8..9c62923 100644
--- a/gas/config/tc-alpha.c
+++ b/gas/config/tc-alpha.c
@@ -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 {
/* 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
/* 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;
/* 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 */
-#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);
}
-
-/* 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 */
#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
diff --git a/gas/config/tc-alpha.h b/gas/config/tc-alpha.h
index 26739f1..1eabfd0 100644
--- a/gas/config/tc-alpha.h
+++ b/gas/config/tc-alpha.h
@@ -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
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index 11f0a0a..6398610 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -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
index 0000000..4bc54f4
--- /dev/null
+++ b/gas/testsuite/gas/alpha/alpha.exp
@@ -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
index 0000000..660f393
--- /dev/null
+++ b/gas/testsuite/gas/alpha/elf-reloc-1.d
@@ -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
index 0000000..7114f57
--- /dev/null
+++ b/gas/testsuite/gas/alpha/elf-reloc-1.s
@@ -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
index 0000000..8353a7e
--- /dev/null
+++ b/gas/testsuite/gas/alpha/elf-reloc-2.l
@@ -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
index 0000000..b53b7eb
--- /dev/null
+++ b/gas/testsuite/gas/alpha/elf-reloc-2.s
@@ -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
index 0000000..764dfb7
--- /dev/null
+++ b/gas/testsuite/gas/alpha/elf-reloc-3.l
@@ -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
index 0000000..c3d959e
--- /dev/null
+++ b/gas/testsuite/gas/alpha/elf-reloc-3.s
@@ -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
index 0000000..f149298
--- /dev/null
+++ b/gas/testsuite/gas/alpha/elf-reloc-4.d
@@ -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
index 0000000..dfd2eeb
--- /dev/null
+++ b/gas/testsuite/gas/alpha/elf-reloc-4.s
@@ -0,0 +1,4 @@
+ ldbu $1, a
+ ldwu $2, b
+ stb $3, c
+ stw $4, d
diff --git a/gas/testsuite/gas/alpha/fp.d b/gas/testsuite/gas/alpha/fp.d
index 9e6f7e9..06f6c8e 100644
--- a/gas/testsuite/gas/alpha/fp.d
+++ b/gas/testsuite/gas/alpha/fp.d
@@ -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
index 05ec881..0000000
--- a/gas/testsuite/gas/alpha/fp.exp
+++ /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
- }
- }
-}
diff --git a/gas/testsuite/gas/alpha/fp.s b/gas/testsuite/gas/alpha/fp.s
index 7cebbbe..e29393e 100644
--- a/gas/testsuite/gas/alpha/fp.s
+++ b/gas/testsuite/gas/alpha/fp.s
@@ -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