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 to extend explicit reloc support in MIPS gas


The patch below allows NewABI-style %reloc() operators to be used
for all ABIs.  The patch is enough to get GAS to emit the relocs:
a follow-on patch will extend the HI/LO pairing code to work with
other paired relocs, notably R_MIPS_GOT16/R_MIPS_LO16.

Notes:

- The patch gets rid of imm_unmatched_hi.  Unless I'm missing something,
  append_insn() can just look at the relocs passed to it.

- The check for an implicit zero in "o(b)" moves from my_getSmallExpresion()
  to mips_ip().  The old code went to great lengths to check for a valid
  register (which, if found, meant that the offset had been left out).
  It seems easier to check whether there is a single bracketed expression
  left: if so, it must be the base register.

  [I guess it would be nice if tc-mips.c had a single routine for
  parsing registers, but that's something for another day.]

- my_getSmallExpression() now parses the whole expression at once
  and records the relocs it sees.  This seems simpler than the
  earlier scheme, in which the function was called several times
  for compound relocations.

- There's a bug fix: %gp_rel() is now allowed as a stand-alone
  relocation.  Before we expected it to be part of a PIC $gp
  calculation.

- We no longer reject unexpected compound relocations for NewABI.
  This isn't a change I'm fervent about, it's just that the old code
  isn't there any more.

  From one point of view (and this is pretty much the spirit of the patch)
  we should accept relocations that can be represented in the output file,
  even if they're unusual.  I don't think the assembler should be overly
  pedantic or try to second-guess the programmer.

  On the other hand, an error or warning might trap mistakes earlier.
  I can add some new checking code if that's what folks prefer.

Patch tested on:

mips-elf mips64-elf mips64vrel-elf mips-ecoff mips-linux-gnu
mipsel-linux-gnu mips64-linux-gnu mips64el-linux-gnu mips-sgi-irix6.5

No regressions, but the new elf-rel11 test fails for mips64el-linux-gnu.
I'll send a separate note about that.

OK to install?

gas/
	* config/tc-mips.c (enum small_ex_type): Remove.
	(imm_unmatched_hi): Remove.
	(md_assemble): Remove use of imm_unmatched_hi.  Remove the last
	argument from calls to append_insn.
	(append_insn): Remove unmatched_hi parameter; check reloc_type[0]
	instead.
	(macro_build): Update append_insn calls.
	(mips16_macro_build, macro_build_lui): Likewise.
	(mips_ip): Rework handling of small expressions.  Move explicit
	relocation handling into my_getSmallExpression.  Assume that the
	value of 'o' operands is zero if there is only one bracketed
	expression left.
	(percent_op): Make constant.  Record the BFD relocation code
	associated with each operator.
	(my_getSmallParser, my_getPercentOp): Remove.
	(parse_relocation): New function.
	(my_getSamllExpression): Rework.  Fill in relocations here
	rather than in mips_ip.

gas/testsuite
	* gas/mips/elf-rel8.[sd], gas/mips/elf-rel9.[sd],
	gas/mips/elf-rel10.[sd], gas/mips/elf-rel11.[sd]: New tests.
	* gas/mips/mips.exp: Run elf-rel8 and elf-rel9 for all elf
	targets.  Run elf-rel10 and elf-rel11 for NewABI targets.

Index: config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.188
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.188 tc-mips.c
*** config/tc-mips.c	23 Jan 2003 12:51:05 -0000	1.188
--- config/tc-mips.c	26 Jan 2003 12:09:08 -0000
*************** static void mips16_mark_labels
*** 810,816 ****
    PARAMS ((void));
  static void append_insn
    PARAMS ((char *place, struct mips_cl_insn * ip, expressionS * p,
! 	   bfd_reloc_code_real_type *r, bfd_boolean));
  static void mips_no_prev_insn
    PARAMS ((int));
  static void mips_emit_delays
--- 810,816 ----
    PARAMS ((void));
  static void append_insn
    PARAMS ((char *place, struct mips_cl_insn * ip, expressionS * p,
! 	   bfd_reloc_code_real_type *r));
  static void mips_no_prev_insn
    PARAMS ((int));
  static void mips_emit_delays
*************** static void mips16_ip
*** 856,867 ****
  static void mips16_immed
    PARAMS ((char *, unsigned int, int, offsetT, bfd_boolean, bfd_boolean,
  	   bfd_boolean, unsigned long *, bfd_boolean *, unsigned short *));
! static int my_getPercentOp
!   PARAMS ((char **, unsigned int *, int *));
! static int my_getSmallParser
!   PARAMS ((char **, unsigned int *, int *));
! static int my_getSmallExpression
!   PARAMS ((expressionS *, char *));
  static void my_getExpression
    PARAMS ((expressionS *, char *));
  #ifdef OBJ_ELF
--- 856,865 ----
  static void mips16_immed
    PARAMS ((char *, unsigned int, int, offsetT, bfd_boolean, bfd_boolean,
  	   bfd_boolean, unsigned long *, bfd_boolean *, unsigned short *));
! static bfd_boolean parse_relocation
!   PARAMS ((char **, bfd_reloc_code_real_type *));
! static size_t my_getSmallExpression
!   PARAMS ((expressionS *, bfd_reloc_code_real_type *, char *));
  static void my_getExpression
    PARAMS ((expressionS *, char *));
  #ifdef OBJ_ELF
*************** static int mips_need_elf_addend_fixup
*** 946,977 ****
    PARAMS ((fixS *));
  #endif
  
- /* Return values of my_getSmallExpression().  */
- 
- enum small_ex_type
- {
-   S_EX_NONE = 0,
-   S_EX_REGISTER,
- 
-   /* Direct relocation creation by %percent_op().  */
-   S_EX_HALF,
-   S_EX_HI,
-   S_EX_LO,
-   S_EX_GP_REL,
-   S_EX_GOT,
-   S_EX_CALL16,
-   S_EX_GOT_DISP,
-   S_EX_GOT_PAGE,
-   S_EX_GOT_OFST,
-   S_EX_GOT_HI,
-   S_EX_GOT_LO,
-   S_EX_NEG,
-   S_EX_HIGHER,
-   S_EX_HIGHEST,
-   S_EX_CALL_HI,
-   S_EX_CALL_LO
- };
- 
  /* Table and functions used to map between CPU/ISA names, and
     ISA levels, and CPU numbers.  */
  
--- 944,949 ----
*************** static bfd_reloc_code_real_type imm_relo
*** 1136,1145 ****
  static bfd_reloc_code_real_type offset_reloc[3]
    = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
  
- /* This is set by mips_ip if imm_reloc is an unmatched HI16_S reloc.  */
- 
- static bfd_boolean imm_unmatched_hi;
- 
  /* These are set by mips16_ip if an explicit extension is used.  */
  
  static bfd_boolean mips16_small, mips16_ext;
--- 1108,1113 ----
*************** md_assemble (str)
*** 1430,1436 ****
      = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
  
    imm_expr.X_op = O_absent;
-   imm_unmatched_hi = FALSE;
    offset_expr.X_op = O_absent;
    imm_reloc[0] = BFD_RELOC_UNUSED;
    imm_reloc[1] = BFD_RELOC_UNUSED;
--- 1398,1403 ----
*************** md_assemble (str)
*** 1464,1474 ****
    else
      {
        if (imm_expr.X_op != O_absent)
! 	append_insn (NULL, &insn, &imm_expr, imm_reloc, imm_unmatched_hi);
        else if (offset_expr.X_op != O_absent)
! 	append_insn (NULL, &insn, &offset_expr, offset_reloc, FALSE);
        else
! 	append_insn (NULL, &insn, NULL, unused_reloc, FALSE);
      }
  }
  
