aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>1996-09-17 19:52:34 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>1996-09-17 19:52:34 +0000
commitb8eb88d06ff00efb00874dd8d3f30d8ed01551b1 (patch)
tree513d771457648fcfa66af5d6e22dc67cf5a065c0
parent24ba333f7b7cfcdfb6f07802b3bc3c28a46eac31 (diff)
downloadgcc-b8eb88d06ff00efb00874dd8d3f30d8ed01551b1.zip
gcc-b8eb88d06ff00efb00874dd8d3f30d8ed01551b1.tar.gz
gcc-b8eb88d06ff00efb00874dd8d3f30d8ed01551b1.tar.bz2
Finish MIPS4 support, add R5000 support.
From-SVN: r12732
-rw-r--r--gcc/config/mips/mips.c335
-rw-r--r--gcc/config/mips/mips.h111
-rw-r--r--gcc/config/mips/mips.md769
3 files changed, 746 insertions, 469 deletions
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 1bc47d4..f32117b9 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -256,7 +256,8 @@ char mips_reg_names[][8] =
"$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
"$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
- "hi", "lo", "accum","$fcr31","$rap"
+ "hi", "lo", "accum","$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",
+ "$fcc5","$fcc6","$fcc7","$rap"
};
/* Mips software names for the registers, used to overwrite the
@@ -272,7 +273,8 @@ char mips_sw_reg_names[][8] =
"$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
"$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
- "hi", "lo", "accum","$fcr31","$rap"
+ "hi", "lo", "accum","$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",
+ "$fcc5","$fcc6","$fcc7","$rap"
};
/* Map hard register number to register class */
@@ -295,7 +297,8 @@ enum reg_class mips_regno_to_class[] =
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
HI_REG, LO_REG, HILO_REG, ST_REGS,
- GR_REGS
+ ST_REGS, ST_REGS, ST_REGS, ST_REGS,
+ ST_REGS, ST_REGS, ST_REGS, GR_REGS
};
/* Map register constraint character to register class. */
@@ -524,6 +527,40 @@ mips_const_double_ok (op, mode)
return FALSE;
}
+/* Accept the floating point constant 1 in the appropriate mode. */
+
+int
+const_float_1_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ REAL_VALUE_TYPE d;
+ static REAL_VALUE_TYPE onedf;
+ static REAL_VALUE_TYPE onesf;
+ static int one_initialized;
+
+ if (GET_CODE (op) != CONST_DOUBLE
+ || mode != GET_MODE (op)
+ || (mode != DFmode && mode != SFmode))
+ return FALSE;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (d, op);
+
+ /* We only initialize these values if we need them, since we will
+ never get called unless mips_isa >= 4. */
+ if (! one_initialized)
+ {
+ onedf = REAL_VALUE_ATOF ("1.0", DFmode);
+ onesf = REAL_VALUE_ATOF ("1.0", SFmode);
+ one_initialized = TRUE;
+ }
+
+ if (mode == DFmode)
+ return REAL_VALUES_EQUAL (d, onedf);
+ else
+ return REAL_VALUES_EQUAL (d, onesf);
+}
+
/* Return truth value if a memory operand fits in a single instruction
(ie, register + small offset). */
@@ -990,6 +1027,10 @@ mips_move_1word (operands, insn, unsignedp)
code1 = GET_CODE (op1);
}
+ /* For our purposes, a condition code mode is the same as SImode. */
+ if (mode == CCmode)
+ mode = SImode;
+
if (code0 == REG)
{
int regno0 = REGNO (op0) + subreg_word0;
@@ -1017,13 +1058,16 @@ mips_move_1word (operands, insn, unsignedp)
ret = "mflo\t%0";
}
+ else if (ST_REG_P (regno1) && mips_isa >= 4)
+ ret = "li\t%0,1\n\tmovf\t%0,%.,%1";
+
else
{
delay = DELAY_LOAD;
if (FP_REG_P (regno1))
ret = "mfc1\t%0,%1";
- else if (regno1 == FPSW_REGNUM)
+ else if (regno1 == FPSW_REGNUM && mips_isa < 4)
ret = "cfc1\t%0,$31";
}
}
@@ -1050,7 +1094,7 @@ mips_move_1word (operands, insn, unsignedp)
}
}
- else if (regno0 == FPSW_REGNUM)
+ else if (regno0 == FPSW_REGNUM && mips_isa < 4)
{
if (GP_REG_P (regno1))
{
@@ -1079,6 +1123,7 @@ mips_move_1word (operands, insn, unsignedp)
ret = "lw\t%0,%1";
break;
case SImode:
+ case CCmode:
ret = ((unsignedp && TARGET_64BIT)
? "lwu\t%0,%1"
: "lw\t%0,%1");
@@ -1981,112 +2026,67 @@ gen_conditional_branch (operands, test_code)
rtx operands[];
enum rtx_code test_code;
{
- static enum machine_mode mode_map[(int)CMP_MAX][(int)ITEST_MAX] = {
- { /* CMP_SI */
- SImode, /* eq */
- SImode, /* ne */
- SImode, /* gt */
- SImode, /* ge */
- SImode, /* lt */
- SImode, /* le */
- SImode, /* gtu */
- SImode, /* geu */
- SImode, /* ltu */
- SImode, /* leu */
- },
- { /* CMP_DI */
- DImode, /* eq */
- DImode, /* ne */
- DImode, /* gt */
- DImode, /* ge */
- DImode, /* lt */
- DImode, /* le */
- DImode, /* gtu */
- DImode, /* geu */
- DImode, /* ltu */
- DImode, /* leu */
- },
- { /* CMP_SF */
- CC_FPmode, /* eq */
- CC_REV_FPmode, /* ne */
- CC_FPmode, /* gt */
- CC_FPmode, /* ge */
- CC_FPmode, /* lt */
- CC_FPmode, /* le */
- VOIDmode, /* gtu */
- VOIDmode, /* geu */
- VOIDmode, /* ltu */
- VOIDmode, /* leu */
- },
- { /* CMP_DF */
- CC_FPmode, /* eq */
- CC_REV_FPmode, /* ne */
- CC_FPmode, /* gt */
- CC_FPmode, /* ge */
- CC_FPmode, /* lt */
- CC_FPmode, /* le */
- VOIDmode, /* gtu */
- VOIDmode, /* geu */
- VOIDmode, /* ltu */
- VOIDmode, /* leu */
- },
- };
-
+ enum cmp_type type = branch_type;
+ rtx cmp0 = branch_cmp[0];
+ rtx cmp1 = branch_cmp[1];
enum machine_mode mode;
- 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)
- {
- mode = word_mode;
- goto fail;
- }
-
- /* 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;
+ rtx reg;
+ int invert;
+ rtx label1, label2;
switch (type)
{
default:
- goto fail;
+ abort_with_insn (gen_rtx (test_code, VOIDmode, cmp0, cmp1), "bad test");
case CMP_SI:
case CMP_DI:
- reg = gen_int_relational (test_code, (rtx)0, cmp0, cmp1, &invert);
- if (reg != (rtx)0)
+ mode = type == CMP_SI ? SImode : DImode;
+ invert = FALSE;
+ reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert);
+ if (reg)
{
cmp0 = reg;
cmp1 = const0_rtx;
test_code = NE;
}
-
- /* Make sure not non-zero constant if ==/!= */
else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
- cmp1 = force_reg (mode, cmp1);
-
+ {
+ /* We don't want to build a comparison against a non-zero
+ constant. */
+ cmp1 = force_reg (mode, cmp1);
+ }
break;
- case CMP_DF:
case CMP_SF:
- {
- 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;
- }
+ case CMP_DF:
+ if (mips_isa < 4)
+ reg = gen_rtx (REG, CCmode, FPSW_REGNUM);
+ else
+ reg = gen_reg_rtx (CCmode);
+
+ /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result ==
+ 0 in the instruction built below. The MIPS FPU handles
+ inequality testing by testing for equality and looking for a
+ false result. */
+ emit_insn (gen_rtx (SET, VOIDmode,
+ reg,
+ gen_rtx (test_code == NE ? EQ : test_code,
+ CCmode, cmp0, cmp1)));
+
+ test_code = test_code == NE ? EQ : NE;
+ mode = CCmode;
+ cmp0 = reg;
+ cmp1 = const0_rtx;
+ invert = FALSE;
break;
}
- /* Generate the jump */
+ /* Generate the branch. */
+
+ label1 = gen_rtx (LABEL_REF, VOIDmode, operands[0]);
+ label2 = pc_rtx;
+
if (invert)
{
label2 = label1;
@@ -2099,13 +2099,102 @@ gen_conditional_branch (operands, test_code)
gen_rtx (test_code, mode, cmp0, cmp1),
label1,
label2)));
+}
- return;
+/* Emit the common code for conditional moves. OPERANDS is the array
+ of operands passed to the conditional move defined_expand. */
-fail:
- abort_with_insn (gen_rtx (test_code, mode, cmp0, cmp1), "bad test");
-}
+void
+gen_conditional_move (operands)
+ rtx *operands;
+{
+ rtx op0 = branch_cmp[0];
+ rtx op1 = branch_cmp[1];
+ enum machine_mode mode = GET_MODE (branch_cmp[0]);
+ enum rtx_code cmp_code = GET_CODE (operands[1]);
+ enum rtx_code move_code = NE;
+ enum machine_mode op_mode = GET_MODE (operands[0]);
+ enum machine_mode cmp_mode;
+ rtx cmp_reg;
+
+ if (GET_MODE_CLASS (mode) != MODE_FLOAT)
+ {
+ switch (cmp_code)
+ {
+ case EQ:
+ cmp_code = XOR;
+ move_code = EQ;
+ break;
+ case NE:
+ cmp_code = XOR;
+ break;
+ case LT:
+ break;
+ case GE:
+ cmp_code = LT;
+ move_code = EQ;
+ break;
+ case GT:
+ cmp_code = LT;
+ op0 = force_reg (mode, branch_cmp[1]);
+ op1 = branch_cmp[0];
+ break;
+ case LE:
+ cmp_code = LT;
+ op0 = force_reg (mode, branch_cmp[1]);
+ op1 = branch_cmp[0];
+ move_code = EQ;
+ break;
+ case LTU:
+ break;
+ case GEU:
+ cmp_code = LTU;
+ move_code = EQ;
+ break;
+ case GTU:
+ cmp_code = LTU;
+ op0 = force_reg (mode, branch_cmp[1]);
+ op1 = branch_cmp[0];
+ break;
+ case LEU:
+ cmp_code = LTU;
+ op0 = force_reg (mode, branch_cmp[1]);
+ op1 = branch_cmp[0];
+ move_code = EQ;
+ break;
+ default:
+ abort ();
+ }
+ }
+ else
+ {
+ if (cmp_code == NE)
+ {
+ cmp_code = EQ;
+ move_code = EQ;
+ }
+ }
+
+ if (mode == SImode || mode == DImode)
+ cmp_mode = mode;
+ else if (mode == SFmode || mode == DFmode)
+ cmp_mode = CCmode;
+ else
+ abort ();
+ cmp_reg = gen_reg_rtx (cmp_mode);
+ emit_insn (gen_rtx (SET, cmp_mode,
+ cmp_reg,
+ gen_rtx (cmp_code, cmp_mode, op0, op1)));
+ emit_insn (gen_rtx (SET, op_mode,
+ operands[0],
+ gen_rtx (IF_THEN_ELSE, op_mode,
+ gen_rtx (move_code, VOIDmode,
+ cmp_reg,
+ CONST0_RTX (SImode)),
+ operands[2],
+ operands[3])));
+}
#if 0
/* Internal code to generate the load and store of one word/short/byte.
@@ -3443,6 +3532,11 @@ override_options ()
mips_cpu = PROCESSOR_R4650;
break;
+ case '5':
+ if (!strcmp (p, "5000") || !strcmp (p, "5k") || !strcmp (p, "5K"))
+ mips_cpu = PROCESSOR_R5000;
+ break;
+
case '6':
if (!strcmp (p, "6000") || !strcmp (p, "6k") || !strcmp (p, "6K"))
mips_cpu = PROCESSOR_R6000;
@@ -3459,7 +3553,10 @@ override_options ()
break;
}
- if (seen_v && mips_cpu != PROCESSOR_R4300 && mips_cpu != PROCESSOR_R4100)
+ if (seen_v
+ && mips_cpu != PROCESSOR_R4300
+ && mips_cpu != PROCESSOR_R4100
+ && mips_cpu != PROCESSOR_R5000)
mips_cpu = PROCESSOR_DEFAULT;
if (mips_cpu == PROCESSOR_DEFAULT)
@@ -3642,8 +3739,15 @@ override_options ()
{
register int temp;
- if (mode == CC_FPmode || mode == CC_REV_FPmode)
- temp = (regno == FPSW_REGNUM);
+ if (mode == CCmode)
+ {
+ if (mips_isa < 4)
+ temp = (regno == FPSW_REGNUM);
+ else
+ temp = (ST_REG_P (regno)
+ || GP_REG_P (regno)
+ || FP_REG_P (regno));
+ }
else if (GP_REG_P (regno))
temp = ((regno & 1) == 0 || (size <= UNITS_PER_WORD));
@@ -3745,6 +3849,7 @@ mips_debugger_offset (addr, offset)
'b' print 'n' for EQ, 'z' for NE
'T' print 'f' for EQ, 't' for NE
't' print 't' for EQ, 'f' for NE
+ 'Z' print register and a comma, but print nothing for $fcc0
'(' Turn on .set noreorder
')' Turn on .set reorder
'[' Turn on .set noat
@@ -3935,6 +4040,19 @@ print_operand (file, op, letter)
assemble_name (file, buffer);
}
+ else if (letter == 'Z')
+ {
+ register int regnum;
+
+ if (code != REG)
+ abort ();
+ regnum = REGNO (op);
+ if (! ST_REG_P (regnum))
+ abort ();
+ if (regnum != ST_REG_FIRST)
+ fprintf (file, "%s,", reg_names[regnum]);
+ }
+
else if (code == REG)
{
register int regnum = REGNO (op);
@@ -5853,5 +5971,26 @@ mips_secondary_reload_class (class, mode, x, in_p)
return GR_REGS;
}
+ /* We can only copy a value to a condition code register from a
+ floating point register, and even then we require a scratch
+ floating point register. We can only copy a value out of a
+ condition code register into a general register. */
+ if (class == ST_REGS)
+ {
+ if (in_p)
+ return FP_REGS;
+ if (GP_REG_P (regno))
+ return NO_REGS;
+ return GR_REGS;
+ }
+ if (ST_REG_P (regno))
+ {
+ if (! in_p)
+ return FP_REGS;
+ if (class == GR_REGS)
+ return NO_REGS;
+ return GR_REGS;
+ }
+
return NO_REGS;
}
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index a1f0b26..c683852 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -70,6 +70,7 @@ enum processor_type {
PROCESSOR_R4300,
PROCESSOR_R4600,
PROCESSOR_R4650,
+ PROCESSOR_R5000,
PROCESSOR_R8000
};
@@ -168,6 +169,7 @@ extern int function_arg_partial_nregs ();
extern void function_epilogue ();
extern void function_prologue ();
extern void gen_conditional_branch ();
+extern void gen_conditional_move ();
extern struct rtx_def * gen_int_relational ();
extern void init_cumulative_args ();
extern int large_int ();
@@ -555,6 +557,18 @@ do \
\
for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) \
fixed_regs[regno] = call_used_regs[regno] = 1; \
+ for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++) \
+ fixed_regs[regno] = call_used_regs[regno] = 1; \
+ } \
+ else if (mips_isa < 4) \
+ { \
+ int regno; \
+ \
+ /* We only have a single condition code register. We \
+ implement this by hiding all the condition code registers, \
+ and generating RTL that refers directly to ST_REG_FIRST. */ \
+ for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++) \
+ fixed_regs[regno] = call_used_regs[regno] = 1; \
} \
SUBTARGET_CONDITIONAL_REGISTER_USAGE \
} \
@@ -1200,14 +1214,16 @@ do { \
even those that are not normally considered general registers.
On the Mips, we have 32 integer registers, 32 floating point
- registers and the special registers hi, lo, hilo, fp status, and rap.
- The hilo register is only used in 64 bit mode. It represents a 64
- bit value stored as two 32 bit values in the hi and lo registers;
- this is the result of the mult instruction. rap is a pointer to the
- stack where the return address reg ($31) was stored. This is needed
- for C++ exception handling. */
+ registers, 8 condition code registers, and the special registers
+ hi, lo, hilo, and rap. The 8 condition code registers are only
+ used if mips_isa >= 4. The hilo register is only used in 64 bit
+ mode. It represents a 64 bit value stored as two 32 bit values in
+ the hi and lo registers; this is the result of the mult
+ instruction. rap is a pointer to the stack where the return
+ address reg ($31) was stored. This is needed for C++ exception
+ handling. */
-#define FIRST_PSEUDO_REGISTER 69
+#define FIRST_PSEUDO_REGISTER 76
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
@@ -1220,7 +1236,7 @@ do { \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 1, 1 \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 \
}
@@ -1237,7 +1253,7 @@ do { \
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- 1, 1, 1, 1, 1 \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \
}
@@ -1260,21 +1276,25 @@ do { \
#define MD_REG_NUM (MD_REG_LAST - MD_REG_FIRST + 1)
#define ST_REG_FIRST 67
-#define ST_REG_LAST 67
+#define ST_REG_LAST 74
#define ST_REG_NUM (ST_REG_LAST - ST_REG_FIRST + 1)
-#define RAP_REG_NUM 68
+#define RAP_REG_NUM 75
#define AT_REGNUM (GP_REG_FIRST + 1)
#define HI_REGNUM (MD_REG_FIRST + 0)
#define LO_REGNUM (MD_REG_FIRST + 1)
#define HILO_REGNUM (MD_REG_FIRST + 2)
+
+/* FPSW_REGNUM is the single condition code used if mips_isa < 4. If
+ mips_isa >= 4, it should not be used, and an arbitrary ST_REG
+ should be used instead. */
#define FPSW_REGNUM ST_REG_FIRST
#define GP_REG_P(REGNO) ((unsigned) ((REGNO) - GP_REG_FIRST) < GP_REG_NUM)
#define FP_REG_P(REGNO) ((unsigned) ((REGNO) - FP_REG_FIRST) < FP_REG_NUM)
#define MD_REG_P(REGNO) ((unsigned) ((REGNO) - MD_REG_FIRST) < MD_REG_NUM)
-#define ST_REG_P(REGNO) ((REGNO) == ST_REG_FIRST)
+#define ST_REG_P(REGNO) ((unsigned) ((REGNO) - ST_REG_FIRST) < ST_REG_NUM)
/* Return number of consecutive hard regs needed starting at reg REGNO
to hold something of mode MODE.
@@ -1464,8 +1484,8 @@ enum reg_class
{ 0x00000000, 0x00000000, 0x00000002 }, /* lo register */ \
{ 0x00000000, 0x00000000, 0x00000004 }, /* hilo register */ \
{ 0x00000000, 0x00000000, 0x00000003 }, /* mul/div registers */ \
- { 0x00000000, 0x00000000, 0x00000008 }, /* status registers */ \
- { 0xffffffff, 0xffffffff, 0x0000000f } /* all registers */ \
+ { 0x00000000, 0x00000000, 0x000007f8 }, /* status registers */ \
+ { 0xffffffff, 0xffffffff, 0x000007ff } /* all registers */ \
}
@@ -1625,7 +1645,8 @@ extern enum reg_class mips_char_to_class[];
|| (CLASS2 == GR_REGS && CLASS1 == FP_REGS))))
/* The HI and LO registers can only be reloaded via the general
- registers. */
+ registers. Condition code registers can only be loaded to the
+ general registers, and from the floating point registers. */
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
mips_secondary_reload_class (CLASS, MODE, X, 1)
@@ -2868,7 +2889,8 @@ while (0)
enum machine_mode xmode = GET_MODE (X); \
if (xmode == SFmode) \
{ \
- if (mips_cpu == PROCESSOR_R3000) \
+ if (mips_cpu == PROCESSOR_R3000 \
+ || mips_cpu == PROCESSOR_R5000) \
return COSTS_N_INSNS (4); \
else if (mips_cpu == PROCESSOR_R6000) \
return COSTS_N_INSNS (5); \
@@ -2878,7 +2900,8 @@ while (0)
\
if (xmode == DFmode) \
{ \
- if (mips_cpu == PROCESSOR_R3000) \
+ if (mips_cpu == PROCESSOR_R3000 \
+ || mips_cpu == PROCESSOR_R5000) \
return COSTS_N_INSNS (5); \
else if (mips_cpu == PROCESSOR_R6000) \
return COSTS_N_INSNS (6); \
@@ -2890,6 +2913,8 @@ while (0)
return COSTS_N_INSNS (12); \
else if (mips_cpu == PROCESSOR_R6000) \
return COSTS_N_INSNS (17); \
+ else if (mips_cpu == PROCESSOR_R5000) \
+ return COSTS_N_INSNS (5); \
else \
return COSTS_N_INSNS (10); \
} \
@@ -2926,6 +2951,8 @@ while (0)
return COSTS_N_INSNS (35); \
else if (mips_cpu == PROCESSOR_R6000) \
return COSTS_N_INSNS (38); \
+ else if (mips_cpu == PROCESSOR_R5000) \
+ return COSTS_N_INSNS (36); \
else \
return COSTS_N_INSNS (69);
@@ -3001,6 +3028,8 @@ while (0)
: (((TO) == HI_REG || (TO) == LO_REG \
|| (TO) == MD_REGS || (FROM) == HILO_REG) \
&& (FROM) == GR_REGS) ? 6 \
+ : (FROM) == ST_REGS && (TO) == GR_REGS ? 4 \
+ : (FROM) == FP_REGS && (TO) == ST_REGS ? 8 \
: 12)
/* ??? Fix this to be right for the R8000. */
@@ -3053,6 +3082,7 @@ while (0)
{"small_int", { CONST_INT }}, \
{"large_int", { CONST_INT }}, \
{"mips_const_double_ok", { CONST_DOUBLE }}, \
+ {"const_float_1_operand", { CONST_DOUBLE }}, \
{"simple_memory_operand", { MEM, SUBREG }}, \
{"equality_op", { EQ, NE }}, \
{"cmp_op", { EQ, NE, GT, GE, GTU, GEU, LT, LE, \
@@ -3083,40 +3113,6 @@ while (0)
final_prescan_insn (INSN, OPVEC, NOPERANDS)
-/* Tell final.c how to eliminate redundant test instructions.
- Here we define machine-dependent flags and fields in cc_status
- (see `conditions.h'). */
-
-/* A list of names to be used for additional modes for condition code
- values in registers. These names are added to `enum machine_mode'
- and all have class `MODE_CC'. By convention, they should start
- with `CC' and end with `mode'.
-
- You should only define this macro if your machine does not use
- `cc0' and only if additional modes are required.
-
- On the MIPS, we use CC_FPmode for all floating point except for not
- equal, CC_REV_FPmode for not equal (to reverse the sense of the
- jump), CC_EQmode for integer equality/inequality comparisons,
- CC_0mode for comparisons against 0, and CCmode for other integer
- comparisons. */
-
-#define EXTRA_CC_MODES CC_EQmode, CC_FPmode, CC_0mode, CC_REV_FPmode
-
-/* A list of C strings giving the names for the modes listed in
- `EXTRA_CC_MODES'. */
-
-#define EXTRA_CC_NAMES "CC_EQ", "CC_FP", "CC_0", "CC_REV_FP"
-
-/* Returns a mode from class `MODE_CC' to be used when comparison
- operation code OP is applied to rtx X. */
-
-#define SELECT_CC_MODE(OP, X, Y) \
- (GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \
- ? SImode \
- : ((OP == NE) ? CC_REV_FPmode : CC_FPmode))
-
-
/* Control the assembler format that we output. */
/* Output at beginning of assembler file.
@@ -3217,6 +3213,13 @@ while (0)
&mips_reg_names[66][0], \
&mips_reg_names[67][0], \
&mips_reg_names[68][0], \
+ &mips_reg_names[69][0], \
+ &mips_reg_names[70][0], \
+ &mips_reg_names[71][0], \
+ &mips_reg_names[72][0], \
+ &mips_reg_names[73][0], \
+ &mips_reg_names[74][0], \
+ &mips_reg_names[75][0], \
}
/* print-rtl.c can't use REGISTER_NAMES, since it depends on mips.c.
@@ -3231,7 +3234,8 @@ while (0)
"$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", \
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", \
"$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", \
- "hi", "lo", "accum","$fcr31","$rap" \
+ "hi", "lo", "accum","$fcc0","$fcc1","$fcc2","$fcc3","$fcc4", \
+ "$fcc5","$fcc6","$fcc7","$rap" \
}
/* If defined, a C initializer for an array of structures
@@ -3310,8 +3314,7 @@ while (0)
{ "fp", 30 + GP_REG_FIRST }, \
{ "ra", 31 + GP_REG_FIRST }, \
{ "$sp", 29 + GP_REG_FIRST }, \
- { "$fp", 30 + GP_REG_FIRST }, \
- { "cc", FPSW_REGNUM }, \
+ { "$fp", 30 + GP_REG_FIRST } \
}
/* Define results of standard character escape sequences. */
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index da9502a..4a61c4f 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -3,7 +3,7 @@
;; Changes by Michael Meissner, meissner@osf.org
;; 64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
;; Brendan Eich, brendan@microunity.com.
-;; Copyright (C) 1989, 90, 91, 92, 93, 94, 95 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 90-5, 1996 Free Software Foundation, Inc.
;; This file is part of GNU CC.
@@ -22,12 +22,6 @@
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
-;; ??? MIPS4 has 8 floating point condition codes. This is not supported yet.
-
-;; ??? MIPS4 has floating point doubleword/word load/stores that accept a
-;; base+index addressing mode. There are no such load/stores for the integer
-;; registers. This is not supported yet.
-
;; ??? Currently does not have define_function_unit support for the R8000.
;; Must include new entries for fmadd in addition to existing entries.
@@ -93,7 +87,8 @@
;; (const_string "default"))))
;; ??? Fix everything that tests this attribute.
-(define_attr "cpu" "default,r3000,r6000,r4000,r4100,r4300,r4600,r4650,r8000"
+(define_attr "cpu"
+ "default,r3000,r6000,r4000,r4100,r4300,r4600,r4650,r5000,r8000"
(const (symbol_ref "mips_cpu_attr")))
;; Attribute defining whether or not we can use the branch-likely instructions
@@ -151,11 +146,13 @@
;; Make the default case (PROCESSOR_DEFAULT) handle the worst case
(define_function_unit "memory" 1 0
- (and (eq_attr "type" "load") (eq_attr "cpu" "!r3000,r4600,r4650,r4100,r4300"))
+ (and (eq_attr "type" "load")
+ (eq_attr "cpu" "!r3000,r4600,r4650,r4100,r4300,r5000"))
3 0)
(define_function_unit "memory" 1 0
- (and (eq_attr "type" "load") (eq_attr "cpu" "r3000,r4600,r4650,r4100,r4300"))
+ (and (eq_attr "type" "load")
+ (eq_attr "cpu" "r3000,r4600,r4650,r4100,r4300,r5000"))
2 0)
(define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0)
@@ -167,7 +164,8 @@
1 3)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "imul") (eq_attr "cpu" "!r3000,r4000,r4600,r4650,r4100,r4300"))
+ (and (eq_attr "type" "imul")
+ (eq_attr "cpu" "!r3000,r4000,r4600,r4650,r4100,r4300,r5000"))
17 17)
(define_function_unit "imuldiv" 1 0
@@ -183,23 +181,33 @@
4 4)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "imul") (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100")))
+ (and (eq_attr "type" "imul")
+ (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100")))
1 1)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "imul") (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100")))
+ (and (eq_attr "type" "imul")
+ (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100")))
4 4)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "imul") (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300")))
+ (and (eq_attr "type" "imul")
+ (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300,r5000")))
5 5)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "imul") (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300")))
+ (and (eq_attr "type" "imul")
+ (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300")))
8 8)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "idiv") (eq_attr "cpu" "!r3000,r4000,r4600,r4650,r4100,r4300"))
+ (and (eq_attr "type" "imul")
+ (and (eq_attr "mode" "DI") (eq_attr "cpu" "r5000")))
+ 9 9)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "idiv")
+ (eq_attr "cpu" "!r3000,r4000,r4600,r4650,r4100,r4300,r5000"))
38 38)
(define_function_unit "imuldiv" 1 0
@@ -219,21 +227,35 @@
69 69)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "idiv") (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100")))
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100")))
35 35)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "idiv") (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100")))
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100")))
67 67)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "idiv") (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300")))
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300")))
37 37)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "idiv") (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300")))
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300")))
69 69)
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "SI") (eq_attr "cpu" "r5000")))
+ 36 36)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "DI") (eq_attr "cpu" "r5000")))
+ 68 68)
+
;; The R4300 does *NOT* have a seperate Floating Point Unit, instead
;; the FP hardware is part of the normal ALU circuitry. This means FP
;; instructions affect the pipe-line, and no functional unit
@@ -242,7 +264,7 @@
;; instructions to be processed in the "imuldiv" unit.
(define_function_unit "adder" 1 1
- (and (eq_attr "type" "fcmp") (eq_attr "cpu" "!r3000,r6000,r4300"))
+ (and (eq_attr "type" "fcmp") (eq_attr "cpu" "!r3000,r6000,r4300,r5000"))
3 0)
(define_function_unit "adder" 1 1
@@ -250,6 +272,10 @@
2 0)
(define_function_unit "adder" 1 1
+ (and (eq_attr "type" "fcmp") (eq_attr "cpu" "r5000"))
+ 1 0)
+
+(define_function_unit "adder" 1 1
(and (eq_attr "type" "fadd") (eq_attr "cpu" "!r3000,r6000,r4300"))
4 0)
@@ -262,89 +288,129 @@
3 0)
(define_function_unit "adder" 1 1
- (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "!r3000,r4600,r4650,r4300"))
+ (and (eq_attr "type" "fabs,fneg")
+ (eq_attr "cpu" "!r3000,r4600,r4650,r4300,r5000"))
2 0)
(define_function_unit "adder" 1 1
- (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "r3000,r4600,r4650"))
+ (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "r3000,r4600,r4650,r5000"))
1 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r3000,r6000,r4600,r4650,r4300")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "cpu" "!r3000,r6000,r4600,r4650,r4300,r5000")))
7 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000,r5000")))
4 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000")))
5 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650")))
8 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r6000,r4300")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r6000,r4300,r5000")))
8 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000,r5000")))
5 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000")))
6 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r3000,r6000,r4600,r4650,r4300")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "cpu" "!r3000,r6000,r4600,r4650,r4300,r5000")))
23 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000")))
12 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000")))
15 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650")))
32 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r6000,r4600,r4650,r4300")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r5000")))
+ 21 0)
+
+(define_function_unit "divide" 1 1
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "DF")
+ (eq_attr "cpu" "!r3000,r6000,r4600,r4650,r4300")))
36 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000")))
19 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000")))
16 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650")))
61 0)
;;; ??? Is this number right?
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fsqrt") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r4600,r4650,r4300")))
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000")))
54 0)
+
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fsqrt") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650")))
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650")))
31 0)
+(define_function_unit "divide" 1 1
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r5000")))
+ 21 0)
+
;;; ??? Is this number right?
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fsqrt") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r4600,r4650,r4300")))
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000")))
112 0)
+
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fsqrt") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650")))
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650")))
60 0)
+(define_function_unit "divide" 1 1
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r5000")))
+ 36 0)
+
;; R4300 FP instruction classes treated as part of the "imuldiv"
;; functional unit:
@@ -1286,7 +1352,7 @@
(plus:DF (mult:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f"))
(match_operand:DF 3 "register_operand" "f")))]
- "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"madd.d\\t%0,%3,%1,%2"
[(set_attr "type" "fmadd")
(set_attr "mode" "DF")
@@ -1308,7 +1374,7 @@
(minus:DF (mult:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f"))
(match_operand:DF 3 "register_operand" "f")))]
- "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"msub.d\\t%0,%3,%1,%2"
[(set_attr "type" "fmadd")
(set_attr "mode" "DF")
@@ -1331,7 +1397,7 @@
(neg:DF (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f"))
(match_operand:DF 3 "register_operand" "f"))))]
- "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"nmadd.d\\t%0,%3,%1,%2"
[(set_attr "type" "fmadd")
(set_attr "mode" "DF")
@@ -1353,7 +1419,7 @@
(minus:DF (match_operand:DF 1 "register_operand" "f")
(mult:DF (match_operand:DF 2 "register_operand" "f")
(match_operand:DF 3 "register_operand" "f"))))]
- "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"nmsub.d\\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "DF")
@@ -1398,6 +1464,26 @@
(set_attr "mode" "SF")
(set_attr "length" "1")])
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (div:DF (match_operand:DF 1 "const_float_1_operand" "")
+ (match_operand:DF 2 "register_operand" "f")))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_fast_math"
+ "recip.d\\t%0,%2"
+ [(set_attr "type" "fdiv")
+ (set_attr "mode" "DF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (div:SF (match_operand:SF 1 "const_float_1_operand" "")
+ (match_operand:SF 2 "register_operand" "f")))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && flag_fast_math"
+ "recip.s\\t%0,%2"
+ [(set_attr "type" "fdiv")
+ (set_attr "mode" "SF")
+ (set_attr "length" "1")])
+
;; If optimizing, prefer the divmod functions over separate div and
;; mod functions, since this will allow using one instruction for both
;; the quotient and remainder. At present, the divmod is not moved out
@@ -1641,6 +1727,26 @@
(set_attr "mode" "SF")
(set_attr "length" "1")])
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (div:DF (match_operand:DF 1 "const_float_1_operand" "")
+ (sqrt:DF (match_operand:DF 2 "register_operand" "f"))))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_fast_math"
+ "rsqrt.d\\t%0,%2"
+ [(set_attr "type" "fsqrt")
+ (set_attr "mode" "DF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (div:SF (match_operand:SF 1 "const_float_1_operand" "")
+ (sqrt:SF (match_operand:SF 2 "register_operand" "f"))))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && flag_fast_math"
+ "rsqrt.s\\t%0,%2"
+ [(set_attr "type" "fsqrt")
+ (set_attr "mode" "SF")
+ (set_attr "length" "1")])
+
;;
;; ....................
@@ -3499,6 +3605,182 @@ move\\t%0,%z4\\n\\
DONE;
}")
+;; This insn handles moving CCmode values. It's really just a
+;; slightly simplified copy of movsi_internal2, with additional cases
+;; to move a condition register to a general register and to move
+;; between the general registers and the floating point registers.
+
+(define_insn "movcc"
+ [(set (match_operand:CC 0 "nonimmediate_operand" "=d,*d,*d,*d,*R,*m,*d,*f,*f,*f,*f,*R,*m")
+ (match_operand:CC 1 "general_operand" "z,*d,*R,*m,*d,*d,*f,*d,*f,*R,*m,*f,*f"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "* return mips_move_1word (operands, insn, FALSE);"
+ [(set_attr "type" "move,move,load,load,store,store,xfer,xfer,move,load,load,store,store")
+ (set_attr "mode" "SI")
+ (set_attr "length" "2,1,1,2,1,2,1,1,1,1,2,1,2")])
+
+;; Reload condition code registers. These need scratch registers.
+
+(define_expand "reload_incc"
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (match_operand:CC 1 "general_operand" "z"))
+ (clobber (match_operand:TF 2 "register_operand" "=&f"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "
+{
+ rtx source;
+ rtx fp1, fp2;
+
+ /* This is called when are copying some value into a condition code
+ register. Operand 0 is the condition code register. Operand 1
+ is the source. Operand 2 is a scratch register; we use TFmode
+ because we actually need two floating point registers. */
+ if (! ST_REG_P (true_regnum (operands[0]))
+ || ! FP_REG_P (true_regnum (operands[2])))
+ abort ();
+
+ /* We need to get the source in SFmode so that the insn is
+ recognized. */
+ if (GET_CODE (operands[1]) == MEM)
+ source = change_address (operands[1], SFmode, NULL_RTX);
+ else if (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG)
+ source = gen_rtx (REG, SFmode, true_regnum (operands[1]));
+ else
+ source = operands[1];
+
+ fp1 = gen_rtx (REG, SFmode, REGNO (operands[2]));
+ fp2 = gen_rtx (REG, SFmode, REGNO (operands[2]) + 1);
+
+ emit_insn (gen_move_insn (fp1, source));
+ emit_insn (gen_move_insn (fp2, gen_rtx (REG, SFmode, 0)));
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0],
+ gen_rtx (LT, CCmode, fp2, fp1)));
+
+ DONE;
+}")
+
+(define_expand "reload_outcc"
+ [(set (match_operand:CC 0 "general_operand" "=z")
+ (match_operand:CC 1 "register_operand" "z"))
+ (clobber (match_operand:CC 2 "register_operand" "=&d"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "
+{
+ /* This is called when we are copying a condition code register out
+ to save it somewhere. Operand 0 should be the location we are
+ going to save it to. Operand 1 should be the condition code
+ register. Operand 2 should be a scratch general purpose register
+ created for us by reload. The mips_secondary_reload_class
+ function should have told reload that we don't need a scratch
+ register if the destination is a general purpose register anyhow. */
+ if (ST_REG_P (true_regnum (operands[0]))
+ || GP_REG_P (true_regnum (operands[0]))
+ || ! ST_REG_P (true_regnum (operands[1]))
+ || ! GP_REG_P (true_regnum (operands[2])))
+ abort ();
+
+ /* All we have to do is copy the value from the condition code to
+ the data register, which movcc can handle, and then store the
+ value into the real final destination. */
+ emit_insn (gen_move_insn (operands[2], operands[1]));
+ emit_insn (gen_move_insn (operands[0], operands[2]));
+
+ DONE;
+}")
+
+;; MIPS4 supports loading and storing a floating point register from
+;; the sum of two general registers. We use two versions for each of
+;; these four instructions: one where the two general registers are
+;; SImode, and one where they are DImode. This is because general
+;; registers will be in SImode when they hold 32 bit values, but,
+;; since the 32 bit values are always sign extended, the [ls][wd]xc1
+;; instructions will still work correctly.
+
+;; ??? Perhaps it would be better to support these instructions by
+;; modifying GO_IF_LEGITIMATE_ADDRESS and friends. However, since
+;; these instructions can only be used to load and store floating
+;; point registers, that would probably cause trouble in reload.
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "lwxc1\\t%0,%1(%2)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (mem:SF (plus:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "register_operand" "d"))))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "lwxc1\\t%0,%1(%2)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "ldxc1\\t%0,%1(%2)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "DF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (mem:DF (plus:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "register_operand" "d"))))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "ldxc1\\t%0,%1(%2)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "DF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))
+ (match_operand:SF 0 "register_operand" "=f"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "swxc1\\t%0,%1(%2)"
+ [(set_attr "type" "store")
+ (set_attr "mode" "SF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (mem:SF (plus:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "register_operand" "d")))
+ (match_operand:SF 0 "register_operand" "=f"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "swxc1\\t%0,%1(%2)"
+ [(set_attr "type" "store")
+ (set_attr "mode" "SF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))
+ (match_operand:DF 0 "register_operand" "=f"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "sdxc1\\t%0,%1(%2)"
+ [(set_attr "type" "store")
+ (set_attr "mode" "DF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (mem:DF (plus:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "register_operand" "d")))
+ (match_operand:DF 0 "register_operand" "=f"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "sdxc1\\t%0,%1(%2)"
+ [(set_attr "type" "store")
+ (set_attr "mode" "DF")
+ (set_attr "length" "1")])
+
;; 16-bit Integer moves
;; Unlike most other insns, the move insns can't be split with
@@ -4625,8 +4907,8 @@ move\\t%0,%z4\\n\\
(define_expand "cmpdf"
[(set (cc0)
- (compare:CC_FP (match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "register_operand" "")))]
+ (compare:CC (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "register_operand" "")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"
{
@@ -4641,8 +4923,8 @@ move\\t%0,%z4\\n\\
(define_expand "cmpsf"
[(set (cc0)
- (compare:CC_FP (match_operand:SF 0 "register_operand" "")
- (match_operand:SF 1 "register_operand" "")))]
+ (compare:CC (match_operand:SF 0 "register_operand" "")
+ (match_operand:SF 1 "register_operand" "")))]
"TARGET_HARD_FLOAT"
"
{
@@ -4665,31 +4947,15 @@ move\\t%0,%z4\\n\\
(define_insn "branch_fp_ne"
[(set (pc)
- (if_then_else (ne:CC_FP (reg:CC_FP 67)
- (const_int 0))
- (match_operand 0 "pc_or_label_operand" "")
- (match_operand 1 "pc_or_label_operand" "")))]
- "TARGET_HARD_FLOAT"
- "*
-{
- mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- 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_fp_ne_rev"
- [(set (pc)
- (if_then_else (ne:CC_REV_FP (reg:CC_REV_FP 67)
- (const_int 0))
- (match_operand 0 "pc_or_label_operand" "")
- (match_operand 1 "pc_or_label_operand" "")))]
+ (if_then_else (ne:CC (match_operand:CC 0 "register_operand" "z")
+ (const_int 0))
+ (match_operand 1 "pc_or_label_operand" "")
+ (match_operand 2 "pc_or_label_operand" "")))]
"TARGET_HARD_FLOAT"
"*
{
mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- return (operands[0] != pc_rtx) ? \"%*bc1f%?\\t%0\" : \"%*bc1t%?\\t%1\";
+ return (operands[1] != pc_rtx) ? \"%*bc1t%?\\t%Z0%1\" : \"%*bc1f%?\\t%Z0%2\";
}"
[(set_attr "type" "branch")
(set_attr "mode" "none")
@@ -4697,37 +4963,20 @@ move\\t%0,%z4\\n\\
(define_insn "branch_fp_eq"
[(set (pc)
- (if_then_else (eq:CC_FP (reg:CC_FP 67)
- (const_int 0))
- (match_operand 0 "pc_or_label_operand" "")
- (match_operand 1 "pc_or_label_operand" "")))]
- "TARGET_HARD_FLOAT"
- "*
-{
- mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- 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_fp_eq_rev"
- [(set (pc)
- (if_then_else (eq:CC_REV_FP (reg:CC_REV_FP 67)
- (const_int 0))
- (match_operand 0 "pc_or_label_operand" "")
- (match_operand 1 "pc_or_label_operand" "")))]
+ (if_then_else (eq:CC (match_operand:CC 0 "register_operand" "z")
+ (const_int 0))
+ (match_operand 1 "pc_or_label_operand" "")
+ (match_operand 2 "pc_or_label_operand" "")))]
"TARGET_HARD_FLOAT"
"*
{
mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- return (operands[0] != pc_rtx) ? \"%*bc1t%?\\t%0\" : \"%*bc1f%?\\t%1\";
+ return (operands[1] != pc_rtx) ? \"%*bc1f%?\\t%Z0%1\" : \"%*bc1t%?\\t%Z0%2\";
}"
[(set_attr "type" "branch")
(set_attr "mode" "none")
(set_attr "length" "1")])
-
(define_insn "branch_zero"
[(set (pc)
(if_then_else (match_operator:SI 0 "cmp_op"
@@ -4860,8 +5109,8 @@ move\\t%0,%z4\\n\\
(define_expand "beq"
[(set (pc)
- (if_then_else (eq:CC_EQ (cc0)
- (const_int 0))
+ (if_then_else (eq:CC (cc0)
+ (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
@@ -4876,8 +5125,8 @@ move\\t%0,%z4\\n\\
(define_expand "bne"
[(set (pc)
- (if_then_else (ne:CC_EQ (cc0)
- (const_int 0))
+ (if_then_else (ne:CC (cc0)
+ (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
@@ -5749,216 +5998,130 @@ move\\t%0,%z4\\n\\
;; ....................
(define_insn "seq_df"
- [(set (reg:CC_FP 67)
- (eq:CC_FP (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (eq:CC (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"*
{
- 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 67)
- (ne:CC_REV_FP (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "register_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
- "*
-{
- 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);
+ return mips_fill_delay_slot (\"c.eq.d\\t%Z0%1,%2\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "slt_df"
- [(set (reg:CC_FP 67)
- (lt:CC_FP (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (lt:CC (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"*
{
- 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);
+ return mips_fill_delay_slot (\"c.lt.d\\t%Z0%1,%2\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "sle_df"
- [(set (reg:CC_FP 67)
- (le:CC_FP (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (le:CC (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"*
{
- 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);
+ return mips_fill_delay_slot (\"c.le.d\\t%Z0%1,%2\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "sgt_df"
- [(set (reg:CC_FP 67)
- (gt:CC_FP (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (gt:CC (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"*
{
- 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);
+ return mips_fill_delay_slot (\"c.lt.d\\t%Z0%2,%1\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "sge_df"
- [(set (reg:CC_FP 67)
- (ge:CC_FP (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (ge:CC (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"*
{
- 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);
+ return mips_fill_delay_slot (\"c.le.d\\t%Z0%2,%1\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "seq_sf"
- [(set (reg:CC_FP 67)
- (eq:CC_FP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
- "TARGET_HARD_FLOAT"
- "*
-{
- 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 67)
- (ne:CC_REV_FP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (eq:CC (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT"
"*
{
- 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);
+ return mips_fill_delay_slot (\"c.eq.s\\t%Z0%1,%2\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "slt_sf"
- [(set (reg:CC_FP 67)
- (lt:CC_FP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (lt:CC (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT"
"*
{
- 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);
+ return mips_fill_delay_slot (\"c.lt.s\\t%Z0%1,%2\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "sle_sf"
- [(set (reg:CC_FP 67)
- (le:CC_FP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (le:CC (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT"
"*
{
- 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);
+ return mips_fill_delay_slot (\"c.le.s\\t%Z0%1,%2\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "sgt_sf"
- [(set (reg:CC_FP 67)
- (gt:CC_FP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (gt:CC (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT"
"*
{
- 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);
+ return mips_fill_delay_slot (\"c.lt.s\\t%Z0%2,%1\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "sge_sf"
- [(set (reg:CC_FP 67)
- (ge:CC_FP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (ge:CC (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT"
"*
{
- 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);
+ return mips_fill_delay_slot (\"c.le.s\\t%Z0%2,%1\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
@@ -6769,13 +6932,16 @@ move\\t%0,%z4\\n\\
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d,d")
(if_then_else:SI
- (match_operator 3 "equality_op" [(reg:CC_FP 67) (const_int 0)])
+ (match_operator 3 "equality_op" [(match_operand:CC 4
+ "register_operand"
+ "z,z")
+ (const_int 0)])
(match_operand:SI 1 "reg_or_0_operand" "dJ,0")
(match_operand:SI 2 "reg_or_0_operand" "0,dJ")))]
- "mips_isa >= 4"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
"@
- mov%T3\\t%0,%z1,$fcc0
- mov%t3\\t%0,%z2,$fcc0"
+ mov%T3\\t%0,%z1,%4
+ mov%t3\\t%0,%z2,%4"
[(set_attr "type" "move")
(set_attr "mode" "SI")])
@@ -6812,13 +6978,16 @@ move\\t%0,%z4\\n\\
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d,d")
(if_then_else:DI
- (match_operator 3 "equality_op" [(reg:CC_FP 67) (const_int 0)])
+ (match_operator 3 "equality_op" [(match_operand:CC 4
+ "register_operand"
+ "z,z")
+ (const_int 0)])
(match_operand:DI 1 "reg_or_0_operand" "dJ,0")
(match_operand:DI 2 "reg_or_0_operand" "0,dJ")))]
- "mips_isa >= 4"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
"@
- mov%T3\\t%0,%z1,$fcc0
- mov%t3\\t%0,%z2,$fcc0"
+ mov%T3\\t%0,%z1,%4
+ mov%t3\\t%0,%z2,%4"
[(set_attr "type" "move")
(set_attr "mode" "DI")])
@@ -6840,13 +7009,16 @@ move\\t%0,%z4\\n\\
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=f,f")
(if_then_else:SF
- (match_operator 3 "equality_op" [(reg:CC_FP 67) (const_int 0)])
+ (match_operator 3 "equality_op" [(match_operand:CC 4
+ "register_operand"
+ "z,z")
+ (const_int 0)])
(match_operand:SF 1 "register_operand" "f,0")
(match_operand:SF 2 "register_operand" "0,f")))]
"mips_isa >= 4 && TARGET_HARD_FLOAT"
"@
- mov%T3.s\\t%0,%1,$fcc0
- mov%t3.s\\t%0,%2,$fcc0"
+ mov%T3.s\\t%0,%1,%4
+ mov%t3.s\\t%0,%2,%4"
[(set_attr "type" "move")
(set_attr "mode" "SF")])
@@ -6858,7 +7030,7 @@ move\\t%0,%z4\\n\\
(const_int 0)])
(match_operand:DF 2 "register_operand" "f,0")
(match_operand:DF 3 "register_operand" "0,f")))]
- "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"@
mov%B4.d\\t%0,%2,%1
mov%b4.d\\t%0,%3,%1"
@@ -6868,13 +7040,16 @@ move\\t%0,%z4\\n\\
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f,f")
(if_then_else:DF
- (match_operator 3 "equality_op" [(reg:CC_FP 67) (const_int 0)])
+ (match_operator 3 "equality_op" [(match_operand:CC 4
+ "register_operand"
+ "z,z")
+ (const_int 0)])
(match_operand:DF 1 "register_operand" "f,0")
(match_operand:DF 2 "register_operand" "0,f")))]
- "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"@
- mov%T3.d\\t%0,%1,$fcc0
- mov%t3.d\\t%0,%2,$fcc0"
+ mov%T3.d\\t%0,%1,%4
+ mov%t3.d\\t%0,%2,%4"
[(set_attr "type" "move")
(set_attr "mode" "DF")])
@@ -6889,85 +7064,45 @@ move\\t%0,%z4\\n\\
"mips_isa >= 4"
"
{
- rtx op0 = branch_cmp[0];
- rtx op1 = branch_cmp[1];
- enum machine_mode mode = GET_MODE (branch_cmp[0]);
- enum rtx_code compare_code = GET_CODE (operands[1]);
- enum rtx_code move_code = NE;
+ gen_conditional_move (operands);
+ DONE;
+}")
- if (GET_MODE_CLASS (mode) != MODE_FLOAT)
- {
- switch (compare_code)
- {
- case EQ:
- compare_code = XOR;
- move_code = EQ;
- break;
- case NE:
- compare_code = XOR;
- break;
- case LT:
- break;
- case GE:
- compare_code = LT;
- move_code = EQ;
- break;
- case GT:
- compare_code = LT;
- op0 = force_reg (mode, branch_cmp[1]);
- op1 = branch_cmp[0];
- break;
- case LE:
- compare_code = LT;
- op0 = force_reg (mode, branch_cmp[1]);
- op1 = branch_cmp[0];
- move_code = EQ;
- break;
- case LTU:
- break;
- case GEU:
- compare_code = LTU;
- move_code = EQ;
- break;
- case GTU:
- compare_code = LTU;
- op0 = force_reg (mode, branch_cmp[1]);
- op1 = branch_cmp[0];
- break;
- case LEU:
- compare_code = LTU;
- op0 = force_reg (mode, branch_cmp[1]);
- op1 = branch_cmp[0];
- move_code = EQ;
- break;
- default:
- abort ();
- }
- }
- else
- {
- if (compare_code == NE)
- {
- /* ??? Perhaps we need to use CC_FP_REVmode here? */
- compare_code = EQ;
- move_code = EQ;
- }
- }
-
- if (mode == SImode || mode == DImode)
- {
- operands[1] = gen_rtx (compare_code, mode, op0, op1);
- operands[4] = gen_reg_rtx (mode);
- }
- else if (mode == SFmode || mode == DFmode)
- {
- operands[1] = gen_rtx (compare_code, CC_FPmode, op0, op1);
- operands[4] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- }
+(define_expand "movdicc"
+ [(set (match_dup 4) (match_operand 1 "comparison_operator" ""))
+ (set (match_operand:DI 0 "register_operand" "")
+ (if_then_else:DI (match_dup 5)
+ (match_operand:DI 2 "reg_or_0_operand" "")
+ (match_operand:DI 3 "reg_or_0_operand" "")))]
+ "mips_isa >= 4"
+ "
+{
+ gen_conditional_move (operands);
+ DONE;
+}")
- operands[5] = gen_rtx (move_code, VOIDmode, operands[4],
- CONST0_RTX (SImode));
+(define_expand "movsfcc"
+ [(set (match_dup 4) (match_operand 1 "comparison_operator" ""))
+ (set (match_operand:SF 0 "register_operand" "")
+ (if_then_else:SF (match_dup 5)
+ (match_operand:SF 2 "reg_or_0_operand" "")
+ (match_operand:SF 3 "reg_or_0_operand" "")))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "
+{
+ gen_conditional_move (operands);
+ DONE;
}")
-;; ??? Need movdicc, movsfcc, and movdfcc patterns. They should be
-;; very similar to the above movsicc pattern.
+(define_expand "movdfcc"
+ [(set (match_dup 4) (match_operand 1 "comparison_operator" ""))
+ (set (match_operand:DF 0 "register_operand" "")
+ (if_then_else:DF (match_dup 5)
+ (match_operand:DF 2 "reg_or_0_operand" "")
+ (match_operand:DF 3 "reg_or_0_operand" "")))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "
+{
+ gen_conditional_move (operands);
+ DONE;
+}")