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] MIPS gas: irix relocation tweaks


This patch changes gas so it creates relocations that are more like those of
Irix for the Newabi.  The primary differences are:
1. use R_MIPS_GOT_DISP for internal and external symbols
2. use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFFSET for internal function symbols
3. make -xgot optional and not the default

Tested on Irix and mips-elf.

	* tc-mips.c (load_address): Use BFD_RELOC_MIPS_GOT_DISP for newabi.
	(macro): Likewise for la.  Likewise for ld.
	(mips_after_parse_args): Make -xgot optional, not the default.
	(md_apply_fix3): Allow composite relocation to set up gp.
	(tc_gen_reloc): Allow relaxing for newabi.
	Relax R_MIPS_CALL16 to R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST if local.
	Relax R_MIPS_GOT16/R_MIPS_LO16 to R_MIPS_GOT_DISP if local.

Index: config/tc-mips.c
===================================================================
RCS file: /cvs/uberbaum/gas/config/tc-mips.c,v
retrieving revision 1.162
diff -u -2 -p -r1.162 tc-mips.c
--- config/tc-mips.c	5 Sep 2002 00:01:18 -0000	1.162
+++ config/tc-mips.c	10 Sep 2002 03:15:11 -0000
@@ -1835,4 +1835,5 @@ append_insn (place, ip, address_expr, re
 
 	    case BFD_RELOC_LO16:
+	    case BFD_RELOC_MIPS_GOT_DISP:
 	      ip->insn_opcode |= address_expr->X_add_number & 0xffff;
 	      break;
@@ -3586,18 +3587,30 @@ load_address (counter, reg, ep, used_at)
 	   nop
 	   addiu	$reg,$reg,<sym>		(BFD_RELOC_LO16)
+	 If we have NewABI, we want
+	   lw		$reg,<sym>($gp)		(BFD_RELOC_MIPS_GOT_DISP)
 	 If there is a constant, it must be added in after.  */
       ex.X_add_number = ep->X_add_number;
       ep->X_add_number = 0;
       frag_grow (20);
-      macro_build ((char *) NULL, counter, ep,
-		   HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)",
-		   reg, (int) BFD_RELOC_MIPS_GOT16, mips_gp_register);
-      macro_build ((char *) NULL, counter, (expressionS *) NULL, "nop", "");
-      p = frag_var (rs_machine_dependent, 4, 0,
-		    RELAX_ENCODE (0, 4, -8, 0, 0, mips_opts.warn_about_macros),
-		    ep->X_add_symbol, (offsetT) 0, (char *) NULL);
-      macro_build (p, counter, ep,
-		   HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
-		   "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
+      if (HAVE_NEWABI)
+	{
+	  macro_build ((char *) NULL, counter, ep,
+		       HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", reg,
+		       (int) BFD_RELOC_MIPS_GOT_DISP, mips_gp_register);
+	}
+      else
+	{
+	  macro_build ((char *) NULL, counter, ep,
+		       HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)",
+		       reg, (int) BFD_RELOC_MIPS_GOT16, mips_gp_register);
+	  macro_build ((char *) NULL, counter, (expressionS *) NULL, "nop", "");
+	  p = frag_var (rs_machine_dependent, 4, 0,
+			RELAX_ENCODE (0, 4, -8, 0, 0, mips_opts.warn_about_macros),
+			ep->X_add_symbol, (offsetT) 0, (char *) NULL);
+	  macro_build (p, counter, ep,
+		       HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
+		       "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
+	}
+
       if (ex.X_add_number != 0)
 	{
@@ -4631,5 +4644,14 @@ macro (ip)
 	     For a local symbol, we want the same instruction
 	     sequence, but we output a BFD_RELOC_LO16 reloc on the
-	     addiu instruction.  */
+	     addiu instruction.
+
+	     For NewABI, we want for local or external data addresses
+	       lw	$tempreg,<sym>($gp)	(BFD_RELOC_MIPS_GOT_DISP)
+	     For a local function symbol, we want
+	       lw	$tempreg,<sym>($gp)	(BFD_RELOC_MIPS_GOT_PAGE)
+	       nop
+	       addiu	$tempreg,$tempreg,<sym>	(BFD_RELOC_MIPS_GOT_OFST)
+	   */
+
 	  expr1.X_add_number = offset_expr.X_add_number;
 	  offset_expr.X_add_number = 0;
@@ -4637,4 +4659,6 @@ macro (ip)
 	  if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
 	    lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16;
+	  else if (HAVE_NEWABI)
+	    lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
 	  macro_build ((char *) NULL, &icnt, &offset_expr,
 		       HAVE_32BIT_ADDRESSES ? "lw" : "ld",
@@ -4736,4 +4760,5 @@ macro (ip)
 	  int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
 	  int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16;
+	  int local_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
 
 	  /* This is the large GOT case.  If this is a reference to an
@@ -4777,29 +4802,8 @@ macro (ip)
 	       addu	$tempreg,$tempreg,$at
 
-	     For NewABI, we want for data addresses
-	       lw	$tempreg,<sym>($gp)	(BFD_RELOC_MIPS_GOT_DISP)
-	     If tempreg is PIC_CALL_REG pointing to a external symbol, we want
-	       lw	$tempreg,<sym>($gp)	(BFD_RELOC_MIPS_CALL16)
+	     For NewABI, we want for local data addresses
+              lw       $tempreg,<sym>($gp)     (BFD_RELOC_MIPS_GOT_DISP)
 	   */
-	  if (HAVE_NEWABI)
-	    {
-	      int reloc_type = (tempreg == PIC_CALL_REG
-				? BFD_RELOC_MIPS_CALL16
-				: BFD_RELOC_MIPS_GOT_DISP);
-
-	      macro_build ((char *) NULL, &icnt, &offset_expr,
-			   HAVE_32BIT_ADDRESSES ? "lw" : "ld",
-			   "t,o(b)", tempreg, reloc_type, mips_gp_register);
-
-	      if (breg != 0)
-		macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
-			     HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
-			     "d,v,t", treg, tempreg, breg);
 
-	      if (! used_at)
-		return;
-
-	      break;
-	    }
 	  expr1.X_add_number = offset_expr.X_add_number;
 	  offset_expr.X_add_number = 0;
@@ -4814,4 +4818,5 @@ macro (ip)
 	      lw_reloc_type = (int) BFD_RELOC_MIPS_CALL_LO16;
 	    }
+
 	  macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
 		       tempreg, lui_reloc_type);