--- 1431,1441 ----
    else
      {
        if (imm_expr.X_op != O_absent)
! 	append_insn (NULL, &insn, &imm_expr, imm_reloc);
        else if (offset_expr.X_op != O_absent)
! 	append_insn (NULL, &insn, &offset_expr, offset_reloc);
        else
! 	append_insn (NULL, &insn, NULL, unused_reloc);
      }
  }
  
*************** mips16_mark_labels ()
*** 1616,1638 ****
     used with RELOC_TYPE.  */
  
  static void
! append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
       char *place;
       struct mips_cl_insn *ip;
       expressionS *address_expr;
       bfd_reloc_code_real_type *reloc_type;
-      bfd_boolean unmatched_hi;
  {
    register unsigned long prev_pinfo, pinfo;
    char *f;
    fixS *fixp[3];
    int nops = 0;
  
    /* Mark instruction labels in mips16 mode.  */
    mips16_mark_labels ();
  
    prev_pinfo = prev_insn.insn_mo->pinfo;
    pinfo = ip->insn_mo->pinfo;
  
    if (place == NULL && (! mips_opts.noreorder || prev_nop_frag != NULL))
      {
--- 1583,1606 ----
     used with RELOC_TYPE.  */
  
  static void
! append_insn (place, ip, address_expr, reloc_type)
       char *place;
       struct mips_cl_insn *ip;
       expressionS *address_expr;
       bfd_reloc_code_real_type *reloc_type;
  {
    register unsigned long prev_pinfo, pinfo;
    char *f;
    fixS *fixp[3];
    int nops = 0;
+   bfd_boolean unmatched_reloc_p;
  
    /* Mark instruction labels in mips16 mode.  */
    mips16_mark_labels ();
  
    prev_pinfo = prev_insn.insn_mo->pinfo;
    pinfo = ip->insn_mo->pinfo;
+   unmatched_reloc_p = FALSE;
  
    if (place == NULL && (! mips_opts.noreorder || prev_nop_frag != NULL))
      {
*************** #define emit_nop()					\
*** 2176,2192 ****
  		   || *reloc_type == BFD_RELOC_MIPS_RELGOT))
  		fixp[0]->fx_no_overflow = 1;
  
! 	      if (unmatched_hi)
  		{
  		  struct mips_hi_fixup *hi_fixup;
  
- 		  assert (*reloc_type == BFD_RELOC_HI16_S);
  		  hi_fixup = ((struct mips_hi_fixup *)
  			      xmalloc (sizeof (struct mips_hi_fixup)));
  		  hi_fixup->fixp = fixp[0];
  		  hi_fixup->seg = now_seg;
  		  hi_fixup->next = mips_hi_fixup_list;
  		  mips_hi_fixup_list = hi_fixup;
  		}
  
  	      if (reloc_type[1] != BFD_RELOC_UNUSED)
--- 2144,2160 ----
  		   || *reloc_type == BFD_RELOC_MIPS_RELGOT))
  		fixp[0]->fx_no_overflow = 1;
  
! 	      if (reloc_type[0] == BFD_RELOC_HI16_S)
  		{
  		  struct mips_hi_fixup *hi_fixup;
  
  		  hi_fixup = ((struct mips_hi_fixup *)
  			      xmalloc (sizeof (struct mips_hi_fixup)));
  		  hi_fixup->fixp = fixp[0];
  		  hi_fixup->seg = now_seg;
  		  hi_fixup->next = mips_hi_fixup_list;
  		  mips_hi_fixup_list = hi_fixup;
+ 		  unmatched_reloc_p = TRUE;
  		}
  
  	      if (reloc_type[1] != BFD_RELOC_UNUSED)
*************** #define emit_nop()					\
*** 2743,2749 ****
       reloc does not become a variant frag.  Otherwise, the
       rearrangement of %hi relocs in frob_file may confuse
       tc_gen_reloc.  */
