X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-alpha.c;h=67f0a823a7f985b5aebe8d76d07132d5a1d9d67b;hb=ad10f812bfdac2cc9e42875246c8fe0ae5224440;hp=64617e9c24dbdf40b739ec43a0710cb4c371abd4;hpb=c699ff04031710cf3c568e1c009a44c083f6c253;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-alpha.c b/gas/config/tc-alpha.c index 64617e9c24..67f0a823a7 100644 --- a/gas/config/tc-alpha.c +++ b/gas/config/tc-alpha.c @@ -1,10 +1,11 @@ /* tc-alpha.c - Processor-specific code for the DEC Alpha AXP CPU. - Copyright (C) 1989, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. + Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 + 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. Modified by Richard Henderson for ELF support. - Modified by Klaus K"ampf for EVAX (openVMS/Alpha) support. + Modified by Klaus K"ampf for EVAX (OpenVMS/Alpha) support. This file is part of GAS, the GNU Assembler. @@ -51,52 +52,83 @@ #include "as.h" #include "subsegs.h" +#include "struc-symbol.h" +#include "ecoff.h" #include "opcode/alpha.h" #ifdef OBJ_ELF #include "elf/alpha.h" +#include "dwarf2dbg.h" #endif -#include - +#include "safe-ctype.h" /* 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_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; enum alpha_macro_arg argsets[16]; }; -/* Two extra symbols we want to see in our input. This is a blatent - misuse of the expressionS.X_op field. */ +/* Extra expression types. */ + +#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. */ +#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 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 O_pregister (O_max+1) /* O_register, but in parentheses */ -#define O_cpregister (O_pregister+1) /* + a leading comma */ +#define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_gprel) /* Macros for extracting the type and number of encoded register tokens */ @@ -110,50 +142,61 @@ struct alpha_macro #define note_fpreg(R) (alpha_fprmask |= (1 << (R))) /* Predicates for 16- and 32-bit ranges */ +/* XXX: The non-shift version appears to trigger a compiler bug when + cross-assembling from x86 w/ gcc 2.7.2. */ -#define range_signed_16(x) ((offsetT)(x) >= -(offsetT)0x8000 && \ - (offsetT)(x) <= (offsetT)0x7FFF) -#define range_signed_32(x) ((offsetT)(x) >= -(offsetT)0x80000000 && \ - (offsetT)(x) <= (offsetT)0x7FFFFFFF) +#if 1 +#define range_signed_16(x) \ + (((offsetT) (x) >> 15) == 0 || ((offsetT) (x) >> 15) == -1) +#define range_signed_32(x) \ + (((offsetT) (x) >> 31) == 0 || ((offsetT) (x) >> 31) == -1) +#else +#define range_signed_16(x) ((offsetT) (x) >= -(offsetT) 0x8000 && \ + (offsetT) (x) <= (offsetT) 0x7FFF) +#define range_signed_32(x) ((offsetT) (x) >= -(offsetT) 0x80000000 && \ + (offsetT) (x) <= (offsetT) 0x7FFFFFFF) +#endif /* Macros for sign extending from 16- and 32-bits. */ /* XXX: The cast macros will work on all the systems that I care about, but really a predicate should be found to use the non-cast forms. */ #if 1 -#define sign_extend_16(x) ((short)(x)) -#define sign_extend_32(x) ((int)(x)) +#define sign_extend_16(x) ((short) (x)) +#define sign_extend_32(x) ((int) (x)) #else -#define sign_extend_16(x) ((offsetT)(((x) & 0xFFFF) ^ 0x8000) - 0x8000) -#define sign_extend_32(x) ((offsetT)(((x) & 0xFFFFFFFF) \ +#define sign_extend_16(x) ((offsetT) (((x) & 0xFFFF) ^ 0x8000) - 0x8000) +#define sign_extend_32(x) ((offsetT) (((x) & 0xFFFFFFFF) \ ^ 0x80000000) - 0x80000000) #endif /* Macros to build tokens */ -#define set_tok_reg(t, r) (memset(&(t), 0, sizeof(t)), \ +#define set_tok_reg(t, r) (memset (&(t), 0, sizeof (t)), \ (t).X_op = O_register, \ (t).X_add_number = (r)) -#define set_tok_preg(t, r) (memset(&(t), 0, sizeof(t)), \ +#define set_tok_preg(t, r) (memset (&(t), 0, sizeof (t)), \ (t).X_op = O_pregister, \ (t).X_add_number = (r)) -#define set_tok_cpreg(t, r) (memset(&(t), 0, sizeof(t)), \ +#define set_tok_cpreg(t, r) (memset (&(t), 0, sizeof (t)), \ (t).X_op = O_cpregister, \ (t).X_add_number = (r)) -#define set_tok_freg(t, r) (memset(&(t), 0, sizeof(t)), \ +#define set_tok_freg(t, r) (memset (&(t), 0, sizeof (t)), \ (t).X_op = O_register, \ - (t).X_add_number = (r)+32) -#define set_tok_sym(t, s, a) (memset(&(t), 0, sizeof(t)), \ + (t).X_add_number = (r) + 32) +#define set_tok_sym(t, s, a) (memset (&(t), 0, sizeof (t)), \ (t).X_op = O_symbol, \ (t).X_add_symbol = (s), \ (t).X_add_number = (a)) -#define set_tok_const(t, n) (memset(&(t), 0, sizeof(t)), \ +#define set_tok_const(t, n) (memset (&(t), 0, sizeof (t)), \ (t).X_op = O_constant, \ (t).X_add_number = (n)) - /* 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 *)); @@ -163,14 +206,14 @@ 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 +static long load_expression PARAMS ((int, const expressionS *, int *, expressionS *)); static void emit_ldgp PARAMS ((const expressionS *, int, const PTR)); @@ -194,8 +237,6 @@ static void s_alpha_text PARAMS ((int)); static void s_alpha_data PARAMS ((int)); #ifndef OBJ_ELF static void s_alpha_comm PARAMS ((int)); -#endif -#if defined (OBJ_ECOFF) || defined (OBJ_EVAX) static void s_alpha_rdata PARAMS ((int)); #endif #ifdef OBJ_ECOFF @@ -203,6 +244,15 @@ static void s_alpha_sdata PARAMS ((int)); #endif #ifdef OBJ_ELF static void s_alpha_section PARAMS ((int)); +static void s_alpha_ent PARAMS ((int)); +static void s_alpha_end PARAMS ((int)); +static void s_alpha_mask PARAMS ((int)); +static void s_alpha_frame PARAMS ((int)); +static void s_alpha_prologue PARAMS ((int)); +static void s_alpha_file PARAMS ((int)); +static void s_alpha_loc PARAMS ((int)); +static void s_alpha_stab PARAMS ((int)); +static void s_alpha_coff_wrapper PARAMS ((int)); #endif #ifdef OBJ_EVAX static void s_alpha_section PARAMS ((int)); @@ -215,22 +265,18 @@ 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 *)); - +static void alpha_align PARAMS ((int, char *, symbolS *, int)); /* Generic assembler global variables which must be defined by all targets. */ -/* These are exported to relaxing code, even though we don't do any - relaxing on this processor currently. */ -int md_short_jump_size = 4; -int md_long_jump_size = 4; - /* Characters which always start a comment. */ const char comment_chars[] = "#"; @@ -255,19 +301,26 @@ char FLT_CHARS[] = "rRsSfFdDxXpP"; #endif #ifdef OBJ_EVAX -const char *md_shortopts = "Fm:g+1h:H"; +const char *md_shortopts = "Fm:g+1h:HG:"; #else -const char *md_shortopts = "Fm:g"; +const char *md_shortopts = "Fm:gG:"; #endif struct option md_longopts[] = { #define OPTION_32ADDR (OPTION_MD_BASE) { "32addr", no_argument, NULL, OPTION_32ADDR }, +#define OPTION_RELAX (OPTION_32ADDR + 1) + { "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 }, +#endif { NULL, no_argument, NULL, 0 } }; -size_t md_longopts_size = sizeof(md_longopts); - +size_t md_longopts_size = sizeof (md_longopts); #ifdef OBJ_EVAX #define AXP_REG_R0 0 @@ -325,7 +378,7 @@ static segT alpha_dtors_section; #endif static segT alpha_lit8_section; -/* Symbols referring to said sections. */ +/* Symbols referring to said sections. */ #ifdef OBJ_ECOFF static symbolS *alpha_lita_symbol; static symbolS *alpha_lit4_symbol; @@ -343,6 +396,11 @@ static offsetT alpha_lit4_literal; static offsetT alpha_lit8_literal; #endif +#ifdef OBJ_ELF +/* The active .ent symbol. */ +static symbolS *alpha_cur_ent_sym; +#endif + /* Is the assembler not allowed to use $at? */ static int alpha_noat_on = 0; @@ -375,6 +433,17 @@ unsigned long alpha_gprmask, alpha_fprmask; /* Whether the debugging option was seen. */ static int alpha_debug; +#ifdef OBJ_ELF +/* Whether we are emitting an mdebug section. */ +int alpha_flag_mdebug = -1; +#endif + +/* Don't fully resolve relocations, allowing code movement in the linker. */ +static int alpha_flag_relax; + +/* What value to give to bfd_set_gp_size. */ +static int g_switch_value = 8; + #ifdef OBJ_EVAX /* Collect information about current procedure here. */ static struct { @@ -400,16 +469,73 @@ static int alpha_flag_show_after_trunc = 0; /* -H */ #endif -/* A table of CPU names and opcode sets. */ +#ifdef RELOC_OP_P +/* A table to map the spelling of a relocation operand into an appropriate + bfd_reloc_code_real_type type. The table is assumed to be ordered such + that op-O_literal indexes into it. */ + +#define ALPHA_RELOC_TABLE(op) \ +(&alpha_reloc_op[ ((!USER_RELOC_P (op)) \ + ? (abort (), 0) \ + : (int) (op) - (int) O_literal) ]) + +#define DEF(NAME, RELOC, REQ, ALLOW) \ + { #NAME, sizeof(#NAME)-1, O_##NAME, RELOC, REQ, ALLOW} + +static const struct alpha_reloc_op_tag { + const char *name; /* string to lookup */ + size_t length; /* size of the string */ + 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[] = { + DEF(literal, BFD_RELOC_ALPHA_ELF_LITERAL, 0, 1), + DEF(lituse_addr, DUMMY_RELOC_LITUSE_ADDR, 1, 1), + DEF(lituse_base, DUMMY_RELOC_LITUSE_BASE, 1, 1), + DEF(lituse_bytoff, DUMMY_RELOC_LITUSE_BYTOFF, 1, 1), + DEF(lituse_jsr, DUMMY_RELOC_LITUSE_JSR, 1, 1), + DEF(gpdisp, BFD_RELOC_ALPHA_GPDISP, 1, 1), + DEF(gprelhigh, BFD_RELOC_ALPHA_GPREL_HI16, 0, 0), + DEF(gprellow, BFD_RELOC_ALPHA_GPREL_LO16, 0, 0), + DEF(gprel, BFD_RELOC_GPREL16, 0, 0) +}; + +#undef DEF + +static const int alpha_num_reloc_op + = sizeof (alpha_reloc_op) / sizeof (*alpha_reloc_op); +#endif /* RELOC_OP_P */ -static const struct cpu_type +/* Maximum # digits needed to hold the largest sequence # */ +#define ALPHA_RELOC_DIGITS 25 + +/* Structure to hold explict sequence information. */ +struct alpha_reloc_tag { + fixS *slaves; /* head of linked list of !literals */ + 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 */ + 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; + +/* Sequence numbers for internal use by macros. */ +static long next_sequence_num = -1; + +/* A table of CPU names and opcode sets. */ + +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 + This supports usage under DU 4.0b that does ".arch ev4", and usage in MILO that does -m21064. Probably something more specific like -m21064-pal should be used, but oh well. */ @@ -418,25 +544,22 @@ static const struct cpu_type { "21066", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, { "21068", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, { "21164", AXP_OPCODE_BASE|AXP_OPCODE_EV5 }, - /* Do we have CIX extension here? */ { "21164a", AXP_OPCODE_BASE|AXP_OPCODE_EV5|AXP_OPCODE_BWX }, - /* Still same PALcodes? */ { "21164pc", (AXP_OPCODE_BASE|AXP_OPCODE_EV5|AXP_OPCODE_BWX - |AXP_OPCODE_CIX|AXP_OPCODE_MAX) }, - /* All new PALcodes? Extras? */ - { "21264", (AXP_OPCODE_BASE|AXP_OPCODE_BWX - |AXP_OPCODE_CIX|AXP_OPCODE_MAX) }, + |AXP_OPCODE_MAX) }, + { "21264", (AXP_OPCODE_BASE|AXP_OPCODE_EV6|AXP_OPCODE_BWX + |AXP_OPCODE_MAX|AXP_OPCODE_CIX) }, { "ev4", AXP_OPCODE_BASE }, { "ev45", AXP_OPCODE_BASE }, { "lca45", AXP_OPCODE_BASE }, { "ev5", AXP_OPCODE_BASE }, { "ev56", AXP_OPCODE_BASE|AXP_OPCODE_BWX }, - { "pca56", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_CIX|AXP_OPCODE_MAX }, - { "ev6", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_CIX|AXP_OPCODE_MAX }, + { "pca56", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX }, + { "ev6", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX|AXP_OPCODE_CIX }, { "all", AXP_OPCODE_BASE }, - { 0 } + { 0, 0 } }; /* The macro table */ @@ -444,67 +567,48 @@ static const struct cpu_type static const struct alpha_macro alpha_macros[] = { /* Load/Store macros */ { "lda", emit_lda, NULL, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, 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_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "ldl_l", emit_ir_load, "ldl_l", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "ldq", emit_ir_load, "ldq", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "ldq_l", emit_ir_load, "ldq_l", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "ldq_u", emit_ir_load, "ldq_u", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "ldf", emit_loadstore, "ldf", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "ldg", emit_loadstore, "ldg", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "lds", emit_loadstore, "lds", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "ldt", emit_loadstore, "ldt", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - - { "ldb", emit_ldX, (PTR)0, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldbu", emit_ldXu, (PTR)0, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldw", emit_ldX, (PTR)1, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldwu", emit_ldXu, (PTR)1, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - - { "uldw", emit_uldX, (PTR)1, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "uldwu", emit_uldXu, (PTR)1, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "uldl", emit_uldX, (PTR)2, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "uldlu", emit_uldXu, (PTR)2, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "uldq", emit_uldXu, (PTR)3, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + + { "ldb", emit_ldX, (PTR) 0, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldbu", emit_ldXu, (PTR) 0, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldw", emit_ldX, (PTR) 1, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldwu", emit_ldXu, (PTR) 1, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + + { "uldw", emit_uldX, (PTR) 1, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "uldwu", emit_uldXu, (PTR) 1, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "uldl", emit_uldX, (PTR) 2, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "uldlu", emit_uldXu, (PTR) 2, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "uldq", emit_uldXu, (PTR) 3, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "ldgp", emit_ldgp, NULL, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA } }, @@ -529,48 +633,34 @@ static const struct alpha_macro alpha_macros[] = { #endif { "stl", emit_loadstore, "stl", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "stl_c", emit_loadstore, "stl_c", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "stq", emit_loadstore, "stq", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "stq_c", emit_loadstore, "stq_c", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "stq_u", emit_loadstore, "stq_u", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "stf", emit_loadstore, "stf", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "stg", emit_loadstore, "stg", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "sts", emit_loadstore, "sts", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, { "stt", emit_loadstore, "stt", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - - { "stb", emit_stX, (PTR)0, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "stw", emit_stX, (PTR)1, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ustw", emit_ustX, (PTR)1, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ustl", emit_ustX, (PTR)2, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ustq", emit_ustX, (PTR)3, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + + { "stb", emit_stX, (PTR) 0, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "stw", emit_stX, (PTR) 1, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ustw", emit_ustX, (PTR) 1, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ustl", emit_ustX, (PTR) 2, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ustq", emit_ustX, (PTR) 3, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, /* Arithmetic macros */ #if 0 @@ -582,11 +672,11 @@ static const struct alpha_macro alpha_macros[] = { { "absq" emit_absq, 2, { EXP, IR } }, #endif - { "sextb", emit_sextX, (PTR)0, + { "sextb", emit_sextX, (PTR) 0, { MACRO_IR, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_EOA, /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } }, - { "sextw", emit_sextX, (PTR)1, + { "sextw", emit_sextX, (PTR) 1, { MACRO_IR, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_EOA, /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } }, @@ -635,12 +725,12 @@ static const struct alpha_macro alpha_macros[] = { { "jsr", emit_jsrjmp, "jsr", { MACRO_PIR, MACRO_EXP, MACRO_EOA, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA, + MACRO_IR, MACRO_EXP, MACRO_EOA, MACRO_EXP, MACRO_EOA } }, { "jmp", emit_jsrjmp, "jmp", { MACRO_PIR, MACRO_EXP, MACRO_EOA, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA, + MACRO_IR, MACRO_EXP, MACRO_EOA, MACRO_EXP, MACRO_EOA } }, { "ret", emit_retjcr, "ret", { MACRO_IR, MACRO_EXP, MACRO_EOA, @@ -665,8 +755,8 @@ static const struct alpha_macro alpha_macros[] = { MACRO_EOA } }, }; -static const int alpha_num_macros - = sizeof(alpha_macros) / sizeof(*alpha_macros); +static const unsigned int alpha_num_macros + = sizeof (alpha_macros) / sizeof (*alpha_macros); /* Public interface functions */ @@ -679,17 +769,25 @@ md_begin () { unsigned int i; + /* Verify that X_op field is wide enough. */ + { + expressionS e; + e.X_op = O_max; + assert (e.X_op == O_max); + } + /* Create the opcode hash table */ alpha_opcode_hash = hash_new (); - for (i = 0; i < alpha_num_opcodes; ) + for (i = 0; i < alpha_num_opcodes;) { const char *name, *retval, *slash; name = alpha_opcodes[i].name; - retval = hash_insert (alpha_opcode_hash, name, (PTR)&alpha_opcodes[i]); + 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 @@ -702,7 +800,7 @@ md_begin () memcpy (p, name, slash - name); strcpy (p + (slash - name), slash + 1); - (void)hash_insert(alpha_opcode_hash, p, (PTR)&alpha_opcodes[i]); + (void) hash_insert (alpha_opcode_hash, p, (PTR) &alpha_opcodes[i]); /* Ignore failures -- the opcode table does duplicate some variants in different forms, like "hw_stq" and "hw_st/q". */ } @@ -716,14 +814,15 @@ md_begin () /* Create the macro hash table */ alpha_macro_hash = hash_new (); - for (i = 0; i < alpha_num_macros; ) + for (i = 0; i < alpha_num_macros;) { const char *name, *retval; name = alpha_macros[i].name; - retval = hash_insert (alpha_macro_hash, name, (PTR)&alpha_macros[i]); + retval = hash_insert (alpha_macro_hash, name, (PTR) &alpha_macros[i]); if (retval) - as_fatal ("internal error: can't hash macro `%s': %s", name, retval); + as_fatal (_("internal error: can't hash macro `%s': %s"), + name, retval); while (++i < alpha_num_macros && (alpha_macros[i].name == name @@ -736,22 +835,22 @@ md_begin () 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); + 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); + 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 */ /* So .sbss will get used for tiny objects. */ - bfd_set_gp_size (stdoutput, 8); + bfd_set_gp_size (stdoutput, g_switch_value); #ifdef OBJ_ECOFF create_literal_section (".lita", &alpha_lita_section, &alpha_lita_symbol); @@ -769,24 +868,16 @@ md_begin () #ifdef OBJ_ELF if (ECOFF_DEBUGGING) { - segT sec; - - sec = subseg_new(".mdebug", (subsegT)0); - bfd_set_section_flags(stdoutput, sec, SEC_HAS_CONTENTS|SEC_READONLY); - bfd_set_section_alignment(stdoutput, sec, 3); - -#ifdef ERIC_neverdef - sec = subseg_new(".reginfo", (subsegT)0); - /* The ABI says this section should be loaded so that the running - program can access it. */ - bfd_set_section_flags(stdoutput, sec, - SEC_ALLOC|SEC_LOAD|SEC_READONLY|SEC_DATA); - bfd_set_section_alignement(stdoutput, sec, 3); -#endif + segT sec = subseg_new (".mdebug", (subsegT) 0); + bfd_set_section_flags (stdoutput, sec, SEC_HAS_CONTENTS | SEC_READONLY); + bfd_set_section_alignment (stdoutput, sec, 3); } #endif /* OBJ_ELF */ - subseg_set(text_section, 0); + /* Create literal lookup hash table. */ + alpha_literal_hash = hash_new (); + + subseg_set (text_section, 0); } /* The public interface to the instruction assembler. */ @@ -797,10 +888,11 @@ md_assemble (str) { char opname[32]; /* current maximum is 13 */ expressionS tok[MAX_INSN_ARGS]; - int ntok, opnamelen, trunclen; + int ntok, trunclen; + size_t opnamelen; /* split off the opcode */ - opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/48"); + opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/46819"); trunclen = (opnamelen < sizeof (opname) - 1 ? opnamelen : sizeof (opname) - 1); @@ -810,7 +902,9 @@ md_assemble (str) /* tokenize the rest of the line */ if ((ntok = tokenize_arguments (str + opnamelen, tok, MAX_INSN_ARGS)) < 0) { - as_bad ("syntax error"); + if (ntok != TOKENIZE_ERROR_REPORT) + as_bad (_("syntax error")); + return; } @@ -825,15 +919,15 @@ md_section_align (seg, size) segT seg; valueT size; { - int align = bfd_get_section_alignment(stdoutput, seg); - valueT mask = ((valueT)1 << align) - 1; + int align = bfd_get_section_alignment (stdoutput, seg); + valueT mask = ((valueT) 1 << align) - 1; return (size + mask) & ~mask; } /* Turn a string in input_line_pointer into a floating point constant - of type type, and store the appropriate bytes in *litP. The number - of LITTLENUMS emitted is stored in *sizeP. An error message is + of type TYPE, and store the appropriate bytes in *LITP. The number + of LITTLENUMS emitted is stored in *SIZEP. An error message is returned, or NULL on OK. */ /* Equal to MAX_PRECISION in atof-ieee.c */ @@ -883,7 +977,7 @@ md_atof (type, litP, sizeP) default: *sizeP = 0; - return "Bad call to MD_ATOF()"; + return _("Bad call to MD_ATOF()"); } t = atof_ieee (input_line_pointer, type, words); if (t) @@ -920,22 +1014,26 @@ md_parse_option (c, arg) alpha_debug = 1; break; + case 'G': + g_switch_value = atoi (arg); + break; + case 'm': { const struct cpu_type *p; for (p = cpu_types; p->name; ++p) - if (strcmp(arg, p->name) == 0) + if (strcmp (arg, p->name) == 0) { alpha_target_name = p->name, alpha_target = p->flags; goto found; } - as_warn("Unknown CPU identifier `%s'", arg); + as_warn (_("Unknown CPU identifier `%s'"), arg); found:; } break; #ifdef OBJ_EVAX - case '+': /* For g++. Hash any name > 63 chars long. */ + case '+': /* For g++. Hash any name > 63 chars long. */ alpha_flag_hash_long_names = 1; break; @@ -947,6 +1045,19 @@ md_parse_option (c, arg) break; #endif + case OPTION_RELAX: + alpha_flag_relax = 1; + break; + +#ifdef OBJ_ELF + case OPTION_MDEBUG: + alpha_flag_mdebug = 1; + break; + case OPTION_NO_MDEBUG: + alpha_flag_mdebug = 0; + break; +#endif + default: return 0; } @@ -960,19 +1071,20 @@ void md_show_usage (stream) FILE *stream; { - fputs("\ + fputs (_("\ Alpha options:\n\ -32addr treat addresses as 32-bit values\n\ -F lack floating point instructions support\n\ --m21064 | -m21066 | -m21164 | -m21164a\n\ --mev4 | -mev45 | -mev5 | -mev56 | -mall\n\ - specify variant of Alpha architecture\n", +-mev4 | -mev45 | -mev5 | -mev56 | -mpca56 | -mev6 | -mall\n\ + specify variant of Alpha architecture\n\ +-m21064 | -m21066 | -m21164 | -m21164a | -m21164pc | -m21264\n\ + these variants include PALcode opcodes\n"), stream); #ifdef OBJ_EVAX - fputs ("\ + fputs (_("\ VMS options:\n\ -+ hash encode (don't truncate) names longer than 64 characters\n\ --H show new symbol after hash truncation\n", +-H show new symbol after hash truncation\n"), stream); #endif } @@ -1007,9 +1119,10 @@ md_pcrel_from (fixP) GPDISP. */ int -md_apply_fix (fixP, valueP) +md_apply_fix3 (fixP, valueP, seg) fixS *fixP; valueT *valueP; + segT seg; { char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where; valueT value = *valueP; @@ -1024,10 +1137,13 @@ md_apply_fix (fixP, valueP) case BFD_RELOC_ALPHA_GPDISP_HI16: { fixS *next = fixP->fx_next; - assert (next->fx_r_type == BFD_RELOC_ALPHA_GPDISP_LO16); - fixP->fx_offset = (next->fx_frag->fr_address + next->fx_where - - fixP->fx_frag->fr_address - fixP->fx_where); + /* With user-specified !gpdisp relocations, we can be missing + the matching LO16 reloc. We will have already issued an + error message. */ + if (next) + fixP->fx_offset = (next->fx_frag->fr_address + next->fx_where + - fixP->fx_frag->fr_address - fixP->fx_where); value = (value - sign_extend_16 (value)) >> 16; } @@ -1044,7 +1160,7 @@ md_apply_fix (fixP, valueP) #endif do_reloc_gp: - fixP->fx_addsy = section_symbol (absolute_section); + fixP->fx_addsy = section_symbol (seg); md_number_to_chars (fixpos, value, 2); break; @@ -1077,16 +1193,18 @@ md_apply_fix (fixP, valueP) /* FIXME: inherited this obliviousness of `value' -- why? */ md_number_to_chars (fixpos, -alpha_gp_value, 4); break; -#endif -#ifdef OBJ_ELF +#else case BFD_RELOC_GPREL32: - return 1; #endif + case BFD_RELOC_GPREL16: + case BFD_RELOC_ALPHA_GPREL_HI16: + case BFD_RELOC_ALPHA_GPREL_LO16: + return 1; case BFD_RELOC_23_PCREL_S2: if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) { - image = bfd_getl32(fixpos); + image = bfd_getl32 (fixpos); image = (image & ~0x1FFFFF) | ((value >> 2) & 0x1FFFFF); goto write_done; } @@ -1095,7 +1213,7 @@ md_apply_fix (fixP, valueP) case BFD_RELOC_ALPHA_HINT: if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) { - image = bfd_getl32(fixpos); + image = bfd_getl32 (fixpos); image = (image & ~0x3FFF) | ((value >> 2) & 0x3FFF); goto write_done; } @@ -1105,44 +1223,40 @@ md_apply_fix (fixP, valueP) 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 + + case BFD_RELOC_VTABLE_INHERIT: + case BFD_RELOC_VTABLE_ENTRY: + return 1; default: { const struct alpha_operand *operand; - if ((int)fixP->fx_r_type >= 0) - as_fatal ("unhandled relocation type %s", + if ((int) fixP->fx_r_type >= 0) + as_fatal (_("unhandled relocation type %s"), bfd_get_reloc_code_name (fixP->fx_r_type)); - assert (-(int)fixP->fx_r_type < alpha_num_operands); - operand = &alpha_operands[-(int)fixP->fx_r_type]; + assert (-(int) fixP->fx_r_type < (int) alpha_num_operands); + operand = &alpha_operands[-(int) fixP->fx_r_type]; /* The rest of these fixups only exist internally during symbol resolution and have no representation in the object file. Therefore they must be completely resolved as constants. */ if (fixP->fx_addsy != 0 - && fixP->fx_addsy->bsym->section != absolute_section) + && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section) as_bad_where (fixP->fx_file, fixP->fx_line, - "non-absolute expression in constant field"); + _("non-absolute expression in constant field")); - image = bfd_getl32(fixpos); - image = insert_operand(image, operand, (offsetT)value, - fixP->fx_file, fixP->fx_line); + image = bfd_getl32 (fixpos); + image = insert_operand (image, operand, (offsetT) value, + fixP->fx_file, fixP->fx_line); } goto write_done; } @@ -1151,13 +1265,13 @@ md_apply_fix (fixP, valueP) return 1; else { - as_warn_where(fixP->fx_file, fixP->fx_line, - "type %d reloc done?\n", (int)fixP->fx_r_type); + as_warn_where (fixP->fx_file, fixP->fx_line, + _("type %d reloc done?\n"), (int) fixP->fx_r_type); goto done; } write_done: - md_number_to_chars(fixpos, image, 4); + md_number_to_chars (fixpos, image, 4); done: fixP->fx_done = 1; @@ -1169,7 +1283,7 @@ done: */ symbolS * -md_undefined_symbol(name) +md_undefined_symbol (name) char *name; { if (*name == '$') @@ -1185,7 +1299,7 @@ md_undefined_symbol(name) /* FALLTHRU */ case 'r': - if (!isdigit(*++name)) + if (!ISDIGIT (*++name)) break; /* FALLTHRU */ @@ -1193,7 +1307,7 @@ md_undefined_symbol(name) case '5': case '6': case '7': case '8': case '9': if (name[1] == '\0') num = name[0] - '0'; - else if (name[0] != '0' && isdigit(name[1]) && name[2] == '\0') + else if (name[0] != '0' && ISDIGIT (name[1]) && name[2] == '\0') { num = (name[0] - '0') * 10 + name[1] - '0'; if (num >= 32) @@ -1202,15 +1316,15 @@ md_undefined_symbol(name) else break; - if (!alpha_noat_on && num == AXP_REG_AT) - as_warn("Used $at without \".set noat\""); + if (!alpha_noat_on && (num + is_float) == AXP_REG_AT) + as_warn (_("Used $at without \".set noat\"")); return alpha_register_table[num + is_float]; case 'a': if (name[1] == 't' && name[2] == '\0') { if (!alpha_noat_on) - as_warn("Used $at without \".set noat\""); + as_warn (_("Used $at without \".set noat\"")); return alpha_register_table[AXP_REG_AT]; } break; @@ -1254,29 +1368,31 @@ alpha_define_label (sym) } /* Return true if we must always emit a reloc for a type and false if - there is some hope of resolving it a assembly time. */ + there is some hope of resolving it at assembly time. */ int alpha_force_relocation (f) fixS *f; { + if (alpha_flag_relax) + return 1; + switch (f->fx_r_type) { 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 + case BFD_RELOC_VTABLE_INHERIT: + case BFD_RELOC_VTABLE_ENTRY: return 1; case BFD_RELOC_23_PCREL_S2: @@ -1286,7 +1402,8 @@ alpha_force_relocation (f) return 0; default: - assert((int)f->fx_r_type < 0 && -(int)f->fx_r_type < alpha_num_operands); + assert ((int) f->fx_r_type < 0 + && -(int) f->fx_r_type < (int) alpha_num_operands); return 0; } } @@ -1299,7 +1416,7 @@ alpha_fix_adjustable (f) { #ifdef OBJ_ELF /* Prevent all adjustments to global symbols */ - if (S_IS_EXTERN (f->fx_addsy)) + if (S_IS_EXTERN (f->fx_addsy) || S_IS_WEAK (f->fx_addsy)) return 0; #endif @@ -1312,22 +1429,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 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: + 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: @@ -1335,8 +1451,8 @@ alpha_fix_adjustable (f) return 1; default: - assert ((int)f->fx_r_type < 0 - && - (int)f->fx_r_type < alpha_num_operands); + assert ((int) f->fx_r_type < 0 + && - (int) f->fx_r_type < (int) alpha_num_operands); return 1; } /*NOTREACHED*/ @@ -1347,31 +1463,32 @@ alpha_fix_adjustable (f) arelent * tc_gen_reloc (sec, fixp) - asection *sec; + asection *sec ATTRIBUTE_UNUSED; fixS *fixp; { arelent *reloc; reloc = (arelent *) xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; + reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; /* Make sure none of our internal relocations make it this far. They'd better have been fully resolved by this point. */ - assert ((int)fixp->fx_r_type > 0); + assert ((int) fixp->fx_r_type > 0); reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); if (reloc->howto == NULL) { as_bad_where (fixp->fx_file, fixp->fx_line, - "cannot represent `%s' relocation in object file", + _("cannot represent `%s' relocation in object file"), bfd_get_reloc_code_name (fixp->fx_r_type)); return NULL; } if (!fixp->fx_pcrel != !reloc->howto->pc_relative) { - as_fatal ("internal error? cannot generate `%s' relocation", + as_fatal (_("internal error? cannot generate `%s' relocation"), bfd_get_reloc_code_name (fixp->fx_r_type)); } assert (!fixp->fx_pcrel == !reloc->howto->pc_relative); @@ -1393,8 +1510,10 @@ tc_gen_reloc (sec, fixp) * at assembly time. bfd_perform_reloc doesn't know about this sort * of thing, and as a result we need to fake it out here. */ - if (S_IS_EXTERN (fixp->fx_addsy) && !S_IS_COMMON(fixp->fx_addsy)) - reloc->addend -= fixp->fx_addsy->bsym->value; + if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy) + || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE)) + && !S_IS_COMMON (fixp->fx_addsy)) + reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value; #endif } @@ -1409,7 +1528,7 @@ tc_gen_reloc (sec, fixp) int tc_get_register (frame) - int frame; + int frame ATTRIBUTE_UNUSED; { int framereg = AXP_REG_SP; @@ -1420,11 +1539,11 @@ tc_get_register (frame) char c = get_symbol_end (); symbolS *sym = md_undefined_symbol (s); - *strchr(s, '\0') = c; + *strchr (s, '\0') = c; if (sym && (framereg = S_GET_VALUE (sym)) <= 31) goto found; } - as_warn ("frame reg expected, using $%d.", framereg); + as_warn (_("frame reg expected, using $%d."), framereg); found: note_gpreg (framereg); @@ -1450,6 +1569,232 @@ alpha_frob_file_before_adjust () #endif /* OBJ_ECOFF */ +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, and similarly for !gpdisp relocations. */ + +void +alpha_adjust_symtab () +{ + if (alpha_literal_hash) + bfd_map_over_sections (stdoutput, alpha_adjust_symtab_relocs, NULL); +} + +static void +alpha_adjust_symtab_relocs (abfd, sec, ptr) + bfd *abfd ATTRIBUTE_UNUSED; + asection *sec; + PTR ptr ATTRIBUTE_UNUSED; +{ + segment_info_type *seginfo = seg_info (sec); + fixS **prevP; + 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 + the links in place. */ + if (seginfo == NULL) + return; + + /* If there are no relocations, skip the section. */ + if (! seginfo->fix_root) + return; + + /* 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; + + 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); + 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; + + default: + *prevP = fixp; + prevP = &fixp->fx_next; + break; + } + } + + /* 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) + { + next = fixp->fx_next; + 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) + { + for (slave = fixp->tc_fix_data.info->slaves; + slave != (fixS *) 0; + slave = slave->tc_fix_data.next_reloc) + { + slave->fx_next = fixp->fx_next; + fixp->fx_next = slave; + } + } + 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 DEBUG_ALPHA +static void +debug_exp (tok, ntok) + expressionS tok[]; + int ntok; +{ + int i; + + fprintf (stderr, "debug_exp: %d tokens", ntok); + for (i = 0; i < ntok; i++) + { + expressionS *t = &tok[i]; + const char *name; + switch (t->X_op) + { + default: name = "unknown"; break; + case O_illegal: name = "O_illegal"; break; + case O_absent: name = "O_absent"; break; + case O_constant: name = "O_constant"; break; + case O_symbol: name = "O_symbol"; break; + case O_symbol_rva: name = "O_symbol_rva"; break; + case O_register: name = "O_register"; break; + case O_big: name = "O_big"; break; + case O_uminus: name = "O_uminus"; break; + case O_bit_not: name = "O_bit_not"; break; + case O_logical_not: name = "O_logical_not"; break; + case O_multiply: name = "O_multiply"; break; + case O_divide: name = "O_divide"; break; + case O_modulus: name = "O_modulus"; break; + case O_left_shift: name = "O_left_shift"; break; + case O_right_shift: name = "O_right_shift"; break; + case O_bit_inclusive_or: name = "O_bit_inclusive_or"; break; + case O_bit_or_not: name = "O_bit_or_not"; break; + case O_bit_exclusive_or: name = "O_bit_exclusive_or"; break; + case O_bit_and: name = "O_bit_and"; break; + case O_add: name = "O_add"; break; + case O_subtract: name = "O_subtract"; break; + case O_eq: name = "O_eq"; break; + case O_ne: name = "O_ne"; break; + case O_lt: name = "O_lt"; break; + case O_le: name = "O_le"; break; + case O_ge: name = "O_ge"; break; + case O_gt: name = "O_gt"; break; + case O_logical_and: name = "O_logical_and"; break; + case O_logical_or: name = "O_logical_or"; break; + case O_index: name = "O_index"; 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_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_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; + } + + fprintf (stderr, ", %s(%s, %s, %d)", name, + (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--", + (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--", + (int) t->X_add_number); + } + fprintf (stderr, "\n"); + fflush (stderr); +} +#endif + /* Parse the arguments to an opcode. */ static int @@ -1461,6 +1806,14 @@ tokenize_arguments (str, tok, ntok) expressionS *end_tok = tok + ntok; char *old_input_line_pointer; int saw_comma = 0, saw_arg = 0; +#ifdef DEBUG_ALPHA + expressionS *orig_tok = tok; +#endif + char *p; + const struct alpha_reloc_op_tag *r; + int c, i; + size_t len; + int reloc_found_p = 0; memset (tok, 0, sizeof (*tok) * ntok); @@ -1468,6 +1821,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 (); @@ -1476,6 +1834,81 @@ tokenize_arguments (str, tok, ntok) case '\0': goto fini; +#ifdef RELOC_OP_P + case '!': + /* A relocation operand can be placed after the normal operand on an + assembly language statement, and has the following form: + !relocation_type!sequence_number. */ + if (reloc_found_p) + { /* only support one relocation op per insn */ + as_bad (_("More than one relocation op per insn")); + goto err_report; + } + + if (!saw_arg) + goto err; + + ++input_line_pointer; + SKIP_WHITESPACE (); + p = input_line_pointer; + c = get_symbol_end (); + + /* Parse !relocation_type */ + len = input_line_pointer - p; + if (len == 0) + { + as_bad (_("No relocation operand")); + goto err_report; + } + + r = &alpha_reloc_op[0]; + for (i = alpha_num_reloc_op - 1; i >= 0; i--, r++) + if (len == r->length && memcmp (p, r->name, len) == 0) + break; + if (i < 0) + { + as_bad (_("Unknown relocation operand: !%s"), p); + goto err_report; + } + + *input_line_pointer = c; + SKIP_WHITESPACE (); + if (*input_line_pointer != '!') + { + if (r->require_seq) + { + as_bad (_("no sequence number after !%s"), p); + goto err_report; + } + + tok->X_add_number = 0; + } + else + { + if (! r->allow_seq) + { + as_bad (_("!%s does not use a sequence number"), p); + goto err_report; + } + + input_line_pointer++; + + /* Parse !sequence_number */ + expression (tok); + if (tok->X_op != O_constant || tok->X_add_number <= 0) + { + as_bad (_("Bad sequence number: !%s!%s"), + r->name, input_line_pointer); + goto err_report; + } + } + + tok->X_op = r->op; + reloc_found_p = 1; + ++tok; + break; +#endif /* RELOC_OP_P */ + case ',': ++input_line_pointer; if (saw_comma || !saw_arg) @@ -1487,7 +1920,7 @@ tokenize_arguments (str, tok, ntok) { char *hold = input_line_pointer++; - /* First try for parenthesized register ... */ + /* First try for parenthesized register ... */ expression (tok); if (*input_line_pointer == ')' && tok->X_op == O_register) { @@ -1506,6 +1939,7 @@ tokenize_arguments (str, tok, ntok) default: if (saw_arg && !saw_comma) goto err; + expression (tok); if (tok->X_op == O_illegal || tok->X_op == O_absent) goto err; @@ -1521,18 +1955,36 @@ fini: if (saw_comma) goto err; input_line_pointer = old_input_line_pointer; + +#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; + +err_report: +#ifdef RELOC_OP_P + is_end_of_line[(unsigned char) '!'] = 0; +#endif input_line_pointer = old_input_line_pointer; - return -1; + return TOKENIZE_ERROR_REPORT; } /* Search forward through all variants of an opcode looking for a syntax match. */ static const struct alpha_opcode * -find_opcode_match(first_opcode, tok, pntok, pcpumatch) +find_opcode_match (first_opcode, tok, pntok, pcpumatch) const struct alpha_opcode *first_opcode; const expressionS *tok; int *pntok; @@ -1574,22 +2026,22 @@ find_opcode_match(first_opcode, tok, pntok, pcpumatch) { case AXP_OPERAND_IR: if (tok[tokidx].X_op != O_register - || !is_ir_num(tok[tokidx].X_add_number)) + || !is_ir_num (tok[tokidx].X_add_number)) goto match_failed; break; case AXP_OPERAND_FPR: if (tok[tokidx].X_op != O_register - || !is_fpr_num(tok[tokidx].X_add_number)) + || !is_fpr_num (tok[tokidx].X_add_number)) goto match_failed; break; - case AXP_OPERAND_IR|AXP_OPERAND_PARENS: + case AXP_OPERAND_IR | AXP_OPERAND_PARENS: if (tok[tokidx].X_op != O_pregister - || !is_ir_num(tok[tokidx].X_add_number)) + || !is_ir_num (tok[tokidx].X_add_number)) goto match_failed; break; - case AXP_OPERAND_IR|AXP_OPERAND_PARENS|AXP_OPERAND_COMMA: + case AXP_OPERAND_IR | AXP_OPERAND_PARENS | AXP_OPERAND_COMMA: if (tok[tokidx].X_op != O_cpregister - || !is_ir_num(tok[tokidx].X_add_number)) + || !is_ir_num (tok[tokidx].X_add_number)) goto match_failed; break; @@ -1604,12 +2056,15 @@ find_opcode_match(first_opcode, tok, pntok, pcpumatch) case O_pregister: case O_cpregister: goto match_failed; + + default: + break; } break; default: /* everything else should have been fake */ - abort(); + abort (); } ++tokidx; } @@ -1623,11 +2078,11 @@ find_opcode_match(first_opcode, tok, pntok, pcpumatch) match_failed:; } - while (++opcode-alpha_opcodes < alpha_num_opcodes - && !strcmp(opcode->name, first_opcode->name)); + while (++opcode - alpha_opcodes < alpha_num_opcodes + && !strcmp (opcode->name, first_opcode->name)); if (*pcpumatch) - *pcpumatch = got_cpu_match; + *pcpumatch = got_cpu_match; return NULL; } @@ -1636,7 +2091,7 @@ find_opcode_match(first_opcode, tok, pntok, pcpumatch) match. */ static const struct alpha_macro * -find_macro_match(first_macro, tok, pntok) +find_macro_match (first_macro, tok, pntok) const struct alpha_macro *first_macro; const expressionS *tok; int *pntok; @@ -1660,31 +2115,46 @@ find_macro_match(first_macro, tok, pntok) tokidx = 0; break; + /* index register */ case MACRO_IR: if (tokidx >= ntok || tok[tokidx].X_op != O_register - || !is_ir_num(tok[tokidx].X_add_number)) + || !is_ir_num (tok[tokidx].X_add_number)) goto match_failed; ++tokidx; break; + + /* parenthesized index register */ case MACRO_PIR: if (tokidx >= ntok || tok[tokidx].X_op != O_pregister - || !is_ir_num(tok[tokidx].X_add_number)) + || !is_ir_num (tok[tokidx].X_add_number)) goto match_failed; ++tokidx; break; + + /* 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 */ case MACRO_CPIR: if (tokidx >= ntok || tok[tokidx].X_op != O_cpregister - || !is_ir_num(tok[tokidx].X_add_number)) + || !is_ir_num (tok[tokidx].X_add_number)) goto match_failed; ++tokidx; break; + + /* floating point register */ case MACRO_FPR: if (tokidx >= ntok || tok[tokidx].X_op != O_register - || !is_fpr_num(tok[tokidx].X_add_number)) + || !is_fpr_num (tok[tokidx].X_add_number)) goto match_failed; ++tokidx; break; + /* normal expression */ case MACRO_EXP: if (tokidx >= ntok) goto match_failed; @@ -1695,7 +2165,18 @@ find_macro_match(first_macro, tok, pntok) case O_register: case O_pregister: case O_cpregister: + case O_literal: + case O_lituse_base: + case O_lituse_bytoff: + case O_lituse_jsr: + case O_gpdisp: + case O_gprelhigh: + case O_gprellow: + case O_gprel: goto match_failed; + + default: + break; } ++tokidx; break; @@ -1709,8 +2190,8 @@ find_macro_match(first_macro, tok, pntok) ++arg; } } - while (++macro-alpha_macros < alpha_num_macros - && !strcmp(macro->name, first_macro->name)); + while (++macro - alpha_macros < alpha_num_macros + && !strcmp (macro->name, first_macro->name)); return NULL; } @@ -1718,7 +2199,7 @@ find_macro_match(first_macro, tok, pntok) /* Insert an operand value into an instruction. */ static unsigned -insert_operand(insn, operand, val, file, line) +insert_operand (insn, operand, val, file, line) unsigned insn; const struct alpha_operand *operand; offsetT val; @@ -1743,14 +2224,14 @@ insert_operand(insn, operand, val, file, line) if (val < min || val > max) { const char *err = - "operand out of range (%s not between %d and %d)"; + _("operand out of range (%s not between %d and %d)"); char buf[sizeof (val) * 3 + 2]; - sprint_value(buf, val); + sprint_value (buf, val); if (file) - as_warn_where(file, line, err, buf, min, max); + as_warn_where (file, line, err, buf, min, max); else - as_warn(err, buf, min, max); + as_warn (err, buf, min, max); } } @@ -1774,12 +2255,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; @@ -1790,12 +2274,12 @@ assemble_insn(opcode, tok, ntok, insn) for (argidx = opcode->operands; *argidx; ++argidx) { const struct alpha_operand *operand = &alpha_operands[*argidx]; - const expressionS *t; + const expressionS *t = (const expressionS *) 0; if (operand->flags & AXP_OPERAND_FAKE) { /* fake operands take no value and generate no fixup */ - image = insert_operand(image, operand, 0, NULL, 0); + image = insert_operand (image, operand, 0, NULL, 0); continue; } @@ -1811,12 +2295,14 @@ assemble_insn(opcode, tok, ntok, insn) break; case AXP_OPERAND_DEFAULT_ZERO: { - static const expressionS zero_exp = { 0, 0, 0, O_constant, 1 }; + static expressionS zero_exp; t = &zero_exp; + zero_exp.X_op = O_constant; + zero_exp.X_unsigned = 1; } break; default: - abort(); + abort (); } } else @@ -1827,30 +2313,91 @@ assemble_insn(opcode, tok, ntok, insn) case O_register: case O_pregister: case O_cpregister: - image = insert_operand(image, operand, regno(t->X_add_number), - NULL, 0); + image = insert_operand (image, operand, regno (t->X_add_number), + NULL, 0); break; case O_constant: - image = insert_operand(image, operand, t->X_add_number, NULL, 0); + 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 (); + + /* 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; - if (insn->nfixups >= MAX_INSN_FIXUPS) - as_fatal("too many fixups"); + if (insn->nfixups >= MAX_INSN_FIXUPS) + as_fatal (_("too many fixups")); - fixup = &insn->fixups[insn->nfixups++]; + fixup = &insn->fixups[insn->nfixups++]; + fixup->exp = *t; + fixup->reloc = BFD_RELOC_ALPHA_HINT; + } + else + { + if (reloc == BFD_RELOC_UNUSED) + reloc = operand->default_reloc; - fixup->exp = *t; - fixup->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; } @@ -1860,14 +2407,14 @@ assemble_insn(opcode, tok, ntok, insn) static void emit_insn (insn) - struct alpha_insn *insn; + struct alpha_insn *insn; { char *f; int i; - /* Take care of alignment duties */ + /* Take care of alignment duties. */ if (alpha_auto_align_on && alpha_current_align < 2) - alpha_align (2, (char *) NULL, alpha_insn_label); + alpha_align (2, (char *) NULL, alpha_insn_label, 0); if (alpha_current_align > 2) alpha_current_align = 2; alpha_insn_label = NULL; @@ -1876,24 +2423,33 @@ emit_insn (insn) f = frag_more (4); md_number_to_chars (f, insn->insn, 4); +#ifdef OBJ_ELF + dwarf2_emit_insn (4); +#endif + /* 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; int size, pcrel; fixS *fixP; /* Some fixups are only used internally and so have no howto */ - if ((int)fixup->reloc < 0) - size = 4, pcrel = 0; -#ifdef OBJ_ELF - /* These relocation types are only used internally. */ - else if (fixup->reloc == BFD_RELOC_ALPHA_GPDISP_HI16 + if ((int) fixup->reloc < 0) + { + operand = &alpha_operands[-(int) fixup->reloc]; + 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; + size = 2; + pcrel = 0; } -#endif else { reloc_howto_type *reloc_howto @@ -1901,27 +2457,94 @@ emit_insn (insn) assert (reloc_howto); size = bfd_get_reloc_size (reloc_howto); + assert (size >= 1 && size <= 4); + pcrel = reloc_howto->pc_relative; } - assert (size >= 1 && size <= 4); fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, size, &fixup->exp, pcrel, fixup->reloc); - /* Turn off complaints that the addend is too large for some fixups */ + /* Turn off complaints that the addend is too large for some fixups, + and copy in the sequence number for the explicit relocations. */ switch (fixup->reloc) { + 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; + + case BFD_RELOC_ALPHA_GPDISP_HI16: + fixP->fx_no_overflow = 1; + fixP->fx_addsy = section_symbol (now_seg); + fixP->fx_offset = 0; + + 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; + case BFD_RELOC_ALPHA_GPDISP_LO16: -#ifdef OBJ_ECOFF + 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) + 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_LITERAL: -#endif -#ifdef OBJ_ELF case BFD_RELOC_ALPHA_ELF_LITERAL: -#endif - case BFD_RELOC_GPREL32: fixP->fx_no_overflow = 1; + + 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; + default: + if ((int) fixup->reloc < 0) + { + if (operand->flags & AXP_OPERAND_NOOVERFLOW) + fixP->fx_no_overflow = 1; + } break; } } @@ -1934,7 +2557,7 @@ emit_insn (insn) than one insn in an insn structure. */ static void -assemble_tokens_to_insn(opname, tok, ntok, insn) +assemble_tokens_to_insn (opname, tok, ntok, insn) const char *opname; const expressionS *tok; int ntok; @@ -1950,17 +2573,17 @@ 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) - as_bad ("inappropriate arguments for opcode `%s'", opname); + as_bad (_("inappropriate arguments for opcode `%s'"), opname); else - as_bad ("opcode `%s' not supported for target %s", opname, - alpha_target_name); + as_bad (_("opcode `%s' not supported for target %s"), opname, + alpha_target_name); } else - as_bad ("unknown opcode `%s'", opname); + as_bad (_("unknown opcode `%s'"), opname); } /* Given an opcode name and a pre-tokenized set of arguments, take the @@ -1977,9 +2600,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)); @@ -2004,22 +2633,28 @@ 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); + as_bad (_("unknown opcode `%s'"), opname); } - /* Some instruction sets indexed by lg(size) */ static const char * const sextX_op[] = { "sextb", "sextw", "sextl", NULL }; @@ -2038,8 +2673,8 @@ static const char * const ldXu_op[] = { "ldbu", "ldwu", NULL, NULL }; static void emit_ldgp (tok, ntok, unused) const expressionS *tok; - int ntok; - const PTR unused; + int ntok ATTRIBUTE_UNUSED; + const PTR unused ATTRIBUTE_UNUSED; { #ifdef OBJ_AOUT FIXME @@ -2051,9 +2686,6 @@ FIXME expressionS newtok[3]; expressionS addend; - /* We're going to need this symbol in md_apply_fix(). */ - (void) section_symbol (absolute_section); - #ifdef OBJ_ECOFF if (regno (tok[2].X_add_number) == AXP_REG_PV) ecoff_set_gp_prolog_size (0); @@ -2068,7 +2700,8 @@ FIXME addend = tok[1]; #ifdef OBJ_ECOFF - assert (addend.X_op == O_constant); + if (addend.X_op != O_constant) + as_bad (_("can not resolve expression")); addend.X_op = O_symbol; addend.X_add_symbol = alpha_gp_symbol; #endif @@ -2076,6 +2709,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); @@ -2090,6 +2724,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 */ @@ -2116,7 +2751,7 @@ add_to_link_pool (basesym, sym, addend) segment_info_type *seginfo = seg_info (alpha_link_section); fixS *fixp; - offset = -basesym->sy_obj; + offset = - *symbol_get_obj (basesym); /* @@ This assumes all entries in a given section will be of the same size... Probably correct, but unwise to rely on. */ @@ -2131,7 +2766,7 @@ add_to_link_pool (basesym, sym, addend) { if (range_signed_16 (offset)) { - return offset; + return offset; } } } @@ -2166,17 +2801,21 @@ add_to_link_pool (basesym, sym, addend) i.e. "ldq $targ, LIT($gp); addq $targ, $0, $targ". Odd, perhaps, but this is what OSF/1 does. - Finally, the return value is true if the calling macro may emit a - LITUSE reloc if otherwise appropriate. */ + If explicit relocations of the form !literal! are allowed, + and used, then explict_reloc with be an expression pointer. -static int + 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 long load_expression (targreg, exp, pbasereg, poffset) int targreg; const expressionS *exp; int *pbasereg; expressionS *poffset; { - int emit_lituse = 0; + long emit_lituse = 0; offsetT addend = exp->X_add_number; int basereg = *pbasereg; struct alpha_insn insn; @@ -2206,16 +2845,16 @@ load_expression (targreg, exp, pbasereg, poffset) } if (lit >= 0x8000) - as_fatal ("overflow in literal (.lita) table"); + as_fatal (_("overflow in literal (.lita) table")); /* emit "ldq r, lit(gp)" */ if (basereg != alpha_gp_register && targreg == basereg) { if (alpha_noat_on) - as_bad ("macro requires $at register while noat in effect"); + as_bad (_("macro requires $at register while noat in effect")); if (targreg == AXP_REG_AT) - as_bad ("macro requires $at while $at in use"); + as_bad (_("macro requires $at while $at in use")); set_tok_reg (newtok[0], AXP_REG_AT); } @@ -2228,6 +2867,7 @@ load_expression (targreg, exp, pbasereg, poffset) 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)" */ @@ -2235,9 +2875,9 @@ load_expression (targreg, exp, pbasereg, poffset) if (basereg != alpha_gp_register && targreg == basereg) { if (alpha_noat_on) - as_bad ("macro requires $at register while noat in effect"); + as_bad (_("macro requires $at register while noat in effect")); if (targreg == AXP_REG_AT) - as_bad ("macro requires $at while $at in use"); + as_bad (_("macro requires $at while $at in use")); set_tok_reg (newtok[0], AXP_REG_AT); } @@ -2247,8 +2887,9 @@ load_expression (targreg, exp, pbasereg, poffset) /* XXX: Disable this .got minimizing optimization so that we can get better instruction offset knowledge in the compiler. This happens very infrequently anyway. */ - if (1 || !range_signed_32 (addend) - && (alpha_noat_on || targreg == AXP_REG_AT)) + if (1 + || (!range_signed_32 (addend) + && (alpha_noat_on || targreg == AXP_REG_AT))) { newtok[1] = *exp; addend = 0; @@ -2264,6 +2905,7 @@ load_expression (targreg, exp, pbasereg, poffset) assert (insn.nfixups == 1); insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL; + insn.sequence = emit_lituse = next_sequence_num--; #endif /* OBJ_ELF */ #ifdef OBJ_EVAX offsetT link; @@ -2308,11 +2950,9 @@ load_expression (targreg, exp, pbasereg, poffset) } #endif /* OBJ_EVAX */ - emit_insn(&insn); + emit_insn (&insn); #ifndef OBJ_EVAX - emit_lituse = 1; - if (basereg != alpha_gp_register && basereg != AXP_REG_ZERO) { /* emit "addq r, base, r" */ @@ -2332,7 +2972,7 @@ load_expression (targreg, exp, pbasereg, poffset) case O_subtract: /* Assume that this difference expression will be resolved to an - absolute value and that that value will fit in 16 bits. */ + absolute value and that that value will fit in 16 bits. */ set_tok_reg (newtok[0], targreg); newtok[1] = *exp; @@ -2344,20 +2984,25 @@ load_expression (targreg, exp, pbasereg, poffset) return 0; case O_big: - as_bad ("%s number invalid; zero assumed", - exp->X_add_number > 0 ? "bignum" : "floating point"); + if (exp->X_add_number > 0) + as_bad (_("bignum invalid; zero assumed")); + else + as_bad (_("floating point number invalid; zero assumed")); addend = 0; break; default: - abort(); + as_bad (_("can't handle expression")); + addend = 0; + break; } 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)" */ @@ -2379,22 +3024,22 @@ load_expression (targreg, exp, pbasereg, poffset) alpha_lit8_literal = add_to_literal_pool (alpha_lit8_symbol, 0x8000, alpha_lita_section, 8); if (alpha_lit8_literal >= 0x8000) - as_fatal ("overflow in literal (.lita) table"); + as_fatal (_("overflow in literal (.lita) table")); #endif } lit = add_to_literal_pool (NULL, addend, alpha_lit8_section, 8) - 0x8000; if (lit >= 0x8000) - as_fatal ("overflow in literal (.lit8) table"); + as_fatal (_("overflow in literal (.lit8) table")); /* emit "lda litreg, .lit8+0x8000" */ if (targreg == basereg) { if (alpha_noat_on) - as_bad ("macro requires $at register while noat in effect"); + as_bad (_("macro requires $at register while noat in effect")); if (targreg == AXP_REG_AT) - as_bad ("macro requires $at while $at in use"); + as_bad (_("macro requires $at while $at in use")); set_tok_reg (newtok[0], AXP_REG_AT); } @@ -2417,6 +3062,7 @@ load_expression (targreg, exp, pbasereg, poffset) #ifdef OBJ_ELF insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL; #endif + insn.sequence = seq_num; emit_insn (&insn); @@ -2428,15 +3074,10 @@ load_expression (targreg, exp, pbasereg, poffset) 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_constant; - insn.fixups[0].exp.X_add_number = 1; + insn.sequence = seq_num; emit_lituse = 0; emit_insn (&insn); @@ -2519,7 +3160,7 @@ static void emit_lda (tok, ntok, unused) const expressionS *tok; int ntok; - const PTR unused; + const PTR unused ATTRIBUTE_UNUSED; { int basereg; @@ -2537,8 +3178,8 @@ emit_lda (tok, ntok, unused) static void emit_ldah (tok, ntok, unused) const expressionS *tok; - int ntok; - const PTR unused; + int ntok ATTRIBUTE_UNUSED; + const PTR unused ATTRIBUTE_UNUSED; { expressionS newtok[3]; @@ -2559,7 +3200,8 @@ 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; @@ -2574,20 +3216,15 @@ emit_ir_load (tok, ntok, opname) newtok[0] = tok[0]; set_tok_preg (newtok[2], basereg); - assemble_tokens_to_insn ((const char *)opname, newtok, 3, &insn); + assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn); 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_constant; - insn.fixups[0].exp.X_add_number = 1; + insn.sequence = lituse; } emit_insn (&insn); @@ -2602,7 +3239,8 @@ emit_loadstore (tok, ntok, opname) int ntok; const PTR opname; { - int basereg, lituse; + int basereg; + long lituse; expressionS newtok[3]; struct alpha_insn insn; @@ -2611,10 +3249,10 @@ emit_loadstore (tok, ntok, opname) else basereg = tok[2].X_add_number; - if (tok[1].X_op != O_constant || !range_signed_16(tok[1].X_add_number)) + if (tok[1].X_op != O_constant || !range_signed_16 (tok[1].X_add_number)) { if (alpha_noat_on) - as_bad ("macro requires $at register while noat in effect"); + as_bad (_("macro requires $at register while noat in effect")); lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, &newtok[1]); } @@ -2627,20 +3265,15 @@ emit_loadstore (tok, ntok, opname) newtok[0] = tok[0]; set_tok_preg (newtok[2], basereg); - assemble_tokens_to_insn ((const char *)opname, newtok, 3, &insn); + assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn); 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_constant; - insn.fixups[0].exp.X_add_number = 1; + insn.sequence = lituse; } emit_insn (&insn); @@ -2655,32 +3288,61 @@ emit_ldXu (tok, ntok, vlgsize) const PTR vlgsize; { if (alpha_target & AXP_OPCODE_BWX) - emit_ir_load (tok, ntok, ldXu_op[(long)vlgsize]); + emit_ir_load (tok, ntok, ldXu_op[(long) 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"); + 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); } } @@ -2693,7 +3355,7 @@ emit_ldX (tok, ntok, vlgsize) const PTR vlgsize; { emit_ldXu (tok, ntok, vlgsize); - assemble_tokens (sextX_op[(long)vlgsize], tok, 1, 1); + assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1); } /* Load an integral value from an unaligned address as an unsigned @@ -2705,11 +3367,11 @@ emit_uldXu (tok, ntok, vlgsize) int ntok; const PTR vlgsize; { - long lgsize = (long)vlgsize; + long lgsize = (long) vlgsize; expressionS newtok[3]; if (alpha_noat_on) - as_bad ("macro requires $at register while noat in effect"); + as_bad (_("macro requires $at register while noat in effect")); /* emit "lda $at, exp" */ @@ -2727,7 +3389,7 @@ emit_uldXu (tok, ntok, vlgsize) /* emit "ldq_u $t10, size-1($at)" */ set_tok_reg (newtok[0], AXP_REG_T10); - set_tok_const (newtok[1], (1< 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_constant; - insn.fixups[0].exp.X_add_number = 3; + insn.sequence = lituse; } emit_insn (&insn); @@ -3240,7 +3948,7 @@ emit_retjcr (tok, ntok, vopname) int ntok; const PTR vopname; { - const char *opname = (const char *)vopname; + const char *opname = (const char *) vopname; expressionS newtok[3]; int r, tokidx = 0; @@ -3262,7 +3970,7 @@ emit_retjcr (tok, ntok, vopname) if (tokidx < ntok) newtok[2] = tok[tokidx]; else - set_tok_const (newtok[2], strcmp(opname, "ret") == 0); + set_tok_const (newtok[2], strcmp (opname, "ret") == 0); assemble_tokens (opname, newtok, 3, 0); } @@ -3334,32 +4042,45 @@ s_alpha_comm (ignore) } if ((temp = get_absolute_expression ()) < 0) { - as_warn (".COMMon length (%ld.) <0! Ignored.", (long) temp); + as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp); ignore_rest_of_line (); return; } *p = 0; symbolP = symbol_find_or_make (name); - *p = c; #ifdef OBJ_EVAX /* Make a section for the common symbol. */ new_seg = subseg_new (xstrdup (name), 0); #endif + *p = c; + +#ifdef OBJ_EVAX + /* alignment might follow */ + if (*input_line_pointer == ',') + { + offsetT align; + + input_line_pointer++; + align = get_absolute_expression (); + bfd_set_section_alignment (stdoutput, new_seg, align); + } +#endif + if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) { - as_bad ("Ignoring attempt to re-define symbol"); + as_bad (_("Ignoring attempt to re-define symbol")); ignore_rest_of_line (); return; } #ifdef OBJ_EVAX if (bfd_section_size (stdoutput, new_seg) > 0) - { + { if (bfd_section_size (stdoutput, new_seg) != temp) - as_bad ("Length of .comm \"%s\" is already %ld. Not changed to %ld.", + as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."), S_GET_NAME (symbolP), (long) bfd_section_size (stdoutput, new_seg), (long) temp); @@ -3368,7 +4089,7 @@ s_alpha_comm (ignore) if (S_GET_VALUE (symbolP)) { if (S_GET_VALUE (symbolP) != (valueT) temp) - as_bad ("Length of .comm \"%s\" is already %ld. Not changed to %ld.", + as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."), S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), (long) temp); @@ -3376,12 +4097,12 @@ s_alpha_comm (ignore) #endif else { -#ifdef OBJ_EVAX +#ifdef OBJ_EVAX subseg_set (new_seg, 0); p = frag_more (temp); new_seg->flags |= SEC_IS_COMMON; if (! S_IS_DEFINED (symbolP)) - symbolP->bsym->section = new_seg; + S_SET_SEGMENT (symbolP, new_seg); #else S_SET_VALUE (symbolP, (valueT) temp); #endif @@ -3392,7 +4113,7 @@ s_alpha_comm (ignore) subseg_set (current_section, current_subsec); #endif - know (symbolP->sy_frag == &zero_address_frag); + know (symbol_get_frag (symbolP) == &zero_address_frag); demand_empty_rest_of_line (); } @@ -3456,24 +4177,264 @@ s_alpha_section (ignore) alpha_current_align = 0; } -#endif +static void +s_alpha_ent (dummy) + int dummy ATTRIBUTE_UNUSED; +{ + if (ECOFF_DEBUGGING) + ecoff_directive_ent (0); + else + { + char *name, name_end; + name = input_line_pointer; + name_end = get_symbol_end (); + + if (! is_name_beginner (*name)) + { + as_warn (_(".ent directive has no name")); + *input_line_pointer = name_end; + } + else + { + symbolS *sym; + + if (alpha_cur_ent_sym) + as_warn (_("nested .ent directives")); + + sym = symbol_find_or_make (name); + symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION; + alpha_cur_ent_sym = sym; + + /* The .ent directive is sometimes followed by a number. Not sure + what it really means, but ignore it. */ + *input_line_pointer = name_end; + SKIP_WHITESPACE (); + if (*input_line_pointer == ',') + { + input_line_pointer++; + SKIP_WHITESPACE (); + } + if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-') + (void) get_absolute_expression (); + } + demand_empty_rest_of_line (); + } +} + +static void +s_alpha_end (dummy) + int dummy ATTRIBUTE_UNUSED; +{ + if (ECOFF_DEBUGGING) + ecoff_directive_end (0); + else + { + char *name, name_end; + name = input_line_pointer; + name_end = get_symbol_end (); + + if (! is_name_beginner (*name)) + { + as_warn (_(".end directive has no name")); + *input_line_pointer = name_end; + } + else + { + symbolS *sym; + + sym = symbol_find (name); + if (sym != alpha_cur_ent_sym) + as_warn (_(".end directive names different symbol than .ent")); + + /* Create an expression to calculate the size of the function. */ + if (sym) + { + symbol_get_obj (sym)->size = + (expressionS *) xmalloc (sizeof (expressionS)); + symbol_get_obj (sym)->size->X_op = O_subtract; + symbol_get_obj (sym)->size->X_add_symbol + = symbol_new ("L0\001", now_seg, frag_now_fix (), frag_now); + symbol_get_obj (sym)->size->X_op_symbol = sym; + symbol_get_obj (sym)->size->X_add_number = 0; + } + + alpha_cur_ent_sym = NULL; + + *input_line_pointer = name_end; + } + demand_empty_rest_of_line (); + } +} + +static void +s_alpha_mask (fp) + int fp; +{ + if (ECOFF_DEBUGGING) + { + if (fp) + ecoff_directive_fmask (0); + else + ecoff_directive_mask (0); + } + else + discard_rest_of_line (); +} + +static void +s_alpha_frame (dummy) + int dummy ATTRIBUTE_UNUSED; +{ + if (ECOFF_DEBUGGING) + ecoff_directive_frame (0); + else + discard_rest_of_line (); +} + +static void +s_alpha_prologue (ignore) + int ignore ATTRIBUTE_UNUSED; +{ + symbolS *sym; + int arg; + + arg = get_absolute_expression (); + demand_empty_rest_of_line (); + + if (ECOFF_DEBUGGING) + sym = ecoff_get_cur_proc_sym (); + else + sym = alpha_cur_ent_sym; + know (sym != NULL); + + switch (arg) + { + case 0: /* No PV required. */ + S_SET_OTHER (sym, STO_ALPHA_NOPV + | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD)); + break; + case 1: /* Std GP load. */ + S_SET_OTHER (sym, STO_ALPHA_STD_GPLOAD + | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD)); + break; + case 2: /* Non-std use of PV. */ + break; + + default: + as_bad (_("Invalid argument %d to .prologue."), arg); + break; + } +} + +static char *first_file_directive; + +static void +s_alpha_file (ignore) + int ignore ATTRIBUTE_UNUSED; +{ + /* Save the first .file directive we see, so that we can change our + minds about whether ecoff debugging should or shouldn't be enabled. */ + if (alpha_flag_mdebug < 0 && ! first_file_directive) + { + char *start = input_line_pointer; + size_t len; + + discard_rest_of_line (); + + len = input_line_pointer - start; + first_file_directive = xmalloc (len + 1); + memcpy (first_file_directive, start, len); + first_file_directive[len] = '\0'; + + input_line_pointer = start; + } + + if (ECOFF_DEBUGGING) + ecoff_directive_file (0); + else + dwarf2_directive_file (0); +} + +static void +s_alpha_loc (ignore) + int ignore ATTRIBUTE_UNUSED; +{ + if (ECOFF_DEBUGGING) + ecoff_directive_loc (0); + else + dwarf2_directive_loc (0); +} + +static void +s_alpha_stab (n) + int n; +{ + /* If we've been undecided about mdebug, make up our minds in favour. */ + if (alpha_flag_mdebug < 0) + { + segT sec = subseg_new (".mdebug", 0); + bfd_set_section_flags (stdoutput, sec, SEC_HAS_CONTENTS | SEC_READONLY); + bfd_set_section_alignment (stdoutput, sec, 3); + + ecoff_read_begin_hook (); + + if (first_file_directive) + { + char *save_ilp = input_line_pointer; + input_line_pointer = first_file_directive; + ecoff_directive_file (0); + input_line_pointer = save_ilp; + free (first_file_directive); + } + + alpha_flag_mdebug = 1; + } + s_stab (n); +} + +static void +s_alpha_coff_wrapper (which) + int which; +{ + static void (* const fns[]) PARAMS ((int)) = { + ecoff_directive_begin, + ecoff_directive_bend, + ecoff_directive_def, + ecoff_directive_dim, + ecoff_directive_endef, + ecoff_directive_scl, + ecoff_directive_tag, + ecoff_directive_val, + }; + + assert (which >= 0 && which < (int) (sizeof (fns)/sizeof (*fns))); + + if (ECOFF_DEBUGGING) + (*fns[which]) (0); + else + { + as_bad (_("ECOFF debugging is disabled.")); + ignore_rest_of_line (); + } +} +#endif /* OBJ_ELF */ #ifdef OBJ_EVAX - + /* Handle the section specific pseudo-op. */ - + static void s_alpha_section (secid) int secid; { int temp; -#define EVAX_SECTION_COUNT 6 - static char *section_name[EVAX_SECTION_COUNT+1] = - { "NULL", ".rdata", ".comm", ".link", ".ctors", ".dtors", ".lcomm" }; +#define EVAX_SECTION_COUNT 5 + static char *section_name[EVAX_SECTION_COUNT + 1] = + { "NULL", ".rdata", ".comm", ".link", ".ctors", ".dtors" }; if ((secid <= 0) || (secid > EVAX_SECTION_COUNT)) { - as_fatal ("Unknown section directive"); + as_fatal (_("Unknown section directive")); demand_empty_rest_of_line (); return; } @@ -3485,19 +4446,6 @@ s_alpha_section (secid) alpha_current_align = 0; } - -/* .prologue */ - -static void -s_alpha_prologue (ignore) - int ignore; -{ - demand_empty_rest_of_line (); - - return; -} - - /* Parse .ent directives. */ static void @@ -3522,20 +4470,19 @@ s_alpha_ent (ignore) if (symexpr.X_op != O_symbol) { - as_fatal (".ent directive has no symbol"); + as_fatal (_(".ent directive has no symbol")); demand_empty_rest_of_line (); return; } symbol = make_expr_symbol (&symexpr); - symbol->bsym->flags |= BSF_FUNCTION; + symbol_get_bfdsym (symbol)->flags |= BSF_FUNCTION; alpha_evax_proc.symbol = symbol; demand_empty_rest_of_line (); return; } - /* Parse .frame ,,RA, directives. */ static void @@ -3550,7 +4497,7 @@ s_alpha_frame (ignore) if (*input_line_pointer++ != ',' || get_absolute_expression_and_terminator (&val) != ',') { - as_warn ("Bad .frame directive 1./2. param"); + as_warn (_("Bad .frame directive 1./2. param")); --input_line_pointer; demand_empty_rest_of_line (); return; @@ -3562,7 +4509,7 @@ s_alpha_frame (ignore) SKIP_WHITESPACE (); if (*input_line_pointer++ != ',') { - as_warn ("Bad .frame directive 3./4. param"); + as_warn (_("Bad .frame directive 3./4. param")); --input_line_pointer; demand_empty_rest_of_line (); return; @@ -3587,7 +4534,7 @@ s_alpha_pdesc (ignore) if (now_seg != alpha_link_section) { - as_bad (".pdesc directive not in link (.link) section"); + as_bad (_(".pdesc directive not in link (.link) section")); demand_empty_rest_of_line (); return; } @@ -3595,29 +4542,31 @@ s_alpha_pdesc (ignore) if ((alpha_evax_proc.symbol == 0) || (!S_IS_DEFINED (alpha_evax_proc.symbol))) { - as_fatal (".pdesc has no matching .ent"); + as_fatal (_(".pdesc has no matching .ent")); demand_empty_rest_of_line (); return; } - alpha_evax_proc.symbol->sy_obj = (valueT)seginfo->literal_pool_size; + *symbol_get_obj (alpha_evax_proc.symbol) = + (valueT) seginfo->literal_pool_size; expression (&exp); if (exp.X_op != O_symbol) { - as_warn (".pdesc directive has no entry symbol"); + as_warn (_(".pdesc directive has no entry symbol")); demand_empty_rest_of_line (); return; } entry_sym = make_expr_symbol (&exp); /* Save bfd symbol of proc desc in function symbol. */ - alpha_evax_proc.symbol->bsym->udata.p = (PTR)entry_sym->bsym; + symbol_get_bfdsym (alpha_evax_proc.symbol)->udata.p + = symbol_get_bfdsym (entry_sym); SKIP_WHITESPACE (); if (*input_line_pointer++ != ',') { - as_warn ("No comma after .pdesc "); + as_warn (_("No comma after .pdesc ")); demand_empty_rest_of_line (); return; } @@ -3626,21 +4575,21 @@ s_alpha_pdesc (ignore) name = input_line_pointer; name_end = get_symbol_end (); - if (strncmp(name, "stack", 5) == 0) + if (strncmp (name, "stack", 5) == 0) { alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_STACK; } - else if (strncmp(name, "reg", 3) == 0) + else if (strncmp (name, "reg", 3) == 0) { alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_REGISTER; } - else if (strncmp(name, "null", 4) == 0) + else if (strncmp (name, "null", 4) == 0) { alpha_evax_proc.pdsckind = PDSC_S_K_KIND_NULL; } else { - as_fatal ("unknown procedure kind"); + as_fatal (_("unknown procedure kind")); demand_empty_rest_of_line (); return; } @@ -3659,34 +4608,33 @@ s_alpha_pdesc (ignore) seginfo->literal_pool_size += 16; *p = alpha_evax_proc.pdsckind - | ((alpha_evax_proc.framereg == 29) ? PDSC_S_M_BASE_REG_IS_FP : 0); - *(p+1) = PDSC_S_M_NATIVE - | PDSC_S_M_NO_JACKET; + | ((alpha_evax_proc.framereg == 29) ? PDSC_S_M_BASE_REG_IS_FP : 0); + *(p + 1) = PDSC_S_M_NATIVE | PDSC_S_M_NO_JACKET; switch (alpha_evax_proc.pdsckind) { - case PDSC_S_K_KIND_NULL: - *(p+2) = 0; - *(p+3) = 0; - break; - case PDSC_S_K_KIND_FP_REGISTER: - *(p+2) = alpha_evax_proc.fp_save; - *(p+3) = alpha_evax_proc.ra_save; - break; - case PDSC_S_K_KIND_FP_STACK: - md_number_to_chars (p+2, (valueT)alpha_evax_proc.rsa_offset, 2); - break; - default: /* impossible */ - break; + case PDSC_S_K_KIND_NULL: + *(p + 2) = 0; + *(p + 3) = 0; + break; + case PDSC_S_K_KIND_FP_REGISTER: + *(p + 2) = alpha_evax_proc.fp_save; + *(p + 3) = alpha_evax_proc.ra_save; + break; + case PDSC_S_K_KIND_FP_STACK: + md_number_to_chars (p + 2, (valueT) alpha_evax_proc.rsa_offset, 2); + break; + default: /* impossible */ + break; } - *(p+4) = 0; - *(p+5) = alpha_evax_proc.type & 0x0f; + *(p + 4) = 0; + *(p + 5) = alpha_evax_proc.type & 0x0f; /* Signature offset. */ - md_number_to_chars (p+6, (valueT)0, 2); + md_number_to_chars (p + 6, (valueT) 0, 2); - fix_new_exp (frag_now, p-frag_now->fr_literal+8, 8, &exp, 0, BFD_RELOC_64); + fix_new_exp (frag_now, p - frag_now->fr_literal+8, 8, &exp, 0, BFD_RELOC_64); if (alpha_evax_proc.pdsckind == PDSC_S_K_KIND_NULL) return; @@ -3698,12 +4646,12 @@ s_alpha_pdesc (ignore) seginfo->literal_pool_size += 8; /* pdesc+16: Size. */ - md_number_to_chars (p, (valueT)alpha_evax_proc.framesize, 4); + md_number_to_chars (p, (valueT) alpha_evax_proc.framesize, 4); - md_number_to_chars (p+4, (valueT)0, 2); + md_number_to_chars (p + 4, (valueT) 0, 2); /* Entry length. */ - md_number_to_chars (p+6, alpha_evax_proc.prologue, 2); + md_number_to_chars (p + 6, alpha_evax_proc.prologue, 2); if (alpha_evax_proc.pdsckind == PDSC_S_K_KIND_FP_REGISTER) return; @@ -3717,12 +4665,11 @@ s_alpha_pdesc (ignore) /* pdesc+24: register masks. */ md_number_to_chars (p, alpha_evax_proc.imask, 4); - md_number_to_chars (p+4, alpha_evax_proc.fmask, 4); + md_number_to_chars (p + 4, alpha_evax_proc.fmask, 4); return; } - /* Support for crash debug on vms. */ static void @@ -3735,7 +4682,7 @@ s_alpha_name (ignore) if (now_seg != alpha_link_section) { - as_bad (".name directive not in link (.link) section"); + as_bad (_(".name directive not in link (.link) section")); demand_empty_rest_of_line (); return; } @@ -3743,7 +4690,7 @@ s_alpha_name (ignore) expression (&exp); if (exp.X_op != O_symbol) { - as_warn (".name directive has no symbol"); + as_warn (_(".name directive has no symbol")); demand_empty_rest_of_line (); return; } @@ -3758,12 +4705,11 @@ s_alpha_name (ignore) p = frag_more (8); seginfo->literal_pool_size += 8; - fix_new_exp (frag_now, p-frag_now->fr_literal, 8, &exp, 0, BFD_RELOC_64); + fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &exp, 0, BFD_RELOC_64); return; } - static void s_alpha_linkage (ignore) int ignore; @@ -3778,7 +4724,7 @@ s_alpha_linkage (ignore) expression (&exp); if (exp.X_op != O_symbol) { - as_fatal ("No symbol after .linkage"); + as_fatal (_("No symbol after .linkage")); } else { @@ -3792,7 +4738,6 @@ s_alpha_linkage (ignore) return; } - static void s_alpha_code_address (ignore) int ignore; @@ -3807,7 +4752,7 @@ s_alpha_code_address (ignore) expression (&exp); if (exp.X_op != O_symbol) { - as_fatal ("No symbol after .code_address"); + as_fatal (_("No symbol after .code_address")); } else { @@ -3821,7 +4766,6 @@ s_alpha_code_address (ignore) return; } - static void s_alpha_fp_save (ignore) int ignore; @@ -3833,7 +4777,6 @@ s_alpha_fp_save (ignore) return; } - static void s_alpha_mask (ignore) int ignore; @@ -3842,20 +4785,19 @@ s_alpha_mask (ignore) if (get_absolute_expression_and_terminator (&val) != ',') { - as_warn ("Bad .mask directive"); + as_warn (_("Bad .mask directive")); --input_line_pointer; } else { alpha_evax_proc.imask = val; - (void)get_absolute_expression (); + (void) get_absolute_expression (); } demand_empty_rest_of_line (); return; } - static void s_alpha_fmask (ignore) int ignore; @@ -3864,7 +4806,7 @@ s_alpha_fmask (ignore) if (get_absolute_expression_and_terminator (&val) != ',') { - as_warn ("Bad .fmask directive"); + as_warn (_("Bad .fmask directive")); --input_line_pointer; } else @@ -3891,7 +4833,6 @@ s_alpha_end (ignore) return; } - static void s_alpha_file (ignore) int ignore; @@ -3903,14 +4844,14 @@ s_alpha_file (ignore) extern char *demand_copy_string PARAMS ((int *lenP)); sprintf (case_hack, "", - alpha_flag_hash_long_names, alpha_flag_show_after_trunc); + alpha_flag_hash_long_names, alpha_flag_show_after_trunc); s = symbol_find_or_make (case_hack); - s->bsym->flags |= BSF_FILE; + symbol_get_bfdsym (s)->flags |= BSF_FILE; get_absolute_expression (); s = symbol_find_or_make (demand_copy_string (&length)); - s->bsym->flags |= BSF_FILE; + symbol_get_bfdsym (s)->flags |= BSF_FILE; demand_empty_rest_of_line (); return; @@ -3921,7 +4862,7 @@ s_alpha_file (ignore) static void s_alpha_gprel32 (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { expressionS e; char *p; @@ -3933,13 +4874,13 @@ s_alpha_gprel32 (ignore) switch (e.X_op) { case O_constant: - e.X_add_symbol = section_symbol(absolute_section); + e.X_add_symbol = section_symbol (absolute_section); e.X_op = O_symbol; /* FALLTHRU */ case O_symbol: break; default: - abort(); + abort (); } #else #ifdef OBJ_ECOFF @@ -3959,14 +4900,14 @@ s_alpha_gprel32 (ignore) #endif if (alpha_auto_align_on && alpha_current_align < 2) - alpha_align (2, (char *) NULL, alpha_insn_label); + alpha_align (2, (char *) NULL, alpha_insn_label, 0); if (alpha_current_align > 2) alpha_current_align = 2; alpha_insn_label = NULL; p = frag_more (4); memset (p, 0, 4); - fix_new_exp (frag_now, p-frag_now->fr_literal, 4, + fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &e, 0, BFD_RELOC_GPREL32); } @@ -4003,7 +4944,7 @@ s_alpha_float_cons (type) } if (alpha_auto_align_on && alpha_current_align < log_size) - alpha_align (log_size, (char *) NULL, alpha_insn_label); + alpha_align (log_size, (char *) NULL, alpha_insn_label, 0); if (alpha_current_align > log_size) alpha_current_align = log_size; alpha_insn_label = NULL; @@ -4016,7 +4957,7 @@ s_alpha_float_cons (type) static void s_alpha_proc (is_static) - int is_static; + int is_static ATTRIBUTE_UNUSED; { char *name; char c; @@ -4035,7 +4976,7 @@ s_alpha_proc (is_static) if (*input_line_pointer != ',') { *p = 0; - as_warn ("Expected comma after name \"%s\"", name); + as_warn (_("Expected comma after name \"%s\""), name); *p = c; temp = 0; ignore_rest_of_line (); @@ -4045,8 +4986,8 @@ s_alpha_proc (is_static) input_line_pointer++; temp = get_absolute_expression (); } - /* symbolP->sy_other = (signed char) temp; */ - as_warn ("unhandled: .proc %s,%d", name, temp); + /* *symbol_get_obj (symbolP) = (signed char) temp; */ + as_warn (_("unhandled: .proc %s,%d"), name, temp); demand_empty_rest_of_line (); } @@ -4055,7 +4996,7 @@ s_alpha_proc (is_static) static void s_alpha_set (x) - int x; + int x ATTRIBUTE_UNUSED; { char *name, ch, *s; int yesno = 1; @@ -4081,7 +5022,7 @@ s_alpha_set (x) else if (!strcmp ("volatile", s)) /* ignore */ ; else - as_warn ("Tried to .set unrecognized mode `%s'", name); + as_warn (_("Tried to .set unrecognized mode `%s'"), name); *input_line_pointer = ch; demand_empty_rest_of_line (); @@ -4092,13 +5033,13 @@ s_alpha_set (x) static void s_alpha_base (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { #if 0 if (first_32bit_quadrant) { /* not fatal, but it might not work in the end */ - as_warn ("File overrides no-base-register option."); + as_warn (_("File overrides no-base-register option.")); first_32bit_quadrant = 0; } #endif @@ -4115,7 +5056,7 @@ s_alpha_base (ignore) if (alpha_gp_register < 0 || alpha_gp_register > 31) { alpha_gp_register = AXP_REG_GP; - as_warn ("Bad base register, using $%d.", alpha_gp_register); + as_warn (_("Bad base register, using $%d."), alpha_gp_register); } demand_empty_rest_of_line (); @@ -4127,7 +5068,7 @@ s_alpha_base (ignore) static void s_alpha_align (ignore) - int ignore; + int ignore ATTRIBUTE_UNUSED; { int align; char fill, *pfill; @@ -4137,11 +5078,11 @@ s_alpha_align (ignore) if (align > max_alignment) { align = max_alignment; - as_bad ("Alignment too large: %d. assumed", align); + as_bad (_("Alignment too large: %d. assumed"), align); } else if (align < 0) { - as_warn ("Alignment negative: 0 assumed"); + as_warn (_("Alignment negative: 0 assumed")); align = 0; } @@ -4157,7 +5098,7 @@ s_alpha_align (ignore) if (align != 0) { alpha_auto_align_on = 1; - alpha_align (align, pfill, alpha_insn_label); + alpha_align (align, pfill, alpha_insn_label, 1); } else { @@ -4202,7 +5143,7 @@ alpha_cons_align (size) ++log_size; if (alpha_auto_align_on && alpha_current_align < log_size) - alpha_align (log_size, (char *) NULL, alpha_insn_label); + alpha_align (log_size, (char *) NULL, alpha_insn_label, 0); if (alpha_current_align > log_size) alpha_current_align = log_size; alpha_insn_label = NULL; @@ -4225,7 +5166,7 @@ s_alpha_ucons (bytes) static void s_alpha_arch (ignored) - int ignored; + int ignored ATTRIBUTE_UNUSED; { char *name, ch; const struct cpu_type *p; @@ -4235,45 +5176,43 @@ s_alpha_arch (ignored) ch = get_symbol_end (); for (p = cpu_types; p->name; ++p) - if (strcmp(name, p->name) == 0) + if (strcmp (name, p->name) == 0) { - alpha_target_name = p->name, alpha_target = p->flags; + alpha_target_name = p->name, alpha_target = p->flags; goto found; } - as_warn("Unknown CPU identifier `%s'", name); + as_warn ("Unknown CPU identifier `%s'", name); found: *input_line_pointer = ch; demand_empty_rest_of_line (); } - - #ifdef DEBUG1 /* print token expression with alpha specific extension. */ static void -alpha_print_token(f, exp) - FILE *f; - const expressionS *exp; +alpha_print_token (f, exp) + FILE *f; + const expressionS *exp; { switch (exp->X_op) { - case O_cpregister: - putc (',', f); - /* FALLTHRU */ - case O_pregister: - putc ('(', f); - { - expressionS nexp = *exp; - nexp.X_op = O_register; - print_expr (f, &nexp); - } - putc (')', f); - break; - default: - print_expr (f, exp); - break; + case O_cpregister: + putc (',', f); + /* FALLTHRU */ + case O_pregister: + putc ('(', f); + { + expressionS nexp = *exp; + nexp.X_op = O_register; + print_expr (f, &nexp); + } + putc (')', f); + break; + default: + print_expr (f, exp); + break; } return; } @@ -4281,9 +5220,7 @@ alpha_print_token(f, exp) /* The target specific pseudo-ops which we support. */ -const pseudo_typeS md_pseudo_table[] = -{ - {"common", s_comm, 0}, /* is this used? */ +const pseudo_typeS md_pseudo_table[] = { #ifdef OBJ_ECOFF {"comm", s_alpha_comm, 0}, /* osf1 compiler does this */ {"rdata", s_alpha_rdata, 0}, @@ -4316,7 +5253,30 @@ const pseudo_typeS md_pseudo_table[] = { "link", s_alpha_section, 3}, { "ctors", s_alpha_section, 4}, { "dtors", s_alpha_section, 5}, - { "lcomm", s_alpha_section, 6}, +#endif +#ifdef OBJ_ELF + /* Frame related pseudos. */ + {"ent", s_alpha_ent, 0}, + {"end", s_alpha_end, 0}, + {"mask", s_alpha_mask, 0}, + {"fmask", s_alpha_mask, 1}, + {"frame", s_alpha_frame, 0}, + {"prologue", s_alpha_prologue, 0}, + {"file", s_alpha_file, 5}, + {"loc", s_alpha_loc, 9}, + {"stabs", s_alpha_stab, 's'}, + {"stabn", s_alpha_stab, 'n'}, + /* COFF debugging related pseudos. */ + {"begin", s_alpha_coff_wrapper, 0}, + {"bend", s_alpha_coff_wrapper, 1}, + {"def", s_alpha_coff_wrapper, 2}, + {"dim", s_alpha_coff_wrapper, 3}, + {"endef", s_alpha_coff_wrapper, 4}, + {"scl", s_alpha_coff_wrapper, 5}, + {"tag", s_alpha_coff_wrapper, 6}, + {"val", s_alpha_coff_wrapper, 7}, +#else + {"prologue", s_ignore, 0}, #endif {"gprel32", s_alpha_gprel32, 0}, {"t_floating", s_alpha_float_cons, 'd'}, @@ -4332,7 +5292,6 @@ const pseudo_typeS md_pseudo_table[] = {"livereg", s_ignore, 0}, {"base", s_alpha_base, 0}, /*??*/ {"option", s_ignore, 0}, - {"prologue", s_ignore, 0}, {"aent", s_ignore, 0}, {"ugen", s_ignore, 0}, {"eflag", s_ignore, 0}, @@ -4368,7 +5327,6 @@ const pseudo_typeS md_pseudo_table[] = {NULL, 0, 0}, }; - /* Build a BFD section with its flags set appropriately for the .lita, .lit8, or .lit4 sections. */ @@ -4416,7 +5374,8 @@ select_gp_value () assert (alpha_gp_value == 0); /* Get minus-one in whatever width... */ - alpha_gp_value = 0; alpha_gp_value--; + alpha_gp_value = 0; + alpha_gp_value--; /* Select the smallest VMA of these existing sections. */ maybe_set_gp (alpha_lita_section); @@ -4435,41 +5394,58 @@ select_gp_value () S_SET_VALUE (alpha_gp_symbol, alpha_gp_value); #ifdef DEBUG1 - printf ("Chose GP value of %lx\n", alpha_gp_value); + printf (_("Chose GP value of %lx\n"), alpha_gp_value); #endif } #endif /* OBJ_ECOFF */ +#ifdef OBJ_ELF +/* Map 's' to SHF_ALPHA_GPREL. */ + +int +alpha_elf_section_letter (letter, ptr_msg) + int letter; + char **ptr_msg; +{ + if (letter == 's') + return SHF_ALPHA_GPREL; + + *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S in string"); + return 0; +} + +/* Map SHF_ALPHA_GPREL to SEC_SMALL_DATA. */ + +flagword +alpha_elf_section_flags (flags, attr, type) + flagword flags; + int attr, type ATTRIBUTE_UNUSED; +{ + if (attr & SHF_ALPHA_GPREL) + flags |= SEC_SMALL_DATA; + return flags; +} +#endif /* OBJ_ELF */ + /* Called internally to handle all alignment needs. This takes care of eliding calls to frag_align if'n the cached current alignment says we've already got it, as well as taking care of the auto-align feature wrt labels. */ static void -alpha_align (n, pfill, label) +alpha_align (n, pfill, label, force) int n; char *pfill; symbolS *label; + int force ATTRIBUTE_UNUSED; { if (alpha_current_align >= n) return; if (pfill == NULL) { - if (n > 2 - && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) - { - static char const nop[4] = { 0x1f, 0x04, 0xff, 0x47 }; - - /* First, make sure we're on a four-byte boundary, in case - someone has been putting .byte values into the text - section. The DEC assembler silently fills with unaligned - no-op instructions. This will zero-fill, then nop-fill - with proper alignment. */ - if (alpha_current_align < 2) - frag_align (2, 0, 0); - frag_align_pattern (n, nop, sizeof nop, 0); - } + if (subseg_text_p (now_seg)) + frag_align_code (n, 0); else frag_align (n, 0, 0); } @@ -4478,14 +5454,61 @@ alpha_align (n, pfill, label) alpha_current_align = n; - if (label != NULL) + if (label != NULL && S_GET_SEGMENT (label) == now_seg) { - assert (S_GET_SEGMENT (label) == now_seg); - label->sy_frag = frag_now; + symbol_set_frag (label, frag_now); S_SET_VALUE (label, (valueT) frag_now_fix ()); } - record_alignment(now_seg, n); + record_alignment (now_seg, n); + + /* ??? If alpha_flag_relax && force && elf, record the requested alignment + in a reloc for the linker to see. */ +} + +/* This is called from HANDLE_ALIGN in write.c. Fill in the contents + of an rs_align_code fragment. */ + +void +alpha_handle_align (fragp) + fragS *fragp; +{ + static char const unop[4] = { 0x00, 0x00, 0xe0, 0x2f }; + static char const nopunop[8] = { + 0x1f, 0x04, 0xff, 0x47, + 0x00, 0x00, 0xe0, 0x2f + }; + + int bytes, fix; + char *p; + + if (fragp->fr_type != rs_align_code) + return; + + bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; + p = fragp->fr_literal + fragp->fr_fix; + fix = 0; + + if (bytes & 3) + { + fix = bytes & 3; + memset (p, 0, fix); + p += fix; + bytes -= fix; + } + + if (bytes & 4) + { + memcpy (p, unop, 4); + p += 4; + bytes -= 4; + fix += 4; + } + + memcpy (p, nopunop, 8); + + fragp->fr_fix += fix; + fragp->fr_var = 8; } /* The Alpha has support for some VAX floating point types, as well as for