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]

PATCH: fix float handling in pdp11 backend


This patch fixes the pdp11 back end to handle float values correctly.

Committed.

	paul

2004-02-03  Paul Koning  <pkoning@equallogic.com>

	* config/pdp11/pdp11-modes.def: Add RESET_FLOAT_FORMAT calls.
	* config/pdp11/pdp11-protos.h (legitimate_const_double_p): Add.
	* config/pdp11/pdp11.c (encode_pdp11_f, decode_pdp11_f,
	encode_pdp11_d, decode_pdp11_d): New functions to handle PDP11
	floating point format.
	(pdp11_f_format, pdp11_d_format): New real_format descriptors for
	the above functions.
	(output_move_quad): Output float values in correct target format.
	(legitimate_const_double_p): New function.
	* config/pdp11/pdp11.h: Fix typos.
	(FLOAT_WORDS_BIG_ENDIAN): Add definition.
	(TARGET_FLOAT_FORMAT): Ditto.
	(pdp11_f_format, pdp11_d_format): Add external declarations.
	(MAX_REGS_PER_ADDRESS): Corrected.
	(LEGITIMATE_CONSTANT_P): Use legitimate_const_double_p().
	(PRINT_OPERAND): Output float literals in target format.

Index: pdp11-modes.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pdp11/pdp11-modes.def,v
retrieving revision 1.3
diff -u -r1.3 pdp11-modes.def
--- pdp11-modes.def	13 Oct 2003 21:16:31 -0000	1.3
+++ pdp11-modes.def	3 Feb 2004 17:32:30 -0000
@@ -1,5 +1,5 @@
 /* Definitions of target machine for GNU compiler, for the pdp-11
-   Copyright (C) 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
    Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
 
 This file is part of GCC.
@@ -23,3 +23,5 @@
    CCFPmode is used for FPU, but should we use a separate reg? */
 
 CC_MODE (CCFP);
+RESET_FLOAT_FORMAT (SF, pdp11_f_format);
+RESET_FLOAT_FORMAT (DF, pdp11_d_format);
Index: pdp11-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pdp11/pdp11-protos.h,v
retrieving revision 1.5
diff -u -r1.5 pdp11-protos.h
--- pdp11-protos.h	28 Sep 2003 12:09:07 -0000	1.5
+++ pdp11-protos.h	3 Feb 2004 17:32:30 -0000
@@ -1,5 +1,5 @@
 /* Definitions of target machine for GNU compiler, for the pdp-11
-   Copyright (C) 2000, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
 
 This file is part of GCC.
@@ -29,6 +29,7 @@
 extern int comp_operator (rtx, enum machine_mode);
 
 extern int legitimate_address_p (enum machine_mode, rtx);
+extern int legitimate_const_double_p (rtx);
 extern void notice_update_cc_on_set (rtx, rtx);
 extern void output_addr_const_pdp11 (FILE *, rtx);
 extern const char *output_move_double (rtx *);
Index: pdp11.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pdp11/pdp11.c,v
retrieving revision 1.35
diff -u -r1.35 pdp11.c
--- pdp11.c	3 Feb 2004 06:43:54 -0000	1.35
+++ pdp11.c	3 Feb 2004 17:32:30 -0000
@@ -51,6 +51,90 @@
    defined in tm.h */
 int current_first_parm_offset;
 
+/* Routines to encode/decode pdp11 floats */
+static void encode_pdp11_f (const struct real_format *fmt,
+			    long *, const REAL_VALUE_TYPE *);
+static void decode_pdp11_f (const struct real_format *,
+			    REAL_VALUE_TYPE *, const long *);
+static void encode_pdp11_d (const struct real_format *fmt,
+			    long *, const REAL_VALUE_TYPE *);
+static void decode_pdp11_d (const struct real_format *,
+			    REAL_VALUE_TYPE *, const long *);
+
+/* These two are taken from the corresponding vax descriptors
+   in real.c, changing only the encode/decode routine pointers.  */
+const struct real_format pdp11_f_format =
+  {
+    encode_pdp11_f,
+    decode_pdp11_f,
+    2,
+    1,
+    24,
+    24,
+    -127,
+    127,
+    15,
+    false,
+    false,
+    false,
+    false,
+    false
+  };
+
+const struct real_format pdp11_d_format =
+  {
+    encode_pdp11_d,
+    decode_pdp11_d,
+    2,
+    1,
+    56,
+    56,
+    -127,
+    127,
+    15,
+    false,
+    false,
+    false,
+    false,
+    false
+  };
+
+static void
+encode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
+		const REAL_VALUE_TYPE *r)
+{
+  (*vax_f_format.encode) (fmt, buf, r);
+  buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
+}
+
+static void
+decode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED,
+		REAL_VALUE_TYPE *r, const long *buf)
+{
+  long tbuf;
+  tbuf = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
+  (*vax_f_format.decode) (fmt, r, &tbuf);
+}
+
+static void
+encode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
+		const REAL_VALUE_TYPE *r)
+{
+  (*vax_d_format.encode) (fmt, buf, r);
+  buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
+  buf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
+}
+
+static void
+decode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED,
+		REAL_VALUE_TYPE *r, const long *buf)
+{
+  long tbuf[2];
+  tbuf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
+  tbuf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
+  (*vax_d_format.decode) (fmt, r, tbuf);
+}
+
 /* This is where the condition code register lives.  */
 /* rtx cc0_reg_rtx; - no longer needed? */
 