!   if (unmatched_hi)
      {
        frag_wane (frag_now);
        frag_new (0);
--- 2711,2717 ----
       reloc does not become a variant frag.  Otherwise, the
       rearrangement of %hi relocs in frob_file may confuse
       tc_gen_reloc.  */
!   if (unmatched_reloc_p)
      {
        frag_wane (frag_now);
        frag_new (0);
*************** macro_build (place, counter, ep, name, f
*** 3140,3146 ****
    va_end (args);
    assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
  
!   append_insn (place, &insn, ep, r, FALSE);
  }
  
  static void
--- 3108,3114 ----
    va_end (args);
    assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
  
!   append_insn (place, &insn, ep, r);
  }
  
  static void
*************** mips16_macro_build (place, counter, ep, 
*** 3266,3272 ****
  
    assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
  
!   append_insn (place, &insn, ep, r, FALSE);
  }
  
  /*
--- 3234,3240 ----
  
    assert (*r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
  
!   append_insn (place, &insn, ep, r);
  }
  
  /*
*************** macro_build_lui (place, counter, ep, reg
*** 3356,3365 ****
    if (*r == BFD_RELOC_UNUSED)
      {
        insn.insn_opcode |= high_expr.X_add_number;
!       append_insn (place, &insn, NULL, r, FALSE);
      }
    else
!     append_insn (place, &insn, &high_expr, r, FALSE);
  }
  
  /* Generate a sequence of instructions to do a load or store from a constant
--- 3324,3333 ----
    if (*r == BFD_RELOC_UNUSED)
      {
        insn.insn_opcode |= high_expr.X_add_number;
!       append_insn (place, &insn, NULL, r);
      }
    else
!     append_insn (place, &insn, &high_expr, r);
  }
  
  /* Generate a sequence of instructions to do a load or store from a constant
*************** mips_ip (str, ip)
*** 9065,9186 ****
  	    case 'i':		/* 16 bit unsigned immediate */
  	    case 'j':		/* 16 bit signed immediate */
  	      *imm_reloc = BFD_RELOC_LO16;
! 	      c = my_getSmallExpression (&imm_expr, s);
! 	      if (c != S_EX_NONE)
! 		{
! 		  if (c != S_EX_LO)
! 		    {
! 		      if (c == S_EX_HI)
! 			{
! 			  *imm_reloc = BFD_RELOC_HI16_S;
! 			  imm_unmatched_hi = TRUE;
! 			}
! #ifdef OBJ_ELF
! 		      else if (c == S_EX_HIGHEST)
! 			*imm_reloc = BFD_RELOC_MIPS_HIGHEST;
! 		      else if (c == S_EX_HIGHER)
! 			*imm_reloc = BFD_RELOC_MIPS_HIGHER;
! 		      else if (c == S_EX_GP_REL)
! 			{
! 			  /* This occurs in NewABI only.  */
! 			  c = my_getSmallExpression (&imm_expr, s);
! 			  if (c != S_EX_NEG)
! 			    as_bad (_("bad composition of relocations"));
! 			  else
! 			    {
! 			      c = my_getSmallExpression (&imm_expr, s);
! 			      if (c != S_EX_LO)
! 				as_bad (_("bad composition of relocations"));
! 			      else
! 				{
! 				  imm_reloc[0] = BFD_RELOC_GPREL16;
! 				  imm_reloc[1] = BFD_RELOC_MIPS_SUB;
! 				  imm_reloc[2] = BFD_RELOC_LO16;
! 				}
! 			    }
! 			}
! #endif
! 		      else
! 			*imm_reloc = BFD_RELOC_HI16;
! 		    }
! 		  else if (imm_expr.X_op == O_constant)
! 		    imm_expr.X_add_number &= 0xffff;
! 		}
! 	      if (*args == 'i')
! 		{
! 		  if ((c == S_EX_NONE && imm_expr.X_op != O_constant)
! 		      || ((imm_expr.X_add_number < 0
! 			   || imm_expr.X_add_number >= 0x10000)
! 			  && imm_expr.X_op == O_constant))
! 		    {
! 		      if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
! 			  !strcmp (insn->name, insn[1].name))
! 			break;
! 		      if (imm_expr.X_op == O_constant
! 			  || imm_expr.X_op == O_big)
! 			as_bad (_("16 bit expression not in range 0..65535"));
! 		    }
! 		}
! 	      else
  		{
  		  int more;
! 		  offsetT max;
  
! 		  /* The upper bound should be 0x8000, but
! 		     unfortunately the MIPS assembler accepts numbers
! 		     from 0x8000 to 0xffff and sign extends them, and
! 		     we want to be compatible.  We only permit this
! 		     extended range for an instruction which does not
! 		     provide any further alternates, since those
! 		     alternates may handle other cases.  People should
! 		     use the numbers they mean, rather than relying on
! 		     a mysterious sign extension.  */
! 		  more = (insn + 1 < &mips_opcodes[NUMOPCODES] &&
! 			  strcmp (insn->name, insn[1].name) == 0);
! 		  if (more)
! 		    max = 0x8000;
  		  else
! 		    max = 0x10000;
! 		  if ((c == S_EX_NONE && imm_expr.X_op != O_constant)
! 		      || ((imm_expr.X_add_number < -0x8000
! 			   || imm_expr.X_add_number >= max)
! 			  && imm_expr.X_op == O_constant)
! 		      || (more
! 			  && imm_expr.X_add_number < 0
! 			  && HAVE_64BIT_GPRS
! 			  && imm_expr.X_unsigned
! 			  && sizeof (imm_expr.X_add_number) <= 4))
  		    {
  		      if (more)
  			break;
  		      if (imm_expr.X_op == O_constant
  			  || imm_expr.X_op == O_big)
! 			as_bad (_("16 bit expression not in range -32768..32767"));
  		    }
  		}
  	      s = expr_end;
  	      continue;
  
  	    case 'o':		/* 16 bit offset */
! 	      c = my_getSmallExpression (&offset_expr, s);
  
  	      /* If this value won't fit into a 16 bit offset, then go
  		 find a macro that will generate the 32 bit offset
  		 code pattern.  */
! 	      if (c == S_EX_NONE
  		  && (offset_expr.X_op != O_constant
  		      || offset_expr.X_add_number >= 0x8000
  		      || offset_expr.X_add_number < -0x8000))
  		break;
  
- 	      if (c == S_EX_HI)
- 		{
- 		  if (offset_expr.X_op != O_constant)
- 		    break;
- 		  offset_expr.X_add_number =
- 		    (offset_expr.X_add_number >> 16) & 0xffff;
- 		}
- 	      *offset_reloc = BFD_RELOC_LO16;
  	      s = expr_end;
  	      continue;
  
--- 9033,9102 ----
  	    case 'i':		/* 16 bit unsigned immediate */
  	    case 'j':		/* 16 bit signed immediate */
  	      *imm_reloc = BFD_RELOC_LO16;
! 	      if (my_getSmallExpression (&imm_expr, imm_reloc, s) == 0)
  		{
  		  int more;
! 		  offsetT minval, maxval;
  
! 		  more = (insn + 1 < &mips_opcodes[NUMOPCODES]
! 			  && strcmp (insn->name, insn[1].name) == 0);
! 
! 		  /* If the expression was written as an unsigned number,
! 		     only treat it as signed if there are no more
! 		     alternatives.  */
! 		  if (more
! 		      && *args == 'j'
! 		      && sizeof (imm_expr.X_add_number) <= 4
! 		      && imm_expr.X_op == O_constant
! 		      && imm_expr.X_add_number < 0
! 		      && imm_expr.X_unsigned
! 		      && HAVE_64BIT_GPRS)
! 		    break;
! 
! 		  /* For compatibility with older assemblers, we accept
! 		     0x8000-0xffff as signed 16-bit numbers when only
! 		     signed numbers are allowed.  */
! 		  if (*args == 'i')
! 		    minval = 0, maxval = 0xffff;
! 		  else if (more)
! 		    minval = -0x8000, maxval = 0x7fff;
  		  else
! 		    minval = -0x8000, maxval = 0xffff;
! 
! 		  if (imm_expr.X_op != O_constant
! 		      || imm_expr.X_add_number < minval
! 		      || imm_expr.X_add_number > maxval)
  		    {
  		      if (more)
  			break;
  		      if (imm_expr.X_op == O_constant
  			  || imm_expr.X_op == O_big)
! 			as_bad (_("expression out of range"));
  		    }
  		}
  	      s = expr_end;
  	      continue;
  
  	    case 'o':		/* 16 bit offset */
! 	      /* Check whether there is only a single bracketed expression
! 		 left.  If so, it must be the base register and the
! 		 constant must be zero.  */
! 	      if (*s == '(' && strchr (s + 1, '(') == 0)
! 		{
! 		  offset_expr.X_op = O_constant;
! 		  offset_expr.X_add_number = 0;
! 		  continue;
! 		}
  
  	      /* If this value won't fit into a 16 bit offset, then go
  		 find a macro that will generate the 32 bit offset
  		 code pattern.  */
! 	      if (my_getSmallExpression (&offset_expr, offset_reloc, s) == 0
  		  && (offset_expr.X_op != O_constant
  		      || offset_expr.X_add_number >= 0x8000
  		      || offset_expr.X_add_number < -0x8000))
  		break;
  
  	      s = expr_end;
  	      continue;
  
*************** mips_ip (str, ip)
*** 9191,9239 ****
  	      continue;
  
  	    case 'u':		/* upper 16 bits */
