This is the mail archive of the binutils@sourceware.cygnus.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]

[PATCH] vtentry fixes for elf32_sparc and a set fix, testsuite additions


Hi!

I found one bug where set 0xffff, %o1 was mis-assembled, so this patch fixes
it, plus it makes compiler happy when sizeof(bfd_vma) is 4 (this could
fix H.J.'s bug, at least elf32_sparc only Linux as works just fine).
Also, I realized vtentry/vtinherit support is broken for elf32_sparc, so
this patch should fix it. Plus I have added some tests to the testsuite.
BTW: elf64_sparc is completely missing vtentry/vtinherit support, but I
haven't seen any implementation of it for any 64bit elf, so I wonder if I
should hack in support for it.

1999-06-08  Jakub Jelinek  <jj@ultra.linux.cz>

        * gas/config/tc-sparc.c (synthetize_setuw, synthetize_setsw,
	synthetize_setx): New functions.
	(md_assemble): Broken the special cases into the above
	functions. Make compiler happy if sizeof(bfd_vma)==4.
	Fix sethi generated from set/setuw. If instructions have a relloc,
	always clear the fields to be relocated in the opcode.
	(sparc_ip): Remove special_case global variable.

	* gas/testsuite/gas/sparc/synth64.s: Add checks for
	single register signx/clruw.
	* gas/testsuite/gas/sparc/set64.s: Add tests for setuw and setsw
	synthetic instructions.
	* gas/testsuite/gas/sparc/prefetch.d: Add -64 as switch.
	* gas/testsuite/gas/sparc/rdpr.d: Ditto.
	* gas/testsuite/gas/sparc/wrpr.d: Ditto.
	* gas/testsuite/gas/sparc/synth64.d: Ditto, reflect synth64.s changes.
	* gas/testsuite/gas/sparc/reloc64.d: Add -64 as switch, be more
	tolerant, as current gas outputs %hi(0) and not %hi(0x0).
	* gas/testsuite/gas/sparc/set64.d: Add -64 as switch, reflect
	set64.s changes and optimizations for setx instruction.
	* gas/testsuite/gas/sparc/sparc.exp: Do sparc64*-*-* checks
	if it is any of the compiled-in targets.

	* bfd/elf64_sparc.c: Use R_SPARC_max_std instead of
	R_SPARC_max in the tests, because many relocations are not defined
	before GNU extensions. Otherwise the tests don't make much sense,
	as they don't catch 90% of the bad cases.
	* bfd/elf32_sparc.c: Ditto, fix R_SPARC_GNU_VTINHERIT and
	R_SPARC_GNU_VTENTRY handling. Now it finally passes testsuite
	with -32 (with the exception of objdump output in one of the tests
	showing the name of the section instead of the symbol at the
	beginning of it).
	* include/elf/sparc.h: Define R_SPARC_max_std.

--- ./gas/config/tc-sparc.c.jj4	Mon Jun  7 18:59:55 1999
+++ ./gas/config/tc-sparc.c	Tue Jun  8 19:03:24 1999
@@ -31,7 +31,7 @@
 
 static struct sparc_arch *lookup_arch PARAMS ((char *));
 static void init_default_arch PARAMS ((void));
-static void sparc_ip PARAMS ((char *, const struct sparc_opcode **));
+static int sparc_ip PARAMS ((char *, const struct sparc_opcode **));
 static int in_signed_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
 static int in_unsigned_range PARAMS ((bfd_vma, bfd_vma));
 static int in_bitfield_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
@@ -922,9 +922,6 @@ BSR (val, amount)
 /* For communication between sparc_ip and get_expression.  */
 static char *expr_end;
 
-/* For communication between md_assemble and sparc_ip.  */
-static int special_case;
-
 /* Values for `special_case'.
    Instructions that require wierd handling because they're longer than
    4 bytes.  */
@@ -949,6 +946,281 @@ static const struct sparc_opcode *last_i
 /* The assembled opcode of `last_insn'.  */
 static unsigned long last_opcode;
 
+/* Handle the set and setuw synthetic instructions.  */
+void
+synthetize_setuw (insn)
+     const struct sparc_opcode *insn;
+{
+  int need_hi22_p = 0;
+  int rd = (the_insn.opcode & RD (~0)) >> 25;
+
+  if (the_insn.exp.X_op == O_constant)
+    {
+      if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
+	{
+	  if (sizeof(offsetT) > 4
+	      && (the_insn.exp.X_add_number < 0
+		  || the_insn.exp.X_add_number > (offsetT) 0xffffffff))
+	    as_warn (_("set: number not in 0..4294967295 range"));
+	}
+      else
+	{
+	  if (sizeof(offsetT) > 4
+	      && (the_insn.exp.X_add_number < -(offsetT) 0x80000000
+		  || the_insn.exp.X_add_number > (offsetT) 0xffffffff))
+	    as_warn (_("set: number not in -2147483648..4294967295 range"));
+	  the_insn.exp.X_add_number = (int)the_insn.exp.X_add_number;
+	}
+    }
+
+  /* See if operand is absolute and small; skip sethi if so.  */
+  if (the_insn.exp.X_op != O_constant
+      || the_insn.exp.X_add_number >= (1 << 12)
+      || the_insn.exp.X_add_number < -(1 << 12))
+    {
+      the_insn.opcode = (SETHI_INSN | RD (rd)
+			 | ((the_insn.exp.X_add_number >> 10)
+			    & (the_insn.exp.X_op == O_constant ? 0x3fffff : 0)));
+      the_insn.reloc = (the_insn.exp.X_op != O_constant
+			? BFD_RELOC_HI22
+			: BFD_RELOC_NONE);
+      output_insn (insn, &the_insn);
+      need_hi22_p = 1;
+    }
+
+  /* See if operand has no low-order bits; skip OR if so.  */
+  if (the_insn.exp.X_op != O_constant
+      || (need_hi22_p && (the_insn.exp.X_add_number & 0x3FF) != 0)
+      || ! need_hi22_p)
+    {
+      the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (rd) : 0)
+			 | RD (rd) | IMMED
+			 | (the_insn.exp.X_add_number
+			    & (the_insn.exp.X_op != O_constant ? 0 :
+			       need_hi22_p ? 0x3ff : 0x1fff)));
+      the_insn.reloc = (the_insn.exp.X_op != O_constant
+			? BFD_RELOC_LO10
+			: BFD_RELOC_NONE);
+      output_insn (insn, &the_insn);
+    }
+}
+    
+/* Handle the setsw synthetic instruction.  */
+void
+synthetize_setsw (insn)
+     const struct sparc_opcode *insn;
+{
+  int low32, rd, opc;
+
+  rd = (the_insn.opcode & RD (~0)) >> 25;
+
+  if (the_insn.exp.X_op != O_constant)
+    {
+      synthetize_setuw (insn);
+
+      /* Need to sign extend it.  */
+      the_insn.opcode = (SRA_INSN | RS1 (rd) | RD (rd));
+      the_insn.reloc = BFD_RELOC_NONE;
+      output_insn (insn, &the_insn);
+      return;
+    }
+
+  if (sizeof(offsetT) > 4
+      && (the_insn.exp.X_add_number < -(offsetT) 0x80000000
+	  || the_insn.exp.X_add_number > (offsetT) 0xffffffff))
+    as_warn (_("setsw: number not in -2147483648..4294967295 range"));
+
+  low32 = the_insn.exp.X_add_number;	
+	      
+  if (low32 >= 0)
+    {
+      synthetize_setuw (insn);
+      return;
+    }
+
+  opc = OR_INSN;
+    
+  the_insn.reloc = BFD_RELOC_NONE;
+  /* See if operand is absolute and small; skip sethi if so.  */
+  if (low32 < -(1 << 12))
+    {
+      the_insn.opcode = (SETHI_INSN | RD (rd)
+			 | (((~the_insn.exp.X_add_number) >> 10) & 0x3fffff));
+      output_insn (insn, &the_insn);
+      low32 = 0x1c00 | (low32 & 0x3ff);
+      opc = RS1 (rd) | XOR_INSN;
+    }
+
+  the_insn.opcode = (opc | RD (rd) | IMMED
+		     | (low32 & 0x1fff));
+  output_insn (insn, &the_insn);
+}
+
+/* Handle the setsw synthetic instruction.  */
+void
+synthetize_setx (insn)
+     const struct sparc_opcode *insn;
+{
+  int upper32, lower32;
+  int tmpreg = (the_insn.opcode & RS1 (~0)) >> 14;
+  int dstreg = (the_insn.opcode & RD (~0)) >> 25;
+  int upper_dstreg;
+  int need_hh22_p = 0, need_hm10_p = 0, need_hi22_p = 0, need_lo10_p = 0;
+  int need_xor10_p = 0;
+    
+#define SIGNEXT32(x) ((((x) & 0xffffffff) ^ 0x80000000) - 0x80000000)
+  lower32 = SIGNEXT32 (the_insn.exp.X_add_number);
+  upper32 = SIGNEXT32 (BSR (the_insn.exp.X_add_number, 32));
+#undef SIGNEXT32
+
+  upper_dstreg = tmpreg;
+  /* The tmp reg should not be the dst reg.  */
+  if (tmpreg == dstreg)
+    as_warn (_("setx: temporary register same as destination register"));
+
+  /* ??? Obviously there are other optimizations we can do
+     (e.g. sethi+shift for 0x1f0000000) and perhaps we shouldn't be
+     doing some of these.  Later.  If you do change things, try to
+     change all of this to be table driven as well.  */
+  /* What to output depends on the number if it's constant.
+     Compute that first, then output what we've decided upon.  */
+  if (the_insn.exp.X_op != O_constant)
+    {
+      if (sparc_arch_size == 32)
+	{
+	  /* When arch size is 32, we want setx to be equivalent
+	     to setuw for anything but constants.  */
+	  the_insn.exp.X_add_number &= 0xffffffff;
+	  synthetize_setuw (insn);
+	  return;
+	}
+      need_hh22_p = need_hm10_p = need_hi22_p = need_lo10_p = 1;
+      lower32 = 0; upper32 = 0;
+    }
+  else
+    {
+      /* Reset X_add_number, we've extracted it as upper32/lower32.
+	 Otherwise fixup_segment will complain about not being able to
+	 write an 8 byte number in a 4 byte field.  */
+      the_insn.exp.X_add_number = 0;
+    
+      /* Only need hh22 if `or' insn can't handle constant.  */
+      if (upper32 < -(1 << 12) || upper32 >= (1 << 12))
+	need_hh22_p = 1;
+    
+      /* Does bottom part (after sethi) have bits?  */
+      if ((need_hh22_p && (upper32 & 0x3ff) != 0)
+	  /* No hh22, but does upper32 still have bits we can't set
+	     from lower32?  */
+	  || (! need_hh22_p && upper32 != 0 && upper32 != -1))
+	need_hm10_p = 1;
+    
+      /* If the lower half is all zero, we build the upper half directly
+	 into the dst reg.  */
+      if (lower32 != 0
+	  /* Need lower half if number is zero or 0xffffffff00000000.  */
+	  || (! need_hh22_p && ! need_hm10_p))
+	{
+	  /* No need for sethi if `or' insn can handle constant.  */
+	  if (lower32 < -(1 << 12) || lower32 >= (1 << 12)
+	      /* Note that we can't use a negative constant in the `or'
+		 insn unless the upper 32 bits are all ones.  */
+	      || (lower32 < 0 && upper32 != -1)
+	      || (lower32 >= 0 && upper32 == -1))
+	    need_hi22_p = 1;
+		      
+	  if (need_hi22_p && upper32 == -1)
+	    need_xor10_p = 1;
+
+	  /* Does bottom part (after sethi) have bits?  */
+	  else if ((need_hi22_p && (lower32 & 0x3ff) != 0)
+		   /* No sethi.  */
+		   || (! need_hi22_p && (lower32 & 0x1fff) != 0)
+		   /* Need `or' if we didn't set anything else.  */
+		   || (! need_hi22_p && ! need_hh22_p && ! need_hm10_p))
+	    need_lo10_p = 1;
+	}
+      else
+	/* Output directly to dst reg if lower 32 bits are all zero.  */
+	upper_dstreg = dstreg;
+    }
+    
+  if (!upper_dstreg && dstreg)
+    as_warn (_("setx: illegal temporary register g0"));
+
+  if (need_hh22_p)
+    {
+      the_insn.opcode = (SETHI_INSN | RD (upper_dstreg)
+			 | ((upper32 >> 10) & 0x3fffff));
+      the_insn.reloc = (the_insn.exp.X_op != O_constant
+			? BFD_RELOC_SPARC_HH22 : BFD_RELOC_NONE);
+      output_insn (insn, &the_insn);
+    }
+    
+  if (need_hi22_p)
+    {
+      the_insn.opcode = (SETHI_INSN | RD (dstreg)
+			 | (((need_xor10_p ? ~lower32 : lower32)
+			    >> 10) & 0x3fffff));
+      the_insn.reloc = (the_insn.exp.X_op != O_constant
+			? BFD_RELOC_SPARC_LM22 : BFD_RELOC_NONE);
+      output_insn (insn, &the_insn);
+    }
+
+  if (need_hm10_p)
+    {
+      the_insn.opcode = (OR_INSN
+			 | (need_hh22_p ? RS1 (upper_dstreg) : 0)
+			 | RD (upper_dstreg)
+			 | IMMED
+			 | (upper32 & (need_hh22_p ? 0x3ff : 0x1fff)));
+      the_insn.reloc = (the_insn.exp.X_op != O_constant
+			? BFD_RELOC_SPARC_HM10 : BFD_RELOC_NONE);
+      output_insn (insn, &the_insn);
+    }
+    
+  if (need_lo10_p)
+    {
+      /* FIXME: One nice optimization to do here is to OR the low part
+	 with the highpart if hi22 isn't needed and the low part is
+	 positive.  */
+      the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (dstreg) : 0)
+			 | RD (dstreg)
+			 | IMMED
+			 | (lower32 & (need_hi22_p ? 0x3ff : 0x1fff)));
+      the_insn.reloc = (the_insn.exp.X_op != O_constant
+			? BFD_RELOC_LO10 : BFD_RELOC_NONE);
+      output_insn (insn, &the_insn);
+    }
+    
+  /* If we needed to build the upper part, shift it into place.  */
+  if (need_hh22_p || need_hm10_p)
+    {
+      the_insn.opcode = (SLLX_INSN | RS1 (upper_dstreg) | RD (upper_dstreg)
+			 | IMMED | 32);
+      the_insn.reloc = BFD_RELOC_NONE;
+      output_insn (insn, &the_insn);
+    }
+    
+  /* To get -1 in upper32, we do sethi %hi(~x), r; xor r, -0x400 | x, r.  */
+  if (need_xor10_p)
+    {
+      the_insn.opcode = (XOR_INSN | RS1 (dstreg) | RD (dstreg) | IMMED
+			 | 0x1c00 | (lower32 & 0x3ff));
+      the_insn.reloc = BFD_RELOC_NONE;
+      output_insn (insn, &the_insn);
+    }
+
+  /* If we needed to build both upper and lower parts, OR them together.  */
+  else if ((need_hh22_p || need_hm10_p) && (need_hi22_p || need_lo10_p))
+    {
+      the_insn.opcode = (OR_INSN | RS1 (dstreg) | RS2 (upper_dstreg)
+			 | RD (dstreg));
+      the_insn.reloc = BFD_RELOC_NONE;
+      output_insn (insn, &the_insn);
+    }
+}
+
 /* Main entry point to assemble one instruction.  */
 
 void
