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] Important gas fixes on sparc


Hi!

This patch has a couple of fixes for SPARC gas, both in 32bit and 64bit
mode:
sethi 0x8000, %g1

should result in
sethi %hi(0x2000000), %g1
and
sethi bar, %g1
should become R_SPARC_22 relocation. This is the bug H.J.Lu was solving in
his Linux binutils patch, but using his solution would always show sethis
immediates without %hi in objdump, gdb & co., which is kind of inconvenient
when 99.9% of all sethis are sethi %hi(x), r.

Also,
set 0xffffff36, %g2
in current gas if bfd_vma is 64bit, but as is run in 32bit mode (-32) and
for non-V9 architecture, was assembled as
sethi %hi(0xfffffc00), %g2
or %g2, 0x336, %g2

although
mov  -202, %g2
is sufficient.
This patch fixes this, plus it fixes setx synthetic instruction (it was
terribly broken) and writes support for setsw (it was assembled to nothing).
Also, this patch adds support for
signx %g3
and
clruw %g4

about which sparc-opc.c claimed it is not doable in sparc-opc.c. It is
easily doable without any special hacks...

If I find some more time, I'll try to optimize setx much more than it can do
now (by using the same algorithm as gcc does (and even there are places for
improvement I think)), but this patch will make it at least work correctly
and optimize several common cases.

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

        * gas/config/tc-sparc.c (md_assemble):
	Fix up setx, support setsw. Optimize set if
	sizeof(bfd_vma) == 64.
	(sparc_ip): Fix sethi - without %hi() it
	should generate R_SPARC_32 reloc, not R_SPARC_HI22.
	* opcodes/sparc-opc.c: Fix up set, setsw, setuw
	operand kinds. Support signx %reg, clruw %reg.

--- ./gas/config/tc-sparc.c.jj3	Wed Jun  2 17:54:51 1999
+++ ./gas/config/tc-sparc.c	Mon Jun  7 18:42:30 1999
@@ -938,6 +938,7 @@ static int special_case;
 /* Bit masks of various insns.  */
 #define NOP_INSN 0x01000000
 #define OR_INSN 0x80100000
+#define XOR_INSN 0x80180000
 #define FMOVS_INSN 0x81A00020
 #define SETHI_INSN 0x01000000
 #define SLLX_INSN 0x81281000
@@ -989,222 +990,295 @@ md_assemble (str)
       as_warn (_("FP branch preceded by FP instruction; NOP inserted"));
     }
 
-  switch (special_case)
-    {
-    case SPECIAL_CASE_NONE:
-      /* normal insn */
-      output_insn (insn, &the_insn);
-      break;
+  for (;;)
+    {    
+      switch (special_case)
+	{
+	case SPECIAL_CASE_NONE:
+	  /* normal insn */
+	  output_insn (insn, &the_insn);
+	  return;
 
-    case SPECIAL_CASE_SET:
-      {
-	int need_hi22_p = 0;
-
-	/* "set" is not defined for negative numbers in v9: it doesn't yield
-	   what you expect it to.  */
-	if (SPARC_OPCODE_ARCH_V9_P (max_architecture)
-	    && the_insn.exp.X_op == O_constant)
-	  {
-	    if (the_insn.exp.X_add_number < 0)
-	      as_warn (_("set: used with negative number"));
-	    else if (the_insn.exp.X_add_number > (offsetT) 0xffffffff)
-	      as_warn (_("set: number larger than 4294967295"));
-	  }
+	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;
+		    }
 
-	/* 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))
-	  {
-	    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 = (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;
-	    the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (rd) : 0)
-			       | RD (rd)
-			       | IMMED
-			       | (the_insn.exp.X_add_number
-				  & (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);
-	  }
-	break;
-      }
-
-    case SPECIAL_CASE_SETSW:
-      {
-	/* FIXME: Not finished.  */
-	break;
-      }
-
-    case SPECIAL_CASE_SETX:
-      {
-#define SIGNEXT32(x) ((((x) & 0xffffffff) ^ 0x80000000) - 0x80000000)
-	int upper32 = SIGNEXT32 (BSR (the_insn.exp.X_add_number, 32));
-	int lower32 = SIGNEXT32 (the_insn.exp.X_add_number);
-#undef SIGNEXT32
-	int tmpreg = (the_insn.opcode & RS1 (~0)) >> 14;
-	int dstreg = (the_insn.opcode & RD (~0)) >> 25;
-	/* Output directly to dst reg if lower 32 bits are all zero.  */
-	int upper_dstreg = (the_insn.exp.X_op == O_constant
-			    && lower32 == 0) ? dstreg : tmpreg;
-	int need_hh22_p = 0, need_hm10_p = 0, need_hi22_p = 0, need_lo10_p = 0;
-
-	/* The tmp reg should not be the dst reg.  */
-	if (tmpreg == dstreg)
-	  as_warn (_("setx: temporary register same as destination register"));
-
-	/* 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;
-
-	/* ??? 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)
-	  need_hh22_p = need_hm10_p = need_hi22_p = need_lo10_p = 1;
-	else
-	  {
-	    /* 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 || lower32 >= 0)))
-	      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.  */
-		|| (! 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))
-		  need_hi22_p = 1;
 
-		/* Does bottom part (after sethi) have bits?  */
-		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;
+	    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;
 	      }
-	  }
 