! 	      c = my_getSmallExpression (&imm_expr, s);
! 	      *imm_reloc = BFD_RELOC_LO16;
! 	      if (c != S_EX_NONE)
! 		{
! 		  if (c != S_EX_LO)
! 		    {
! 		      if (c == S_EX_HI)
! 			{
! 			  *imm_reloc = BFD_RELOC_HI16_S;
! 			  imm_unmatched_hi = TRUE;
! 			}
! #ifdef OBJ_ELF
! 		      else if (c == S_EX_HIGHEST)
! 			*imm_reloc = BFD_RELOC_MIPS_HIGHEST;
! 		      else if (c == S_EX_GP_REL)
! 			{
! 			  /* This occurs in NewABI only.  */
! 			  c = my_getSmallExpression (&imm_expr, s);
! 			  if (c != S_EX_NEG)
! 			    as_bad (_("bad composition of relocations"));
! 			  else
! 			    {
! 			      c = my_getSmallExpression (&imm_expr, s);
! 			      if (c != S_EX_HI)
! 				as_bad (_("bad composition of relocations"));
! 			      else
! 				{
! 				  imm_reloc[0] = BFD_RELOC_GPREL16;
! 				  imm_reloc[1] = BFD_RELOC_MIPS_SUB;
! 				  imm_reloc[2] = BFD_RELOC_HI16_S;
! 				}
! 			    }
! 			}
! #endif
! 		      else
! 			*imm_reloc = BFD_RELOC_HI16;
! 		    }
! 		  else if (imm_expr.X_op == O_constant)
! 		    imm_expr.X_add_number &= 0xffff;
! 		}
! 	      else if (imm_expr.X_op == O_constant
! 		       && (imm_expr.X_add_number < 0
! 			   || imm_expr.X_add_number >= 0x10000))
  		as_bad (_("lui expression not in range 0..65535"));
  	      s = expr_end;
  	      continue;
--- 9107,9116 ----
  	      continue;
  
  	    case 'u':		/* upper 16 bits */
! 	      if (my_getSmallExpression (&imm_expr, imm_reloc, s) == 0
! 		  && imm_expr.X_op == O_constant
! 		  && (imm_expr.X_add_number < 0
! 		      || imm_expr.X_add_number >= 0x10000))
  		as_bad (_("lui expression not in range 0..65535"));
  	      s = expr_end;
  	      continue;
*************** mips16_immed (file, line, type, val, war
*** 10070,10291 ****
      }
  }
  
! static struct percent_op_match
  {
!    const char *str;
!    const enum small_ex_type type;
  } percent_op[] =
  {
!   {"%lo", S_EX_LO},
  #ifdef OBJ_ELF
!   {"%call_hi", S_EX_CALL_HI},
!   {"%call_lo", S_EX_CALL_LO},
!   {"%call16", S_EX_CALL16},
!   {"%got_disp", S_EX_GOT_DISP},
!   {"%got_page", S_EX_GOT_PAGE},
!   {"%got_ofst", S_EX_GOT_OFST},
!   {"%got_hi", S_EX_GOT_HI},
!   {"%got_lo", S_EX_GOT_LO},
!   {"%got", S_EX_GOT},
!   {"%gp_rel", S_EX_GP_REL},
!   {"%half", S_EX_HALF},
!   {"%highest", S_EX_HIGHEST},
!   {"%higher", S_EX_HIGHER},
!   {"%neg", S_EX_NEG},
  #endif
!   {"%hi", S_EX_HI}
  };
  
- /* Parse small expression input.  STR gets adjusted to eat up whitespace.
-    It detects valid "%percent_op(...)" and "($reg)" strings.  Percent_op's
-    can be nested, this is handled by blanking the innermost, parsing the
-    rest by subsequent calls.  */
  
! static int
! my_getSmallParser (str, len, nestlevel)
       char **str;
!      unsigned int *len;
!      int *nestlevel;
  {
!   *len = 0;
!   *str += strspn (*str, " \t");
!   /* Check for expression in parentheses.  */
!   if (**str == '(')
!     {
!       char *b = *str + 1 + strspn (*str + 1, " \t");
!       char *e;
! 
!       /* Check for base register.  */
!       if (b[0] == '$')
! 	{
! 	  if (strchr (b, ')')
! 	      && (e = b + strcspn (b, ") \t"))
! 	      && e - b > 1 && e - b < 4)
! 	    {
! 	      if ((e - b == 3
! 		   && ((b[1] == 'f' && b[2] == 'p')
! 		       || (b[1] == 's' && b[2] == 'p')
! 		       || (b[1] == 'g' && b[2] == 'p')
! 		       || (b[1] == 'a' && b[2] == 't')
! 		       || (ISDIGIT (b[1])
! 			   && ISDIGIT (b[2]))))
! 		  || (ISDIGIT (b[1])))
! 		{
! 		  *len = strcspn (*str, ")") + 1;
! 		  return S_EX_REGISTER;
! 		}
! 	    }
! 	}
!       /* Check for percent_op (in parentheses).  */
!       else if (b[0] == '%')
! 	{
! 	  *str = b;
! 	  return my_getPercentOp (str, len, nestlevel);
! 	}
  
!       /* Some other expression in the parentheses, which can contain
! 	 parentheses itself. Attempt to find the matching one.  */
        {
! 	int pcnt = 1;
! 	char *s;
  
! 	*len = 1;
! 	for (s = *str + 1; *s && pcnt; s++, (*len)++)
  	  {
! 	    if (*s == '(')
! 	      ++pcnt;
! 	    else if (*s == ')')
! 	      --pcnt;
  	  }
        }
!     }
!   /* Check for percent_op (outside of parentheses).  */
!   else if (*str[0] == '%')
!     return my_getPercentOp (str, len, nestlevel);
! 
!   /* Any other expression.  */
!   return S_EX_NONE;
  }
  
- static int
- my_getPercentOp (str, len, nestlevel)
-      char **str;
-      unsigned int *len;
-      int *nestlevel;
- {
-   char *tmp = *str + 1;
-   unsigned int i = 0;
  
!   while (ISALPHA (*tmp) || *tmp == '_')
!     {
!       *tmp = TOLOWER (*tmp);
!       tmp++;
!     }
!   while (i < (sizeof (percent_op) / sizeof (struct percent_op_match)))
!     {
!       if (strncmp (*str, percent_op[i].str, strlen (percent_op[i].str)))
! 	i++;
!       else
! 	{
! 	  int type = percent_op[i].type;
! 
! 	  /* Only %hi and %lo are allowed for OldABI.  */
! 	  if (! HAVE_NEWABI && type != S_EX_HI && type != S_EX_LO)
! 	    return S_EX_NONE;
  
! 	  *len = strlen (percent_op[i].str);
! 	  ++(*nestlevel);
! 	  return type;
! 	}
!     }
!   return S_EX_NONE;
! }
  
