diff options
author | Richard Sandiford <rsandifo@redhat.com> | 2002-07-17 09:24:08 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2002-07-17 09:24:08 +0000 |
commit | 8214bf98d2177d333ce6ac401789b444ccf43658 (patch) | |
tree | d6efa314e85f244662bb350a1403c5f41878c06b | |
parent | 5fc5be15222493c4325d413f5abe7026b5038e63 (diff) | |
download | gcc-8214bf98d2177d333ce6ac401789b444ccf43658.zip gcc-8214bf98d2177d333ce6ac401789b444ccf43658.tar.gz gcc-8214bf98d2177d333ce6ac401789b444ccf43658.tar.bz2 |
mips-protos.h (mips_sign_extend): Declare.
* config/mips/mips-protos.h (mips_sign_extend): Declare.
* config/mips/mips.h (MASK_DEBUG_H, TARGET_DEBUG_H_MODE): Remove.
(TARGET_SWITCHES): Remove debugh.
(ISA_HAS_TRUNC_W): New macro.
(CLASS_CANNOT_CHANGE_MODE): Include FP_REGS if TARGET_FLOAT64.
(PREDICATE_CODES): Remove se_nonimmediate_operand.
* config/mips/mips.c (movdi_operand): Allow sign-extensions of
any SImode move_operand.
(se_nonimmediate_operand): Remove.
(mips_sign_extend): New.
(mips_move_2words): Use it for sign-extended source operands.
(override_options): Allow integers to be put into single FPRs.
(mips_secondary_reload_class): Handle integers in float registers.
* config/mips/mips.md (extendsidi2): Turn into a define_expand.
(fix_truncsfsi2, fix_truncdfsi2): Likewise.
(fix_truncdfsi2_insn, fix_truncdfsi2_macro): New.
(fix_truncsfsi2_insn, fix_truncsfsi2_macro): New.
(fix_truncdfdi2): Provide only a single alternative, in which the
integer is in a float register. Depend on TARGET_FLOAT64 rather
than TARGET_64BIT.
(fix_truncsfdi2, floatdidf2, floatdisf2): Likewise.
(floatsidf2, floatsisf2): Likewise, but no TARGET_FLOAT64 dependency.
(movdi_internal2): Don't allow the source operand to be sign-extended.
Add alternatives for float registers.
(*movdi_internal2_extend): New. Version of movdi_internal2 that
allows sign-extension.
(*movdi_internal2_mips16): Name the existing mips16 movdi pattern.
(movsi_internal2): Rename to movsi_internal. Add alternatives for
float registers. Remove TARGET_DEBUG_H_MODE test.
(movhi_internal1): Rename to movhi_internal. Don't check
TARGET_DEBUG_H_MODE. Fix transposed *d and *f source constraints.
(movqi_internal1): Rename to movqi_internal and remove
TARGET_DEBUG_H_MODE dependency.
(movsi_internal1, movhi_internal2, movqi_internal2): Remove.
From-SVN: r55514
-rw-r--r-- | gcc/ChangeLog | 37 | ||||
-rw-r--r-- | gcc/config/mips/mips-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 132 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 23 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 321 |
5 files changed, 262 insertions, 252 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b3db910..b23d59d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,40 @@ +2002-07-17 Richard Sandiford <rsandifo@redhat.com> + + * config/mips/mips-protos.h (mips_sign_extend): Declare. + * config/mips/mips.h (MASK_DEBUG_H, TARGET_DEBUG_H_MODE): Remove. + (TARGET_SWITCHES): Remove debugh. + (ISA_HAS_TRUNC_W): New macro. + (CLASS_CANNOT_CHANGE_MODE): Include FP_REGS if TARGET_FLOAT64. + (PREDICATE_CODES): Remove se_nonimmediate_operand. + * config/mips/mips.c (movdi_operand): Allow sign-extensions of + any SImode move_operand. + (se_nonimmediate_operand): Remove. + (mips_sign_extend): New. + (mips_move_2words): Use it for sign-extended source operands. + (override_options): Allow integers to be put into single FPRs. + (mips_secondary_reload_class): Handle integers in float registers. + * config/mips/mips.md (extendsidi2): Turn into a define_expand. + (fix_truncsfsi2, fix_truncdfsi2): Likewise. + (fix_truncdfsi2_insn, fix_truncdfsi2_macro): New. + (fix_truncsfsi2_insn, fix_truncsfsi2_macro): New. + (fix_truncdfdi2): Provide only a single alternative, in which the + integer is in a float register. Depend on TARGET_FLOAT64 rather + than TARGET_64BIT. + (fix_truncsfdi2, floatdidf2, floatdisf2): Likewise. + (floatsidf2, floatsisf2): Likewise, but no TARGET_FLOAT64 dependency. + (movdi_internal2): Don't allow the source operand to be sign-extended. + Add alternatives for float registers. + (*movdi_internal2_extend): New. Version of movdi_internal2 that + allows sign-extension. + (*movdi_internal2_mips16): Name the existing mips16 movdi pattern. + (movsi_internal2): Rename to movsi_internal. Add alternatives for + float registers. Remove TARGET_DEBUG_H_MODE test. + (movhi_internal1): Rename to movhi_internal. Don't check + TARGET_DEBUG_H_MODE. Fix transposed *d and *f source constraints. + (movqi_internal1): Rename to movqi_internal and remove + TARGET_DEBUG_H_MODE dependency. + (movsi_internal1, movhi_internal2, movqi_internal2): Remove. + 2002-07-16 Jim Wilson <wilson@redhat.com> * toplev.c (lang_dependent_init): Create function context for diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 0b585a5..01bd254 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -98,6 +98,7 @@ extern const char *mips_fill_delay_slot PARAMS ((const char *, rtx)); extern const char *mips_move_1word PARAMS ((rtx *, rtx, int)); extern const char *mips_move_2words PARAMS ((rtx *, rtx)); +extern const char *mips_sign_extend PARAMS ((rtx, rtx, rtx)); extern const char *mips_emit_prefetch PARAMS ((rtx *)); extern const char *mips_restore_gp PARAMS ((rtx *, rtx)); extern const char *output_block_move PARAMS ((rtx, rtx *, int, diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 64c458f..56225f4 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -1200,9 +1200,11 @@ move_operand (op, mode) /* Return nonzero if OPERAND is valid as a source operand for movdi. This accepts not only general_operand, but also sign extended - constants and registers. We need to accept sign extended constants + move_operands. Note that we need to accept sign extended constants in case a sign extended register which is used in an expression, - and is equivalent to a constant, is spilled. */ + and is equivalent to a constant, is spilled. We need to accept + sign-extended memory in order to reload registers from stack slots, + and so that we generate efficient code for extendsidi2. */ int movdi_operand (op, mode) @@ -1213,11 +1215,7 @@ movdi_operand (op, mode) && mode == DImode && GET_CODE (op) == SIGN_EXTEND && GET_MODE (op) == DImode - && (GET_MODE (XEXP (op, 0)) == SImode - || (GET_CODE (XEXP (op, 0)) == CONST_INT - && GET_MODE (XEXP (op, 0)) == VOIDmode)) - && (register_operand (XEXP (op, 0), SImode) - || immediate_operand (XEXP (op, 0), SImode))) + && move_operand (XEXP (op, 0), SImode)) return 1; return (general_operand (op, mode) @@ -1326,26 +1324,6 @@ se_nonmemory_operand (op, mode) return nonmemory_operand (op, mode); } -/* Like nonimmediate_operand, but when in 64 bit mode also accept a - sign extend of a 32 bit register, since the value is known to be - already sign extended. */ - -int -se_nonimmediate_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (TARGET_64BIT - && mode == DImode - && GET_CODE (op) == SIGN_EXTEND - && GET_MODE (op) == DImode - && GET_MODE (XEXP (op, 0)) == SImode - && register_operand (XEXP (op, 0), SImode)) - return 1; - - return nonimmediate_operand (op, mode); -} - /* Accept any operand that can appear in a mips16 constant table instruction. We can't use any of the standard operand functions because for these instructions we accept values that are not @@ -2464,6 +2442,33 @@ mips_restore_gp (operands, insn) return mips_move_1word (operands, insn, 0); } +/* Return an instruction to sign-extend SImode value SRC and store it + in DImode value DEST. INSN is the original extendsidi2-type insn. */ + +const char * +mips_sign_extend (insn, dest, src) + rtx insn, dest, src; +{ + rtx operands[MAX_RECOG_OPERANDS]; + + if ((register_operand (src, SImode) && FP_REG_P (true_regnum (src))) + || memory_operand (src, SImode)) + { + /* If the source is a floating-point register, we need to use a + 32-bit move, since the float register is not kept sign-extended. + If the source is in memory, we need a 32-bit load. */ + operands[0] = gen_lowpart_SUBREG (SImode, dest); + operands[1] = src; + return mips_move_1word (operands, insn, false); + } + else + { + operands[0] = dest; + operands[1] = src; + return mips_move_2words (operands, insn); + } +} + /* Return the appropriate instructions to move 2 words */ const char * @@ -2480,6 +2485,9 @@ mips_move_2words (operands, insn) int subreg_offset1 = 0; enum delay_type delay = DELAY_NONE; + if (code1 == SIGN_EXTEND) + return mips_sign_extend (insn, op0, XEXP (op1, 0)); + while (code0 == SUBREG) { subreg_offset0 += subreg_regno_offset (REGNO (SUBREG_REG (op0)), @@ -2490,12 +2498,6 @@ mips_move_2words (operands, insn) code0 = GET_CODE (op0); } - if (code1 == SIGN_EXTEND) - { - op1 = XEXP (op1, 0); - code1 = GET_CODE (op1); - } - while (code1 == SUBREG) { subreg_offset1 += subreg_regno_offset (REGNO (SUBREG_REG (op1)), @@ -2506,17 +2508,6 @@ mips_move_2words (operands, insn) code1 = GET_CODE (op1); } - /* Sanity check. */ - if (GET_CODE (operands[1]) == SIGN_EXTEND - && code1 != REG - && code1 != CONST_INT - /* The following three can happen as the result of a questionable - cast. */ - && code1 != LABEL_REF - && code1 != SYMBOL_REF - && code1 != CONST) - abort (); - if (code0 == REG) { int regno0 = REGNO (op0) + subreg_offset0; @@ -5406,10 +5397,12 @@ override_options () the value, not about whether math works on the register. */ || (mips_abi == ABI_MEABI && size <= 4)) - && (class == MODE_FLOAT - || class == MODE_COMPLEX_FLOAT - || (TARGET_DEBUG_H_MODE && class == MODE_INT)) - && size <= UNITS_PER_FPVALUE); + && (((class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) + && size <= UNITS_PER_FPVALUE) + /* Allow integer modes that fit into a single + register. We need to put integers into FPRs + when using instructions like cvt and trunc. */ + || (class == MODE_INT && size <= UNITS_PER_FPREG))); else if (MD_REG_P (regno)) temp = (class == MODE_INT @@ -8319,6 +8312,18 @@ mips_secondary_reload_class (class, mode, x, in_p) if (GET_CODE (x) == REG) regno = REGNO (x) + off; } + + /* 64-bit floating-point registers don't store 32-bit values + in sign-extended form. The only way we can reload + (sign_extend:DI (reg:SI $f0)) is by moving $f0 into + an integer register using a 32-bit move. */ + if (FP_REG_P (regno)) + return (class == GR_REGS ? NO_REGS : GR_REGS); + + /* For the same reason, we can only reload (sign_extend:DI FOO) into + a floating-point register when FOO is an integer register. */ + if (class == FP_REGS) + return (GP_REG_P (regno) ? NO_REGS : GR_REGS); } else if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG) @@ -8378,6 +8383,37 @@ mips_secondary_reload_class (class, mode, x, in_p) return class == GR_REGS ? NO_REGS : GR_REGS; } + if (class == FP_REGS) + { + if (GET_CODE (x) == MEM) + { + /* In this case we can use lwc1, swc1, ldc1 or sdc1. */ + return NO_REGS; + } + else if (CONSTANT_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT) + { + /* We can use the l.s and l.d macros to load floating-point + constants. ??? For l.s, we could probably get better + code by returning GR_REGS here. */ + return NO_REGS; + } + else if (GP_REG_P (regno) || x == CONST0_RTX (mode)) + { + /* In this case we can use mtc1, mfc1, dmtc1 or dmfc1. */ + return NO_REGS; + } + else if (FP_REG_P (regno)) + { + /* In this case we can use mov.s or mov.d. */ + return NO_REGS; + } + else + { + /* Otherwise, we need to reload through an integer register. */ + return GR_REGS; + } + } + /* In mips16 mode, going between memory and anything but M16_REGS requires an M16_REG. */ if (TARGET_MIPS16) diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 309ea45..238f2b7 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -225,7 +225,6 @@ extern void sbss_section PARAMS ((void)); #define MASK_DEBUG_E 0 /* function_arg debug */ #define MASK_DEBUG_F 0 /* ??? */ #define MASK_DEBUG_G 0 /* don't support 64 bit arithmetic */ -#define MASK_DEBUG_H 0 /* allow ints in FP registers */ #define MASK_DEBUG_I 0 /* unused */ /* Dummy switches used only in specs */ @@ -253,7 +252,6 @@ extern void sbss_section PARAMS ((void)); #define TARGET_DEBUG_E_MODE (target_flags & MASK_DEBUG_E) #define TARGET_DEBUG_F_MODE (target_flags & MASK_DEBUG_F) #define TARGET_DEBUG_G_MODE (target_flags & MASK_DEBUG_G) -#define TARGET_DEBUG_H_MODE (target_flags & MASK_DEBUG_H) #define TARGET_DEBUG_I_MODE (target_flags & MASK_DEBUG_I) /* Reg. Naming in .s ($21 vs. $a0) */ @@ -585,8 +583,6 @@ extern void sbss_section PARAMS ((void)); NULL}, \ {"debugg", MASK_DEBUG_G, \ NULL}, \ - {"debugh", MASK_DEBUG_H, \ - NULL}, \ {"debugi", MASK_DEBUG_I, \ NULL}, \ {"", (TARGET_DEFAULT \ @@ -783,6 +779,11 @@ extern void sbss_section PARAMS ((void)); || ISA_MIPS64) \ && !TARGET_MIPS16) +/* True if trunc.w.s and trunc.w.d are real (not synthetic) + instructions. Both require TARGET_HARD_FLOAT, and trunc.w.d + also requires TARGET_DOUBLE_FLOAT. */ +#define ISA_HAS_TRUNC_W (!ISA_MIPS1) + /* CC1_SPEC causes -mips3 and -mips4 to set -mfp64 and -mgp64; -mips1 or -mips2 sets -mfp32 and -mgp32. This can be overridden by an explicit -mfp32, -mfp64, -mgp32 or -mgp64. -mfp64 sets MASK_FLOAT64 in @@ -2243,17 +2244,20 @@ extern enum reg_class mips_char_to_class[256]; /* If defined, gives a class of registers that cannot be used as the operand of a SUBREG that changes the mode of the object illegally. - When FP regs are larger than integer regs... Er, anyone remember what - goes wrong? In little-endian mode, the hi-lo registers are numbered backwards, so (subreg:SI (reg:DI hi) 0) gets the high word instead of the low - word as intended. */ + word as intended. + + Also, loading a 32-bit value into a 64-bit floating-point register + will not sign-extend the value, despite what LOAD_EXTEND_OP says. + We can't allow 64-bit float registers to change from a 32-bit + mode to a 64-bit mode. */ #define CLASS_CANNOT_CHANGE_MODE \ (TARGET_BIG_ENDIAN \ - ? (TARGET_FLOAT64 && ! TARGET_64BIT ? FP_REGS : NO_REGS) \ - : (TARGET_FLOAT64 && ! TARGET_64BIT ? HI_AND_FP_REGS : HI_REG)) + ? (TARGET_FLOAT64 ? FP_REGS : NO_REGS) \ + : (TARGET_FLOAT64 ? HI_AND_FP_REGS : HI_REG)) /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */ @@ -3677,7 +3681,6 @@ typedef struct mips_args { {"se_nonmemory_operand", { CONST_INT, CONST_DOUBLE, CONST, \ SYMBOL_REF, LABEL_REF, SUBREG, \ REG, SIGN_EXTEND }}, \ - {"se_nonimmediate_operand", { SUBREG, REG, MEM, SIGN_EXTEND }}, \ {"consttable_operand", { LABEL_REF, SYMBOL_REF, CONST_INT, \ CONST_DOUBLE, CONST }}, \ {"extend_operator", { SIGN_EXTEND, ZERO_EXTEND }}, \ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 1205e52..c832878 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -4122,16 +4122,14 @@ move\\t%0,%z4\\n\\ ;; In 64 bit mode, 32 bit values in general registers are always ;; correctly sign extended. That means that if the target is a ;; general register, we can sign extend from SImode to DImode just by -;; doing a move. +;; doing a move. The matching define_insns are *movdi_internal2_extend +;; and *movdi_internal2_mips16. -(define_insn "extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=d,y,d,*d,d,d") - (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,d,y,*x,R,m")))] +(define_expand "extendsidi2" + [(set (match_operand:DI 0 "register_operand" "") + (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))] "TARGET_64BIT" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "move,move,move,hilo,load,load") - (set_attr "mode" "DI") - (set_attr "length" "4,4,4,4,4,8")]) + "") ;; These patterns originally accepted general_operands, however, slightly ;; better code is generated by only accepting register_operands, and then @@ -4307,65 +4305,67 @@ move\\t%0,%z4\\n\\ ;; ;; .................... -;; The SImode scratch register can not be shared with address regs used for -;; operand zero, because then the address in the move instruction will be -;; clobbered. We mark the scratch register as early clobbered to prevent this. - -;; We need the ?X in alternative 1 so that it will be chosen only if the -;; destination is a floating point register. Otherwise, alternative 1 can -;; have lower cost than alternative 0 (because there is one less loser), and -;; can be chosen when it won't work (because integral reloads into FP -;; registers are not supported). - -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,*f,R,To") - (fix:SI (match_operand:DF 1 "register_operand" "f,*f,f,f"))) - (clobber (match_scratch:SI 2 "=d,*d,&d,&d")) - (clobber (match_scratch:DF 3 "=f,?*X,f,f"))] +(define_expand "fix_truncdfsi2" + [(set (match_operand:SI 0 "register_operand" "=f") + (fix:SI (match_operand:DF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "* { - rtx xoperands[10]; - - if (which_alternative == 1) - return \"trunc.w.d %0,%1,%2\"; - - output_asm_insn (\"trunc.w.d %3,%1,%2\", operands); + if (!ISA_HAS_TRUNC_W) + { + emit_insn (gen_fix_truncdfsi2_macro (operands[0], operands[1])); + DONE; + } +}) - xoperands[0] = operands[0]; - xoperands[1] = operands[3]; - output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); - return \"\"; -}" +(define_insn "fix_truncdfsi2_insn" + [(set (match_operand:SI 0 "register_operand" "=f") + (fix:SI (match_operand:DF 1 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && ISA_HAS_TRUNC_W" + "trunc.w.d %0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "DF") - (set_attr "length" "44,36,40,44")]) - + (set_attr "length" "4")]) + +(define_insn "fix_truncdfsi2_macro" + [(set (match_operand:SI 0 "register_operand" "=f") + (fix:SI (match_operand:DF 1 "register_operand" "f"))) + (clobber (match_scratch:DF 2 "=d"))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !ISA_HAS_TRUNC_W" + "trunc.w.d %0,%1,%2" + [(set_attr "type" "fcvt") + (set_attr "mode" "DF") + (set_attr "length" "36")]) -(define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,*f,R,To") - (fix:SI (match_operand:SF 1 "register_operand" "f,*f,f,f"))) - (clobber (match_scratch:SI 2 "=d,*d,&d,&d")) - (clobber (match_scratch:SF 3 "=f,?*X,f,f"))] +(define_expand "fix_truncsfsi2" + [(set (match_operand:SI 0 "register_operand" "=f") + (fix:SI (match_operand:SF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT" - "* { - rtx xoperands[10]; - - if (which_alternative == 1) - return \"trunc.w.s %0,%1,%2\"; - - output_asm_insn (\"trunc.w.s %3,%1,%2\", operands); + if (!ISA_HAS_TRUNC_W) + { + emit_insn (gen_fix_truncsfsi2_macro (operands[0], operands[1])); + DONE; + } +}) - xoperands[0] = operands[0]; - xoperands[1] = operands[3]; - output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); - return \"\"; -}" +(define_insn "fix_truncsfsi2_insn" + [(set (match_operand:SI 0 "register_operand" "=f") + (fix:SI (match_operand:SF 1 "register_operand" "f")))] + "TARGET_HARD_FLOAT && ISA_HAS_TRUNC_W" + "trunc.w.s %0,%1" [(set_attr "type" "fcvt") - (set_attr "mode" "SF") - (set_attr "length" "44,36,40,44")]) - + (set_attr "mode" "DF") + (set_attr "length" "4")]) + +(define_insn "fix_truncsfsi2_macro" + [(set (match_operand:SI 0 "register_operand" "=f") + (fix:SI (match_operand:SF 1 "register_operand" "f"))) + (clobber (match_scratch:SF 2 "=d"))] + "TARGET_HARD_FLOAT && !ISA_HAS_TRUNC_W" + "trunc.w.s %0,%1,%2" + [(set_attr "type" "fcvt") + (set_attr "mode" "DF") + (set_attr "length" "36")]) ;;; ??? trunc.l.d is mentioned in the appendix of the 1993 r4000/r4600 manuals ;;; but not in the chapter that describes the FPU. It is not mentioned at all @@ -4377,122 +4377,66 @@ move\\t%0,%z4\\n\\ ;;; If this is disabled, then fixuns_truncdfdi2 must be disabled also. (define_insn "fix_truncdfdi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,*f,R,To") - (fix:DI (match_operand:DF 1 "register_operand" "f,*f,f,f"))) - (clobber (match_scratch:DF 2 "=f,?*X,f,f"))] - "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" - "* -{ - rtx xoperands[10]; - - if (which_alternative == 1) - return \"trunc.l.d %0,%1\"; - - output_asm_insn (\"trunc.l.d %2,%1\", operands); - - xoperands[0] = operands[0]; - xoperands[1] = operands[2]; - output_asm_insn (mips_move_2words (xoperands, insn), xoperands); - return \"\"; -}" + [(set (match_operand:DI 0 "register_operand" "=f") + (fix:DI (match_operand:DF 1 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" + "trunc.l.d %0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "DF") - (set_attr "length" "8,4,8,12")]) + (set_attr "length" "4")]) ;;; ??? trunc.l.s is mentioned in the appendix of the 1993 r4000/r4600 manuals ;;; but not in the chapter that describes the FPU. It is not mentioned at all ;;; in the 1991 manuals. The r4000 at Cygnus does not have this instruction. (define_insn "fix_truncsfdi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,*f,R,To") - (fix:DI (match_operand:SF 1 "register_operand" "f,*f,f,f"))) - (clobber (match_scratch:DF 2 "=f,?*X,f,f"))] - "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" - "* -{ - rtx xoperands[10]; - - if (which_alternative == 1) - return \"trunc.l.s %0,%1\"; - - output_asm_insn (\"trunc.l.s %2,%1\", operands); - - xoperands[0] = operands[0]; - xoperands[1] = operands[2]; - output_asm_insn (mips_move_2words (xoperands, insn), xoperands); - return \"\"; -}" + [(set (match_operand:DI 0 "register_operand" "=f") + (fix:DI (match_operand:SF 1 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" + "trunc.l.s %0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "SF") - (set_attr "length" "8,4,8,12")]) + (set_attr "length" "4")]) (define_insn "floatsidf2" - [(set (match_operand:DF 0 "register_operand" "=f,f,f") - (float:DF (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))] + [(set (match_operand:DF 0 "register_operand" "=f") + (float:DF (match_operand:SI 1 "register_operand" "f")))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "* -{ - dslots_load_total++; - if (GET_CODE (operands[1]) == MEM) - return \"l.s\\t%0,%1%#\;cvt.d.w\\t%0,%0\"; - - return \"mtc1\\t%1,%0%#\;cvt.d.w\\t%0,%0\"; -}" + "cvt.d.w\\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "DF") - (set_attr "length" "12,16,12")]) + (set_attr "length" "4")]) (define_insn "floatdidf2" - [(set (match_operand:DF 0 "register_operand" "=f,f,f") - (float:DF (match_operand:DI 1 "se_nonimmediate_operand" "d,R,m")))] - "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" - "* -{ - dslots_load_total++; - if (GET_CODE (operands[1]) == MEM) - return \"l.d\\t%0,%1%#\;cvt.d.l\\t%0,%0\"; - - return \"dmtc1\\t%1,%0%#\;cvt.d.l\\t%0,%0\"; -}" + [(set (match_operand:DF 0 "register_operand" "=f") + (float:DF (match_operand:DI 1 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" + "cvt.d.l\\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "DF") - (set_attr "length" "12,16,12")]) + (set_attr "length" "4")]) (define_insn "floatsisf2" - [(set (match_operand:SF 0 "register_operand" "=f,f,f") - (float:SF (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))] + [(set (match_operand:SF 0 "register_operand" "=f") + (float:SF (match_operand:SI 1 "register_operand" "f")))] "TARGET_HARD_FLOAT" - "* -{ - dslots_load_total++; - if (GET_CODE (operands[1]) == MEM) - return \"l.s\\t%0,%1%#\;cvt.s.w\\t%0,%0\"; - - return \"mtc1\\t%1,%0%#\;cvt.s.w\\t%0,%0\"; -}" + "cvt.s.w\\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "SF") - (set_attr "length" "12,16,12")]) + (set_attr "length" "4")]) (define_insn "floatdisf2" - [(set (match_operand:SF 0 "register_operand" "=f,f,f") - (float:SF (match_operand:DI 1 "se_nonimmediate_operand" "d,R,m")))] - "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" - "* -{ - dslots_load_total++; - if (GET_CODE (operands[1]) == MEM) - return \"l.d\\t%0,%1%#\;cvt.s.l\\t%0,%0\"; - - return \"dmtc1\\t%1,%0%#\;cvt.s.l\\t%0,%0\"; -}" + [(set (match_operand:SF 0 "register_operand" "=f") + (float:SF (match_operand:DI 1 "register_operand" "f")))] + "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" + "cvt.s.l\\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "SF") - (set_attr "length" "12,16,12")]) + (set_attr "length" "4")]) (define_expand "fixuns_truncdfsi2" @@ -5140,19 +5084,44 @@ move\\t%0,%z4\\n\\ "") (define_insn "movdi_internal2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m,*x,*d,*x,*a,*B*C*D,*B*C*D,*B*C*D,*d,*m,*R") - (match_operand:DI 1 "movdi_operand" "d,IKL,Mnis,R,m,dJ,dJ,J,*x,*d,*J,*d,*m,*R,*B*C*D,*B*C*D,*B*C*D"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m,*f,*f,*f,*f,*d,*R,*m,*x,*d,*x,*a,*B*C*D,*B*C*D,*B*C*D,*d,*m,*R") + (match_operand:DI 1 "move_operand" "d,IKL,Mnis,R,m,dJ,dJ,*f,*d*J,*R,*m,*f,*f,*f,*J,*x,*d,*J,*d,*m,*R,*B*C*D,*B*C*D,*B*C*D"))] "TARGET_64BIT && !TARGET_MIPS16 && (register_operand (operands[0], DImode) - || se_register_operand (operands[1], DImode) + || register_operand (operands[1], DImode) || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) || operands[1] == CONST0_RTX (DImode))" "* return mips_move_2words (operands, insn); " - [(set_attr "type" "move,arith,arith,load,load,store,store,hilo,hilo,hilo,hilo,xfer,load,load,xfer,store,store") + [(set_attr "type" "move,arith,arith,load,load,store,store,move,xfer,load,load,xfer,store,store,hilo,hilo,hilo,hilo,xfer,load,load,xfer,store,store") (set_attr "mode" "DI") - (set_attr "length" "4,4,8,4,8,4,8,4,4,4,8,8,8,8,8,8,8")]) + (set_attr "length" "4,4,8,4,8,4,8,4,4,4,8,4,4,8,4,4,4,8,8,8,8,8,8,8")]) -(define_insn "" +;; Sign-extended operands are reloaded using this instruction, so the +;; constraints must handle every SImode source operand X and destination +;; register R for which: +;; +;; mips_secondary_reload_class (CLASS_OF (R), DImode, true, +;; gen_rtx_SIGN_EXTEND (DImode, X)) +;; +;; returns NO_REGS. Also handle memory destinations, where allowed. +;; +;; This pattern is essentially a trimmed-down version of movdi_internal2. +;; The main difference is that dJ -> f and f -> d are the only constraints +;; involving float registers. See mips_secondary_reload_class for details. +(define_insn "*movdi_internal2_extend" + [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m,*d,*f,*x,*d,*x,*a,*B*C*D,*B*C*D,*B*C*D,*d,*m,*R") + (sign_extend:DI (match_operand:SI 1 "move_operand" "d,IKL,Mnis,R,m,dJ,dJ,*f,*d*J,*J,*x,*d,*J,*d,*m,*R,*B*C*D,*B*C*D,*B*C*D")))] + "TARGET_64BIT && !TARGET_MIPS16 + && (register_operand (operands[0], DImode) + || register_operand (operands[1], DImode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) + || operands[1] == CONST0_RTX (DImode))" + "* return mips_sign_extend (insn, operands[0], operands[1]);" + [(set_attr "type" "move,arith,arith,load,load,store,store,xfer,xfer,hilo,hilo,hilo,hilo,xfer,load,load,xfer,store,store") + (set_attr "mode" "DI") + (set_attr "length" "4,4,8,4,8,4,8,4,4,4,4,4,8,8,8,8,8,8,8")]) + +(define_insn "*movdi_internal2_mips16" [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,R,m,*d") (match_operand:DI 1 "movdi_operand" "d,d,y,K,N,s,R,m,d,d,*x"))] "TARGET_64BIT && TARGET_MIPS16 @@ -5535,29 +5504,17 @@ move\\t%0,%z4\\n\\ ;; The difference between these two is whether or not ints are allowed ;; in FP registers (off by default, use -mdebugh to enable). -(define_insn "movsi_internal1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m,*d,*f*z,*f,*f,*f,*R,*m,*x,*x,*d,*d,*B*C*D,*B*C*D,*B*C*D,*d,*m,*R") - (match_operand:SI 1 "move_operand" "d,IKL,Mnis,R,m,dJ,dJ,*f*z,*d,*f,*R,*m,*f,*f,J,*d,*x,*a,*d,*m,*R,*B*C*D,*B*C*D,*B*C*D"))] - "TARGET_DEBUG_H_MODE && !TARGET_MIPS16 - && (register_operand (operands[0], SImode) - || register_operand (operands[1], SImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "move,arith,arith,load,load,store,store,xfer,xfer,move,load,load,store,store,hilo,hilo,hilo,hilo,xfer,load,load,xfer,store,store") - (set_attr "mode" "SI") - (set_attr "length" "4,4,8,4,8,4,8,4,4,4,4,8,4,8,4,4,4,4,4,4,8,4,4,8")]) - -(define_insn "movsi_internal2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m,*d,*z,*x,*d,*x,*d,*B*C*D,*B*C*D,*B*C*D,*d,*m,*R") - (match_operand:SI 1 "move_operand" "d,IKL,Mnis,R,m,dJ,dJ,*z,*d,J,*x,*d,*a,*d,*m,*R,*B*C*D,*B*C*D,*B*C*D"))] - "!TARGET_DEBUG_H_MODE && !TARGET_MIPS16 +(define_insn "movsi_internal" + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m,*f,*f,*f,?*f,*d,*R,*m,*d,*z,*x,*d,*x,*d,*B*C*D,*B*C*D,*B*C*D,*d,*m,*R") + (match_operand:SI 1 "move_operand" "d,IKL,Mnis,R,m,dJ,dJ,*f,*d*J,*R,*m,*f,*f,*f,*z,*d,J,*x,*d,*a,*d,*m,*R,*B*C*D,*B*C*D,*B*C*D"))] + "!TARGET_MIPS16 && (register_operand (operands[0], SImode) || register_operand (operands[1], SImode) || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "move,arith,arith,load,load,store,store,xfer,xfer,hilo,hilo,hilo,hilo,xfer,load,load,xfer,store,store") + [(set_attr "type" "move,arith,arith,load,load,store,store,move,xfer,load,load,xfer,store,store,xfer,xfer,hilo,hilo,hilo,hilo,xfer,load,load,xfer,store,store") (set_attr "mode" "SI") - (set_attr "length" "4,4,8,4,8,4,8,4,4,4,4,4,4,4,4,8,4,4,8")]) + (set_attr "length" "4,4,8,4,8,4,8,4,4,4,8,4,4,8,4,4,4,4,4,4,4,4,8,4,4,8")]) ;; This is the mips16 movsi instruction. We accept a small integer as ;; the source if the destination is a GP memory reference. This is @@ -6041,10 +5998,10 @@ move\\t%0,%z4\\n\\ ;; The difference between these two is whether or not ints are allowed ;; in FP registers (off by default, use -mdebugh to enable). -(define_insn "movhi_internal1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f*z,*x,*d") +(define_insn "movhi_internal" + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f*z,*f,*x,*d") (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x"))] - "TARGET_DEBUG_H_MODE && !TARGET_MIPS16 + "!TARGET_MIPS16 && (register_operand (operands[0], HImode) || register_operand (operands[1], HImode) || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" @@ -6053,18 +6010,6 @@ move\\t%0,%z4\\n\\ (set_attr "mode" "HI") (set_attr "length" "4,4,4,8,4,8,4,4,4,4,4")]) -(define_insn "movhi_internal2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d") - (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))] - "!TARGET_DEBUG_H_MODE && !TARGET_MIPS16 - && (register_operand (operands[0], HImode) - || register_operand (operands[1], HImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,hilo,hilo") - (set_attr "mode" "HI") - (set_attr "length" "4,4,4,8,4,8,4,4,4,4")]) - (define_insn "" [(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,R,m,*d") (match_operand:HI 1 "general_operand" "d,d,y,K,N,R,m,d,d,*x"))] @@ -6163,10 +6108,10 @@ move\\t%0,%z4\\n\\ ;; The difference between these two is whether or not ints are allowed ;; in FP registers (off by default, use -mdebugh to enable). -(define_insn "movqi_internal1" +(define_insn "movqi_internal" [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f*z,*f,*x,*d") (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x"))] - "TARGET_DEBUG_H_MODE && !TARGET_MIPS16 + "!TARGET_MIPS16 && (register_operand (operands[0], QImode) || register_operand (operands[1], QImode) || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" @@ -6175,18 +6120,6 @@ move\\t%0,%z4\\n\\ (set_attr "mode" "QI") (set_attr "length" "4,4,4,8,4,8,4,4,4,4,4")]) -(define_insn "movqi_internal2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d") - (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))] - "!TARGET_DEBUG_H_MODE && !TARGET_MIPS16 - && (register_operand (operands[0], QImode) - || register_operand (operands[1], QImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,hilo,hilo") - (set_attr "mode" "QI") - (set_attr "length" "4,4,4,8,4,8,4,4,4,4")]) - (define_insn "" [(set (match_operand:QI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,R,m,*d") (match_operand:QI 1 "general_operand" "d,d,y,K,N,R,m,d,d,*x"))] |