public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Re: [PATCH] Important gas fixes on sparc
  1999-07-01  0:00 ` Richard Henderson
@ 1999-07-01  0:00   ` David S. Miller
  0 siblings, 0 replies; 7+ messages in thread
From: David S. Miller @ 1999-07-01  0:00 UTC (permalink / raw)
  To: rth; +Cc: jj, binutils

   Date: Mon, 7 Jun 1999 10:54:55 -0700
   From: Richard Henderson <rth@cygnus.com>

   You may want to hack this in your local tree to emit a warning for
   R_SPARC_22.  Red Hat 6 was delayed on Sparc because of this change.
   So there's some amount of assembly code out there that's got this
   wrong.

This was fixed, at least in the kernel sources, as soon as I became
aware of hjl's fixes.

Later,
David S. Miller
davem@redhat.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Important gas fixes on sparc
  1999-07-01  0:00 [PATCH] Important gas fixes on sparc Jakub Jelinek
  1999-07-01  0:00 ` Richard Henderson
  1999-07-01  0:00 ` David S. Miller
@ 1999-07-01  0:00 ` Doug Evans
  1999-07-01  0:00   ` Jakub Jelinek
  1999-07-01  0:00 ` Richard Henderson
  3 siblings, 1 reply; 7+ messages in thread
From: Doug Evans @ 1999-07-01  0:00 UTC (permalink / raw)
  To: jj; +Cc: binutils, davem, rth

   Date: Mon, 7 Jun 1999 19:35:15 +0200
   From: Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>

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

	   (sparc_ip): Fix sethi - without %hi() it
	   should generate R_SPARC_32 reloc, not R_SPARC_HI22.

This is just a typo in the changelog entry, right?
R_SPARC_32 for a sethi insn?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Important gas fixes on sparc
  1999-07-01  0:00 [PATCH] Important gas fixes on sparc Jakub Jelinek
                   ` (2 preceding siblings ...)
  1999-07-01  0:00 ` Doug Evans
@ 1999-07-01  0:00 ` Richard Henderson
  1999-07-01  0:00   ` David S. Miller
  3 siblings, 1 reply; 7+ messages in thread
From: Richard Henderson @ 1999-07-01  0:00 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: binutils, David S. Miller

On Mon, Jun 07, 1999 at 07:35:15PM +0200, Jakub Jelinek wrote:
> ... 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.

You may want to hack this in your local tree to emit a warning for
R_SPARC_22.  Red Hat 6 was delayed on Sparc because of this change.
So there's some amount of assembly code out there that's got this
wrong.


r~

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Important gas fixes on sparc
  1999-07-01  0:00 [PATCH] Important gas fixes on sparc Jakub Jelinek
  1999-07-01  0:00 ` Richard Henderson
@ 1999-07-01  0:00 ` David S. Miller
  1999-07-01  0:00 ` Doug Evans
  1999-07-01  0:00 ` Richard Henderson
  3 siblings, 0 replies; 7+ messages in thread
From: David S. Miller @ 1999-07-01  0:00 UTC (permalink / raw)
  To: jj; +Cc: binutils, rth

   Date: Mon, 7 Jun 1999 19:35:15 +0200
   From: Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>

   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.

Please make the author of said gcc optimizations know about the
improvements, he is very eager to learn about them :-)

Later,
David S. Miller
davem@redhat.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Important gas fixes on sparc
  1999-07-01  0:00 ` Doug Evans
@ 1999-07-01  0:00   ` Jakub Jelinek
  0 siblings, 0 replies; 7+ messages in thread
From: Jakub Jelinek @ 1999-07-01  0:00 UTC (permalink / raw)
  To: Doug Evans; +Cc: binutils, davem, rth

On Mon, Jun 07, 1999 at 11:48:58AM -0700, Doug Evans wrote:
>    Date: Mon, 7 Jun 1999 19:35:15 +0200
>    From: Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
> 
>    1999-06-07  Jakub Jelinek  <jj@ultra.linux.cz>
> 
> 	   (sparc_ip): Fix sethi - without %hi() it
> 	   should generate R_SPARC_32 reloc, not R_SPARC_HI22.
> 
> This is just a typo in the changelog entry, right?
> R_SPARC_32 for a sethi insn?

Sure, it generates R_SPARC_22 (BFD_RELOC_SPARC22).

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.2.9 on a sparc64 machine (1343.49 BogoMips)
___________________________________________________________________

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH] Important gas fixes on sparc
@ 1999-07-01  0:00 Jakub Jelinek
  1999-07-01  0:00 ` Richard Henderson
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Jakub Jelinek @ 1999-07-01  0:00 UTC (permalink / raw)
  To: binutils; +Cc: David S. Miller, Richard Henderson

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)
___________________________________________________________________

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Important gas fixes on sparc
  1999-07-01  0:00 [PATCH] Important gas fixes on sparc Jakub Jelinek
@ 1999-07-01  0:00 ` Richard Henderson
  1999-07-01  0:00 ` David S. Miller
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Richard Henderson @ 1999-07-01  0:00 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: binutils, David S. Miller

On Mon, Jun 07, 1999 at 07:35:15PM +0200, Jakub Jelinek wrote:
> 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.

Applied.

It wouldn't bother me at all if next time you're in to tweek this
code you were to break up some of these over-large functions.  And
clean up the special_case global variable thing -- blech.


r~

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~1999-07-01  0:00 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-07-01  0:00 [PATCH] Important gas fixes on sparc Jakub Jelinek
1999-07-01  0:00 ` Richard Henderson
1999-07-01  0:00 ` David S. Miller
1999-07-01  0:00 ` Doug Evans
1999-07-01  0:00   ` Jakub Jelinek
1999-07-01  0:00 ` Richard Henderson
1999-07-01  0:00   ` David S. Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).