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: Powerpc64 long double support


On Mon, Mar 08, 2004 at 11:59:45PM -0800, Richard Henderson wrote:
> I *do* think that's better than frobbing rv.sign yourself.
> The less the format of real.h gets exposed the better.

OK.  I decided to avoid including tree.h in insn-output.c.  Instead,
I'm using a new rs6000 backend function to calculate -0.0.  I believe
it's not necessary to GTY(()) rs6000_dfmode_m0_rtx because it will
point somewhere inside const_double_htab.

	* real.c (encode_ibm_extended): Use -0.0 in low double of Inf,
	NaN, and zero.  Update comment.
	* config/rs6000/rs6000.md (extenddftf2): Use -0.0 in low double.
	* config/rs6000/rs6000.c (rs6000_dfmode_m0): New function.
	* config/rs6000/rs6000-protos.h (rs6000_dfmode_m0): Declare.
	Replace "struct rtx_def *" with "rtx" in decls protected with
	#ifdef RTX_CODE.  Formatting.

Bootstrapped, regression tested powerpc64-linux.

Index: gcc/real.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.139
diff -u -p -r1.139 real.c
--- gcc/real.c	4 Mar 2004 10:23:20 -0000	1.139
+++ gcc/real.c	9 Mar 2004 23:34:36 -0000
@@ -3216,10 +3215,9 @@ const struct real_format ieee_extended_i
    numbers whose sum is equal to the extended precision value.  The number
    with greater magnitude is first.  This format has the same magnitude
    range as an IEEE double precision value, but effectively 106 bits of
-   significand precision.  Infinity and NaN are represented by their IEEE
-   double precision value stored in the first number, the second number is
-   ignored.  Zeroes, Infinities, and NaNs are set in both doubles
-   due to precedent.  */
+   significand precision.  Zero, Infinity and NaN are represented by their
+   IEEE double precision value stored in the first number, the second
+   number is -0.0.  */
 
 static void encode_ibm_extended (const struct real_format *fmt,
 				 long *, const REAL_VALUE_TYPE *);
@@ -3256,9 +3254,21 @@ encode_ibm_extended (const struct real_f
   else
     {
       /* Inf, NaN, 0 are all representable as doubles, so the
-	 least-significant part can be 0.0.  */
-      buf[2] = 0;
-      buf[3] = 0;
+	 least-significant part can be zero.  We choose -0.0 because
+	 conversion of IBM extended precision to double is done by
+	 adding the two component doubles.  -0.0 is the only value that
+	 will result in a long double -0.0 correctly converting to a
+	 -0.0 double.  */
+      if (FLOAT_WORDS_BIG_ENDIAN)
+	{
+	  buf[2] = 0x80000000;
+	  buf[3] = 0;
+	}
+      else
+	{
+	  buf[2] = 0;
+	  buf[3] = 0x80000000;
+	}
     }
 }
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.604
diff -u -p -r1.604 rs6000.c
--- gcc/config/rs6000/rs6000.c	8 Mar 2004 04:24:27 -0000	1.604
+++ gcc/config/rs6000/rs6000.c	9 Mar 2004 23:34:47 -0000
@@ -2780,6 +2780,22 @@ rs6000_legitimize_address (rtx x, rtx ol
     return NULL_RTX;
 }
 
+/* Construct a -0.0 here for use by extenddftf2.  */
+
+rtx
+rs6000_dfmode_m0 (void)
+{
+  static rtx rs6000_dfmode_m0_rtx;
+
+  if (rs6000_dfmode_m0_rtx == NULL_RTX)
+    {
+      REAL_VALUE_TYPE dconstm0 = REAL_VALUE_NEGATE (dconst0);
+      rs6000_dfmode_m0_rtx = CONST_DOUBLE_FROM_REAL_VALUE (dconstm0, DFmode);
+    }
+
+  return rs6000_dfmode_m0_rtx;
+}
+
 /* Construct the SYMBOL_REF for the tls_get_addr function.  */
 
 static GTY(()) rtx rs6000_tls_symbol;
