aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000
diff options
context:
space:
mode:
authorMichael Meissner <meissner@gcc.gnu.org>1996-07-10 19:12:59 +0000
committerMichael Meissner <meissner@gcc.gnu.org>1996-07-10 19:12:59 +0000
commitc4c4037309a400397313e01b3fd7c38ae2264acf (patch)
tree651af82f9d39d7e3e23414fb6406500a5b08b10f /gcc/config/rs6000
parenta72734717c6437270db05b0423c99c99fcaf7798 (diff)
downloadgcc-c4c4037309a400397313e01b3fd7c38ae2264acf.zip
gcc-c4c4037309a400397313e01b3fd7c38ae2264acf.tar.gz
gcc-c4c4037309a400397313e01b3fd7c38ae2264acf.tar.bz2
Use integer ops to load SF constants for software floating point; fix up software floating constants in general
From-SVN: r12421
Diffstat (limited to 'gcc/config/rs6000')
-rw-r--r--gcc/config/rs6000/rs6000.c20
-rw-r--r--gcc/config/rs6000/rs6000.h10
-rw-r--r--gcc/config/rs6000/rs6000.md220
3 files changed, 195 insertions, 55 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 408661c..7b78960 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -373,6 +373,24 @@ rs6000_immed_double_const (i0, i1, mode)
}
+/* 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;
+}
+
+
/* Return non-zero if this function is known to have a null epilogue. */
int
@@ -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)
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 7626eff..f291bae 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -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 ();
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index c015c3d..80135d3 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -5036,10 +5036,7 @@
"(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]));
@@ -5468,7 +5465,7 @@
}
}
- 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))
@@ -5480,9 +5477,9 @@
(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;
@@ -5490,23 +5487,47 @@
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"
"@
@@ -5515,8 +5536,11 @@
{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")])
(define_expand "movdf"
@@ -5557,15 +5581,101 @@
(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" "")
@@ -5580,9 +5690,9 @@
;; 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))"
@@ -5611,21 +5721,23 @@
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))"
@@ -5654,15 +5766,17 @@
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))"
@@ -5671,14 +5785,17 @@
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))"
@@ -5686,8 +5803,11 @@
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")])
;; Next come the multi-word integer load and store and the load and store
;; multiple insns.
@@ -5761,7 +5881,7 @@
}
}")
-(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
@@ -5906,7 +6026,7 @@
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