(define_code_iterator most_cond [eq ne gt ge lt le gtu geu ltu leu
unordered ordered ])
+;; Likewise, but only the ones that use Z or S.
+(define_code_iterator zs_cond [eq ne gtu geu ltu leu ])
+
;; This code iterator is used for sign- and zero- extensions.
(define_mode_iterator small_int_modes [(HI "") (QI "")])
(define_expand "cbranchsi4"
[(set (pc)
- (if_then_else (match_operator:SI 0 "comparison_operator"
- [(match_operand:SI 1 "register_operand")
- (match_operand:SI 2 "rx_source_operand")])
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "rx_source_operand")])
(label_ref (match_operand 3 ""))
(pc)))
]
(define_insn_and_split "*cbranchsi4_<code>"
[(set (pc)
- (if_then_else (most_cond:SI (match_operand:SI 0 "register_operand" "r")
+ (if_then_else (most_cond (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "rx_source_operand" "riQ"))
(label_ref (match_operand 2 "" ""))
(pc)))
"
)
+;; -----------------------------------------------------------------------------
+;; These two are the canonical TST/branch insns. However, GCC
+;; generates a wide variety of tst-like patterns, we catch those
+;; below.
+(define_insn_and_split "*tstbranchsi4_<code>"
+ [(set (pc)
+ (if_then_else (zs_cond (and:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "rx_source_operand" "riQ"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ ]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ "
+ emit_insn (gen_tstsi (operands[0], operands[1]));
+
+ emit_jump_insn (gen_conditional_branch (operands[2],
+ gen_rtx_fmt_ee (<zs_cond:CODE>, CCmode,
+ gen_rtx_REG (CCmode, CC_REG), const0_rtx)));
+ "
+)
+
+;; Inverse of above
+(define_insn_and_split "*tstbranchsi4r_<code>"
+ [(set (pc)
+ (if_then_else (zs_cond (and:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "rx_source_operand" "riQ"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))
+ ]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ "
+ emit_insn (gen_tstsi (operands[0], operands[1]));
+
+ emit_jump_insn (gen_conditional_branch (operands[2],
+ gen_rtx_fmt_ee (reverse_condition (<zs_cond:CODE>), CCmode,
+ gen_rtx_REG (CCmode, CC_REG), const0_rtx)));
+ "
+)
+
+;; Various other ways that GCC codes "var & const"
+
+(define_insn_and_split "*tstbranchsi4m_eq"
+ [(set (pc)
+ (if_then_else (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand 1 "rx_constshift_operand" "i")
+ (match_operand 2 "rx_constshift_operand" "i"))
+ (const_int 0))
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ ]
+ ""
+ "#"
+ ""
+ [(set (pc)
+ (if_then_else (eq (and:SI (match_dup 0)
+ (match_dup 4))
+ (const_int 0))
+ (label_ref (match_dup 3))
+ (pc)))
+ ]
+ "operands[4] = GEN_INT (((1 << INTVAL (operands[1]))-1) << INTVAL (operands[2]));"
+)
+
+(define_insn_and_split "*tstbranchsi4m_ne"
+ [(set (pc)
+ (if_then_else (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand 1 "rx_constshift_operand" "i")
+ (match_operand 2 "rx_constshift_operand" "i"))
+ (const_int 0))
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ ]
+ ""
+ "#"
+ ""
+ [(set (pc)
+ (if_then_else (ne (and:SI (match_dup 0)
+ (match_dup 4))
+ (const_int 0))
+ (label_ref (match_dup 3))
+ (pc)))
+ ]
+ "operands[4] = GEN_INT (((1 << INTVAL (operands[1]))-1) << INTVAL (operands[2]));"
+)
+
+;; -----------------------------------------------------------------------------
+
(define_expand "cbranchsf4"
[(set (pc)
- (if_then_else (match_operator:SF 0 "comparison_operator"
- [(match_operand:SF 1 "register_operand")
- (match_operand:SF 2 "rx_source_operand")])
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:SF 1 "register_operand")
+ (match_operand:SF 2 "rx_source_operand")])
(label_ref (match_operand 3 ""))
(pc)))
]
(define_insn_and_split "*cbranchsf4_<code>"
[(set (pc)
- (if_then_else (most_cond:SF (match_operand:SF 0 "register_operand" "r")
- (match_operand:SF 1 "rx_source_operand" "rFiQ"))
+ (if_then_else (most_cond (match_operand:SF 0 "register_operand" "r")
+ (match_operand:SF 1 "rx_source_operand" "rFiQ"))
(label_ref (match_operand 2 "" ""))
(pc)))
]