@@ -956,10 +1228,10 @@ md_assemble (str)
      char *str;
 {
   const struct sparc_opcode *insn;
+  int special_case;
 
   know (str);
-  special_case = SPECIAL_CASE_NONE;
-  sparc_ip (str, &insn);
+  special_case = sparc_ip (str, &insn);
 
   /* We warn about attempts to put a floating point branch in a delay slot,
      unless the delay slot has been annulled.  */
@@ -990,301 +1262,50 @@ md_assemble (str)
       as_warn (_("FP branch preceded by FP instruction; NOP inserted"));
     }
 
-  for (;;)
-    {    
-      switch (special_case)
-	{
-	case SPECIAL_CASE_NONE:
-	  /* normal insn */
-	  output_insn (insn, &the_insn);
-	  return;
-
-	case SPECIAL_CASE_SETSW:
-	  if (the_insn.exp.X_op == O_constant)
-	    {
-	      int low32;
-	      if (the_insn.exp.X_add_number < -(offsetT)0x80000000
-		  || the_insn.exp.X_add_number > (offsetT) 0xffffffff)
-		as_warn (_("setsw: number not in -2147483648..4294967295 range"));
-
-	      low32 = the_insn.exp.X_add_number;	
-	      
-	      if (low32 < 0)
-		{
-		  int rd = (the_insn.opcode & RD (~0)) >> 25;
-		  int opc = OR_INSN;
-    
-		  the_insn.reloc = BFD_RELOC_NONE;
-		  /* See if operand is absolute and small; skip sethi if so.  */
-		  if (low32 < -(1 << 12))
-		    {
-		      the_insn.opcode = (SETHI_INSN | RD (rd)
-					| (((~the_insn.exp.X_add_number) >> 10) & 0x3fffff));
-		      output_insn (insn, &the_insn);
-		      low32 = 0x1c00 | (low32 & 0x3ff);
-		      opc = RS1 (rd) | XOR_INSN;
-		    }
-
-		  the_insn.opcode = (opc | RD (rd) | IMMED
-				     | (low32 & 0x1fff));
-		  output_insn (insn, &the_insn);
-		  return;
-		}
-	    }
-	  /* FALLTHROUGH */
-    
-	case SPECIAL_CASE_SET:
-	  {
-	    int need_hi22_p = 0;
-	    int rd = (the_insn.opcode & RD (~0)) >> 25;
-
-	    if (the_insn.exp.X_op == O_constant)
-	      {
-		if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
-		  {
-		    if (the_insn.exp.X_add_number < 0
-			|| the_insn.exp.X_add_number > (offsetT) 0xffffffff)
-		      as_warn (_("set: number not in 0..4294967295 range"));
-		  }
-		else
-		  {
-		    if (the_insn.exp.X_add_number < (offsetT)-0x80000000
-			|| the_insn.exp.X_add_number > (offsetT) 0xffffffff)
-		      as_warn (_("set: number not in -2147483648..4294967295 range"));
-		    if (the_insn.exp.X_add_number >= (offsetT)0x80000000)
-		      the_insn.exp.X_add_number -= (offsetT)0x100000000;
-		  }
-	      }
-    
-	    /* See if operand is absolute and small; skip sethi if so.  */
-	    if (the_insn.exp.X_op != O_constant
-		|| the_insn.exp.X_add_number >= (1 << 12)
-		|| the_insn.exp.X_add_number < -(1 << 12))
-	      {
-		the_insn.opcode = (SETHI_INSN | RD (rd)
-				   | ((the_insn.exp.X_add_number >> 10)
-				      & the_insn.exp.X_op == O_constant ? 0x3fffff : 0));
-		the_insn.reloc = BFD_RELOC_HI22;
-		output_insn (insn, &the_insn);
-		need_hi22_p = 1;
-	      }
-
-	    /* See if operand has no low-order bits; skip OR if so.  */
-	    if (the_insn.exp.X_op != O_constant
-		|| (need_hi22_p && (the_insn.exp.X_add_number & 0x3FF) != 0)
-		|| ! need_hi22_p)
-	      {
-		the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (rd) : 0)
-				   | RD (rd)
-				   | IMMED
-				   | (the_insn.exp.X_add_number
-				      & (the_insn.exp.X_op != O_constant ? 0 :
-					 need_hi22_p ? 0x3ff : 0x1fff)));
-		the_insn.reloc = (the_insn.exp.X_op != O_constant
-				  ? BFD_RELOC_LO10
-				  : BFD_RELOC_NONE);
-		output_insn (insn, &the_insn);
-	      }
+  switch (special_case)
+    {
+    case SPECIAL_CASE_NONE:
+      /* normal insn */
+      output_insn (insn, &the_insn);
+      break;
 
-	    if (special_case == SPECIAL_CASE_SETSW
-		&& the_insn.exp.X_op != O_constant)
-	      {
-	        /* Need to sign extend it.  */
-		the_insn.opcode = (SRA_INSN | RS1 (rd) | RD (rd));
-		the_insn.reloc = BFD_RELOC_NONE;
-		output_insn (insn, &the_insn);
-	      }
-	    return;
-	  }
-    
-	case SPECIAL_CASE_SETX:
-	  {
-	    int upper32, lower32;
-	    int tmpreg = (the_insn.opcode & RS1 (~0)) >> 14;
-	    int dstreg = (the_insn.opcode & RD (~0)) >> 25;
-	    int upper_dstreg;
-	    int need_hh22_p = 0, need_hm10_p = 0, need_hi22_p = 0, need_lo10_p = 0;
-	    int need_xor10_p = 0;
-    
-    #define SIGNEXT32(x) ((((x) & 0xffffffff) ^ 0x80000000) - 0x80000000)
-	    lower32 = SIGNEXT32 (the_insn.exp.X_add_number);
-	    upper32 = SIGNEXT32 (BSR (the_insn.exp.X_add_number, 32));
-    #undef SIGNEXT32
-
-	    upper_dstreg = tmpreg;
-	    /* The tmp reg should not be the dst reg.  */
-	    if (tmpreg == dstreg)
-	      as_warn (_("setx: temporary register same as destination register"));
-
-	    /* ??? Obviously there are other optimizations we can do
-	       (e.g. sethi+shift for 0x1f0000000) and perhaps we shouldn't be
-	       doing some of these.  Later.  If you do change things, try to
-	       change all of this to be table driven as well.  */
-    
-	    /* What to output depends on the number if it's constant.
-	       Compute that first, then output what we've decided upon.  */
-	    if (the_insn.exp.X_op != O_constant)
-	      {
-		if (sparc_arch_size == 32)
-		  {
-		    /* When arch size is 32, we want setx to be equivalent
-		       to setuw for anything but constants.  */
-		    the_insn.exp.X_add_number &= 0xffffffff;
-		    special_case = SPECIAL_CASE_SET;
-		    continue;
-		  }
-		need_hh22_p = need_hm10_p = need_hi22_p = need_lo10_p = 1;
-		lower32 = 0; upper32 = 0;
-	      }
-	    else
-	      {
-		/* Reset X_add_number, we've extracted it as upper32/lower32.
-		   Otherwise fixup_segment will complain about not being able to
-		   write an 8 byte number in a 4 byte field.  */
-		the_insn.exp.X_add_number = 0;
-    
-		/* Only need hh22 if `or' insn can't handle constant.  */
-		if (upper32 < -(1 << 12) || upper32 >= (1 << 12))
-		  need_hh22_p = 1;
-    
-		/* Does bottom part (after sethi) have bits?  */
-		if ((need_hh22_p && (upper32 & 0x3ff) != 0)
-		    /* No hh22, but does upper32 still have bits we can't set
-		       from lower32?  */
-		    || (! need_hh22_p && upper32 != 0 && upper32 != -1))
-		  need_hm10_p = 1;
-    
-		/* If the lower half is all zero, we build the upper half directly
-		   into the dst reg.  */
-		if (lower32 != 0
-		    /* Need lower half if number is zero or 0xffffffff00000000.  */
-		    || (! need_hh22_p && ! need_hm10_p))
-		  {
-		    /* No need for sethi if `or' insn can handle constant.  */
-		    if (lower32 < -(1 << 12) || lower32 >= (1 << 12)
-			/* Note that we can't use a negative constant in the `or'
-			   insn unless the upper 32 bits are all ones.  */
-			|| (lower32 < 0 && upper32 != -1)
-			|| (lower32 >= 0 && upper32 == -1))
-		      need_hi22_p = 1;
-		      
-		    if (need_hi22_p && upper32 == -1)
-		      need_xor10_p = 1;
-		    /* Does bottom part (after sethi) have bits?  */
-		    else if ((need_hi22_p && (lower32 & 0x3ff) != 0)
-			/* No sethi.  */
-			|| (! need_hi22_p && (lower32 & 0x1fff) != 0)
-			/* Need `or' if we didn't set anything else.  */
-			|| (! need_hi22_p && ! need_hh22_p && ! need_hm10_p))
-		      need_lo10_p = 1;
-		  }
-		else
-		  /* Output directly to dst reg if lower 32 bits are all
-		     zero.  */
-		  upper_dstreg = dstreg;
-	      }
-    
-	    if (need_hh22_p)
-	      {
-		the_insn.opcode = (SETHI_INSN | RD (upper_dstreg)
-				   | ((upper32 >> 10) & 0x3fffff));
-		the_insn.reloc = (the_insn.exp.X_op != O_constant
-				  ? BFD_RELOC_SPARC_HH22 : BFD_RELOC_NONE);
-		output_insn (insn, &the_insn);
-	      }
-    
-	    if (need_hi22_p)
-	      {
-		the_insn.opcode = (SETHI_INSN | RD (dstreg)
-				   | (((need_xor10_p ? ~lower32 : lower32)
-				       >> 10) & 0x3fffff));
-		the_insn.reloc = (the_insn.exp.X_op != O_constant
-				  ? BFD_RELOC_SPARC_LM22 : BFD_RELOC_NONE);
-		output_insn (insn, &the_insn);
-	      }
+    case SPECIAL_CASE_SETSW:
+      synthetize_setsw (insn);
+      break;
+	  
+    case SPECIAL_CASE_SET:
+      synthetize_setuw (insn);
+      break;
 
-	    if (need_hm10_p)
-	      {
-		the_insn.opcode = (OR_INSN
-				   | (need_hh22_p ? RS1 (upper_dstreg) : 0)
-				   | RD (upper_dstreg)
-				   | IMMED
-				   | (upper32
-				      & (need_hh22_p ? 0x3ff : 0x1fff)));
-		the_insn.reloc = (the_insn.exp.X_op != O_constant
-				  ? BFD_RELOC_SPARC_HM10 : BFD_RELOC_NONE);
-		output_insn (insn, &the_insn);
-	      }
-    
-	    if (need_lo10_p)
-	      {
-		/* FIXME: One nice optimization to do here is to OR the low part
-		   with the highpart if hi22 isn't needed and the low part is
-		   positive.  */
-		the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (dstreg) : 0)
-				   | RD (dstreg)
-				   | IMMED
-				   | (lower32
-				      & (need_hi22_p ? 0x3ff : 0x1fff)));
-		the_insn.reloc = BFD_RELOC_LO10;
-		output_insn (insn, &the_insn);
-	      }
-    
-	    /* If we needed to build the upper part, shift it into place.  */
-	    if (need_hh22_p || need_hm10_p)
-	      {
-		the_insn.opcode = (SLLX_INSN | RS1 (upper_dstreg) | RD (upper_dstreg)
-				   | IMMED | 32);
-		the_insn.reloc = BFD_RELOC_NONE;
-		output_insn (insn, &the_insn);
-	      }
-    
-	    /* To get -1 in upper32, we do sethi %hi(~x), r; xor r, -0x400 | x, r.  */
-	    if (need_xor10_p)
-	      {
-		the_insn.opcode = (XOR_INSN | RS1 (dstreg) | RD (dstreg) | IMMED
-				   | 0x1c00 | (lower32 & 0x3ff));
-		the_insn.reloc = BFD_RELOC_NONE;
-		output_insn (insn, &the_insn);
-	      }
-	    /* If we needed to build both upper and lower parts, OR them together.  */
-	    else if ((need_hh22_p || need_hm10_p)
-		     && (need_hi22_p || need_lo10_p))
-	      {
-		the_insn.opcode = (OR_INSN | RS1 (dstreg) | RS2 (upper_dstreg)
-				   | RD (dstreg));
-		the_insn.reloc = BFD_RELOC_NONE;
-		output_insn (insn, &the_insn);
-	      }
-	    return;
-	  }
-    
-	case SPECIAL_CASE_FDIV:
-	  {
-	    int rd = (the_insn.opcode >> 25) & 0x1f;
+    case SPECIAL_CASE_SETX:
+      synthetize_setx (insn);
+      break;
+      
+    case SPECIAL_CASE_FDIV:
+      {
+	int rd = (the_insn.opcode >> 25) & 0x1f;
     
-	    output_insn (insn, &the_insn);
+	output_insn (insn, &the_insn);
     
-	    /* According to information leaked from Sun, the "fdiv" instructions
-	       on early SPARC machines would produce incorrect results sometimes.
-	       The workaround is to add an fmovs of the destination register to
-	       itself just after the instruction.  This was true on machines
-	       with Weitek 1165 float chips, such as the Sun-4/260 and /280. */
-	    assert (the_insn.reloc == BFD_RELOC_NONE);
-	    the_insn.opcode = FMOVS_INSN | rd | RD (rd);
-	    output_insn (insn, &the_insn);
-	    return;
-	  }
+	/* According to information leaked from Sun, the "fdiv" instructions
+	   on early SPARC machines would produce incorrect results sometimes.
+	   The workaround is to add an fmovs of the destination register to
+	   itself just after the instruction.  This was true on machines
+	   with Weitek 1165 float chips, such as the Sun-4/260 and /280. */
+	assert (the_insn.reloc == BFD_RELOC_NONE);
+	the_insn.opcode = FMOVS_INSN | rd | RD (rd);
+	output_insn (insn, &the_insn);
+	return;
+      }
     