-	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);
-	  }
+	    /* 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);
+	      }
 
-	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 (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;
 	  }
-
-	if (need_hi22_p)
+    
+	case SPECIAL_CASE_SETX:
 	  {
-	    the_insn.opcode = (SETHI_INSN | RD (dstreg)
-			       | ((lower32 >> 10) & 0x3fffff));
-	    the_insn.reloc = BFD_RELOC_HI22;
-	    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);
-	  }
+	    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);
+	      }
 
-	/* 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);
+	    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;
 	  }
-
-	/* If we needed to build both upper and lower parts, OR them together.  */
-	if ((need_hh22_p || need_hm10_p)
-	    && (need_hi22_p || need_lo10_p))
+    
+	case SPECIAL_CASE_FDIV:
 	  {
-	    the_insn.opcode = (OR_INSN | RS1 (dstreg) | RS2 (upper_dstreg)
-			       | RD (dstreg));
-	    the_insn.reloc = BFD_RELOC_NONE;
+	    int rd = (the_insn.opcode >> 25) & 0x1f;
+    
 	    output_insn (insn, &the_insn);
-	  }
-	/* We didn't need both regs, but we may have to sign extend lower32.  */
-	else if (need_hi22_p && upper32 == -1)
-	  {
-	    the_insn.opcode = (SRA_INSN | RS1 (dstreg) | RD (dstreg)
-			       | IMMED | 0);
-	    the_insn.reloc = BFD_RELOC_NONE;
+    
+	    /* 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;
 	  }
-	break;
-      }
-
-    case SPECIAL_CASE_FDIV:
-      {
-	int rd = (the_insn.opcode >> 25) & 0x1f;
-
-	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);
-	break;
-      }
-
-    default:
-      as_fatal (_("failed special case insn sanity check"));
+    
+	default:
+	  as_fatal (_("failed special case insn sanity check"));
+	}
     }
 }
 
@@ -1916,14 +1990,10 @@ sparc_ip (str, pinsn)
 		}
 	      break;
 
-	    case '0':		/* 64 bit immediate (setx insn) */
+	    case '0':		/* 64 bit immediate (set, setsw, setx insn) */
 	      the_insn.reloc = BFD_RELOC_NONE; /* reloc handled elsewhere */
 	      goto immediate;
 
-	    case 'h':		/* high 22 bits */
-	      the_insn.reloc = BFD_RELOC_HI22;
-	      goto immediate;
-
 	    case 'l':		/* 22 bit PC relative immediate */
 	      the_insn.reloc = BFD_RELOC_SPARC_WDISP22;
 	      the_insn.pcrel = 1;
@@ -1934,6 +2004,7 @@ sparc_ip (str, pinsn)
 	      the_insn.pcrel = 1;
 	      goto immediate;
 
+	    case 'h':
 	    case 'n':		/* 22 bit immediate */
 	      the_insn.reloc = BFD_RELOC_SPARC22;
 	      goto immediate;
--- ./opcodes/sparc-opc.c.jj3	Tue May 25 17:19:05 1999
+++ ./opcodes/sparc-opc.c	Mon Jun  7 16:47:45 1999
@@ -1476,9 +1476,9 @@ CONDFC  ("fbule", "cb013", 0xe, 0),
 
 { "nop",	F2(0, 4), 0xfeffffff, "", 0, v6 }, /* sethi 0, %g0 */
 
-{ "set",	F2(0x0, 0x4), F2(~0x0, ~0x4), "Sh,d", F_ALIAS, v6 },
-{ "setuw",	F2(0x0, 0x4), F2(~0x0, ~0x4), "Sh,d", F_ALIAS, v9 },
-{ "setsw",	F2(0x0, 0x4), F2(~0x0, ~0x4), "Sh,d", F_ALIAS, v9 },
+{ "set",	F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,d", F_ALIAS, v6 },
+{ "setuw",	F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,d", F_ALIAS, v9 },
+{ "setsw",	F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,d", F_ALIAS, v9 },
 { "setx",	F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,1,d", F_ALIAS, v9 },
 
 { "sethi",	F2(0x0, 0x4), F2(~0x0, ~0x4), "h,d", 0, v6 },
@@ -1729,10 +1729,11 @@ SLCBCC("cbnefr", 15),
 { "casxa",	F3(3, 0x3e, 1), F3(~3, ~0x3e, ~1), "[1]o,2,d", 0, v9 },
 
 /* v9 synthetic insns */
-/* FIXME: still missing "signx d", and "clruw d".  Can't be done here.  */
 { "iprefetch",	F2(0, 1)|(2<<20)|BPRED, F2(~0, ~1)|(1<<20)|ANNUL|COND(~0), "G", 0, v9 }, /* bn,a,pt %xcc,label */
 { "signx",	F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|ASI(~0)|RS2_G0, "1,d", F_ALIAS, v9 }, /* sra rs1,%g0,rd */
+{ "signx",	F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|ASI(~0)|RS2_G0, "r", F_ALIAS, v9 }, /* sra rd,%g0,rd */
 { "clruw",	F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|ASI(~0)|RS2_G0, "1,d", F_ALIAS, v9 }, /* srl rs1,%g0,rd */
+{ "clruw",	F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|ASI(~0)|RS2_G0, "r", F_ALIAS, v9 }, /* srl rd,%g0,rd */
 { "cas",	F3(3, 0x3c, 0)|ASI(0x80), F3(~3, ~0x3c, ~0)|ASI(~0x80), "[1],2,d", F_ALIAS, v9 }, /* casa [rs1]ASI_P,rs2,rd */
 { "casl",	F3(3, 0x3c, 0)|ASI(0x88), F3(~3, ~0x3c, ~0)|ASI(~0x88), "[1],2,d", F_ALIAS, v9 }, /* casa [rs1]ASI_P_L,rs2,rd */
 { "casx",	F3(3, 0x3e, 0)|ASI(0x80), F3(~3, ~0x3e, ~0)|ASI(~0x80), "[1],2,d", F_ALIAS, v9 }, /* casxa [rs1]ASI_P,rs2,rd */


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]