diff options
Diffstat (limited to 'gas/config/tc-alpha.c')
-rw-r--r-- | gas/config/tc-alpha.c | 781 |
1 files changed, 494 insertions, 287 deletions
diff --git a/gas/config/tc-alpha.c b/gas/config/tc-alpha.c index 91879bd..9a17444 100644 --- a/gas/config/tc-alpha.c +++ b/gas/config/tc-alpha.c @@ -1,10 +1,10 @@ /* tc-alpha.c - Processor-specific code for the DEC Alpha AXP CPU. - Copyright (C) 1989, 93, 94, 95, 1996 Free Software Foundation, Inc. + Copyright (C) 1989, 93, 94, 95, 96, 1997 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 Kaempf for EVAX (openVMS/Alpha) support. + Modified by Klaus K"ampf for EVAX (openVMS/Alpha) support. This file is part of GAS, the GNU Assembler. @@ -87,8 +87,8 @@ enum alpha_macro_arg struct alpha_macro { const char *name; - void (*emit) PARAMS((const expressionS *, int, void *)); - void *arg; + void (*emit) PARAMS ((const expressionS *, int, const PTR)); + const PTR arg; enum alpha_macro_arg argsets[16]; }; @@ -154,70 +154,73 @@ struct alpha_macro /* Prototypes for all local functions */ -static int tokenize_arguments PARAMS((char *, expressionS*, int)); +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*)); + PARAMS ((const struct alpha_opcode *, const expressionS *, int *, int *)); static const struct alpha_macro *find_macro_match - PARAMS((const struct alpha_macro*, const expressionS*, int*)); -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*)); -static void emit_insn PARAMS((struct alpha_insn *)); -static void assemble_tokens_to_insn PARAMS((const char *, const expressionS*, - int, struct alpha_insn *)); -static void assemble_tokens PARAMS((const char *, const expressionS*, - int, int)); - -static int load_expression PARAMS((int, const expressionS*, int *, - expressionS*)); - -static void emit_ldgp PARAMS((const expressionS*, int, void*)); -static void emit_division PARAMS((const expressionS*, int, void*)); -static void emit_lda PARAMS((const expressionS*, int, void*)); -static void emit_ldah PARAMS((const expressionS*, int, void*)); -static void emit_ir_load PARAMS((const expressionS*, int, void*)); -static void emit_loadstore PARAMS((const expressionS*, int, void*)); -static void emit_jsrjmp PARAMS((const expressionS*, int, void*)); -static void emit_ldX PARAMS((const expressionS*, int, void*)); -static void emit_ldXu PARAMS((const expressionS*, int, void*)); -static void emit_uldX PARAMS((const expressionS*, int, void*)); -static void emit_uldXu PARAMS((const expressionS*, int, void*)); -static void emit_ldil PARAMS((const expressionS*, int, void*)); -static void emit_stX PARAMS((const expressionS*, int, void*)); -static void emit_ustX PARAMS((const expressionS*, int, void*)); -static void emit_sextX PARAMS((const expressionS*, int, void*)); -static void emit_retjcr PARAMS((const expressionS*, int, void*)); - -static void s_alpha_text PARAMS((int)); -static void s_alpha_data PARAMS((int)); + PARAMS ((const struct alpha_macro *, const expressionS *, int *)); +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 *)); +static void emit_insn PARAMS ((struct alpha_insn *)); +static void assemble_tokens_to_insn + PARAMS ((const char *, const expressionS *, int, struct alpha_insn *)); +static void assemble_tokens + PARAMS ((const char *, const expressionS *, int, int)); + +static int load_expression + PARAMS ((int, const expressionS *, int *, expressionS *)); + +static void emit_ldgp PARAMS ((const expressionS *, int, const PTR)); +static void emit_division PARAMS ((const expressionS *, int, const PTR)); +static void emit_lda PARAMS ((const expressionS *, int, const PTR)); +static void emit_ldah PARAMS ((const expressionS *, int, const PTR)); +static void emit_ir_load PARAMS ((const expressionS *, int, const PTR)); +static void emit_loadstore PARAMS ((const expressionS *, int, const PTR)); +static void emit_jsrjmp PARAMS ((const expressionS *, int, const PTR)); +static void emit_ldX PARAMS ((const expressionS *, int, const PTR)); +static void emit_ldXu PARAMS ((const expressionS *, int, const PTR)); +static void emit_uldX PARAMS ((const expressionS *, int, const PTR)); +static void emit_uldXu PARAMS ((const expressionS *, int, const PTR)); +static void emit_ldil PARAMS ((const expressionS *, int, const PTR)); +static void emit_stX PARAMS ((const expressionS *, int, const PTR)); +static void emit_ustX PARAMS ((const expressionS *, int, const PTR)); +static void emit_sextX PARAMS ((const expressionS *, int, const PTR)); +static void emit_retjcr PARAMS ((const expressionS *, int, const PTR)); + +static void s_alpha_text PARAMS ((int)); +static void s_alpha_data PARAMS ((int)); #ifndef OBJ_ELF -static void s_alpha_comm PARAMS((int)); +static void s_alpha_comm PARAMS ((int)); #endif #if defined (OBJ_ECOFF) || defined (OBJ_EVAX) -static void s_alpha_rdata PARAMS((int)); +static void s_alpha_rdata PARAMS ((int)); #endif #ifdef OBJ_ECOFF -static void s_alpha_sdata PARAMS((int)); +static void s_alpha_sdata PARAMS ((int)); #endif #ifdef OBJ_ELF -static void s_alpha_section PARAMS((int)); +static void s_alpha_section PARAMS ((int)); #endif -static void s_alpha_gprel32 PARAMS((int)); -static void s_alpha_float_cons PARAMS((int)); -static void s_alpha_proc PARAMS((int)); -static void s_alpha_set PARAMS((int)); -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 create_literal_section PARAMS((const char *, segT*, symbolS**)); +#ifdef OBJ_EVAX +static void s_alpha_section PARAMS ((int)); +#endif +static void s_alpha_gprel32 PARAMS ((int)); +static void s_alpha_float_cons PARAMS ((int)); +static void s_alpha_proc PARAMS ((int)); +static void s_alpha_set PARAMS ((int)); +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 create_literal_section PARAMS ((const char *, segT *, symbolS **)); #ifndef OBJ_ELF -static void select_gp_value PARAMS((void)); +static void select_gp_value PARAMS ((void)); #endif -static void alpha_align PARAMS((int, char *, symbolS *)); +static void alpha_align PARAMS ((int, char *, symbolS *)); /* Generic assembler global variables which must be defined by all @@ -287,7 +290,7 @@ size_t md_longopts_size = sizeof(md_longopts); #endif /* OBJ_EVAX */ /* The cpu for which we are generating code */ -static unsigned alpha_target = AXP_OPCODE_ALL; +static unsigned alpha_target = AXP_OPCODE_BASE; static const char *alpha_target_name = "<all>"; /* The hash table of instruction opcodes */ @@ -317,6 +320,8 @@ static segT alpha_lit4_section; #endif #ifdef OBJ_EVAX static segT alpha_link_section; +static segT alpha_ctors_section; +static segT alpha_dtors_section; #endif static segT alpha_lit8_section; @@ -327,9 +332,17 @@ static symbolS *alpha_lit4_symbol; #endif #ifdef OBJ_EVAX static symbolS *alpha_link_symbol; +static symbolS *alpha_ctors_symbol; +static symbolS *alpha_dtors_symbol; #endif static symbolS *alpha_lit8_symbol; +/* Literal for .litX+0x8000 within .lita */ +#ifdef OBJ_ECOFF +static offsetT alpha_lit4_literal; +static offsetT alpha_lit8_literal; +#endif + /* Is the assembler not allowed to use $at? */ static int alpha_noat_on = 0; @@ -377,21 +390,10 @@ static struct { static int alpha_flag_hash_long_names = 0; /* -+ */ static int alpha_flag_show_after_trunc = 0; /* -H */ -static int alpha_flag_no_hash_mixed_case = 0; /* -h NUM */ - -/* Flag that determines how we map names. This takes several values, and - * is set with the -h switch. A value of zero implies names should be - * upper case, and the presence of the -h switch inhibits the case hack. - * No -h switch at all sets alpha_vms_name_mapping to 0, and allows case hacking. - * A value of 2 (set with -h2) implies names should be - * all lower case, with no case hack. A value of 3 (set with -h3) implies - * that case should be preserved. */ - -/* If the -+ switch is given, then the hash is appended to any name that is - * longer than 31 characters, regardless of the setting of the -h switch. - */ -static char alpha_vms_name_mapping = 0; +/* If the -+ switch is given, then a hash is appended to any name that is + * longer than 64 characters, else longer symbol names are truncated. + */ static int alpha_basereg_clobbered; #endif @@ -434,32 +436,32 @@ static const struct alpha_macro alpha_macros[] = { { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - { "ldb", emit_ldX, (void *)0, + { "ldb", emit_ldX, (PTR)0, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldbu", emit_ldXu, (void *)0, + { "ldbu", emit_ldXu, (PTR)0, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldw", emit_ldX, (void *)1, + { "ldw", emit_ldX, (PTR)1, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldwu", emit_ldXu, (void *)1, + { "ldwu", emit_ldXu, (PTR)1, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "uldw", emit_uldX, (void*)1, + { "uldw", emit_uldX, (PTR)1, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "uldwu", emit_uldXu, (void*)1, + { "uldwu", emit_uldXu, (PTR)1, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "uldl", emit_uldX, (void*)2, + { "uldl", emit_uldX, (PTR)2, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "uldlu", emit_uldXu, (void*)2, + { "uldlu", emit_uldXu, (PTR)2, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "uldq", emit_uldXu, (void*)3, + { "uldq", emit_uldXu, (PTR)3, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, @@ -513,19 +515,19 @@ static const struct alpha_macro alpha_macros[] = { { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - { "stb", emit_stX, (void*)0, + { "stb", emit_stX, (PTR)0, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "stw", emit_stX, (void*)1, + { "stw", emit_stX, (PTR)1, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ustw", emit_ustX, (void*)1, + { "ustw", emit_ustX, (PTR)1, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ustl", emit_ustX, (void*)2, + { "ustl", emit_ustX, (PTR)2, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ustq", emit_ustX, (void*)3, + { "ustq", emit_ustX, (PTR)3, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA } }, @@ -539,11 +541,11 @@ static const struct alpha_macro alpha_macros[] = { { "absq" emit_absq, 2, { EXP, IR } }, #endif - { "sextb", emit_sextX, (void *)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, (void *)1, + { "sextw", emit_sextX, (PTR)1, { MACRO_IR, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_EOA, /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } }, @@ -744,7 +746,7 @@ md_begin () 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, + bfd_set_section_flags(stdoutput, sec, SEC_ALLOC|SEC_LOAD|SEC_READONLY|SEC_DATA); bfd_set_section_alignement(stdoutput, sec, 3); #endif @@ -894,18 +896,34 @@ md_parse_option (c, arg) unsigned flags; } *p, m[] = { - { "21064", AXP_OPCODE_EV4|AXP_OPCODE_ALL }, - { "21066", AXP_OPCODE_EV4|AXP_OPCODE_ALL }, - { "21164", AXP_OPCODE_EV5|AXP_OPCODE_ALL }, - { "21164a", AXP_OPCODE_EV56|AXP_OPCODE_ALL }, - { "ev4", AXP_OPCODE_EV4|AXP_OPCODE_ALL }, - { "ev45", AXP_OPCODE_EV4|AXP_OPCODE_ALL }, - { "ev5", AXP_OPCODE_EV5|AXP_OPCODE_ALL }, - { "ev56", AXP_OPCODE_EV56|AXP_OPCODE_ALL }, - { "all", AXP_OPCODE_ALL }, + { "21064", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, + { "21064a", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, + { "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) }, + + { "ev4", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, + { "ev45", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, + { "lca45", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, + { "ev5", AXP_OPCODE_BASE|AXP_OPCODE_EV5 }, + { "ev56", AXP_OPCODE_BASE|AXP_OPCODE_EV5|AXP_OPCODE_BWX }, + { "pca56", (AXP_OPCODE_BASE|AXP_OPCODE_EV5|AXP_OPCODE_BWX + |AXP_OPCODE_CIX|AXP_OPCODE_MAX) }, + { "ev6", (AXP_OPCODE_BASE|AXP_OPCODE_BWX + |AXP_OPCODE_CIX|AXP_OPCODE_MAX) }, + + { "all", AXP_OPCODE_BASE }, { 0 } }; - + for (p = m; p->name; ++p) if (strcmp(arg, p->name) == 0) { @@ -917,8 +935,8 @@ md_parse_option (c, arg) } break; -#if OBJ_EVAX - case '+': /* For g++. Hash any name > 31 chars long. */ +#ifdef OBJ_EVAX + case '+': /* For g++. Hash any name > 63 chars long. */ alpha_flag_hash_long_names = 1; break; @@ -926,11 +944,7 @@ md_parse_option (c, arg) alpha_flag_show_after_trunc = 1; break; - case 'h': /* No hashing of mixed-case names */ - { - alpha_vms_name_mapping = atoi (arg); - alpha_flag_no_hash_mixed_case = 1; - } + case 'h': /* for gnu-c/vax compatibility. */ break; #endif @@ -958,10 +972,8 @@ Alpha options:\n\ #ifdef OBJ_EVAX fputs ("\ VMS options:\n\ --+ hash encode names longer than 31 characters\n\ --H show new symbol after hash truncation\n\ --h NUM don't hash mixed-case names, and adjust case:\n\ - 0 = upper, 2 = lower, 3 = preserve case\n", +-+ hash encode (don't truncate) names longer than 64 characters\n\ +-H show new symbol after hash truncation\n", stream); #endif } @@ -1015,7 +1027,7 @@ md_apply_fix (fixP, valueP) 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_offset = (next->fx_frag->fr_address + next->fx_where - fixP->fx_frag->fr_address - fixP->fx_where); value = (value - sign_extend_16 (value)) >> 16; @@ -1093,12 +1105,13 @@ md_apply_fix (fixP, valueP) return 1; #endif #ifdef OBJ_ELF - case BFD_RELOC_ALPHA_LITERAL: + 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 @@ -1106,15 +1119,15 @@ md_apply_fix (fixP, valueP) { const struct alpha_operand *operand; - if (fixP->fx_r_type <= BFD_RELOC_UNUSED) + if ((int)fixP->fx_r_type >= 0) as_fatal ("unhandled relocation type %s", bfd_get_reloc_code_name (fixP->fx_r_type)); - assert (fixP->fx_r_type < BFD_RELOC_UNUSED + alpha_num_operands); - operand = &alpha_operands[fixP->fx_r_type - BFD_RELOC_UNUSED]; + assert (-(int)fixP->fx_r_type < 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. + resolution and have no representation in the object file. Therefore they must be completely resolved as constants. */ if (fixP->fx_addsy != 0 @@ -1134,10 +1147,10 @@ md_apply_fix (fixP, valueP) else { as_warn_where(fixP->fx_file, fixP->fx_line, - "type %d reloc done?\n", fixP->fx_r_type); + "type %d reloc done?\n", (int)fixP->fx_r_type); goto done; } - + write_done: md_number_to_chars(fixpos, image, 4); @@ -1146,7 +1159,7 @@ done: return 0; } -/* +/* * Look for a register name in the given symbol. */ @@ -1177,7 +1190,7 @@ md_undefined_symbol(name) num = name[0] - '0'; else if (name[0] != '0' && isdigit(name[1]) && name[2] == '\0') { - num = (name[0] - '0')*10 + name[1] - '0'; + num = (name[0] - '0') * 10 + name[1] - '0'; if (num >= 32) break; } @@ -1247,11 +1260,17 @@ alpha_force_relocation (f) case BFD_RELOC_ALPHA_GPDISP_HI16: case BFD_RELOC_ALPHA_GPDISP_LO16: case BFD_RELOC_ALPHA_GPDISP: +#ifdef OBJ_ECOFF case BFD_RELOC_ALPHA_LITERAL: +#endif +#ifdef OBJ_ELF + case BFD_RELOC_ALPHA_ELF_LITERAL: +#endif case BFD_RELOC_ALPHA_LITUSE: case BFD_RELOC_GPREL32: #ifdef OBJ_EVAX case BFD_RELOC_ALPHA_LINKAGE: + case BFD_RELOC_ALPHA_CODEADDR: #endif return 1; @@ -1262,8 +1281,7 @@ alpha_force_relocation (f) return 0; default: - assert(f->fx_r_type > BFD_RELOC_UNUSED && - f->fx_r_type < BFD_RELOC_UNUSED + alpha_num_operands); + assert((int)f->fx_r_type < 0 && -(int)f->fx_r_type < alpha_num_operands); return 0; } } @@ -1284,10 +1302,37 @@ alpha_fix_adjustable (f) but we can adjust the values contained within it? */ switch (f->fx_r_type) { + case BFD_RELOC_ALPHA_GPDISP_HI16: + case BFD_RELOC_ALPHA_GPDISP_LO16: + 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_LINKAGE: + case BFD_RELOC_ALPHA_CODEADDR: +#endif + return 1; + + case BFD_RELOC_ALPHA_LITUSE: + return 0; + case BFD_RELOC_GPREL32: + case BFD_RELOC_23_PCREL_S2: + case BFD_RELOC_32: + case BFD_RELOC_64: + case BFD_RELOC_ALPHA_HINT: return 1; + default: - return !alpha_force_relocation (f); + assert ((int)f->fx_r_type < 0 + && - (int)f->fx_r_type < alpha_num_operands); + return 1; } /*NOTREACHED*/ } @@ -1302,13 +1347,13 @@ tc_gen_reloc (sec, fixp) { arelent *reloc; - reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent)); + reloc = (arelent *) xmalloc (sizeof (arelent)); reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; 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 (fixp->fx_r_type < BFD_RELOC_UNUSED); + assert ((int)fixp->fx_r_type > 0); reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); if (reloc->howto == NULL) @@ -1337,7 +1382,7 @@ tc_gen_reloc (sec, fixp) { reloc->addend = fixp->fx_offset; #ifdef OBJ_ELF - /* + /* * Ohhh, this is ugly. The problem is that if this is a local global * symbol, the relocation will entirely be performed at link time, not * at assembly time. bfd_perform_reloc doesn't know about this sort @@ -1394,12 +1439,12 @@ tokenize_arguments (str, tok, ntok) char *old_input_line_pointer; int saw_comma = 0, saw_arg = 0; - memset (tok, 0, sizeof(*tok)*ntok); + memset (tok, 0, sizeof (*tok) * ntok); - /* Save and restore input_line_pointer around this function */ + /* Save and restore input_line_pointer around this function */ old_input_line_pointer = input_line_pointer; input_line_pointer = str; - + while (tok < end_tok && *input_line_pointer) { SKIP_WHITESPACE (); @@ -1555,7 +1600,7 @@ find_opcode_match(first_opcode, tok, pntok, pcpumatch) match_failed:; } - while (++opcode-alpha_opcodes < alpha_num_opcodes + while (++opcode-alpha_opcodes < alpha_num_opcodes && !strcmp(opcode->name, first_opcode->name)); if (*pcpumatch) @@ -1631,7 +1676,7 @@ find_macro_match(first_macro, tok, pntok) } ++tokidx; break; - + match_failed: while (*arg != MACRO_EOA) ++arg; @@ -1641,7 +1686,7 @@ find_macro_match(first_macro, tok, pntok) ++arg; } } - while (++macro-alpha_macros < alpha_num_macros + while (++macro-alpha_macros < alpha_num_macros && !strcmp(macro->name, first_macro->name)); return NULL; @@ -1674,9 +1719,9 @@ insert_operand(insn, operand, val, file, line) if (val < min || val > max) { - const char *err = + const char *err = "operand out of range (%s not between %d and %d)"; - char buf[sizeof(val)*3+2]; + char buf[sizeof (val) * 3 + 2]; sprint_value(buf, val); if (file) @@ -1690,9 +1735,9 @@ insert_operand(insn, operand, val, file, line) { const char *errmsg = NULL; - insn = (*operand->insert)(insn, val, &errmsg); + insn = (*operand->insert) (insn, val, &errmsg); if (errmsg) - as_warn(errmsg); + as_warn (errmsg); } else insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift); @@ -1700,7 +1745,7 @@ insert_operand(insn, operand, val, file, line) return insn; } -/* +/* * Turn an opcode description and a set of arguments into * an instruction and a fixup. */ @@ -1716,7 +1761,7 @@ assemble_insn(opcode, tok, ntok, insn) unsigned image; int tokidx = 0; - memset(insn, 0, sizeof(*insn)); + memset (insn, 0, sizeof (*insn)); image = opcode->opcode; for (argidx = opcode->operands; *argidx; ++argidx) @@ -1786,7 +1831,7 @@ assemble_insn(opcode, tok, ntok, insn) insn->insn = image; } -/* +/* * Actually output an instruction with its fixup. */ @@ -1816,7 +1861,7 @@ emit_insn (insn) fixS *fixP; /* Some fixups are only used internally and so have no howto */ - if (fixup->reloc > BFD_RELOC_UNUSED) + if ((int)fixup->reloc < 0) size = 4, pcrel = 0; #ifdef OBJ_ELF /* These relocation types are only used internally. */ @@ -1828,7 +1873,7 @@ emit_insn (insn) #endif else { - reloc_howto_type *reloc_howto + reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, fixup->reloc); assert (reloc_howto); @@ -1844,7 +1889,12 @@ emit_insn (insn) switch (fixup->reloc) { case BFD_RELOC_ALPHA_GPDISP_LO16: +#ifdef OBJ_ECOFF case BFD_RELOC_ALPHA_LITERAL: +#endif +#ifdef OBJ_ELF + case BFD_RELOC_ALPHA_ELF_LITERAL: +#endif case BFD_RELOC_GPREL32: fixP->fx_no_overflow = 1; break; @@ -1936,7 +1986,7 @@ assemble_tokens (opname, tok, ntok, local_macros_on) return; } } - + if (found_something) if (cpumatch) as_bad ("inappropriate arguments for opcode `%s'", opname); @@ -1956,14 +2006,17 @@ static const char * const extXl_op[] = { "extbl", "extwl", "extll", "extql" }; static const char * const extXh_op[] = { NULL, "extwh", "extlh", "extqh" }; static const char * const mskXl_op[] = { "mskbl", "mskwl", "mskll", "mskql" }; static const char * const mskXh_op[] = { NULL, "mskwh", "msklh", "mskqh" }; +static const char * const stX_op[] = { "stb", "stw", "stl", "stq" }; +static const char * const ldX_op[] = { "ldb", "ldw", "ldll", "ldq" }; +static const char * const ldXu_op[] = { "ldbu", "ldwu", NULL, NULL }; /* Implement the ldgp macro. */ -static void +static void emit_ldgp (tok, ntok, unused) const expressionS *tok; int ntok; - void *unused; + const PTR unused; { #ifdef OBJ_AOUT FIXME @@ -2004,7 +2057,7 @@ FIXME emit_insn (&insn); set_tok_preg (newtok[2], tok[0].X_add_number); - + assemble_tokens_to_insn ("lda", newtok, 3, &insn); #ifdef OBJ_ECOFF @@ -2140,7 +2193,7 @@ load_expression (targreg, exp, pbasereg, poffset) as_bad ("macro requires $at register while noat in effect"); if (targreg == AXP_REG_AT) as_bad ("macro requires $at while $at in use"); - + set_tok_reg (newtok[0], AXP_REG_AT); } else @@ -2162,7 +2215,7 @@ load_expression (targreg, exp, pbasereg, poffset) as_bad ("macro requires $at register while noat in effect"); if (targreg == AXP_REG_AT) as_bad ("macro requires $at while $at in use"); - + set_tok_reg (newtok[0], AXP_REG_AT); } else @@ -2184,7 +2237,7 @@ load_expression (targreg, exp, pbasereg, poffset) assemble_tokens_to_insn ("ldq", newtok, 3, &insn); assert (insn.nfixups == 1); - insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL; + insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL; #endif /* OBJ_ELF */ #ifdef OBJ_EVAX offsetT link; @@ -2240,6 +2293,7 @@ load_expression (targreg, exp, pbasereg, poffset) #endif /* OBJ_EVAX */ emit_insn(&insn); + #ifndef OBJ_EVAX emit_lituse = 1; @@ -2252,6 +2306,7 @@ load_expression (targreg, exp, pbasereg, poffset) assemble_tokens ("addq", newtok, 3, 0); } #endif + basereg = targreg; } break; @@ -2283,7 +2338,6 @@ load_expression (targreg, exp, pbasereg, poffset) /* for 64-bit addends, just put it in the literal pool */ #ifdef OBJ_EVAX - /* emit "ldq targreg, lit(basereg)" */ lit = add_to_link_pool (alpha_evax_proc.symbol, section_symbol (absolute_section), addend); @@ -2291,7 +2345,6 @@ load_expression (targreg, exp, pbasereg, poffset) set_tok_const (newtok[1], lit); set_tok_preg (newtok[2], alpha_gp_register); assemble_tokens ("ldq", newtok, 3, 0); - #else if (alpha_lit8_section == NULL) @@ -2299,14 +2352,20 @@ load_expression (targreg, exp, pbasereg, poffset) create_literal_section (".lit8", &alpha_lit8_section, &alpha_lit8_symbol); - S_SET_VALUE (alpha_lit8_symbol, 0x8000); + +#ifdef OBJ_ECOFF + 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"); +#endif } lit = add_to_literal_pool (NULL, addend, alpha_lit8_section, 8) - 0x8000; if (lit >= 0x8000) as_fatal ("overflow in literal (.lit8) table"); - /* emit "ldq litreg, .lit8+lit" */ + /* emit "lda litreg, .lit8+0x8000" */ if (targreg == basereg) { @@ -2319,9 +2378,46 @@ load_expression (targreg, exp, pbasereg, poffset) } else set_tok_reg (newtok[0], targreg); - set_tok_sym (newtok[1], alpha_lit8_symbol, lit); +#ifdef OBJ_ECOFF + set_tok_sym (newtok[1], alpha_lita_symbol, alpha_lit8_literal); +#endif +#ifdef OBJ_ELF + set_tok_sym (newtok[1], alpha_lit8_symbol, 0x8000); +#endif + set_tok_preg (newtok[2], alpha_gp_register); + + assemble_tokens_to_insn ("ldq", newtok, 3, &insn); + + assert (insn.nfixups == 1); +#ifdef OBJ_ECOFF + insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL; +#endif +#ifdef OBJ_ELF + insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL; +#endif + + emit_insn (&insn); + + /* emit "ldq litreg, lit(litreg)" */ + + set_tok_const (newtok[1], lit); + set_tok_preg (newtok[2], newtok[0].X_add_number); + + 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.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; + emit_lituse = 0; - assemble_tokens ("ldq", newtok, 2, 1); /* note this does recurse */ + emit_insn (&insn); /* emit "addq litreg, base, target" */ @@ -2401,7 +2497,7 @@ static void emit_lda (tok, ntok, unused) const expressionS *tok; int ntok; - void *unused; + const PTR unused; { int basereg; @@ -2420,7 +2516,7 @@ static void emit_ldah (tok, ntok, unused) const expressionS *tok; int ntok; - void *unused; + const PTR unused; { expressionS newtok[3]; @@ -2439,7 +2535,7 @@ static void emit_ir_load (tok, ntok, opname) const expressionS *tok; int ntok; - void *opname; + const PTR opname; { int basereg, lituse; expressionS newtok[3]; @@ -2473,8 +2569,8 @@ emit_ir_load (tok, ntok, opname) } emit_insn (&insn); -#if OBJ_EVAX - /* special hack. If the basereg is clobbered for a call +#ifdef OBJ_EVAX + /* special hack. If the basereg is clobbered for a call all lda's before the call don't have a basereg. */ if ((tok[0].X_op == O_register) && (tok[0].X_add_number == alpha_gp_register)) @@ -2491,12 +2587,12 @@ static void emit_loadstore (tok, ntok, opname) const expressionS *tok; int ntok; - void *opname; + const PTR opname; { int basereg, lituse; expressionS newtok[3]; struct alpha_insn insn; - + if (ntok == 2) basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register); else @@ -2539,44 +2635,49 @@ emit_loadstore (tok, ntok, opname) /* Load a half-word or byte as an unsigned value. */ -static void +static void emit_ldXu (tok, ntok, vlgsize) const expressionS *tok; int ntok; - void *vlgsize; + const PTR vlgsize; { - expressionS newtok[3]; + if (alpha_target & AXP_OPCODE_BWX) + emit_ir_load (tok, ntok, ldXu_op[(long)vlgsize]); + else + { + expressionS newtok[3]; - if (alpha_noat_on) - as_bad ("macro requires $at register while noat in effect"); - - /* emit "lda $at, exp" */ + if (alpha_noat_on) + as_bad ("macro requires $at register while noat in effect"); - memcpy (newtok, tok, sizeof(expressionS)*ntok); - newtok[0].X_add_number = AXP_REG_AT; - assemble_tokens ("lda", newtok, ntok, 1); + /* emit "lda $at, exp" */ - /* emit "ldq_u targ, 0($at)" */ + memcpy (newtok, tok, sizeof (expressionS) * ntok); + newtok[0].X_add_number = AXP_REG_AT; + assemble_tokens ("lda", newtok, ntok, 1); - 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); + /* emit "ldq_u targ, 0($at)" */ - /* emit "extXl targ, $at, targ" */ + 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_reg (newtok[1], AXP_REG_AT); - newtok[2] = newtok[0]; - assemble_tokens (extXl_op[(long)vlgsize], newtok, 3, 1); + /* emit "extXl targ, $at, targ" */ + + set_tok_reg (newtok[1], AXP_REG_AT); + newtok[2] = newtok[0]; + assemble_tokens (extXl_op[(long)vlgsize], newtok, 3, 1); + } } /* Load a half-word or byte as a signed value. */ -static void +static void emit_ldX (tok, ntok, vlgsize) const expressionS *tok; int ntok; - void *vlgsize; + const PTR vlgsize; { emit_ldXu (tok, ntok, vlgsize); assemble_tokens (sextX_op[(long)vlgsize], tok, 1, 1); @@ -2589,7 +2690,7 @@ static void emit_uldXu (tok, ntok, vlgsize) const expressionS *tok; int ntok; - void *vlgsize; + const PTR vlgsize; { long lgsize = (long)vlgsize; expressionS newtok[3]; @@ -2599,7 +2700,7 @@ emit_uldXu (tok, ntok, vlgsize) /* emit "lda $at, exp" */ - memcpy (newtok, tok, sizeof(expressionS)*ntok); + memcpy (newtok, tok, sizeof (expressionS) * ntok); newtok[0].X_add_number = AXP_REG_AT; assemble_tokens ("lda", newtok, ntok, 1); @@ -2636,7 +2737,7 @@ emit_uldXu (tok, ntok, vlgsize) newtok[2] = tok[0]; assemble_tokens ("or", newtok, 3, 1); } - + /* Load an integral value from an unaligned address as a signed value. Note that quads should get funneled to the unsigned load since we don't have to do the sign extension. */ @@ -2645,7 +2746,7 @@ static void emit_uldX (tok, ntok, vlgsize) const expressionS *tok; int ntok; - void *vlgsize; + const PTR vlgsize; { emit_uldXu (tok, ntok, vlgsize); assemble_tokens (sextX_op[(long)vlgsize], tok, 1, 1); @@ -2657,7 +2758,7 @@ static void emit_ldil (tok, ntok, unused) const expressionS *tok; int ntok; - void *unused; + const PTR unused; { expressionS newtok[2]; @@ -2672,50 +2773,57 @@ emit_ldil (tok, ntok, unused) static void emit_stX (tok, ntok, vlgsize) const expressionS *tok; - void *vlgsize; + int ntok; + const PTR vlgsize; { int lgsize = (int)(long)vlgsize; - expressionS newtok[3]; - if (alpha_noat_on) - as_bad("macro requires $at register while noat in effect"); + if (alpha_target & AXP_OPCODE_BWX) + emit_loadstore (tok, ntok, stX_op[lgsize]); + else + { + expressionS newtok[3]; - /* emit "lda $at, exp" */ + if (alpha_noat_on) + as_bad("macro requires $at register while noat in effect"); - memcpy (newtok, tok, sizeof(expressionS)*ntok); - newtok[0].X_add_number = AXP_REG_AT; - assemble_tokens ("lda", newtok, ntok, 1); + /* emit "lda $at, exp" */ - /* emit "ldq_u $t9, 0($at)" */ + memcpy (newtok, tok, sizeof (expressionS) * ntok); + newtok[0].X_add_number = AXP_REG_AT; + assemble_tokens ("lda", newtok, ntok, 1); - set_tok_reg (newtok[0], AXP_REG_T9); - set_tok_const (newtok[1], 0); - set_tok_preg (newtok[2], AXP_REG_AT); - assemble_tokens ("ldq_u", newtok, 3, 1); + /* emit "ldq_u $t9, 0($at)" */ - /* emit "insXl src, $at, $t10" */ + set_tok_reg (newtok[0], AXP_REG_T9); + set_tok_const (newtok[1], 0); + set_tok_preg (newtok[2], AXP_REG_AT); + assemble_tokens ("ldq_u", newtok, 3, 1); - newtok[0] = tok[0]; - set_tok_reg (newtok[1], AXP_REG_AT); - set_tok_reg (newtok[2], AXP_REG_T10); - assemble_tokens (insXl_op[lgsize], newtok, 3, 1); + /* emit "insXl src, $at, $t10" */ - /* emit "mskXl $t9, $at, $t9" */ + newtok[0] = tok[0]; + set_tok_reg (newtok[1], AXP_REG_AT); + set_tok_reg (newtok[2], AXP_REG_T10); + assemble_tokens (insXl_op[lgsize], newtok, 3, 1); - set_tok_reg (newtok[0], AXP_REG_T9); - newtok[2] = newtok[0]; - assemble_tokens (mskXl_op[lgsize], newtok, 3, 1); + /* emit "mskXl $t9, $at, $t9" */ - /* emit "or $t9, $t10, $t9" */ + set_tok_reg (newtok[0], AXP_REG_T9); + newtok[2] = newtok[0]; + assemble_tokens (mskXl_op[lgsize], newtok, 3, 1); - set_tok_reg (newtok[1], AXP_REG_T10); - assemble_tokens ("or", newtok, 3, 1); + /* emit "or $t9, $t10, $t9" */ - /* emit "stq_u $t9, 0($at) */ + set_tok_reg (newtok[1], AXP_REG_T10); + assemble_tokens ("or", newtok, 3, 1); - set_tok_const (newtok[1], 0); - set_tok_preg (newtok[2], AXP_REG_AT); - assemble_tokens ("stq_u", newtok, 3, 1); + /* emit "stq_u $t9, 0($at) */ + + set_tok_const (newtok[1], 0); + set_tok_preg (newtok[2], AXP_REG_AT); + assemble_tokens ("stq_u", newtok, 3, 1); + } } /* Store an integer to an unaligned address. */ @@ -2724,14 +2832,14 @@ static void emit_ustX (tok, ntok, vlgsize) const expressionS *tok; int ntok; - void *vlgsize; + const PTR vlgsize; { int lgsize = (int)(long)vlgsize; expressionS newtok[3]; /* emit "lda $at, exp" */ - memcpy (newtok, tok, sizeof(expressionS)*ntok); + memcpy (newtok, tok, sizeof (expressionS) * ntok); newtok[0].X_add_number = AXP_REG_AT; assemble_tokens ("lda", newtok, ntok, 1); @@ -2807,22 +2915,29 @@ static void emit_sextX (tok, ntok, vlgsize) const expressionS *tok; int ntok; - void *vlgsize; + const PTR vlgsize; { - int bitshift = 64 - 8*(1 << (long)vlgsize); - expressionS newtok[3]; + long lgsize = (long)vlgsize; - /* emit "sll src,bits,dst" */ + if (alpha_target & AXP_OPCODE_BWX) + assemble_tokens (sextX_op[lgsize], tok, ntok, 0); + else + { + int bitshift = 64 - 8 * (1 << lgsize); + expressionS newtok[3]; - newtok[0] = tok[0]; - set_tok_const (newtok[1], bitshift); - newtok[2] = tok[ntok - 1]; - assemble_tokens ("sll", newtok, 3, 1); + /* emit "sll src,bits,dst" */ + + newtok[0] = tok[0]; + set_tok_const (newtok[1], bitshift); + newtok[2] = tok[ntok - 1]; + assemble_tokens ("sll", newtok, 3, 1); - /* emit "sra dst,bits,dst" */ + /* emit "sra dst,bits,dst" */ - newtok[0] = newtok[2]; - assemble_tokens ("sra", newtok, 3, 1); + newtok[0] = newtok[2]; + assemble_tokens ("sra", newtok, 3, 1); + } } /* Implement the division and modulus macros. */ @@ -2832,11 +2947,11 @@ emit_sextX (tok, ntok, vlgsize) /* Make register usage like in normal procedure call. Don't clobber PV and RA. */ -static void +static void emit_division (tok, ntok, symname) const expressionS *tok; int ntok; - void *symname; + const PTR symname; { /* DIVISION and MODULUS. Yech. * @@ -2850,7 +2965,7 @@ emit_division (tok, ntok, symname) * mov R0,result * * with appropriate optimizations if R0,R16,R17 are the registers - * specified by the compiler. + * specified by the compiler. */ int xr, yr, rr; @@ -2859,7 +2974,7 @@ emit_division (tok, ntok, symname) xr = regno (tok[0].X_add_number); yr = regno (tok[1].X_add_number); - + if (ntok < 3) rr = xr; else @@ -2932,11 +3047,11 @@ emit_division (tok, ntok, symname) #else /* !OBJ_EVAX */ -static void +static void emit_division (tok, ntok, symname) const expressionS *tok; int ntok; - void *symname; + const PTR symname; { /* DIVISION and MODULUS. Yech. * Convert @@ -2949,7 +3064,7 @@ emit_division (tok, ntok, symname) * mov t12,result * * with appropriate optimizations if t10,t11,t12 are the registers - * specified by the compiler. + * specified by the compiler. */ int xr, yr, rr; @@ -2958,7 +3073,7 @@ emit_division (tok, ntok, symname) xr = regno (tok[0].X_add_number); yr = regno (tok[1].X_add_number); - + if (ntok < 3) rr = xr; else @@ -3045,7 +3160,7 @@ static void emit_jsrjmp (tok, ntok, vopname) const expressionS *tok; int ntok; - void *vopname; + const PTR vopname; { const char *opname = (const char *) vopname; struct alpha_insn insn; @@ -3102,7 +3217,7 @@ emit_jsrjmp (tok, ntok, vopname) emit_insn (&insn); -#if OBJ_EVAX +#ifdef OBJ_EVAX alpha_basereg_clobbered = 0; /* reload PV from 0(FP) if it is our current base register. */ @@ -3123,7 +3238,7 @@ static void emit_retjcr (tok, ntok, vopname) const expressionS *tok; int ntok; - void *vopname; + const PTR vopname; { const char *opname = (const char *)vopname; expressionS newtok[3]; @@ -3166,7 +3281,7 @@ s_alpha_text (i) alpha_insn_label = NULL; alpha_auto_align_on = 1; alpha_current_align = 0; -} +} /* Handle the .data pseudo-op. This is like the usual one, but it clears alpha_insn_label and restores auto alignment. */ @@ -3179,9 +3294,9 @@ s_alpha_data (i) alpha_insn_label = NULL; alpha_auto_align_on = 1; alpha_current_align = 0; -} +} -#ifndef OBJ_ELF +#ifdef OBJ_ECOFF /* Handle the OSF/1 .comm pseudo quirks. */ @@ -3228,27 +3343,6 @@ s_alpha_comm (ignore) return; } -#if OBJ_EVAX - { - /* Fill common area with zeros. */ - char *pfrag; - segT current_seg = now_seg; - subsegT current_subseg = now_subseg; - - subseg_set (bss_section, 1); - frag_align (3, 0); - - symbolP->sy_frag = frag_now; - pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP, - temp, (char *)0); - - *pfrag = 0; - S_SET_SEGMENT (symbolP, bss_section); - - subseg_set (current_seg, current_subseg); - } -#endif - if (S_GET_VALUE (symbolP)) { if (S_GET_VALUE (symbolP) != (valueT) temp) @@ -3263,16 +3357,14 @@ s_alpha_comm (ignore) S_SET_EXTERNAL (symbolP); } -#ifndef OBJ_EVAX know (symbolP->sy_frag == &zero_address_frag); -#endif demand_empty_rest_of_line (); } #endif /* ! OBJ_ELF */ -#if defined (OBJ_ECOFF) || defined (OBJ_EVAX) +#ifdef OBJ_ECOFF /* Handle the .rdata pseudo-op. This is like the usual one, but it clears alpha_insn_label and restores auto alignment. */ @@ -3318,7 +3410,7 @@ s_alpha_sdata (ignore) /* Handle the .section pseudo-op. This is like the usual one, but it clears alpha_insn_label and restores auto alignment. */ -static void +static void s_alpha_section (ignore) int ignore; { @@ -3329,17 +3421,29 @@ s_alpha_section (ignore) alpha_current_align = 0; } -#endif +#endif #ifdef OBJ_EVAX + +/* Handle the section specific pseudo-op. */ + static void -s_alpha_link (ignore) - int ignore; +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" }; + if ((secid <= 0) || (secid > EVAX_SECTION_COUNT)) + { + as_fatal ("Unknown section directive"); + demand_empty_rest_of_line (); + return; + } temp = get_absolute_expression (); - subseg_new (".link", 0); + subseg_new (section_name[secid], 0); demand_empty_rest_of_line (); alpha_insn_label = NULL; alpha_auto_align_on = 1; @@ -3514,7 +3618,7 @@ s_alpha_pdesc (ignore) md_flush_pending_output (); #endif - frag_align (3, 0); + frag_align (3, 0, 0); p = frag_more (16); fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0); fixp->fx_done = 1; @@ -3585,6 +3689,47 @@ s_alpha_pdesc (ignore) } +/* Support for crash debug on vms. */ + +static void +s_alpha_name (ignore) + int ignore; +{ + register char *p; + expressionS exp; + segment_info_type *seginfo = seg_info (alpha_link_section); + + if (now_seg != alpha_link_section) + { + as_bad (".name directive not in link (.link) section"); + demand_empty_rest_of_line (); + return; + } + + expression (&exp); + if (exp.X_op != O_symbol) + { + as_warn (".name directive has no symbol"); + demand_empty_rest_of_line (); + return; + } + + demand_empty_rest_of_line (); + +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif + + frag_align (3, 0, 0); + 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); + + return; +} + + static void s_alpha_linkage (ignore) int ignore; @@ -3615,6 +3760,35 @@ s_alpha_linkage (ignore) static void +s_alpha_code_address (ignore) + int ignore; +{ + expressionS exp; + char *p; + +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif + + expression (&exp); + if (exp.X_op != O_symbol) + { + as_fatal ("No symbol after .code_address"); + } + else + { + p = frag_more (8); + memset (p, 0, 8); + fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &exp, 0,\ + BFD_RELOC_ALPHA_CODEADDR); + } + demand_empty_rest_of_line (); + + return; +} + + +static void s_alpha_fp_save (ignore) int ignore; { @@ -3689,17 +3863,14 @@ static void s_alpha_file (ignore) int ignore; { - symbolS* s; + symbolS *s; int length; static char case_hack[32]; extern char *demand_copy_string PARAMS ((int *lenP)); - sprintf (case_hack, "<CASE:%01d%01d%01d%01d>", - alpha_flag_hash_long_names, - alpha_flag_show_after_trunc, - alpha_flag_no_hash_mixed_case, - alpha_vms_name_mapping); + sprintf (case_hack, "<CASE:%01d%01d>", + alpha_flag_hash_long_names, alpha_flag_show_after_trunc); s = symbol_find_or_make (case_hack); s->bsym->flags |= BSF_FILE; @@ -4004,19 +4175,48 @@ alpha_cons_align (size) alpha_insn_label = NULL; } + +#ifdef DEBUG1 +/* print token expression with alpha specific extension. */ + +static void +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; + } + return; +} +#endif + /* The target specific pseudo-ops which we support. */ const pseudo_typeS md_pseudo_table[] = { {"common", s_comm, 0}, /* is this used? */ -#ifndef OBJ_ELF +#ifdef OBJ_ECOFF {"comm", s_alpha_comm, 0}, /* osf1 compiler does this */ + {"rdata", s_alpha_rdata, 0}, #endif {"text", s_alpha_text, 0}, {"data", s_alpha_data, 0}, -#if defined (OBJ_ECOFF) || defined (OBJ_EVAX) - {"rdata", s_alpha_rdata, 0}, -#endif #ifdef OBJ_ECOFF {"sdata", s_alpha_sdata, 0}, #endif @@ -4028,15 +4228,22 @@ const pseudo_typeS md_pseudo_table[] = #endif #ifdef OBJ_EVAX { "pdesc", s_alpha_pdesc, 0}, + { "name", s_alpha_name, 0}, { "linkage", s_alpha_linkage, 0}, + { "code_address", s_alpha_code_address, 0}, { "ent", s_alpha_ent, 0}, { "frame", s_alpha_frame, 0}, { "fp_save", s_alpha_fp_save, 0}, { "mask", s_alpha_mask, 0}, { "fmask", s_alpha_fmask, 0}, - { "link", s_alpha_link, 0}, { "end", s_alpha_end, 0}, { "file", s_alpha_file, 0}, + { "rdata", s_alpha_section, 1}, + { "comm", s_alpha_section, 2}, + { "link", s_alpha_section, 3}, + { "ctors", s_alpha_section, 4}, + { "dtors", s_alpha_section, 5}, + { "lcomm", s_alpha_section, 6}, #endif {"gprel32", s_alpha_gprel32, 0}, {"t_floating", s_alpha_float_cons, 'd'}, @@ -4173,14 +4380,14 @@ alpha_align (n, pfill, label) no-op instructions. This will zero-fill, then nop-fill with proper alignment. */ if (alpha_current_align < 2) - frag_align (2, 0); - frag_align_pattern (n, nop, sizeof nop); + frag_align (2, 0, 0); + frag_align_pattern (n, nop, sizeof nop, 0); } else - frag_align (n, 0); + frag_align (n, 0, 0); } else - frag_align (n, *pfill); + frag_align (n, *pfill, 0); alpha_current_align = n; |