[(set_attr "prefix_rep" "1")
(set_attr "type" "bitmanip")
(set_attr "mode" "HI")])
+
+(define_expand "paritydi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (parity:DI (match_operand:DI 1 "nonimmediate_operand" "")))]
+ "! TARGET_POPCNT"
+{
+ rtx scratch = gen_reg_rtx (QImode);
+ rtx cond;
+
+ emit_insn (gen_paritydi2_cmp (NULL_RTX, NULL_RTX,
+ NULL_RTX, operands[1]));
+
+ cond = gen_rtx_fmt_ee (ORDERED, QImode,
+ gen_rtx_REG (CCmode, FLAGS_REG),
+ const0_rtx);
+ emit_insn (gen_rtx_SET (VOIDmode, scratch, cond));
+
+ if (TARGET_64BIT)
+ emit_insn (gen_zero_extendqidi2 (operands[0], scratch));
+ else
+ {
+ rtx tmp = gen_reg_rtx (SImode);
+
+ emit_insn (gen_zero_extendqisi2 (tmp, scratch));
+ emit_insn (gen_zero_extendsidi2 (operands[0], tmp));
+ }
+ DONE;
+})
+
+(define_insn_and_split "paritydi2_cmp"
+ [(set (reg:CC FLAGS_REG)
+ (parity:CC (match_operand:DI 3 "nonimmediate_operand" "0,m")))
+ (clobber (match_scratch:DI 0 "=r,X"))
+ (clobber (match_scratch:SI 1 "=r,r"))
+ (clobber (match_scratch:HI 2 "=Q,Q"))]
+ "! TARGET_POPCNT"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 1)
+ (xor:SI (match_dup 1) (match_dup 4)))
+ (clobber (reg:CC FLAGS_REG))])
+ (parallel
+ [(set (reg:CC FLAGS_REG)
+ (parity:CC (match_dup 1)))
+ (clobber (match_dup 1))
+ (clobber (match_dup 2))])]
+{
+ operands[4] = gen_lowpart (SImode, operands[3]);
+
+ if (MEM_P (operands[3]))
+ emit_move_insn (operands[1], gen_highpart (SImode, operands[3]));
+ else if (! TARGET_64BIT)
+ operands[1] = gen_highpart (SImode, operands[3]);
+ else
+ {
+ emit_move_insn (operands[1], gen_lowpart (SImode, operands[3]));
+ emit_insn (gen_lshrdi3 (operands[3], operands[3], GEN_INT (32)));
+ }
+})
+
+(define_expand "paritysi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (parity:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
+ "! TARGET_POPCNT"
+{
+ rtx scratch = gen_reg_rtx (QImode);
+ rtx cond;
+
+ emit_insn (gen_paritysi2_cmp (NULL_RTX, NULL_RTX, operands[1]));
+
+ cond = gen_rtx_fmt_ee (ORDERED, QImode,
+ gen_rtx_REG (CCmode, FLAGS_REG),
+ const0_rtx);
+ emit_insn (gen_rtx_SET (VOIDmode, scratch, cond));
+
+ emit_insn (gen_zero_extendqisi2 (operands[0], scratch));
+ DONE;
+})
+
+(define_insn_and_split "paritysi2_cmp"
+ [(set (reg:CC FLAGS_REG)
+ (parity:CC (match_operand:SI 2 "nonimmediate_operand" "0,m")))
+ (clobber (match_scratch:SI 0 "=r,X"))
+ (clobber (match_scratch:HI 1 "=Q,Q"))]
+ "! TARGET_POPCNT"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 1)
+ (xor:HI (match_dup 1) (match_dup 3)))
+ (clobber (reg:CC FLAGS_REG))])
+ (parallel
+ [(set (reg:CC FLAGS_REG)
+ (parity:CC (match_dup 1)))
+ (clobber (match_dup 1))])]
+{
+ operands[3] = gen_lowpart (HImode, operands[2]);
+
+ if (MEM_P (operands[2]))
+ emit_move_insn (operands[1], gen_highpart (HImode, operands[2]));
+ else
+ {
+ emit_move_insn (operands[1], gen_lowpart (HImode, operands[2]));
+ emit_insn (gen_lshrsi3 (operands[2], operands[2], GEN_INT (16)));
+ }
+})
+
+(define_insn "*parityhi2_cmp"
+ [(set (reg:CC FLAGS_REG)
+ (parity:CC (match_operand:HI 1 "register_operand" "0")))
+ (clobber (match_scratch:HI 0 "=Q"))]
+ "! TARGET_POPCNT"
+ "xor{b}\t{%h0, %b0|%b0, %h0}"
+ [(set_attr "length" "2")
+ (set_attr "mode" "HI")])
+
+(define_insn "*parityqi2_cmp"
+ [(set (reg:CC FLAGS_REG)
+ (parity:CC (match_operand:QI 0 "register_operand" "q")))]
+ "! TARGET_POPCNT"
+ "test{b}\t%0, %0"
+ [(set_attr "length" "2")
+ (set_attr "mode" "QI")])
\f
;; Thread-local storage patterns for ELF.
;;