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