diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 1bc47d407644..f32117b94da5 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; - -fail: - abort_with_insn (gen_rtx (test_code, mode, cmp0, cmp1), "bad test"); } +/* Emit the common code for conditional moves. OPERANDS is the array + of operands passed to the conditional move defined_expand. */ + +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 a1f0b26b32aa..c683852e4ff9 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, \ @@ -3082,40 +3112,6 @@ while (0) #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \ 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. */ @@ -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 da9502ac5d0a..4a61c4f23492 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,13 +264,17 @@ ;; 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) @@ -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" "")))] + (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) ? \"%*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" "")))] - "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" "")))] + (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) ? \"%*bc1f%?\\t%0\" : \"%*bc1t%?\\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_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" "")))] - "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_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")))] + [(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); -}" - [(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")))] - "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; - - 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); - } - - operands[5] = gen_rtx (move_code, VOIDmode, operands[4], - CONST0_RTX (SImode)); + gen_conditional_move (operands); + DONE; }") -;; ??? Need movdicc, movsfcc, and movdfcc patterns. They should be -;; very similar to the above movsicc pattern. +(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; +}") + +(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; +}") + +(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; +}")