sparc.c (input_operand): Do not accept a LO_SUM MEM for TFmode when !v9.
authorDavid S. Miller <davem@pierdol.cobaltmicro.com>
Mon, 10 Aug 1998 23:47:28 +0000 (23:47 +0000)
committerDavid S. Miller <davem@gcc.gnu.org>
Mon, 10 Aug 1998 23:47:28 +0000 (16:47 -0700)
* config/sparc/sparc.c (input_operand): Do not accept a LO_SUM MEM
for TFmode when !v9.  We require offsettable memory addresses.
* config/sparc/sparc.h (ALTER_HARD_SUBREG): Handle TFmode to
DFmode register number conversions.
* config/sparc/sparc.md (define_split DFmode moves): If register
is a SUBREG do alter_subreg on it before using.
(define_expand movtf): Fixup comment about alignment on v9.
(define_split TFmode moves): Don't use gen_{high,low}part, create
explicit SUBREGs instead.

From-SVN: r21658

gcc/ChangeLog
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/config/sparc/sparc.md

index 7ce44f1e55db796d8b7ed6c6d2680bd26f9f7563..ee408a4e697bcc6821baad1ef8116c5a2a19e0a5 100644 (file)
@@ -1,3 +1,15 @@
+Mon Aug 10 22:39:09 1998  David S. Miller  <davem@pierdol.cobaltmicro.com>
+
+       * config/sparc/sparc.c (input_operand): Do not accept a LO_SUM MEM
+       for TFmode when !v9.  We require offsettable memory addresses.
+       * config/sparc/sparc.h (ALTER_HARD_SUBREG): Handle TFmode to
+       DFmode register number conversions.
+       * config/sparc/sparc.md (define_split DFmode moves): If register
+       is a SUBREG do alter_subreg on it before using.
+       (define_expand movtf): Fixup comment about alignment on v9.
+       (define_split TFmode moves): Don't use gen_{high,low}part, create
+       explicit SUBREGs instead.
+
 Mon Aug 10 19:02:55 1998  John Carr  <jfc@mit.edu>
 
        * Makefile.in (mbchar.o): Depend on mbchar.c.
index c4411fae5fd3cdb58eb5777f19f44b5560859d73..94e86fa3aa795b021db9b5e3b56b53820275d6cf 100644 (file)
@@ -1010,8 +1010,17 @@ input_operand (op, mode)
       rtx inside = XEXP (op, 0);
 
       if (GET_CODE (inside) == LO_SUM)
-       return (register_operand (XEXP (inside, 0), Pmode)
-               && CONSTANT_P (XEXP (inside, 1)));
+       {
+         /* We can't allow these because all of the splits
+            (eventually as they trickle down into DFmode
+            splits) require offsettable memory references.  */
+         if (! TARGET_V9
+             && GET_MODE (op) == TFmode)
+           return 0;
+
+         return (register_operand (XEXP (inside, 0), Pmode)
+                 && CONSTANT_P (XEXP (inside, 1)));
+       }
       return memory_address_p (mode, inside);
     }
 
index 9749bd1a3b607d4d2764bef77eee7ed8aa78de58..110e987eadd4c8facf0149850d0f94673b0e9c10 100644 (file)
@@ -980,7 +980,8 @@ while (0)
 
 /* A subreg in 64 bit mode will have the wrong offset for a floating point
    register.  The least significant part is at offset 1, compared to 0 for
-   integer registers.  This only applies when FMODE is a larger mode.  */
+   integer registers.  This only applies when FMODE is a larger mode.
+   We also need to handle a special case of TF-->DF conversions.  */
 #define ALTER_HARD_SUBREG(TMODE, WORD, FMODE, REGNO)                   \
      (TARGET_ARCH64                                                    \
       && (REGNO) >= SPARC_FIRST_FP_REG                                 \
@@ -988,7 +989,9 @@ while (0)
       && (TMODE) == SImode                                             \
       && !((FMODE) == QImode || (FMODE) == HImode)                     \
       ? ((REGNO) + 1)                                                  \
-      : ((REGNO) + (WORD)))
+      : ((TMODE) == DFmode && (FMODE) == TFmode)                       \
+        ? ((REGNO) + ((WORD) * 2))                                     \
+        : ((REGNO) + (WORD)))
 
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
    See sparc.c for how we initialize this.  */
