(trap_cmp_op, mips_gen_conditional_trap): New func decls.
* config/mips/mips.h (ISA_HAS_COND_TRAP): New macro.
(PREDICATE_CODES): Add "trap_cmp_op".
* config/mips/mips.c
(trap_cmp_op, mips_gen_conditional_trap): New functions.
* config/mips/mips.md (trap, conditional_trap): New patterns.
From-SVN: r36371
+2000-09-12 Greg McGary <greg@mcgary.org>
+
+ * config/mips/mips-protos.h
+ (trap_cmp_op, mips_gen_conditional_trap): New func decls.
+ * config/mips/mips.h (ISA_HAS_COND_TRAP): New macro.
+ (PREDICATE_CODES): Add "trap_cmp_op".
+ * config/mips/mips.c
+ (trap_cmp_op, mips_gen_conditional_trap): New functions.
+ * config/mips/mips.md (trap, conditional_trap): New patterns.
+
2000-09-12 Bernd Schmidt <bernds@redhat.co.uk>
* flow.c (try_pre_increment_1): Don't do anything to sets of the stack
extern int arith32_operand PARAMS ((rtx, enum machine_mode));
extern int arith_operand PARAMS ((rtx, enum machine_mode));
extern int cmp_op PARAMS ((rtx, enum machine_mode));
+extern int trap_cmp_op PARAMS ((rtx, enum machine_mode));
extern int const_float_1_operand PARAMS ((rtx, enum machine_mode));
extern void expand_block_move PARAMS ((rtx []));
extern int equality_op PARAMS ((rtx, enum machine_mode));
#endif /* TREE_CODE */
extern void gen_conditional_branch PARAMS ((rtx[], enum rtx_code));
extern void gen_conditional_move PARAMS ((rtx *));
+extern void mips_gen_conditional_trap PARAMS ((rtx *));
extern int large_int PARAMS ((rtx, enum machine_mode));
extern void machine_dependent_reorg PARAMS ((rtx));
extern int mips_address_cost PARAMS ((rtx));
/* registers to check for load delay */
rtx mips_load_reg, mips_load_reg2, mips_load_reg3, mips_load_reg4;
-/* Cached operands, and operator to compare for use in set/branch on
- condition codes. */
+/* Cached operands, and operator to compare for use in set/branch/trap
+ on condition codes. */
rtx branch_cmp[2];
/* what type of branch to use */
return GET_RTX_CLASS (GET_CODE (op)) == '<';
}
+/* Return nonzero if the code is a relational operation suitable for a
+ conditional trap instructuion (only EQ, NE, LT, LTU, GE, GEU).
+ We need this in the insn that expands `trap_if' in order to prevent
+ combine from erroneously altering the condition. */
+
+int
+trap_cmp_op (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (mode != GET_MODE (op))
+ return 0;
+
+ switch (GET_CODE (op))
+ {
+ case EQ:
+ case NE:
+ case LT:
+ case LTU:
+ case GE:
+ case GEU:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
/* Return nonzero if the operand is either the PC or a label_ref. */
int
CONST0_RTX (SImode)),
operands[2], operands[3])));
}
+
+/* Emit the common code for conditional moves. OPERANDS is the array
+ of operands passed to the conditional move defined_expand. */
+
+void
+mips_gen_conditional_trap (operands)
+ rtx operands[];
+{
+ rtx op0, op1;
+ enum rtx_code cmp_code = GET_CODE (operands[0]);
+ enum machine_mode mode = GET_MODE (branch_cmp[0]);
+
+ /* MIPS conditional trap machine instructions don't have GT or LE
+ flavors, so we must invert the comparison and convert to LT and
+ GE, respectively. */
+ switch (cmp_code)
+ {
+ case GT: cmp_code = LT; break;
+ case LE: cmp_code = GE; break;
+ case GTU: cmp_code = LTU; break;
+ case LEU: cmp_code = GEU; break;
+ default: break;
+ }
+ if (cmp_code == GET_CODE (operands[0]))
+ {
+ op0 = force_reg (mode, branch_cmp[0]);
+ op1 = branch_cmp[1];
+ }
+ else
+ {
+ op0 = force_reg (mode, branch_cmp[1]);
+ op1 = branch_cmp[0];
+ }
+ if (GET_CODE (op1) == CONST_INT && ! SMALL_INT (op1))
+ op1 = force_reg (mode, op1);
+
+ emit_insn (gen_rtx_TRAP_IF (VOIDmode,
+ gen_rtx (cmp_code, GET_MODE (operands[0]), op0, op1),
+ operands[1]));
+}
\f
/* Write a loop to move a constant number of bytes.
Generate load/stores as follows:
#define ISA_HAS_FP4 (mips_isa == 4 \
)
+/* ISA has conditional trap instructions. */
+#define ISA_HAS_COND_TRAP (mips_isa >= 2)
/* CC1_SPEC causes -mips3 and -mips4 to set -mfp64 and -mgp64; -mips1 or
{"equality_op", { EQ, NE }}, \
{"cmp_op", { EQ, NE, GT, GE, GTU, GEU, LT, LE, \
LTU, LEU }}, \
+ {"trap_cmp_op", { EQ, NE, GE, GEU, LT, LTU }}, \
{"pc_or_label_operand", { PC, LABEL_REF }}, \
{"call_insn_operand", { CONST_INT, CONST, SYMBOL_REF, REG}}, \
{"move_operand", { CONST_INT, CONST_DOUBLE, CONST, \
;;
;; (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "SF")) 54 0)
;; (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "DF")) 112 0)
+\f
+;;
+;; ....................
+;;
+;; CONDITIONAL TRAPS
+;;
+;; ....................
+;;
+
+(define_insn "trap"
+ [(trap_if (const_int 1) (const_int 0))]
+ ""
+ "*
+{
+ if (ISA_HAS_COND_TRAP)
+ return \"teq\\t$0,$0\";
+ else
+ return \"break\";
+}")
+
+(define_expand "conditional_trap"
+ [(trap_if (match_operator 0 "cmp_op"
+ [(match_dup 2) (match_dup 3)])
+ (match_operand 1 "const_int_operand" ""))]
+ "ISA_HAS_COND_TRAP"
+ "
+{
+ mips_gen_conditional_trap (operands);
+ DONE;
+}")
+;; Match a TRAP_IF with 2nd arg of 0. The div_trap_* insns match a
+;; 2nd arg of any CONST_INT, so this insn must appear first.
+;; gen_div_trap always generates TRAP_IF with 2nd arg of 6 or 7.
+
+(define_insn ""
+ [(trap_if (match_operator 0 "trap_cmp_op"
+ [(match_operand:SI 1 "reg_or_0_operand" "d")
+ (match_operand:SI 2 "nonmemory_operand" "dI")])
+ (const_int 0))]
+ "ISA_HAS_COND_TRAP"
+ "t%C0\\t%z1,%z2")
\f
;;
;; ....................