-	default:
-	  as_fatal (_("failed special case insn sanity check"));
-	}
+    default:
+      as_fatal (_("failed special case insn sanity check"));
     }
 }
 
 /* Subroutine of md_assemble to do the actual parsing.  */
 
-static void
+static int
 sparc_ip (str, pinsn)
      char *str;
      const struct sparc_opcode **pinsn;
@@ -1300,6 +1321,7 @@ sparc_ip (str, pinsn)
   int match = 0;
   int comma = 0;
   int v9_arg_p;
+  int special_case = SPECIAL_CASE_NONE;
 
   s = str;
   if (islower ((unsigned char) *s))
@@ -1331,7 +1353,7 @@ sparc_ip (str, pinsn)
   if (insn == NULL)
     {
       as_bad (_("Unknown opcode: `%s'"), str);
-      return;
+      return special_case;
     }
   if (comma)
     {
@@ -2066,7 +2088,7 @@ sparc_ip (str, pinsn)
 		    if (s[o->len + 1] != '(')
 		      {
 			as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);
-			return;
+			return special_case;
 		      }
 
 		    op_arg = o->name;
@@ -2102,7 +2124,7 @@ sparc_ip (str, pinsn)
 		    if (*s1 != ')')
 		      {
 			as_bad (_("Illegal operands: %%%s requires arguments in ()"), op_arg);
-			return;
+			return special_case;
 		      }
 		    
 		    *s1 = '\0';
