This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH]: Generate relax relocations in gas HC11/HC12


Hi!

This patch adds the necessary support to generate the relocs for linker
relaxation (HC11/HC12).  A RL_JUMP reloc is put at beginning of each branch
instruction.  The assembler must not resolve relocs itself and transform them
to be based on sections.  The linker will need the real symbol to know if relaxation
of the instruction can be done.

Committed on mainline.

	Stephane

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.

Index: config/tc-m68hc11.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m68hc11.h,v
retrieving revision 1.8
diff -u -p -r1.8 tc-m68hc11.h
--- config/tc-m68hc11.h	13 Aug 2002 21:52:57 -0000	1.8
+++ config/tc-m68hc11.h	13 Aug 2002 22:19:43 -0000
@@ -72,13 +72,11 @@ extern const char *m68hc11_arch_format P
 #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
@@ -98,6 +96,12 @@ extern int m68hc11_parse_long_option PAR
    absolute branches.  */
 #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 {\
Index: config/tc-m68hc11.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m68hc11.c,v
retrieving revision 1.26
diff -u -p -r1.26 tc-m68hc11.c
--- config/tc-m68hc11.c	13 Aug 2002 21:52:57 -0000	1.26
+++ config/tc-m68hc11.c	13 Aug 2002 22:19:44 -0000
@@ -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_op
   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_op
 	  && (!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_op
     }
   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_op
     {
       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_operand
   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, se
 	      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, se
   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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]