/* 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)
#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)
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, \
/* 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. */
[(set_attr "type" "*,load,store,*,*,*")
(set_attr "length" "*,*,*,8,12,16")])
\f
+(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")])
+\f
;; Next come the multi-word integer load and store and the load and store
;; multiple insns.
(define_expand "movdi"
#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)
#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 \
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") }, \
#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