Index: gcc/config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.299
diff -u -p -r1.299 rs6000.md
--- gcc/config/rs6000/rs6000.md	9 Mar 2004 12:10:25 -0000	1.299
+++ gcc/config/rs6000/rs6000.md	9 Mar 2004 23:34:54 -0000
@@ -8235,7 +8235,7 @@
   "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
 {
-  operands[2] = CONST0_RTX (DFmode);
+  operands[2] = rs6000_dfmode_m0 ();
 })
 
 (define_insn_and_split "*extenddftf2_internal"
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.74
diff -u -p -r1.74 rs6000-protos.h
--- gcc/config/rs6000/rs6000-protos.h	6 Feb 2004 06:18:19 -0000	1.74
+++ gcc/config/rs6000/rs6000-protos.h	9 Mar 2004 23:34:40 -0000
@@ -32,8 +32,9 @@ extern void init_cumulative_args (CUMULA
 extern void rs6000_va_start (tree, rtx);
 #endif /* TREE_CODE */
 
-extern struct rtx_def *rs6000_got_register (rtx);
-extern struct rtx_def *find_addr_reg (rtx);
+extern rtx rs6000_got_register (rtx);
+extern rtx rs6000_dfmode_m0 (void);
+extern rtx find_addr_reg (rtx);
 extern int any_operand (rtx, enum machine_mode);
 extern int short_cint_operand (rtx, enum machine_mode);
 extern int u_short_cint_operand (rtx, enum machine_mode);
@@ -120,41 +121,40 @@ extern int rs6000_emit_cmove (rtx, rtx, 
 extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx);
 extern void output_toc (FILE *, rtx, int, enum machine_mode);
 extern void rs6000_initialize_trampoline (rtx, rtx, rtx);
-extern struct rtx_def *rs6000_longcall_ref (rtx);
+extern rtx rs6000_longcall_ref (rtx);
 extern void rs6000_fatal_bad_address (rtx);
 extern int stmw_operation (rtx, enum machine_mode);
 extern int mfcr_operation (rtx, enum machine_mode);
 extern int mtcrf_operation (rtx, enum machine_mode);
 extern int lmw_operation (rtx, enum machine_mode);
-extern struct rtx_def *create_TOC_reference (rtx);
+extern rtx create_TOC_reference (rtx);
 extern void rs6000_split_multireg_move (rtx, rtx);
 extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
 extern rtx rs6000_legitimize_address (rtx, rtx, enum machine_mode);
 extern rtx rs6000_legitimize_reload_address (rtx, enum machine_mode,
-			    int, int, int, int *);
+					     int, int, int, int *);
 extern int rs6000_legitimate_address (enum machine_mode, rtx, int);
 extern bool rs6000_mode_dependent_address (rtx);
 extern rtx rs6000_return_addr (int, rtx);
 extern void rs6000_output_symbol_ref (FILE*, rtx);
 extern HOST_WIDE_INT rs6000_initial_elimination_offset (int, int);
 
-extern rtx rs6000_machopic_legitimize_pic_address (rtx orig, 
-                            enum machine_mode mode, rtx reg);
+extern rtx rs6000_machopic_legitimize_pic_address (rtx, enum machine_mode,
+						   rtx);
 
 #endif /* RTX_CODE */
 
 #ifdef TREE_CODE
 extern unsigned int rs6000_special_round_type_align (tree, int, int);
-extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
-					  tree, int);
+extern void function_arg_advance (CUMULATIVE_ARGS *,
+				  enum machine_mode, tree, int);
 extern int function_arg_boundary (enum machine_mode, tree);
 extern struct rtx_def *function_arg (CUMULATIVE_ARGS *,
-					     enum machine_mode, tree, int);
+				     enum machine_mode, tree, int);
 extern int function_arg_partial_nregs (CUMULATIVE_ARGS *,
-					       enum machine_mode, tree, int);
+				       enum machine_mode, tree, int);
 extern int function_arg_pass_by_reference (CUMULATIVE_ARGS *,
-						   enum machine_mode,
-						   tree, int);
+					   enum machine_mode, tree, int);
 extern rtx rs6000_function_value (tree, tree);
 extern rtx rs6000_libcall_value (enum machine_mode);
 extern struct rtx_def *rs6000_va_arg (tree, tree);

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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