From e371935fea357fda4aff68fadadf3f7ecbb9672a Mon Sep 17 00:00:00 2001 From: Stephane Carrez Date: Tue, 13 Aug 2002 22:20:50 +0000 Subject: [PATCH] * config/tc-m68hc11.h (MD_PCREL_FROM_SECTION): Remove. (TC_HANDLES_FX_DONE): Define to let md_apply_fix3 set fx_done flag according to the reloc. (tc_fix_adjustable, tc_m68hc11_fix_adjustable): Define. (TC_FORCE_RELOCATION): Define. (tc_m68hc11_force_relocation): Declare. * config/tc-m68hc11.c (md_pseudo_table): Add relax command. (s_m68hc11_relax): New function for relax group. (build_insn, build_jump_insn): Emit a M68HC11_RL_JUMP reloc at beginning of jump instruction. (md_pcrel_from): Rename from md_pcrel_from_section and fix address computation. (tc-gen_reloc): Update. (md_estimate_size_before_relax): Create the BFD_RELOC_16_PCREL as PC-relative fixup. (tc_m68hc11_force_relocation): New function, handle new relocs. (tc_m68hc11_fix_adjustable): New to make sure there are enough reloc for the linker relax pass. (md_apply_fix3): Handle M68HC11_RL_JUMP, M68HC11_RL_GROUP and VTABLE relocs. --- gas/ChangeLog | 24 ++++++++ gas/config/tc-m68hc11.c | 142 +++++++++++++++++++++++++++++++++++++++++++----- gas/config/tc-m68hc11.h | 12 ++-- 3 files changed, 161 insertions(+), 17 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 3d08c0b..6861b71 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,29 @@ 2002-08-13 Stephane Carrez + * config/tc-m68hc11.h (MD_PCREL_FROM_SECTION): Remove. + (TC_HANDLES_FX_DONE): Define to let md_apply_fix3 set fx_done flag + according to the reloc. + (tc_fix_adjustable, tc_m68hc11_fix_adjustable): Define. + (TC_FORCE_RELOCATION): Define. + (tc_m68hc11_force_relocation): Declare. + + * config/tc-m68hc11.c (md_pseudo_table): Add relax command. + (s_m68hc11_relax): New function for relax group. + (build_insn, build_jump_insn): Emit a M68HC11_RL_JUMP reloc at + beginning of jump instruction. + (md_pcrel_from): Rename from md_pcrel_from_section and fix + address computation. + (tc-gen_reloc): Update. + (md_estimate_size_before_relax): Create the BFD_RELOC_16_PCREL as + PC-relative fixup. + (tc_m68hc11_force_relocation): New function, handle new relocs. + (tc_m68hc11_fix_adjustable): New to make sure there are enough + reloc for the linker relax pass. + (md_apply_fix3): Handle M68HC11_RL_JUMP, M68HC11_RL_GROUP + and VTABLE relocs. + +2002-08-13 Stephane Carrez + * config/tc-m68hc11.c (m68hc11_elf_final_processing): New function. (md_pseudo_table): Add .mode, .far and .interrupt pseudo op. (s_m68hc11_mode): New function for .mode pseudo op. diff --git a/gas/config/tc-m68hc11.c b/gas/config/tc-m68hc11.c index d570784..dc21941 100644 --- a/gas/config/tc-m68hc11.c +++ b/gas/config/tc-m68hc11.c @@ -182,6 +182,9 @@ static void build_insn PARAMS ((struct m68hc11_opcode *, operand *, int)); static int relaxable_symbol PARAMS ((symbolS *)); +/* Pseudo op to indicate a relax group. */ +static void s_m68hc11_relax PARAMS((int)); + /* Pseudo op to control the ELF flags. */ static void s_m68hc11_mode PARAMS ((int)); @@ -264,6 +267,9 @@ const pseudo_typeS md_pseudo_table[] = { /* Motorola ALIS. */ {"xrefb", s_ignore, 0}, /* Same as xref */ + /* Gcc driven relaxation. */ + {"relax", s_m68hc11_relax, 0}, + /* .mode instruction (ala SH). */ {"mode", s_m68hc11_mode, 0}, @@ -1516,6 +1522,8 @@ build_jump_insn (opcode, operands, nb_operands, jmp_mode) unsigned char code; char *f; unsigned long n; + fragS *frag; + int where; /* The relative branch convertion is not supported for brclr and brset. */ @@ -1536,6 +1544,12 @@ build_jump_insn (opcode, operands, nb_operands, jmp_mode) && (!check_range (n, opcode->format) && (jmp_mode == 1 || flag_fixed_branchs == 0)))) { + frag = frag_now; + where = frag_now_fix (); + + fix_new (frag_now, frag_now_fix (), 1, + &abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP); + if (code == M6811_BSR || code == M6811_BRA || code == M6812_BSR) { code = convert_branch (code); @@ -1590,6 +1604,12 @@ build_jump_insn (opcode, operands, nb_operands, jmp_mode) } else if (opcode->format & M6812_OP_JUMP_REL16) { + frag = frag_now; + where = frag_now_fix (); + + fix_new (frag_now, frag_now_fix (), 1, + &abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP); + f = m68hc11_new_insn (2); number_to_chars_bigendian (f, M6811_OPCODE_PAGE2, 1); number_to_chars_bigendian (f + 1, code, 1); @@ -1599,6 +1619,12 @@ build_jump_insn (opcode, operands, nb_operands, jmp_mode) { char *opcode; + frag = frag_now; + where = frag_now_fix (); + + fix_new (frag_now, frag_now_fix (), 1, + &abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP); + /* Branch offset must fit in 8-bits, don't do some relax. */ if (jmp_mode == 0 && flag_fixed_branchs) { @@ -2002,9 +2028,19 @@ build_insn (opcode, operands, nb_operands) char *f; long format; int move_insn = 0; + fragS *frag; + int where; /* Put the page code instruction if there is one. */ format = opcode->format; + + frag = frag_now; + where = frag_now_fix (); + + if (format & M6811_OP_BRANCH) + fix_new (frag, where, 1, + &abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP); + if (format & OP_EXTENDED) { int page_code; @@ -2592,21 +2628,42 @@ s_m68hc11_mark_symbol (mark) demand_empty_rest_of_line (); } + +static void +s_m68hc11_relax (ignore) + int ignore ATTRIBUTE_UNUSED; +{ + expressionS ex; + + expression (&ex); + + if (ex.X_op != O_symbol || ex.X_add_number != 0) + { + as_bad (_("bad .relax format")); + ignore_rest_of_line (); + return; + } + + fix_new_exp (frag_now, frag_now_fix (), 1, &ex, 1, + BFD_RELOC_M68HC11_RL_GROUP); + + demand_empty_rest_of_line (); +} + /* Relocation, relaxation and frag conversions. */ + +/* PC-relative offsets are relative to the start of the + next instruction. That is, the address of the offset, plus its + size, since the offset is always the last part of the insn. */ long -md_pcrel_from_section (fixp, sec) - fixS *fixp; - segT sec; +md_pcrel_from (fixP) + fixS *fixP; { - int adjust; - if (fixp->fx_addsy != (symbolS *) NULL - && (!S_IS_DEFINED (fixp->fx_addsy) - || (S_GET_SEGMENT (fixp->fx_addsy) != sec))) + if (fixP->fx_r_type == BFD_RELOC_M68HC11_RL_JUMP) return 0; - adjust = fixp->fx_pcrel_adjust; - return fixp->fx_frag->fr_address + fixp->fx_where + adjust; + return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; } /* If while processing a fixup, a reloc really needs to be created @@ -2638,10 +2695,10 @@ tc_gen_reloc (section, fixp) reloc->addend = fixp->fx_addnumber; else reloc->addend = (section->vma - + (fixp->fx_pcrel_adjust == 64 - ? -1 : fixp->fx_pcrel_adjust) + /*+ (fixp->fx_pcrel_adjust == 64 + ? -1 : fixp->fx_pcrel_adjust)*/ + fixp->fx_addnumber - + md_pcrel_from_section (fixp, section)); + + md_pcrel_from (fixp)); return reloc; } @@ -2873,7 +2930,7 @@ md_estimate_size_before_relax (fragP, segment) fragP->fr_opcode[0] = M6811_OPCODE_PAGE2; fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, - fragP->fr_offset, 0, BFD_RELOC_16_PCREL); + fragP->fr_offset, 1, BFD_RELOC_16_PCREL); fragP->fr_fix += 2; break; @@ -2934,6 +2991,54 @@ md_estimate_size_before_relax (fragP, segment) return md_relax_table[fragP->fr_subtype].rlx_length; } +/* See whether we need to force a relocation into the output file. */ +int +tc_m68hc11_force_relocation (fixP) + fixS * fixP; +{ + switch (fixP->fx_r_type) + { + case BFD_RELOC_VTABLE_INHERIT: + case BFD_RELOC_VTABLE_ENTRY: + case BFD_RELOC_M68HC11_RL_GROUP: + return 1; + + default: + return 0; + } +} + +/* Here we decide which fixups can be adjusted to make them relative + to the beginning of the section instead of the symbol. Basically + we need to make sure that the linker relaxation is done + correctly, so in some cases we force the original symbol to be + used. */ +int +tc_m68hc11_fix_adjustable (fixP) + fixS *fixP; +{ + /* Prevent all adjustments to global symbols. */ + if (! relaxable_symbol (fixP->fx_addsy)) + return 0; + + switch (fixP->fx_r_type) + { + /* For the linker relaxation to work correctly, these relocs + need to be on the symbol itself. */ + case BFD_RELOC_16: + case BFD_RELOC_LO16: + case BFD_RELOC_M68HC11_RL_JUMP: + case BFD_RELOC_M68HC11_RL_GROUP: + case BFD_RELOC_VTABLE_INHERIT: + case BFD_RELOC_VTABLE_ENTRY: + return 0; + + case BFD_RELOC_32: + default: + return 1; + } +} + void md_apply_fix3 (fixP, valP, seg) fixS *fixP; @@ -3037,10 +3142,21 @@ md_apply_fix3 (fixP, valP, seg) where[0] = where[0] | (value & 0x07); break; + case BFD_RELOC_M68HC11_RL_JUMP: + case BFD_RELOC_M68HC11_RL_GROUP: + case BFD_RELOC_VTABLE_INHERIT: + case BFD_RELOC_VTABLE_ENTRY: + fixP->fx_done = 0; + return; + default: as_fatal (_("Line %d: unknown relocation type: 0x%x."), fixP->fx_line, fixP->fx_r_type); } + + /* Are we finished with this relocation now? */ + if (fixP->fx_addsy == 0 && !fixP->fx_pcrel) + fixP->fx_done = 1; } /* Set the ELF specific flags. */ diff --git a/gas/config/tc-m68hc11.h b/gas/config/tc-m68hc11.h index 418b7b5..e17df1e 100644 --- a/gas/config/tc-m68hc11.h +++ b/gas/config/tc-m68hc11.h @@ -72,13 +72,11 @@ extern const char *m68hc11_arch_format PARAMS ((void)); #define LISTING_HEADER m68hc11_listing_header () extern const char *m68hc11_listing_header PARAMS ((void)); -/* call md_pcrel_from_section, not md_pcrel_from */ -#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC) -extern long md_pcrel_from_section PARAMS ((struct fix *fixp, segT sec)); - /* Permit temporary numeric labels. */ #define LOCAL_LABELS_FB 1 +#define TC_HANDLES_FX_DONE + #define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */ #define tc_init_after_args m68hc11_init_after_args @@ -99,6 +97,12 @@ extern int m68hc11_parse_long_option PARAMS ((char *)); #define TC_GENERIC_RELAX_TABLE md_relax_table extern struct relax_type md_relax_table[]; +#define TC_FORCE_RELOCATION(fix) tc_m68hc11_force_relocation (fix) +extern int tc_m68hc11_force_relocation PARAMS ((struct fix *)); + +#define tc_fix_adjustable(X) tc_m68hc11_fix_adjustable(X) +extern int tc_m68hc11_fix_adjustable PARAMS ((struct fix *)); + #define md_operand(x) #define tc_frob_label(sym) do {\ S_SET_VALUE (sym, (valueT) frag_now_fix ()); \ -- 2.7.4