@@ -4922,10 +4927,19 @@ macro (ip)
 	      p += 4;
 	    }
+
+	  if (HAVE_NEWABI)
+	    local_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
 	  macro_build (p, &icnt, &offset_expr,
 		       HAVE_32BIT_ADDRESSES ? "lw" : "ld",
-		       "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16,
+		       "t,o(b)", tempreg,
+		       local_reloc_type,
 		       mips_gp_register);
 	  p += 4;
-	  if (expr1.X_add_number >= -0x8000
+	  if (expr1.X_add_number == 0 && HAVE_NEWABI)
+	    {
+	      /* BFD_RELOC_MIPS_GOT_DISP is sufficient for newabi */
+	    }
+	 else
+	   if (expr1.X_add_number >= -0x8000
 	      && expr1.X_add_number < 0x8000)
 	    {
@@ -5598,4 +5612,5 @@ macro (ip)
 	{
 	  char *p;
+	  int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
 
 	  /* If this is a reference to an external symbol, we want
@@ -5603,9 +5618,6 @@ macro (ip)
 	       nop
 	       <op>	$treg,0($tempreg)
-	     Otherwise we want
-	       lw	$tempreg,<sym>($gp)	(BFD_RELOC_MIPS_GOT16)
-	       nop
-	       addiu	$tempreg,$tempreg,<sym>	(BFD_RELOC_LO16)
-	       <op>	$treg,0($tempreg)
+	     If we have NewABI, we want
+	       lw	$reg,<sym>($gp)		(BFD_RELOC_MIPS_GOT_DISP)
 	     If there is a base register, we add it to $tempreg before
 	     the <op>.  If there is a constant, we stick it in the
@@ -5617,4 +5629,6 @@ macro (ip)
 	  expr1.X_add_number = offset_expr.X_add_number;
 	  offset_expr.X_add_number = 0;
+	  if (HAVE_NEWABI)
+	    lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP;
 	  if (expr1.X_add_number < -0x8000
 	      || expr1.X_add_number >= 0x8000)
@@ -5623,5 +5637,5 @@ macro (ip)
 	  macro_build ((char *) NULL, &icnt, &offset_expr,
 		       HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", tempreg,
-		       (int) BFD_RELOC_MIPS_GOT16, mips_gp_register);
+		       (int) lw_reloc_type, mips_gp_register);
 	  macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
 	  p = frag_var (rs_machine_dependent, 4, 0,
@@ -5668,4 +5682,5 @@ macro (ip)
 	  expr1.X_add_number = offset_expr.X_add_number;
 	  offset_expr.X_add_number = 0;
+
 	  if (expr1.X_add_number < -0x8000
 	      || expr1.X_add_number >= 0x8000)
@@ -5715,4 +5730,5 @@ macro (ip)
 	      p += 4;
 	    }
+
 	  macro_build (p, &icnt, &offset_expr,
 		       HAVE_32BIT_ADDRESSES ? "lw" : "ld",
@@ -10419,7 +10435,4 @@ mips_after_parse_args ()
   mips_opts.fp32 = file_mips_fp32;
 
-  if (HAVE_NEWABI)
-    mips_big_got = 1;
-
   if (mips_flag_mdebug < 0)
     {
@@ -10643,4 +10656,5 @@ md_apply_fix3 (fixP, valP, seg)
   long insn;
   valueT value;
+  static int previous_fx_r_type = 0;
 
   assert (fixP->fx_size == 4
@@ -10742,6 +10756,12 @@ md_apply_fix3 (fixP, valP, seg)
   fixP->fx_addnumber = value;	/* Remember value for tc_gen_reloc.  */
 
-  if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel)
+  /* We are not done if this is a composite relocation to set up gp.  */
+  if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel
+      && !(fixP->fx_r_type == BFD_RELOC_MIPS_SUB
+	   || (previous_fx_r_type == BFD_RELOC_MIPS_SUB
+	       && (fixP->fx_r_type == BFD_RELOC_HI16_S
+		   || fixP->fx_r_type == BFD_RELOC_LO16))))
     fixP->fx_done = 1;
+  previous_fx_r_type = fixP->fx_r_type;
 
   switch (fixP->fx_r_type)
@@ -12636,5 +12656,6 @@ tc_gen_reloc (section, fixp)
      reloc and generate a new one.  */
   if (fixp->fx_frag->fr_opcode != NULL
-      && (fixp->fx_r_type == BFD_RELOC_GPREL16
+      && ((fixp->fx_r_type == BFD_RELOC_GPREL16
+	   && ! HAVE_NEWABI)
 	  || fixp->fx_r_type == BFD_RELOC_MIPS_GOT16
 	  || fixp->fx_r_type == BFD_RELOC_MIPS_CALL16
@@ -12643,5 +12664,5 @@ tc_gen_reloc (section, fixp)
 	  || fixp->fx_r_type == BFD_RELOC_MIPS_CALL_HI16
 	  || fixp->fx_r_type == BFD_RELOC_MIPS_CALL_LO16)
-      && ! HAVE_NEWABI)
+    )
     {
       arelent *reloc2;
@@ -12704,13 +12735,30 @@ tc_gen_reloc (section, fixp)
 	    case BFD_RELOC_MIPS_GOT16:
 	      break;
-	    case BFD_RELOC_MIPS_CALL16:
 	    case BFD_RELOC_MIPS_GOT_LO16:
 	    case BFD_RELOC_MIPS_CALL_LO16:
 	      fixp->fx_r_type = BFD_RELOC_MIPS_GOT16;
 	      break;
+	    case BFD_RELOC_MIPS_CALL16:
+	      if (HAVE_NEWABI)
+		{
+		  /* BFD_RELOC_MIPS_GOT16;*/
+		  fixp->fx_r_type = BFD_RELOC_MIPS_GOT_PAGE;
+		  reloc2->howto = bfd_reloc_type_lookup
+		    (stdoutput, BFD_RELOC_MIPS_GOT_OFST);
+		}
+	      else
+		fixp->fx_r_type = BFD_RELOC_MIPS_GOT16;
+	      break;
 	    }
 	}
       else
 	abort ();
+
+      /* newabi uses R_MIPS_GOT_DISP for local symbols */
+      if (HAVE_NEWABI && BFD_RELOC_MIPS_GOT_LO16)
+	{
+	  fixp->fx_r_type = BFD_RELOC_MIPS_GOT_DISP;
+	  retval[1] = NULL;
+	}
     }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]