index 5cf7e807db4f4854920fb2ab34fab44e307adb77..e054d25db662ed32688c135b88fe5be32e0b0f4b 100644 (file)
 
   self_reference = reg_mentioned_p (operands[0],
                                     XEXP (XEXP (word1, 0), 0));
+  if (GET_CODE (operands[0]) == SUBREG)
+    operands[0] = alter_subreg (operands[0]);
+
   if (self_reference != 0
       && WORDS_BIG_ENDIAN)
     {
   rtx word1 = change_address (operands[0], SFmode,
                              plus_constant_for_output (XEXP (word0, 0), 4));
 
+  if (GET_CODE (operands[1]) == SUBREG)
+    operands[1] = alter_subreg (operands[1]);
   emit_insn (gen_movsf (word0,
                        gen_highpart (SFmode, operands[1])));
   emit_insn (gen_movsf (word1,
                                                    operands[1]));
     }
 
-  /* Handle MEM cases first, note that even v9 only guarentees
-     8-byte alignment for quads so... */
+  /* Handle MEM cases first, note that only v9 guarentees
+     full 16-byte alignment for quads. */
   if (GET_CODE (operands[0]) == MEM)
     {
       if (register_operand (operands[1], TFmode))
@@ -3179,10 +3184,11 @@ movtf_is_ok:
   if (GET_CODE (set_src) == SUBREG)
     set_src = alter_subreg (set_src);
 
-  dest1 = gen_highpart (DFmode, set_dest);
-  dest2 = gen_lowpart (DFmode, set_dest);
-  src1 = gen_highpart (DFmode, set_src);
-  src2 = gen_lowpart (DFmode, set_src);
+  /* Ugly, but gen_highpart will crap out here for 32-bit targets.  */
+  dest1 = gen_rtx_SUBREG (DFmode, set_dest, WORDS_BIG_ENDIAN == 0);
+  dest2 = gen_rtx_SUBREG (DFmode, set_dest, WORDS_BIG_ENDIAN != 0);
+  src1 = gen_rtx_SUBREG (DFmode, set_src, WORDS_BIG_ENDIAN == 0);
+  src2 = gen_rtx_SUBREG (DFmode, set_src, WORDS_BIG_ENDIAN != 0);
 
   /* Now emit using the real source and destination we found, swapping
      the order if we detect overlap.  */
@@ -3210,11 +3216,13 @@ movtf_is_ok:
   rtx word0 = change_address (operands[1], DFmode, NULL_RTX);
   rtx word1 = change_address (operands[1], DFmode,
                              plus_constant_for_output (XEXP (word0, 0), 8));
+  rtx dest1, dest2;
 
-  emit_insn (gen_movdf (gen_highpart (DFmode, operands[0]),
-                       word0));
-  emit_insn (gen_movdf (gen_lowpart (DFmode, operands[0]),
-                       word1));
+  /* Ugly, but gen_highpart will crap out here for 32-bit targets.  */
+  dest1 = gen_rtx_SUBREG (DFmode, operands[0], WORDS_BIG_ENDIAN == 0);
+  dest2 = gen_rtx_SUBREG (DFmode, operands[0], WORDS_BIG_ENDIAN != 0);
+  emit_insn (gen_movdf (dest1, word0));
+  emit_insn (gen_movdf (dest2, word1));
   DONE;
 }")
 
@@ -3229,11 +3237,13 @@ movtf_is_ok:
   rtx word0 = change_address (operands[0], DFmode, NULL_RTX);
   rtx word1 = change_address (operands[0], DFmode,
                              plus_constant_for_output (XEXP (word0, 0), 8));
+  rtx src1, src2;
 
-  emit_insn (gen_movdf (word0,
-                       gen_highpart (DFmode, operands[1])));
-  emit_insn (gen_movdf (word1,
-                       gen_lowpart (DFmode, operands[1])));
+  /* Ugly, but gen_highpart will crap out here for 32-bit targets.  */
+  src1 = gen_rtx_SUBREG (DFmode, operands[1], WORDS_BIG_ENDIAN == 0);
+  src2 = gen_rtx_SUBREG (DFmode, operands[1], WORDS_BIG_ENDIAN != 0);
+  emit_insn (gen_movdf (word0, src1));
+  emit_insn (gen_movdf (word1, src2));
   DONE;
 }")
 \f