rs6000-protos.h (rs6000_expand_float128_convert): Add declaration.
2015-08-26 Michael Meissner <meissner@linux.vnet.ibm.com> * config/rs6000/rs6000-protos.h (rs6000_expand_float128_convert): Add declaration. * config/rs6000/rs6000.c (rs6000_emit_le_vsx_store): Fix a comment. (rs6000_cannot_change_mode_class): Add support for IEEE 128-bit floating point in VSX registers. (rs6000_output_move_128bit): Always print out the set insn if we can't generate an appropriate 128-bit move. (rs6000_generate_compare): Add support for IEEE 128-bit floating point in VSX registers comparisons. (rs6000_expand_float128_convert): Likewise. * config/rs6000/predicates.md (int_reg_operand_not_pseudo): New predicate for only GPR hard registers. * config/rs6000/rs6000.md (FP): Add IEEE 128-bit floating point modes to iterators. Add new iterators for moving 128-bit values in scalar FPR registers and VSX registers. (FMOVE128): Likewise. (FMOVE128_FPR): Likewise. (FMOVE128_GPR): Likewise. (FMOVE128_VSX): Likewise. (FLOAT128_SFDFTF): New iterators for IEEE 128-bit floating point in VSX registers. (IFKF): Likewise. (IBM128): Likewise. (TFIFKF): Likewise. (RELOAD): Add IEEE 128-bit floating point modes. (signbittf2): Convert TF insns to add support for new IEEE 128-bit floating point in VSX registers modes. (signbit<mode>2, IBM128 iterator): Likewise. (mov<mode>_64bit_dm, FMOVE128_FPR iterator): Likewise. (mov<mode>_32bit, FMOVE128_FPR iterator): Likewise. (negtf2): Likewise. (neg<mode>2, TFIFKF iterator): Likewise. (negtf2_internal): Likewise. (abstf2): Likewise. (abs<mode>2, TFIFKF iterator): Likewise. (ieee_128bit_negative_zero): New IEEE 128-bit floating point in VSX insn support for negate, absolute value, and negative absolute value. (ieee_128bit_vsx_neg<mode>2): Likewise. (ieee_128bit_vsx_neg<mode>2_internal): Likewise. (ieee_128bit_vsx_abs<mode>2): Likewise. (ieee_128bit_vsx_abs<mode>2_internal): Likewise. (ieee_128bit_vsx_nabs<mode>2): Likewise. (ieee_128bit_vsx_nabs<mode>2_internal): Likewise. (FP128_64): Update pack/unpack 128-bit insns for IEEE 128-bit floating point in VSX registers. (unpack<mode>_dm): Likewise. (unpack<mode>_nodm): Likewise. (pack<mode>): Likewise. (unpackv1ti): Likewise. (unpack<mode>, FMOVE128_VSX iterator): Likewise. (packv1ti): Likewise. (pack<mode>, FMOVE128_VSX iterator): Likewise. (extenddftf2): Add support for IEEE 128-bit floating point in VSX registers. (extenddftf2_internal): Likewise. (trunctfdf2): Likewise. (trunctfdf2_internal2): Likewise. (fix_trunc_helper): Likewise. (fix_trunctfdi2"): Likewise. (floatditf2): Likewise. (floatuns<mode>tf2): Likewise. (extend<FLOAT128_SFDFTF:mode><IFKF:mode>2): Likewise. (trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2): Likewise. (fix_trunc<IFKF:mode><SDI:mode>2): Likewise. (fixuns_trunc<IFKF:mode><SDI:mode>2): Likewise. (float<SDI:mode><IFKF:mode>2): Likewise. (floatuns<SDI:mode><IFKF:mode>2): Likewise. From-SVN: r227230
This commit is contained in:
parent
66c182be12
commit
526303ecaa
5 changed files with 637 additions and 74 deletions
|
@ -1,3 +1,79 @@
|
|||
2015-08-26 Michael Meissner <meissner@linux.vnet.ibm.com>
|
||||
|
||||
* config/rs6000/rs6000-protos.h (rs6000_expand_float128_convert):
|
||||
Add declaration.
|
||||
|
||||
* config/rs6000/rs6000.c (rs6000_emit_le_vsx_store): Fix a
|
||||
comment.
|
||||
(rs6000_cannot_change_mode_class): Add support for IEEE 128-bit
|
||||
floating point in VSX registers.
|
||||
(rs6000_output_move_128bit): Always print out the set insn if we
|
||||
can't generate an appropriate 128-bit move.
|
||||
(rs6000_generate_compare): Add support for IEEE 128-bit floating
|
||||
point in VSX registers comparisons.
|
||||
(rs6000_expand_float128_convert): Likewise.
|
||||
|
||||
* config/rs6000/predicates.md (int_reg_operand_not_pseudo): New
|
||||
predicate for only GPR hard registers.
|
||||
|
||||
* config/rs6000/rs6000.md (FP): Add IEEE 128-bit floating point
|
||||
modes to iterators. Add new iterators for moving 128-bit values in
|
||||
scalar FPR registers and VSX registers.
|
||||
(FMOVE128): Likewise.
|
||||
(FMOVE128_FPR): Likewise.
|
||||
(FMOVE128_GPR): Likewise.
|
||||
(FMOVE128_VSX): Likewise.
|
||||
(FLOAT128_SFDFTF): New iterators for IEEE 128-bit floating point
|
||||
in VSX registers.
|
||||
(IFKF): Likewise.
|
||||
(IBM128): Likewise.
|
||||
(TFIFKF): Likewise.
|
||||
(RELOAD): Add IEEE 128-bit floating point modes.
|
||||
(signbittf2): Convert TF insns to add support for new IEEE 128-bit
|
||||
floating point in VSX registers modes.
|
||||
(signbit<mode>2, IBM128 iterator): Likewise.
|
||||
(mov<mode>_64bit_dm, FMOVE128_FPR iterator): Likewise.
|
||||
(mov<mode>_32bit, FMOVE128_FPR iterator): Likewise.
|
||||
(negtf2): Likewise.
|
||||
(neg<mode>2, TFIFKF iterator): Likewise.
|
||||
(negtf2_internal): Likewise.
|
||||
(abstf2): Likewise.
|
||||
(abs<mode>2, TFIFKF iterator): Likewise.
|
||||
(ieee_128bit_negative_zero): New IEEE 128-bit floating point in
|
||||
VSX insn support for negate, absolute value, and negative absolute
|
||||
value.
|
||||
(ieee_128bit_vsx_neg<mode>2): Likewise.
|
||||
(ieee_128bit_vsx_neg<mode>2_internal): Likewise.
|
||||
(ieee_128bit_vsx_abs<mode>2): Likewise.
|
||||
(ieee_128bit_vsx_abs<mode>2_internal): Likewise.
|
||||
(ieee_128bit_vsx_nabs<mode>2): Likewise.
|
||||
(ieee_128bit_vsx_nabs<mode>2_internal): Likewise.
|
||||
(FP128_64): Update pack/unpack 128-bit insns for IEEE 128-bit
|
||||
floating point in VSX registers.
|
||||
(unpack<mode>_dm): Likewise.
|
||||
(unpack<mode>_nodm): Likewise.
|
||||
(pack<mode>): Likewise.
|
||||
(unpackv1ti): Likewise.
|
||||
(unpack<mode>, FMOVE128_VSX iterator): Likewise.
|
||||
(packv1ti): Likewise.
|
||||
(pack<mode>, FMOVE128_VSX iterator): Likewise.
|
||||
(extenddftf2): Add support for IEEE 128-bit floating point in VSX
|
||||
registers.
|
||||
(extenddftf2_internal): Likewise.
|
||||
(trunctfdf2): Likewise.
|
||||
(trunctfdf2_internal2): Likewise.
|
||||
(fix_trunc_helper): Likewise.
|
||||
(fix_trunctfdi2"): Likewise.
|
||||
(floatditf2): Likewise.
|
||||
(floatuns<mode>tf2): Likewise.
|
||||
(extend<FLOAT128_SFDFTF:mode><IFKF:mode>2): Likewise.
|
||||
(trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2): Likewise.
|
||||
(fix_trunc<IFKF:mode><SDI:mode>2): Likewise.
|
||||
(fixuns_trunc<IFKF:mode><SDI:mode>2): Likewise.
|
||||
(float<SDI:mode><IFKF:mode>2): Likewise.
|
||||
(floatuns<SDI:mode><IFKF:mode>2): Likewise.
|
||||
|
||||
|
||||
2015-08-26 Renlin Li <renlin.li@arm.com>
|
||||
|
||||
* config/aarch64/aarch64.md (*aarch64_bfi<GPI:mode><ALLX:mode>4): New.
|
||||
|
|
|
@ -239,6 +239,25 @@
|
|||
return INT_REGNO_P (REGNO (op));
|
||||
})
|
||||
|
||||
;; Like int_reg_operand, but don't return true for pseudo registers
|
||||
(define_predicate "int_reg_operand_not_pseudo"
|
||||
(match_operand 0 "register_operand")
|
||||
{
|
||||
if ((TARGET_E500_DOUBLE || TARGET_SPE) && invalid_e500_subreg (op, mode))
|
||||
return 0;
|
||||
|
||||
if (GET_CODE (op) == SUBREG)
|
||||
op = SUBREG_REG (op);
|
||||
|
||||
if (!REG_P (op))
|
||||
return 0;
|
||||
|
||||
if (REGNO (op) >= FIRST_PSEUDO_REGISTER)
|
||||
return 0;
|
||||
|
||||
return INT_REGNO_P (REGNO (op));
|
||||
})
|
||||
|
||||
;; Like int_reg_operand, but only return true for base registers
|
||||
(define_predicate "base_reg_operand"
|
||||
(match_operand 0 "int_reg_operand")
|
||||
|
|
|
@ -54,6 +54,7 @@ extern const char *output_vec_const_move (rtx *);
|
|||
extern const char *rs6000_output_move_128bit (rtx *);
|
||||
extern bool rs6000_move_128bit_ok_p (rtx []);
|
||||
extern bool rs6000_split_128bit_ok_p (rtx []);
|
||||
extern void rs6000_expand_float128_convert (rtx, rtx, bool);
|
||||
extern void rs6000_expand_vector_init (rtx, rtx);
|
||||
extern void paired_expand_vector_init (rtx, rtx);
|
||||
extern void rs6000_expand_vector_set (rtx, rtx, int);
|
||||
|
|
|
@ -8485,7 +8485,7 @@ rs6000_emit_le_vsx_store (rtx dest, rtx source, machine_mode mode)
|
|||
during expand. */
|
||||
gcc_assert (!reload_in_progress && !lra_in_progress && !reload_completed);
|
||||
|
||||
/* Use V2DImode to do swaps of types with 128-bit scalare parts (TImode,
|
||||
/* Use V2DImode to do swaps of types with 128-bit scalar parts (TImode,
|
||||
V1TImode). */
|
||||
if (mode == TImode || mode == V1TImode)
|
||||
{
|
||||
|
@ -18542,6 +18542,8 @@ rs6000_cannot_change_mode_class (machine_mode from,
|
|||
{
|
||||
unsigned to_nregs = hard_regno_nregs[FIRST_FPR_REGNO][to];
|
||||
unsigned from_nregs = hard_regno_nregs[FIRST_FPR_REGNO][from];
|
||||
bool to_float128_vector_p = FLOAT128_VECTOR_P (to);
|
||||
bool from_float128_vector_p = FLOAT128_VECTOR_P (from);
|
||||
|
||||
/* Don't allow 64-bit types to overlap with 128-bit types that take a
|
||||
single register under VSX because the scalar part of the register
|
||||
|
@ -18550,7 +18552,10 @@ rs6000_cannot_change_mode_class (machine_mode from,
|
|||
IEEE floating point can't overlap, and neither can small
|
||||
values. */
|
||||
|
||||
if (TARGET_IEEEQUAD && (to == TFmode || from == TFmode))
|
||||
if (to_float128_vector_p && from_float128_vector_p)
|
||||
return false;
|
||||
|
||||
else if (to_float128_vector_p || from_float128_vector_p)
|
||||
return true;
|
||||
|
||||
/* TDmode in floating-mode registers must always go into a register
|
||||
|
@ -18578,6 +18583,8 @@ rs6000_cannot_change_mode_class (machine_mode from,
|
|||
if (TARGET_E500_DOUBLE
|
||||
&& ((((to) == DFmode) + ((from) == DFmode)) == 1
|
||||
|| (((to) == TFmode) + ((from) == TFmode)) == 1
|
||||
|| (((to) == IFmode) + ((from) == IFmode)) == 1
|
||||
|| (((to) == KFmode) + ((from) == KFmode)) == 1
|
||||
|| (((to) == DDmode) + ((from) == DDmode)) == 1
|
||||
|| (((to) == TDmode) + ((from) == TDmode)) == 1
|
||||
|| (((to) == DImode) + ((from) == DImode)) == 1))
|
||||
|
@ -18774,13 +18781,7 @@ rs6000_output_move_128bit (rtx operands[])
|
|||
return output_vec_const_move (operands);
|
||||
}
|
||||
|
||||
if (TARGET_DEBUG_ADDR)
|
||||
{
|
||||
fprintf (stderr, "\n===== Bad 128 bit move:\n");
|
||||
debug_rtx (gen_rtx_SET (dest, src));
|
||||
}
|
||||
|
||||
gcc_unreachable ();
|
||||
fatal_insn ("Bad 128-bit move", gen_rtx_SET (dest, src));
|
||||
}
|
||||
|
||||
/* Validate a 128-bit move. */
|
||||
|
@ -19824,6 +19825,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
|
|||
break;
|
||||
|
||||
case TFmode:
|
||||
case IFmode:
|
||||
case KFmode:
|
||||
cmp = (flag_finite_math_only && !flag_trapping_math)
|
||||
? gen_tsttfeq_gpr (compare_result, op0, op1)
|
||||
: gen_cmptfeq_gpr (compare_result, op0, op1);
|
||||
|
@ -19851,6 +19854,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
|
|||
break;
|
||||
|
||||
case TFmode:
|
||||
case IFmode:
|
||||
case KFmode:
|
||||
cmp = (flag_finite_math_only && !flag_trapping_math)
|
||||
? gen_tsttfgt_gpr (compare_result, op0, op1)
|
||||
: gen_cmptfgt_gpr (compare_result, op0, op1);
|
||||
|
@ -19878,6 +19883,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
|
|||
break;
|
||||
|
||||
case TFmode:
|
||||
case IFmode:
|
||||
case KFmode:
|
||||
cmp = (flag_finite_math_only && !flag_trapping_math)
|
||||
? gen_tsttflt_gpr (compare_result, op0, op1)
|
||||
: gen_cmptflt_gpr (compare_result, op0, op1);
|
||||
|
@ -19915,6 +19922,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
|
|||
break;
|
||||
|
||||
case TFmode:
|
||||
case IFmode:
|
||||
case KFmode:
|
||||
cmp = (flag_finite_math_only && !flag_trapping_math)
|
||||
? gen_tsttfeq_gpr (compare_result2, op0, op1)
|
||||
: gen_cmptfeq_gpr (compare_result2, op0, op1);
|
||||
|
@ -19937,14 +19946,117 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
|
|||
|
||||
emit_insn (cmp);
|
||||
}
|
||||
|
||||
/* IEEE 128-bit support in VSX registers. The comparison function (__cmpkf2)
|
||||
returns 0..15 that is laid out the same way as the PowerPC CR register
|
||||
would for a normal floating point comparison. */
|
||||
else if (FLOAT128_IEEE_P (mode))
|
||||
{
|
||||
rtx and_reg = gen_reg_rtx (SImode);
|
||||
rtx dest = gen_reg_rtx (SImode);
|
||||
rtx libfunc = optab_libfunc (cmp_optab, mode);
|
||||
HOST_WIDE_INT mask_value = 0;
|
||||
|
||||
/* Values that __cmpkf2 returns. */
|
||||
#define PPC_CMP_UNORDERED 0x1 /* isnan (a) || isnan (b). */
|
||||
#define PPC_CMP_EQUAL 0x2 /* a == b. */
|
||||
#define PPC_CMP_GREATER_THEN 0x4 /* a > b. */
|
||||
#define PPC_CMP_LESS_THEN 0x8 /* a < b. */
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case EQ:
|
||||
mask_value = PPC_CMP_EQUAL;
|
||||
code = NE;
|
||||
break;
|
||||
|
||||
case NE:
|
||||
mask_value = PPC_CMP_EQUAL;
|
||||
code = EQ;
|
||||
break;
|
||||
|
||||
case GT:
|
||||
mask_value = PPC_CMP_GREATER_THEN;
|
||||
code = NE;
|
||||
break;
|
||||
|
||||
case GE:
|
||||
mask_value = PPC_CMP_GREATER_THEN | PPC_CMP_EQUAL;
|
||||
code = NE;
|
||||
break;
|
||||
|
||||
case LT:
|
||||
mask_value = PPC_CMP_LESS_THEN;
|
||||
code = NE;
|
||||
break;
|
||||
|
||||
case LE:
|
||||
mask_value = PPC_CMP_LESS_THEN | PPC_CMP_EQUAL;
|
||||
code = NE;
|
||||
break;
|
||||
|
||||
case UNLE:
|
||||
mask_value = PPC_CMP_GREATER_THEN;
|
||||
code = EQ;
|
||||
break;
|
||||
|
||||
case UNLT:
|
||||
mask_value = PPC_CMP_GREATER_THEN | PPC_CMP_EQUAL;
|
||||
code = EQ;
|
||||
break;
|
||||
|
||||
case UNGE:
|
||||
mask_value = PPC_CMP_LESS_THEN;
|
||||
code = EQ;
|
||||
break;
|
||||
|
||||
case UNGT:
|
||||
mask_value = PPC_CMP_LESS_THEN | PPC_CMP_EQUAL;
|
||||
code = EQ;
|
||||
break;
|
||||
|
||||
case UNEQ:
|
||||
mask_value = PPC_CMP_EQUAL | PPC_CMP_UNORDERED;
|
||||
code = NE;
|
||||
|
||||
case LTGT:
|
||||
mask_value = PPC_CMP_EQUAL | PPC_CMP_UNORDERED;
|
||||
code = EQ;
|
||||
break;
|
||||
|
||||
case UNORDERED:
|
||||
mask_value = PPC_CMP_UNORDERED;
|
||||
code = NE;
|
||||
break;
|
||||
|
||||
case ORDERED:
|
||||
mask_value = PPC_CMP_UNORDERED;
|
||||
code = EQ;
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
gcc_assert (mask_value != 0);
|
||||
and_reg = emit_library_call_value (libfunc, and_reg, LCT_CONST, SImode, 2,
|
||||
op0, mode, op1, mode);
|
||||
|
||||
emit_insn (gen_andsi3 (dest, and_reg, GEN_INT (mask_value)));
|
||||
compare_result = gen_reg_rtx (CCmode);
|
||||
comp_mode = CCmode;
|
||||
|
||||
emit_insn (gen_rtx_SET (compare_result,
|
||||
gen_rtx_COMPARE (comp_mode, dest, const0_rtx)));
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Generate XLC-compatible TFmode compare as PARALLEL with extra
|
||||
CLOBBERs to match cmptf_internal2 pattern. */
|
||||
if (comp_mode == CCFPmode && TARGET_XL_COMPAT
|
||||
&& GET_MODE (op0) == TFmode
|
||||
&& !TARGET_IEEEQUAD
|
||||
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128)
|
||||
&& FLOAT128_IBM_P (GET_MODE (op0))
|
||||
&& TARGET_HARD_FLOAT && TARGET_FPRS)
|
||||
emit_insn (gen_rtx_PARALLEL (VOIDmode,
|
||||
gen_rtvec (10,
|
||||
gen_rtx_SET (compare_result,
|
||||
|
@ -19977,6 +20089,7 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
|
|||
/* Some kinds of FP comparisons need an OR operation;
|
||||
under flag_finite_math_only we don't bother. */
|
||||
if (FLOAT_MODE_P (mode)
|
||||
&& !FLOAT128_IEEE_P (mode)
|
||||
&& !flag_finite_math_only
|
||||
&& !(TARGET_HARD_FLOAT && !TARGET_FPRS)
|
||||
&& (code == LE || code == GE
|
||||
|
@ -20016,6 +20129,68 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
|
|||
}
|
||||
|
||||
|
||||
/* Expand floating point conversion to/from __float128 and __ibm128. */
|
||||
|
||||
void
|
||||
rs6000_expand_float128_convert (rtx dest, rtx src, bool unsigned_p)
|
||||
{
|
||||
machine_mode dest_mode = GET_MODE (dest);
|
||||
machine_mode src_mode = GET_MODE (src);
|
||||
convert_optab cvt = unknown_optab;
|
||||
rtx libfunc = NULL_RTX;
|
||||
rtx dest2;
|
||||
|
||||
if (dest_mode == src_mode)
|
||||
gcc_unreachable ();
|
||||
|
||||
if (FLOAT128_IEEE_P (dest_mode))
|
||||
{
|
||||
if (src_mode == SFmode
|
||||
|| src_mode == DFmode
|
||||
|| FLOAT128_IBM_P (src_mode))
|
||||
cvt = sext_optab;
|
||||
|
||||
else if (GET_MODE_CLASS (src_mode) == MODE_INT)
|
||||
cvt = (unsigned_p) ? ufloat_optab : sfloat_optab;
|
||||
|
||||
else if (FLOAT128_IEEE_P (src_mode))
|
||||
emit_move_insn (dest, gen_lowpart (dest_mode, src));
|
||||
|
||||
else
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
else if (FLOAT128_IEEE_P (src_mode))
|
||||
{
|
||||
if (dest_mode == SFmode
|
||||
|| dest_mode == DFmode
|
||||
|| FLOAT128_IBM_P (dest_mode))
|
||||
cvt = trunc_optab;
|
||||
|
||||
else if (GET_MODE_CLASS (dest_mode) == MODE_INT)
|
||||
cvt = (unsigned_p) ? ufix_optab : sfix_optab;
|
||||
|
||||
else
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
gcc_assert (cvt != unknown_optab);
|
||||
libfunc = convert_optab_libfunc (cvt, dest_mode, src_mode);
|
||||
gcc_assert (libfunc != NULL_RTX);
|
||||
|
||||
dest2 = emit_library_call_value (libfunc, dest, LCT_CONST, dest_mode, 1, src,
|
||||
src_mode);
|
||||
|
||||
gcc_assert (dest != NULL_RTX);
|
||||
if (!rtx_equal_p (dest, dest2))
|
||||
emit_move_insn (dest, dest2);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Emit the RTL for an sISEL pattern. */
|
||||
|
||||
void
|
||||
|
|
|
@ -348,6 +348,8 @@
|
|||
&& TARGET_HARD_FLOAT
|
||||
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
|
||||
&& TARGET_LONG_DOUBLE_128")
|
||||
(IF "TARGET_FLOAT128")
|
||||
(KF "TARGET_FLOAT128")
|
||||
(DD "TARGET_DFP")
|
||||
(TD "TARGET_DFP")])
|
||||
|
||||
|
@ -365,9 +367,14 @@
|
|||
(define_mode_iterator FMOVE32 [SF SD])
|
||||
(define_mode_iterator FMOVE64 [DF DD])
|
||||
(define_mode_iterator FMOVE64X [DI DF DD])
|
||||
(define_mode_iterator FMOVE128 [(TF "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128")
|
||||
(define_mode_iterator FMOVE128 [(TF "TARGET_LONG_DOUBLE_128")
|
||||
(IF "TARGET_LONG_DOUBLE_128")
|
||||
(TD "TARGET_HARD_FLOAT && TARGET_FPRS")])
|
||||
|
||||
(define_mode_iterator FMOVE128_FPR [(TF "FLOAT128_2REG_P (TFmode)")
|
||||
(IF "FLOAT128_2REG_P (IFmode)")
|
||||
(TD "TARGET_HARD_FLOAT && TARGET_FPRS")])
|
||||
|
||||
; Iterators for 128 bit types for direct move
|
||||
(define_mode_iterator FMOVE128_GPR [(TI "TARGET_VSX_TIMODE")
|
||||
(V16QI "")
|
||||
|
@ -376,7 +383,13 @@
|
|||
(V4SF "")
|
||||
(V2DI "")
|
||||
(V2DF "")
|
||||
(V1TI "")])
|
||||
(V1TI "")
|
||||
(KF "")
|
||||
(TF "")
|
||||
(IF "")])
|
||||
|
||||
; Iterator for 128-bit VSX types for pack/unpack
|
||||
(define_mode_iterator FMOVE128_VSX [V1TI KF])
|
||||
|
||||
; Whether a floating point move is ok, don't allow SD without hardware FP
|
||||
(define_mode_attr fmove_ok [(SF "")
|
||||
|
@ -432,6 +445,25 @@
|
|||
; Iterator for just SF/DF
|
||||
(define_mode_iterator SFDF [SF DF])
|
||||
|
||||
; Iterator for float128 floating conversions
|
||||
(define_mode_iterator FLOAT128_SFDFTF [
|
||||
(SF "TARGET_FLOAT128")
|
||||
(DF "TARGET_FLOAT128")
|
||||
(TF "FLOAT128_IBM_P (TFmode)")
|
||||
(IF "TARGET_FLOAT128")])
|
||||
|
||||
; Iterator for special 128-bit floating point. This is for non-default
|
||||
; conversions, so TFmode is not used here.
|
||||
(define_mode_iterator IFKF [IF KF])
|
||||
|
||||
; Iterator for 128-bit floating point that uses the IBM double-double format
|
||||
(define_mode_iterator IBM128 [IF TF])
|
||||
|
||||
; Iterator for 128-bit floating point
|
||||
(define_mode_iterator TFIFKF [(KF "TARGET_FLOAT128")
|
||||
(IF "TARGET_FLOAT128")
|
||||
(TF "TARGET_LONG_DOUBLE_128")])
|
||||
|
||||
; SF/DF suffix for traditional floating instructions
|
||||
(define_mode_attr Ftrad [(SF "s") (DF "")])
|
||||
|
||||
|
@ -596,7 +628,7 @@
|
|||
;; Reload iterator for creating the function to allocate a base register to
|
||||
;; supplement addressing modes.
|
||||
(define_mode_iterator RELOAD [V16QI V8HI V4SI V2DI V4SF V2DF V1TI
|
||||
SF SD SI DF DD DI TI PTI])
|
||||
SF SD SI DF DD DI TI PTI KF IF TF])
|
||||
|
||||
|
||||
;; Start with fixed-point load and store insns. Here we put only the more
|
||||
|
@ -4204,19 +4236,18 @@
|
|||
;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in
|
||||
;; builtins.c and optabs.c that are not correct for IBM long double
|
||||
;; when little-endian.
|
||||
(define_expand "signbittf2"
|
||||
(define_expand "signbit<mode>2"
|
||||
[(set (match_dup 2)
|
||||
(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))
|
||||
(float_truncate:DF (match_operand:IBM128 1 "gpc_reg_operand" "")))
|
||||
(set (match_dup 3)
|
||||
(subreg:DI (match_dup 2) 0))
|
||||
(set (match_dup 4)
|
||||
(match_dup 5))
|
||||
(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||||
(match_dup 6))]
|
||||
"!TARGET_IEEEQUAD
|
||||
"FLOAT128_IBM_P (<MODE>mode)
|
||||
&& TARGET_HARD_FLOAT
|
||||
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
|
||||
&& TARGET_LONG_DOUBLE_128"
|
||||
&& (TARGET_FPRS || TARGET_E500_DOUBLE)"
|
||||
{
|
||||
operands[2] = gen_reg_rtx (DFmode);
|
||||
operands[3] = gen_reg_rtx (DImode);
|
||||
|
@ -6390,9 +6421,10 @@
|
|||
;; problematical. Don't allow direct move for this case.
|
||||
|
||||
(define_insn_and_split "*mov<mode>_64bit_dm"
|
||||
[(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r,r,wm")
|
||||
(match_operand:FMOVE128 1 "input_operand" "d,m,d,j,r,jY,r,wm,r"))]
|
||||
[(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r,r,wm")
|
||||
(match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r,wm,r"))]
|
||||
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64
|
||||
&& FLOAT128_2REG_P (<MODE>mode)
|
||||
&& (<MODE>mode != TDmode || WORDS_BIG_ENDIAN)
|
||||
&& (gpc_reg_operand (operands[0], <MODE>mode)
|
||||
|| gpc_reg_operand (operands[1], <MODE>mode))"
|
||||
|
@ -6415,9 +6447,12 @@
|
|||
[(set_attr "length" "8,8,8,8,12,12,8")])
|
||||
|
||||
(define_insn_and_split "*mov<mode>_32bit"
|
||||
[(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r")
|
||||
(match_operand:FMOVE128 1 "input_operand" "d,m,d,j,r,jY,r"))]
|
||||
[(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r")
|
||||
(match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r"))]
|
||||
"TARGET_HARD_FLOAT && TARGET_FPRS && !TARGET_POWERPC64
|
||||
&& (FLOAT128_2REG_P (<MODE>mode)
|
||||
|| int_reg_operand_not_pseudo (operands[0], <MODE>mode)
|
||||
|| int_reg_operand_not_pseudo (operands[1], <MODE>mode))
|
||||
&& (gpc_reg_operand (operands[0], <MODE>mode)
|
||||
|| gpc_reg_operand (operands[1], <MODE>mode))"
|
||||
"#"
|
||||
|
@ -6441,12 +6476,12 @@
|
|||
(define_expand "extenddftf2"
|
||||
[(set (match_operand:TF 0 "nonimmediate_operand" "")
|
||||
(float_extend:TF (match_operand:DF 1 "input_operand" "")))]
|
||||
"!TARGET_IEEEQUAD
|
||||
&& TARGET_HARD_FLOAT
|
||||
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
|
||||
"TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)
|
||||
&& TARGET_LONG_DOUBLE_128"
|
||||
{
|
||||
if (TARGET_E500_DOUBLE)
|
||||
if (TARGET_IEEEQUAD)
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], false);
|
||||
else if (TARGET_E500_DOUBLE)
|
||||
emit_insn (gen_spe_extenddftf2 (operands[0], operands[1]));
|
||||
else
|
||||
emit_insn (gen_extenddftf2_fprs (operands[0], operands[1]));
|
||||
|
@ -6495,25 +6530,34 @@
|
|||
(define_expand "extendsftf2"
|
||||
[(set (match_operand:TF 0 "nonimmediate_operand" "")
|
||||
(float_extend:TF (match_operand:SF 1 "gpc_reg_operand" "")))]
|
||||
"!TARGET_IEEEQUAD
|
||||
&& TARGET_HARD_FLOAT
|
||||
"TARGET_HARD_FLOAT
|
||||
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
|
||||
&& TARGET_LONG_DOUBLE_128"
|
||||
{
|
||||
rtx tmp = gen_reg_rtx (DFmode);
|
||||
emit_insn (gen_extendsfdf2 (tmp, operands[1]));
|
||||
emit_insn (gen_extenddftf2 (operands[0], tmp));
|
||||
if (TARGET_IEEEQUAD)
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], false);
|
||||
else
|
||||
{
|
||||
rtx tmp = gen_reg_rtx (DFmode);
|
||||
emit_insn (gen_extendsfdf2 (tmp, operands[1]));
|
||||
emit_insn (gen_extenddftf2 (operands[0], tmp));
|
||||
}
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "trunctfdf2"
|
||||
[(set (match_operand:DF 0 "gpc_reg_operand" "")
|
||||
(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))]
|
||||
"!TARGET_IEEEQUAD
|
||||
&& TARGET_HARD_FLOAT
|
||||
"TARGET_HARD_FLOAT
|
||||
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
|
||||
&& TARGET_LONG_DOUBLE_128"
|
||||
"")
|
||||
{
|
||||
if (TARGET_IEEEQUAD)
|
||||
{
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], false);
|
||||
DONE;
|
||||
}
|
||||
})
|
||||
|
||||
(define_insn_and_split "trunctfdf2_internal1"
|
||||
[(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d")
|
||||
|
@ -6544,12 +6588,13 @@
|
|||
(define_expand "trunctfsf2"
|
||||
[(set (match_operand:SF 0 "gpc_reg_operand" "")
|
||||
(float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "")))]
|
||||
"!TARGET_IEEEQUAD
|
||||
&& TARGET_HARD_FLOAT
|
||||
"TARGET_HARD_FLOAT
|
||||
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
|
||||
&& TARGET_LONG_DOUBLE_128"
|
||||
{
|
||||
if (TARGET_E500_DOUBLE)
|
||||
if (TARGET_IEEEQUAD)
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], false);
|
||||
else if (TARGET_E500_DOUBLE)
|
||||
emit_insn (gen_spe_trunctfsf2 (operands[0], operands[1]));
|
||||
else
|
||||
emit_insn (gen_trunctfsf2_fprs (operands[0], operands[1]));
|
||||
|
@ -6600,10 +6645,12 @@
|
|||
(define_expand "fix_trunctfsi2"
|
||||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||||
(fix:SI (match_operand:TF 1 "gpc_reg_operand" "")))]
|
||||
"!TARGET_IEEEQUAD && TARGET_HARD_FLOAT
|
||||
"TARGET_HARD_FLOAT
|
||||
&& (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128"
|
||||
{
|
||||
if (TARGET_E500_DOUBLE)
|
||||
if (TARGET_IEEEQUAD)
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], false);
|
||||
else if (TARGET_E500_DOUBLE)
|
||||
emit_insn (gen_spe_fix_trunctfsi2 (operands[0], operands[1]));
|
||||
else
|
||||
emit_insn (gen_fix_trunctfsi2_fprs (operands[0], operands[1]));
|
||||
|
@ -6651,20 +6698,73 @@
|
|||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "negtf2"
|
||||
[(set (match_operand:TF 0 "gpc_reg_operand" "")
|
||||
(neg:TF (match_operand:TF 1 "gpc_reg_operand" "")))]
|
||||
"!TARGET_IEEEQUAD
|
||||
&& TARGET_HARD_FLOAT
|
||||
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
|
||||
&& TARGET_LONG_DOUBLE_128"
|
||||
"")
|
||||
(define_expand "fix_trunctfdi2"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "")
|
||||
(fix:DI (match_operand:TF 1 "gpc_reg_operand" "")))]
|
||||
"TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
|
||||
{
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], false);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "fixuns_trunctf<mode>2"
|
||||
[(set (match_operand:SDI 0 "nonimmediate_operand" "")
|
||||
(unsigned_fix:SDI (match_operand:TF 1 "gpc_reg_operand" "")))]
|
||||
"TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
|
||||
{
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], true);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "floatditf2"
|
||||
[(set (match_operand:TF 0 "nonimmediate_operand" "")
|
||||
(float:TF (match_operand:DI 1 "gpc_reg_operand" "")))]
|
||||
"TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
|
||||
{
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], false);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "floatuns<mode>tf2"
|
||||
[(set (match_operand:TF 0 "nonimmediate_operand" "")
|
||||
(unsigned_float:TF (match_operand:SDI 1 "gpc_reg_operand" "")))]
|
||||
"TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
|
||||
{
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], true);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "neg<mode>2"
|
||||
[(set (match_operand:TFIFKF 0 "gpc_reg_operand" "")
|
||||
(neg:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))]
|
||||
"FLOAT128_IEEE_P (<MODE>mode)
|
||||
|| (FLOAT128_IBM_P (<MODE>mode)
|
||||
&& TARGET_HARD_FLOAT
|
||||
&& (TARGET_FPRS || TARGET_E500_DOUBLE))"
|
||||
"
|
||||
{
|
||||
if (FLOAT128_IEEE_P (<MODE>mode))
|
||||
{
|
||||
if (TARGET_FLOAT128)
|
||||
emit_insn (gen_ieee_128bit_vsx_neg<mode>2 (operands[0], operands[1]));
|
||||
else
|
||||
{
|
||||
rtx libfunc = optab_libfunc (neg_optab, <MODE>mode);
|
||||
rtx target = emit_library_call_value (libfunc, operands[0], LCT_CONST,
|
||||
<MODE>mode, 1,
|
||||
operands[1], <MODE>mode);
|
||||
|
||||
if (target && !rtx_equal_p (target, operands[0]))
|
||||
emit_move_insn (operands[0], target);
|
||||
}
|
||||
DONE;
|
||||
}
|
||||
}")
|
||||
|
||||
(define_insn "negtf2_internal"
|
||||
[(set (match_operand:TF 0 "gpc_reg_operand" "=d")
|
||||
(neg:TF (match_operand:TF 1 "gpc_reg_operand" "d")))]
|
||||
"!TARGET_IEEEQUAD
|
||||
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
|
||||
"TARGET_HARD_FLOAT && TARGET_FPRS && FLOAT128_IBM_P (TFmode)"
|
||||
"*
|
||||
{
|
||||
if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
|
||||
|
@ -6675,16 +6775,29 @@
|
|||
[(set_attr "type" "fp")
|
||||
(set_attr "length" "8")])
|
||||
|
||||
(define_expand "abstf2"
|
||||
[(set (match_operand:TF 0 "gpc_reg_operand" "")
|
||||
(abs:TF (match_operand:TF 1 "gpc_reg_operand" "")))]
|
||||
"!TARGET_IEEEQUAD
|
||||
&& TARGET_HARD_FLOAT
|
||||
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
|
||||
&& TARGET_LONG_DOUBLE_128"
|
||||
(define_expand "abs<mode>2"
|
||||
[(set (match_operand:TFIFKF 0 "gpc_reg_operand" "")
|
||||
(abs:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))]
|
||||
"FLOAT128_IEEE_P (<MODE>mode)
|
||||
|| (FLOAT128_IBM_P (<MODE>mode)
|
||||
&& TARGET_HARD_FLOAT
|
||||
&& (TARGET_FPRS || TARGET_E500_DOUBLE))"
|
||||
"
|
||||
{
|
||||
rtx label = gen_label_rtx ();
|
||||
rtx label;
|
||||
|
||||
if (FLOAT128_IEEE_P (<MODE>mode))
|
||||
{
|
||||
if (TARGET_FLOAT128)
|
||||
{
|
||||
emit_insn (gen_ieee_128bit_vsx_abs<mode>2 (operands[0], operands[1]));
|
||||
DONE;
|
||||
}
|
||||
else
|
||||
FAIL;
|
||||
}
|
||||
|
||||
label = gen_label_rtx ();
|
||||
if (TARGET_E500_DOUBLE)
|
||||
{
|
||||
if (flag_finite_math_only && !flag_trapping_math)
|
||||
|
@ -6720,6 +6833,184 @@
|
|||
operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
|
||||
operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
|
||||
}")
|
||||
|
||||
|
||||
;; Generate IEEE 128-bit -0.0 (0x80000000000000000000000000000000) in a vector
|
||||
;; register
|
||||
|
||||
(define_expand "ieee_128bit_negative_zero"
|
||||
[(set (match_operand:V16QI 0 "register_operand" "") (match_dup 1))]
|
||||
"TARGET_FLOAT128"
|
||||
{
|
||||
rtvec v = rtvec_alloc (16);
|
||||
int i, high;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
RTVEC_ELT (v, i) = const0_rtx;
|
||||
|
||||
high = (BYTES_BIG_ENDIAN) ? 0 : 15;
|
||||
RTVEC_ELT (v, high) = GEN_INT (0x80);
|
||||
|
||||
rs6000_expand_vector_init (operands[0], gen_rtx_PARALLEL (V16QImode, v));
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; IEEE 128-bit negate
|
||||
|
||||
;; We have 2 insns here for negate and absolute value. The first uses
|
||||
;; match_scratch so that phases like combine can recognize neg/abs as generic
|
||||
;; insns, and second insn after the first split pass loads up the bit to
|
||||
;; twiddle the sign bit. Later GCSE passes can then combine multiple uses of
|
||||
;; neg/abs to create the constant just once.
|
||||
|
||||
(define_insn_and_split "ieee_128bit_vsx_neg<mode>2"
|
||||
[(set (match_operand:TFIFKF 0 "register_operand" "=wa")
|
||||
(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
|
||||
(clobber (match_scratch:V16QI 2 "=v"))]
|
||||
"TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
|
||||
"#"
|
||||
"&& 1"
|
||||
[(parallel [(set (match_dup 0)
|
||||
(neg:TFIFKF (match_dup 1)))
|
||||
(use (match_dup 2))])]
|
||||
{
|
||||
if (GET_CODE (operands[2]) == SCRATCH)
|
||||
operands[2] = gen_reg_rtx (V16QImode);
|
||||
|
||||
operands[3] = gen_reg_rtx (V16QImode);
|
||||
emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
|
||||
}
|
||||
[(set_attr "length" "8")
|
||||
(set_attr "type" "vecsimple")])
|
||||
|
||||
(define_insn "*ieee_128bit_vsx_neg<mode>2_internal"
|
||||
[(set (match_operand:TFIFKF 0 "register_operand" "=wa")
|
||||
(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
|
||||
(use (match_operand:V16QI 2 "register_operand" "=v"))]
|
||||
"TARGET_FLOAT128"
|
||||
"xxlxor %x0,%x1,%x2"
|
||||
[(set_attr "type" "vecsimple")])
|
||||
|
||||
;; IEEE 128-bit absolute value
|
||||
(define_insn_and_split "ieee_128bit_vsx_abs<mode>2"
|
||||
[(set (match_operand:TFIFKF 0 "register_operand" "=wa")
|
||||
(abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
|
||||
(clobber (match_scratch:V16QI 2 "=v"))]
|
||||
"TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
|
||||
"#"
|
||||
"&& 1"
|
||||
[(parallel [(set (match_dup 0)
|
||||
(abs:TFIFKF (match_dup 1)))
|
||||
(use (match_dup 2))])]
|
||||
{
|
||||
if (GET_CODE (operands[2]) == SCRATCH)
|
||||
operands[2] = gen_reg_rtx (V16QImode);
|
||||
|
||||
operands[3] = gen_reg_rtx (V16QImode);
|
||||
emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
|
||||
}
|
||||
[(set_attr "length" "8")
|
||||
(set_attr "type" "vecsimple")])
|
||||
|
||||
(define_insn "*ieee_128bit_vsx_abs<mode>2_internal"
|
||||
[(set (match_operand:TFIFKF 0 "register_operand" "=wa")
|
||||
(abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
|
||||
(use (match_operand:V16QI 2 "register_operand" "=v"))]
|
||||
"TARGET_FLOAT128"
|
||||
"xxlandc %x0,%x1,%x2"
|
||||
[(set_attr "type" "vecsimple")])
|
||||
|
||||
;; IEEE 128-bit negative absolute value
|
||||
(define_insn_and_split "*ieee_128bit_vsx_nabs<mode>2"
|
||||
[(set (match_operand:TFIFKF 0 "register_operand" "=wa")
|
||||
(neg:TFIFKF
|
||||
(abs:TFIFKF
|
||||
(match_operand:TFIFKF 1 "register_operand" "wa"))))
|
||||
(clobber (match_scratch:V16QI 2 "=v"))]
|
||||
"TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
|
||||
"#"
|
||||
"&& 1"
|
||||
[(parallel [(set (match_dup 0)
|
||||
(abs:TFIFKF (match_dup 1)))
|
||||
(use (match_dup 2))])]
|
||||
{
|
||||
if (GET_CODE (operands[2]) == SCRATCH)
|
||||
operands[2] = gen_reg_rtx (V16QImode);
|
||||
|
||||
operands[3] = gen_reg_rtx (V16QImode);
|
||||
emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
|
||||
}
|
||||
[(set_attr "length" "8")
|
||||
(set_attr "type" "vecsimple")])
|
||||
|
||||
(define_insn "*ieee_128bit_vsx_nabs<mode>2_internal"
|
||||
[(set (match_operand:TFIFKF 0 "register_operand" "=wa")
|
||||
(neg:TFIFKF
|
||||
(abs:TFIFKF
|
||||
(match_operand:TFIFKF 1 "register_operand" "wa"))))
|
||||
(use (match_operand:V16QI 2 "register_operand" "=v"))]
|
||||
"TARGET_FLOAT128"
|
||||
"xxlor %x0,%x1,%x2"
|
||||
[(set_attr "type" "vecsimple")])
|
||||
|
||||
;; Float128 conversion functions. These expand to library function calls.
|
||||
|
||||
(define_expand "extend<FLOAT128_SFDFTF:mode><IFKF:mode>2"
|
||||
[(set (match_operand:IFKF 0 "nonimmediate_operand" "")
|
||||
(float_extend:IFKF
|
||||
(match_operand:FLOAT128_SFDFTF 1 "gpc_reg_operand" "")))]
|
||||
"TARGET_FLOAT128"
|
||||
{
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], false);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2"
|
||||
[(set (match_operand:FLOAT128_SFDFTF 0 "nonimmediate_operand" "")
|
||||
(float_truncate:FLOAT128_SFDFTF
|
||||
(match_operand:IFKF 1 "gpc_reg_operand" "")))]
|
||||
"TARGET_FLOAT128"
|
||||
{
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], false);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "fix_trunc<IFKF:mode><SDI:mode>2"
|
||||
[(set (match_operand:SDI 0 "nonimmediate_operand" "")
|
||||
(fix:SDI (match_operand:IFKF 1 "gpc_reg_operand" "")))]
|
||||
"TARGET_FLOAT128"
|
||||
{
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], false);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "fixuns_trunc<IFKF:mode><SDI:mode>2"
|
||||
[(set (match_operand:SDI 0 "nonimmediate_operand" "")
|
||||
(unsigned_fix:SDI (match_operand:IFKF 1 "gpc_reg_operand" "")))]
|
||||
"TARGET_FLOAT128"
|
||||
{
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], true);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "float<SDI:mode><IFKF:mode>2"
|
||||
[(set (match_operand:IFKF 0 "nonimmediate_operand" "")
|
||||
(float:KF (match_operand:SDI 1 "gpc_reg_operand" "")))]
|
||||
"TARGET_FLOAT128"
|
||||
{
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], false);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "floatuns<SDI:mode><IFKF:mode>2"
|
||||
[(set (match_operand:IFKF 0 "nonimmediate_operand" "")
|
||||
(unsigned_float:IFKF (match_operand:SDI 1 "gpc_reg_operand" "")))]
|
||||
"TARGET_FLOAT128"
|
||||
{
|
||||
rs6000_expand_float128_convert (operands[0], operands[1], true);
|
||||
DONE;
|
||||
})
|
||||
|
||||
|
||||
;; Reload helper functions used by rs6000_secondary_reload. The patterns all
|
||||
;; must have 3 arguments, and scratch register constraint must be a single
|
||||
|
@ -12122,7 +12413,10 @@
|
|||
;; Pack/unpack 128-bit floating point types that take 2 scalar registers
|
||||
|
||||
; Type of the 64-bit part when packing/unpacking 128-bit floating point types
|
||||
(define_mode_attr FP128_64 [(TF "DF") (TD "DI")])
|
||||
(define_mode_attr FP128_64 [(TF "DF")
|
||||
(IF "DF")
|
||||
(TD "DI")
|
||||
(KF "DI")])
|
||||
|
||||
(define_expand "unpack<mode>"
|
||||
[(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "")
|
||||
|
@ -12130,7 +12424,7 @@
|
|||
[(match_operand:FMOVE128 1 "register_operand" "")
|
||||
(match_operand:QI 2 "const_0_to_1_operand" "")]
|
||||
UNSPEC_UNPACK_128BIT))]
|
||||
""
|
||||
"FLOAT128_2REG_P (<MODE>mode)"
|
||||
"")
|
||||
|
||||
(define_insn_and_split "unpack<mode>_dm"
|
||||
|
@ -12139,7 +12433,7 @@
|
|||
[(match_operand:FMOVE128 1 "register_operand" "d,d,r,d,r")
|
||||
(match_operand:QI 2 "const_0_to_1_operand" "i,i,i,i,i")]
|
||||
UNSPEC_UNPACK_128BIT))]
|
||||
"TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
|
||||
"TARGET_POWERPC64 && TARGET_DIRECT_MOVE && FLOAT128_2REG_P (<MODE>mode)"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(set (match_dup 0) (match_dup 3))]
|
||||
|
@ -12163,7 +12457,7 @@
|
|||
[(match_operand:FMOVE128 1 "register_operand" "d,d")
|
||||
(match_operand:QI 2 "const_0_to_1_operand" "i,i")]
|
||||
UNSPEC_UNPACK_128BIT))]
|
||||
"!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE"
|
||||
"(!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE) && FLOAT128_2REG_P (<MODE>mode)"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(set (match_dup 0) (match_dup 3))]
|
||||
|
@ -12187,7 +12481,7 @@
|
|||
[(match_operand:<FP128_64> 1 "register_operand" "0,d")
|
||||
(match_operand:<FP128_64> 2 "register_operand" "d,d")]
|
||||
UNSPEC_PACK_128BIT))]
|
||||
""
|
||||
"FLOAT128_2REG_P (<MODE>mode)"
|
||||
"@
|
||||
fmr %L0,%2
|
||||
#"
|
||||
|
@ -12207,12 +12501,12 @@
|
|||
[(set_attr "type" "fp,fp")
|
||||
(set_attr "length" "4,8")])
|
||||
|
||||
(define_insn "unpackv1ti"
|
||||
(define_insn "unpack<mode>"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d,d")
|
||||
(unspec:DI [(match_operand:V1TI 1 "register_operand" "0,wa")
|
||||
(unspec:DI [(match_operand:FMOVE128_VSX 1 "register_operand" "0,wa")
|
||||
(match_operand:QI 2 "const_0_to_1_operand" "O,i")]
|
||||
UNSPEC_UNPACK_128BIT))]
|
||||
"TARGET_VSX"
|
||||
"VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
|
||||
{
|
||||
if (REGNO (operands[0]) == REGNO (operands[1]) && INTVAL (operands[2]) == 0)
|
||||
return ASM_COMMENT_START " xxpermdi to same register";
|
||||
|
@ -12220,19 +12514,17 @@
|
|||
operands[3] = GEN_INT (INTVAL (operands[2]) == 0 ? 0 : 3);
|
||||
return "xxpermdi %x0,%x1,%x1,%3";
|
||||
}
|
||||
[(set_attr "type" "vecperm")
|
||||
(set_attr "length" "4")])
|
||||
[(set_attr "type" "vecperm")])
|
||||
|
||||
(define_insn "packv1ti"
|
||||
[(set (match_operand:V1TI 0 "register_operand" "=wa")
|
||||
(unspec:V1TI
|
||||
(define_insn "pack<mode>"
|
||||
[(set (match_operand:FMOVE128_VSX 0 "register_operand" "=wa")
|
||||
(unspec:FMOVE128_VSX
|
||||
[(match_operand:DI 1 "register_operand" "d")
|
||||
(match_operand:DI 2 "register_operand" "d")]
|
||||
UNSPEC_PACK_128BIT))]
|
||||
"TARGET_VSX"
|
||||
"xxpermdi %x0,%x1,%x2,0"
|
||||
[(set_attr "type" "vecperm")
|
||||
(set_attr "length" "4")])
|
||||
[(set_attr "type" "vecperm")])
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue