{
unsigned HOST_WIDE_INT reg_size;
- /* TF/TD modes are special in that they always take 2 registers. */
+ /* 128-bit floating point usually takes 2 registers, unless it is IEEE
+ 128-bit floating point that can go in vector registers, which has VSX
+ memory addressing. */
if (FP_REGNO_P (regno))
- reg_size = ((VECTOR_MEM_VSX_P (mode) && mode != TDmode && mode != TFmode)
+ reg_size = (VECTOR_MEM_VSX_P (mode)
? UNITS_PER_VSX_WORD
: UNITS_PER_FP_WORD);
asked for it. */
if (TARGET_VSX && VSX_REGNO_P (regno)
&& (VECTOR_MEM_VSX_P (mode)
+ || FLOAT128_VECTOR_P (mode)
|| reg_addr[mode].scalar_in_vmx_p
|| (TARGET_VSX_TIMODE && mode == TImode)
|| (TARGET_VADDUQM && mode == V1TImode)))
modes and DImode. */
if (FP_REGNO_P (regno))
{
+ if (FLOAT128_VECTOR_P (mode))
+ return false;
+
if (SCALAR_FLOAT_MODE_P (mode)
&& (mode != TDmode || (regno % 2) == 0)
&& FP_REGNO_P (last_regno))
machine_mode m2 = (machine_mode)m;
int reg_size2 = reg_size;
- /* TFmode/TDmode always takes 2 registers, even in VSX. */
- if (TARGET_VSX && VSX_REG_CLASS_P (c)
- && (m == TDmode || m == TFmode))
+ /* TDmode & IBM 128-bit floating point always takes 2 registers, even
+ in VSX. */
+ if (TARGET_VSX && VSX_REG_CLASS_P (c) && FLOAT128_2REG_P (m))
reg_size2 = UNITS_PER_FP_WORD;
rs6000_class_max_nregs[m][c]
|| mode == DDmode || mode == TDmode || mode == PTImode)
&& REG_P (SUBREG_REG (op))
&& (GET_MODE (SUBREG_REG (op)) == DFmode
- || GET_MODE (SUBREG_REG (op)) == TFmode))
+ || GET_MODE (SUBREG_REG (op)) == TFmode
+ || GET_MODE (SUBREG_REG (op)) == IFmode
+ || GET_MODE (SUBREG_REG (op)) == KFmode))
return true;
/* Reject (subreg:DF (reg:DI)); likewise with subreg:TF and
reg:TI. */
if (GET_CODE (op) == SUBREG
- && (mode == DFmode || mode == TFmode)
+ && (mode == DFmode || mode == TFmode || mode == IFmode
+ || mode == KFmode)
&& REG_P (SUBREG_REG (op))
&& (GET_MODE (SUBREG_REG (op)) == DImode
|| GET_MODE (SUBREG_REG (op)) == TImode
case V2DImode:
case V1TImode:
case TImode:
+ case TFmode:
+ case KFmode:
/* AltiVec/VSX vector modes. Only reg+reg addressing is valid. While
TImode is not a vector mode, if we want to use the VSX registers to
- move it around, we need to restrict ourselves to reg+reg
- addressing. */
+ move it around, we need to restrict ourselves to reg+reg addressing.
+ Similarly for IEEE 128-bit floating point that is passed in a single
+ vector register. */
if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
return false;
break;
break;
case TFmode:
+ case IFmode:
+ case KFmode:
if (TARGET_E500_DOUBLE)
return (SPE_CONST_OFFSET_OK (offset)
&& SPE_CONST_OFFSET_OK (offset + 8));
case TDmode:
case TImode:
case PTImode:
+ case IFmode:
+ case KFmode:
/* As in legitimate_offset_address_p we do not assume
worst-case. The mode here is just a hint as to the registers
used. A TImode is usually in gprs, but may actually be in
&& !reg_addr[mode].scalar_in_vmx_p
&& mode != TFmode
&& mode != TDmode
+ && mode != IFmode
+ && mode != KFmode
&& (mode != TImode || !TARGET_VSX_TIMODE)
&& mode != PTImode
&& (mode != DImode || TARGET_POWERPC64)
return 1;
if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict, false))
return 1;
- if (mode != TFmode
- && mode != TDmode
+ if (!FLOAT128_2REG_P (mode)
&& ((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
|| TARGET_POWERPC64
|| (mode != DFmode && mode != DDmode)
/* 128-bit constant floating-point values on Darwin should really be loaded
as two parts. However, this premature splitting is a problem when DFmode
values can go into Altivec registers. */
- if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
- && !reg_addr[DFmode].scalar_in_vmx_p
- && mode == TFmode && GET_CODE (operands[1]) == CONST_DOUBLE)
+ if (FLOAT128_IBM_P (mode) && !reg_addr[DFmode].scalar_in_vmx_p
+ && GET_CODE (operands[1]) == CONST_DOUBLE)
{
rs6000_emit_move (simplify_gen_subreg (DFmode, operands[0], mode, 0),
simplify_gen_subreg (DFmode, operands[1], mode, 0),
case TFmode:
case TDmode:
- rs6000_eliminate_indexed_memrefs (operands);
+ case IFmode:
+ case KFmode:
+ if (FLOAT128_2REG_P (mode))
+ rs6000_eliminate_indexed_memrefs (operands);
/* fall through */
case DFmode:
\f
/* Nonzero if we can use a floating-point register to pass this arg. */
#define USE_FP_FOR_ARG_P(CUM,MODE) \
- (SCALAR_FLOAT_MODE_P (MODE) \
+ (SCALAR_FLOAT_MODE_NOT_VECTOR_P (MODE) \
&& (CUM)->fregno <= FP_ARG_MAX_REG \
&& TARGET_HARD_FLOAT && TARGET_FPRS)
if (field_count > 0)
{
- int n_regs = (SCALAR_FLOAT_MODE_P (field_mode)?
+ int n_regs = (SCALAR_FLOAT_MODE_P (field_mode) ?
(GET_MODE_SIZE (field_mode) + 7) >> 3 : 1);
/* The ELFv2 ABI allows homogeneous aggregates to occupy
return true;
}
- if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD && TYPE_MODE (type) == TFmode)
+ if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD
+ && FLOAT128_IEEE_P (TYPE_MODE (type)))
return true;
return false;
<= 8))
rs6000_returns_struct = true;
}
- if (SCALAR_FLOAT_MODE_P (return_mode))
+ if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (return_mode))
rs6000_passes_float = true;
else if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode)
|| SPE_VECTOR_MODE (return_mode))
&& (GET_MODE_SIZE (mode) == 8
|| (TARGET_HARD_FLOAT
&& TARGET_FPRS
- && (mode == TFmode || mode == TDmode))))
+ && FLOAT128_2REG_P (mode))))
return 64;
+ else if (FLOAT128_VECTOR_P (mode))
+ return 128;
else if (SPE_VECTOR_MODE (mode)
|| (type && TREE_CODE (type) == VECTOR_TYPE
&& int_size_in_bytes (type) >= 8
if (DEFAULT_ABI == ABI_V4
&& cum->escapes)
{
- if (SCALAR_FLOAT_MODE_P (mode))
+ if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode))
rs6000_passes_float = true;
else if (named && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
rs6000_passes_vector = true;
if (TARGET_HARD_FLOAT && TARGET_FPRS
&& ((TARGET_SINGLE_FLOAT && mode == SFmode)
|| (TARGET_DOUBLE_FLOAT && mode == DFmode)
- || (mode == TFmode && !TARGET_IEEEQUAD)
- || mode == SDmode || mode == DDmode || mode == TDmode))
+ || FLOAT128_2REG_P (mode)
+ || DECIMAL_FLOAT_MODE_P (mode)))
{
/* _Decimal128 must use an even/odd register pair. This assumes
that the register number is odd when fregno is odd. */
if (mode == TDmode && (cum->fregno % 2) == 1)
cum->fregno++;
- if (cum->fregno + (mode == TFmode || mode == TDmode ? 1 : 0)
+ if (cum->fregno + (FLOAT128_2REG_P (mode) ? 1 : 0)
<= FP_ARG_V4_MAX_REG)
cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
else
{
cum->fregno = FP_ARG_V4_MAX_REG + 1;
- if (mode == DFmode || mode == TFmode
+ if (mode == DFmode || FLOAT128_IBM_P (mode)
|| mode == DDmode || mode == TDmode)
cum->words += cum->words & 1;
cum->words += rs6000_arg_size (mode, type);
cum->words = align_words + n_words;
- if (SCALAR_FLOAT_MODE_P (elt_mode)
- && TARGET_HARD_FLOAT && TARGET_FPRS)
+ if (SCALAR_FLOAT_MODE_P (elt_mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
{
/* _Decimal128 must be passed in an even/odd float register pair.
This assumes that the register number is odd when fregno is
= gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (mode, cum->fregno++),
GEN_INT (bitpos / BITS_PER_UNIT));
- if (mode == TFmode || mode == TDmode)
+ if (FLOAT128_2REG_P (mode))
cum->fregno++;
}
else if (cum->named && USE_ALTIVEC_FOR_ARG_P (cum, mode, 1))
if (TARGET_HARD_FLOAT && TARGET_FPRS
&& ((TARGET_SINGLE_FLOAT && mode == SFmode)
|| (TARGET_DOUBLE_FLOAT && mode == DFmode)
- || (mode == TFmode && !TARGET_IEEEQUAD)
- || mode == SDmode || mode == DDmode || mode == TDmode))
+ || FLOAT128_2REG_P (mode)
+ || DECIMAL_FLOAT_MODE_P (mode)))
{
/* _Decimal128 must use an even/odd register pair. This assumes
that the register number is odd when fregno is odd. */
if (mode == TDmode && (cum->fregno % 2) == 1)
cum->fregno++;
- if (cum->fregno + (mode == TFmode || mode == TDmode ? 1 : 0)
+ if (cum->fregno + (FLOAT128_2REG_P (mode) ? 1 : 0)
<= FP_ARG_V4_MAX_REG)
return gen_rtx_REG (mode, cum->fregno);
else
machine_mode fmode = elt_mode;
if (cum->fregno + (i + 1) * n_fpreg > FP_ARG_MAX_REG + 1)
{
- gcc_assert (fmode == TFmode || fmode == TDmode);
+ gcc_assert (FLOAT128_2REG_P (fmode));
fmode = DECIMAL_FLOAT_MODE_P (fmode) ? DDmode : DFmode;
}
machine_mode mode, const_tree type,
bool named ATTRIBUTE_UNUSED)
{
- if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD && mode == TFmode)
+ if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD
+ && FLOAT128_IEEE_P (TYPE_MODE (type)))
{
if (TARGET_DEBUG_ARG)
- fprintf (stderr, "function_arg_pass_by_reference: V4 long double\n");
+ fprintf (stderr, "function_arg_pass_by_reference: V4 IEEE 128-bit\n");
return 1;
}
&& ((TARGET_SINGLE_FLOAT && TYPE_MODE (type) == SFmode)
|| (TARGET_DOUBLE_FLOAT
&& (TYPE_MODE (type) == DFmode
- || TYPE_MODE (type) == TFmode
- || TYPE_MODE (type) == SDmode
- || TYPE_MODE (type) == DDmode
- || TYPE_MODE (type) == TDmode))))
+ || FLOAT128_2REG_P (TYPE_MODE (type))
+ || DECIMAL_FLOAT_MODE_P (TYPE_MODE (type))))))
{
/* FP args go in FP registers, if present. */
reg = fpr;
static int
rs6000_secondary_reload_memory (rtx addr,
enum reg_class rclass,
- enum machine_mode mode)
+ machine_mode mode)
{
int extra_cost = 0;
rtx reg, and_arg, plus_arg0, plus_arg1;
/* Ugly hack because %y is overloaded. */
if ((TARGET_SPE || TARGET_E500_DOUBLE)
&& (GET_MODE_SIZE (GET_MODE (x)) == 8
- || GET_MODE (x) == TFmode
+ || FLOAT128_2REG_P (GET_MODE (x))
|| GET_MODE (x) == TImode
|| GET_MODE (x) == PTImode))
{
((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) ? DFmode : SFmode);
else if (ALTIVEC_REGNO_P (reg))
reg_mode = V16QImode;
- else if (TARGET_E500_DOUBLE && mode == TFmode)
+ else if (TARGET_E500_DOUBLE && FLOAT128_2REG_P (mode))
reg_mode = DFmode;
else
reg_mode = word_mode;
if (SPE_VECTOR_MODE (mode))
return true;
- if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode))
+ if (TARGET_E500_DOUBLE
+ && (mode == DFmode || FLOAT128_2REG_P (mode)))
return true;
}
}
case DDmode:
case TFmode:
case TDmode:
+ case IFmode:
+ case KFmode:
bits = 0x3;
break;
TOC, things we put here aren't actually in the TOC, so we can allow
FP constants. */
if (GET_CODE (x) == CONST_DOUBLE &&
- (GET_MODE (x) == TFmode || GET_MODE (x) == TDmode))
+ (GET_MODE (x) == TFmode || GET_MODE (x) == TDmode
+ || GET_MODE (x) == IFmode || GET_MODE (x) == KFmode))
{
REAL_VALUE_TYPE rv;
long k[4];
/* Moving between two similar registers is just one instruction. */
else if (reg_classes_intersect_p (to, from))
- ret = (mode == TFmode || mode == TDmode) ? 4 : 2;
+ ret = (FLOAT128_2REG_P (mode)) ? 4 : 2;
/* Everything else has to go through GENERAL_REGS. */
else
{
int first_reg, n_regs;
- if (SCALAR_FLOAT_MODE_P (elt_mode))
+ if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (elt_mode))
{
/* _Decimal128 must use even/odd register pairs. */
first_reg = (elt_mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
/* _Decimal128 must use an even/odd register pair. */
regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
- else if (SCALAR_FLOAT_TYPE_P (valtype) && TARGET_HARD_FLOAT && TARGET_FPRS
+ else if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS
&& ((TARGET_SINGLE_FLOAT && (mode == SFmode)) || TARGET_DOUBLE_FLOAT))
regno = FP_ARG_RETURN;
else if (TREE_CODE (valtype) == COMPLEX_TYPE
/* VSX is a superset of Altivec and adds V2DImode/V2DFmode. Since the same
return register is used in both cases, and we won't see V2DImode/V2DFmode
for pure altivec, combine the two cases. */
- else if (TREE_CODE (valtype) == VECTOR_TYPE
+ else if ((TREE_CODE (valtype) == VECTOR_TYPE || FLOAT128_VECTOR_P (mode))
&& TARGET_ALTIVEC && TARGET_ALTIVEC_ABI
&& ALTIVEC_OR_VSX_VECTOR_MODE (mode))
regno = ALTIVEC_ARG_RETURN;
else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
&& (mode == DFmode || mode == DCmode
- || mode == TFmode || mode == TCmode))
+ || FLOAT128_IBM_P (mode) || mode == TCmode))
return spe_build_register_parallel (mode, GP_ARG_RETURN);
else
regno = GP_ARG_RETURN;
if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
/* _Decimal128 must use an even/odd register pair. */
regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
- else if (SCALAR_FLOAT_MODE_P (mode)
+ else if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode)
&& TARGET_HARD_FLOAT && TARGET_FPRS
&& ((TARGET_SINGLE_FLOAT && mode == SFmode) || TARGET_DOUBLE_FLOAT))
regno = FP_ARG_RETURN;
return rs6000_complex_function_value (mode);
else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
&& (mode == DFmode || mode == DCmode
- || mode == TFmode || mode == TCmode))
+ || FLOAT128_IBM_P (mode) || mode == TCmode))
return spe_build_register_parallel (mode, GP_ARG_RETURN);
else
regno = GP_ARG_RETURN;
if (DECIMAL_FLOAT_MODE_P (mode))
return default_decimal_float_supported_p ();
+ else if (mode == KFmode)
+ return TARGET_FLOAT128;
else
return default_scalar_mode_supported_p (mode);
}
if (TARGET_SPE && SPE_VECTOR_MODE (mode))
return true;
- else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
+ /* There is no vector form for IEEE 128-bit. If we return true for IEEE
+ 128-bit, the compiler might try to widen IEEE 128-bit to IBM
+ double-double. */
+ else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode) && !FLOAT128_IEEE_P (mode))
return true;
else