@@ -683,22 +767,12 @@
     {
       if (GET_CODE (operands[1]) == CONST_DOUBLE)
 	{
-	    /* floats only. not yet supported!
-
-	     -- compute it into PDP float format, - internally,
-	     just use IEEE and ignore possible problems ;-)
-
-	     we might get away with it !!!! */
-
-	    abort();
-	    
-#ifndef HOST_WORDS_BIG_ENDIAN
-	  latehalf[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
-	  operands[1] = GEN_INT	(CONST_DOUBLE_HIGH (operands[1]));
-#else /* HOST_WORDS_BIG_ENDIAN */
-	  latehalf[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
-	  operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
-#endif /* HOST_WORDS_BIG_ENDIAN */
+	  REAL_VALUE_TYPE r;
+	  long dval[2];
+	  REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+	  REAL_VALUE_TO_TARGET_DOUBLE (r, dval);
+	  latehalf[1] = GEN_INT (dval[1]);
+	  operands[1] = GEN_INT	(dval[0]);
 	}
       else if (GET_CODE(operands[1]) == CONST_INT)
 	{
@@ -1589,6 +1663,21 @@
     return 1;
 
 /* #undef REG_OK_STRICT */
+}
+
+/* This function checks whether a real value can be encoded as
+   a literal, i.e., addressing mode 27.  In that mode, real values
+   are one word values, so the remaining 48 bits have to be zero.  */
+int
+legitimate_const_double_p (rtx address)
+{
+  REAL_VALUE_TYPE r;
+  long sval[2];
+  REAL_VALUE_FROM_CONST_DOUBLE (r, address);
+  REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
+  if ((sval[0] & 0xffff) == 0 && sval[1] == 0)
+    return 1;
+  return 0;
 }
 
 /* A copy of output_addr_const modified for pdp11 expression syntax.
Index: pdp11.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pdp11/pdp11.h,v
retrieving revision 1.54
diff -u -r1.54 pdp11.h
--- pdp11.h	26 Jan 2004 18:17:58 -0000	1.54
+++ pdp11.h	3 Feb 2004 17:32:31 -0000
@@ -167,14 +167,27 @@
 /* Define this if most significant byte of a word is the lowest numbered.  */
 #define BYTES_BIG_ENDIAN 0
 
-/* Define this if most significant word of a multiword number is numbered.  */
+/* Define this if most significant word of a multiword number is first.  */
 #define WORDS_BIG_ENDIAN 1
 
+/* Define that floats are in VAX order, not high word first as for ints. */
+#define FLOAT_WORDS_BIG_ENDIAN 0
+
 /* Width of a word, in units (bytes). 
 
    UNITS OR BYTES - seems like units */
 #define UNITS_PER_WORD 2
 
+/* This machine doesn't use IEEE floats.  */
+/* Because the pdp11 (at least Unix) convention for 32 bit ints is
+   big endian, opposite for what you need for float, the vax float
+   conversion routines aren't actually used directly.  But the underlying
+   format is indeed the vax/pdp11 float format.  */
+#define TARGET_FLOAT_FORMAT VAX_FLOAT_FORMAT
+
+extern const struct real_format pdp11_f_format;
+extern const struct real_format pdp11_d_format;
+
 /* Maximum sized of reasonable data type 
    DImode or Dfmode ...*/
 #define MAX_FIXED_MODE_SIZE 64	
@@ -446,8 +459,8 @@
    operand as its first argument and the constraint letter as its
    second operand.
 
-   `Q'	is for memory references using take more than 1 instruction.
-   `R'	is for memory references which take 1 word for the instruction.  */
+   `Q'	is for memory references that require an extra word after the opcode.
+   `R'	is for memory references which are encoded within the opcode.  */
 
 #define EXTRA_CONSTRAINT(OP,CODE)					\
   ((GET_CODE (OP) != MEM) ? 0						\
@@ -678,7 +691,7 @@
 
 /* Maximum number of registers that can appear in a valid memory address.  */
 
-#define MAX_REGS_PER_ADDRESS 2
+#define MAX_REGS_PER_ADDRESS 1
 
 /* Recognize any constant value that is a valid address.  */
 
@@ -687,7 +700,8 @@
 /* Nonzero if the constant value X is a legitimate general operand.
    It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
 
-#define LEGITIMATE_CONSTANT_P(X) (TARGET_FPU? 1: !(GET_CODE(X) == CONST_DOUBLE))
+#define LEGITIMATE_CONSTANT_P(X)                                        \
+  (GET_CODE (X) != CONST_DOUBLE || legitimate_const_double_p (X))
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
@@ -1078,9 +1092,11 @@
   else if (GET_CODE (X) == MEM)						\
     output_address (XEXP (X, 0));					\
   else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != SImode)	\
-    { char buf[30];							\
-      real_to_decimal (buf, CONST_DOUBLE_REAL_VALUE (X), sizeof (buf), 0, 1); \
-      fprintf (FILE, "$0F%s", buf); }					\
+    { REAL_VALUE_TYPE r;						\
+      long sval[2];							\
+      REAL_VALUE_FROM_CONST_DOUBLE (r, X);				\
+      REAL_VALUE_TO_TARGET_DOUBLE (r, sval);				\
+      fprintf (FILE, "$%#o", sval[0] >> 16); }				\
   else { putc ('$', FILE); output_addr_const_pdp11 (FILE, X); }}
 
 /* Print a memory address as an operand to reference that memory location.  */


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