diff options
author | Michael Meissner <meissner@gcc.gnu.org> | 1992-04-27 19:14:40 +0000 |
---|---|---|
committer | Michael Meissner <meissner@gcc.gnu.org> | 1992-04-27 19:14:40 +0000 |
commit | 34b650b300c86bf21af5b3f1aacdedaa124f4aec (patch) | |
tree | 41e8be71892b22e8704027f231877297b277bffd /gcc | |
parent | 31d04616b57669ad6727d4c0052e31c1a300a8d4 (diff) | |
download | gcc-34b650b300c86bf21af5b3f1aacdedaa124f4aec.zip gcc-34b650b300c86bf21af5b3f1aacdedaa124f4aec.tar.gz gcc-34b650b300c86bf21af5b3f1aacdedaa124f4aec.tar.bz2 |
*** empty log message ***
From-SVN: r844
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/mips/mips.c | 399 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 61 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 865 |
3 files changed, 858 insertions, 467 deletions
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 203ade8..f47d88f 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -94,6 +94,24 @@ extern char **save_argv; extern char *version_string; extern char *language_string; +/* Enumeration for all of the relational tests, so that we can build + arrays indexed by the test type, and not worry about the order + of EQ, NE, etc. */ + +enum internal_test { + ITEST_EQ, + ITEST_NE, + ITEST_GT, + ITEST_GE, + ITEST_LT, + ITEST_LE, + ITEST_GTU, + ITEST_GEU, + ITEST_LTU, + ITEST_LEU, + ITEST_MAX + }; + /* Global variables for machine-dependent things. */ /* Threshold for data being put into the small data/bss area, instead @@ -462,6 +480,16 @@ md_register_operand (op, mode) && MD_REG_P (REGNO (op))); } +/* Return truth value of whether OP is the FP status register. */ + +int +fpsw_register_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return (GET_CODE (op) == REG && ST_REG_P (REGNO (op))); +} + /* Return truth value if a CONST_DOUBLE is ok to be a legitimate constant. */ int @@ -658,6 +686,23 @@ fcmp_op (op, mode) return (classify_op (op, mode) & CLASS_FCMP_OP) != 0; } + +/* Return true if the operand is either the PC or a label_ref. */ + +int +pc_or_label_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (op == pc_rtx) + return TRUE; + + if (GET_CODE (op) == LABEL_REF) + return TRUE; + + return FALSE; +} + /* Return an operand string if the given instruction's delay slot or wrap it in a .set noreorder section. This is for filling delay @@ -683,7 +728,7 @@ mips_fill_delay_slot (ret, type, operands, cur_insn) register rtx next_insn = (cur_insn) ? NEXT_INSN (cur_insn) : (rtx)0; register int num_nops; - if (type == DELAY_LOAD) + if (type == DELAY_LOAD || type == DELAY_FCMP) num_nops = 1; else if (type == DELAY_HILO) @@ -1436,6 +1481,210 @@ mips_address_cost (addr) } +/* Make normal rtx_code into something we can index from an array */ + +static enum internal_test +map_test_to_internal_test (test_code) + enum rtx_code test_code; +{ + enum internal_test test = ITEST_MAX; + + switch (test_code) + { + case EQ: test = ITEST_EQ; break; + case NE: test = ITEST_NE; break; + case GT: test = ITEST_GT; break; + case GE: test = ITEST_GE; break; + case LT: test = ITEST_LT; break; + case LE: test = ITEST_LE; break; + case GTU: test = ITEST_GTU; break; + case GEU: test = ITEST_GEU; break; + case LTU: test = ITEST_LTU; break; + case LEU: test = ITEST_LEU; break; + } + + return test; +} + + +/* Generate the code to compare two integer values. The return value is: + (reg:SI xx) The pseudo register the comparison is in + (const_int 0) The comparison is always false + (const_int 1) The comparison is always true + (rtx)0 No register, generate a simple branch. */ + +rtx +gen_int_relational (test_code, result, cmp0, cmp1, p_invert) + enum rtx_code test_code; /* relational test (EQ, etc) */ + rtx result; /* result to store comp. or 0 if branch */ + rtx cmp0; /* first operand to compare */ + rtx cmp1; /* second operand to compare */ + int *p_invert; /* NULL or ptr to hold whether branch needs */ + /* to reserse it's test */ +{ + struct cmp_info { + enum rtx_code test_code; /* code to use in instruction (LT vs. LTU) */ + int const_low; /* low bound of constant we can accept */ + int const_high; /* high bound of constant we can accept */ + int const_add; /* constant to add (convert LE -> LT) */ + int reverse_regs; /* reverse registers in test */ + int invert_const; /* != 0 if invert value if cmp1 is constant */ + int invert_reg; /* != 0 if invert value if cmp1 is register */ + }; + + static struct cmp_info info[ (int)ITEST_MAX ] = { + + { XOR, 0, 65535, 0, 0, 0, 0 }, /* EQ */ + { XOR, 0, 65535, 0, 0, 1, 1 }, /* NE */ + { LT, -32769, 32766, 1, 1, 1, 0 }, /* GT */ + { LT, -32768, 32767, 0, 0, 1, 1 }, /* GE */ + { LT, -32768, 32767, 0, 0, 0, 0 }, /* LT */ + { LT, -32769, 32766, 1, 1, 0, 1 }, /* LE */ + { LTU, -32769, 32766, 1, 1, 1, 0 }, /* GTU */ + { LTU, -32768, 32767, 0, 0, 1, 1 }, /* GEU */ + { LTU, -32768, 32767, 0, 0, 0, 0 }, /* LTU */ + { LTU, -32769, 32766, 1, 1, 0, 1 }, /* LEU */ + }; + + enum internal_test test; + struct cmp_info *p_info; + int branch_p; + int eqne_p; + int invert; + rtx reg; + rtx reg2; + + test = map_test_to_internal_test (test_code); + if (test == ITEST_MAX) + abort (); + + p_info = &info[ (int)test ]; + eqne_p = (p_info->test_code == XOR); + + /* See if the test is always true or false. */ + if ((GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG) + && GET_CODE (cmp1) == CONST_INT) + { + int value = INTVAL (cmp1); + rtx truth = (rtx)0; + + if (test == ITEST_GEU && value == 0) + truth = const1_rtx; + + else if (test == ITEST_LTU && value == 0) + truth = const0_rtx; + + else if (!TARGET_INT64) + { + if (test == ITEST_LTU && value == -1) + truth = const1_rtx; + + else if (test == ITEST_GTU && value == -1) + truth = const0_rtx; + + else if (test == ITEST_LEU && value == -1) + truth = const1_rtx; + + else if (test == ITEST_GT && value == 0x7fffffff) + truth = const0_rtx; + + else if (test == ITEST_LE && value == 0x7fffffff) + truth = const1_rtx; + + else if (test == ITEST_LT && value == 0x80000000) + truth = const0_rtx; + + else if (test == ITEST_GE && value == 0x80000000) + truth = const1_rtx; + } + + if (truth != (rtx)0) + { + if (result != (rtx)0) + emit_move_insn (result, truth); + + return truth; + } + } + + /* Eliminate simple branches */ + branch_p = (result == (rtx)0); + if (branch_p) + { + if (GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG) + { + /* Comparisons against zero are simple branches */ + if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0) + return (rtx)0; + + /* Test for beq/bne. */ + if (eqne_p) + return (rtx)0; + } + + /* allocate a psuedo to calculate the value in. */ + result = gen_reg_rtx (SImode); + } + + /* Make sure we can handle any constants given to us. */ + if (GET_CODE (cmp0) == CONST_INT) + cmp0 = force_reg (SImode, cmp0); + + if (GET_CODE (cmp1) == CONST_INT) + { + int value = INTVAL (cmp1); + if (value < p_info->const_low || value > p_info->const_high) + cmp1 = force_reg (SImode, cmp1); + } + + /* See if we need to invert the result. */ + invert = (GET_CODE (cmp1) == CONST_INT) + ? p_info->invert_const + : p_info->invert_reg; + + if (p_invert != (int *)0) + { + *p_invert = invert; + invert = FALSE; + } + + /* Comparison to constants, may involve adding 1 to change a LT into LE. + Comparison between two registers, may involve switching operands. */ + if (GET_CODE (cmp1) == CONST_INT) + { + if (p_info->const_add != 0) + cmp1 = gen_rtx (CONST_INT, VOIDmode, INTVAL (cmp1) + p_info->const_add); + } + else if (p_info->reverse_regs) + { + rtx temp = cmp0; + cmp0 = cmp1; + cmp1 = temp; + } + + reg = (invert || eqne_p) ? gen_reg_rtx (SImode) : result; + emit_move_insn (reg, gen_rtx (p_info->test_code, SImode, cmp0, cmp1)); + + if (test == ITEST_NE && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0) + { + emit_move_insn (result, gen_rtx (GTU, SImode, reg, const0_rtx)); + invert = FALSE; + } + + else if (eqne_p) + { + reg2 = (invert) ? gen_reg_rtx (SImode) : result; + emit_move_insn (reg2, gen_rtx (LTU, SImode, reg, const1_rtx)); + reg = reg2; + } + + if (invert) + emit_move_insn (result, gen_rtx (XOR, SImode, reg, const1_rtx)); + + return result; +} + + /* Emit the common code for doing conditional branches. operand[0] is the label to jump to. The comparison operands are saved away by cmp{si,sf,df}. */ @@ -1445,36 +1694,22 @@ gen_conditional_branch (operands, test_code) rtx operands[]; enum rtx_code test_code; { - enum { - I_EQ, - I_NE, - I_GT, - I_GE, - I_LT, - I_LE, - I_GTU, - I_GEU, - I_LTU, - I_LEU, - I_MAX - } test = I_MAX; - - static enum machine_mode mode_map[(int)CMP_MAX][(int)I_MAX] = { + static enum machine_mode mode_map[(int)CMP_MAX][(int)ITEST_MAX] = { { /* CMP_SI */ - CC_EQmode, /* eq */ - CC_EQmode, /* ne */ - CCmode, /* gt */ - CCmode, /* ge */ - CCmode, /* lt */ - CCmode, /* le */ - CCmode, /* gtu */ - CCmode, /* geu */ - CCmode, /* ltu */ - CCmode, /* leu */ + SImode, /* eq */ + SImode, /* ne */ + SImode, /* gt */ + SImode, /* ge */ + SImode, /* lt */ + SImode, /* le */ + SImode, /* gtu */ + SImode, /* geu */ + SImode, /* ltu */ + SImode, /* leu */ }, { /* CMP_SF */ CC_FPmode, /* eq */ - CC_FPmode, /* ne */ + CC_REV_FPmode, /* ne */ CC_FPmode, /* gt */ CC_FPmode, /* ge */ CC_FPmode, /* lt */ @@ -1486,7 +1721,7 @@ gen_conditional_branch (operands, test_code) }, { /* CMP_DF */ CC_FPmode, /* eq */ - CC_FPmode, /* ne */ + CC_REV_FPmode, /* ne */ CC_FPmode, /* gt */ CC_FPmode, /* ge */ CC_FPmode, /* lt */ @@ -1499,33 +1734,22 @@ gen_conditional_branch (operands, test_code) }; enum machine_mode mode; - enum cmp_type type = branch_type; - rtx cmp0 = branch_cmp[0]; - rtx cmp1 = branch_cmp[1]; - rtx label = gen_rtx (LABEL_REF, VOIDmode, operands[0]); - - /* Make normal rtx_code into something we can index from an array */ - switch (test_code) + enum cmp_type type = branch_type; + rtx cmp0 = branch_cmp[0]; + rtx cmp1 = branch_cmp[1]; + rtx label1 = gen_rtx (LABEL_REF, VOIDmode, operands[0]); + rtx label2 = pc_rtx; + rtx reg = (rtx)0; + int invert = 0; + enum internal_test test = map_test_to_internal_test (test_code); + + if (test == ITEST_MAX) { - case EQ: test = I_EQ; break; - case NE: test = I_NE; break; - case GT: test = I_GT; break; - case GE: test = I_GE; break; - case LT: test = I_LT; break; - case LE: test = I_LE; break; - case GTU: test = I_GTU; break; - case GEU: test = I_GEU; break; - case LTU: test = I_LTU; break; - case LEU: test = I_LEU; break; - } - - if (test == I_MAX) - { - mode = CCmode; + mode = SImode; goto fail; } - /* Get the machine mode to use (CCmode, CC_EQmode, or CC_FPmode). */ + /* Get the machine mode to use (CCmode, CC_EQmode, CC_FPmode, or CC_REV_FPmode). */ mode = mode_map[(int)type][(int)test]; if (mode == VOIDmode) goto fail; @@ -1536,50 +1760,46 @@ gen_conditional_branch (operands, test_code) goto fail; case CMP_SI: - /* Change >, >=, <, <= tests against 0 to use CC_0mode, since we have - special instructions to do these tests directly. */ - - if (mode == CCmode && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0) - { - emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, cmp0)); - mode = CC_0mode; - } - - else if (mode == CCmode && GET_CODE (cmp0) == CONST_INT && INTVAL (cmp0) == 0) + reg = gen_int_relational (test_code, (rtx)0, cmp0, cmp1, &invert); + if (reg != (rtx)0) { - emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, cmp1)); - test_code = reverse_condition (test_code); - mode = CC_0mode; + cmp0 = reg; + cmp1 = const0_rtx; + test_code = NE; } - else - { - /* force args to register for equality comparisons. */ - if (mode == CC_EQmode && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0) - cmp1 = force_reg (SImode, cmp1); + /* Make sure not non-zero constant if ==/!= */ + else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0) + cmp1 = force_reg (SImode, cmp1); - emit_insn (gen_rtx (SET, VOIDmode, - cc0_rtx, - gen_rtx (COMPARE, mode, cmp0, cmp1))); - } break; case CMP_DF: - emit_insn (gen_cmpdf_internal (cmp0, cmp1)); - break; - case CMP_SF: - emit_insn (gen_cmpsf_internal (cmp0, cmp1)); + { + rtx reg = gen_rtx (REG, mode, FPSW_REGNUM); + emit_insn (gen_rtx (SET, VOIDmode, reg, gen_rtx (test_code, mode, cmp0, cmp1))); + cmp0 = reg; + cmp1 = const0_rtx; + test_code = NE; + } break; } /* Generate the jump */ + if (invert) + { + label2 = label1; + label1 = pc_rtx; + } + emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx, gen_rtx (IF_THEN_ELSE, VOIDmode, - gen_rtx (test_code, mode, cc0_rtx, const0_rtx), - label, - pc_rtx))); + gen_rtx (test_code, mode, cmp0, cmp1), + label1, + label2))); + return; fail: @@ -2728,9 +2948,9 @@ override_options () mips_char_to_class['f'] = ((TARGET_HARD_FLOAT) ? FP_REGS : NO_REGS); mips_char_to_class['h'] = HI_REG; mips_char_to_class['l'] = LO_REG; - mips_char_to_class['s'] = ST_REGS; mips_char_to_class['x'] = MD_REGS; mips_char_to_class['y'] = GR_REGS; + mips_char_to_class['z'] = ST_REGS; /* Set up array to map GCC register number to debug register number. Ignore the special purpose register numbers. */ @@ -2762,22 +2982,25 @@ override_options () for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) { - register int temp = FALSE; + register int temp; + + if (mode == CC_FPmode || mode == CC_REV_FPmode) + temp = (regno == FPSW_REGNUM); - if (GP_REG_P (regno)) + else if (GP_REG_P (regno)) temp = ((regno & 1) == 0 || (size <= UNITS_PER_WORD)); else if (FP_REG_P (regno)) temp = ((TARGET_FLOAT64 || ((regno & 1) == 0)) - && (TARGET_DEBUG_H_MODE - || class == MODE_FLOAT - || class == MODE_COMPLEX_FLOAT)); + && (class == MODE_FLOAT + || class == MODE_COMPLEX_FLOAT + || (TARGET_DEBUG_H_MODE && class == MODE_INT))); else if (MD_REG_P (regno)) temp = (mode == SImode || (regno == MD_REG_FIRST && mode == DImode)); - else if (ST_REG_P (regno)) - temp = ((mode == SImode) || (class == MODE_CC)); + else + temp = FALSE; mips_hard_regno_mode_ok[(int)mode][regno] = temp; } diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 866ce6f..240d64a 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -49,7 +49,8 @@ enum cmp_type { enum delay_type { DELAY_NONE, /* no delay slot */ DELAY_LOAD, /* load from memory delay */ - DELAY_HILO /* move from/to hi/lo registers */ + DELAY_HILO, /* move from/to hi/lo registers */ + DELAY_FCMP /* delay after doing c.<xx>.{d,s} */ }; /* Which processor to schedule for. Since there is no difference between @@ -120,12 +121,14 @@ extern unsigned long compute_frame_size (); extern void expand_block_move (); extern int equality_op (); extern int fcmp_op (); +extern int fpsw_register_operand (); extern struct rtx_def * function_arg (); extern void function_arg_advance (); extern int function_arg_partial_nregs (); extern void function_epilogue (); extern void function_prologue (); extern void gen_conditional_branch (); +extern struct rtx_def * gen_int_relational (); extern void init_cumulative_args (); extern int large_int (); extern int md_register_operand (); @@ -145,6 +148,7 @@ extern void mips_output_filename (); extern void mips_output_lineno (); extern char *output_block_move (); extern void override_options (); +extern int pc_or_label_operand (); extern void print_operand_address (); extern void print_operand (); extern void print_options (); @@ -416,7 +420,7 @@ while (0) /* Print subsidiary information on the compiler version in use. */ -#define MIPS_VERSION "[AL 1.1, MM 15]" +#define MIPS_VERSION "[AL 1.1, MM 16]" #ifndef MACHINE_TYPE #define MACHINE_TYPE "BSD Mips" @@ -646,7 +650,7 @@ do { \ #define MASK_DEBUG 0x40000000 /* Eliminate version # in .s file */ #define MASK_DEBUG_A 0x20000000 /* don't allow <label>($reg) addrs */ #define MASK_DEBUG_B 0x10000000 /* GO_IF_LEGITIMATE_ADDRESS debug */ -#define MASK_DEBUG_C 0x08000000 /* suppress normal divmod patterns */ +#define MASK_DEBUG_C 0x08000000 /* allow new seq, sne, etc. patterns */ #define MASK_DEBUG_D 0x04000000 /* don't do define_split's */ #define MASK_DEBUG_E 0x02000000 /* function_arg debug */ #define MASK_DEBUG_F 0x01000000 /* don't try to suppress load nop's */ @@ -1280,8 +1284,8 @@ extern enum reg_class mips_regno_to_class[]; 'f' Floating point registers 'h' Hi register 'l' Lo register - 's' Status registers - 'x' Multiply/divide registers */ + 'x' Multiply/divide registers + 'z' FP Status register */ extern enum reg_class mips_char_to_class[]; @@ -2547,47 +2551,34 @@ do \ } \ while (0) -/* A list of names to be used for additional modes for condition - code values in registers (*note Jump Patterns::.). 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'. +/* 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, CC_EQmode for - integer equality/inequality comparisons, CC_0mode for comparisons - against 0, and CCmode for other integer comparisons. */ + 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 +#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'. For example, the Sparc defines this macro and - `EXTRA_CC_MODES' as + `EXTRA_CC_MODES'. */ - #define EXTRA_CC_MODES CC_NOOVmode, CCFPmode - #define EXTRA_CC_NAMES "CC_NOOV", "CCFP" - - This macro is not required if `EXTRA_CC_MODES' is not defined. */ - -#define EXTRA_CC_NAMES "CC_EQ", "CC_FP", "CC_0" +#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. For example, on the - Sparc, `SELECT_CC_MODE' is defined as (see *note Jump - Patterns::. for a description of the reason for this definition) - - #define SELECT_CC_MODE(OP,X) \ - (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode \ - : (GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ - || GET_CODE (X) == NEG) \ - ? CC_NOOVmode : CCmode) - - This macro is not required if `EXTRA_CC_MODES' is not defined. */ + operation code OP is applied to rtx X. */ -#define SELECT_CC_MODE (OP, X) \ - (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CC_FPmode : \ - (OP == EQ || OP == NE) ? CC_EQmode : CCmode) +#define SELECT_CC_MODE(OP, X) \ + (GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \ + ? SImode \ + : ((OP == NE) ? CC_REV_FPmode : CC_FPmode)) /* Control the assembler format that we output. */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 2a188ce..f4b7e05 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -58,7 +58,7 @@ (const_string "unknown")) ;; Main data type used by the insn -(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF" (const_string "unknown")) +(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF,FPSW" (const_string "unknown")) ;; # instructions (4 bytes each) (define_attr "length" "" (const_int 1)) @@ -133,6 +133,8 @@ (define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0) +(define_function_unit "fp_comp" 1 0 (eq_attr "type" "fcmp") 2 0) + (define_function_unit "transfer" 1 0 (eq_attr "type" "xfer") 2 0) (define_function_unit "transfer" 1 0 (eq_attr "type" "hilo") 3 0) @@ -317,7 +319,7 @@ (subreg:SI (match_dup 2) 0))) (set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 0) 0) + (ltu:SI (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 2) 0))) (set (subreg:SI (match_dup 0) 1) @@ -346,7 +348,7 @@ (subreg:SI (match_dup 2) 1))) (set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 0) 1) + (ltu:SI (subreg:SI (match_dup 0) 1) (subreg:SI (match_dup 2) 1))) (set (subreg:SI (match_dup 0) 0) @@ -387,7 +389,7 @@ (match_dup 2))) (set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 0) 0) + (ltu:SI (subreg:SI (match_dup 0) 0) (match_dup 2))) (set (subreg:SI (match_dup 0) 1) @@ -410,7 +412,7 @@ (match_dup 2))) (set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 0) 1) + (ltu:SI (subreg:SI (match_dup 0) 1) (match_dup 2))) (set (subreg:SI (match_dup 0) 0) @@ -491,7 +493,7 @@ && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" [(set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 1) 0) + (ltu:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0))) (set (subreg:SI (match_dup 0) 0) @@ -518,7 +520,7 @@ && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" [(set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 1) 1) + (ltu:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1))) (set (subreg:SI (match_dup 0) 1) @@ -559,7 +561,7 @@ && INTVAL (operands[2]) > 0" [(set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 1) 0) + (ltu:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) (set (subreg:SI (match_dup 0) 0) @@ -582,7 +584,7 @@ && INTVAL (operands[2]) > 0" [(set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 1) 1) + (ltu:SI (subreg:SI (match_dup 1) 1) (match_dup 2))) (set (subreg:SI (match_dup 0) 1) @@ -760,7 +762,7 @@ (match_dup 2))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] - "optimize && !TARGET_DEBUG_C_MODE" + "optimize" "* { if (find_reg_note (insn, REG_UNUSED, operands[3])) @@ -784,7 +786,7 @@ (match_dup 2))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] - "optimize && !TARGET_DEBUG_C_MODE" + "optimize" "* { if (find_reg_note (insn, REG_UNUSED, operands[3])) @@ -805,7 +807,7 @@ (match_operand:SI 2 "register_operand" "d"))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] - "!optimize || TARGET_DEBUG_C_MODE" + "!optimize" "div\\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "SI") @@ -817,7 +819,7 @@ (match_operand:SI 2 "register_operand" "d"))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] - "!optimize || TARGET_DEBUG_C_MODE" + "!optimize" "rem\\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "SI") @@ -829,7 +831,7 @@ (match_operand:SI 2 "register_operand" "d"))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] - "!optimize || TARGET_DEBUG_C_MODE" + "!optimize" "divu\\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "SI") @@ -841,7 +843,7 @@ (match_operand:SI 2 "register_operand" "d"))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] - "!optimize || TARGET_DEBUG_C_MODE" + "!optimize" "remu\\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "SI") @@ -2629,14 +2631,9 @@ move\\t%0,%z4\\n\\ ;; done, so that we can constrain things appropriately. There ;; are assumptions in the rest of GCC that break if we fold the ;; operands into the branchs for integer operations, and use cc0 -;; for floating point. -;; -;; 3) The compare define_insns then once again set branch_cmp and -;; branch_type, and the branch define_insns use them. -;; -;; 4) If a set condition code is done instead of a branch, then the -;; operands are folded into the RTL, and a separate set of cc0 is -;; not done. This allows slt's to be put into delay slots. +;; for floating point, so we use the fp status register instead. +;; If needed, an appropriate temporary is created to hold the +;; of the integer compare. (define_expand "cmpsi" [(set (cc0) @@ -2669,53 +2666,6 @@ move\\t%0,%z4\\n\\ } }") -(define_insn "cmpsi_eqne" - [(set (cc0) - (compare:CC_EQ (match_operand:SI 0 "register_operand" "dJ") - (match_operand:SI 1 "reg_or_0_operand" "dJ")))] - "" - "* -{ - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SI; - return \"\"; -}" - [(set_attr "type" "icmp") - (set_attr "mode" "none") - (set_attr "length" "0")]) - -(define_insn "cmpsi_zero" - [(set (cc0) - (match_operand:SI 0 "reg_or_0_operand" "dJ"))] - "" - "* -{ - branch_cmp[0] = operands[0]; - branch_cmp[1] = const0_rtx; - branch_type = CMP_SI; - return \"\"; -}" - [(set_attr "type" "icmp") - (set_attr "mode" "none") - (set_attr "length" "0")]) - -(define_insn "cmpsi_relational" - [(set (cc0) - (compare:CC (match_operand:SI 0 "register_operand" "dJ") - (match_operand:SI 1 "arith_operand" "dI")))] - "" - "* -{ - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SI; - return \"\"; -}" - [(set_attr "type" "icmp") - (set_attr "mode" "none") - (set_attr "length" "0")]) - (define_expand "cmpdf" [(set (cc0) (compare:CC_FP (match_operand:DF 0 "register_operand" "") @@ -2732,23 +2682,6 @@ move\\t%0,%z4\\n\\ } }") -(define_insn "cmpdf_internal" - [(set (cc0) - (compare:CC_FP (match_operand:DF 0 "register_operand" "f") - (match_operand:DF 1 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "* -{ - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_DF; - return \"\"; -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "none") - (set_attr "length" "0")]) - - (define_expand "cmpsf" [(set (cc0) (compare:CC_FP (match_operand:SF 0 "register_operand" "") @@ -2765,22 +2698,6 @@ move\\t%0,%z4\\n\\ } }") -(define_insn "cmpsf_internal" - [(set (cc0) - (compare:CC_FP (match_operand:SF 0 "register_operand" "f") - (match_operand:SF 1 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "* -{ - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SF; - return \"\"; -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "none") - (set_attr "length" "0")]) - ;; ;; .................... @@ -2789,224 +2706,163 @@ move\\t%0,%z4\\n\\ ;; ;; .................... -;; We really can't note that integer branches clobber $at, and FP -;; branches clobber $fcr31 because if we use a parallel operation, a -;; normal insn is used to hold the value instead of jump_insn. See -;; above for cmpxx saving the operands in branch_cmp and branch_type. - -(define_insn "branch_fp_true" +(define_insn "branch_fp_ne" [(set (pc) - (if_then_else (match_operator:CC_FP 0 "fcmp_op" [(cc0) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] + (if_then_else (ne:CC_FP (reg:CC_FP 66) + (const_int 0)) + (match_operand 0 "pc_or_label_operand" "") + (match_operand 1 "pc_or_label_operand" "")))] "" "* { - operands[2] = branch_cmp[0]; - operands[3] = branch_cmp[1]; - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - if (branch_type == CMP_DF) - { - switch (GET_CODE (operands[0])) - { - case EQ: return \"c.eq.d\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case NE: return \"c.eq.d\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case LT: return \"c.lt.d\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case LE: return \"c.le.d\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case GT: return \"c.lt.d\\t%3,%2%#\;%*bc1t%?\\t%l1\"; - case GE: return \"c.le.d\\t%3,%2%#\;%*bc1t%?\\t%l1\"; - } - } - - else if (branch_type == CMP_SF) - { - switch (GET_CODE (operands[0])) - { - case EQ: return \"c.eq.s\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case NE: return \"c.eq.s\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case LT: return \"c.lt.s\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case LE: return \"c.le.s\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case GT: return \"c.lt.s\\t%3,%2%#\;%*bc1t%?\\t%l1\"; - case GE: return \"c.le.s\\t%3,%2%#\;%*bc1t%?\\t%l1\"; - } - } - - abort_with_insn (insn, \"Bad floating compare/branch\"); - return (char *)0; + return (operands[0] != pc_rtx) ? \"%*bc1t%?\\t%0\" : \"%*bc1f%?\\t%1\"; }" [(set_attr "type" "branch") (set_attr "mode" "none") - (set_attr "length" "3")]) + (set_attr "length" "1")]) -(define_insn "branch_fp_false" +(define_insn "branch_fp_ne_rev" [(set (pc) - (if_then_else (match_operator:CC_FP 0 "fcmp_op" [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] + (if_then_else (ne:CC_REV_FP (reg:CC_REV_FP 66) + (const_int 0)) + (match_operand 0 "pc_or_label_operand" "") + (match_operand 1 "pc_or_label_operand" "")))] "" "* { - operands[2] = branch_cmp[0]; - operands[3] = branch_cmp[1]; - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - if (branch_type == CMP_DF) - { - switch (GET_CODE (operands[0])) - { - case EQ: return \"c.eq.d\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case NE: return \"c.eq.d\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case LT: return \"c.lt.d\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case LE: return \"c.le.d\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case GT: return \"c.lt.d\\t%3,%2%#\;%*bc1f%?\\t%l1\"; - case GE: return \"c.le.d\\t%3,%2%#\;%*bc1f%?\\t%l1\"; - } - } - - else if (branch_type == CMP_SF) - { - switch (GET_CODE (operands[0])) - { - case EQ: return \"c.eq.s\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case NE: return \"c.eq.s\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case LT: return \"c.lt.s\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case LE: return \"c.le.s\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case GT: return \"c.lt.s\\t%3,%2%#\;%*bc1f%?\\t%l1\"; - case GE: return \"c.le.s\\t%3,%2%#\;%*bc1f%?\\t%l1\"; - } - } - - abort_with_insn (insn, \"Bad floating compare/branch\"); - return (char *)0; + return (operands[0] != pc_rtx) ? \"%*bc1f%?\\t%0\" : \"%*bc1t%?\\t%1\"; }" [(set_attr "type" "branch") (set_attr "mode" "none") - (set_attr "length" "3")]) - + (set_attr "length" "1")]) -(define_insn "branch_eqne_true" +(define_insn "branch_fp_eq" [(set (pc) - (if_then_else (match_operator:CC_EQ 0 "equality_op" [(cc0) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] + (if_then_else (eq:CC_FP (reg:CC_FP 66) + (const_int 0)) + (match_operand 0 "pc_or_label_operand" "") + (match_operand 1 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - operands[2] = branch_cmp[0]; - operands[3] = branch_cmp[1]; - return \"%*b%C0%?\\t%z2,%z3,%1\"; + return (operands[0] != pc_rtx) ? \"%*bc1f%?\\t%0\" : \"%*bc1t%?\\t%1\"; }" [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "1")]) -(define_insn "branch_eqne_false" +(define_insn "branch_fp_eq_rev" [(set (pc) - (if_then_else (match_operator:CC_EQ 0 "equality_op" [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] + (if_then_else (eq:CC_REV_FP (reg:CC_REV_FP 66) + (const_int 0)) + (match_operand 0 "pc_or_label_operand" "") + (match_operand 1 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - operands[2] = branch_cmp[0]; - operands[3] = branch_cmp[1]; - return \"%*b%N0%?\\t%z2,%z3,%1\"; + return (operands[0] != pc_rtx) ? \"%*bc1t%?\\t%0\" : \"%*bc1f%?\\t%1\"; }" [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "1")]) -(define_insn "branch_zero_true" + +(define_insn "branch_zero" [(set (pc) - (if_then_else (match_operator:CC_0 0 "cmp_op" [(cc0) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] + (if_then_else (match_operator:SI 0 "cmp_op" + [(match_operand:SI 1 "arith32_operand" "rn") + (const_int 0)]) + (match_operand 2 "pc_or_label_operand" "") + (match_operand 3 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - operands[2] = branch_cmp[0]; - switch (GET_CODE (operands[0])) + /* Handle places where CSE has folded a constant into the register operand. */ + if (GET_CODE (operands[1]) == CONST_INT) { - case EQ: return \"%*beq%?\\t%z2,%.,%1\"; - case NE: return \"%*bne%?\\t%z2,%.,%1\"; - case GTU: return \"%*bne%?\\t%z2,%.,%1\"; - case LEU: return \"%*beq%?\\t%z2,%.,%1\"; - case GEU: return \"%*j\\t%1\"; - case LTU: return \"#%*bltuz\\t%z2,%1\"; + int value = INTVAL (operands[1]); + int truth = 0; + + switch (GET_CODE (operands[0])) + { + default: abort (); + case EQ: truth = (value == 0); break; + case NE: truth = (value != 0); break; + case GT: truth = (value > 0); break; + case GE: truth = (value >= 0); break; + case LT: truth = (value < 0); break; + case LE: truth = (value <= 0); break; + case GTU: truth = (((unsigned)value) > 0); break; + case GEU: truth = 1; break; + case LTU: truth = 0; break; + case LEU: truth = (((unsigned)value) <= 0); break; + } + + if (operands[2] != pc_rtx) + return (truth) ? \"%*j\\t%2\" : \"#bne\\t%z1,%.,%2\"; + else + return (truth) ? \"#bne\\t%z1,%.,%3\" : \"%*j\\t%3\"; } - return \"%*b%C0z%?\\t%z2,%1\"; -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "1")]) + if (operands[2] != pc_rtx) + { /* normal jump */ + switch (GET_CODE (operands[0])) + { + case EQ: return \"%*beq%?\\t%z1,%.,%2\"; + case NE: return \"%*bne%?\\t%z1,%.,%2\"; + case GTU: return \"%*bne%?\\t%z1,%.,%2\"; + case LEU: return \"%*beq%?\\t%z1,%.,%2\"; + case GEU: return \"%*j\\t%2\"; + case LTU: return \"#%*bltuz\\t%z1,%2\"; + } -(define_insn "branch_zero_false" - [(set (pc) - (if_then_else (match_operator:CC_0 0 "cmp_op" [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "" - "* -{ - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - operands[2] = branch_cmp[0]; - switch (GET_CODE (operands[0])) - { - case EQ: return \"%*bne%?\\t%z2,%.,%1\"; - case NE: return \"%*beq%?\\t%z2,%.,%1\"; - case GTU: return \"%*beq%?\\t%z2,%.,%1\"; - case LEU: return \"%*bne\\t%z2,%.,%1\"; - case GEU: return \"#%*bgeuz\\t%z2,%1\"; - case LTU: return \"%*j\\t%1\"; + return \"%*b%C0z%?\\t%z1,%2\"; } + else + { /* inverted jump */ + switch (GET_CODE (operands[0])) + { + case EQ: return \"%*bne%?\\t%z1,%.,%3\"; + case NE: return \"%*beq%?\\t%z1,%.,%3\"; + case GTU: return \"%*beq%?\\t%z1,%.,%3\"; + case LEU: return \"%*bne%?\\t%z1,%.,%3\"; + case GEU: return \"#%*bgeuz\\t%z1,%3\"; + case LTU: return \"%*j\\t%3\"; + } - return \"%*b%N0z%?\\t%z2,%1\"; + return \"%*b%N0z%?\\t%z1,%3\"; + } }" [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "1")]) -(define_insn "branch_relop_true" - [(set (pc) - (if_then_else (match_operator:CC 0 "cmp2_op" [(cc0) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "* -{ - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - operands[2] = branch_cmp[0]; - operands[3] = branch_cmp[1]; - - return \"%&b%C0%?\\t%z2,%z3,%1%!\"; -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "2")]) -(define_insn "branch_relop_false" +(define_insn "branch_equality" [(set (pc) - (if_then_else (match_operator:CC 0 "cmp2_op" [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] + (if_then_else (match_operator:SI 0 "equality_op" + [(match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")]) + (match_operand 3 "pc_or_label_operand" "") + (match_operand 4 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - operands[2] = branch_cmp[0]; - operands[3] = branch_cmp[1]; - - return \"%&b%N0%?\\t%z2,%z3,%1%!\"; + return (operands[3] != pc_rtx) + ? \"%*b%C0%?\\t%z1,%z2,%3\" + : \"%*b%N0%?\\t%z1,%z2,%4\"; }" [(set_attr "type" "branch") (set_attr "mode" "none") - (set_attr "length" "2")]) + (set_attr "length" "1")]) + (define_expand "beq" [(set (pc) @@ -3179,8 +3035,8 @@ move\\t%0,%z4\\n\\ (define_expand "seq" [(set (match_operand:SI 0 "register_operand" "=d") - (eq:CC_EQ (match_dup 1) - (match_dup 2)))] + (eq:SI (match_dup 1) + (match_dup 2)))] "" " { @@ -3193,43 +3049,59 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (TARGET_DEBUG_C_MODE) + { + gen_int_relational (EQ, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) operands[2] = force_reg (SImode, operands[2]); /* fall through and generate default code */ }") -(define_insn "seq_si" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (eq:CC_EQ (match_operand:SI 1 "register_operand" "%d,d,d") - (match_operand:SI 2 "uns_arith_operand" "J,d,K")))] + +(define_insn "seq_si_zero" + [(set (match_operand:SI 0 "register_operand" "=d") + (eq:SI (match_operand:SI 1 "register_operand" "d") + (const_int 0)))] "" + "sltu\\t%0,%1,1" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "1")]) + +(define_insn "seq_si" + [(set (match_operand:SI 0 "register_operand" "=d,d") + (eq:SI (match_operand:SI 1 "register_operand" "%d,d") + (match_operand:SI 2 "uns_arith_operand" "d,K")))] + "!TARGET_DEBUG_C_MODE" "@ - sltu\\t%0,%1,1 xor\\t%0,%1,%2\;sltu\\t%0,%0,1 - xori\\t%0,%1,%x2\;sltu\\t%0,%0,1" - [(set_attr "type" "arith,arith,arith") - (set_attr "mode" "SI,SI,SI") - (set_attr "length" "1,2,2")]) + xori\\t%0,%1,%2\;sltu\\t%0,%0,1" + [(set_attr "type" "arith,arith") + (set_attr "mode" "SI,SI") + (set_attr "length" "2,2")]) (define_split [(set (match_operand:SI 0 "register_operand" "") - (eq:CC_EQ (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "uns_arith_operand" "")))] - "!TARGET_DEBUG_D_MODE + (eq:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "uns_arith_operand" "")))] + "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)" [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) - (ltu:CC (match_dup 0) + (ltu:SI (match_dup 0) (const_int 1)))] "") (define_expand "sne" [(set (match_operand:SI 0 "register_operand" "=d") - (ne:CC_EQ (match_dup 1) - (match_dup 2)))] + (ne:SI (match_dup 1) + (match_dup 2)))] "" " { @@ -3242,48 +3114,57 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (TARGET_DEBUG_C_MODE) + { + gen_int_relational (NE, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) operands[2] = force_reg (SImode, operands[2]); /* fall through and generate default code */ }") -(define_insn "sne_si" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (ne:CC_EQ (match_operand:SI 1 "register_operand" "%d,d,d") - (match_operand:SI 2 "uns_arith_operand" "J,d,K")))] +(define_insn "sne_si_zero" + [(set (match_operand:SI 0 "register_operand" "=d") + (ne:SI (match_operand:SI 1 "register_operand" "d") + (const_int 0)))] "" - "* -{ - if (GET_CODE (operands[2]) != CONST_INT) - return \"xor\\t%0,%1,%2\;sltu\\t%0,%.,%0\"; - - if (INTVAL (operands[2]) == 0) - return \"sltu\\t%0,%.,%1\"; + "sltu\\t%0,%.,%1" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "1")]) - return \"xori\\t%0,%1,%x2\;sltu\\t%0,%.,%0\"; -}" - [(set_attr "type" "arith,arith,arith") - (set_attr "mode" "SI,SI,SI") - (set_attr "length" "1,2,2")]) +(define_insn "sne_si" + [(set (match_operand:SI 0 "register_operand" "=d,d") + (ne:SI (match_operand:SI 1 "register_operand" "%d,d") + (match_operand:SI 2 "uns_arith_operand" "d,K")))] + "!TARGET_DEBUG_C_MODE" + "@ + xor\\t%0,%1,%2\;sltu\\t%0,%.,%0 + xori\\t%0,%1,%x2\;sltu\\t%0,%.,%0" + [(set_attr "type" "arith,arith") + (set_attr "mode" "SI,SI") + (set_attr "length" "2,2")]) (define_split [(set (match_operand:SI 0 "register_operand" "") - (ne:CC_EQ (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "uns_arith_operand" "")))] - "!TARGET_DEBUG_D_MODE + (ne:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "uns_arith_operand" "")))] + "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)" [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) - (gtu:CC (match_dup 0) + (gtu:SI (match_dup 0) (const_int 0)))] "") (define_expand "sgt" [(set (match_operand:SI 0 "register_operand" "=d") - (gt:CC (match_dup 1) + (gt:SI (match_dup 1) (match_dup 2)))] "" " @@ -3297,6 +3178,12 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (TARGET_DEBUG_C_MODE) + { + gen_int_relational (GT, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0) operands[2] = force_reg (SImode, operands[2]); @@ -3305,7 +3192,7 @@ move\\t%0,%z4\\n\\ (define_insn "sgt_si" [(set (match_operand:SI 0 "register_operand" "=d") - (gt:CC (match_operand:SI 1 "register_operand" "d") + (gt:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "reg_or_0_operand" "dJ")))] "" "slt\\t%0,%z2,%1" @@ -3315,7 +3202,7 @@ move\\t%0,%z4\\n\\ (define_expand "sge" [(set (match_operand:SI 0 "register_operand" "=d") - (ge:CC (match_dup 1) + (ge:SI (match_dup 1) (match_dup 2)))] "" " @@ -3327,14 +3214,20 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (TARGET_DEBUG_C_MODE) + { + gen_int_relational (GE, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + /* fall through and generate default code */ }") (define_insn "sge_si" [(set (match_operand:SI 0 "register_operand" "=d") - (ge:CC (match_operand:SI 1 "register_operand" "d") + (ge:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] - "" + "!TARGET_DEBUG_C_MODE" "slt\\t%0,%1,%2\;xori\\t%0,%0,0x0001" [(set_attr "type" "arith") (set_attr "mode" "SI") @@ -3342,11 +3235,11 @@ move\\t%0,%z4\\n\\ (define_split [(set (match_operand:SI 0 "register_operand" "") - (ge:CC (match_operand:SI 1 "register_operand" "") + (ge:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "arith_operand" "")))] - "!TARGET_DEBUG_D_MODE" + "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE" [(set (match_dup 0) - (lt:CC (match_dup 1) + (lt:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) (xor:SI (match_dup 0) @@ -3355,7 +3248,7 @@ move\\t%0,%z4\\n\\ (define_expand "slt" [(set (match_operand:SI 0 "register_operand" "=d") - (lt:CC (match_dup 1) + (lt:SI (match_dup 1) (match_dup 2)))] "" " @@ -3367,12 +3260,18 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (TARGET_DEBUG_C_MODE) + { + gen_int_relational (LT, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + /* fall through and generate default code */ }") (define_insn "slt_si" [(set (match_operand:SI 0 "register_operand" "=d") - (lt:CC (match_operand:SI 1 "register_operand" "d") + (lt:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "" "slt\\t%0,%1,%2" @@ -3382,7 +3281,7 @@ move\\t%0,%z4\\n\\ (define_expand "sle" [(set (match_operand:SI 0 "register_operand" "=d") - (le:CC (match_dup 1) + (le:SI (match_dup 1) (match_dup 2)))] "" " @@ -3396,31 +3295,49 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (TARGET_DEBUG_C_MODE) + { + gen_int_relational (LE, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767) operands[2] = force_reg (SImode, operands[2]); /* fall through and generate default code */ }") -(define_insn "sle_si" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (le:CC (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "arith_operand" "d,I")))] - "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) < 32767" - "@ - slt\\t%0,%z2,%1\;xori\\t%0,%0,0x0001 - slt\\t%0,%1,(%2+1)" - [(set_attr "type" "arith,arith") - (set_attr "mode" "SI,SI") - (set_attr "length" "2,1")]) +(define_insn "sle_si_const" + [(set (match_operand:SI 0 "register_operand" "=d") + (le:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "small_int" "I")))] + "INTVAL (operands[2]) < 32767" + "* +{ + operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2])+1); + return \"slt\\t%0,%1,%2\"; +}" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "1")]) + +(define_insn "sle_si_reg" + [(set (match_operand:SI 0 "register_operand" "=d") + (le:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")))] + "!TARGET_DEBUG_C_MODE" + "slt\\t%0,%z2,%1\;xori\\t%0,%0,0x0001" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "2")]) (define_split [(set (match_operand:SI 0 "register_operand" "") - (le:CC (match_operand:SI 1 "register_operand" "") + (le:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" "")))] - "!TARGET_DEBUG_D_MODE" + "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE" [(set (match_dup 0) - (lt:CC (match_dup 2) + (lt:SI (match_dup 2) (match_dup 1))) (set (match_dup 0) (xor:SI (match_dup 0) @@ -3429,7 +3346,7 @@ move\\t%0,%z4\\n\\ (define_expand "sgtu" [(set (match_operand:SI 0 "register_operand" "=d") - (gtu:CC (match_dup 1) + (gtu:SI (match_dup 1) (match_dup 2)))] "" " @@ -3443,6 +3360,12 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (TARGET_DEBUG_C_MODE) + { + gen_int_relational (GTU, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0) operands[2] = force_reg (SImode, operands[2]); @@ -3451,7 +3374,7 @@ move\\t%0,%z4\\n\\ (define_insn "sgtu_si" [(set (match_operand:SI 0 "register_operand" "=d") - (gtu:CC (match_operand:SI 1 "register_operand" "d") + (gtu:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "reg_or_0_operand" "dJ")))] "" "sltu\\t%0,%z2,%1" @@ -3461,7 +3384,7 @@ move\\t%0,%z4\\n\\ (define_expand "sgeu" [(set (match_operand:SI 0 "register_operand" "=d") - (geu:CC (match_dup 1) + (geu:SI (match_dup 1) (match_dup 2)))] "" " @@ -3473,14 +3396,20 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (TARGET_DEBUG_C_MODE) + { + gen_int_relational (GEU, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + /* fall through and generate default code */ }") (define_insn "sgeu_si" [(set (match_operand:SI 0 "register_operand" "=d") - (geu:CC (match_operand:SI 1 "register_operand" "d") + (geu:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] - "" + "!TARGET_DEBUG_C_MODE" "sltu\\t%0,%1,%2\;xori\\t%0,%0,0x0001" [(set_attr "type" "arith") (set_attr "mode" "SI") @@ -3488,11 +3417,11 @@ move\\t%0,%z4\\n\\ (define_split [(set (match_operand:SI 0 "register_operand" "") - (geu:CC (match_operand:SI 1 "register_operand" "") + (geu:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "arith_operand" "")))] - "!TARGET_DEBUG_D_MODE" + "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE" [(set (match_dup 0) - (ltu:CC (match_dup 1) + (ltu:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) (xor:SI (match_dup 0) @@ -3501,7 +3430,7 @@ move\\t%0,%z4\\n\\ (define_expand "sltu" [(set (match_operand:SI 0 "register_operand" "=d") - (ltu:CC (match_dup 1) + (ltu:SI (match_dup 1) (match_dup 2)))] "" " @@ -3513,12 +3442,18 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (TARGET_DEBUG_C_MODE) + { + gen_int_relational (LTU, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + /* fall through and generate default code */ }") (define_insn "sltu_si" [(set (match_operand:SI 0 "register_operand" "=d") - (ltu:CC (match_operand:SI 1 "register_operand" "d") + (ltu:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "" "sltu\\t%0,%1,%2" @@ -3528,7 +3463,7 @@ move\\t%0,%z4\\n\\ (define_expand "sleu" [(set (match_operand:SI 0 "register_operand" "=d") - (leu:CC (match_dup 1) + (leu:SI (match_dup 1) (match_dup 2)))] "" " @@ -3542,31 +3477,49 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (TARGET_DEBUG_C_MODE) + { + gen_int_relational (LEU, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767) operands[2] = force_reg (SImode, operands[2]); /* fall through and generate default code */ }") -(define_insn "sleu_si" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (leu:CC (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "arith_operand" "d,I")))] - "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) < 32767" - "@ - sltu\\t%0,%z2,%1\;xori\\t%0,%0,0x0001 - sltu\\t%0,%1,(%2+1)" - [(set_attr "type" "arith,arith") - (set_attr "mode" "SI,SI") - (set_attr "length" "2,1")]) +(define_insn "sleu_si_const" + [(set (match_operand:SI 0 "register_operand" "=d") + (leu:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "small_int" "I")))] + "INTVAL (operands[2]) < 32767" + "* +{ + operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2])+1); + return \"sltu\\t%0,%1,%2\"; +}" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "1")]) + +(define_insn "sleu_si_reg" + [(set (match_operand:SI 0 "register_operand" "=d") + (leu:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")))] + "!TARGET_DEBUG_C_MODE" + "sltu\\t%0,%z2,%1\;xori\\t%0,%0,0x0001" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "2")]) (define_split [(set (match_operand:SI 0 "register_operand" "") - (leu:CC (match_operand:SI 1 "register_operand" "") + (leu:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" "")))] - "!TARGET_DEBUG_D_MODE" + "!TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE" [(set (match_dup 0) - (ltu:CC (match_dup 2) + (ltu:SI (match_dup 2) (match_dup 1))) (set (match_dup 0) (xor:SI (match_dup 0) @@ -3577,6 +3530,230 @@ move\\t%0,%z4\\n\\ ;; ;; .................... ;; +;; FLOATING POINT COMPARISONS +;; +;; .................... + +(define_insn "seq_df" + [(set (reg:CC_FP 66) + (eq:CC_FP (match_operand:DF 0 "register_operand" "f") + (match_operand:DF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.eq.d\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sne_df" + [(set (reg:CC_REV_FP 66) + (ne:CC_REV_FP (match_operand:DF 0 "register_operand" "f") + (match_operand:DF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.eq.d\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "slt_df" + [(set (reg:CC_FP 66) + (lt:CC_FP (match_operand:DF 0 "register_operand" "f") + (match_operand:DF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.lt.d\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sle_df" + [(set (reg:CC_FP 66) + (le:CC_FP (match_operand:DF 0 "register_operand" "f") + (match_operand:DF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.le.d\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sgt_df" + [(set (reg:CC_FP 66) + (gt:CC_FP (match_operand:DF 0 "register_operand" "f") + (match_operand:DF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.lt.d\\t%1,%0\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sge_df" + [(set (reg:CC_FP 66) + (ge:CC_FP (match_operand:DF 0 "register_operand" "f") + (match_operand:DF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.le.d\\t%1,%0\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "seq_sf" + [(set (reg:CC_FP 66) + (eq:CC_FP (match_operand:SF 0 "register_operand" "f") + (match_operand:SF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.eq.s\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sne_sf" + [(set (reg:CC_REV_FP 66) + (ne:CC_REV_FP (match_operand:SF 0 "register_operand" "f") + (match_operand:SF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.eq.s\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "slt_sf" + [(set (reg:CC_FP 66) + (lt:CC_FP (match_operand:SF 0 "register_operand" "f") + (match_operand:SF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.lt.s\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sle_sf" + [(set (reg:CC_FP 66) + (le:CC_FP (match_operand:SF 0 "register_operand" "f") + (match_operand:SF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.le.s\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sgt_sf" + [(set (reg:CC_FP 66) + (gt:CC_FP (match_operand:SF 0 "register_operand" "f") + (match_operand:SF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.lt.s\\t%1,%0\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sge_sf" + [(set (reg:CC_FP 66) + (ge:CC_FP (match_operand:SF 0 "register_operand" "f") + (match_operand:SF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.le.s\\t%1,%0\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + + +;; +;; .................... +;; ;; UNCONDITIONAL BRANCHES ;; ;; .................... |