* config/tc-m68hc11.h (MD_PCREL_FROM_SECTION): Remove.
authorStephane Carrez <stcarrez@nerim.fr>
Tue, 13 Aug 2002 22:20:50 +0000 (22:20 +0000)
committerStephane Carrez <stcarrez@nerim.fr>
Tue, 13 Aug 2002 22:20:50 +0000 (22:20 +0000)
(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
gas/config/tc-m68hc11.c
gas/config/tc-m68hc11.h

index 3d08c0b..6861b71 100644 (file)
@@ -1,5 +1,29 @@
 2002-08-13  Stephane Carrez  <stcarrez@nerim.fr>
 
+       * 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  <stcarrez@nerim.fr>
+
        * 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.
index d570784..dc21941 100644 (file)
@@ -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 ();
+}
+
 \f
 /* 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.  */
index 418b7b5..e17df1e 100644 (file)
@@ -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 ()); \