extern char *version_string;
extern char *language_string;
+/* Enumeration for all of the relational tests, so that we can build
+ arrays indexed by the test type, and not worry about the order
+ of EQ, NE, etc. */
+
+enum internal_test {
+ ITEST_EQ,
+ ITEST_NE,
+ ITEST_GT,
+ ITEST_GE,
+ ITEST_LT,
+ ITEST_LE,
+ ITEST_GTU,
+ ITEST_GEU,
+ ITEST_LTU,
+ ITEST_LEU,
+ ITEST_MAX
+ };
+
/* Global variables for machine-dependent things. */
/* Threshold for data being put into the small data/bss area, instead
&& MD_REG_P (REGNO (op)));
}
+/* Return truth value of whether OP is the FP status register. */
+
+int
+fpsw_register_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (GET_CODE (op) == REG && ST_REG_P (REGNO (op)));
+}
+
/* Return truth value if a CONST_DOUBLE is ok to be a legitimate constant. */
int
return (classify_op (op, mode) & CLASS_FCMP_OP) != 0;
}
+
+/* Return true if the operand is either the PC or a label_ref. */
+
+int
+pc_or_label_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (op == pc_rtx)
+ return TRUE;
+
+ if (GET_CODE (op) == LABEL_REF)
+ return TRUE;
+
+ return FALSE;
+}
+
\f
/* Return an operand string if the given instruction's delay slot or
wrap it in a .set noreorder section. This is for filling delay
register rtx next_insn = (cur_insn) ? NEXT_INSN (cur_insn) : (rtx)0;
register int num_nops;
- if (type == DELAY_LOAD)
+ if (type == DELAY_LOAD || type == DELAY_FCMP)
num_nops = 1;
else if (type == DELAY_HILO)
return 4;
}
+\f
+/* Make normal rtx_code into something we can index from an array */
+
+static enum internal_test
+map_test_to_internal_test (test_code)
+ enum rtx_code test_code;
+{
+ enum internal_test test = ITEST_MAX;
+
+ switch (test_code)
+ {
+ case EQ: test = ITEST_EQ; break;
+ case NE: test = ITEST_NE; break;
+ case GT: test = ITEST_GT; break;
+ case GE: test = ITEST_GE; break;
+ case LT: test = ITEST_LT; break;
+ case LE: test = ITEST_LE; break;
+ case GTU: test = ITEST_GTU; break;
+ case GEU: test = ITEST_GEU; break;
+ case LTU: test = ITEST_LTU; break;
+ case LEU: test = ITEST_LEU; break;
+ }
+
+ return test;
+}
+
+\f
+/* Generate the code to compare two integer values. The return value is:
+ (reg:SI xx) The pseudo register the comparison is in
+ (const_int 0) The comparison is always false
+ (const_int 1) The comparison is always true
+ (rtx)0 No register, generate a simple branch. */
+
+rtx
+gen_int_relational (test_code, result, cmp0, cmp1, p_invert)
+ enum rtx_code test_code; /* relational test (EQ, etc) */
+ rtx result; /* result to store comp. or 0 if branch */
+ rtx cmp0; /* first operand to compare */
+ rtx cmp1; /* second operand to compare */
+ int *p_invert; /* NULL or ptr to hold whether branch needs */
+ /* to reserse it's test */
+{
+ struct cmp_info {
+ enum rtx_code test_code; /* code to use in instruction (LT vs. LTU) */
+ int const_low; /* low bound of constant we can accept */
+ int const_high; /* high bound of constant we can accept */
+ int const_add; /* constant to add (convert LE -> LT) */
+ int reverse_regs; /* reverse registers in test */
+ int invert_const; /* != 0 if invert value if cmp1 is constant */
+ int invert_reg; /* != 0 if invert value if cmp1 is register */
+ };
+
+ static struct cmp_info info[ (int)ITEST_MAX ] = {
+
+ { XOR, 0, 65535, 0, 0, 0, 0 }, /* EQ */
+ { XOR, 0, 65535, 0, 0, 1, 1 }, /* NE */
+ { LT, -32769, 32766, 1, 1, 1, 0 }, /* GT */
+ { LT, -32768, 32767, 0, 0, 1, 1 }, /* GE */
+ { LT, -32768, 32767, 0, 0, 0, 0 }, /* LT */
+ { LT, -32769, 32766, 1, 1, 0, 1 }, /* LE */
+ { LTU, -32769, 32766, 1, 1, 1, 0 }, /* GTU */
+ { LTU, -32768, 32767, 0, 0, 1, 1 }, /* GEU */
+ { LTU, -32768, 32767, 0, 0, 0, 0 }, /* LTU */
+ { LTU, -32769, 32766, 1, 1, 0, 1 }, /* LEU */
+ };
+
+ enum internal_test test;
+ struct cmp_info *p_info;
+ int branch_p;
+ int eqne_p;
+ int invert;
+ rtx reg;
+ rtx reg2;
+
+ test = map_test_to_internal_test (test_code);
+ if (test == ITEST_MAX)
+ abort ();
+
+ p_info = &info[ (int)test ];
+ eqne_p = (p_info->test_code == XOR);
+
+ /* See if the test is always true or false. */
+ if ((GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG)
+ && GET_CODE (cmp1) == CONST_INT)
+ {
+ int value = INTVAL (cmp1);
+ rtx truth = (rtx)0;
+
+ if (test == ITEST_GEU && value == 0)
+ truth = const1_rtx;
+
+ else if (test == ITEST_LTU && value == 0)
+ truth = const0_rtx;
+
+ else if (!TARGET_INT64)
+ {
+ if (test == ITEST_LTU && value == -1)
+ truth = const1_rtx;
+
+ else if (test == ITEST_GTU && value == -1)
+ truth = const0_rtx;
+
+ else if (test == ITEST_LEU && value == -1)
+ truth = const1_rtx;
+
+ else if (test == ITEST_GT && value == 0x7fffffff)
+ truth = const0_rtx;
+
+ else if (test == ITEST_LE && value == 0x7fffffff)
+ truth = const1_rtx;
+
+ else if (test == ITEST_LT && value == 0x80000000)
+ truth = const0_rtx;
+
+ else if (test == ITEST_GE && value == 0x80000000)
+ truth = const1_rtx;
+ }
+
+ if (truth != (rtx)0)
+ {
+ if (result != (rtx)0)
+ emit_move_insn (result, truth);
+
+ return truth;
+ }
+ }
+
+ /* Eliminate simple branches */
+ branch_p = (result == (rtx)0);
+ if (branch_p)
+ {
+ if (GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG)
+ {
+ /* Comparisons against zero are simple branches */
+ if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
+ return (rtx)0;
+
+ /* Test for beq/bne. */
+ if (eqne_p)
+ return (rtx)0;
+ }
+
+ /* allocate a psuedo to calculate the value in. */
+ result = gen_reg_rtx (SImode);
+ }
+
+ /* Make sure we can handle any constants given to us. */
+ if (GET_CODE (cmp0) == CONST_INT)
+ cmp0 = force_reg (SImode, cmp0);
+
+ if (GET_CODE (cmp1) == CONST_INT)
+ {
+ int value = INTVAL (cmp1);
+ if (value < p_info->const_low || value > p_info->const_high)
+ cmp1 = force_reg (SImode, cmp1);
+ }
+
+ /* See if we need to invert the result. */
+ invert = (GET_CODE (cmp1) == CONST_INT)
+ ? p_info->invert_const
+ : p_info->invert_reg;
+
+ if (p_invert != (int *)0)
+ {
+ *p_invert = invert;
+ invert = FALSE;
+ }
+
+ /* Comparison to constants, may involve adding 1 to change a LT into LE.
+ Comparison between two registers, may involve switching operands. */
+ if (GET_CODE (cmp1) == CONST_INT)
+ {
+ if (p_info->const_add != 0)
+ cmp1 = gen_rtx (CONST_INT, VOIDmode, INTVAL (cmp1) + p_info->const_add);
+ }
+ else if (p_info->reverse_regs)
+ {
+ rtx temp = cmp0;
+ cmp0 = cmp1;
+ cmp1 = temp;
+ }
+
+ reg = (invert || eqne_p) ? gen_reg_rtx (SImode) : result;
+ emit_move_insn (reg, gen_rtx (p_info->test_code, SImode, cmp0, cmp1));
+
+ if (test == ITEST_NE && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
+ {
+ emit_move_insn (result, gen_rtx (GTU, SImode, reg, const0_rtx));
+ invert = FALSE;
+ }
+
+ else if (eqne_p)
+ {
+ reg2 = (invert) ? gen_reg_rtx (SImode) : result;
+ emit_move_insn (reg2, gen_rtx (LTU, SImode, reg, const1_rtx));
+ reg = reg2;
+ }
+
+ if (invert)
+ emit_move_insn (result, gen_rtx (XOR, SImode, reg, const1_rtx));
+
+ return result;
+}
+
\f
/* Emit the common code for doing conditional branches.
operand[0] is the label to jump to.
rtx operands[];
enum rtx_code test_code;
{
- enum {
- I_EQ,
- I_NE,
- I_GT,
- I_GE,
- I_LT,
- I_LE,
- I_GTU,
- I_GEU,
- I_LTU,
- I_LEU,
- I_MAX
- } test = I_MAX;
-
- static enum machine_mode mode_map[(int)CMP_MAX][(int)I_MAX] = {
+ static enum machine_mode mode_map[(int)CMP_MAX][(int)ITEST_MAX] = {
{ /* CMP_SI */
- CC_EQmode, /* eq */
- CC_EQmode, /* ne */
- CCmode, /* gt */
- CCmode, /* ge */
- CCmode, /* lt */
- CCmode, /* le */
- CCmode, /* gtu */
- CCmode, /* geu */
- CCmode, /* ltu */
- CCmode, /* leu */
+ SImode, /* eq */
+ SImode, /* ne */
+ SImode, /* gt */
+ SImode, /* ge */
+ SImode, /* lt */
+ SImode, /* le */
+ SImode, /* gtu */
+ SImode, /* geu */
+ SImode, /* ltu */
+ SImode, /* leu */
},
{ /* CMP_SF */
CC_FPmode, /* eq */
- CC_FPmode, /* ne */
+ CC_REV_FPmode, /* ne */
CC_FPmode, /* gt */
CC_FPmode, /* ge */
CC_FPmode, /* lt */
},
{ /* CMP_DF */
CC_FPmode, /* eq */
- CC_FPmode, /* ne */
+ CC_REV_FPmode, /* ne */
CC_FPmode, /* gt */
CC_FPmode, /* ge */
CC_FPmode, /* lt */
};
enum machine_mode mode;
- enum cmp_type type = branch_type;
- rtx cmp0 = branch_cmp[0];
- rtx cmp1 = branch_cmp[1];
- rtx label = gen_rtx (LABEL_REF, VOIDmode, operands[0]);
-
- /* Make normal rtx_code into something we can index from an array */
- switch (test_code)
+ enum cmp_type type = branch_type;
+ rtx cmp0 = branch_cmp[0];
+ rtx cmp1 = branch_cmp[1];
+ rtx label1 = gen_rtx (LABEL_REF, VOIDmode, operands[0]);
+ rtx label2 = pc_rtx;
+ rtx reg = (rtx)0;
+ int invert = 0;
+ enum internal_test test = map_test_to_internal_test (test_code);
+
+ if (test == ITEST_MAX)
{
- case EQ: test = I_EQ; break;
- case NE: test = I_NE; break;
- case GT: test = I_GT; break;
- case GE: test = I_GE; break;
- case LT: test = I_LT; break;
- case LE: test = I_LE; break;
- case GTU: test = I_GTU; break;
- case GEU: test = I_GEU; break;
- case LTU: test = I_LTU; break;
- case LEU: test = I_LEU; break;
- }
-
- if (test == I_MAX)
- {
- mode = CCmode;
+ mode = SImode;
goto fail;
}
- /* Get the machine mode to use (CCmode, CC_EQmode, or CC_FPmode). */
+ /* Get the machine mode to use (CCmode, CC_EQmode, CC_FPmode, or CC_REV_FPmode). */
mode = mode_map[(int)type][(int)test];
if (mode == VOIDmode)
goto fail;
goto fail;
case CMP_SI:
- /* Change >, >=, <, <= tests against 0 to use CC_0mode, since we have
- special instructions to do these tests directly. */
-
- if (mode == CCmode && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
- {
- emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, cmp0));
- mode = CC_0mode;
- }
-
- else if (mode == CCmode && GET_CODE (cmp0) == CONST_INT && INTVAL (cmp0) == 0)
+ reg = gen_int_relational (test_code, (rtx)0, cmp0, cmp1, &invert);
+ if (reg != (rtx)0)
{
- emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, cmp1));
- test_code = reverse_condition (test_code);
- mode = CC_0mode;
+ cmp0 = reg;
+ cmp1 = const0_rtx;
+ test_code = NE;
}
- else
- {
- /* force args to register for equality comparisons. */
- if (mode == CC_EQmode && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
- cmp1 = force_reg (SImode, cmp1);
+ /* Make sure not non-zero constant if ==/!= */
+ else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
+ cmp1 = force_reg (SImode, cmp1);
- emit_insn (gen_rtx (SET, VOIDmode,
- cc0_rtx,
- gen_rtx (COMPARE, mode, cmp0, cmp1)));
- }
break;
case CMP_DF:
- emit_insn (gen_cmpdf_internal (cmp0, cmp1));
- break;
-
case CMP_SF:
- emit_insn (gen_cmpsf_internal (cmp0, cmp1));
+ {
+ rtx reg = gen_rtx (REG, mode, FPSW_REGNUM);
+ emit_insn (gen_rtx (SET, VOIDmode, reg, gen_rtx (test_code, mode, cmp0, cmp1)));
+ cmp0 = reg;
+ cmp1 = const0_rtx;
+ test_code = NE;
+ }
break;
}
/* Generate the jump */
+ if (invert)
+ {
+ label2 = label1;
+ label1 = pc_rtx;
+ }
+
emit_jump_insn (gen_rtx (SET, VOIDmode,
pc_rtx,
gen_rtx (IF_THEN_ELSE, VOIDmode,
- gen_rtx (test_code, mode, cc0_rtx, const0_rtx),
- label,
- pc_rtx)));
+ gen_rtx (test_code, mode, cmp0, cmp1),
+ label1,
+ label2)));
+
return;
fail:
mips_char_to_class['f'] = ((TARGET_HARD_FLOAT) ? FP_REGS : NO_REGS);
mips_char_to_class['h'] = HI_REG;
mips_char_to_class['l'] = LO_REG;
- mips_char_to_class['s'] = ST_REGS;
mips_char_to_class['x'] = MD_REGS;
mips_char_to_class['y'] = GR_REGS;
+ mips_char_to_class['z'] = ST_REGS;
/* Set up array to map GCC register number to debug register number.
Ignore the special purpose register numbers. */
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
{
- register int temp = FALSE;
+ register int temp;
+
+ if (mode == CC_FPmode || mode == CC_REV_FPmode)
+ temp = (regno == FPSW_REGNUM);
- if (GP_REG_P (regno))
+ else if (GP_REG_P (regno))
temp = ((regno & 1) == 0 || (size <= UNITS_PER_WORD));
else if (FP_REG_P (regno))
temp = ((TARGET_FLOAT64 || ((regno & 1) == 0))
- && (TARGET_DEBUG_H_MODE
- || class == MODE_FLOAT
- || class == MODE_COMPLEX_FLOAT));
+ && (class == MODE_FLOAT
+ || class == MODE_COMPLEX_FLOAT
+ || (TARGET_DEBUG_H_MODE && class == MODE_INT)));
else if (MD_REG_P (regno))
temp = (mode == SImode || (regno == MD_REG_FIRST && mode == DImode));
- else if (ST_REG_P (regno))
- temp = ((mode == SImode) || (class == MODE_CC));
+ else
+ temp = FALSE;
mips_hard_regno_mode_ok[(int)mode][regno] = temp;
}
(const_string "unknown"))
;; Main data type used by the insn
-(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF" (const_string "unknown"))
+(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF,FPSW" (const_string "unknown"))
;; # instructions (4 bytes each)
(define_attr "length" "" (const_int 1))
(define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0)
+(define_function_unit "fp_comp" 1 0 (eq_attr "type" "fcmp") 2 0)
+
(define_function_unit "transfer" 1 0 (eq_attr "type" "xfer") 2 0)
(define_function_unit "transfer" 1 0 (eq_attr "type" "hilo") 3 0)
(subreg:SI (match_dup 2) 0)))
(set (match_dup 3)
- (ltu:CC (subreg:SI (match_dup 0) 0)
+ (ltu:SI (subreg:SI (match_dup 0) 0)
(subreg:SI (match_dup 2) 0)))
(set (subreg:SI (match_dup 0) 1)
(subreg:SI (match_dup 2) 1)))
(set (match_dup 3)
- (ltu:CC (subreg:SI (match_dup 0) 1)
+ (ltu:SI (subreg:SI (match_dup 0) 1)
(subreg:SI (match_dup 2) 1)))
(set (subreg:SI (match_dup 0) 0)
(match_dup 2)))
(set (match_dup 3)
- (ltu:CC (subreg:SI (match_dup 0) 0)
+ (ltu:SI (subreg:SI (match_dup 0) 0)
(match_dup 2)))
(set (subreg:SI (match_dup 0) 1)
(match_dup 2)))
(set (match_dup 3)
- (ltu:CC (subreg:SI (match_dup 0) 1)
+ (ltu:SI (subreg:SI (match_dup 0) 1)
(match_dup 2)))
(set (subreg:SI (match_dup 0) 0)
&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
[(set (match_dup 3)
- (ltu:CC (subreg:SI (match_dup 1) 0)
+ (ltu:SI (subreg:SI (match_dup 1) 0)
(subreg:SI (match_dup 2) 0)))
(set (subreg:SI (match_dup 0) 0)
&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
[(set (match_dup 3)
- (ltu:CC (subreg:SI (match_dup 1) 1)
+ (ltu:SI (subreg:SI (match_dup 1) 1)
(subreg:SI (match_dup 2) 1)))
(set (subreg:SI (match_dup 0) 1)
&& INTVAL (operands[2]) > 0"
[(set (match_dup 3)
- (ltu:CC (subreg:SI (match_dup 1) 0)
+ (ltu:SI (subreg:SI (match_dup 1) 0)
(match_dup 2)))
(set (subreg:SI (match_dup 0) 0)
&& INTVAL (operands[2]) > 0"
[(set (match_dup 3)
- (ltu:CC (subreg:SI (match_dup 1) 1)
+ (ltu:SI (subreg:SI (match_dup 1) 1)
(match_dup 2)))
(set (subreg:SI (match_dup 0) 1)
(match_dup 2)))
(clobber (reg:SI 64))
(clobber (reg:SI 65))]
- "optimize && !TARGET_DEBUG_C_MODE"
+ "optimize"
"*
{
if (find_reg_note (insn, REG_UNUSED, operands[3]))
(match_dup 2)))
(clobber (reg:SI 64))
(clobber (reg:SI 65))]
- "optimize && !TARGET_DEBUG_C_MODE"
+ "optimize"
"*
{
if (find_reg_note (insn, REG_UNUSED, operands[3]))
(match_operand:SI 2 "register_operand" "d")))
(clobber (reg:SI 64))
(clobber (reg:SI 65))]
- "!optimize || TARGET_DEBUG_C_MODE"
+ "!optimize"
"div\\t%0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")
(match_operand:SI 2 "register_operand" "d")))
(clobber (reg:SI 64))
(clobber (reg:SI 65))]
- "!optimize || TARGET_DEBUG_C_MODE"
+ "!optimize"
"rem\\t%0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")
(match_operand:SI 2 "register_operand" "d")))
(clobber (reg:SI 64))
(clobber (reg:SI 65))]
- "!optimize || TARGET_DEBUG_C_MODE"
+ "!optimize"
"divu\\t%0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")
(match_operand:SI 2 "register_operand" "d")))
(clobber (reg:SI 64))
(clobber (reg:SI 65))]
- "!optimize || TARGET_DEBUG_C_MODE"
+ "!optimize"
"remu\\t%0,%1,%2"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")
;; done, so that we can constrain things appropriately. There
;; are assumptions in the rest of GCC that break if we fold the
;; operands into the branchs for integer operations, and use cc0
-;; for floating point.
-;;
-;; 3) The compare define_insns then once again set branch_cmp and
-;; branch_type, and the branch define_insns use them.
-;;
-;; 4) If a set condition code is done instead of a branch, then the
-;; operands are folded into the RTL, and a separate set of cc0 is
-;; not done. This allows slt's to be put into delay slots.
+;; for floating point, so we use the fp status register instead.
+;; If needed, an appropriate temporary is created to hold the
+;; of the integer compare.
(define_expand "cmpsi"
[(set (cc0)
}
}")
-(define_insn "cmpsi_eqne"
- [(set (cc0)
- (compare:CC_EQ (match_operand:SI 0 "register_operand" "dJ")
- (match_operand:SI 1 "reg_or_0_operand" "dJ")))]
- ""
- "*
-{
- branch_cmp[0] = operands[0];
- branch_cmp[1] = operands[1];
- branch_type = CMP_SI;
- return \"\";
-}"
- [(set_attr "type" "icmp")
- (set_attr "mode" "none")
- (set_attr "length" "0")])
-
-(define_insn "cmpsi_zero"
- [(set (cc0)
- (match_operand:SI 0 "reg_or_0_operand" "dJ"))]
- ""
- "*
-{
- branch_cmp[0] = operands[0];
- branch_cmp[1] = const0_rtx;
- branch_type = CMP_SI;
- return \"\";
-}"
- [(set_attr "type" "icmp")
- (set_attr "mode" "none")
- (set_attr "length" "0")])
-
-(define_insn "cmpsi_relational"
- [(set (cc0)
- (compare:CC (match_operand:SI 0 "register_operand" "dJ")
- (match_operand:SI 1 "arith_operand" "dI")))]
- ""
- "*
-{
- branch_cmp[0] = operands[0];
- branch_cmp[1] = operands[1];
- branch_type = CMP_SI;
- return \"\";
-}"
- [(set_attr "type" "icmp")
- (set_attr "mode" "none")
- (set_attr "length" "0")])
-
(define_expand "cmpdf"
[(set (cc0)
(compare:CC_FP (match_operand:DF 0 "register_operand" "")
}
}")
-(define_insn "cmpdf_internal"
- [(set (cc0)
- (compare:CC_FP (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "register_operand" "f")))]
- "TARGET_HARD_FLOAT"
- "*
-{
- branch_cmp[0] = operands[0];
- branch_cmp[1] = operands[1];
- branch_type = CMP_DF;
- return \"\";
-}"
- [(set_attr "type" "fcmp")
- (set_attr "mode" "none")
- (set_attr "length" "0")])
-
-
(define_expand "cmpsf"
[(set (cc0)
(compare:CC_FP (match_operand:SF 0 "register_operand" "")
}
}")
-(define_insn "cmpsf_internal"
- [(set (cc0)
- (compare:CC_FP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
- "TARGET_HARD_FLOAT"
- "*
-{
- branch_cmp[0] = operands[0];
- branch_cmp[1] = operands[1];
- branch_type = CMP_SF;
- return \"\";
-}"
- [(set_attr "type" "fcmp")
- (set_attr "mode" "none")
- (set_attr "length" "0")])
-
\f
;;
;; ....................
;;
;; ....................
-;; We really can't note that integer branches clobber $at, and FP
-;; branches clobber $fcr31 because if we use a parallel operation, a
-;; normal insn is used to hold the value instead of jump_insn. See
-;; above for cmpxx saving the operands in branch_cmp and branch_type.
-
-(define_insn "branch_fp_true"
+(define_insn "branch_fp_ne"
[(set (pc)
- (if_then_else (match_operator:CC_FP 0 "fcmp_op" [(cc0) (const_int 0)])
- (label_ref (match_operand 1 "" ""))
- (pc)))]
+ (if_then_else (ne:CC_FP (reg:CC_FP 66)
+ (const_int 0))
+ (match_operand 0 "pc_or_label_operand" "")
+ (match_operand 1 "pc_or_label_operand" "")))]
""
"*
{
- operands[2] = branch_cmp[0];
- operands[3] = branch_cmp[1];
-
mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- if (branch_type == CMP_DF)
- {
- switch (GET_CODE (operands[0]))
- {
- case EQ: return \"c.eq.d\\t%2,%3%#\;%*bc1t%?\\t%l1\";
- case NE: return \"c.eq.d\\t%2,%3%#\;%*bc1f%?\\t%l1\";
- case LT: return \"c.lt.d\\t%2,%3%#\;%*bc1t%?\\t%l1\";
- case LE: return \"c.le.d\\t%2,%3%#\;%*bc1t%?\\t%l1\";
- case GT: return \"c.lt.d\\t%3,%2%#\;%*bc1t%?\\t%l1\";
- case GE: return \"c.le.d\\t%3,%2%#\;%*bc1t%?\\t%l1\";
- }
- }
-
- else if (branch_type == CMP_SF)
- {
- switch (GET_CODE (operands[0]))
- {
- case EQ: return \"c.eq.s\\t%2,%3%#\;%*bc1t%?\\t%l1\";
- case NE: return \"c.eq.s\\t%2,%3%#\;%*bc1f%?\\t%l1\";
- case LT: return \"c.lt.s\\t%2,%3%#\;%*bc1t%?\\t%l1\";
- case LE: return \"c.le.s\\t%2,%3%#\;%*bc1t%?\\t%l1\";
- case GT: return \"c.lt.s\\t%3,%2%#\;%*bc1t%?\\t%l1\";
- case GE: return \"c.le.s\\t%3,%2%#\;%*bc1t%?\\t%l1\";
- }
- }
-
- abort_with_insn (insn, \"Bad floating compare/branch\");
- return (char *)0;
+ return (operands[0] != pc_rtx) ? \"%*bc1t%?\\t%0\" : \"%*bc1f%?\\t%1\";
}"
[(set_attr "type" "branch")
(set_attr "mode" "none")
- (set_attr "length" "3")])
+ (set_attr "length" "1")])
-(define_insn "branch_fp_false"
+(define_insn "branch_fp_ne_rev"
[(set (pc)
- (if_then_else (match_operator:CC_FP 0 "fcmp_op" [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 1 "" ""))))]
+ (if_then_else (ne:CC_REV_FP (reg:CC_REV_FP 66)
+ (const_int 0))
+ (match_operand 0 "pc_or_label_operand" "")
+ (match_operand 1 "pc_or_label_operand" "")))]
""
"*
{
- operands[2] = branch_cmp[0];
- operands[3] = branch_cmp[1];
-
mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- if (branch_type == CMP_DF)
- {
- switch (GET_CODE (operands[0]))
- {
- case EQ: return \"c.eq.d\\t%2,%3%#\;%*bc1f%?\\t%l1\";
- case NE: return \"c.eq.d\\t%2,%3%#\;%*bc1t%?\\t%l1\";
- case LT: return \"c.lt.d\\t%2,%3%#\;%*bc1f%?\\t%l1\";
- case LE: return \"c.le.d\\t%2,%3%#\;%*bc1f%?\\t%l1\";
- case GT: return \"c.lt.d\\t%3,%2%#\;%*bc1f%?\\t%l1\";
- case GE: return \"c.le.d\\t%3,%2%#\;%*bc1f%?\\t%l1\";
- }
- }
-
- else if (branch_type == CMP_SF)
- {
- switch (GET_CODE (operands[0]))
- {
- case EQ: return \"c.eq.s\\t%2,%3%#\;%*bc1f%?\\t%l1\";
- case NE: return \"c.eq.s\\t%2,%3%#\;%*bc1t%?\\t%l1\";
- case LT: return \"c.lt.s\\t%2,%3%#\;%*bc1f%?\\t%l1\";
- case LE: return \"c.le.s\\t%2,%3%#\;%*bc1f%?\\t%l1\";
- case GT: return \"c.lt.s\\t%3,%2%#\;%*bc1f%?\\t%l1\";
- case GE: return \"c.le.s\\t%3,%2%#\;%*bc1f%?\\t%l1\";
- }
- }
-
- abort_with_insn (insn, \"Bad floating compare/branch\");
- return (char *)0;
+ return (operands[0] != pc_rtx) ? \"%*bc1f%?\\t%0\" : \"%*bc1t%?\\t%1\";
}"
[(set_attr "type" "branch")
(set_attr "mode" "none")
- (set_attr "length" "3")])
-
+ (set_attr "length" "1")])
-(define_insn "branch_eqne_true"
+(define_insn "branch_fp_eq"
[(set (pc)
- (if_then_else (match_operator:CC_EQ 0 "equality_op" [(cc0) (const_int 0)])
- (label_ref (match_operand 1 "" ""))
- (pc)))]
+ (if_then_else (eq:CC_FP (reg:CC_FP 66)
+ (const_int 0))
+ (match_operand 0 "pc_or_label_operand" "")
+ (match_operand 1 "pc_or_label_operand" "")))]
""
"*
{
mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- operands[2] = branch_cmp[0];
- operands[3] = branch_cmp[1];
- return \"%*b%C0%?\\t%z2,%z3,%1\";
+ return (operands[0] != pc_rtx) ? \"%*bc1f%?\\t%0\" : \"%*bc1t%?\\t%1\";
}"
[(set_attr "type" "branch")
(set_attr "mode" "none")
(set_attr "length" "1")])
-(define_insn "branch_eqne_false"
+(define_insn "branch_fp_eq_rev"
[(set (pc)
- (if_then_else (match_operator:CC_EQ 0 "equality_op" [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 1 "" ""))))]
+ (if_then_else (eq:CC_REV_FP (reg:CC_REV_FP 66)
+ (const_int 0))
+ (match_operand 0 "pc_or_label_operand" "")
+ (match_operand 1 "pc_or_label_operand" "")))]
""
"*
{
mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- operands[2] = branch_cmp[0];
- operands[3] = branch_cmp[1];
- return \"%*b%N0%?\\t%z2,%z3,%1\";
+ return (operands[0] != pc_rtx) ? \"%*bc1t%?\\t%0\" : \"%*bc1f%?\\t%1\";
}"
[(set_attr "type" "branch")
(set_attr "mode" "none")
(set_attr "length" "1")])
-(define_insn "branch_zero_true"
+
+(define_insn "branch_zero"
[(set (pc)
- (if_then_else (match_operator:CC_0 0 "cmp_op" [(cc0) (const_int 0)])
- (label_ref (match_operand 1 "" ""))
- (pc)))]
+ (if_then_else (match_operator:SI 0 "cmp_op"
+ [(match_operand:SI 1 "arith32_operand" "rn")
+ (const_int 0)])
+ (match_operand 2 "pc_or_label_operand" "")
+ (match_operand 3 "pc_or_label_operand" "")))]
""
"*
{
mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- operands[2] = branch_cmp[0];
- switch (GET_CODE (operands[0]))
+ /* Handle places where CSE has folded a constant into the register operand. */
+ if (GET_CODE (operands[1]) == CONST_INT)
{
- case EQ: return \"%*beq%?\\t%z2,%.,%1\";
- case NE: return \"%*bne%?\\t%z2,%.,%1\";
- case GTU: return \"%*bne%?\\t%z2,%.,%1\";
- case LEU: return \"%*beq%?\\t%z2,%.,%1\";
- case GEU: return \"%*j\\t%1\";
- case LTU: return \"#%*bltuz\\t%z2,%1\";
+ int value = INTVAL (operands[1]);
+ int truth = 0;
+
+ switch (GET_CODE (operands[0]))
+ {
+ default: abort ();
+ case EQ: truth = (value == 0); break;
+ case NE: truth = (value != 0); break;
+ case GT: truth = (value > 0); break;
+ case GE: truth = (value >= 0); break;
+ case LT: truth = (value < 0); break;
+ case LE: truth = (value <= 0); break;
+ case GTU: truth = (((unsigned)value) > 0); break;
+ case GEU: truth = 1; break;
+ case LTU: truth = 0; break;
+ case LEU: truth = (((unsigned)value) <= 0); break;
+ }
+
+ if (operands[2] != pc_rtx)
+ return (truth) ? \"%*j\\t%2\" : \"#bne\\t%z1,%.,%2\";
+ else
+ return (truth) ? \"#bne\\t%z1,%.,%3\" : \"%*j\\t%3\";
}
- return \"%*b%C0z%?\\t%z2,%1\";
-}"
- [(set_attr "type" "branch")
- (set_attr "mode" "none")
- (set_attr "length" "1")])
+ if (operands[2] != pc_rtx)
+ { /* normal jump */
+ switch (GET_CODE (operands[0]))
+ {
+ case EQ: return \"%*beq%?\\t%z1,%.,%2\";
+ case NE: return \"%*bne%?\\t%z1,%.,%2\";
+ case GTU: return \"%*bne%?\\t%z1,%.,%2\";
+ case LEU: return \"%*beq%?\\t%z1,%.,%2\";
+ case GEU: return \"%*j\\t%2\";
+ case LTU: return \"#%*bltuz\\t%z1,%2\";
+ }
-(define_insn "branch_zero_false"
- [(set (pc)
- (if_then_else (match_operator:CC_0 0 "cmp_op" [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 1 "" ""))))]
- ""
- "*
-{
- mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- operands[2] = branch_cmp[0];
- switch (GET_CODE (operands[0]))
- {
- case EQ: return \"%*bne%?\\t%z2,%.,%1\";
- case NE: return \"%*beq%?\\t%z2,%.,%1\";
- case GTU: return \"%*beq%?\\t%z2,%.,%1\";
- case LEU: return \"%*bne\\t%z2,%.,%1\";
- case GEU: return \"#%*bgeuz\\t%z2,%1\";
- case LTU: return \"%*j\\t%1\";
+ return \"%*b%C0z%?\\t%z1,%2\";
}
+ else
+ { /* inverted jump */
+ switch (GET_CODE (operands[0]))
+ {
+ case EQ: return \"%*bne%?\\t%z1,%.,%3\";
+ case NE: return \"%*beq%?\\t%z1,%.,%3\";
+ case GTU: return \"%*beq%?\\t%z1,%.,%3\";
+ case LEU: return \"%*bne%?\\t%z1,%.,%3\";
+ case GEU: return \"#%*bgeuz\\t%z1,%3\";
+ case LTU: return \"%*j\\t%3\";
+ }
- return \"%*b%N0z%?\\t%z2,%1\";
+ return \"%*b%N0z%?\\t%z1,%3\";
+ }
}"
[(set_attr "type" "branch")
(set_attr "mode" "none")
(set_attr "length" "1")])
-(define_insn "branch_relop_true"
- [(set (pc)
- (if_then_else (match_operator:CC 0 "cmp2_op" [(cc0) (const_int 0)])
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- ""
- "*
-{
- mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- operands[2] = branch_cmp[0];
- operands[3] = branch_cmp[1];
-
- return \"%&b%C0%?\\t%z2,%z3,%1%!\";
-}"
- [(set_attr "type" "branch")
- (set_attr "mode" "none")
- (set_attr "length" "2")])
-(define_insn "branch_relop_false"
+(define_insn "branch_equality"
[(set (pc)
- (if_then_else (match_operator:CC 0 "cmp2_op" [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 1 "" ""))))]
+ (if_then_else (match_operator:SI 0 "equality_op"
+ [(match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")])
+ (match_operand 3 "pc_or_label_operand" "")
+ (match_operand 4 "pc_or_label_operand" "")))]
""
"*
{
mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- operands[2] = branch_cmp[0];
- operands[3] = branch_cmp[1];
-
- return \"%&b%N0%?\\t%z2,%z3,%1%!\";
+ return (operands[3] != pc_rtx)
+ ? \"%*b%C0%?\\t%z1,%z2,%3\"
+ : \"%*b%N0%?\\t%z1,%z2,%4\";
}"
[(set_attr "type" "branch")
(set_attr "mode" "none")
- (set_attr "length" "2")])
+ (set_attr "length" "1")])
+
(define_expand "beq"
[(set (pc)
(define_expand "seq"
[(set (match_operand:SI 0 "register_operand" "=d")
- (eq:CC_EQ (match_dup 1)
- (match_dup 2)))]
+ (eq:SI (match_dup 1)
+ (match_dup 2)))]
""
"
{
operands[1] = branch_cmp[0];
operands[2] = branch_cmp[1];
+ if (TARGET_DEBUG_C_MODE)
+ {
+ gen_int_relational (EQ, operands[0], operands[1], operands[2], (int *)0);
+ DONE;
+ }
+
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
operands[2] = force_reg (SImode, operands[2]);
/* fall through and generate default code */
}")
-(define_insn "seq_si"
- [(set (match_operand:SI 0 "register_operand" "=d,d,d")
- (eq:CC_EQ (match_operand:SI 1 "register_operand" "%d,d,d")
- (match_operand:SI 2 "uns_arith_operand" "J,d,K")))]
+
+(define_insn "seq_si_zero"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (eq:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 0)))]
""
+ "sltu\\t%0,%1,1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "1")])
+
+(define_insn "seq_si"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (eq:SI (match_operand:SI 1 "register_operand" "%d,d")
+ (match_operand:SI 2 "uns_arith_operand" "d,K")))]
+ "!TARGET_DEBUG_C_MODE"
"@
- sltu\\t%0,%1,1
xor\\t%0,%1,%2\;sltu\\t%0,%0,1
- xori\\t%0,%1,%x2\;sltu\\t%0,%0,1"
- [(set_attr "type" "arith,arith,arith")
- (set_attr "mode" "SI,SI,SI")
- (set_attr "length" "1,2,2")])
+ xori\\t%0,%1,%2\;sltu\\t%0,%0,1"
+ [(set_attr "type" "arith,arith")
+ (set_attr "mode" "SI,SI")
+ (set_attr "length" "2,2")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
- (eq:CC_EQ (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "uns_arith_operand" "")))]
- "!TARGET_DEBUG_D_MODE
+ (eq:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "uns_arith_operand" "")))]
+ "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE
&& (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)"
[(set (match_dup 0)
(xor:SI (match_dup 1)
(match_dup 2)))
(set (match_dup 0)
- (ltu:CC (match_dup 0)
+ (ltu:SI (match_dup 0)
(const_int 1)))]
"")
(define_expand "sne"
[(set (match_operand:SI 0 "register_operand" "=d")
- (ne:CC_EQ (match_dup 1)
- (match_dup 2)))]
+ (ne:SI (match_dup 1)
+ (match_dup 2)))]
""
"
{
operands[1] = branch_cmp[0];
operands[2] = branch_cmp[1];
+ if (TARGET_DEBUG_C_MODE)
+ {
+ gen_int_relational (NE, operands[0], operands[1], operands[2], (int *)0);
+ DONE;
+ }
+
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
operands[2] = force_reg (SImode, operands[2]);
/* fall through and generate default code */
}")
-(define_insn "sne_si"
- [(set (match_operand:SI 0 "register_operand" "=d,d,d")
- (ne:CC_EQ (match_operand:SI 1 "register_operand" "%d,d,d")
- (match_operand:SI 2 "uns_arith_operand" "J,d,K")))]
+(define_insn "sne_si_zero"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ne:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 0)))]
""
- "*
-{
- if (GET_CODE (operands[2]) != CONST_INT)
- return \"xor\\t%0,%1,%2\;sltu\\t%0,%.,%0\";
-
- if (INTVAL (operands[2]) == 0)
- return \"sltu\\t%0,%.,%1\";
+ "sltu\\t%0,%.,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "1")])
- return \"xori\\t%0,%1,%x2\;sltu\\t%0,%.,%0\";
-}"
- [(set_attr "type" "arith,arith,arith")
- (set_attr "mode" "SI,SI,SI")
- (set_attr "length" "1,2,2")])
+(define_insn "sne_si"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (ne:SI (match_operand:SI 1 "register_operand" "%d,d")
+ (match_operand:SI 2 "uns_arith_operand" "d,K")))]
+ "!TARGET_DEBUG_C_MODE"
+ "@
+ xor\\t%0,%1,%2\;sltu\\t%0,%.,%0
+ xori\\t%0,%1,%x2\;sltu\\t%0,%.,%0"
+ [(set_attr "type" "arith,arith")
+ (set_attr "mode" "SI,SI")
+ (set_attr "length" "2,2")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
- (ne:CC_EQ (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "uns_arith_operand" "")))]
- "!TARGET_DEBUG_D_MODE
+ (ne:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "uns_arith_operand" "")))]
+ "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE
&& (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)"
[(set (match_dup 0)
(xor:SI (match_dup 1)
(match_dup 2)))
(set (match_dup 0)
- (gtu:CC (match_dup 0)
+ (gtu:SI (match_dup 0)
(const_int 0)))]
"")
(define_expand "sgt"
[(set (match_operand:SI 0 "register_operand" "=d")
- (gt:CC (match_dup 1)
+ (gt:SI (match_dup 1)
(match_dup 2)))]
""
"
operands[1] = branch_cmp[0];
operands[2] = branch_cmp[1];
+ if (TARGET_DEBUG_C_MODE)
+ {
+ gen_int_relational (GT, operands[0], operands[1], operands[2], (int *)0);
+ DONE;
+ }
+
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
operands[2] = force_reg (SImode, operands[2]);
(define_insn "sgt_si"
[(set (match_operand:SI 0 "register_operand" "=d")
- (gt:CC (match_operand:SI 1 "register_operand" "d")
+ (gt:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "reg_or_0_operand" "dJ")))]
""
"slt\\t%0,%z2,%1"
(define_expand "sge"
[(set (match_operand:SI 0 "register_operand" "=d")
- (ge:CC (match_dup 1)
+ (ge:SI (match_dup 1)
(match_dup 2)))]
""
"
operands[1] = branch_cmp[0];
operands[2] = branch_cmp[1];
+ if (TARGET_DEBUG_C_MODE)
+ {
+ gen_int_relational (GE, operands[0], operands[1], operands[2], (int *)0);
+ DONE;
+ }
+
/* fall through and generate default code */
}")
(define_insn "sge_si"
[(set (match_operand:SI 0 "register_operand" "=d")
- (ge:CC (match_operand:SI 1 "register_operand" "d")
+ (ge:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "arith_operand" "dI")))]
- ""
+ "!TARGET_DEBUG_C_MODE"
"slt\\t%0,%1,%2\;xori\\t%0,%0,0x0001"
[(set_attr "type" "arith")
(set_attr "mode" "SI")
(define_split
[(set (match_operand:SI 0 "register_operand" "")
- (ge:CC (match_operand:SI 1 "register_operand" "")
+ (ge:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "arith_operand" "")))]
- "!TARGET_DEBUG_D_MODE"
+ "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE"
[(set (match_dup 0)
- (lt:CC (match_dup 1)
+ (lt:SI (match_dup 1)
(match_dup 2)))
(set (match_dup 0)
(xor:SI (match_dup 0)
(define_expand "slt"
[(set (match_operand:SI 0 "register_operand" "=d")
- (lt:CC (match_dup 1)
+ (lt:SI (match_dup 1)
(match_dup 2)))]
""
"
operands[1] = branch_cmp[0];
operands[2] = branch_cmp[1];
+ if (TARGET_DEBUG_C_MODE)
+ {
+ gen_int_relational (LT, operands[0], operands[1], operands[2], (int *)0);
+ DONE;
+ }
+
/* fall through and generate default code */
}")
(define_insn "slt_si"
[(set (match_operand:SI 0 "register_operand" "=d")
- (lt:CC (match_operand:SI 1 "register_operand" "d")
+ (lt:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "arith_operand" "dI")))]
""
"slt\\t%0,%1,%2"
(define_expand "sle"
[(set (match_operand:SI 0 "register_operand" "=d")
- (le:CC (match_dup 1)
+ (le:SI (match_dup 1)
(match_dup 2)))]
""
"
operands[1] = branch_cmp[0];
operands[2] = branch_cmp[1];
+ if (TARGET_DEBUG_C_MODE)
+ {
+ gen_int_relational (LE, operands[0], operands[1], operands[2], (int *)0);
+ DONE;
+ }
+
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767)
operands[2] = force_reg (SImode, operands[2]);
/* fall through and generate default code */
}")
-(define_insn "sle_si"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (le:CC (match_operand:SI 1 "register_operand" "d,d")
- (match_operand:SI 2 "arith_operand" "d,I")))]
- "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) < 32767"
- "@
- slt\\t%0,%z2,%1\;xori\\t%0,%0,0x0001
- slt\\t%0,%1,(%2+1)"
- [(set_attr "type" "arith,arith")
- (set_attr "mode" "SI,SI")
- (set_attr "length" "2,1")])
+(define_insn "sle_si_const"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (le:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "small_int" "I")))]
+ "INTVAL (operands[2]) < 32767"
+ "*
+{
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2])+1);
+ return \"slt\\t%0,%1,%2\";
+}"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "1")])
+
+(define_insn "sle_si_reg"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (le:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))]
+ "!TARGET_DEBUG_C_MODE"
+ "slt\\t%0,%z2,%1\;xori\\t%0,%0,0x0001"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "2")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
- (le:CC (match_operand:SI 1 "register_operand" "")
+ (le:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "register_operand" "")))]
- "!TARGET_DEBUG_D_MODE"
+ "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE"
[(set (match_dup 0)
- (lt:CC (match_dup 2)
+ (lt:SI (match_dup 2)
(match_dup 1)))
(set (match_dup 0)
(xor:SI (match_dup 0)
(define_expand "sgtu"
[(set (match_operand:SI 0 "register_operand" "=d")
- (gtu:CC (match_dup 1)
+ (gtu:SI (match_dup 1)
(match_dup 2)))]
""
"
operands[1] = branch_cmp[0];
operands[2] = branch_cmp[1];
+ if (TARGET_DEBUG_C_MODE)
+ {
+ gen_int_relational (GTU, operands[0], operands[1], operands[2], (int *)0);
+ DONE;
+ }
+
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
operands[2] = force_reg (SImode, operands[2]);
(define_insn "sgtu_si"
[(set (match_operand:SI 0 "register_operand" "=d")
- (gtu:CC (match_operand:SI 1 "register_operand" "d")
+ (gtu:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "reg_or_0_operand" "dJ")))]
""
"sltu\\t%0,%z2,%1"
(define_expand "sgeu"
[(set (match_operand:SI 0 "register_operand" "=d")
- (geu:CC (match_dup 1)
+ (geu:SI (match_dup 1)
(match_dup 2)))]
""
"
operands[1] = branch_cmp[0];
operands[2] = branch_cmp[1];
+ if (TARGET_DEBUG_C_MODE)
+ {
+ gen_int_relational (GEU, operands[0], operands[1], operands[2], (int *)0);
+ DONE;
+ }
+
/* fall through and generate default code */
}")
(define_insn "sgeu_si"
[(set (match_operand:SI 0 "register_operand" "=d")
- (geu:CC (match_operand:SI 1 "register_operand" "d")
+ (geu:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "arith_operand" "dI")))]
- ""
+ "!TARGET_DEBUG_C_MODE"
"sltu\\t%0,%1,%2\;xori\\t%0,%0,0x0001"
[(set_attr "type" "arith")
(set_attr "mode" "SI")
(define_split
[(set (match_operand:SI 0 "register_operand" "")
- (geu:CC (match_operand:SI 1 "register_operand" "")
+ (geu:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "arith_operand" "")))]
- "!TARGET_DEBUG_D_MODE"
+ "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE"
[(set (match_dup 0)
- (ltu:CC (match_dup 1)
+ (ltu:SI (match_dup 1)
(match_dup 2)))
(set (match_dup 0)
(xor:SI (match_dup 0)
(define_expand "sltu"
[(set (match_operand:SI 0 "register_operand" "=d")
- (ltu:CC (match_dup 1)
+ (ltu:SI (match_dup 1)
(match_dup 2)))]
""
"
operands[1] = branch_cmp[0];
operands[2] = branch_cmp[1];
+ if (TARGET_DEBUG_C_MODE)
+ {
+ gen_int_relational (LTU, operands[0], operands[1], operands[2], (int *)0);
+ DONE;
+ }
+
/* fall through and generate default code */
}")
(define_insn "sltu_si"
[(set (match_operand:SI 0 "register_operand" "=d")
- (ltu:CC (match_operand:SI 1 "register_operand" "d")
+ (ltu:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "arith_operand" "dI")))]
""
"sltu\\t%0,%1,%2"
(define_expand "sleu"
[(set (match_operand:SI 0 "register_operand" "=d")
- (leu:CC (match_dup 1)
+ (leu:SI (match_dup 1)
(match_dup 2)))]
""
"
operands[1] = branch_cmp[0];
operands[2] = branch_cmp[1];
+ if (TARGET_DEBUG_C_MODE)
+ {
+ gen_int_relational (LEU, operands[0], operands[1], operands[2], (int *)0);
+ DONE;
+ }
+
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767)
operands[2] = force_reg (SImode, operands[2]);
/* fall through and generate default code */
}")
-(define_insn "sleu_si"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (leu:CC (match_operand:SI 1 "register_operand" "d,d")
- (match_operand:SI 2 "arith_operand" "d,I")))]
- "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) < 32767"
- "@
- sltu\\t%0,%z2,%1\;xori\\t%0,%0,0x0001
- sltu\\t%0,%1,(%2+1)"
- [(set_attr "type" "arith,arith")
- (set_attr "mode" "SI,SI")
- (set_attr "length" "2,1")])
+(define_insn "sleu_si_const"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (leu:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "small_int" "I")))]
+ "INTVAL (operands[2]) < 32767"
+ "*
+{
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2])+1);
+ return \"sltu\\t%0,%1,%2\";
+}"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "1")])
+
+(define_insn "sleu_si_reg"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (leu:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))]
+ "!TARGET_DEBUG_C_MODE"
+ "sltu\\t%0,%z2,%1\;xori\\t%0,%0,0x0001"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "2")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
- (leu:CC (match_operand:SI 1 "register_operand" "")
+ (leu:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "register_operand" "")))]
- "!TARGET_DEBUG_D_MODE"
+ "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE"
[(set (match_dup 0)
- (ltu:CC (match_dup 2)
+ (ltu:SI (match_dup 2)
(match_dup 1)))
(set (match_dup 0)
(xor:SI (match_dup 0)
(const_int 1)))]
"")
+\f
+;;
+;; ....................
+;;
+;; FLOATING POINT COMPARISONS
+;;
+;; ....................
+
+(define_insn "seq_df"
+ [(set (reg:CC_FP 66)
+ (eq:CC_FP (match_operand:DF 0 "register_operand" "f")
+ (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ rtx xoperands[10];
+ xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+ xoperands[1] = operands[0];
+ xoperands[2] = operands[1];
+
+ return mips_fill_delay_slot (\"c.eq.d\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")
+ (set_attr "length" "1")])
+
+(define_insn "sne_df"
+ [(set (reg:CC_REV_FP 66)
+ (ne:CC_REV_FP (match_operand:DF 0 "register_operand" "f")
+ (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ rtx xoperands[10];
+ xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+ xoperands[1] = operands[0];
+ xoperands[2] = operands[1];
+
+ return mips_fill_delay_slot (\"c.eq.d\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")
+ (set_attr "length" "1")])
+
+(define_insn "slt_df"
+ [(set (reg:CC_FP 66)
+ (lt:CC_FP (match_operand:DF 0 "register_operand" "f")
+ (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ rtx xoperands[10];
+ xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+ xoperands[1] = operands[0];
+ xoperands[2] = operands[1];
+
+ return mips_fill_delay_slot (\"c.lt.d\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")
+ (set_attr "length" "1")])
+
+(define_insn "sle_df"
+ [(set (reg:CC_FP 66)
+ (le:CC_FP (match_operand:DF 0 "register_operand" "f")
+ (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ rtx xoperands[10];
+ xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+ xoperands[1] = operands[0];
+ xoperands[2] = operands[1];
+
+ return mips_fill_delay_slot (\"c.le.d\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")
+ (set_attr "length" "1")])
+
+(define_insn "sgt_df"
+ [(set (reg:CC_FP 66)
+ (gt:CC_FP (match_operand:DF 0 "register_operand" "f")
+ (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ rtx xoperands[10];
+ xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+ xoperands[1] = operands[0];
+ xoperands[2] = operands[1];
+
+ return mips_fill_delay_slot (\"c.lt.d\\t%1,%0\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")
+ (set_attr "length" "1")])
+
+(define_insn "sge_df"
+ [(set (reg:CC_FP 66)
+ (ge:CC_FP (match_operand:DF 0 "register_operand" "f")
+ (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ rtx xoperands[10];
+ xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+ xoperands[1] = operands[0];
+ xoperands[2] = operands[1];
+
+ return mips_fill_delay_slot (\"c.le.d\\t%1,%0\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")
+ (set_attr "length" "1")])
+
+(define_insn "seq_sf"
+ [(set (reg:CC_FP 66)
+ (eq:CC_FP (match_operand:SF 0 "register_operand" "f")
+ (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ rtx xoperands[10];
+ xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+ xoperands[1] = operands[0];
+ xoperands[2] = operands[1];
+
+ return mips_fill_delay_slot (\"c.eq.s\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")
+ (set_attr "length" "1")])
+
+(define_insn "sne_sf"
+ [(set (reg:CC_REV_FP 66)
+ (ne:CC_REV_FP (match_operand:SF 0 "register_operand" "f")
+ (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ rtx xoperands[10];
+ xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+ xoperands[1] = operands[0];
+ xoperands[2] = operands[1];
+
+ return mips_fill_delay_slot (\"c.eq.s\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")
+ (set_attr "length" "1")])
+
+(define_insn "slt_sf"
+ [(set (reg:CC_FP 66)
+ (lt:CC_FP (match_operand:SF 0 "register_operand" "f")
+ (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ rtx xoperands[10];
+ xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+ xoperands[1] = operands[0];
+ xoperands[2] = operands[1];
+
+ return mips_fill_delay_slot (\"c.lt.s\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")
+ (set_attr "length" "1")])
+
+(define_insn "sle_sf"
+ [(set (reg:CC_FP 66)
+ (le:CC_FP (match_operand:SF 0 "register_operand" "f")
+ (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ rtx xoperands[10];
+ xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+ xoperands[1] = operands[0];
+ xoperands[2] = operands[1];
+
+ return mips_fill_delay_slot (\"c.le.s\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")
+ (set_attr "length" "1")])
+
+(define_insn "sgt_sf"
+ [(set (reg:CC_FP 66)
+ (gt:CC_FP (match_operand:SF 0 "register_operand" "f")
+ (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ rtx xoperands[10];
+ xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+ xoperands[1] = operands[0];
+ xoperands[2] = operands[1];
+
+ return mips_fill_delay_slot (\"c.lt.s\\t%1,%0\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")
+ (set_attr "length" "1")])
+
+(define_insn "sge_sf"
+ [(set (reg:CC_FP 66)
+ (ge:CC_FP (match_operand:SF 0 "register_operand" "f")
+ (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ rtx xoperands[10];
+ xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
+ xoperands[1] = operands[0];
+ xoperands[2] = operands[1];
+
+ return mips_fill_delay_slot (\"c.le.s\\t%1,%0\", DELAY_FCMP, xoperands, insn);
+}"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")
+ (set_attr "length" "1")])
+
\f
;;
;; ....................