aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@redhat.com>2002-07-17 09:24:08 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2002-07-17 09:24:08 +0000
commit8214bf98d2177d333ce6ac401789b444ccf43658 (patch)
treed6efa314e85f244662bb350a1403c5f41878c06b
parent5fc5be15222493c4325d413f5abe7026b5038e63 (diff)
downloadgcc-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/ChangeLog37
-rw-r--r--gcc/config/mips/mips-protos.h1
-rw-r--r--gcc/config/mips/mips.c132
-rw-r--r--gcc/config/mips/mips.h23
-rw-r--r--gcc/config/mips/mips.md321
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"))]