}
}
+/* Emit the double word assignment DST = { LO, HI }. */
+
+void
+split_double_concat (machine_mode mode, rtx dst, rtx lo, rtx hi)
+{
+ rtx dlo, dhi;
+ int deleted_move_count = 0;
+ split_double_mode (mode, &dst, 1, &dlo, &dhi);
+ if (!rtx_equal_p (dlo, hi))
+ {
+ if (!rtx_equal_p (dlo, lo))
+ emit_move_insn (dlo, lo);
+ else
+ deleted_move_count++;
+ if (!rtx_equal_p (dhi, hi))
+ emit_move_insn (dhi, hi);
+ else
+ deleted_move_count++;
+ }
+ else if (!rtx_equal_p (lo, dhi))
+ {
+ if (!rtx_equal_p (dhi, hi))
+ emit_move_insn (dhi, hi);
+ else
+ deleted_move_count++;
+ if (!rtx_equal_p (dlo, lo))
+ emit_move_insn (dlo, lo);
+ else
+ deleted_move_count++;
+ }
+ else if (mode == TImode)
+ emit_insn (gen_swapdi (dlo, dhi));
+ else
+ emit_insn (gen_swapsi (dlo, dhi));
+
+ if (deleted_move_count == 2)
+ emit_note (NOTE_INSN_DELETED);
+}
+
+
/* Generate either "mov $0, reg" or "xor reg, reg", as appropriate
for the target. */
;; Zero extension instructions
+(define_insn_and_split "zero_extendditi2"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o")
+ (zero_extend:TI (match_operand:DI 1 "nonimmediate_operand" "rm,r")))]
+ "TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 3) (match_dup 1))
+ (set (match_dup 4) (const_int 0))]
+ "split_double_mode (TImode, &operands[0], 1, &operands[3], &operands[4]);")
+
(define_expand "zero_extendsidi2"
[(set (match_operand:DI 0 "nonimmediate_operand")
(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))])
}
})
+(define_insn_and_split "*add<dwi>3_doubleword_zext"
+ [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=r,o")
+ (plus:<DWI>
+ (zero_extend:<DWI>
+ (match_operand:DWIH 2 "nonimmediate_operand" "rm,r"))
+ (match_operand:<DWI> 1 "nonimmediate_operand" "0,0")))
+ (clobber (reg:CC FLAGS_REG))]
+ "ix86_binary_operator_ok (UNKNOWN, <DWI>mode, operands)"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (plus:DWIH (match_dup 1) (match_dup 2))
+ (match_dup 1)))
+ (set (match_dup 0)
+ (plus:DWIH (match_dup 1) (match_dup 2)))])
+ (parallel [(set (match_dup 3)
+ (plus:DWIH
+ (plus:DWIH
+ (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))
+ (match_dup 4))
+ (const_int 0)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "split_double_mode (<DWI>mode, &operands[0], 2, &operands[0], &operands[3]);")
+
(define_insn "*add<mode>_1"
[(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r")
(plus:SWI48
}
})
+(define_insn_and_split "*sub<dwi>3_doubleword_zext"
+ [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=r,o")
+ (minus:<DWI>
+ (match_operand:<DWI> 1 "nonimmediate_operand" "0,0")
+ (zero_extend:<DWI>
+ (match_operand:DWIH 2 "nonimmediate_operand" "rm,r"))))
+ (clobber (reg:CC FLAGS_REG))]
+ "ix86_binary_operator_ok (UNKNOWN, <DWI>mode, operands)"
+ "#"
+ "&& reload_completed"
+ [(parallel [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0)
+ (minus:DWIH (match_dup 1) (match_dup 2)))])
+ (parallel [(set (match_dup 3)
+ (minus:DWIH
+ (minus:DWIH
+ (match_dup 4)
+ (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)))
+ (const_int 0)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "split_double_mode (<DWI>mode, &operands[0], 2, &operands[0], &operands[3]);")
+
(define_insn "*sub<mode>_1"
[(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
(minus:SWI
;; Split DST = (HI<<32)|LO early to minimize register usage.
(define_code_iterator any_or_plus [plus ior xor])
-(define_split
- [(set (match_operand:DI 0 "register_operand")
- (any_or_plus:DI
- (ashift:DI (match_operand:DI 1 "register_operand")
- (const_int 32))
- (zero_extend:DI (match_operand:SI 2 "register_operand"))))]
- "!TARGET_64BIT"
- [(set (match_dup 3) (match_dup 4))
- (set (match_dup 5) (match_dup 2))]
+(define_insn_and_split "*concat<mode><dwi>3_1"
+ [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro")
+ (any_or_plus:<DWI>
+ (ashift:<DWI> (match_operand:<DWI> 1 "register_operand" "r")
+ (match_operand:<DWI> 2 "const_int_operand"))
+ (zero_extend:<DWI> (match_operand:DWIH 3 "register_operand" "r"))))]
+ "INTVAL (operands[2]) == <MODE_SIZE> * BITS_PER_UNIT"
+ "#"
+ "&& reload_completed"
+ [(clobber (const_int 0))]
{
- operands[3] = gen_highpart (SImode, operands[0]);
- operands[4] = gen_lowpart (SImode, operands[1]);
- operands[5] = gen_lowpart (SImode, operands[0]);
+ split_double_concat (<DWI>mode, operands[0], operands[3],
+ gen_lowpart (<MODE>mode, operands[1]));
+ DONE;
})
-(define_split
- [(set (match_operand:DI 0 "register_operand")
- (any_or_plus:DI
- (zero_extend:DI (match_operand:SI 1 "register_operand"))
- (ashift:DI (match_operand:DI 2 "register_operand")
- (const_int 32))))]
- "!TARGET_64BIT"
- [(set (match_dup 3) (match_dup 4))
- (set (match_dup 5) (match_dup 1))]
+(define_insn_and_split "*concat<mode><dwi>3_2"
+ [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro")
+ (any_or_plus:<DWI>
+ (zero_extend:<DWI> (match_operand:DWIH 1 "register_operand" "r"))
+ (ashift:<DWI> (match_operand:<DWI> 2 "register_operand" "r")
+ (match_operand:<DWI> 3 "const_int_operand"))))]
+ "INTVAL (operands[3]) == <MODE_SIZE> * BITS_PER_UNIT"
+ "#"
+ "&& reload_completed"
+ [(clobber (const_int 0))]
+{
+ split_double_concat (<DWI>mode, operands[0], operands[1],
+ gen_lowpart (<MODE>mode, operands[2]));
+ DONE;
+})
+
+(define_insn_and_split "*concat<mode><dwi>3_3"
+ [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro")
+ (any_or_plus:<DWI>
+ (ashift:<DWI>
+ (zero_extend:<DWI> (match_operand:DWIH 1 "register_operand" "r"))
+ (match_operand:<DWI> 2 "const_int_operand"))
+ (zero_extend:<DWI> (match_operand:DWIH 3 "register_operand" "r"))))]
+ "INTVAL (operands[2]) == <MODE_SIZE> * BITS_PER_UNIT"
+ "#"
+ "&& reload_completed"
+ [(clobber (const_int 0))]
{
- operands[3] = gen_highpart (SImode, operands[0]);
- operands[4] = gen_lowpart (SImode, operands[2]);
- operands[5] = gen_lowpart (SImode, operands[0]);
+ split_double_concat (<DWI>mode, operands[0], operands[3], operands[1]);
+ DONE;
+})
+
+(define_insn_and_split "*concat<mode><dwi>3_4"
+ [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro")
+ (any_or_plus:<DWI>
+ (zero_extend:<DWI> (match_operand:DWIH 1 "register_operand" "r"))
+ (ashift:<DWI>
+ (zero_extend:<DWI> (match_operand:DWIH 2 "register_operand" "r"))
+ (match_operand:<DWI> 3 "const_int_operand"))))]
+ "INTVAL (operands[3]) == <MODE_SIZE> * BITS_PER_UNIT"
+ "#"
+ "&& reload_completed"
+ [(clobber (const_int 0))]
+{
+ split_double_concat (<DWI>mode, operands[0], operands[1], operands[2]);
+ DONE;
})
\f
;; Negation instructions