! static int
! my_getSmallExpression (ep, str)
       expressionS *ep;
       char *str;
  {
!   static char *oldstr = NULL;
!   int c = S_EX_NONE;
!   int oldc;
!   int nestlevel = -1;
!   unsigned int len;
  
!   /* Don't update oldstr if the last call had nested percent_op's. We need
!      it to parse the outer ones later.  */
!   if (! oldstr)
!     oldstr = str;
  
!   do
      {
!       oldc = c;
!       c = my_getSmallParser (&str, &len, &nestlevel);
!       if (c != S_EX_NONE && c != S_EX_REGISTER)
! 	str += len;
      }
-   while (c != S_EX_NONE && c != S_EX_REGISTER);
- 
-   if (nestlevel >= 0)
-     {
-       /* A percent_op was encountered.  Don't try to get an expression if
- 	 it is already blanked out.  */
-       if (*(str + strspn (str + 1, " )")) != ')')
- 	{
- 	  char save;
  
! 	  /* Let my_getExpression() stop at the closing parenthesis.  */
! 	  save = *(str + len);
! 	  *(str + len) = '\0';
! 	  my_getExpression (ep, str);
! 	  *(str + len) = save;
! 	}
!       if (nestlevel > 0)
! 	{
! 	  /* Blank out including the % sign and the proper matching
! 	     parenthesis.  */
! 	  int pcnt = 1;
! 	  char *s = strrchr (oldstr, '%');
! 	  char *end;
  
! 	  for (end = strchr (s, '(') + 1; *end && pcnt; end++)
! 	    {
! 	      if (*end == '(')
! 		++pcnt;
! 	      else if (*end == ')')
! 		--pcnt;
! 	    }
  
! 	  memset (s, ' ', end - s);
! 	  str = oldstr;
! 	}
!       else
! 	expr_end = str + len;
  
!       c = oldc;
!     }
!   else if (c == S_EX_NONE)
!     {
!       my_getExpression (ep, str);
!     }
!   else if (c == S_EX_REGISTER)
!     {
!       ep->X_op = O_constant;
!       expr_end = str;
!       ep->X_add_symbol = NULL;
!       ep->X_op_symbol = NULL;
!       ep->X_add_number = 0;
!     }
!   else
!     {
!       as_fatal (_("internal error"));
!     }
  
!   if (nestlevel <= 0)
!     /* All percent_op's have been handled.  */
!     oldstr = NULL;
  
!   return c;
  }
  
  static void
--- 9947,10064 ----
      }
  }
  
! static const struct percent_op_match
  {
!   const char *str;
!   bfd_reloc_code_real_type reloc;
  } percent_op[] =
  {
!   {"%lo", BFD_RELOC_LO16},
  #ifdef OBJ_ELF
!   {"%call_hi", BFD_RELOC_MIPS_CALL_HI16},
!   {"%call_lo", BFD_RELOC_MIPS_CALL_LO16},
!   {"%call16", BFD_RELOC_MIPS_CALL16},
!   {"%got_disp", BFD_RELOC_MIPS_GOT_DISP},
!   {"%got_page", BFD_RELOC_MIPS_GOT_PAGE},
!   {"%got_ofst", BFD_RELOC_MIPS_GOT_OFST},
!   {"%got_hi", BFD_RELOC_MIPS_GOT_HI16},
!   {"%got_lo", BFD_RELOC_MIPS_GOT_LO16},
!   {"%got", BFD_RELOC_MIPS_GOT16},
!   {"%gp_rel", BFD_RELOC_GPREL16},
!   {"%half", BFD_RELOC_16},
!   {"%highest", BFD_RELOC_MIPS_HIGHEST},
!   {"%higher", BFD_RELOC_MIPS_HIGHER},
!   {"%neg", BFD_RELOC_MIPS_SUB},
  #endif
!   {"%hi", BFD_RELOC_HI16_S}
  };
  
  
! /* Return true if *STR points to a relocation operator.  When returning true,
!    move *STR over the operator and store its relocation code in *RELOC.
!    Leave both *STR and *RELOC alone when returning false.  */
! 
! static bfd_boolean
! parse_relocation (str, reloc)
       char **str;
!      bfd_reloc_code_real_type *reloc;
  {
!   size_t i;
  
!   for (i = 0; i < ARRAY_SIZE (percent_op); i++)
!     if (strncasecmp (*str, percent_op[i].str, strlen (percent_op[i].str)) == 0)
        {
! 	*str += strlen (percent_op[i].str);
! 	*reloc = percent_op[i].reloc;
  
! 	/* Check whether the output BFD supports this relocation.
! 	   If not, issue an error and fall back on something safe.  */
! 	if (!bfd_reloc_type_lookup (stdoutput, percent_op[i].reloc))
  	  {
! 	    as_bad ("relocation %s isn't supported by the current ABI",
! 		    percent_op[i].str);
! 	    *reloc = BFD_RELOC_LO16;
  	  }
+ 	return TRUE;
        }
!   return FALSE;
  }
  
  
! /* Parse string STR as a 16-bit relocatable operand.  Store the
!    expression in *EP and the relocations in the array starting
!    at RELOC.  Return the number of relocation operators used.
  
!    On exit, EXPR_END points to the first character after the expression.
!    If no relocation operators are used, RELOC[0] is set to BFD_RELOC_LO16.  */
  
! static size_t
! my_getSmallExpression (ep, reloc, str)
       expressionS *ep;
+      bfd_reloc_code_real_type *reloc;
       char *str;
  {
!   bfd_reloc_code_real_type reversed_reloc[3];
!   size_t reloc_index, i;
!   int bracket_depth;
  
!   reloc_index = 0;
!   bracket_depth = 0;
  
!   /* Search for the start of the main expression, recoding relocations
!      in REVERSED_RELOC.  */
!   for (;;)
      {
!       if (*str == '(')
! 	bracket_depth++, str++;
!       else if (*str == ' ' || *str == '\t')
! 	str++;
!       else if (*str == '%'
! 	       && reloc_index < (HAVE_NEWABI ? 3 : 1)
! 	       && parse_relocation (&str, &reversed_reloc[reloc_index]))
! 	reloc_index++;
!       else
! 	break;
      }
  
!   my_getExpression (ep, str);
!   str = expr_end;
  
!   /* Match every open bracket.  */
!   while (bracket_depth > 0 && (*str == ')' || *str == ' ' || *str == '\t'))
!     if (*str++ == ')')
!       bracket_depth--;
  
!   if (bracket_depth > 0)
!     as_bad ("unclosed '('");
  
!   expr_end = str;
  
!   reloc[0] = BFD_RELOC_LO16;
!   for (i = 0; i < reloc_index; i++)
!     reloc[i] = reversed_reloc[reloc_index - 1 - i];
  
!   return reloc_index;
  }
  
  static void
