Use integer ops to load SF constants for software floating point; fix up software...
authorMichael Meissner <meissner@gcc.gnu.org>
Wed, 10 Jul 1996 19:12:59 +0000 (19:12 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Wed, 10 Jul 1996 19:12:59 +0000 (19:12 +0000)
From-SVN: r12421

gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md

index 408661c1dbccd48d39e1700563c52cd5c94e5c61..7b7896001b4920e9f0ecd23cf10873f3b693173d 100644 (file)
@@ -372,6 +372,24 @@ rs6000_immed_double_const (i0, i1, mode)
   return immed_double_const (i0, i1, mode);
 }
 
+\f
+/* Return the GOT register, creating it if needed.  */
+
+struct rtx_def *
+rs6000_got_register (value)
+     rtx value;
+{
+  if (!pic_offset_table_rtx)
+    {
+      if (reload_in_progress || reload_completed)
+       fatal_insn ("internal error -- needed new GOT register during reload phase to load:", value);
+
+      pic_offset_table_rtx = gen_reg_rtx (SImode);
+    }
+
+  return pic_offset_table_rtx;
+}
+
 \f
 /* Return non-zero if this function is known to have a null epilogue.  */
 
@@ -614,7 +632,7 @@ num_insns_constant (op, mode)
      rtx op;
      enum machine_mode mode;
 {
-  if (mode != SImode && mode != DImode)
+  if (mode != SImode && mode != DImode && mode != SFmode && mode != DFmode)
     abort ();
 
   if (GET_CODE (op) == CONST_INT)
index 7626eff03c5ac0caa11c90bf53a3f120ae862255..f291bae62a39d892db5ff4bb755a8d8a8163e895 100644 (file)
@@ -1029,12 +1029,13 @@ enum reg_class
    We flag for special constants when we can copy the constant into
    a general register in two insns for DF/DI and one insn for SF.
 
-   'H' is used for DI constants that take 3 insns.  */
+   'H' is used for DI/DF constants that take 3 insns.  */
 
 #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)                         \
-  ((C) == 'G' ? easy_fp_constant (VALUE, GET_MODE (VALUE)) :           \
-   (C) == 'H' ? (num_insns_constant (VALUE, DImode) == 3) :            \
-   0)
+  (  (C) == 'G' ? (num_insns_constant (VALUE, GET_MODE (VALUE))                \
+                  == ((GET_MODE (VALUE) == SFmode) ? 1 : 2))           \
+   : (C) == 'H' ? (num_insns_constant (VALUE, GET_MODE (VALUE)) == 3)  \
+   : 0)
 
 /* Optional extra constraints for this machine.
 
@@ -3018,6 +3019,7 @@ extern void rs6000_override_options ();
 extern void rs6000_file_start ();
 extern struct rtx_def *rs6000_float_const ();
 extern struct rtx_def *rs6000_immed_double_const ();
+extern struct rtx_def *rs6000_got_register ();
 extern int direct_return ();
 extern int any_operand ();
 extern int short_cint_operand ();
index c015c3dfcf76e01a0632e2d315e4238cff10bf74..80135d3da06396f4c65ea528741a950ddd3887f3 100644 (file)
   "(DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) && flag_pic"
   "
 {
-  if (!pic_offset_table_rtx)
-    pic_offset_table_rtx = gen_reg_rtx (SImode);
-
-  operands[2] = pic_offset_table_rtx;
+  operands[2] = rs6000_got_register (operands[1]);
   if (flag_pic > 1)
     {
       emit_insn (gen_movsi_got_large (operands[0], operands[1], operands[2]));
        }
     }
 
-  if (CONSTANT_P (operands[1]))
+  if (CONSTANT_P (operands[1]) && TARGET_HARD_FLOAT)
     {
       operands[1] = force_const_mem (SFmode, operands[1]);
       if (! memory_address_p (SFmode, XEXP (operands[1], 0))
 
 (define_split
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
-       (match_operand:SF 1 "easy_fp_constant" ""))]
-  "reload_completed && REGNO (operands[0]) <= 31"
-  [(set (subreg:SI (match_dup 0) 0) (match_dup 2))]
+       (match_operand:SF 1 "const_double_operand" ""))]
+  "TARGET_32BIT && reload_completed && num_insns_constant (operands[1], SFmode) <= 1 && REGNO (operands[0]) <= 31"
+  [(set (match_dup 2) (match_dup 3))]
   "
 {
   long l;
 
   REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
   REAL_VALUE_TO_TARGET_SINGLE (rv, l);
-  operands[2] = GEN_INT(l);
+
+  operands[2] = gen_rtx (SUBREG, SImode, operands[0], 0);
+  operands[3] = GEN_INT(l);
 }")
 
-(define_insn ""
-  [(set (match_operand:SF 0 "fp_reg_or_mem_operand" "=f,f,m")
-       (match_operand:SF 1 "input_operand" "f,m,f"))]
+(define_split
+  [(set (match_operand:SF 0 "gpc_reg_operand" "")
+       (match_operand:SF 1 "const_double_operand" ""))]
+  "TARGET_32BIT && reload_completed && num_insns_constant (operands[1], SFmode) == 2 && REGNO (operands[0]) <= 31"
+  [(set (match_dup 2) (match_dup 3))
+   (set (match_dup 2) (ior:SI (match_dup 2) (match_dup 4)))]
+  "
+{
+  long l;
+  REAL_VALUE_TYPE rv;
+
+  REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
+  REAL_VALUE_TO_TARGET_SINGLE (rv, l);
+
+  operands[2] = gen_rtx (SUBREG, SImode, operands[0], 0);
+  operands[3] = GEN_INT(l & 0xffff0000);
+  operands[4] = GEN_INT(l & 0x0000ffff);
+}")
+
+(define_insn "*movsf_hardfloat"
+  [(set (match_operand:SF 0 "fp_reg_or_mem_operand" "=f,f,m,!r,!r")
+       (match_operand:SF 1 "input_operand" "f,m,f,G,Fn"))]
   "(gpc_reg_operand (operands[0], SFmode)
    || gpc_reg_operand (operands[1], SFmode)) && TARGET_HARD_FLOAT"
   "@
    fmr %0,%1
    lfs%U1%X1 %0,%1
-   stfs%U0%X0 %1,%0"
-  [(set_attr "type" "fp,fpload,fpstore")])
+   stfs%U0%X0 %1,%0
+   #
+   #"
+  [(set_attr "type" "fp,fpload,fpstore,*,*")
+   (set_attr "length" "4,4,4,4,8")])
 
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,r,r,r")
-       (match_operand:SF 1 "input_operand" "r,m,r,I,J,R"))]
+(define_insn "*movsf_softfloat"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,r")
+       (match_operand:SF 1 "input_operand" "r,m,r,I,J,R,G,Fn"))]
   "(gpc_reg_operand (operands[0], SFmode)
    || gpc_reg_operand (operands[1], SFmode)) && TARGET_SOFT_FLOAT"
   "@
    {st%U0%X0|stw%U0%X0} %1,%0
    {lil|li} %0,%1
    {liu|lis} %0,%v1
-   {cal|la} %0,%1(%*)"
-  [(set_attr "type" "*,load,store,*,*,*")])
+   {cal|la} %0,%1(%*)
+   #
+   #"
+  [(set_attr "type" "*,load,store,*,*,*,*,*")
+   (set_attr "length" "4,4,4,4,4,4,4,8")])
 
 \f
 (define_expand "movdf"
 
 (define_split
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
-       (match_operand:DF 1 "easy_fp_constant" ""))]
-  "TARGET_32BIT && reload_completed && REGNO (operands[0]) <= 31"
-  [(set (match_dup 2) (match_dup 3))
-   (set (match_dup 4) (match_dup 5))]
+       (match_operand:DF 1 "const_int_operand" ""))]
+  "TARGET_32BIT && reload_completed && num_insns_constant (operands[1], DFmode) <= 1 && REGNO (operands[0]) <= 31"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 1))]
+  "
+{
+  operands[2] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN == 0);
+  operands[3] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN != 0);
+  operands[4] = (INTVAL (operands[1]) & 0x80000000) ? constm1_rtx : const0_rtx;
+}")
+
+(define_split
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (match_operand:DF 1 "const_int_operand" ""))]
+  "TARGET_32BIT && reload_completed && num_insns_constant (operands[1], DFmode) >= 2 && REGNO (operands[0]) <= 31"
+  [(set (match_dup 3) (match_dup 5))
+   (set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (ior:SI (match_dup 3) (match_dup 6)))]
+  "
+{
+  HOST_WIDE_INT value = INTVAL (operands[1]);
+  operands[2] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN == 0);
+  operands[3] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN != 0);
+  operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx;
+  operands[5] = GEN_INT (value & 0xffff0000);
+  operands[6] = GEN_INT (value & 0x0000ffff);
+}")
+
+(define_split
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (match_operand:DF 1 "const_double_operand" ""))]
+  "TARGET_32BIT && reload_completed && num_insns_constant (operands[1], DFmode) <= 2 && REGNO (operands[0]) <= 31"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+  "
+{
+  operands[2] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN == 0);
+  operands[3] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN != 0);
+  operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
+  operands[5] = GEN_INT (CONST_DOUBLE_LOW  (operands[1]));
+}")
+
+(define_split
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (match_operand:DF 1 "const_double_operand" ""))]
+  "TARGET_32BIT && reload_completed && num_insns_constant (operands[1], DFmode) == 3 && REGNO (operands[0]) <= 31"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))
+   (set (match_dup 2) (ior:SI (match_dup 2) (match_dup 6)))]
+  "
+{
+  HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
+  HOST_WIDE_INT low  = CONST_DOUBLE_LOW  (operands[1]);
+  rtx high_reg = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN == 0);
+  rtx low_reg  = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN != 0);
+
+  if (((unsigned HOST_WIDE_INT) (low + 0x8000) < 0x10000)
+      || (low & 0xffff) == 0)
+    {
+      operands[2] = high_reg;
+      operands[3] = low_reg;
+      operands[4] = GEN_INT (high & 0xffff0000);
+      operands[5] = GEN_INT (low);
+      operands[6] = GEN_INT (high & 0x0000ffff);
+    }
+  else
+    {
+      operands[2] = low_reg;
+      operands[3] = high_reg;
+      operands[4] = GEN_INT (low & 0xffff0000);
+      operands[5] = GEN_INT (high);
+      operands[6] = GEN_INT (low & 0x0000ffff);
+    }
+}")
+
+(define_split
+  [(set (match_operand:DF 0 "gpc_reg_operand" "")
+       (match_operand:DF 1 "const_double_operand" ""))]
+  "TARGET_32BIT && reload_completed && num_insns_constant (operands[1], DFmode) >= 4 && REGNO (operands[0]) <= 31"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))
+   (set (match_dup 2) (ior:SI (match_dup 2) (match_dup 6)))
+   (set (match_dup 3) (ior:SI (match_dup 3) (match_dup 7)))]
   "
-{ operands[2] = operand_subword (operands[0], 0, 0, DFmode);
-  operands[3] = operand_subword (operands[1], 0, 0, DFmode);
-  operands[4] = operand_subword (operands[0], 1, 0, DFmode);
-  operands[5] = operand_subword (operands[1], 1, 0, DFmode); }")
+{
+  HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
+  HOST_WIDE_INT low  = CONST_DOUBLE_LOW  (operands[1]);
+
+  operands[2] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN == 0);
+  operands[3] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN != 0);
+  operands[4] = GEN_INT (high & 0xffff0000);
+  operands[5] = GEN_INT (low  & 0xffff0000);
+  operands[6] = GEN_INT (high & 0x0000ffff);
+  operands[7] = GEN_INT (low  & 0x0000ffff);
+}")
 
 (define_split
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
 ;; the constant into an FP register, since it will probably be used there.
 ;; The "??" is a kludge until we can figure out a more reasonable way
 ;; of handling these non-offsettable values.
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,o,!r,f,f,m")
-       (match_operand:DF 1 "input_operand" "r,o,r,G,f,m,f"))]
+(define_insn "*movdf_hardfloat32"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,o,!r,!r,!r,f,f,m")
+       (match_operand:DF 1 "input_operand" "r,o,r,G,H,F,f,m,f"))]
   "! TARGET_POWERPC64 && TARGET_HARD_FLOAT
    && (register_operand (operands[0], DFmode)
        || register_operand (operands[1], DFmode))"
     case 2:
       return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
     case 3:
-      return \"#\";
     case 4:
-      return \"fmr %0,%1\";
     case 5:
-      return \"lfd%U1%X1 %0,%1\";
+      return \"#\";
     case 6:
+      return \"fmr %0,%1\";
+    case 7:
+      return \"lfd%U1%X1 %0,%1\";
+    case 8:
       return \"stfd%U0%X0 %1,%0\";
     }
 }"
-  [(set_attr "type" "*,load,store,*,fp,fpload,fpstore")
-   (set_attr "length" "8,8,8,8,*,*,*")])
+  [(set_attr "type" "*,load,store,*,*,*,fp,fpload,fpstore")
+   (set_attr "length" "8,8,8,8,12,16,*,*,*")])
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,o,r")
-       (match_operand:DF 1 "input_operand" "r,o,r,G"))]
+(define_insn "*movdf_softfloat32"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,o,r,r,r")
+       (match_operand:DF 1 "input_operand" "r,o,r,G,H,F"))]
   "! TARGET_POWERPC64 && TARGET_SOFT_FLOAT
    && (register_operand (operands[0], DFmode)
        || register_operand (operands[1], DFmode))"
     case 2:
       return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
     case 3:
+    case 4:
+    case 5:
       return \"#\";
     }
 }"
-  [(set_attr "type" "*,load,store,*")
-   (set_attr "length" "8,8,8,8")])
+  [(set_attr "type" "*,load,store,*,*,*")
+   (set_attr "length" "8,8,8,8,12,16")])
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,o,!r,f,f,m")
-       (match_operand:DF 1 "input_operand" "r,o,r,G,f,m,f"))]
+(define_insn "*movdf_hardfloat64"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,o,!r,!r,!r,f,f,m")
+       (match_operand:DF 1 "input_operand" "r,o,r,G,H,F,f,m,f"))]
   "TARGET_POWERPC64 && TARGET_HARD_FLOAT
    && (register_operand (operands[0], DFmode)
        || register_operand (operands[1], DFmode))"
    ld%U1%X1 %0,%1
    std%U0%X0 %1,%0
    #
+   #
+   #
    fmr %0,%1
    lfd%U1%X1 %0,%1
    stfd%U0%X0 %1,%0"
-  [(set_attr "type" "*,load,store,*,fp,fpload,fpstore")])
+  [(set_attr "type" "*,load,store,*,*,*,fp,fpload,fpstore")
+   (set_attr "length" "4,4,4,8,12,16,4,4,4")])
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,o,r")
-       (match_operand:DF 1 "input_operand" "r,o,r,G"))]
+(define_insn "*movdf_softfloat64"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,o,r,r,r")
+       (match_operand:DF 1 "input_operand" "r,o,r,G,H,F"))]
   "TARGET_POWERPC64 && TARGET_SOFT_FLOAT
    && (register_operand (operands[0], DFmode)
        || register_operand (operands[1], DFmode))"
    mr %0,%1
    ld%U1%X1 %0,%1
    std%U0%X0 %1,%0
+   #
+   #
    #"
-  [(set_attr "type" "*,load,store,*")])
+  [(set_attr "type" "*,load,store,*,*,*")
+   (set_attr "length" "*,*,*,8,12,16")])
 \f
 ;; Next come the multi-word integer load and store and the load and store
 ;; multiple insns.
     }
 }")
 
-(define_insn ""
+(define_insn "*movdi_32"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,f,f,m,r,r,r,r,r")
        (match_operand:DI 1 "input_operand" "r,m,r,f,m,f,IJK,n,G,H,F"))]
   "TARGET_32BIT
   operands[7] = GEN_INT (low  & 0x0000ffff);
 }")
 
-(define_insn ""
+(define_insn "*movdi_64"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,f,f,m,r,*h,*h")
        (match_operand:DI 1 "input_operand" "r,m,r,I,J,nF,R,f,m,f,*h,r,0"))]
   "TARGET_64BIT