@@ -2114,7 +2136,7 @@ sparc_ip (str, pinsn)
 		    if (*s != '+' && *s != '-')
 		      {
 			as_bad (_("Illegal operands: Can't do arithmetics other than + and - involving %%%s()"), op_arg);
-			return;
+			return special_case;
 		      }
 		    *s1 = '0';
 		    s = s1;
@@ -2217,7 +2239,7 @@ sparc_ip (str, pinsn)
 		    else if (the_insn.exp2.X_op != O_constant)
 		      {
 			as_bad (_("Illegal operands: Can't add non-constant expression to %%%s()"), op_arg);
-			return;
+			return special_case;
 		      }
 		    else
 		      {
@@ -2227,7 +2249,7 @@ sparc_ip (str, pinsn)
 			    || sparc_pic_code)
 			  {
 			    as_bad (_("Illegal operands: Can't do arithmetics involving %%%s() of a relocatable symbol"), op_arg);
-			    return;
+			    return special_case;
 			  }
 			the_insn.reloc = BFD_RELOC_SPARC_OLO10;
 		      }
@@ -2441,7 +2463,7 @@ sparc_ip (str, pinsn)
 	  else
 	    {
 	      as_bad (_("Illegal operands%s"), error_message);
-	      return;
+	      return special_case;
 	    }
 	}
       else
