📄 tc-alpha.c
字号:
/* Round up a section's size to the appropriate boundary. */valueTmd_section_align (seg, size) segT seg; valueT size;{ 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 returned, or NULL on OK. *//* Equal to MAX_PRECISION in atof-ieee.c */#define MAX_LITTLENUMS 6extern char *vax_md_atof PARAMS ((int, char *, int *));char *md_atof (type, litP, sizeP) char type; char *litP; int *sizeP;{ int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE *wordP; char *t; switch (type) { /* VAX floats */ case 'G': /* VAX md_atof doesn't like "G" for some reason. */ type = 'g'; case 'F': case 'D': return vax_md_atof (type, litP, sizeP); /* IEEE floats */ case 'f': prec = 2; break; case 'd': prec = 4; break; case 'x': case 'X': prec = 6; break; case 'p': case 'P': prec = 6; break; default: *sizeP = 0; return _("Bad call to MD_ATOF()"); } t = atof_ieee (input_line_pointer, type, words); if (t) input_line_pointer = t; *sizeP = prec * sizeof (LITTLENUM_TYPE); for (wordP = words + prec - 1; prec--;) { md_number_to_chars (litP, (long) (*wordP--), sizeof (LITTLENUM_TYPE)); litP += sizeof (LITTLENUM_TYPE); } return 0;}/* Take care of the target-specific command-line options. */intmd_parse_option (c, arg) int c; char *arg;{ switch (c) { case 'F': alpha_nofloats_on = 1; break; case OPTION_32ADDR: alpha_addr32_on = 1; break; case 'g': 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) { alpha_target_name = p->name, alpha_target = p->flags; goto found; } as_warn (_("Unknown CPU identifier `%s'"), arg); found:; } break;#ifdef OBJ_EVAX case '+': /* For g++. Hash any name > 63 chars long. */ alpha_flag_hash_long_names = 1; break; case 'H': /* Show new symbol after hash truncation */ alpha_flag_show_after_trunc = 1; break; case 'h': /* for gnu-c/vax compatibility. */ 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; } return 1;}/* Print a description of the command-line options that we accept. */voidmd_show_usage (stream) FILE *stream;{ fputs (_("\Alpha options:\n\-32addr treat addresses as 32-bit values\n\-F lack floating point instructions support\n\-mev4 | -mev45 | -mev5 | -mev56 | -mpca56 | -mev6 | -mall\n\ specify variant of Alpha architecture\n\-m21064 | -m21066 | -m21164 | -m21164a | -m21164pc | -m21264\n\ these variants include PALcode opcodes\n"), stream);#ifdef OBJ_EVAX fputs (_("\VMS options:\n\-+ hash encode (don't truncate) names longer than 64 characters\n\-H show new symbol after hash truncation\n"), stream);#endif}/* Decide from what point a pc-relative relocation is relative to, relative to the pc-relative fixup. Er, relatively speaking. */longmd_pcrel_from (fixP) fixS *fixP;{ valueT addr = fixP->fx_where + fixP->fx_frag->fr_address; switch (fixP->fx_r_type) { case BFD_RELOC_ALPHA_GPDISP: case BFD_RELOC_ALPHA_GPDISP_HI16: case BFD_RELOC_ALPHA_GPDISP_LO16: return addr; default: return fixP->fx_size + addr; }}/* Attempt to simplify or even eliminate a fixup. The return value is ignored; perhaps it was once meaningful, but now it is historical. To indicate that a fixup has been eliminated, set fixP->fx_done. For ELF, here it is that we transform the GPDISP_HI16 reloc we used internally into the GPDISP reloc used externally. We had to do this so that we'd have the GPDISP_LO16 reloc as a tag to compute the distance to the "lda" instruction for setting the addend to GPDISP. */intmd_apply_fix (fixP, valueP) fixS *fixP; valueT *valueP;{ char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where; valueT value = *valueP; unsigned image, size; switch (fixP->fx_r_type) { /* The GPDISP relocations are processed internally with a symbol referring to the current function; we need to drop in a value which, when added to the address of the start of the function, gives the desired GP. */ 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); value = (value - sign_extend_16 (value)) >> 16; }#ifdef OBJ_ELF fixP->fx_r_type = BFD_RELOC_ALPHA_GPDISP;#endif goto do_reloc_gp; case BFD_RELOC_ALPHA_GPDISP_LO16: value = sign_extend_16 (value); fixP->fx_offset = 0;#ifdef OBJ_ELF fixP->fx_done = 1;#endif do_reloc_gp: fixP->fx_addsy = section_symbol (now_seg); md_number_to_chars (fixpos, value, 2); break; case BFD_RELOC_16: if (fixP->fx_pcrel) fixP->fx_r_type = BFD_RELOC_16_PCREL; size = 2; goto do_reloc_xx; case BFD_RELOC_32: if (fixP->fx_pcrel) fixP->fx_r_type = BFD_RELOC_32_PCREL; size = 4; goto do_reloc_xx; case BFD_RELOC_64: if (fixP->fx_pcrel) fixP->fx_r_type = BFD_RELOC_64_PCREL; size = 8; do_reloc_xx: if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) { md_number_to_chars (fixpos, value, size); goto done; } return 1;#ifdef OBJ_ECOFF case BFD_RELOC_GPREL32: assert (fixP->fx_subsy == alpha_gp_symbol); fixP->fx_subsy = 0; /* FIXME: inherited this obliviousness of `value' -- why? */ md_number_to_chars (fixpos, -alpha_gp_value, 4); break;#endif#ifdef OBJ_ELF case BFD_RELOC_GPREL32: return 1;#endif case BFD_RELOC_23_PCREL_S2: if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) { image = bfd_getl32 (fixpos); image = (image & ~0x1FFFFF) | ((value >> 2) & 0x1FFFFF); goto write_done; } return 1; case BFD_RELOC_ALPHA_HINT: if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) { image = bfd_getl32 (fixpos); image = (image & ~0x3FFF) | ((value >> 2) & 0x3FFF); goto write_done; } return 1;#ifdef OBJ_ECOFF case BFD_RELOC_ALPHA_LITERAL: md_number_to_chars (fixpos, value, 2); return 1; case BFD_RELOC_ALPHA_LITUSE: return 1;#endif#ifdef OBJ_ELF case BFD_RELOC_ALPHA_ELF_LITERAL: case BFD_RELOC_ALPHA_LITUSE: return 1;#endif#ifdef OBJ_EVAX case BFD_RELOC_ALPHA_LINKAGE: case BFD_RELOC_ALPHA_CODEADDR: return 1;#endif#ifdef RELOC_OP_P case BFD_RELOC_ALPHA_USER_LITERAL: case BFD_RELOC_ALPHA_USER_LITUSE_BASE: case BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF: case BFD_RELOC_ALPHA_USER_LITUSE_JSR: return 1; case BFD_RELOC_ALPHA_USER_GPDISP: case BFD_RELOC_ALPHA_USER_GPRELHIGH: case BFD_RELOC_ALPHA_USER_GPRELLOW: abort ();#endif case BFD_RELOC_VTABLE_INHERIT: case BFD_RELOC_VTABLE_ENTRY: return 1; default: { const struct alpha_operand *operand; 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 < (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 && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section) as_bad_where (fixP->fx_file, fixP->fx_line, _("non-absolute expression in constant field")); image = bfd_getl32 (fixpos); image = insert_operand (image, operand, (offsetT) value, fixP->fx_file, fixP->fx_line); } goto write_done; } if (fixP->fx_addsy != 0 || fixP->fx_pcrel != 0) return 1; else { 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);done: fixP->fx_done = 1; return 0;}/* * Look for a register name in the given symbol. */symbolS *md_undefined_symbol (name) char *name;{ if (*name == '$') { int is_float = 0, num; switch (*++name) { case 'f': if (name[1] == 'p' && name[2] == '\0') return alpha_register_table[AXP_REG_FP]; is_float = 32; /* FALLTHRU */ case 'r': if (!isdigit (*++name)) break; /* FALLTHRU */ case '0': case '1': case '2': case '3': case '4': 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') { num = (name[0] - '0') * 10 + name[1] - '0'; if (num >= 32) break; } else break; 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\"")); return alpha_register_table[AXP_REG_AT]; } break; case 'g': if (name[1] == 'p' && name[2] == '\0') return alpha_register_table[alpha_gp_register]; break; case 's': if (name[1] == 'p' && name[2] == '\0') return alpha_register_table[AXP_REG_SP]; break; } } return NULL;}#ifdef OBJ_ECOFF/* @@@ Magic ECOFF bits. */voidalpha_frob_ecoff_data (){ select_gp_value (); /* $zero and $f31 are read-only */ alpha_gprmask &= ~1; alpha_fprmask &= ~1;}#endif/* Hook to remember a recently defined label so that the auto-align code can adjust the symbol after we know what alignment will be required. */voidalpha_define_label (sym) symbolS *sym;{ alpha_insn_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. */intalpha_force_relocation (f) fixS *f;{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -