;; SImode signed integer comparisons
;; -------------------------------------------------------------------------
-(define_insn ""
+;; Various patterns to generate the TST #imm, R0 instruction.
+;; Although this adds some pressure on the R0 register, it can potentially
+;; result in faster code, even if the operand has to be moved to R0 first.
+;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group
+;; instructions and thus will be executed in parallel. On SH4A TST #imm, R0
+;; is an EX group instruction but still can be executed in parallel with the
+;; MT group MOV Rm, Rn instruction.
+
+;; Usual TST #imm, R0 patterns for SI, HI and QI
+;; This is usually used for bit patterns other than contiguous bits
+;; and single bits.
+
+(define_insn "tstsi_t"
[(set (reg:SI T_REG)
- (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
+ (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r")
(match_operand:SI 1 "logical_operand" "K08,r"))
(const_int 0)))]
"TARGET_SH1"
"tst %1,%0"
[(set_attr "type" "mt_group")])
+(define_insn "tsthi_t"
+ [(set (reg:SI T_REG)
+ (eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z")
+ (match_operand 1 "const_int_operand")) 0)
+ (const_int 0)))]
+ "TARGET_SH1
+ && CONST_OK_FOR_K08 (INTVAL (operands[1]))"
+ "tst %1,%0"
+ [(set_attr "type" "mt_group")])
+
+(define_insn "tstqi_t"
+ [(set (reg:SI T_REG)
+ (eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z")
+ (match_operand 1 "const_int_operand")) 0)
+ (const_int 0)))]
+ "TARGET_SH1
+ && (CONST_OK_FOR_K08 (INTVAL (operands[1]))
+ || CONST_OK_FOR_I08 (INTVAL (operands[1])))"
+{
+ operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
+ return "tst %1,%0";
+}
+ [(set_attr "type" "mt_group")])
+
+;; Test low QI subreg against zero.
+;; This avoids unecessary zero extension before the test.
+
+(define_insn "tstqi_t_zero"
+ [(set (reg:SI T_REG)
+ (eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))]
+ "TARGET_SH1"
+ "tst #255,%0"
+ [(set_attr "type" "mt_group")])
+
+;; Extract LSB, negate and store in T bit.
+
+(define_insn "tstsi_t_and_not"
+ [(set (reg:SI T_REG)
+ (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
+ (const_int 1)))]
+ "TARGET_SH1"
+ "tst #1,%0"
+ [(set_attr "type" "mt_group")])
+
+;; Extract contiguous bits and compare them against zero.
+
+(define_insn "tstsi_t_zero_extract_eq"
+ [(set (reg:SI T_REG)
+ (eq:SI (zero_extract:SI (match_operand 0 "logical_operand" "z")
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand"))
+ (const_int 0)))]
+ "TARGET_SH1
+ && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
+{
+ operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
+ return "tst %1,%0";
+}
+ [(set_attr "type" "mt_group")])
+
+;; This split is required when testing bits in a QI subreg.
+
+(define_split
+ [(set (reg:SI T_REG)
+ (eq:SI (if_then_else:SI (zero_extract:SI
+ (match_operand 0 "logical_operand" "")
+ (match_operand 1 "const_int_operand")
+ (match_operand 2 "const_int_operand"))
+ (match_operand 3 "const_int_operand")
+ (const_int 0))
+ (const_int 0)))]
+ "TARGET_SH1
+ && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
+ && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
+ [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
+ (const_int 0)))]
+ "
+{
+ if (GET_MODE (operands[0]) == QImode)
+ operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
+}")
+
+;; Extract single bit, negate and store it in the T bit.
+;; Not used for SH4A.
+
+(define_insn "tstsi_t_zero_extract_xor"
+ [(set (reg:SI T_REG)
+ (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
+ (match_operand:SI 3 "const_int_operand"))
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand")))]
+ "TARGET_SH1
+ && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
+ && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
+ "tst %3,%0"
+ [(set_attr "type" "mt_group")])
+
+;; Extract single bit, negate and store it in the T bit.
+;; Used for SH4A little endian.
+
+(define_insn "tstsi_t_zero_extract_subreg_xor_little"
+ [(set (reg:SI T_REG)
+ (zero_extract:SI
+ (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
+ (match_operand:SI 3 "const_int_operand")) 0)
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand")))]
+ "TARGET_SH1 && TARGET_LITTLE_ENDIAN
+ && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
+ == (INTVAL (operands[3]) & 255)
+ && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
+{
+ operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
+ return "tst %3,%0";
+}
+ [(set_attr "type" "mt_group")])
+
+;; Extract single bit, negate and store it in the T bit.
+;; Used for SH4A big endian.
+
+(define_insn "tstsi_t_zero_extract_subreg_xor_big"
+ [(set (reg:SI T_REG)
+ (zero_extract:SI
+ (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
+ (match_operand:SI 3 "const_int_operand")) 3)
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand")))]
+ "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN
+ && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
+ == (INTVAL (operands[3]) & 255)
+ && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
+{
+ operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
+ return "tst %3,%0";
+}
+ [(set_attr "type" "mt_group")])
+
;; ??? Perhaps should only accept reg/constant if the register is reg 0.
;; That would still allow reload to create cmpi instructions, but would
;; perhaps allow forcing the constant into a register when that is better.
&& (arith_reg_operand (operands[1], SImode)
|| (immediate_operand (operands[1], SImode)
&& satisfies_constraint_I08 (operands[1])))"
- "bt 0f\;mov %1,%0\\n0:"
+ "bt 0f\;mov %1,%0\\n0:"
[(set_attr "type" "mt_group,arith") ;; poor approximation
(set_attr "length" "4")])
&& (arith_reg_operand (operands[1], SImode)
|| (immediate_operand (operands[1], SImode)
&& satisfies_constraint_I08 (operands[1])))"
- "bf 0f\;mov %1,%0\\n0:"
+ "bf 0f\;mov %1,%0\\n0:"
[(set_attr "type" "mt_group,arith") ;; poor approximation
(set_attr "length" "4")])
;; -------------------------------------------------------------------------
(define_insn "*andsi3_compact"
- [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
+ [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
(and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
- (match_operand:SI 2 "logical_operand" "r,K08")))]
+ (match_operand:SI 2 "logical_operand" "K08,r")))]
"TARGET_SH1"
"and %2,%0"
[(set_attr "type" "arith")])