@@ -2509,7 +2531,7 @@ sparc_ip (str, pinsn)
 	      as_tsktsk (_(" (Requires %s; requested architecture is %s.)"),
 			 required_archs,
 			 sparc_opcode_archs[max_architecture].name);
-	      return;
+	      return special_case;
 	    }
 	} /* if no match */
 
@@ -2517,6 +2539,7 @@ sparc_ip (str, pinsn)
     } /* forever looking for a match */
 
   the_insn.opcode = opcode;
+  return special_case;
 }
 
 /* Parse an argument that can be expressed as a keyword.
--- ./gas/testsuite/gas/sparc/prefetch.d.jj4	Thu Apr 22 10:12:08 1999
+++ ./gas/testsuite/gas/sparc/prefetch.d	Tue Jun  8 16:20:15 1999
@@ -1,4 +1,4 @@
-#as: -Av9
+#as: -64 -Av9
 #objdump: -dr
 #name: sparc64 prefetch
 
--- ./gas/testsuite/gas/sparc/rdpr.d.jj4	Thu Apr 22 10:12:08 1999
+++ ./gas/testsuite/gas/sparc/rdpr.d	Tue Jun  8 16:20:28 1999
@@ -1,4 +1,4 @@
-#as: -Av9
+#as: -64 -Av9
 #objdump: -dr
 #name: sparc64 rdpr
 
--- ./gas/testsuite/gas/sparc/reloc64.d.jj4	Thu Apr 22 10:12:08 1999
+++ ./gas/testsuite/gas/sparc/reloc64.d	Tue Jun  8 17:10:55 1999
@@ -1,4 +1,4 @@
-#as: -Av9
+#as: -64 -Av9
 #objdump: -dr
 #name: sparc64 reloc64
 
@@ -10,12 +10,12 @@ Disassembly of section .text:
    0:	03 04 8d 15 	sethi  %hi\(0x12345400\), %g1
    4:	82 10 62 78 	or  %g1, 0x278, %g1.*
    8:	01 00 00 00 	nop 
-   c:	03 00 00 00 	sethi  %hi\(0x0\), %g1
+   c:	03 00 00 00 	sethi  %hi\((0x|)0\), %g1
 			c: R_SPARC_HH22	.text
   10:	82 10 60 00 	mov  %g1, %g1	! 0 <foo>
 			10: R_SPARC_HM10	.text
   14:	01 00 00 00 	nop 
-  18:	03 00 00 00 	sethi  %hi\(0x0\), %g1
+  18:	03 00 00 00 	sethi  %hi\((0x|)0\), %g1
 			18: R_SPARC_HH22	.text\+0x1234567800000000
   1c:	82 10 60 00 	mov  %g1, %g1	! 0 <foo>
 			1c: R_SPARC_HM10	.text\+0x1234567800000000
@@ -25,20 +25,20 @@ Disassembly of section .text:
   2c:	05 1d 95 0c 	sethi  %hi\(0x76543000\), %g2
   30:	84 10 62 10 	or  %g1, 0x210, %g2
   34:	01 00 00 00 	nop 
-  38:	03 00 00 00 	sethi  %hi\(0x0\), %g1
+  38:	03 00 00 00 	sethi  %hi\((0x|)0\), %g1
 			38: R_SPARC_HH22	.text
   3c:	82 10 60 00 	mov  %g1, %g1	! 0 <foo>
 			3c: R_SPARC_HM10	.text
-  40:	05 00 00 00 	sethi  %hi\(0x0\), %g2
+  40:	05 00 00 00 	sethi  %hi\((0x|)0\), %g2
 			40: R_SPARC_LM22	.text
   44:	84 10 60 00 	mov  %g1, %g2
 			44: R_SPARC_LO10	.text
   48:	01 00 00 00 	nop 
-  4c:	03 00 00 00 	sethi  %hi\(0x0\), %g1
+  4c:	03 00 00 00 	sethi  %hi\((0x|)0\), %g1
 			4c: R_SPARC_HH22	.text\+0xfedcba9876543210
   50:	82 10 60 00 	mov  %g1, %g1	! 0 <foo>
 			50: R_SPARC_HM10	.text\+0xfedcba9876543210
-  54:	05 00 00 00 	sethi  %hi\(0x0\), %g2
+  54:	05 00 00 00 	sethi  %hi\((0x|)0\), %g2
 			54: R_SPARC_LM22	.text\+0xfedcba9876543210
   58:	84 10 60 00 	mov  %g1, %g2
 			58: R_SPARC_LO10	.text\+0xfedcba9876543210
@@ -47,14 +47,14 @@ Disassembly of section .text:
   64:	82 10 61 43 	or  %g1, 0x143, %g1.*
   68:	82 10 62 10 	or  %g1, 0x210, %g1
   6c:	01 00 00 00 	nop 
-  70:	03 00 00 00 	sethi  %hi\(0x0\), %g1
+  70:	03 00 00 00 	sethi  %hi\((0x|)0\), %g1
 			70: R_SPARC_H44	.text
   74:	82 10 60 00 	mov  %g1, %g1	! 0 <foo>
 			74: R_SPARC_M44	.text
   78:	82 10 60 00 	mov  %g1, %g1
 			78: R_SPARC_L44	.text
   7c:	01 00 00 00 	nop 
-  80:	03 00 00 00 	sethi  %hi\(0x0\), %g1
+  80:	03 00 00 00 	sethi  %hi\((0x|)0\), %g1
 			80: R_SPARC_H44	.text\+0xa9876543210
   84:	82 10 60 00 	mov  %g1, %g1	! 0 <foo>
 			84: R_SPARC_M44	.text\+0xa9876543210
@@ -64,12 +64,12 @@ Disassembly of section .text:
   90:	03 22 6a f3 	sethi  %hi\(0x89abcc00\), %g1
   94:	82 18 7e 10 	xor  %g1, -496, %g1
   98:	01 00 00 00 	nop 
-  9c:	03 00 00 00 	sethi  %hi\(0x0\), %g1
+  9c:	03 00 00 00 	sethi  %hi\((0x|)0\), %g1
 			9c: R_SPARC_HIX22	.text
   a0:	82 18 60 00 	xor  %g1, 0, %g1
 			a0: R_SPARC_LOX10	.text
   a4:	01 00 00 00 	nop 
-  a8:	03 00 00 00 	sethi  %hi\(0x0\), %g1
+  a8:	03 00 00 00 	sethi  %hi\((0x|)0\), %g1
 			a8: R_SPARC_HIX22	.text\+0xffffffff76543210
   ac:	82 18 60 00 	xor  %g1, 0, %g1
 			ac: R_SPARC_LOX10	.text\+0xffffffff76543210
--- ./gas/testsuite/gas/sparc/set64.d.jj4	Thu Apr 22 10:12:08 1999
+++ ./gas/testsuite/gas/sparc/set64.d	Tue Jun  8 18:09:51 1999
@@ -1,4 +1,4 @@
-#as: -Av9
+#as: -64 -Av9
 #objdump: -dr
 #name: sparc64 set64
 
@@ -7,22 +7,22 @@
 Disassembly of section .text:
 
 0+ <foo>:
-   0:	05 00 00 00 	sethi  %hi\(0x0\), %g2
+   0:	05 00 00 00 	sethi  %hi\((0x|)0\), %g2
 			0: R_SPARC_HI22	.text
    4:	84 10 a0 00 	mov  %g2, %g2	! 0 <foo>
 			4: R_SPARC_LO10	.text
    8:	07 1d 95 0c 	sethi  %hi\(0x76543000\), %g3
-   c:	86 10 e2 10 	or  %g3, 0x210, %g3	! 76543210 <\*ABS\*\+(0x|)0x76543210>
+   c:	86 10 e2 10 	or  %g3, 0x210, %g3	! 76543210 <(\*ABS\*|foo)\+(0x|)0x76543210>
   10:	88 10 20 00 	clr  %g4
   14:	0b 00 00 3f 	sethi  %hi\(0xfc00\), %g5
-  18:	8a 11 63 ff 	or  %g5, 0x3ff, %g5	! ffff <\*ABS\*\+(0x|)ffff>
-  1c:	03 00 00 00 	sethi  %hi\(0x0\), %g1
+  18:	8a 11 63 ff 	or  %g5, 0x3ff, %g5	! ffff <(\*ABS\*|foo)\+(0x|)ffff>
+  1c:	03 00 00 00 	sethi  %hi\((0x|)0\), %g1
 			1c: R_SPARC_HH22	.text
-  20:	82 10 60 00 	mov  %g1, %g1	! 0 <foo>
-			20: R_SPARC_HM10	.text
-  24:	05 00 00 00 	sethi  %hi\(0x0\), %g2
-			24: R_SPARC_HI22	.text
-  28:	84 10 a0 00 	mov  %g2, %g2	! 0 <foo>
+  20:	05 00 00 00 	sethi  %hi\((0x|)0\), %g2
+			20: R_SPARC_LM22	.text
+  24:	82 10 60 00 	mov  %g1, %g1
+			24: R_SPARC_HM10	.text
+  28:	84 10 a0 00 	mov  %g2, %g2
 			28: R_SPARC_LO10	.text
   2c:	83 28 70 20 	sllx  %g1, 0x20, %g1
   30:	84 10 80 01 	or  %g2, %g1, %g2
@@ -32,57 +32,78 @@ Disassembly of section .text:
   40:	86 10 2f ff 	mov  0xfff, %g3
   44:	07 00 00 04 	sethi  %hi\(0x1000\), %g3
   48:	86 10 30 00 	mov  -4096, %g3
-  4c:	07 3f ff fb 	sethi  %hi\(0xffffec00\), %g3
-  50:	86 10 e3 ff 	or  %g3, 0x3ff, %g3	! ffffefff <\*ABS\*\+(0x|)ffffefff>
-  54:	87 38 e0 00 	sra  %g3, 0, %g3
-  58:	07 00 00 3f 	sethi  %hi\(0xfc00\), %g3
-  5c:	86 10 e3 ff 	or  %g3, 0x3ff, %g3	! ffff <\*ABS\*\+(0x|)ffff>
-  60:	07 3f ff c0 	sethi  %hi\(0xffff0000\), %g3
-  64:	87 38 e0 00 	sra  %g3, 0, %g3
-  68:	09 1f ff ff 	sethi  %hi\(0x7ffffc00\), %g4
-  6c:	88 11 23 ff 	or  %g4, 0x3ff, %g4	! 7fffffff <\*ABS\*\+(0x|)7fffffff>
-  70:	09 20 00 00 	sethi  %hi\(0x80000000\), %g4
-  74:	09 20 00 00 	sethi  %hi\(0x80000000\), %g4
-  78:	89 39 20 00 	sra  %g4, 0, %g4
-  7c:	82 10 3f ff 	mov  -1, %g1
-  80:	09 1f ff ff 	sethi  %hi\(0x7ffffc00\), %g4
-  84:	88 11 23 ff 	or  %g4, 0x3ff, %g4	! 7fffffff <\*ABS\*\+(0x|)7fffffff>
-  88:	83 28 70 20 	sllx  %g1, 0x20, %g1
-  8c:	88 11 00 01 	or  %g4, %g1, %g4
-  90:	09 3f ff ff 	sethi  %hi\(0xfffffc00\), %g4
-  94:	88 11 23 ff 	or  %g4, 0x3ff, %g4	! ffffffff <\*ABS\*\+(0x|)ffffffff>
-  98:	88 10 20 01 	mov  1, %g4
-  9c:	89 29 30 20 	sllx  %g4, 0x20, %g4
-  a0:	03 1f ff ff 	sethi  %hi\(0x7ffffc00\), %g1
-  a4:	82 10 63 ff 	or  %g1, 0x3ff, %g1	! 7fffffff <\*ABS\*\+(0x|)7fffffff>
-  a8:	0b 3f ff ff 	sethi  %hi\(0xfffffc00\), %g5
-  ac:	8a 11 63 ff 	or  %g5, 0x3ff, %g5	! ffffffff <\*ABS\*\+(0x|)ffffffff>
-  b0:	83 28 70 20 	sllx  %g1, 0x20, %g1
-  b4:	8a 11 40 01 	or  %g5, %g1, %g5
-  b8:	0b 20 00 00 	sethi  %hi\(0x80000000\), %g5
-  bc:	8b 29 70 20 	sllx  %g5, 0x20, %g5
-  c0:	8a 10 3f ff 	mov  -1, %g5
-  c4:	8b 29 70 20 	sllx  %g5, 0x20, %g5
-  c8:	0b 20 00 00 	sethi  %hi\(0x80000000\), %g5
-  cc:	8b 39 60 00 	sra  %g5, 0, %g5
+  4c:	07 00 00 04 	sethi  %hi\(0x1000\), %g3
+  50:	86 18 ff ff 	xor  %g3, -1, %g3
+  54:	07 00 00 3f 	sethi  %hi\(0xfc00\), %g3
+  58:	86 10 e3 ff 	or  %g3, 0x3ff, %g3	! ffff <(\*ABS\*|foo)\+(0x|)ffff>
+  5c:	07 00 00 3f 	sethi  %hi\(0xfc00\), %g3
+  60:	86 18 fc 00 	xor  %g3, -1024, %g3
+  64:	09 1f ff ff 	sethi  %hi\(0x7ffffc00\), %g4
+  68:	88 11 23 ff 	or  %g4, 0x3ff, %g4	! 7fffffff <(\*ABS\*|foo)\+(0x|)7fffffff>
+  6c:	09 20 00 00 	sethi  %hi\(0x80000000\), %g4
+  70:	09 1f ff ff 	sethi  %hi\(0x7ffffc00\), %g4
+  74:	88 19 3c 00 	xor  %g4, -1024, %g4
+  78:	09 20 00 00 	sethi  %hi\(0x80000000\), %g4
+  7c:	88 19 3f ff 	xor  %g4, -1, %g4
+  80:	09 3f ff ff 	sethi  %hi\(0xfffffc00\), %g4
+  84:	88 11 23 ff 	or  %g4, 0x3ff, %g4	! ffffffff <(\*ABS\*|foo)\+(0x|)ffffffff>
+  88:	88 10 20 01 	mov  1, %g4
+  8c:	89 29 30 20 	sllx  %g4, 0x20, %g4
+  90:	03 1f ff ff 	sethi  %hi\(0x7ffffc00\), %g1
+  94:	0b 3f ff ff 	sethi  %hi\(0xfffffc00\), %g5
+  98:	82 10 63 ff 	or  %g1, 0x3ff, %g1
+  9c:	8a 11 63 ff 	or  %g5, 0x3ff, %g5
+  a0:	83 28 70 20 	sllx  %g1, 0x20, %g1
+  a4:	8a 11 40 01 	or  %g5, %g1, %g5
+  a8:	0b 20 00 00 	sethi  %hi\(0x80000000\), %g5
+  ac:	8b 29 70 20 	sllx  %g5, 0x20, %g5
+  b0:	0b 3f ff ff 	sethi  %hi\(0xfffffc00\), %g5
+  b4:	8a 19 7c 00 	xor  %g5, -1024, %g5
+  b8:	0b 1f ff ff 	sethi  %hi\(0x7ffffc00\), %g5
+  bc:	8a 19 7c 00 	xor  %g5, -1024, %g5
+  c0:	03 3f ff c0 	sethi  %hi\(0xffff0000\), %g1
+  c4:	0b 3f ff c0 	sethi  %hi\(0xffff0000\), %g5
+  c8:	83 28 70 20 	sllx  %g1, 0x20, %g1
+  cc:	8a 11 40 01 	or  %g5, %g1, %g5
   d0:	03 3f ff c0 	sethi  %hi\(0xffff0000\), %g1
-  d4:	0b 3f ff c0 	sethi  %hi\(0xffff0000\), %g5
+  d4:	8a 10 20 01 	mov  1, %g5
   d8:	83 28 70 20 	sllx  %g1, 0x20, %g1
   dc:	8a 11 40 01 	or  %g5, %g1, %g5
-  e0:	03 3f ff c0 	sethi  %hi\(0xffff0000\), %g1
-  e4:	8a 10 20 01 	mov  1, %g5
-  e8:	83 28 70 20 	sllx  %g1, 0x20, %g1
-  ec:	8a 11 40 01 	or  %g5, %g1, %g5
-  f0:	82 10 20 01 	mov  1, %g1
+  e0:	0b 3f ff c0 	sethi  %hi\(0xffff0000\), %g5
+  e4:	82 10 20 01 	mov  1, %g1
+  e8:	8a 11 60 01 	or  %g5, 1, %g5
+  ec:	83 28 70 20 	sllx  %g1, 0x20, %g1
+  f0:	8a 11 40 01 	or  %g5, %g1, %g5
   f4:	0b 3f ff c0 	sethi  %hi\(0xffff0000\), %g5
-  f8:	8a 11 60 01 	or  %g5, 1, %g5	! ffff0001 <\*ABS\*\+(0x|)ffff0001>
+  f8:	82 10 20 01 	mov  1, %g1
   fc:	83 28 70 20 	sllx  %g1, 0x20, %g1
  100:	8a 11 40 01 	or  %g5, %g1, %g5
  104:	82 10 20 01 	mov  1, %g1
- 108:	0b 3f ff c0 	sethi  %hi\(0xffff0000\), %g5
+ 108:	8a 10 20 01 	mov  1, %g5
  10c:	83 28 70 20 	sllx  %g1, 0x20, %g1
  110:	8a 11 40 01 	or  %g5, %g1, %g5
- 114:	82 10 20 01 	mov  1, %g1
- 118:	8a 10 20 01 	mov  1, %g5
- 11c:	83 28 70 20 	sllx  %g1, 0x20, %g1
- 120:	8a 11 40 01 	or  %g5, %g1, %g5
+ 114:	05 00 00 00 	sethi  %hi\((0x|)0\), %g2
+			114: R_SPARC_HI22	.text
+ 118:	84 10 a0 00 	mov  %g2, %g2	! 0 <foo>
+			118: R_SPARC_LO10	.text
+ 11c:	07 1d 95 0c 	sethi  %hi\(0x76543000\), %g3
+ 120:	86 10 e2 10 	or  %g3, 0x210, %g3	! 76543210 <(\*ABS\*|foo)\+0x76543210>
+ 124:	88 10 20 00 	clr  %g4
+ 128:	0b 00 00 3f 	sethi  %hi\(0xfc00\), %g5
+ 12c:	8a 11 63 ff 	or  %g5, 0x3ff, %g5	! ffff <(\*ABS\*|foo)\+0xffff>
+ 130:	05 00 00 00 	sethi  %hi\((0x|)0\), %g2
+			130: R_SPARC_HI22	.text
+ 134:	84 10 a0 00 	mov  %g2, %g2	! 0 <foo>
+			134: R_SPARC_LO10	.text
+ 138:	85 38 80 00 	signx  %g2
+ 13c:	07 1d 95 0c 	sethi  %hi\(0x76543000\), %g3
+ 140:	86 10 e2 10 	or  %g3, 0x210, %g3	! 76543210 <(\*ABS\*|foo)\+0x76543210>
+ 144:	88 10 20 00 	clr  %g4
+ 148:	0b 00 00 3f 	sethi  %hi\(0xfc00\), %g5
+ 14c:	8a 11 63 ff 	or  %g5, 0x3ff, %g5	! ffff <(\*ABS\*|foo)\+0xffff>
+ 150:	82 10 3f ff 	mov  -1, %g1
+ 154:	05 1f ff ff 	sethi  %hi\(0x7ffffc00\), %g2
+ 158:	84 10 a3 ff 	or  %g2, 0x3ff, %g2	! 7fffffff <(\*ABS\*|foo)\+0x7fffffff>
+ 15c:	07 00 00 3f 	sethi  %hi\(0xfc00\), %g3
+ 160:	86 18 fc 00 	xor  %g3, -1024, %g3
+ 164:	88 10 3f ff 	mov  -1, %g4
--- ./gas/testsuite/gas/sparc/synth64.d.jj4	Thu Apr 22 10:12:09 1999
+++ ./gas/testsuite/gas/sparc/synth64.d	Tue Jun  8 18:08:46 1999
@@ -1,4 +1,4 @@
-#as: -Av9
+#as: -64 -Av9
 #objdump: -dr --prefix-addresses
 #name: sparc64 synth64
 
@@ -17,3 +17,5 @@ Disassembly of section .text:
 0+0024 <foo\+(0x|)20> clrx  \[ %g1 \+ 1 \]
 0+0028 <foo\+(0x|)24> clrx  \[ %g1 \+ 0x2a \]
 0+002c <foo\+(0x|)28> clrx  \[ 0x42 \]
+0+0030 <foo\+(0x|)2c> signx  %g1
+0+0034 <foo\+(0x|)30> clruw  %g2
--- ./gas/testsuite/gas/sparc/wrpr.d.jj4	Thu Apr 22 10:12:09 1999
+++ ./gas/testsuite/gas/sparc/wrpr.d	Tue Jun  8 16:22:03 1999
@@ -1,4 +1,4 @@
-#as: -Av9
+#as: -64 -Av9
 #objdump: -dr
 #name: sparc64 wrpr
 
--- ./gas/testsuite/gas/sparc/sparc.exp.jj4	Thu Apr 22 10:12:08 1999
+++ ./gas/testsuite/gas/sparc/sparc.exp	Tue Jun  8 18:13:34 1999
@@ -5,20 +5,29 @@
 # disassembly.  The way to fix this is to include a hex dump of the insns
 # and test that as well.  Later.
 
-if [istarget sparc*-*-*] {
-    run_dump_test "synth"
-}
+# Find out if these binutils are either sparc64*-*-* or
+# sparc*-*-* with --enable-targets=sparc64-*-*
+proc gas_64_check { } {
+    global NM
+    global NMFLAGS
+    global srcdir
 
+    catch "exec $srcdir/lib/run $NM $NMFLAGS --help" nm_help
+    return [regexp "elf64\[_-\]sparc" $nm_help];
+}
 
-if [istarget sparc64*-*-*] {
-    run_dump_test "asi"
-    run_dump_test "membar"
-    run_dump_test "prefetch"
-    run_dump_test "set64"
-    run_dump_test "synth64"
-    run_dump_test "rdpr"
-    run_dump_test "wrpr"
-    run_dump_test "reloc64"
+if [istarget sparc*-*-*] {
+    run_dump_test "synth"
+    if [gas_64_check] {
+	run_dump_test "asi"
+	run_dump_test "membar"
+	run_dump_test "prefetch"
+	run_dump_test "set64"
+	run_dump_test "synth64"
+	run_dump_test "rdpr"
+	run_dump_test "wrpr"
+	run_dump_test "reloc64"
+    }
 }
 
 if [istarget sparclet*-*-*] {
--- ./gas/testsuite/gas/sparc/synth64.s.jj4	Thu Apr 22 10:12:09 1999
+++ ./gas/testsuite/gas/sparc/synth64.s	Tue Jun  8 17:49:45 1999
@@ -14,3 +14,6 @@ foo:
 	clrx [%g1+1]
 	clrx [42+%g1]
 	clrx [0x42]
+
+	signx %g1
+	clruw %g2
--- ./gas/testsuite/gas/sparc/set64.s.jj4	Thu Apr 22 10:12:08 1999
+++ ./gas/testsuite/gas/sparc/set64.s	Tue Jun  8 17:59:28 1999
@@ -1,5 +1,4 @@
 # sparc64 set insn handling (includes set, setuw, setsw, setx)
-# FIXME: setuw,setsw not tested for yet.
 
 foo:
 	set foo,%g2
@@ -41,3 +40,17 @@ foo:
 	setx 0x00000001ffff0001,%g1,%g5		! test hm10,hi22,lo10
 	setx 0x00000001ffff0000,%g1,%g5		! test hm10,hi22
 	setx 0x0000000100000001,%g1,%g5		! test hm10,lo10
+
+	setuw foo,%g2
+	setuw 0x76543210,%g3
+	setuw 0,%g4
+	setuw 65535,%g5
+
+	setsw foo,%g2
+	setsw 0x76543210,%g3
+	setsw 0,%g4
+	setsw 65535,%g5
+	setsw 0xffffffff,%g1
+	setsw 0x7fffffff,%g2
+	setsw 0xffff0000,%g3
+	setsw -1,%g4
--- ./bfd/elf32-sparc.c.jj4	Tue May 25 17:35:59 1999
+++ ./bfd/elf32-sparc.c	Tue Jun  8 15:47:00 1999
@@ -215,8 +215,20 @@ elf32_sparc_info_to_howto (abfd, cache_p
      arelent *cache_ptr;
      Elf_Internal_Rela *dst;
 {
-  BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_SPARC_max);
-  cache_ptr->howto = &_bfd_sparc_elf_howto_table[ELF32_R_TYPE(dst->r_info)];
+  switch (ELF32_R_TYPE(dst->r_info))
+    {
+    case R_SPARC_GNU_VTINHERIT:
+      cache_ptr->howto = &elf32_sparc_vtinherit_howto;
+      break;
+
+    case R_SPARC_GNU_VTENTRY:
+      cache_ptr->howto = &elf32_sparc_vtentry_howto;
+      break;
+
+    default:
+      BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_SPARC_max_std);
+      cache_ptr->howto = &_bfd_sparc_elf_howto_table[ELF32_R_TYPE(dst->r_info)];
+    }
 }
 
 /* For unsupported relocs.  */
