+
+
+;
+; Population count instruction
+;
+
+; The S/390 popcount instruction counts the bits of op1 in 8 byte
+; portions and stores the result in the corresponding bytes in op0.
+(define_insn "*popcount<mode>"
+ [(set (match_operand:INT 0 "register_operand" "=d")
+ (unspec:INT [(match_operand:INT 1 "register_operand" "d")] UNSPEC_POPCNT))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_Z196"
+ "popcnt\t%0,%1"
+ [(set_attr "op_type" "RRE")])
+
+(define_expand "popcountdi2"
+ [; popcnt op0, op1
+ (parallel [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_operand:DI 1 "register_operand")]
+ UNSPEC_POPCNT))
+ (clobber (reg:CC CC_REGNUM))])
+ ; sllg op2, op0, 32
+ (set (match_dup 2) (ashift:DI (match_dup 0) (const_int 32)))
+ ; agr op0, op2
+ (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])
+ ; sllg op2, op0, 16
+ (set (match_operand:DI 2 "register_operand" "")
+ (ashift:DI (match_dup 0) (const_int 16)))
+ ; agr op0, op2
+ (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])
+ ; sllg op2, op0, 8
+ (set (match_dup 2) (ashift:DI (match_dup 0) (const_int 8)))
+ ; agr op0, op2
+ (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])
+ ; srlg op0, op0, 56
+ (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 56)))]
+ "TARGET_Z196 && TARGET_64BIT"
+ "operands[2] = gen_reg_rtx (DImode);")
+
+(define_expand "popcountsi2"
+ [; popcnt op0, op1
+ (parallel [(set (match_operand:SI 0 "register_operand" "")
+ (unspec:SI [(match_operand:SI 1 "register_operand")]
+ UNSPEC_POPCNT))
+ (clobber (reg:CC CC_REGNUM))])
+ ; sllk op2, op0, 16
+ (set (match_operand:SI 2 "register_operand" "")
+ (ashift:SI (match_dup 0) (const_int 16)))
+ ; ar op0, op2
+ (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])
+ ; sllk op2, op0, 8
+ (set (match_dup 2) (ashift:SI (match_dup 0) (const_int 8)))
+ ; ar op0, op2
+ (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])
+ ; srl op0, op0, 24
+ (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
+ "TARGET_Z196"
+ "operands[2] = gen_reg_rtx (SImode);")
+
+(define_expand "popcounthi2"
+ [; popcnt op0, op1
+ (parallel [(set (match_operand:HI 0 "register_operand" "")
+ (unspec:HI [(match_operand:HI 1 "register_operand")]
+ UNSPEC_POPCNT))
+ (clobber (reg:CC CC_REGNUM))])
+ ; sllk op2, op0, 8
+ (set (match_operand:SI 2 "register_operand" "")
+ (ashift:SI (match_dup 0) (const_int 8)))
+ ; ar op0, op2
+ (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])
+ ; srl op0, op0, 8
+ (set (match_dup 0) (lshiftrt:HI (match_dup 0) (const_int 8)))]
+ "TARGET_Z196"
+ "operands[2] = gen_reg_rtx (SImode);")
+
+(define_expand "popcountqi2"
+ [; popcnt op0, op1
+ (parallel [(set (match_operand:QI 0 "register_operand" "")
+ (unspec:QI [(match_operand:QI 1 "register_operand")]
+ UNSPEC_POPCNT))
+ (clobber (reg:CC CC_REGNUM))])]
+ "TARGET_Z196"
+ "")
+
+;;
+;;- Copy sign instructions
+;;
+
+(define_insn "copysign<mode>3"
+ [(set (match_operand:FP 0 "register_operand" "=f")
+ (unspec:FP [(match_operand:FP 1 "register_operand" "<fT0>")
+ (match_operand:FP 2 "register_operand" "f")]
+ UNSPEC_COPYSIGN))]
+ "TARGET_Z196"
+ "cpsdr\t%0,%2,%1"
+ [(set_attr "op_type" "RRF")
+ (set_attr "type" "fsimp<mode>")])