/* tc-alpha.c - Processor-specific code for the DEC Alpha AXP CPU.
- Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
+ Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Carnegie Mellon University, 1993.
Written by Alessandro Forin, based on earlier gas-1.38 target CPU files.
Modified by Ken Raeburn for gas-2.x and ECOFF support.
#include "safe-ctype.h"
\f
-/* Local types */
+/* Local types. */
#define TOKENIZE_ERROR -1
#define TOKENIZE_ERROR_REPORT -2
#define MAX_INSN_FIXUPS 2
#define MAX_INSN_ARGS 5
-struct alpha_fixup {
+struct alpha_fixup
+{
expressionS exp;
bfd_reloc_code_real_type reloc;
};
-struct alpha_insn {
+struct alpha_insn
+{
unsigned insn;
int nfixups;
struct alpha_fixup fixups[MAX_INSN_FIXUPS];
long sequence;
};
-enum alpha_macro_arg {
- MACRO_EOA = 1,
- MACRO_IR,
- MACRO_PIR,
- MACRO_OPIR,
- MACRO_CPIR,
- MACRO_FPR,
- MACRO_EXP,
-};
+enum alpha_macro_arg
+ {
+ MACRO_EOA = 1,
+ MACRO_IR,
+ MACRO_PIR,
+ MACRO_OPIR,
+ MACRO_CPIR,
+ MACRO_FPR,
+ MACRO_EXP,
+ };
-struct alpha_macro {
+struct alpha_macro
+{
const char *name;
void (*emit) PARAMS ((const expressionS *, int, const PTR));
const PTR arg;
#define O_pregister O_md1 /* O_register, in parentheses */
#define O_cpregister O_md2 /* + a leading comma */
-/* Note, the alpha_reloc_op table below depends on the ordering
- of O_literal .. O_gpre16. */
+/* The alpha_reloc_op table below depends on the ordering of these. */
#define O_literal O_md3 /* !literal relocation */
#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 O_lituse_tlsgd O_md8 /* !lituse_tlsgd relocation */
+#define O_lituse_tlsldm O_md9 /* !lituse_tlsldm relocation */
+#define O_gpdisp O_md10 /* !gpdisp relocation */
+#define O_gprelhigh O_md11 /* !gprelhigh relocation */
+#define O_gprellow O_md12 /* !gprellow relocation */
+#define O_gprel O_md13 /* !gprel relocation */
+#define O_samegp O_md14 /* !samegp relocation */
+#define O_tlsgd O_md15 /* !tlsgd relocation */
+#define O_tlsldm O_md16 /* !tlsldm relocation */
+#define O_gotdtprel O_md17 /* !gotdtprel relocation */
+#define O_dtprelhi O_md18 /* !dtprelhi relocation */
+#define O_dtprello O_md19 /* !dtprello relocation */
+#define O_dtprel O_md20 /* !dtprel relocation */
+#define O_gottprel O_md21 /* !gottprel relocation */
+#define O_tprelhi O_md22 /* !tprelhi relocation */
+#define O_tprello O_md23 /* !tprello relocation */
+#define O_tprel O_md24 /* !tprel 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 DUMMY_RELOC_LITUSE_TLSGD (BFD_RELOC_UNUSED + 5)
+#define DUMMY_RELOC_LITUSE_TLSLDM (BFD_RELOC_UNUSED + 6)
-#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_tprel)
-#define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_gprel)
-
-/* Macros for extracting the type and number of encoded register tokens */
+/* Macros for extracting the type and number of encoded register tokens. */
#define is_ir_num(x) (((x) & 32) == 0)
#define is_fpr_num(x) (((x) & 32) != 0)
#define regno(x) ((x) & 31)
-/* Something odd inherited from the old assembler */
+/* Something odd inherited from the old assembler. */
#define note_gpreg(R) (alpha_gprmask |= (1 << (R)))
#define note_fpreg(R) (alpha_fprmask |= (1 << (R)))
^ 0x80000000) - 0x80000000)
#endif
-/* Macros to build tokens */
+/* Macros to build tokens. */
#define set_tok_reg(t, r) (memset (&(t), 0, sizeof (t)), \
(t).X_op = O_register, \
(t).X_op = O_constant, \
(t).X_add_number = (n))
\f
-/* Prototypes for all local functions */
+/* 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 void alpha_adjust_relocs PARAMS ((bfd *, asection *, PTR));
static int tokenize_arguments PARAMS ((char *, expressionS *, int));
static const struct alpha_opcode *find_opcode_match
const char *md_shortopts = "Fm:gG:";
#endif
-struct option md_longopts[] = {
+struct option md_longopts[] =
+ {
#define OPTION_32ADDR (OPTION_MD_BASE)
- { "32addr", no_argument, NULL, OPTION_32ADDR },
+ { "32addr", no_argument, NULL, OPTION_32ADDR },
#define OPTION_RELAX (OPTION_32ADDR + 1)
- { "relax", no_argument, NULL, OPTION_RELAX },
+ { "relax", no_argument, NULL, OPTION_RELAX },
#ifdef OBJ_ELF
#define OPTION_MDEBUG (OPTION_RELAX + 1)
#define OPTION_NO_MDEBUG (OPTION_MDEBUG + 1)
- { "mdebug", no_argument, NULL, OPTION_MDEBUG },
- { "no-mdebug", no_argument, NULL, OPTION_NO_MDEBUG },
+ { "mdebug", no_argument, NULL, OPTION_MDEBUG },
+ { "no-mdebug", no_argument, NULL, OPTION_NO_MDEBUG },
#endif
- { NULL, no_argument, NULL, 0 }
-};
+ { NULL, no_argument, NULL, 0 }
+ };
size_t md_longopts_size = sizeof (md_longopts);
\f
#define AXP_REG_GP AXP_REG_PV
#endif /* OBJ_EVAX */
-/* The cpu for which we are generating code */
+/* The cpu for which we are generating code. */
static unsigned alpha_target = AXP_OPCODE_BASE;
static const char *alpha_target_name = "<all>";
-/* The hash table of instruction opcodes */
+/* The hash table of instruction opcodes. */
static struct hash_control *alpha_opcode_hash;
-/* The hash table of macro opcodes */
+/* The hash table of macro opcodes. */
static struct hash_control *alpha_macro_hash;
#ifdef OBJ_ECOFF
-/* The $gp relocation symbol */
+/* The $gp relocation symbol. */
static symbolS *alpha_gp_symbol;
/* XXX: what is this, and why is it exported? */
valueT alpha_gp_value;
#endif
-/* The current $gp register */
+/* The current $gp register. */
static int alpha_gp_register = AXP_REG_GP;
-/* A table of the register symbols */
+/* A table of the register symbols. */
static symbolS *alpha_register_table[64];
-/* Constant sections, or sections of constants */
+/* Constant sections, or sections of constants. */
#ifdef OBJ_ECOFF
static segT alpha_lita_section;
-static segT alpha_lit4_section;
#endif
#ifdef OBJ_EVAX
static segT alpha_link_section;
/* Symbols referring to said sections. */
#ifdef OBJ_ECOFF
static symbolS *alpha_lita_symbol;
-static symbolS *alpha_lit4_symbol;
#endif
#ifdef OBJ_EVAX
static symbolS *alpha_link_symbol;
#endif
static symbolS *alpha_lit8_symbol;
-/* Literal for .litX+0x8000 within .lita */
+/* Literal for .litX+0x8000 within .lita. */
#ifdef OBJ_ECOFF
-static offsetT alpha_lit4_literal;
static offsetT alpha_lit8_literal;
#endif
static symbolS *alpha_cur_ent_sym;
#endif
-/* Is the assembler not allowed to use $at? */
+/* Is the assembler not allowed to use $at? */
static int alpha_noat_on = 0;
-/* Are macros enabled? */
+/* Are macros enabled? */
static int alpha_macros_on = 1;
-/* Are floats disabled? */
+/* Are floats disabled? */
static int alpha_nofloats_on = 0;
-/* Are addresses 32 bit? */
+/* Are addresses 32 bit? */
static int alpha_addr32_on = 0;
/* Symbol labelling the current insn. When the Alpha gas sees
static int alpha_flag_show_after_trunc = 0; /* -H */
/* If the -+ switch is given, then a hash is appended to any name that is
- * longer than 64 characters, else longer symbol names are truncated.
- */
+ longer than 64 characters, else longer symbol names are truncated. */
#endif
\f
#define DEF(NAME, RELOC, REQ, ALLOW) \
{ #NAME, sizeof(#NAME)-1, O_##NAME, RELOC, REQ, ALLOW}
-static const struct alpha_reloc_op_tag {
+static const struct alpha_reloc_op_tag
+{
const char *name; /* string to lookup */
size_t length; /* size of the string */
operatorT op; /* which operator to use */
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[] = {
+}
+alpha_reloc_op[] =
+{
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(lituse_tlsgd, DUMMY_RELOC_LITUSE_TLSGD, 1, 1),
+ DEF(lituse_tlsldm, DUMMY_RELOC_LITUSE_TLSLDM, 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)
+ DEF(gprel, BFD_RELOC_GPREL16, 0, 0),
+ DEF(samegp, BFD_RELOC_ALPHA_BRSGP, 0, 0),
+ DEF(tlsgd, BFD_RELOC_ALPHA_TLSGD, 0, 1),
+ DEF(tlsldm, BFD_RELOC_ALPHA_TLSLDM, 0, 1),
+ DEF(gotdtprel, BFD_RELOC_ALPHA_GOTDTPREL16, 0, 0),
+ DEF(dtprelhi, BFD_RELOC_ALPHA_DTPREL_HI16, 0, 0),
+ DEF(dtprello, BFD_RELOC_ALPHA_DTPREL_LO16, 0, 0),
+ DEF(dtprel, BFD_RELOC_ALPHA_DTPREL16, 0, 0),
+ DEF(gottprel, BFD_RELOC_ALPHA_GOTTPREL16, 0, 0),
+ DEF(tprelhi, BFD_RELOC_ALPHA_TPREL_HI16, 0, 0),
+ DEF(tprello, BFD_RELOC_ALPHA_TPREL_LO16, 0, 0),
+ DEF(tprel, BFD_RELOC_ALPHA_TPREL16, 0, 0),
};
#undef DEF
/* Structure to hold explict sequence information. */
struct alpha_reloc_tag
{
- fixS *slaves; /* head of linked list of !literals */
+ fixS *master; /* the literal reloc */
+ fixS *slaves; /* head of linked list of lituses */
segT segment; /* segment relocs are in or undefined_section*/
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 */
+ unsigned saw_tlsgd : 1; /* true if ... */
+ unsigned saw_tlsldm : 1;
+ unsigned saw_lu_tlsgd : 1;
+ unsigned saw_lu_tlsldm : 1;
+ unsigned multi_section_p : 1; /* true if more than one section was used */
char string[1]; /* printable form of sequence to hash with */
};
\f
/* A table of CPU names and opcode sets. */
-static const struct cpu_type {
+static const struct cpu_type
+{
const char *name;
unsigned flags;
-} cpu_types[] = {
+}
+cpu_types[] =
+{
/* Ad hoc convention: cpu number gets palcode, process code doesn't.
This supports usage under DU 4.0b that does ".arch ev4", and
usage in MILO that does -m21064. Probably something more
|AXP_OPCODE_MAX) },
{ "21264", (AXP_OPCODE_BASE|AXP_OPCODE_EV6|AXP_OPCODE_BWX
|AXP_OPCODE_MAX|AXP_OPCODE_CIX) },
+ { "21264a", (AXP_OPCODE_BASE|AXP_OPCODE_EV6|AXP_OPCODE_BWX
+ |AXP_OPCODE_MAX|AXP_OPCODE_CIX) },
+ { "21264b", (AXP_OPCODE_BASE|AXP_OPCODE_EV6|AXP_OPCODE_BWX
+ |AXP_OPCODE_MAX|AXP_OPCODE_CIX) },
{ "ev4", AXP_OPCODE_BASE },
{ "ev45", AXP_OPCODE_BASE },
{ "ev56", AXP_OPCODE_BASE|AXP_OPCODE_BWX },
{ "pca56", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX },
{ "ev6", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX|AXP_OPCODE_CIX },
+ { "ev67", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX|AXP_OPCODE_CIX },
+ { "ev68", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX|AXP_OPCODE_CIX },
{ "all", AXP_OPCODE_BASE },
{ 0, 0 }
/* The macro table */
-static const struct alpha_macro alpha_macros[] = {
+static const struct alpha_macro alpha_macros[] =
+{
/* Load/Store macros */
{ "lda", emit_lda, NULL,
{ MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
assert (e.X_op == O_max);
}
- /* Create the opcode hash table */
-
+ /* Create the opcode hash table. */
alpha_opcode_hash = hash_new ();
for (i = 0; i < alpha_num_opcodes;)
{
continue;
}
- /* Create the macro hash table */
-
+ /* Create the macro hash table. */
alpha_macro_hash = hash_new ();
for (i = 0; i < alpha_num_macros;)
{
continue;
}
- /* Construct symbols for each of the registers */
-
+ /* Construct symbols for each of the registers. */
for (i = 0; i < 32; ++i)
{
char name[4];
+
sprintf (name, "$%d", i);
alpha_register_table[i] = symbol_create (name, reg_section, i,
&zero_address_frag);
for (; i < 64; ++i)
{
char name[5];
+
sprintf (name, "$f%d", i - 32);
alpha_register_table[i] = symbol_create (name, reg_section, i,
&zero_address_frag);
}
- /* Create the special symbols and sections we'll be using */
+ /* Create the special symbols and sections we'll be using. */
/* So .sbss will get used for tiny objects. */
bfd_set_gp_size (stdoutput, g_switch_value);
md_assemble (str)
char *str;
{
- char opname[32]; /* current maximum is 13 */
+ char opname[32]; /* Current maximum is 13. */
expressionS tok[MAX_INSN_ARGS];
int ntok, trunclen;
size_t opnamelen;
- /* split off the opcode */
+ /* Split off the opcode. */
opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/46819");
trunclen = (opnamelen < sizeof (opname) - 1
? opnamelen
memcpy (opname, str, trunclen);
opname[trunclen] = '\0';
- /* tokenize the rest of the line */
+ /* Tokenize the rest of the line. */
if ((ntok = tokenize_arguments (str + opnamelen, tok, MAX_INSN_ARGS)) < 0)
{
if (ntok != TOKENIZE_ERROR_REPORT)
return;
}
- /* finish it off */
+ /* Finish it off. */
assemble_tokens (opname, tok, ntok, alpha_macros_on);
}
of LITTLENUMS emitted is stored in *SIZEP. An error message is
returned, or NULL on OK. */
-/* Equal to MAX_PRECISION in atof-ieee.c */
+/* Equal to MAX_PRECISION in atof-ieee.c. */
#define MAX_LITTLENUMS 6
extern char *vax_md_atof PARAMS ((int, char *, int *));
Alpha options:\n\
-32addr treat addresses as 32-bit values\n\
-F lack floating point instructions support\n\
--mev4 | -mev45 | -mev5 | -mev56 | -mpca56 | -mev6 | -mall\n\
+-mev4 | -mev45 | -mev5 | -mev56 | -mpca56 | -mev6 | -mev67 | -mev68 | -mall\n\
specify variant of Alpha architecture\n\
--m21064 | -m21066 | -m21164 | -m21164a | -m21164pc | -m21264\n\
+-m21064 | -m21066 | -m21164 | -m21164a | -m21164pc | -m21264 | -m21264a | -m21264b\n\
these variants include PALcode opcodes\n"),
stream);
#ifdef OBJ_EVAX
valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
switch (fixP->fx_r_type)
{
- case BFD_RELOC_ALPHA_GPDISP:
- case BFD_RELOC_ALPHA_GPDISP_HI16:
- case BFD_RELOC_ALPHA_GPDISP_LO16:
- return addr;
+ case BFD_RELOC_23_PCREL_S2:
+ case BFD_RELOC_ALPHA_HINT:
+ case BFD_RELOC_ALPHA_BRSGP:
+ return addr + 4;
default:
- return fixP->fx_size + addr;
+ return addr;
}
}
the distance to the "lda" instruction for setting the addend to
GPDISP. */
-int
-md_apply_fix3 (fixP, valueP, seg)
+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)
{
/* The GPDISP relocations are processed internally with a symbol
- referring to the current function; we need to drop in a value
- which, when added to the address of the start of the function,
- gives the desired GP. */
+ referring to the current function's section; we need to drop
+ in a value which, when added to the address of the start of
+ the function, gives the desired GP. */
case BFD_RELOC_ALPHA_GPDISP_HI16:
{
fixS *next = fixP->fx_next;
md_number_to_chars (fixpos, value, size);
goto done;
}
- return 1;
+ return;
#ifdef OBJ_ECOFF
case BFD_RELOC_GPREL32:
case BFD_RELOC_GPREL16:
case BFD_RELOC_ALPHA_GPREL_HI16:
case BFD_RELOC_ALPHA_GPREL_LO16:
- return 1;
+ return;
case BFD_RELOC_23_PCREL_S2:
if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
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)
image = (image & ~0x3FFF) | ((value >> 2) & 0x3FFF);
goto write_done;
}
- return 1;
+ return;
+
+#ifdef OBJ_ELF
+ case BFD_RELOC_ALPHA_BRSGP:
+ return;
+
+ case BFD_RELOC_ALPHA_TLSGD:
+ case BFD_RELOC_ALPHA_TLSLDM:
+ case BFD_RELOC_ALPHA_GOTDTPREL16:
+ case BFD_RELOC_ALPHA_DTPREL_HI16:
+ case BFD_RELOC_ALPHA_DTPREL_LO16:
+ case BFD_RELOC_ALPHA_DTPREL16:
+ case BFD_RELOC_ALPHA_GOTTPREL16:
+ case BFD_RELOC_ALPHA_TPREL_HI16:
+ case BFD_RELOC_ALPHA_TPREL_LO16:
+ case BFD_RELOC_ALPHA_TPREL16:
+ if (fixP->fx_addsy)
+ S_SET_THREAD_LOCAL (fixP->fx_addsy);
+ return;
+#endif
#ifdef OBJ_ECOFF
case BFD_RELOC_ALPHA_LITERAL:
md_number_to_chars (fixpos, value, 2);
- return 1;
+ return;
#endif
case BFD_RELOC_ALPHA_ELF_LITERAL:
case BFD_RELOC_ALPHA_LITUSE:
case BFD_RELOC_ALPHA_LINKAGE:
case BFD_RELOC_ALPHA_CODEADDR:
- return 1;
+ return;
case BFD_RELOC_VTABLE_INHERIT:
case BFD_RELOC_VTABLE_ENTRY:
- return 1;
+ return;
default:
{
}
if (fixP->fx_addsy != 0 || fixP->fx_pcrel != 0)
- return 1;
+ return;
else
{
as_warn_where (fixP->fx_file, fixP->fx_line,
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)
}
/* 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)
case BFD_RELOC_ALPHA_GPREL_LO16:
case BFD_RELOC_ALPHA_LINKAGE:
case BFD_RELOC_ALPHA_CODEADDR:
- case BFD_RELOC_VTABLE_INHERIT:
- case BFD_RELOC_VTABLE_ENTRY:
+ case BFD_RELOC_ALPHA_BRSGP:
+ case BFD_RELOC_ALPHA_TLSGD:
+ case BFD_RELOC_ALPHA_TLSLDM:
+ case BFD_RELOC_ALPHA_GOTDTPREL16:
+ case BFD_RELOC_ALPHA_DTPREL_HI16:
+ case BFD_RELOC_ALPHA_DTPREL_LO16:
+ case BFD_RELOC_ALPHA_DTPREL16:
+ case BFD_RELOC_ALPHA_GOTTPREL16:
+ case BFD_RELOC_ALPHA_TPREL_HI16:
+ case BFD_RELOC_ALPHA_TPREL_LO16:
+ case BFD_RELOC_ALPHA_TPREL16:
return 1;
- case BFD_RELOC_23_PCREL_S2:
- case BFD_RELOC_32:
- case BFD_RELOC_64:
- case BFD_RELOC_ALPHA_HINT:
- return 0;
-
default:
- assert ((int) f->fx_r_type < 0
- && -(int) f->fx_r_type < (int) alpha_num_operands);
- return 0;
+ break;
}
+
+ return generic_force_reloc (f);
}
/* Return true if we can partially resolve a relocation now. */
alpha_fix_adjustable (f)
fixS *f;
{
-#ifdef OBJ_ELF
- /* Prevent all adjustments to global symbols */
- if (S_IS_EXTERN (f->fx_addsy) || S_IS_WEAK (f->fx_addsy))
- return 0;
-#endif
-
/* Are there any relocation types for which we must generate a reloc
but we can adjust the values contained within it? */
switch (f->fx_r_type)
case BFD_RELOC_ALPHA_HINT:
return 1;
+ case BFD_RELOC_ALPHA_TLSGD:
+ case BFD_RELOC_ALPHA_TLSLDM:
+ case BFD_RELOC_ALPHA_GOTDTPREL16:
+ case BFD_RELOC_ALPHA_DTPREL_HI16:
+ case BFD_RELOC_ALPHA_DTPREL_LO16:
+ case BFD_RELOC_ALPHA_DTPREL16:
+ case BFD_RELOC_ALPHA_GOTTPREL16:
+ case BFD_RELOC_ALPHA_TPREL_HI16:
+ case BFD_RELOC_ALPHA_TPREL_LO16:
+ case BFD_RELOC_ALPHA_TPREL16:
+ /* ??? No idea why we can't return a reference to .tbss+10, but
+ we're preventing this in the other assemblers. Follow for now. */
+ return 0;
+
+#ifdef OBJ_ELF
+ case BFD_RELOC_ALPHA_BRSGP:
+ /* If we have a BRSGP reloc to a local symbol, adjust it to BRADDR and
+ let it get resolved at assembly time. */
+ {
+ symbolS *sym = f->fx_addsy;
+ const char *name;
+ int offset = 0;
+
+ if (generic_force_reloc (f))
+ return 0;
+
+ switch (S_GET_OTHER (sym) & STO_ALPHA_STD_GPLOAD)
+ {
+ case STO_ALPHA_NOPV:
+ break;
+ case STO_ALPHA_STD_GPLOAD:
+ offset = 8;
+ break;
+ default:
+ if (S_IS_LOCAL (sym))
+ name = "<local>";
+ else
+ name = S_GET_NAME (sym);
+ as_bad_where (f->fx_file, f->fx_line,
+ _("!samegp reloc against symbol without .prologue: %s"),
+ name);
+ break;
+ }
+ f->fx_r_type = BFD_RELOC_23_PCREL_S2;
+ f->fx_offset += offset;
+ return 1;
+ }
+#endif
+
default:
- assert ((int) f->fx_r_type < 0
- && - (int) f->fx_r_type < (int) alpha_num_operands);
return 1;
}
/*NOTREACHED*/
#ifdef OBJ_ECOFF
if (fixp->fx_r_type == BFD_RELOC_ALPHA_LITERAL)
{
- /* fake out bfd_perform_relocation. sigh */
+ /* Fake out bfd_perform_relocation. sigh. */
reloc->addend = -alpha_gp_value;
}
else
{
reloc->addend = fixp->fx_offset;
#ifdef OBJ_ELF
- /*
- * Ohhh, this is ugly. The problem is that if this is a local global
- * symbol, the relocation will entirely be performed at link time, not
- * 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.
- */
+ /* Ohhh, this is ugly. The problem is that if this is a local global
+ symbol, the relocation will entirely be performed at link time, not
+ 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)
- || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE))
+ || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE)
+ || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_THREAD_LOCAL))
&& !S_IS_COMMON (fixp->fx_addsy))
reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value;
#endif
relocations, and similarly for !gpdisp relocations. */
void
-alpha_adjust_symtab ()
+alpha_before_fix ()
{
if (alpha_literal_hash)
- bfd_map_over_sections (stdoutput, alpha_adjust_symtab_relocs, NULL);
+ bfd_map_over_sections (stdoutput, alpha_adjust_relocs, NULL);
}
static void
-alpha_adjust_symtab_relocs (abfd, sec, ptr)
+alpha_adjust_relocs (abfd, sec, ptr)
bfd *abfd ATTRIBUTE_UNUSED;
asection *sec;
PTR ptr ATTRIBUTE_UNUSED;
fixS *fixp;
fixS *next;
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
switch (fixp->fx_r_type)
{
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);
+#ifdef RELOC_OP_P
+ if (fixp->fx_offset == LITUSE_ALPHA_TLSGD)
+ {
+ if (! fixp->tc_fix_data.info->saw_tlsgd)
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("No !tlsgd!%ld was found"),
+ fixp->tc_fix_data.info->sequence);
+ }
+ else if (fixp->fx_offset == LITUSE_ALPHA_TLSLDM)
+ {
+ if (! fixp->tc_fix_data.info->saw_tlsldm)
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("No !tlsldm!%ld was found"),
+ fixp->tc_fix_data.info->sequence);
+ }
+#endif
break;
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 ldah !gpdisp!%ld was found"),
fixp->tc_fix_data.info->sequence);
break;
+ case BFD_RELOC_ALPHA_ELF_LITERAL:
+ if (fixp->tc_fix_data.info
+ && (fixp->tc_fix_data.info->saw_tlsgd
+ || fixp->tc_fix_data.info->saw_tlsldm))
+ break;
+ /* FALLTHRU */
+
default:
*prevP = fixp;
prevP = &fixp->fx_next;
}
}
- /* 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.
+ /* Go back and re-chain dependent relocations. They are currently
+ 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
next = fixp->fx_next;
switch (fixp->fx_r_type)
{
+ case BFD_RELOC_ALPHA_TLSGD:
+ case BFD_RELOC_ALPHA_TLSLDM:
+ if (!fixp->tc_fix_data.info)
+ break;
+ if (fixp->tc_fix_data.info->n_master == 0)
+ break;
+ else if (fixp->tc_fix_data.info->n_master > 1)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("too many !literal!%ld for %s"),
+ fixp->tc_fix_data.info->sequence,
+ (fixp->fx_r_type == BFD_RELOC_ALPHA_TLSGD
+ ? "!tlsgd" : "!tlsldm"));
+ break;
+ }
+
+ fixp->tc_fix_data.info->master->fx_next = fixp->fx_next;
+ fixp->fx_next = fixp->tc_fix_data.info->master;
+ fixp = fixp->fx_next;
+ /* FALLTHRU */
+
case BFD_RELOC_ALPHA_ELF_LITERAL:
- if (fixp->tc_fix_data.info->n_master == 1
+ if (fixp->tc_fix_data.info
+ && fixp->tc_fix_data.info->n_master == 1
&& ! fixp->tc_fix_data.info->multi_section_p)
{
for (slave = fixp->tc_fix_data.info->slaves;
{
expressionS *t = &tok[i];
const char *name;
+
switch (t->X_op)
{
default: name = "unknown"; break;
case O_pregister: name = "O_pregister"; break;
case O_cpregister: name = "O_cpregister"; break;
case O_literal: name = "O_literal"; break;
+ case O_lituse_addr: name = "O_lituse_addr"; break;
case O_lituse_base: name = "O_lituse_base"; break;
case O_lituse_bytoff: name = "O_lituse_bytoff"; break;
case O_lituse_jsr: name = "O_lituse_jsr"; break;
+ case O_lituse_tlsgd: name = "O_lituse_tlsgd"; break;
+ case O_lituse_tlsldm: name = "O_lituse_tlsldm"; break;
case O_gpdisp: name = "O_gpdisp"; break;
case O_gprelhigh: name = "O_gprelhigh"; break;
case O_gprellow: name = "O_gprellow"; 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;
- case O_md14: name = "O_md14"; break;
- case O_md15: name = "O_md15"; break;
- case O_md16: name = "O_md16"; break;
+ case O_samegp: name = "O_samegp"; break;
+ case O_tlsgd: name = "O_tlsgd"; break;
+ case O_tlsldm: name = "O_tlsldm"; break;
+ case O_gotdtprel: name = "O_gotdtprel"; break;
+ case O_dtprelhi: name = "O_dtprelhi"; break;
+ case O_dtprello: name = "O_dtprello"; break;
+ case O_dtprel: name = "O_dtprel"; break;
+ case O_gottprel: name = "O_gottprel"; break;
+ case O_tprelhi: name = "O_tprelhi"; break;
+ case O_tprello: name = "O_tprello"; break;
+ case O_tprel: name = "O_tprel"; break;
}
fprintf (stderr, ", %s(%s, %s, %d)", name,
#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);
- /* Save and restore input_line_pointer around this function */
+ /* Save and restore input_line_pointer around this function. */
old_input_line_pointer = input_line_pointer;
input_line_pointer = str;
assembly language statement, and has the following form:
!relocation_type!sequence_number. */
if (reloc_found_p)
- { /* only support one relocation op per insn */
+ {
+ /* Only support one relocation op per insn. */
as_bad (_("More than one relocation op per insn"));
goto err_report;
}
goto err;
++input_line_pointer;
- SKIP_WHITESPACE ();
+ SKIP_WHITESPACE ();
p = input_line_pointer;
c = get_symbol_end ();
- /* Parse !relocation_type */
+ /* Parse !relocation_type. */
len = input_line_pointer - p;
if (len == 0)
{
}
*input_line_pointer = c;
- SKIP_WHITESPACE ();
+ SKIP_WHITESPACE ();
if (*input_line_pointer != '!')
{
if (r->require_seq)
input_line_pointer++;
- /* Parse !sequence_number */
+ /* Parse !sequence_number. */
expression (tok);
if (tok->X_op != O_constant || tok->X_add_number <= 0)
{
break;
}
- /* ... then fall through to plain expression */
+ /* ... then fall through to plain expression. */
input_line_pointer = hold;
}
input_line_pointer = old_input_line_pointer;
return TOKENIZE_ERROR;
-err_report:
#ifdef RELOC_OP_P
+err_report:
is_end_of_line[(unsigned char) '!'] = 0;
#endif
input_line_pointer = old_input_line_pointer;
const unsigned char *opidx;
int tokidx = 0;
- /* Don't match opcodes that don't exist on this architecture */
+ /* Don't match opcodes that don't exist on this architecture. */
if (!(opcode->flags & alpha_target))
goto match_failed;
{
const struct alpha_operand *operand = &alpha_operands[*opidx];
- /* only take input from real operands */
+ /* Only take input from real operands. */
if (operand->flags & AXP_OPERAND_FAKE)
continue;
- /* when we expect input, make sure we have it */
+ /* When we expect input, make sure we have it. */
if (tokidx >= ntok)
{
if ((operand->flags & AXP_OPERAND_OPTIONAL_MASK) == 0)
continue;
}
- /* match operand type with expression type */
+ /* Match operand type with expression type. */
switch (operand->flags & AXP_OPERAND_TYPECHECK_MASK)
{
case AXP_OPERAND_IR:
break;
default:
- /* everything else should have been fake */
+ /* Everything else should have been fake. */
abort ();
}
++tokidx;
}
- /* possible match -- did we use all of our input? */
+ /* Possible match -- did we use all of our input? */
if (tokidx == ntok)
{
*pntok = ntok;
match_failed:;
}
- while (++opcode - alpha_opcodes < alpha_num_opcodes
+ while (++opcode - alpha_opcodes < (int) alpha_num_opcodes
&& !strcmp (opcode->name, first_opcode->name));
if (*pcpumatch)
tokidx = 0;
break;
- /* index register */
+ /* Index register. */
case MACRO_IR:
if (tokidx >= ntok || tok[tokidx].X_op != O_register
|| !is_ir_num (tok[tokidx].X_add_number))
++tokidx;
break;
- /* parenthesized index register */
+ /* Parenthesized index register. */
case MACRO_PIR:
if (tokidx >= ntok || tok[tokidx].X_op != O_pregister
|| !is_ir_num (tok[tokidx].X_add_number))
++tokidx;
break;
- /* optional parenthesized index register */
+ /* Optional parenthesized index register. */
case MACRO_OPIR:
if (tokidx < ntok && tok[tokidx].X_op == O_pregister
&& is_ir_num (tok[tokidx].X_add_number))
++tokidx;
break;
- /* leading comma with a parenthesized index register */
+ /* Leading comma with a parenthesized index register. */
case MACRO_CPIR:
if (tokidx >= ntok || tok[tokidx].X_op != O_cpregister
|| !is_ir_num (tok[tokidx].X_add_number))
++tokidx;
break;
- /* floating point register */
+ /* Floating point register. */
case MACRO_FPR:
if (tokidx >= ntok || tok[tokidx].X_op != O_register
|| !is_fpr_num (tok[tokidx].X_add_number))
++tokidx;
break;
- /* normal expression */
+ /* Normal expression. */
case MACRO_EXP:
if (tokidx >= ntok)
goto match_failed;
case O_gprelhigh:
case O_gprellow:
case O_gprel:
+ case O_samegp:
goto match_failed;
default:
++arg;
}
}
- while (++macro - alpha_macros < alpha_num_macros
+ while (++macro - alpha_macros < (int) alpha_num_macros
&& !strcmp (macro->name, first_macro->name));
return NULL;
return insn;
}
-/*
- * Turn an opcode description and a set of arguments into
- * an instruction and a fixup.
- */
+/* Turn an opcode description and a set of arguments into
+ an instruction and a fixup. */
static void
assemble_insn (opcode, tok, ntok, insn, reloc)
abort ();
/* There is one special case for which an insn receives two
- relocations, and thus the user-supplied reloc does not
+ relocations, and thus the user-supplied reloc does not
override the operand reloc. */
if (operand->default_reloc == BFD_RELOC_ALPHA_HINT)
{
insn->insn = image;
}
-/*
- * Actually output an instruction with its fixup.
- */
+/* Actually output an instruction with its fixup. */
static void
emit_insn (insn)
dwarf2_emit_insn (4);
#endif
- /* Apply the fixups in order */
+ /* Apply the fixups in order. */
for (i = 0; i < insn->nfixups; ++i)
{
const struct alpha_operand *operand = (const struct alpha_operand *) 0;
struct alpha_fixup *fixup = &insn->fixups[i];
- struct alpha_reloc_tag *info;
+ struct alpha_reloc_tag *info = NULL;
int size, pcrel;
fixS *fixP;
- /* Some fixups are only used internally and so have no howto */
+ /* Some fixups are only used internally and so have no howto. */
if ((int) fixup->reloc < 0)
{
operand = &alpha_operands[-(int) fixup->reloc];
case BFD_RELOC_GPREL16:
case BFD_RELOC_ALPHA_GPREL_HI16:
case BFD_RELOC_ALPHA_GPREL_LO16:
+ case BFD_RELOC_ALPHA_GOTDTPREL16:
+ case BFD_RELOC_ALPHA_DTPREL_HI16:
+ case BFD_RELOC_ALPHA_DTPREL_LO16:
+ case BFD_RELOC_ALPHA_DTPREL16:
+ case BFD_RELOC_ALPHA_GOTTPREL16:
+ case BFD_RELOC_ALPHA_TPREL_HI16:
+ case BFD_RELOC_ALPHA_TPREL_LO16:
+ case BFD_RELOC_ALPHA_TPREL16:
fixP->fx_no_overflow = 1;
break;
case BFD_RELOC_ALPHA_ELF_LITERAL:
fixP->fx_no_overflow = 1;
+ if (insn->sequence == 0)
+ break;
info = get_alpha_reloc_tag (insn->sequence);
+ info->master = fixP;
info->n_master++;
if (info->segment != now_seg)
info->multi_section_p = 1;
fixP->tc_fix_data.info = info;
break;
+#ifdef RELOC_OP_P
case DUMMY_RELOC_LITUSE_ADDR:
- fixP->fx_offset = LITUSE_ADDR;
+ fixP->fx_offset = LITUSE_ALPHA_ADDR;
goto do_lituse;
case DUMMY_RELOC_LITUSE_BASE:
- fixP->fx_offset = LITUSE_BASE;
+ fixP->fx_offset = LITUSE_ALPHA_BASE;
goto do_lituse;
case DUMMY_RELOC_LITUSE_BYTOFF:
- fixP->fx_offset = LITUSE_BYTOFF;
+ fixP->fx_offset = LITUSE_ALPHA_BYTOFF;
goto do_lituse;
case DUMMY_RELOC_LITUSE_JSR:
- fixP->fx_offset = LITUSE_JSR;
+ fixP->fx_offset = LITUSE_ALPHA_JSR;
+ goto do_lituse;
+ case DUMMY_RELOC_LITUSE_TLSGD:
+ fixP->fx_offset = LITUSE_ALPHA_TLSGD;
+ goto do_lituse;
+ case DUMMY_RELOC_LITUSE_TLSLDM:
+ fixP->fx_offset = LITUSE_ALPHA_TLSLDM;
+ goto do_lituse;
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++;
+ if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSGD)
+ info->saw_lu_tlsgd = 1;
+ else if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSLDM)
+ info->saw_lu_tlsldm = 1;
+ if (++info->n_slaves > 1)
+ {
+ if (info->saw_lu_tlsgd)
+ as_bad (_("too many lituse insns for !lituse_tlsgd!%ld"),
+ insn->sequence);
+ else if (info->saw_lu_tlsldm)
+ as_bad (_("too many lituse insns for !lituse_tlsldm!%ld"),
+ insn->sequence);
+ }
fixP->tc_fix_data.info = info;
fixP->tc_fix_data.next_reloc = info->slaves;
info->slaves = fixP;
info->multi_section_p = 1;
break;
+ case BFD_RELOC_ALPHA_TLSGD:
+ fixP->fx_no_overflow = 1;
+
+ if (insn->sequence == 0)
+ break;
+ info = get_alpha_reloc_tag (insn->sequence);
+ if (info->saw_tlsgd)
+ as_bad (_("duplicate !tlsgd!%ld"), insn->sequence);
+ else if (info->saw_tlsldm)
+ as_bad (_("sequence number in use for !tlsldm!%ld"),
+ insn->sequence);
+ else
+ info->saw_tlsgd = 1;
+ fixP->tc_fix_data.info = info;
+ break;
+
+ case BFD_RELOC_ALPHA_TLSLDM:
+ fixP->fx_no_overflow = 1;
+
+ if (insn->sequence == 0)
+ break;
+ info = get_alpha_reloc_tag (insn->sequence);
+ if (info->saw_tlsldm)
+ as_bad (_("duplicate !tlsldm!%ld"), insn->sequence);
+ else if (info->saw_tlsgd)
+ as_bad (_("sequence number in use for !tlsgd!%ld"),
+ insn->sequence);
+ else
+ info->saw_tlsldm = 1;
+ fixP->tc_fix_data.info = info;
+ break;
+#endif
default:
if ((int) fixup->reloc < 0)
{
int cpumatch = 1;
bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
+#ifdef RELOC_OP_P
/* 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)
+ else
+#endif
+ if (local_macros_on)
{
macro = ((const struct alpha_macro *)
hash_find (alpha_macro_hash, opname));
}
}
- /* search opcodes */
+ /* Search opcodes. */
opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname);
if (opcode)
{
as_bad (_("unknown opcode `%s'"), opname);
}
\f
-/* Some instruction sets indexed by lg(size) */
+/* Some instruction sets indexed by lg(size). */
static const char * const sextX_op[] = { "sextb", "sextw", "sextl", NULL };
static const char * const insXl_op[] = { "insbl", "inswl", "insll", "insql" };
static const char * const insXh_op[] = { NULL, "inswh", "inslh", "insqh" };
static const char * const mskXl_op[] = { "mskbl", "mskwl", "mskll", "mskql" };
static const char * const mskXh_op[] = { NULL, "mskwh", "msklh", "mskqh" };
static const char * const stX_op[] = { "stb", "stw", "stl", "stq" };
-static const char * const ldX_op[] = { "ldb", "ldw", "ldll", "ldq" };
static const char * const ldXu_op[] = { "ldbu", "ldwu", NULL, NULL };
/* Implement the ldgp macro. */
#ifdef OBJ_ECOFF
offsetT lit;
- /* attempt to reduce .lit load by splitting the offset from
+ /* Attempt to reduce .lit load by splitting the offset from
its symbol when possible, but don't create a situation in
which we'd fail. */
if (!range_signed_32 (addend) &&
const PTR symname;
{
/* DIVISION and MODULUS. Yech.
- *
- * Convert
- * OP x,y,result
- * to
- * mov x,R16 # if x != R16
- * mov y,R17 # if y != R17
- * lda AT,__OP
- * jsr AT,(AT),0
- * mov R0,result
- *
- * with appropriate optimizations if R0,R16,R17 are the registers
- * specified by the compiler.
- */
+
+ Convert
+ OP x,y,result
+ to
+ mov x,R16 # if x != R16
+ mov y,R17 # if y != R17
+ lda AT,__OP
+ jsr AT,(AT),0
+ mov R0,result
+
+ with appropriate optimizations if R0,R16,R17 are the registers
+ specified by the compiler. */
int xr, yr, rr;
symbolS *sym;
else
rr = regno (tok[2].X_add_number);
- /* Move the operands into the right place */
+ /* Move the operands into the right place. */
if (yr == AXP_REG_R16 && xr == AXP_REG_R17)
{
- /* They are in exactly the wrong order -- swap through AT */
+ /* They are in exactly the wrong order -- swap through AT. */
if (alpha_noat_on)
as_bad (_("macro requires $at register while noat in effect"));
set_tok_sym (newtok[1], sym, 0);
assemble_tokens ("lda", newtok, 2, 1);
- /* Call the division routine */
+ /* Call the division routine. */
set_tok_reg (newtok[0], AXP_REG_AT);
set_tok_cpreg (newtok[1], AXP_REG_AT);
set_tok_const (newtok[2], 0);
assemble_tokens ("jsr", newtok, 3, 1);
- /* Move the result to the right place */
+ /* Move the result to the right place. */
if (rr != AXP_REG_R0)
{
set_tok_reg (newtok[0], AXP_REG_R0);
const PTR symname;
{
/* DIVISION and MODULUS. Yech.
- * Convert
- * OP x,y,result
- * to
- * lda pv,__OP
- * mov x,t10
- * mov y,t11
- * jsr t9,(pv),__OP
- * mov t12,result
- *
- * with appropriate optimizations if t10,t11,t12 are the registers
- * specified by the compiler.
- */
+ Convert
+ OP x,y,result
+ to
+ lda pv,__OP
+ mov x,t10
+ mov y,t11
+ jsr t9,(pv),__OP
+ mov t12,result
+
+ with appropriate optimizations if t10,t11,t12 are the registers
+ specified by the compiler. */
int xr, yr, rr;
symbolS *sym;
sym = symbol_find_or_make ((const char *) symname);
- /* Move the operands into the right place */
+ /* Move the operands into the right place. */
if (yr == AXP_REG_T10 && xr == AXP_REG_T11)
{
- /* They are in exactly the wrong order -- swap through AT */
-
+ /* They are in exactly the wrong order -- swap through AT. */
if (alpha_noat_on)
as_bad (_("macro requires $at register while noat in effect"));
}
}
- /* Call the division routine */
+ /* Call the division routine. */
set_tok_reg (newtok[0], AXP_REG_T9);
set_tok_sym (newtok[1], sym, 0);
assemble_tokens ("jsr", newtok, 2, 1);
- /* Reload the GP register */
+ /* Reload the GP register. */
#ifdef OBJ_AOUT
FIXME
#endif
assemble_tokens ("ldgp", newtok, 3, 1);
#endif
- /* Move the result to the right place */
+ /* Move the result to the right place. */
if (rr != AXP_REG_T12)
{
set_tok_reg (newtok[0], AXP_REG_T12);
assemble_tokens (opname, newtok, 3, 0);
}
\f
-/* Assembler directives */
+/* Assembler directives. */
/* Handle the .text pseudo-op. This is like the usual one, but it
clears alpha_insn_label and restores auto alignment. */
int i;
{
+#ifdef OBJ_ELF
+ obj_elf_text (i);
+#else
s_text (i);
+#endif
alpha_insn_label = NULL;
alpha_auto_align_on = 1;
alpha_current_align = 0;
s_alpha_data (i)
int i;
{
+#ifdef OBJ_ELF
+ obj_elf_data (i);
+#else
s_data (i);
+#endif
alpha_insn_label = NULL;
alpha_auto_align_on = 1;
alpha_current_align = 0;
static void
s_alpha_comm (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
register char *name;
register char c;
static void
s_alpha_rdata (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
int temp;
static void
s_alpha_sdata (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
int temp;
static void
s_alpha_section (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
obj_elf_section (ignore);
sym = ecoff_get_cur_proc_sym ();
else
sym = alpha_cur_ent_sym;
- know (sym != NULL);
+
+ if (sym == NULL)
+ {
+ as_bad (_(".prologue directive without a preceding .ent directive"));
+ return;
+ }
switch (arg)
{
static void
s_alpha_ent (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
symbolS *symbol;
expressionS symexpr;
static void
s_alpha_frame (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
long val;
static void
s_alpha_pdesc (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
char *name;
char name_end;
static void
s_alpha_name (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
register char *p;
expressionS exp;
static void
s_alpha_linkage (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
expressionS exp;
char *p;
static void
s_alpha_code_address (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
expressionS exp;
char *p;
static void
s_alpha_fp_save (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
alpha_evax_proc.fp_save = tc_get_register (1);
static void
s_alpha_mask (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
long val;
static void
s_alpha_fmask (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
long val;
static void
s_alpha_end (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
char c;
static void
s_alpha_file (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
symbolS *s;
int length;
static char case_hack[32];
- extern char *demand_copy_string PARAMS ((int *lenP));
-
sprintf (case_hack, "<CASE:%01d%01d>",
alpha_flag_hash_long_names, alpha_flag_show_after_trunc);
/* @@@ GP selection voodoo. All of this seems overly complicated and
unnecessary; which is the primary reason it's for ECOFF only. */
+static inline void maybe_set_gp PARAMS ((asection *));
static inline void
maybe_set_gp (sec)
if (letter == 's')
return SHF_ALPHA_GPREL;
- *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S in string");
- return 0;
+ *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S,G,T in string");
+ return -1;
}
/* Map SHF_ALPHA_GPREL to SEC_SMALL_DATA. */
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;