From 06f4e019e245e05883b43893b9c15d75ab72a303 Mon Sep 17 00:00:00 2001 From: David Edelsohn Date: Tue, 20 Nov 2001 16:13:07 +0000 Subject: [PATCH] rs6000.c (rs6000_emit_eh_toc_restore): Remove ALIGN parm. * rs6000.c (rs6000_emit_eh_toc_restore): Remove ALIGN parm. * rs6000.c (rs6000_emit_move): Add TFmode case. * sysv4.h (MASK_LONG_DOUBLE_128, TARGET_LONG_DOUBLE_128, LONG_DOUBLE_TYPE_SIZE, MAX_LONG_DOUBLE_TYPE_SIZE, LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Move from here... * rs6000.h: ... to here. * rs6000.md (movtf, extenddftf2, extendsftf2, trunctfdf2, trunctfsf2, floatditf2, floatsitf2, fix_trunctfdi2, fix_trunctfsi2, negtf2, abstf2, nabstf2): New patterns. From-SVN: r47218 --- gcc/ChangeLog | 13 +++ gcc/config/rs6000/rs6000.c | 5 +- gcc/config/rs6000/rs6000.h | 21 ++++- gcc/config/rs6000/rs6000.md | 177 ++++++++++++++++++++++++++++++++++++ gcc/config/rs6000/sysv4.h | 24 +---- 5 files changed, 214 insertions(+), 26 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f5325dcf8a7..96e01267ac9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2001-11-20 David Edelsohn + + * rs6000.c (rs6000_emit_eh_toc_restore): Remove ALIGN parm. + + * rs6000.c (rs6000_emit_move): Add TFmode case. + * sysv4.h (MASK_LONG_DOUBLE_128, TARGET_LONG_DOUBLE_128, + LONG_DOUBLE_TYPE_SIZE, MAX_LONG_DOUBLE_TYPE_SIZE, + LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Move from here... + * rs6000.h: ... to here. + * rs6000.md (movtf, extenddftf2, extendsftf2, trunctfdf2, + trunctfsf2, floatditf2, floatsitf2, fix_trunctfdi2, + fix_trunctfsi2, negtf2, abstf2, nabstf2): New patterns. + Tue Nov 20 06:41:38 2001 Richard Kenner * emit-rtl.c (get_mem_attrs): Fix typo. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 186692db38c..d9b3e0902ec 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1935,6 +1935,7 @@ rs6000_emit_move (dest, source, mode) operands[1] = force_const_mem (mode, operands[1]); break; + case TFmode: case DFmode: case SFmode: if (CONSTANT_P (operands[1]) @@ -6594,7 +6595,7 @@ rs6000_emit_eh_toc_restore (stacksize) emit_label (loop_start); do_compare_rtx_and_jump (opcode, tocompare, NE, 1, - SImode, NULL_RTX, 0, NULL_RTX, + SImode, NULL_RTX, NULL_RTX, no_toc_restore_needed); mem = gen_rtx_MEM (Pmode, @@ -6604,7 +6605,7 @@ rs6000_emit_eh_toc_restore (stacksize) emit_label (no_toc_restore_needed); do_compare_rtx_and_jump (top_of_stack, bottom_of_stack, EQ, 1, - Pmode, NULL_RTX, 0, NULL_RTX, + Pmode, NULL_RTX, NULL_RTX, loop_exit); mem = gen_rtx_MEM (Pmode, bottom_of_stack); diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 238cedc4562..94aa09e8b93 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -217,6 +217,9 @@ extern int target_flags; /* Enhance the current ABI with AltiVec extensions. */ #define MASK_ALTIVEC_ABI 0x00100000 +/* Use 128-bit long double. */ +#define MASK_LONG_DOUBLE_128 0x00200000 + #define TARGET_POWER (target_flags & MASK_POWER) #define TARGET_POWER2 (target_flags & MASK_POWER2) #define TARGET_POWERPC (target_flags & MASK_POWERPC) @@ -237,6 +240,7 @@ extern int target_flags; #define TARGET_SCHED_PROLOG (target_flags & MASK_SCHED_PROLOG) #define TARGET_ALTIVEC (target_flags & MASK_ALTIVEC) #define TARGET_ALTIVEC_ABI (target_flags & MASK_ALTIVEC_ABI) +#define TARGET_LONG_DOUBLE_128 (target_flags & MASK_LONG_DOUBLE_128) #define TARGET_32BIT (! TARGET_64BIT) #define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT) @@ -341,6 +345,10 @@ extern int target_flags; N_("Generate fused multiply/add instructions")},\ {"no-fused-madd", MASK_NO_FUSED_MADD, \ N_("Don't generate fused multiply/add instructions")},\ + {"long-double-64", -MASK_LONG_DOUBLE_128, \ + N_("Use 64 bit long doubles") }, \ + {"long-double-128", MASK_LONG_DOUBLE_128, \ + N_("Use 128 bit long doubles") }, \ {"sched-prolog", MASK_SCHED_PROLOG, \ ""}, \ {"no-sched-prolog", -MASK_SCHED_PROLOG, \ @@ -576,7 +584,18 @@ extern int rs6000_debug_arg; /* debug argument handling */ /* A C expression for the size in bits of the type `long double' on the target machine. If you don't define this, the default is two words. */ -#define LONG_DOUBLE_TYPE_SIZE 64 +#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64) + +/* Constant which presents upper bound of the above value. */ +#define MAX_LONG_DOUBLE_TYPE_SIZE 128 + +/* Define this to set long double type size to use in libgcc2.c, which can + not depend on target_flags. */ +#ifdef __LONG_DOUBLE_128__ +#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128 +#else +#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64 +#endif /* Width in bits of a pointer. See also the macro `Pmode' defined below. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 6b8dda70683..0292c57ec45 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -7906,6 +7906,183 @@ [(set_attr "type" "*,load,store,*,*,*") (set_attr "length" "*,*,*,8,12,16")]) +(define_expand "movtf" + [(set (match_operand:TF 0 "general_operand" "") + (match_operand:TF 1 "any_operand" ""))] + "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" + "{ rs6000_emit_move (operands[0], operands[1], TFmode); DONE; }") + +(define_insn "*movtf_internal" + [(set (match_operand:TF 0 "nonimmediate_operand" "=f,f,m,!r,!r,!r") + (match_operand:TF 1 "input_operand" "f,m,f,G,H,F"))] + "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128 + && (gpc_reg_operand (operands[0], TFmode) + || gpc_reg_operand (operands[1], TFmode))" + "* +{ + switch (which_alternative) + { + default: + abort (); + case 0: + /* We normally copy the low-numbered register first. However, if + the first register operand 0 is the same as the second register of + operand 1, we must copy in the opposite order. */ + if (REGNO (operands[0]) == REGNO (operands[1]) + 1) + return \"fmr %L0,%L1\;fmr %0,%1\"; + else + return \"fmr %0,%1\;fmr %L0,%L1\"; + case 1: + return \"lfd %0,%1\;lfd %L0,%L1\"; + case 2: + return \"stfd %1,%0\;stfd %L1,%L0\"; + case 3: + case 4: + case 5: + return \"#\"; + } +}" + [(set_attr "type" "fp,fpload,fpstore,*,*,*") + (set_attr "length" "8,8,8,12,16,20")]) + +(define_split + [(set (match_operand:TF 0 "gpc_reg_operand" "") + (match_operand:TF 1 "const_double_operand" ""))] + "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" + [(set (match_dup 3) (match_dup 1)) + (set (match_dup 0) + (float_extend:TF (match_dup 3)))] + " +{ + operands[2] = operand_subword (operands[1], 0, 0, DFmode); + operands[3] = gen_reg_rtx (DFmode); +}") + +(define_insn_and_split "extenddftf2" + [(set (match_operand:TF 0 "gpc_reg_operand" "=f") + (float_extend:TF (match_operand:DF 1 "gpc_reg_operand" "f")))] + "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" + "#" + "" + [(set (match_dup 2) (match_dup 3))] + " +{ + operands[2] = gen_rtx_REG (DFmode, REGNO (operands[0] + 1)); + operands[3] = CONST0_RTX (DFmode); +}") + +(define_insn_and_split "extendsftf2" + [(set (match_operand:TF 0 "gpc_reg_operand" "=f") + (float_extend:TF (match_operand:SF 1 "gpc_reg_operand" "f")))] + "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" + "#" + "" + [(set (match_dup 2) (match_dup 3))] + " +{ + operands[2] = gen_rtx_REG (SFmode, REGNO (operands[0] + 1)); + operands[3] = CONST0_RTX (SFmode); +}") + +(define_insn "trunctfdf2" + [(set (match_operand:DF 0 "gpc_reg_operand" "=f") + (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "f")))] + "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" + "fadd %0,%1,%L1" + [(set_attr "type" "fp") + (set_attr "length" "8")]) + +(define_insn_and_split "trunctfsf2" + [(set (match_operand:SF 0 "gpc_reg_operand" "=f") + (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "f")))] + "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" + "#" + "" + [(set (match_dup 2) + (float_truncate:DF (match_dup 1))) + (set (match_dup 0) + (float_truncate:SF (match_dup 2)))] + " +{ + operands[2] = gen_reg_rtx (DFmode); +}") + +(define_expand "floatditf2" + [(set (match_dup 2) + (float:DF (match_operand:DI 1 "gpc_reg_operand" ""))) + (set (match_operand:TF 0 "gpc_reg_operand" "") + (float_extend:TF (match_dup 2)))] + "DEFAULT_ABI == ABI_AIX && TARGET_POWERPC64 + && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" + "{ operands[2] = gen_reg_rtx (DFmode); }") + +(define_expand "floatsitf2" + [(set (match_dup 2) + (float:DF (match_operand:SI 1 "gpc_reg_operand" ""))) + (set (match_operand:TF 0 "gpc_reg_operand" "") + (float_extend:TF (match_dup 2)))] + "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" + "{ operands[2] = gen_reg_rtx (DFmode); }") + +(define_expand "fix_trunctfdi2" + [(set (match_dup 2) + (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" ""))) + (set (match_operand:DI 0 "gpc_reg_operand" "") + (fix:SI (match_dup 2)))] + "DEFAULT_ABI == ABI_AIX && TARGET_POWERPC64 + && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" + "{ operands[2] = gen_reg_rtx (DFmode); }") + +(define_expand "fix_trunctfsi2" + [(set (match_dup 2) + (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" ""))) + (set (match_operand:SI 0 "gpc_reg_operand" "") + (fix:SI (match_dup 2)))] + "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" + "{ operands[2] = gen_reg_rtx (DFmode); }") + +(define_insn "negtf2" + [(set (match_operand:TF 0 "gpc_reg_operand" "=f") + (neg:TF (match_operand:TF 1 "gpc_reg_operand" "f")))] + "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" + "* +{ + if (REGNO (operands[0]) == REGNO (operands[1]) + 1) + return \"fneg %L0,%L1\;fneg %0,%1\"; + else + return \"fneg %0,%1\;fneg %L0,%L1\"; +}" + [(set_attr "type" "fp") + (set_attr "length" "8")]) + +(define_insn "abstf2" + [(set (match_operand:TF 0 "gpc_reg_operand" "=f") + (abs:TF (match_operand:TF 1 "gpc_reg_operand" "f")))] + "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" + "* +{ + if (REGNO (operands[0]) == REGNO (operands[1]) + 1) + return \"fabs %L0,%L1\;fabs %0,%1\"; + else + return \"fabs %0,%1\;fabs %L0,%L1\"; +}" + [(set_attr "type" "fp") + (set_attr "length" "8")]) + +(define_insn "" + [(set (match_operand:TF 0 "gpc_reg_operand" "=f") + (neg:TF (abs:TF (match_operand:TF 1 "gpc_reg_operand" "f"))))] + "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" + "* +{ + if (REGNO (operands[0]) == REGNO (operands[1]) + 1) + return \"fnabs %L0,%L1\;fnabs %0,%1\"; + else + return \"fnabs %0,%1\;fnabs %L0,%L1\"; +}" + [(set_attr "type" "fp") + (set_attr "length" "8")]) + ;; Next come the multi-word integer load and store and the load and store ;; multiple insns. (define_expand "movdi" diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index fcff961c90d..99e4c27ba03 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -56,8 +56,7 @@ extern enum rs6000_sdata_type rs6000_sdata; #define MASK_LITTLE_ENDIAN 0x04000000 /* Target is little endian. */ #define MASK_REGNAMES 0x02000000 /* Use alternate register names. */ #define MASK_PROTOTYPE 0x01000000 /* Only prototyped fcns pass variable args. */ -#define MASK_LONG_DOUBLE_128 0x00800000 /* Use IEEE quad long double. */ -#define MASK_NO_BITFIELD_WORD 0x00400000 /* Bitfields cannot cross word boundaries */ +#define MASK_NO_BITFIELD_WORD 0x00800000 /* Bitfields cannot cross word boundaries */ #define TARGET_NO_BITFIELD_TYPE (target_flags & MASK_NO_BITFIELD_TYPE) #define TARGET_STRICT_ALIGN (target_flags & MASK_STRICT_ALIGN) @@ -66,7 +65,6 @@ extern enum rs6000_sdata_type rs6000_sdata; #define TARGET_LITTLE_ENDIAN (target_flags & MASK_LITTLE_ENDIAN) #define TARGET_REGNAMES (target_flags & MASK_REGNAMES) #define TARGET_PROTOTYPE (target_flags & MASK_PROTOTYPE) -#define TARGET_LONG_DOUBLE_128 (target_flags & MASK_LONG_DOUBLE_128) #define TARGET_NO_BITFIELD_WORD (target_flags & MASK_NO_BITFIELD_WORD) #define TARGET_TOC ((target_flags & MASK_64BIT) \ || ((target_flags & (MASK_RELOCATABLE \ @@ -126,10 +124,6 @@ extern int g_switch_set; /* Whether -G xx was passed. */ N_("Produce big endian code.") }, \ { "big", -MASK_LITTLE_ENDIAN, \ N_("Produce big endian code.") }, \ - { "long-double-64", -MASK_LONG_DOUBLE_128, \ - N_("Use 64 bit long doubles") }, \ - { "long-double-128", MASK_LONG_DOUBLE_128, \ - N_("Use 128 bit long doubles") }, \ { "no-toc", 0, N_("no description yet") }, \ { "toc", MASK_MINIMAL_TOC, N_("no description yet") }, \ { "full-toc", MASK_MINIMAL_TOC, N_("no description yet") }, \ @@ -366,22 +360,6 @@ do { \ #undef WCHAR_TYPE_SIZE #define WCHAR_TYPE_SIZE 32 -/* Define for support of TFmode long double and REAL_ARITHMETIC. - PowerPC SVR4 ABI says that long double is 4 words. */ -#undef LONG_DOUBLE_TYPE_SIZE -#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64) - -/* Constant which presents upper bound of the above value. */ -#define MAX_LONG_DOUBLE_TYPE_SIZE 128 - -/* Define this to set long double type size to use in libgcc2.c, which can - not depend on target_flags. */ -#ifdef __LONG_DOUBLE_128__ -#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128 -#else -#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64 -#endif - /* Make int foo : 8 not cause structures to be aligned to an int boundary. */ /* Override elfos.h definition. */ #undef PCC_BITFIELD_TYPE_MATTERS -- 2.30.2