summaryrefslogtreecommitdiff
path: root/gcc/config/mips/mips.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/mips/mips.c')
-rw-r--r--gcc/config/mips/mips.c72
1 files changed, 70 insertions, 2 deletions
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index f059dddd616..860ce956d7b 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -188,8 +188,8 @@ int num_refs[3];
/* 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 */
@@ -964,6 +964,34 @@ cmp_op (op, mode)
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
@@ -3139,6 +3167,46 @@ gen_conditional_move (operands)
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]));
+}
/* Write a loop to move a constant number of bytes.
Generate load/stores as follows: