📄 tc-alpha.c
字号:
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_GPREL32:#ifdef OBJ_EVAX case BFD_RELOC_ALPHA_LINKAGE: case BFD_RELOC_ALPHA_CODEADDR:#endif#ifdef RELOC_OP_P case BFD_RELOC_ALPHA_USER_LITERAL: case BFD_RELOC_ALPHA_USER_LITUSE_BASE: case BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF: case BFD_RELOC_ALPHA_USER_LITUSE_JSR: case BFD_RELOC_ALPHA_USER_GPDISP: case BFD_RELOC_ALPHA_USER_GPRELHIGH: case BFD_RELOC_ALPHA_USER_GPRELLOW:#endif case BFD_RELOC_VTABLE_INHERIT: case BFD_RELOC_VTABLE_ENTRY: return 1; case BFD_RELOC_23_PCREL_S2: case BFD_RELOC_32: case BFD_RELOC_64: case BFD_RELOC_ALPHA_HINT: return 0; default: assert ((int) f->fx_r_type < 0 && -(int) f->fx_r_type < (int) alpha_num_operands); return 0; }}/* Return true if we can partially resolve a relocation now. */intalpha_fix_adjustable (f) fixS *f;{#ifdef OBJ_ELF /* Prevent all adjustments to global symbols */ if (S_IS_EXTERN (f->fx_addsy) || S_IS_WEAK (f->fx_addsy)) return 0;#endif /* Are there any relocation types for which we must generate a reloc but we can adjust the values contained within it? */ switch (f->fx_r_type) { case BFD_RELOC_ALPHA_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 RELOC_OP_P case BFD_RELOC_ALPHA_USER_LITERAL:#endif#ifdef OBJ_EVAX case BFD_RELOC_ALPHA_LINKAGE: case BFD_RELOC_ALPHA_CODEADDR:#endif return 1; case BFD_RELOC_ALPHA_LITUSE:#ifdef RELOC_OP_P case BFD_RELOC_ALPHA_USER_LITUSE_BASE: case BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF: case BFD_RELOC_ALPHA_USER_LITUSE_JSR: case BFD_RELOC_ALPHA_USER_GPDISP: case BFD_RELOC_ALPHA_USER_GPRELHIGH: case BFD_RELOC_ALPHA_USER_GPRELLOW:#endif case BFD_RELOC_VTABLE_ENTRY: case BFD_RELOC_VTABLE_INHERIT: return 0; case BFD_RELOC_GPREL32: case BFD_RELOC_23_PCREL_S2: case BFD_RELOC_32: case BFD_RELOC_64: case BFD_RELOC_ALPHA_HINT: return 1; default: assert ((int) f->fx_r_type < 0 && - (int) f->fx_r_type < (int) alpha_num_operands); return 1; } /*NOTREACHED*/}/* Generate the BFD reloc to be stuck in the object file from the fixup used internally in the assembler. */arelent *tc_gen_reloc (sec, fixp) asection *sec ATTRIBUTE_UNUSED; fixS *fixp;{ arelent *reloc; reloc = (arelent *) xmalloc (sizeof (arelent)); 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); 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"), 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"), bfd_get_reloc_code_name (fixp->fx_r_type)); } assert (!fixp->fx_pcrel == !reloc->howto->pc_relative);#ifdef OBJ_ECOFF if (fixp->fx_r_type == BFD_RELOC_ALPHA_LITERAL) { /* fake out bfd_perform_relocation. sigh */ reloc->addend = -alpha_gp_value; } else#endif { reloc->addend = fixp->fx_offset;#ifdef OBJ_ELF /* * Ohhh, this is ugly. The problem is that if this is a local global * symbol, the relocation will entirely be performed at link time, not * at assembly time. bfd_perform_reloc doesn't know about this sort * of thing, and as a result we need to fake it out here. */ if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)) && !S_IS_COMMON (fixp->fx_addsy)) reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value;#endif } return reloc;}/* Parse a register name off of the input_line and return a register number. Gets md_undefined_symbol above to do the register name matching for us. Only called as a part of processing the ECOFF .frame directive. */inttc_get_register (frame) int frame ATTRIBUTE_UNUSED;{ int framereg = AXP_REG_SP; SKIP_WHITESPACE (); if (*input_line_pointer == '$') { char *s = input_line_pointer; char c = get_symbol_end (); symbolS *sym = md_undefined_symbol (s); *strchr (s, '\0') = c; if (sym && (framereg = S_GET_VALUE (sym)) <= 31) goto found; } as_warn (_("frame reg expected, using $%d."), framereg);found: note_gpreg (framereg); return framereg;}/* This is called before the symbol table is processed. In order to work with gcc when using mips-tfile, we must keep all local labels. However, in other cases, we want to discard them. If we were called with -g, but we didn't see any debugging information, it may mean that gcc is smuggling debugging information through to mips-tfile, in which case we must generate all local labels. */#ifdef OBJ_ECOFFvoidalpha_frob_file_before_adjust (){ if (alpha_debug != 0 && ! ecoff_debugging_seen) flag_keep_locals = 1;}#endif /* OBJ_ECOFF */#ifdef RELOC_OP_P/* Before the relocations are written, reorder them, so that user supplied !lituse relocations follow the appropriate !literal relocations. Also convert the gas-internal relocations to the appropriate linker relocations. */voidalpha_adjust_symtab (){ if (alpha_literal_hash) {#ifdef DEBUG2_ALPHA fprintf (stderr, "alpha_adjust_symtab called\n");#endif /* Go over each section, reordering the relocations so that all of the explicit LITUSE's are adjacent to the explicit LITERAL's. */ bfd_map_over_sections (stdoutput, alpha_adjust_symtab_relocs, (char *) 0); }}/* Inner function to move LITUSE's next to the LITERAL. */static voidalpha_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 *lituse; int n_lituses = 0;#ifdef DEBUG2_ALPHA int n = 0; int n_literals = 0; int n_dup_literals = 0;#endif /* 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's. */ prevP = &(seginfo->fix_root); for (fixp = seginfo->fix_root; fixp; fixp = next) { next = fixp->fx_next; fixp->fx_next = (fixS *) 0;#ifdef DEBUG2_ALPHA n++;#endif switch (fixp->fx_r_type) { default: *prevP = fixp; prevP = &(fixp->fx_next);#ifdef DEBUG2_ALPHA fprintf (stderr, "alpha_adjust_symtab_relocs: 0x%lx, other relocation %s\n", (long) fixp, bfd_get_reloc_code_name (fixp->fx_r_type));#endif break; case BFD_RELOC_ALPHA_USER_LITERAL: *prevP = fixp; prevP = &(fixp->fx_next); /* prevent assembler from trying to adjust the offset */#ifdef DEBUG2_ALPHA n_literals++; if (fixp->tc_fix_data.info->n_literals != 1) n_dup_literals++; fprintf (stderr, "alpha_adjust_symtab_relocs: 0x%lx, !literal!%.6d, # literals = %2d\n", (long) fixp, fixp->tc_fix_data.info->sequence, fixp->tc_fix_data.info->n_literals);#endif break; /* do not link in lituse's */ case BFD_RELOC_ALPHA_USER_LITUSE_BASE: case BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF: case BFD_RELOC_ALPHA_USER_LITUSE_JSR: n_lituses++; if (fixp->tc_fix_data.info->n_literals == 0) as_bad_where (fixp->fx_file, fixp->fx_line, _("No !literal!%d was found"), fixp->tc_fix_data.info->sequence);#ifdef DEBUG2_ALPHA fprintf (stderr, "alpha_adjust_symtab_relocs: 0x%lx, !lituse !%.6d, # lituses = %2d, next_lituse = 0x%lx\n", (long) fixp, fixp->tc_fix_data.info->sequence, fixp->tc_fix_data.info->n_lituses, (long) fixp->tc_fix_data.next_lituse);#endif break; } } /* If there were any lituses, go and add them to the chain, unless there is more than one !literal for a given sequence number. They are linked through the next_lituse field in reverse order, so as we go through the next_lituse chain, we effectively reverse the chain once again. If there was more than one !literal, we fall back to loading up the address w/o optimization. Also, if the !literals/!lituses are spread in different segments (happens in the Linux kernel semaphores), suppress the optimization. */ if (n_lituses) { for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next) { switch (fixp->fx_r_type) { default: break; case BFD_RELOC_ALPHA_USER_LITERAL:#ifdef OBJ_ELF fixp->fx_r_type = BFD_RELOC_ALPHA_ELF_LITERAL;#else fixp->fx_r_type = BFD_RELOC_ALPHA_LITERAL; /* XXX check this */#endif if (fixp->tc_fix_data.info->n_literals == 1 && ! fixp->tc_fix_data.info->multi_section_p) { for (lituse = fixp->tc_fix_data.info->lituse; lituse != (fixS *) 0; lituse = lituse->tc_fix_data.next_lituse) { lituse->fx_next = fixp->fx_next; fixp->fx_next = lituse; } } break; case BFD_RELOC_ALPHA_USER_LITUSE_BASE: case BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF: case BFD_RELOC_ALPHA_USER_LITUSE_JSR: fixp->fx_r_type = BFD_RELOC_ALPHA_LITUSE; break; } } }#ifdef DEBUG2_ALPHA fprintf (stderr, "alpha_adjust_symtab_relocs: %s, %d literal%s, %d duplicate literal%s, %d lituse%s\n\n", sec->name, n_literals, (n_literals == 1) ? "" : "s", n_dup_literals, (n_dup_literals == 1) ? "" : "s", n_lituses, (n_lituses == 1) ? "" : "s");#endif}#endif /* RELOC_OP_P */#ifdef DEBUG_ALPHAstatic voiddebug_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_md10: name = "O_md10"; 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 inttokenize_arguments (str, tok, ntok) char *str; expressionS tok[]; int ntok;{ expressionS *end_tok = tok + ntok; char *old_input_line_pointer; int saw_comma = 0, saw_arg = 0;#ifdef DEBUG_ALPHA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -