This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: 128 bit floats on PA64


Here is the PA portion of a patch to implement 128-bit long doubles
for TARGET_64BIT.

CLASS_CANNOT_CHANGE_MODE_P is revised so that now the only mode changes
that are inhibited are those from SImode.  This is because SImode loads
to floating-point registers do not zero-extend.  I believe that this
is necessary as we do SImode loads to FPRs for the xmpy patterns.
They might happen in other rare situations as well.

Based on my reading of the "64-Bit Runtime Architecture for PA-RISC 2.0,
Version 3.3" (see pages 18 and 19), function_arg was grossly mishandling
DCmode and TCmode.  I believe that these should be treated in a manner
similar to that for other aggregates (BLKmode).  The same is also true
for TFmode quad-precision values.  As a result, I was able to considerably
simplify the TARGET_64BIT code.

I am currently running a bootstrap and regression check.  I only made
a couple of small tweaks to the code in pa.c from what I checked yesterday,
so I am not expecting any new surprises.  The testsuite results improve
with this patch.  I don't see any testsuite failures relating to TFmode
or complex number handling.

Let me know ASAP if you have any comments, particularly if you believe
that I have misinterpreted the ABI wrt quad-precision floating point
and complex parameters.  I think that this patch is a candidate for
the branch.  Although this fixes a problem in code that likely never
worked, I think it is a good idea to minimize the amount of code using
an incorrect ABI.

Dave
-- 
J. David Anglin                                  dave.anglin@nrc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6605)

2002-09-03  John David Anglin  <dave@hiauly1.hia.nrc.ca>

	* pa-64.h (LONG_DOUBLE_TYPE_SIZE): Define to 128.
	* pa64-regs.h (CLASS_CANNOT_CHANGE_MODE_P): Inhibit changes from SImode
	for floating-point register class.
	* pa.c (function_arg): Fix handling of modes wider than one word for
	TARGET_64BIT.

Index: config/pa/pa-64.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/pa/pa-64.h,v
retrieving revision 1.10
diff -u -3 -p -r1.10 pa-64.h
--- config/pa/pa-64.h	8 May 2002 23:10:59 -0000	1.10
+++ config/pa/pa-64.h	3 Sep 2002 17:27:10 -0000
@@ -65,10 +65,8 @@ Boston, MA 02111-1307, USA.  */
 #define FLOAT_TYPE_SIZE 32
 #undef DOUBLE_TYPE_SIZE
 #define DOUBLE_TYPE_SIZE 64
-/* This should be 128, but until we work out the ABI for the 128bit
-   FP codes supplied by HP we'll keep it at 64 bits.  */
 #undef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE 128
 
 /* Temporary until we figure out what to do with those *(&@$ 32bit
    relocs which appear in stabs.  */
Index: config/pa/pa64-regs.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/pa/pa64-regs.h,v
retrieving revision 1.9
diff -u -3 -p -r1.9 pa64-regs.h
--- config/pa/pa64-regs.h	11 Nov 2001 17:45:02 -0000	1.9
+++ config/pa/pa64-regs.h	3 Sep 2002 17:27:10 -0000
@@ -234,16 +234,21 @@ enum reg_class { NO_REGS, R1_REGS, GENER
 
 /* If defined, gives a class of registers that cannot be used as the
    operand of a SUBREG that changes the mode of the object illegally.  */
-/* ??? This may not actually be necessary anymore.  But until I can prove
-   otherwise it will stay.  */
+
 #define CLASS_CANNOT_CHANGE_MODE	(FP_REGS)
 
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
-  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
+/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.
+
+   SImode loads to floating-point registers are not zero-extended.
+   The definition for LOAD_EXTEND_OP specifies that integer loads
+   narrower than BITS_PER_WORD will be zero-extended.  As a result,
+   we inhibit changes from SImode unless they are to a mode that is
+   identical in size.  */
+
+#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO)				\
+  ((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
 
-/* The same information, inverted:
-   Return the class number of the smallest class containing
+/* Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
    or could index an array.  */
 
Index: config/pa/pa.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/pa/pa.c,v
retrieving revision 1.178
diff -u -3 -p -r1.178 pa.c
--- config/pa/pa.c	31 Aug 2002 19:47:07 -0000	1.178
+++ config/pa/pa.c	3 Sep 2002 17:27:22 -0000
@@ -7446,6 +7446,8 @@ function_arg (cum, mode, type, named, in
      int incoming;
 {
   int max_arg_words = (TARGET_64BIT ? 8 : 4);
+  int arg_size = FUNCTION_ARG_SIZE (mode, type);
+  int alignment = 0;
   int fpr_reg_base;
   int gpr_reg_base;
   rtx retval;
@@ -7456,16 +7458,15 @@ function_arg (cum, mode, type, named, in
          this routine should return zero.  FUNCTION_ARG_PARTIAL_NREGS will
          handle arguments which are split between regs and stack slots if
          the ABI mandates split arguments.  */
-      if (cum->words + FUNCTION_ARG_SIZE (mode, type) > max_arg_words
+      if (cum->words + arg_size > max_arg_words
           || mode == VOIDmode)
 	return NULL_RTX;
     }
   else
     {
-      int offset = 0;
-      if (FUNCTION_ARG_SIZE (mode, type) > 1 && (cum->words & 1))
-	offset = 1;
-      if (cum->words + offset >= max_arg_words
+      if (arg_size > 1)
+	alignment = cum->words & 1;
+      if (cum->words + alignment >= max_arg_words
 	  || mode == VOIDmode)
 	return NULL_RTX;
     }
@@ -7474,70 +7475,54 @@ function_arg (cum, mode, type, named, in
      particularly in their handling of FP registers.  We might
      be able to cleverly share code between them, but I'm not
      going to bother in the hope that splitting them up results
-     in code that is more easily understood.
+     in code that is more easily understood.  */
 
-     The 64bit code probably is very wrong for structure passing.  */
   if (TARGET_64BIT)
     {
       /* Advance the base registers to their current locations.
 
          Remember, gprs grow towards smaller register numbers while
-	 fprs grow to higher register numbers.  Also remember FP regs
-	 are always 4 bytes wide, while the size of an integer register
-	 varies based on the size of the target word.  */
+	 fprs grow to higher register numbers.  Also remember that
+	 although FP regs are 32-bit addressable, we pretend that
+	 the registers are 64-bits wide.  */
       gpr_reg_base = 26 - cum->words;
       fpr_reg_base = 32 + cum->words;
 
-      /* If the argument is more than a word long, then we need to align
-	 the base registers.  Same caveats as above.  */
-      if (FUNCTION_ARG_SIZE (mode, type) > 1)
+      /* Arguments wider than one word need special treatment.  */
+      if (arg_size > 1)
 	{
-	  if (mode != BLKmode)
-	    {
-	      /* First deal with alignment of the doubleword.  */
-	      gpr_reg_base -= (cum->words & 1);
+	  /* Double-extended precision (80-bit), quad-precision (128-bit)
+	     and aggregates including complex numbers are aligned on
+	     128-bit boundaries.  The first eight 64-bit argument slots
+	     are associated one-to-one, with general registers r26
+	     through r19, and also with floating-point registers fr4
+	     through fr11.  Arguments larger than one word are always
+	     passed in general registers.  */
 
-	      /* This seems backwards, but it is what HP specifies.  We need
-	         gpr_reg_base to point to the smaller numbered register of
-	         the integer register pair.  So if we have an even register
-	          number, then decrement the gpr base.  */
-	      gpr_reg_base -= ((gpr_reg_base % 2) == 0);
-
-	      /* FP values behave sanely, except that each FP reg is only
-	         half of word.  */
-	      fpr_reg_base += ((fpr_reg_base % 2) == 0);
-            }
-	  else
+	  rtx loc[8];
+	  int i, offset = 0, ub = arg_size;
+
+	  /* Align the base register.  */
+	  gpr_reg_base -= alignment;
+
+	  ub = MIN (ub, max_arg_words - cum->words - alignment);
+	  for (i = 0; i < ub; i++)
 	    {
-	      rtx loc[8];
-	      int i, offset = 0, ub;
-              ub = FUNCTION_ARG_SIZE (mode, type);
-	      ub = MIN (ub,
-			MAX (0, max_arg_words - cum->words - (cum->words & 1)));
-	      gpr_reg_base -= (cum->words & 1);
-	      for (i = 0; i < ub; i++)
-		{
-		  loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
-					      gen_rtx_REG (DImode,
-							   gpr_reg_base),
-					      GEN_INT (offset));
-		  gpr_reg_base -= 1;
-		  offset += 8;
-		}
-	      if (ub == 0)
-		return NULL_RTX;
-	      else if (ub == 1)
-		return XEXP (loc[0], 0);
-	      else
-		return gen_rtx_PARALLEL (mode, gen_rtvec_v (ub, loc));
+	      loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
+					  gen_rtx_REG (DImode, gpr_reg_base),
+					  GEN_INT (offset));
+	      gpr_reg_base -= 1;
+	      offset += 8;
 	    }
+
+	  return gen_rtx_PARALLEL (mode, gen_rtvec_v (ub, loc));
 	}
     }
   else
     {
       /* If the argument is larger than a word, then we know precisely
 	 which registers we must use.  */
-      if (FUNCTION_ARG_SIZE (mode, type) > 1)
+      if (arg_size > 1)
 	{
 	  if (cum->words)
 	    {
@@ -7559,19 +7544,6 @@ function_arg (cum, mode, type, named, in
 	}
     }
 
-  if (TARGET_64BIT && mode == TFmode)
-    {
-      return
-	gen_rtx_PARALLEL
-	  (mode,
-	   gen_rtvec (2,
-		      gen_rtx_EXPR_LIST (VOIDmode,
-					 gen_rtx_REG (DImode, gpr_reg_base + 1),
-					 const0_rtx),
-		      gen_rtx_EXPR_LIST (VOIDmode,
-					 gen_rtx_REG (DImode, gpr_reg_base),
-					 GEN_INT (8))));
-    }
   /* Determine if the argument needs to be passed in both general and
      floating point registers.  */
   if (((TARGET_PORTABLE_RUNTIME || TARGET_64BIT || TARGET_ELF32)


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