+;; Double-precision floating point instructions for IBM long double.
+
+(define_insn_and_split "spe_trunctfdf2_internal1"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=r,?r")
+ (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "0,r")))]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
+ "@
+ #
+ evor %0,%1,%1"
+ "&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])"
+ [(const_int 0)]
+{
+ emit_note (NOTE_INSN_DELETED);
+ DONE;
+})
+
+(define_insn_and_split "spe_trunctfsf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=r")
+ (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "r")))
+ (clobber (match_scratch:DF 2 "=r"))]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2)
+ (float_truncate:DF (match_dup 1)))
+ (set (match_dup 0)
+ (float_truncate:SF (match_dup 2)))]
+ "")
+
+(define_insn "spe_extenddftf2"
+ [(set (match_operand:TF 0 "rs6000_nonimmediate_operand" "=r,?r,r,o")
+ (float_extend:TF (match_operand:DF 1 "input_operand" "0,r,m,r")))
+ (clobber (match_scratch:DF 2 "=X,X,X,&r"))]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
+ "@
+ evxor %L0,%L0,%L0
+ evor %0,%1,%1\;evxor %L0,%L0,%L0
+ evldd%X1 %0,%y1\;evxor %L0,%L0,%L0
+ evstdd%X0 %1,%y0\;evxor %2,%2,%2\;evstdd %2,%Y0")
+
+(define_expand "spe_fix_trunctfsi2"
+ [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ (fix:SI (match_operand:TF 1 "gpc_reg_operand" "")))
+ (clobber (match_dup 2))
+ (clobber (match_dup 3))
+ (clobber (match_dup 4))])]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
+{
+ operands[2] = gen_reg_rtx (DFmode);
+ operands[3] = gen_reg_rtx (SImode);
+ operands[4] = gen_reg_rtx (SImode);
+})
+
+; Like fix_trunc_helper, add with rounding towards 0.
+(define_insn "spe_fix_trunctfsi2_internal"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (fix:SI (match_operand:TF 1 "gpc_reg_operand" "r")))
+ (clobber (match_operand:DF 2 "gpc_reg_operand" "=r"))
+ (clobber (match_operand:SI 3 "gpc_reg_operand" "=&r"))
+ (clobber (match_operand:SI 4 "gpc_reg_operand" "=&r"))]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
+ "mfspefscr %3\;rlwinm %4,%3,0,0,29\;ori %4,%4,1\;efdadd %2,%1,%L1\;mtspefscr %3\;efdctsiz %0, %2")
+
+(define_insn "spe_negtf2_internal"
+ [(set (match_operand:TF 0 "gpc_reg_operand" "=r")
+ (neg:TF (match_operand:TF 1 "gpc_reg_operand" "r")))]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
+ "*
+{
+ if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
+ return \"efdneg %L0,%L1\;efdneg %0,%1\";
+ else
+ return \"efdneg %0,%1\;efdneg %L0,%L1\";
+}")
+
+(define_expand "spe_abstf2_cmp"
+ [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
+ (match_operand:TF 1 "gpc_reg_operand" "f"))
+ (set (match_dup 3) (match_dup 5))
+ (set (match_dup 5) (abs:DF (match_dup 5)))
+ (set (match_dup 4) (unspec:CCFP [(compare:CCFP (match_dup 3)
+ (match_dup 5))] CMPDFEQ_GPR))
+ (set (pc) (if_then_else (eq (match_dup 4) (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (match_dup 6) (neg:DF (match_dup 6)))]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
+ "
+{
+ const int hi_word = FLOAT_WORDS_BIG_ENDIAN ? 0 : GET_MODE_SIZE (DFmode);
+ const int lo_word = FLOAT_WORDS_BIG_ENDIAN ? GET_MODE_SIZE (DFmode) : 0;
+ operands[3] = gen_reg_rtx (DFmode);
+ operands[4] = gen_reg_rtx (CCFPmode);
+ operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
+ operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
+}")
+
+(define_expand "spe_abstf2_tst"
+ [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
+ (match_operand:TF 1 "gpc_reg_operand" "f"))
+ (set (match_dup 3) (match_dup 5))
+ (set (match_dup 5) (abs:DF (match_dup 5)))
+ (set (match_dup 4) (unspec:CCFP [(compare:CCFP (match_dup 3)
+ (match_dup 5))] TSTDFEQ_GPR))
+ (set (pc) (if_then_else (eq (match_dup 4) (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (match_dup 6) (neg:DF (match_dup 6)))]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
+ "
+{
+ const int hi_word = FLOAT_WORDS_BIG_ENDIAN ? 0 : GET_MODE_SIZE (DFmode);
+ const int lo_word = FLOAT_WORDS_BIG_ENDIAN ? GET_MODE_SIZE (DFmode) : 0;
+ operands[3] = gen_reg_rtx (DFmode);
+ operands[4] = gen_reg_rtx (CCFPmode);
+ operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
+ operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
+}")
+