if (GET_CODE (set_src) == SUBREG)
set_src = alter_subreg (set_src);
- /* Ugly, but gen_highpart will crap out here for 32-bit targets. */
- dest1 = gen_rtx_SUBREG (DFmode, set_dest, WORDS_BIG_ENDIAN == 0);
- dest2 = gen_rtx_SUBREG (DFmode, set_dest, WORDS_BIG_ENDIAN != 0);
- src1 = gen_rtx_SUBREG (DFmode, set_src, WORDS_BIG_ENDIAN == 0);
- src2 = gen_rtx_SUBREG (DFmode, set_src, WORDS_BIG_ENDIAN != 0);
+ dest1 = gen_rtx_REG (DFmode,
+ REGNO (set_dest) + (WORDS_BIG_ENDIAN ? 0 : 2));
+ dest2 = gen_rtx_REG (DFmode,
+ REGNO (set_dest) + (WORDS_BIG_ENDIAN ? 2 : 0));
+ src1 = gen_rtx_REG (DFmode,
+ REGNO (set_src) + (WORDS_BIG_ENDIAN ? 0 : 2));
+ src2 = gen_rtx_REG (DFmode,
+ REGNO (set_src) + (WORDS_BIG_ENDIAN ? 2 : 0));
/* Now emit using the real source and destination we found, swapping
the order if we detect overlap. */
rtx word0 = change_address (operands[1], DFmode, NULL_RTX);
rtx word1 = change_address (operands[1], DFmode,
plus_constant_for_output (XEXP (word0, 0), 8));
- rtx dest1, dest2;
+ rtx set_dest, dest1, dest2;
+
+ set_dest = operands[0];
+ if (GET_CODE (set_dest) == SUBREG)
+ set_dest = alter_subreg (set_dest);
- /* Ugly, but gen_highpart will crap out here for 32-bit targets. */
- dest1 = gen_rtx_SUBREG (DFmode, operands[0], WORDS_BIG_ENDIAN == 0);
- dest2 = gen_rtx_SUBREG (DFmode, operands[0], WORDS_BIG_ENDIAN != 0);
+ dest1 = gen_rtx_REG (DFmode,
+ REGNO (set_dest) + (WORDS_BIG_ENDIAN ? 0 : 2));
+ dest2 = gen_rtx_REG (DFmode,
+ REGNO (set_dest) + (WORDS_BIG_ENDIAN ? 2 : 0));
/* Now output, ordering such that we don't clobber any registers
mentioned in the address. */
[(clobber (const_int 0))]
"
{
- rtx word0 = change_address (operands[0], DFmode, NULL_RTX);
- rtx word1 = change_address (operands[0], DFmode,
- plus_constant_for_output (XEXP (word0, 0), 8));
- rtx src1, src2;
+ rtx word1 = change_address (operands[0], DFmode, NULL_RTX);
+ rtx word2 = change_address (operands[0], DFmode,
+ plus_constant_for_output (XEXP (word1, 0), 8));
+ rtx set_src, src1, src2;
- /* Ugly, but gen_highpart will crap out here for 32-bit targets. */
- src1 = gen_rtx_SUBREG (DFmode, operands[1], WORDS_BIG_ENDIAN == 0);
- src2 = gen_rtx_SUBREG (DFmode, operands[1], WORDS_BIG_ENDIAN != 0);
- emit_insn (gen_movdf (word0, src1));
- emit_insn (gen_movdf (word1, src2));
+ set_src = operands[1];
+ if (GET_CODE (set_src) == SUBREG)
+ set_src = alter_subreg (set_src);
+
+ src1 = gen_rtx_REG (DFmode,
+ REGNO (set_src) + (WORDS_BIG_ENDIAN ? 0 : 2));
+ src2 = gen_rtx_REG (DFmode,
+ REGNO (set_src) + (WORDS_BIG_ENDIAN ? 2 : 0));
+ emit_insn (gen_movdf (word1, src1));
+ emit_insn (gen_movdf (word2, src2));
DONE;
}")
\f
[(set_attr "type" "fpcmove")
(set_attr "length" "1")])
-(define_insn "*movdf_cc_sp64"
+(define_insn "movdf_cc_sp64"
[(set (match_operand:DF 0 "register_operand" "=e,e")
(if_then_else:DF (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
[(set_attr "type" "fpcmove")
(set_attr "length" "1")])
-(define_insn "*movtf_cc_sp64"
+(define_insn "*movtf_cc_hq_sp64"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(if_then_else:TF (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
[(set_attr "type" "fpcmove")
(set_attr "length" "1")])
+(define_insn "*movtf_cc_sp64"
+ [(set (match_operand:TF 0 "register_operand" "=e,e")
+ (if_then_else:TF (match_operator 1 "comparison_operator"
+ [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+ (const_int 0)])
+ (match_operand:TF 3 "register_operand" "e,0")
+ (match_operand:TF 4 "register_operand" "0,e")))]
+ "TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
+ "#"
+ [(set_attr "type" "fpcmove")
+ (set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:TF 0 "register_operand" "=e,e")
+ (if_then_else:TF (match_operator 1 "comparison_operator"
+ [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+ (const_int 0)])
+ (match_operand:TF 3 "register_operand" "e,0")
+ (match_operand:TF 4 "register_operand" "0,e")))]
+ "reload_completed && TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
+ [(clobber (const_int 0))]
+ "
+{
+ rtx set_dest = operands[0];
+ rtx set_srca = operands[3];
+ rtx set_srcb = operands[4];
+ int third = rtx_equal_p (set_dest, set_srca);
+ rtx dest1, dest2;
+ rtx srca1, srca2, srcb1, srcb2;
+
+ if (GET_CODE (set_dest) == SUBREG)
+ set_dest = alter_subreg (set_dest);
+ if (GET_CODE (set_srca) == SUBREG)
+ set_srca = alter_subreg (set_srca);
+ if (GET_CODE (set_srcb) == SUBREG)
+ set_srcb = alter_subreg (set_srcb);
+
+ dest1 = gen_rtx_REG (DFmode,
+ REGNO (set_dest) + (WORDS_BIG_ENDIAN ? 0 : 2));
+ dest2 = gen_rtx_REG (DFmode,
+ REGNO (set_dest) + (WORDS_BIG_ENDIAN ? 2 : 0));
+ srca1 = gen_rtx_REG (DFmode,
+ REGNO (set_srca) + (WORDS_BIG_ENDIAN ? 0 : 2));
+ srca2 = gen_rtx_REG (DFmode,
+ REGNO (set_srca) + (WORDS_BIG_ENDIAN ? 2 : 0));
+ srcb1 = gen_rtx_REG (DFmode,
+ REGNO (set_srcb) + (WORDS_BIG_ENDIAN ? 0 : 2));
+ srcb2 = gen_rtx_REG (DFmode,
+ REGNO (set_srcb) + (WORDS_BIG_ENDIAN ? 2 : 0));
+
+ /* Now emit using the real source and destination we found, swapping
+ the order if we detect overlap. */
+ if ((third && reg_overlap_mentioned_p (dest1, srcb2))
+ || (!third && reg_overlap_mentioned_p (dest1, srca2)))
+ {
+ emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
+ emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
+ }
+ else
+ {
+ emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
+ emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
+ }
+ DONE;
+}")
+
(define_insn "*movqi_cc_reg_sp64"
[(set (match_operand:QI 0 "register_operand" "=r,r")
(if_then_else:QI (match_operator 1 "v9_regcmp_op"
[(set_attr "type" "fpcmove")
(set_attr "length" "1")])
-(define_insn "*movdf_cc_reg_sp64"
+(define_insn "movdf_cc_reg_sp64"
[(set (match_operand:DF 0 "register_operand" "=e,e")
(if_then_else:DF (match_operator 1 "v9_regcmp_op"
[(match_operand:DI 2 "register_operand" "r,r")
[(set_attr "type" "fpcmove")
(set_attr "length" "1")])
-(define_insn "*movtf_cc_reg_sp64"
+(define_insn "*movtf_cc_reg_hq_sp64"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(if_then_else:TF (match_operator 1 "v9_regcmp_op"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
(match_operand:TF 3 "register_operand" "e,0")
(match_operand:TF 4 "register_operand" "0,e")))]
- "TARGET_ARCH64 && TARGET_FPU"
+ "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
"@
fmovrq%D1\\t%2, %3, %0
fmovrq%d1\\t%2, %4, %0"
[(set_attr "type" "fpcmove")
(set_attr "length" "1")])
+
+(define_insn "*movtf_cc_reg_sp64"
+ [(set (match_operand:TF 0 "register_operand" "=e,e")
+ (if_then_else:TF (match_operator 1 "v9_regcmp_op"
+ [(match_operand:DI 2 "register_operand" "r,r")
+ (const_int 0)])
+ (match_operand:TF 3 "register_operand" "e,0")
+ (match_operand:TF 4 "register_operand" "0,e")))]
+ "TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
+ "#"
+ [(set_attr "type" "fpcmove")
+ (set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:TF 0 "register_operand" "=e,e")
+ (if_then_else:TF (match_operator 1 "v9_regcmp_op"
+ [(match_operand:DI 2 "register_operand" "r,r")
+ (const_int 0)])
+ (match_operand:TF 3 "register_operand" "e,0")
+ (match_operand:TF 4 "register_operand" "0,e")))]
+ "reload_completed && TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
+ [(clobber (const_int 0))]
+ "
+{
+ rtx set_dest = operands[0];
+ rtx set_srca = operands[3];
+ rtx set_srcb = operands[4];
+ int third = rtx_equal_p (set_dest, set_srca);
+ rtx dest1, dest2;
+ rtx srca1, srca2, srcb1, srcb2;
+
+ if (GET_CODE (set_dest) == SUBREG)
+ set_dest = alter_subreg (set_dest);
+ if (GET_CODE (set_srca) == SUBREG)
+ set_srca = alter_subreg (set_srca);
+ if (GET_CODE (set_srcb) == SUBREG)
+ set_srcb = alter_subreg (set_srcb);
+
+ dest1 = gen_rtx_REG (DFmode,
+ REGNO (set_dest) + (WORDS_BIG_ENDIAN ? 0 : 2));
+ dest2 = gen_rtx_REG (DFmode,
+ REGNO (set_dest) + (WORDS_BIG_ENDIAN ? 2 : 0));
+ srca1 = gen_rtx_REG (DFmode,
+ REGNO (set_srca) + (WORDS_BIG_ENDIAN ? 0 : 2));
+ srca2 = gen_rtx_REG (DFmode,
+ REGNO (set_srca) + (WORDS_BIG_ENDIAN ? 2 : 0));
+ srcb1 = gen_rtx_REG (DFmode,
+ REGNO (set_srcb) + (WORDS_BIG_ENDIAN ? 0 : 2));
+ srcb2 = gen_rtx_REG (DFmode,
+ REGNO (set_srcb) + (WORDS_BIG_ENDIAN ? 2 : 0));
+
+ /* Now emit using the real source and destination we found, swapping
+ the order if we detect overlap. */
+ if ((third && reg_overlap_mentioned_p (dest1, srcb2))
+ || (!third && reg_overlap_mentioned_p (dest1, srca2)))
+ {
+ emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
+ emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
+ }
+ else
+ {
+ emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
+ emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
+ }
+ DONE;
+}")
+
\f
;;- zero extension instructions