@@ -1134,7 +1146,7 @@ elf32_sparc_relocate_section (output_bfd
           || r_type == R_SPARC_GNU_VTENTRY)
         continue;
 
-      if (r_type < 0 || r_type >= (int) R_SPARC_max)
+      if (r_type < 0 || r_type >= (int) R_SPARC_max_std)
 	{
 	  bfd_set_error (bfd_error_bad_value);
 	  return false;
--- ./bfd/elf64-sparc.c.jj4	Tue Jun  8 18:26:50 1999
+++ ./bfd/elf64-sparc.c	Tue Jun  8 18:27:23 1999
@@ -215,7 +215,7 @@ sparc64_elf_info_to_howto (abfd, cache_p
      arelent *cache_ptr;
      Elf64_Internal_Rela *dst;
 {
-  BFD_ASSERT (ELF64_R_TYPE_ID (dst->r_info) < (unsigned int) R_SPARC_max);
+  BFD_ASSERT (ELF64_R_TYPE_ID (dst->r_info) < (unsigned int) R_SPARC_max_std);
   cache_ptr->howto = &sparc64_elf_howto_table[ELF64_R_TYPE_ID (dst->r_info)];
 }
 
@@ -1281,7 +1281,7 @@ sparc64_elf_relocate_section (output_bfd
       bfd_reloc_status_type r;
 
       r_type = ELF64_R_TYPE_ID (rel->r_info);
-      if (r_type < 0 || r_type >= (int) R_SPARC_max)
+      if (r_type < 0 || r_type >= (int) R_SPARC_max_std)
 	{
 	  bfd_set_error (bfd_error_bad_value);
 	  return false;
--- ./include/elf/sparc.h.jj4	Thu Apr 22 10:13:54 1999
+++ ./include/elf/sparc.h	Tue Jun  8 15:37:32 1999
@@ -128,6 +128,8 @@ START_RELOC_NUMBERS (elf_sparc_reloc_typ
   /* little endian data relocs */
   RELOC_NUMBER (R_SPARC_REV32, 56)
 
+  EMPTY_RELOC  (R_SPARC_max_std)
+
   RELOC_NUMBER (R_SPARC_GNU_VTINHERIT, 250)
   RELOC_NUMBER (R_SPARC_GNU_VTENTRY, 251)
 

Cheers,
    Jakub
___________________________________________________________________
Jakub Jelinek | jj@sunsite.mff.cuni.cz | http://sunsite.mff.cuni.cz
Administrator of SunSITE Czech Republic, MFF, Charles University
___________________________________________________________________
UltraLinux  |  http://ultra.linux.cz/  |  http://ultra.penguin.cz/
Linux version 2.3.4 on a sparc64 machine (1343.49 BogoMips)
___________________________________________________________________

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