"$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
"$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 */
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. */
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). */
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;
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";
}
}
}
}
- else if (regno0 == FPSW_REGNUM)
+ else if (regno0 == FPSW_REGNUM && mips_isa < 4)
{
if (GP_REG_P (regno1))
{
ret = "lw\t%0,%1";
break;
case SImode:
+ case CCmode:
ret = ((unsignedp && TARGET_64BIT)
? "lwu\t%0,%1"
: "lw\t%0,%1");
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;
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])));
+}
\f
#if 0
/* Internal code to generate the load and store of one word/short/byte.
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;
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)
{
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));
'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
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);
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;
}
PROCESSOR_R4300,
PROCESSOR_R4600,
PROCESSOR_R4650,
+ PROCESSOR_R5000,
PROCESSOR_R8000
};
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 ();
\
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 \
} \
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.
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 \
}
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 \
}
#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.
{ 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 */ \
}
|| (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)
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); \
\
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); \
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); \
} \
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);
: (((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. */
{"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, \
#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
final_prescan_insn (INSN, OPVEC, NOPERANDS)
-\f
-/* 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))
-
\f
/* Control the assembler format that we output. */
&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.
"$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
{ "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. */
;; 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.
;; 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.
;; (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
;; 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)
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
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
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
;; 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
(and (eq_attr "type" "fcmp") (eq_attr "cpu" "r3000,r6000"))
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)
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:
(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")
(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")
(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")
(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")
(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
(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")])
+
\f
;;
;; ....................
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
(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"
"
{
(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"
"
{
(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")
(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"
(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)))]
""
(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)))]
""
;; ....................
(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")
(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")])
(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")])
(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")])
(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"
(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")])
"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;
+}")