Index: testsuite/gas/mips/mips.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
retrieving revision 1.57
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.57 mips.exp
*** testsuite/gas/mips/mips.exp	31 Dec 2002 08:11:17 -0000	1.57
--- testsuite/gas/mips/mips.exp	26 Jan 2003 12:09:08 -0000
*************** if { [istarget mips*-*-*] } then {
*** 376,381 ****
--- 376,383 ----
      set ilocks [istarget mipstx39*-*-*]
      set gpr_ilocks [expr [istarget mipstx39*-*-*]]
      set addr32 [expr [istarget mipstx39*-*-*]]
+     set have_newabi [expr [istarget mips-*-irix6*] \
+ 			  || [istarget mips64*-*-linux*]]
  
      if { [istarget "mips*-*-*linux*"] } then {
  	set tmips "t"
*************** if { [istarget mips*-*-*] } then {
*** 601,606 ****
--- 603,614 ----
  	run_dump_test "elf-rel5"
  	run_dump_test "elf-rel6"
  	run_dump_test "elf-rel7"
+ 	run_dump_test "elf-rel8"
+ 	run_dump_test "elf-rel9"
+ 	if {$have_newabi} {
+ 	    run_dump_test "elf-rel10"
+ 	    run_dump_test "elf-rel11"
+ 	}
  	run_dump_test "${tmips}${el}empic"
  	run_dump_test "empic2"
  	run_dump_test "empic3_e"
*** /dev/null	Thu Apr 11 15:25:15 2002
--- testsuite/gas/mips/elf-rel8.d	Sat Jan 25 15:32:10 2003
***************
*** 0 ****
--- 1,57 ----
+ #as: -march=mips2 -mabi=32
+ #objdump: -M gpr-names=numeric -dr
+ #name: MIPS ELF reloc 8
+ 
+ .*:     file format .*
+ 
+ Disassembly of section \.text:
+ 
+ 0+00 <foo>:
+    0:	3c040000 	lui	\$4,0x0
+ 			0: R_MIPS_HI16	gvar
+    4:	24840000 	addiu	\$4,\$4,0
+ 			4: R_MIPS_LO16	gvar
+    8:	8ca40000 	lw	\$4,0\(\$5\)
+ 			8: R_MIPS_LO16	gvar
+    c:	8fc40002 	lw	\$4,2\(\$30\)
+   10:	3c040000 	lui	\$4,0x0
+ 			10: R_MIPS_CALL_HI16	gfunc
+   14:	009c2021 	addu	\$4,\$4,\$28
+   18:	8c990000 	lw	\$25,0\(\$4\)
+ 			18: R_MIPS_CALL_LO16	gfunc
+   1c:	3c040000 	lui	\$4,0x0
+ 			1c: R_MIPS_GOT_HI16	gvar
+   20:	009c2021 	addu	\$4,\$4,\$28
+   24:	8c850000 	lw	\$5,0\(\$4\)
+ 			24: R_MIPS_GOT_LO16	gvar
+   28:	8f840000 	lw	\$4,0\(\$28\)
+ 			28: R_MIPS_GOT16	\.data
+   2c:	a0850000 	sb	\$5,0\(\$4\)
+ 			2c: R_MIPS_LO16	\.data
+   30:	3c040000 	lui	\$4,0x0
+ 			30: R_MIPS_CALL_HI16	gfunc
+   34:	24840000 	addiu	\$4,\$4,0
+ 			34: R_MIPS_CALL_LO16	gfunc
+   38:	3c040000 	lui	\$4,0x0
+ 			38: R_MIPS_GOT_HI16	gvar
+   3c:	24840000 	addiu	\$4,\$4,0
+ 			3c: R_MIPS_GOT_LO16	gvar
+   40:	8f840000 	lw	\$4,0\(\$28\)
+ 			40: R_MIPS_GOT16	\.data
+   44:	24840000 	addiu	\$4,\$4,0
+ 			44: R_MIPS_LO16	\.data
+   48:	8f990000 	lw	\$25,0\(\$28\)
+ 			48: R_MIPS_CALL16	gfunc
+   4c:	27840000 	addiu	\$4,\$28,0
+ 			4c: R_MIPS_CALL16	gfunc
+   50:	8f840000 	lw	\$4,0\(\$28\)
+ 			50: R_MIPS_GOT_DISP	gvar
+   54:	27840000 	addiu	\$4,\$28,0
+ 			54: R_MIPS_GOT_DISP	gvar
+   58:	8f840000 	lw	\$4,0\(\$28\)
+ 			58: R_MIPS_GPREL16	gvar
+   5c:	af840000 	sw	\$4,0\(\$28\)
+ 			5c: R_MIPS_GPREL16	gvar
+   60:	27840000 	addiu	\$4,\$28,0
+ 			60: R_MIPS_GPREL16	gvar
+ 	\.\.\.
*** /dev/null	Thu Apr 11 15:25:15 2002
--- testsuite/gas/mips/elf-rel8.s	Sat Jan 25 17:01:55 2003
***************
*** 0 ****
--- 1,53 ----
+ 	.equ	$fprel, 2
+ 
+ 	.ent	foo
+ foo:
+ 	# Test various forms of relocation syntax.
+ 
+ 	lui	$4,(%hi gvar)
+ 	addiu	$4,$4,(%lo (gvar))
+ 	lw	$4,%lo gvar($5)
+ 
+ 	# Check that registers aren't confused with $ identifiers.
+ 
+ 	lw	$4,($fprel)($fp)
+ 
+ 	# Check various forms of paired relocations.
+ 
+ 	lui	$4,%call_hi(gfunc)
+ 	addu	$4,$4,$gp
+ 	lw	$25,%call_lo(gfunc)($4)
+ 
+ 	lui	$4,%got_hi(gvar)
+ 	addu	$4,$4,$gp
+ 	lw	$5,%got_lo(gvar)($4)
+ 
+ 	lw	$4,%got(lvar)($28)
+ 	sb	$5,%lo(lvar)($4)
+ 
+ 	lui	$4,%call_hi(gfunc)
+ 	addiu	$4,$4,%call_lo(gfunc)
+ 
+ 	lui	$4,%got_hi(gvar)
+ 	addiu	$4,$4,%got_lo(gvar)
+ 
+ 	lw	$4,%got(lvar)($28)
+ 	addiu	$4,$4,%lo(lvar)
+ 
+ 	# Check individual relocations.
+ 
+ 	lw	$25,%call16(gfunc)($28)
+ 	addiu	$4,$28,%call16(gfunc)
+ 
+ 	lw	$4,%got_disp(gvar)($28)
+ 	addiu	$4,$28,%got_disp(gvar)
+ 
+ 	lw	$4,%gp_rel(gvar)($28)
+ 	sw	$4,%gp_rel(gvar)($28)
+ 	addiu	$4,$28,%gp_rel(gvar)
+ 
+ 	.space	64
+ 	.end	foo
+ 
+ 	.data
+ lvar:	.word	1,2
*** /dev/null	Thu Apr 11 15:25:15 2002
--- testsuite/gas/mips/elf-rel9.d	Sat Jan 25 15:31:55 2003
***************
*** 0 ****
--- 1,68 ----
+ #as: -march=mips2 -mabi=32
+ #objdump: -M gpr-names=numeric -dr
+ #name: MIPS ELF reloc 9
+ 
+ .*:     file format .*
+ 
+ Disassembly of section \.text:
+ 
+ 0+00 <foo>:
+    0:	8f840000 	lw	\$4,0\(\$28\)
+ 			0: R_MIPS_GOT16	\.data
+    4:	24840010 	addiu	\$4,\$4,16
+ 			4: R_MIPS_LO16	\.data
+    8:	8f840000 	lw	\$4,0\(\$28\)
+ 			8: R_MIPS_GOT16	\.data
+    c:	24840020 	addiu	\$4,\$4,32
+ 			c: R_MIPS_LO16	\.data
+   10:	8f840000 	lw	\$4,0\(\$28\)
+ 			10: R_MIPS_GOT16	\.data
+   14:	24847ffc 	addiu	\$4,\$4,32764
+ 			14: R_MIPS_LO16	\.data
+   18:	8f840001 	lw	\$4,1\(\$28\)
+ 			18: R_MIPS_GOT16	\.data
+   1c:	24848000 	addiu	\$4,\$4,-32768
+ 			1c: R_MIPS_LO16	\.data
+   20:	8f840001 	lw	\$4,1\(\$28\)
+ 			20: R_MIPS_GOT16	\.data
+   24:	2484fffc 	addiu	\$4,\$4,-4
+ 			24: R_MIPS_LO16	\.data
+   28:	8f840001 	lw	\$4,1\(\$28\)
+ 			28: R_MIPS_GOT16	\.data
+   2c:	24840000 	addiu	\$4,\$4,0
+ 			2c: R_MIPS_LO16	\.data
+   30:	8f840002 	lw	\$4,2\(\$28\)
+ 			30: R_MIPS_GOT16	\.data
+   34:	24848010 	addiu	\$4,\$4,-32752
+ 			34: R_MIPS_LO16	\.data
+   38:	8f840002 	lw	\$4,2\(\$28\)
+ 			38: R_MIPS_GOT16	\.data
+   3c:	2484f000 	addiu	\$4,\$4,-4096
+ 			3c: R_MIPS_LO16	\.data
+   40:	8f840002 	lw	\$4,2\(\$28\)
+ 			40: R_MIPS_GOT16	\.data
+   44:	2484ffff 	addiu	\$4,\$4,-1
+ 			44: R_MIPS_LO16	\.data
+   48:	8f840002 	lw	\$4,2\(\$28\)
+ 			48: R_MIPS_GOT16	\.data
+   4c:	2484f100 	addiu	\$4,\$4,-3840
+ 			4c: R_MIPS_LO16	\.data
+   50:	8f840003 	lw	\$4,3\(\$28\)
+ 			50: R_MIPS_GOT16	\.data
+   54:	24841345 	addiu	\$4,\$4,4933
+ 			54: R_MIPS_LO16	\.data
+   58:	8f84c000 	lw	\$4,-16384\(\$28\)
+ 			58: R_MIPS_GPREL16	\.sdata\+0x4000
+   5c:	8f84c004 	lw	\$4,-16380\(\$28\)
+ 			5c: R_MIPS_GPREL16	\.sdata\+0x4000
+   60:	8f84c004 	lw	\$4,-16380\(\$28\)
+ 			60: R_MIPS_GPREL16	\.sdata\+0x4000
+   64:	8f84c008 	lw	\$4,-16376\(\$28\)
+ 			64: R_MIPS_GPREL16	\.sdata\+0x4000
+   68:	8f84c00c 	lw	\$4,-16372\(\$28\)
+ 			68: R_MIPS_GPREL16	\.sdata\+0x4000
+   6c:	8f84c014 	lw	\$4,-16364\(\$28\)
+ 			6c: R_MIPS_GPREL16	\.sdata\+0x4000
+   70:	8f84c018 	lw	\$4,-16360\(\$28\)
+ 			70: R_MIPS_GPREL16	\.sdata\+0x4000
+ 	\.\.\.
*** /dev/null	Thu Apr 11 15:25:15 2002
--- testsuite/gas/mips/elf-rel9.s	Sat Jan 25 14:42:36 2003
***************
*** 0 ****
--- 1,57 ----
+ 	.ent	foo
+ foo:
+ 	lw	$4,%got(l1)($28)
+ 	addiu	$4,$4,%lo(l1)
+ 
+ 	lw	$4,%got(l1 + 16)($28)
+ 	addiu	$4,$4,%lo(l1 + 16)
+ 
+ 	lw	$4,%got(l1 + 0x7fec)($28)
+ 	addiu	$4,$4,%lo(l1 + 0x7fec)
+ 
+ 	lw	$4,%got(l1 + 0x7ff0)($28)
+ 	addiu	$4,$4,%lo(l1 + 0x7ff0)
+ 
+ 	lw	$4,%got(l1 + 0xffec)($28)
+ 	addiu	$4,$4,%lo(l1 + 0xffec)
+ 
+ 	lw	$4,%got(l1 + 0xfff0)($28)
+ 	addiu	$4,$4,%lo(l1 + 0xfff0)
+ 
+ 	lw	$4,%got(l1 + 0x18000)($28)
+ 	addiu	$4,$4,%lo(l1 + 0x18000)
+ 
+ 	lw	$4,%got(l2)($28)
+ 	addiu	$4,$4,%lo(l2)
+ 
+ 	lw	$4,%got(l2 + 0xfff)($28)
+ 	addiu	$4,$4,%lo(l2 + 0xfff)
+ 
+ 	lw	$4,%got(l2 + 0x1000)($28)
+ 	addiu	$4,$4,%lo(l2 + 0x100)
+ 
+ 	lw	$4,%got(l2 + 0x12345)($28)
+ 	addiu	$4,$4,%lo(l2 + 0x12345)
+ 
+ 	lw	$4,%gp_rel(l3)($28)
+ 	lw	$4,%gp_rel(l3 + 4)($28)
+ 	lw	$4,%gp_rel(l4)($28)
+ 	lw	$4,%gp_rel(l4 + 4)($28)
+ 	lw	$4,%gp_rel(l5)($28)
+ 	lw	$4,%gp_rel(l5 + 8)($28)
+ 	lw	$4,%gp_rel(l5 + 12)($28)
+ 
+ 	.space	64
+ 	.end	foo
+ 
+ 	.data
+ 	.word	1,2,3,4
+ l1:	.word	4,5
+ 	.space	0x1f000 - 24
+ l2:	.word	7,8
+ 
+ 	.sdata
+ l3:	.word	1
+ l4:	.word	2
+ 	.word	3
+ l5:	.word	4
*** /dev/null	Thu Apr 11 15:25:15 2002
--- testsuite/gas/mips/elf-rel10.d	Sat Jan 25 20:29:39 2003
***************
*** 0 ****
--- 1,29 ----
+ #as: -march=mips3 -mabi=n32 -KPIC
+ #readelf: --relocs
+ #name: MIPS ELF reloc 10
+ 
+ Relocation section '\.rela\.text' at offset .* contains 22 entries:
+  *Offset * Info * Type * Sym\.Value * Sym\. Name \+ Addend
+ 0+0000 * 0+..07 * R_MIPS_GPREL16 * 0+0000 * foo \+ 0
+ 0+0000 * 0+0018 * R_MIPS_SUB * 0+0000
+ 0+0000 * 0+0005 * R_MIPS_HI16 * 0+0000
+ 0+0004 * 0+..07 * R_MIPS_GPREL16 * 0+0000 * foo \+ 0
+ 0+0004 * 0+0018 * R_MIPS_SUB * 0+0000
+ 0+0004 * 0+0006 * R_MIPS_LO16 * 0+0000
+ 0+000c * 0+..07 * R_MIPS_GPREL16 * 0+0000 * \.text \+ c
+ 0+000c * 0+0018 * R_MIPS_SUB * 0+0000
+ 0+000c * 0+0005 * R_MIPS_HI16 * 0+0000
+ 0+0010 * 0+..07 * R_MIPS_GPREL16 * 0+0000 * \.text \+ c
+ 0+0010 * 0+0018 * R_MIPS_SUB * 0+0000
+ 0+0010 * 0+0006 * R_MIPS_LO16 * 0+0000
+ 0+0018 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * foo \+ 0
+ 0+001c * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * foo \+ 0
+ 0+0020 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * foo \+ 1234
+ 0+0024 * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * foo \+ 1234
+ 0+0028 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * \.text \+ c
+ 0+002c * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * \.text \+ c
+ 0+0030 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * \.text \+ 33221d
+ 0+0034 * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * \.text \+ 33221d
+ 0+0038 * 0+..14 * R_MIPS_GOT_PAGE * 0+0000 * frob \+ 0
+ 0+003c * 0+..15 * R_MIPS_GOT_OFST * 0+0000 * frob \+ 0
+ #pass
*** /dev/null	Thu Apr 11 15:25:15 2002
--- testsuite/gas/mips/elf-rel10.s	Sat Jan 25 17:13:28 2003
***************
*** 0 ****
--- 1,31 ----
+ 	.globl	foo
+ 	.ent	foo
+ foo:
+ 	lui	$gp,%hi(%neg(%gp_rel(foo)))
+ 	addiu	$gp,$gp,%lo(%neg(%gp_rel(foo)))
+ 	daddu	$gp,$gp,$25
+ 	.end	foo
+ 
+ 	.ent	bar
+ bar:
+ 	lui	$gp,%hi(%neg(%gp_rel(bar)))
+ 	addiu	$gp,$gp,%lo(%neg(%gp_rel(bar)))
+ 	daddu	$gp,$gp,$25
+ 	.end	bar
+ 
+ 	.ent	frob
+ 	lw	$4,%got_page(foo)($gp)
+ 	addiu	$4,$4,%got_ofst(foo)
+ 
+ 	lw	$4,%got_page(foo + 0x1234)($gp)
+ 	addiu	$4,$4,%got_ofst(foo + 0x1234)
+ 
+ 	lw	$4,%got_page(bar)($gp)
+ 	addiu	$4,$4,%got_ofst(bar)
+ 
+ 	lw	$4,%got_page(bar + 0x332211)($gp)
+ 	addiu	$4,$4,%got_ofst(bar + 0x332211)
+ 
+ 	lw	$4,%got_page(frob)($gp)
+ 	addiu	$4,$4,%got_ofst(frob)
+ 	.end	frob
*** /dev/null	Thu Apr 11 15:25:15 2002
--- testsuite/gas/mips/elf-rel11.d	Sat Jan 25 21:54:02 2003
***************
*** 0 ****
--- 1,43 ----
+ #as: -march=mips3 -mabi=64
+ #readelf: --relocs
+ #name: MIPS ELF reloc 11
+ 
+ Relocation section '\.rela\.text' at offset .* contains 12 entries:
+  *Offset * Info * Type * Sym\. Value * Sym\. Name \+ Addend
+ 0+0000 * 0+..0000001d * R_MIPS_HIGHEST * 0+0000 * bar \+ 0
+  * Type2: R_MIPS_NONE *
+  * Type3: R_MIPS_NONE *
+ 0+0008 * 0+..0000001c * R_MIPS_HIGHER * 0+0000 * bar \+ 0
+  * Type2: R_MIPS_NONE *
+  * Type3: R_MIPS_NONE *
+ 0+0004 * 0+..00000005 * R_MIPS_HI16 * 0+0000 * bar \+ 0
+  * Type2: R_MIPS_NONE *
+  * Type3: R_MIPS_NONE *
+ 0+000c * 0+..00000006 * R_MIPS_LO16 * 0+0000 * bar \+ 0
+  * Type2: R_MIPS_NONE *
+  * Type3: R_MIPS_NONE *
+ 0+0018 * 0+..0000001d * R_MIPS_HIGHEST * 0+0000 * bar \+ 12345678
+  * Type2: R_MIPS_NONE *
+  * Type3: R_MIPS_NONE *
+ 0+0020 * 0+..0000001c * R_MIPS_HIGHER * 0+0000 * bar \+ 12345678
+  * Type2: R_MIPS_NONE *
+  * Type3: R_MIPS_NONE *
+ 0+001c * 0+..00000005 * R_MIPS_HI16 * 0+0000 * bar \+ 12345678
+  * Type2: R_MIPS_NONE *
+  * Type3: R_MIPS_NONE *
+ 0+0024 * 0+..00000006 * R_MIPS_LO16 * 0+0000 * bar \+ 12345678
+  * Type2: R_MIPS_NONE *
+  * Type3: R_MIPS_NONE *
+ 0+0030 * 0+..0000001d * R_MIPS_HIGHEST * 0+0000 * \.data \+ 10
+  * Type2: R_MIPS_NONE *
+  * Type3: R_MIPS_NONE *
+ 0+0034 * 0+..0000001c * R_MIPS_HIGHER * 0+0000 * \.data \+ 10
+  * Type2: R_MIPS_NONE *
+  * Type3: R_MIPS_NONE *
+ 0+003c * 0+..00000005 * R_MIPS_HI16 * 0+0000 * \.data \+ 10
+  * Type2: R_MIPS_NONE *
+  * Type3: R_MIPS_NONE *
+ 0+0044 * 0+..00000006 * R_MIPS_LO16 * 0+0000 * \.data \+ 10
+  * Type2: R_MIPS_NONE *
+  * Type3: R_MIPS_NONE *
+ #pass
*** /dev/null	Thu Apr 11 15:25:15 2002
--- testsuite/gas/mips/elf-rel11.s	Sat Jan 25 21:07:29 2003
***************
*** 0 ****
--- 1,27 ----
+ 	.ent	foo
+ foo:
+ 	lui	$4,%highest(bar)
+ 	lui	$5,%hi(bar)
+ 	daddiu	$4,$4,%higher(bar)
+ 	daddiu	$5,$5,%lo(bar)
+ 	dsll32	$4,$4,0
+ 	daddu	$4,$4,$5
+ 
+ 	lui	$4,%highest(bar + 0x12345678)
+ 	lui	$5,%hi(bar + 0x12345678)
+ 	daddiu	$4,$4,%higher(bar + 0x12345678)
+ 	daddiu	$5,$5,%lo(bar + 0x12345678)
+ 	dsll32	$4,$4,0
+ 	daddu	$4,$4,$5
+ 
+ 	lui	$4,%highest(l1)
+ 	daddiu	$4,$4,%higher(l1)
+ 	dsll	$4,$4,16
+ 	daddiu	$4,$4,%hi(l1)
+ 	dsll	$4,$4,16
+ 	lw	$4,%lo(l1)($4)
+ 	.end	foo
+ 
+ 	.data
+ 	.word	1,2,3,4
+ l1:	.word	4,5


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