summaryrefslogtreecommitdiffstats
path: root/contrib/binutils/gas/config/tc-alpha.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/binutils/gas/config/tc-alpha.c')
-rw-r--r--contrib/binutils/gas/config/tc-alpha.c1469
1 files changed, 618 insertions, 851 deletions
diff --git a/contrib/binutils/gas/config/tc-alpha.c b/contrib/binutils/gas/config/tc-alpha.c
index ba42aaa..b1a3471 100644
--- a/contrib/binutils/gas/config/tc-alpha.c
+++ b/contrib/binutils/gas/config/tc-alpha.c
@@ -62,7 +62,7 @@
#include "dwarf2dbg.h"
#endif
-#include <ctype.h>
+#include "safe-ctype.h"
/* Local types */
@@ -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,58 @@ 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, REQ, ALLOW) \
+ { #NAME, sizeof(#NAME)-1, O_##NAME, RELOC, REQ, ALLOW}
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 require_seq : 1; /* require a sequence number */
+ unsigned int allow_seq : 1; /* allow 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, 0, 1),
+ DEF(lituse_addr, DUMMY_RELOC_LITUSE_ADDR, 1, 1),
+ DEF(lituse_base, DUMMY_RELOC_LITUSE_BASE, 1, 1),
+ DEF(lituse_bytoff, DUMMY_RELOC_LITUSE_BYTOFF, 1, 1),
+ DEF(lituse_jsr, DUMMY_RELOC_LITUSE_JSR, 1, 1),
+ DEF(gpdisp, BFD_RELOC_ALPHA_GPDISP, 1, 1),
+ DEF(gprelhigh, BFD_RELOC_ALPHA_GPREL_HI16, 0, 0),
+ DEF(gprellow, BFD_RELOC_ALPHA_GPREL_LO16, 0, 0),
+ DEF(gprel, BFD_RELOC_GPREL16, 0, 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 +567,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 +633,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 +723,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 +786,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 +874,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. */
@@ -1158,13 +1118,14 @@ md_pcrel_from (fixP)
the distance to the "lda" instruction for setting the addend to
GPDISP. */
-int
-md_apply_fix (fixP, valueP)
+void
+md_apply_fix3 (fixP, valP, seg)
fixS *fixP;
- valueT *valueP;
+ valueT * valP;
+ segT seg;
{
char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
- valueT value = *valueP;
+ valueT value = * valP;
unsigned image, size;
switch (fixP->fx_r_type)
@@ -1176,10 +1137,13 @@ md_apply_fix (fixP, valueP)
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;
}
@@ -1196,7 +1160,7 @@ md_apply_fix (fixP, valueP)
#endif
do_reloc_gp:
- fixP->fx_addsy = section_symbol (now_seg);
+ fixP->fx_addsy = section_symbol (seg);
md_number_to_chars (fixpos, value, 2);
break;
@@ -1220,7 +1184,7 @@ md_apply_fix (fixP, valueP)
md_number_to_chars (fixpos, value, size);
goto done;
}
- return 1;
+ return;
#ifdef OBJ_ECOFF
case BFD_RELOC_GPREL32:
@@ -1229,11 +1193,13 @@ md_apply_fix (fixP, valueP)
/* 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;
case BFD_RELOC_23_PCREL_S2:
if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
@@ -1242,7 +1208,7 @@ md_apply_fix (fixP, valueP)
image = (image & ~0x1FFFFF) | ((value >> 2) & 0x1FFFFF);
goto write_done;
}
- return 1;
+ return;
case BFD_RELOC_ALPHA_HINT:
if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
@@ -1251,43 +1217,22 @@ md_apply_fix (fixP, valueP)
image = (image & ~0x3FFF) | ((value >> 2) & 0x3FFF);
goto write_done;
}
- return 1;
+ return;
#ifdef OBJ_ECOFF
case BFD_RELOC_ALPHA_LITERAL:
md_number_to_chars (fixpos, value, 2);
- return 1;
-
- case BFD_RELOC_ALPHA_LITUSE:
- return 1;
+ return;
#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
+ return;
case BFD_RELOC_VTABLE_INHERIT:
case BFD_RELOC_VTABLE_ENTRY:
- return 1;
+ return;
default:
{
@@ -1317,7 +1262,7 @@ md_apply_fix (fixP, valueP)
}
if (fixP->fx_addsy != 0 || fixP->fx_pcrel != 0)
- return 1;
+ return;
else
{
as_warn_where (fixP->fx_file, fixP->fx_line,
@@ -1330,12 +1275,9 @@ write_done:
done:
fixP->fx_done = 1;
- return 0;
}
-/*
- * Look for a register name in the given symbol.
- */
+/* Look for a register name in the given symbol. */
symbolS *
md_undefined_symbol (name)
@@ -1354,7 +1296,7 @@ md_undefined_symbol (name)
/* FALLTHRU */
case 'r':
- if (!isdigit (*++name))
+ if (!ISDIGIT (*++name))
break;
/* FALLTHRU */
@@ -1362,7 +1304,7 @@ md_undefined_symbol (name)
case '5': case '6': case '7': case '8': case '9':
if (name[1] == '\0')
num = name[0] - '0';
- else if (name[0] != '0' && isdigit (name[1]) && name[2] == '\0')
+ else if (name[0] != '0' && ISDIGIT (name[1]) && name[2] == '\0')
{
num = (name[0] - '0') * 10 + name[1] - '0';
if (num >= 32)
@@ -1423,7 +1365,7 @@ alpha_define_label (sym)
}
/* Return true if we must always emit a reloc for a type and false if
- there is some hope of resolving it a assembly time. */
+ there is some hope of resolving it at assembly time. */
int
alpha_force_relocation (f)
@@ -1437,27 +1379,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;
@@ -1496,35 +1426,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:
@@ -1591,7 +1507,8 @@ tc_gen_reloc (sec, fixp)
* at assembly time. bfd_perform_reloc doesn't know about this sort
* of thing, and as a result we need to fake it out here.
*/
- if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy))
+ if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)
+ || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE))
&& !S_IS_COMMON (fixp->fx_addsy))
reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value;
#endif
@@ -1649,31 +1566,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)
@@ -1685,14 +1616,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
@@ -1704,121 +1629,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
@@ -1875,7 +1773,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;
@@ -1908,13 +1806,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);
@@ -1922,6 +1818,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 ();
@@ -1944,59 +1845,66 @@ 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;
-
- /* Parse !sequence_number */
- memset (tok, '\0', sizeof (expressionS));
- expression (tok);
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != '!')
+ {
+ if (r->require_seq)
+ {
+ as_bad (_("no sequence number after !%s"), p);
+ goto err_report;
+ }
- if (tok->X_op != O_constant
- || ! ALPHA_RELOC_SEQUENCE_OK (tok->X_add_number))
+ tok->X_add_number = 0;
+ }
+ else
{
- as_bad (_("Bad sequence number: !%s!%s"),
- r->name, input_line_pointer);
- goto err_report;
+ if (! r->allow_seq)
+ {
+ as_bad (_("!%s does not use a sequence number"), p);
+ goto err_report;
+ }
+
+ input_line_pointer++;
+
+ /* Parse !sequence_number */
+ expression (tok);
+ if (tok->X_op != O_constant || tok->X_add_number <= 0)
+ {
+ as_bad (_("Bad sequence number: !%s!%s"),
+ r->name, input_line_pointer);
+ goto err_report;
+ }
}
tok->X_op = r->op;
reloc_found_p = 1;
++tok;
break;
-#endif
+#endif /* RELOC_OP_P */
case ',':
++input_line_pointer;
@@ -2048,18 +1956,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
@@ -2247,7 +2162,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:
@@ -2255,7 +2169,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:
@@ -2264,38 +2178,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;
@@ -2370,12 +2252,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;
@@ -2431,24 +2316,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;
}
@@ -2483,12 +2429,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)
@@ -2497,43 +2440,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);
@@ -2542,79 +2466,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)
@@ -2650,7 +2570,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)
@@ -2677,9 +2597,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));
@@ -2695,17 +2621,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)
@@ -2715,18 +2630,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);
}
@@ -2761,17 +2683,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);
@@ -2795,6 +2706,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);
@@ -2809,6 +2721,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 */
@@ -2888,18 +2801,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;
@@ -2949,9 +2862,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)" */
@@ -2988,25 +2901,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))
@@ -3048,8 +2950,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" */
@@ -3065,14 +2965,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);
@@ -3099,8 +2997,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)" */
@@ -3160,6 +3059,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);
@@ -3171,16 +3071,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);
@@ -3260,66 +3154,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
@@ -3333,17 +3180,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);
@@ -3361,83 +3197,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);
@@ -3452,25 +3236,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
@@ -3481,8 +3251,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
{
@@ -3495,35 +3264,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);
@@ -3542,41 +3289,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);
}
}
@@ -3671,17 +3434,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);
@@ -3703,35 +3455,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" */
@@ -3740,9 +3532,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);
}
}
@@ -3846,19 +3649,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];
@@ -3905,17 +3695,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);
@@ -4015,17 +3794,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);
@@ -4120,18 +3888,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);
@@ -4149,8 +3907,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
@@ -4167,20 +3924,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);
@@ -4199,17 +3949,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
@@ -4472,7 +4211,7 @@ s_alpha_ent (dummy)
input_line_pointer++;
SKIP_WHITESPACE ();
}
- if (isdigit (*input_line_pointer) || *input_line_pointer == '-')
+ if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
(void) get_absolute_expression ();
}
demand_empty_rest_of_line ();
@@ -5657,6 +5396,34 @@ select_gp_value ()
}
#endif /* OBJ_ECOFF */
+#ifdef OBJ_ELF
+/* Map 's' to SHF_ALPHA_GPREL. */
+
+int
+alpha_elf_section_letter (letter, ptr_msg)
+ int letter;
+ char **ptr_msg;
+{
+ if (letter == 's')
+ return SHF_ALPHA_GPREL;
+
+ *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S in string");
+ return 0;
+}
+
+/* Map SHF_ALPHA_GPREL to SEC_SMALL_DATA. */
+
+flagword
+alpha_elf_section_flags (flags, attr, type)
+ flagword flags;
+ int attr, type ATTRIBUTE_UNUSED;
+{
+ if (attr & SHF_ALPHA_GPREL)
+ flags |= SEC_SMALL_DATA;
+ return flags;
+}
+#endif /* OBJ_ELF */
+
/* Called internally to handle all alignment needs. This takes care
of eliding calls to frag_align if'n the cached current alignment
says we've already got it, as well as taking care of the auto-align
@@ -5703,10 +5470,10 @@ void
alpha_handle_align (fragp)
fragS *fragp;
{
- static char const unop[4] = { 0x00, 0x00, 0xe0, 0x2f };
+ static char const unop[4] = { 0x00, 0x00, 0xfe, 0x2f };
static char const nopunop[8] = {
0x1f, 0x04, 0xff, 0x47,
- 0x00, 0x00, 0xe0, 0x2f
+ 0x00, 0x00, 0xfe, 0x2f
};
int bytes, fix;
OpenPOWER on IntegriCloud