diff options
author | Stephane Carrez <stcarrez@nerim.fr> | 2002-08-13 22:20:50 +0000 |
---|---|---|
committer | Stephane Carrez <stcarrez@nerim.fr> | 2002-08-13 22:20:50 +0000 |
commit | e371935fea357fda4aff68fadadf3f7ecbb9672a (patch) | |
tree | 73b47ad5c538d41fc78c51effe249c6794fa1e37 /gas/config/tc-m68hc11.c | |
parent | 3c1499adb353ea2d7312cbd78e109dee250d2436 (diff) | |
download | gdb-e371935fea357fda4aff68fadadf3f7ecbb9672a.zip gdb-e371935fea357fda4aff68fadadf3f7ecbb9672a.tar.gz gdb-e371935fea357fda4aff68fadadf3f7ecbb9672a.tar.bz2 |
* 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.
Diffstat (limited to 'gas/config/tc-m68hc11.c')
-rw-r--r-- | gas/config/tc-m68hc11.c | 142 |
1 files changed, 129 insertions, 13 deletions
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. */ |