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
This commit is contained in:
Richard Sandiford 2002-07-17 09:24:08 +00:00 committed by Richard Sandiford
parent 5fc5be1522
commit 8214bf98d2
5 changed files with 264 additions and 254 deletions

View File

@ -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

View File

@ -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,

View File

@ -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)

View File

@ -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 }}, \

View File

@ -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 (!ISA_HAS_TRUNC_W)
{
emit_insn (gen_fix_truncdfsi2_macro (operands[0], operands[1]));
DONE;
}
})
if (which_alternative == 1)
return \"trunc.w.d %0,%1,%2\";
output_asm_insn (\"trunc.w.d %3,%1,%2\", operands);
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_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"))]
"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);
xoperands[0] = operands[0];
xoperands[1] = operands[3];
output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands);
return \"\";
}"
(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" "SF")
(set_attr "length" "44,36,40,44")])
(set_attr "mode" "DF")
(set_attr "length" "36")])
(define_expand "fix_truncsfsi2"
[(set (match_operand:SI 0 "register_operand" "=f")
(fix:SI (match_operand:SF 1 "register_operand" "f")))]
"TARGET_HARD_FLOAT"
{
if (!ISA_HAS_TRUNC_W)
{
emit_insn (gen_fix_truncsfsi2_macro (operands[0], operands[1]));
DONE;
}
})
(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" "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
(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,move,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,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,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
&& (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 "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"))]