;; 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
;; Contributed by A. Lichnewsky, lich@inria.inria.fr
;; Changes by Michael Meissner, meissner@osf.org
-;; 64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
+;; 64-bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
;; Brendan Eich, brendan@microunity.com.
;; This file is part of GCC.
(UNSPEC_MFHILO 26)
(UNSPEC_TLS_LDM 27)
(UNSPEC_TLS_GET_TP 28)
+ (UNSPEC_MFHC1 31)
+ (UNSPEC_MTHC1 32)
(UNSPEC_ADDRESS_FIRST 100)
(UNSPEC_CVT_PW_PS 205)
(UNSPEC_CVT_PS_PW 206)
(UNSPEC_MULR_PS 207)
+ (UNSPEC_ABS_PS 208)
- (UNSPEC_RSQRT1 208)
- (UNSPEC_RSQRT2 209)
- (UNSPEC_RECIP1 210)
- (UNSPEC_RECIP2 211)
- (UNSPEC_SINGLE_CC 212)
- (UNSPEC_SCC 213)
+ (UNSPEC_RSQRT1 209)
+ (UNSPEC_RSQRT2 210)
+ (UNSPEC_RECIP1 211)
+ (UNSPEC_RECIP2 212)
+ (UNSPEC_SINGLE_CC 213)
+ (UNSPEC_SCC 214)
;; MIPS DSP ASE Revision 0.98 3/24/2005
(UNSPEC_ADDQ 300)
(UNSPEC_MTHLIP 365)
(UNSPEC_WRDSP 366)
(UNSPEC_RDDSP 367)
+
+ ;; MIPS DSP ASE REV 2 Revision 0.02 11/24/2006
+ (UNSPEC_ABSQ_S_QB 400)
+ (UNSPEC_ADDU_PH 401)
+ (UNSPEC_ADDU_S_PH 402)
+ (UNSPEC_ADDUH_QB 403)
+ (UNSPEC_ADDUH_R_QB 404)
+ (UNSPEC_APPEND 405)
+ (UNSPEC_BALIGN 406)
+ (UNSPEC_CMPGDU_EQ_QB 407)
+ (UNSPEC_CMPGDU_LT_QB 408)
+ (UNSPEC_CMPGDU_LE_QB 409)
+ (UNSPEC_DPA_W_PH 410)
+ (UNSPEC_DPS_W_PH 411)
+ (UNSPEC_MADD 412)
+ (UNSPEC_MADDU 413)
+ (UNSPEC_MSUB 414)
+ (UNSPEC_MSUBU 415)
+ (UNSPEC_MUL_PH 416)
+ (UNSPEC_MUL_S_PH 417)
+ (UNSPEC_MULQ_RS_W 418)
+ (UNSPEC_MULQ_S_PH 419)
+ (UNSPEC_MULQ_S_W 420)
+ (UNSPEC_MULSA_W_PH 421)
+ (UNSPEC_MULT 422)
+ (UNSPEC_MULTU 423)
+ (UNSPEC_PRECR_QB_PH 424)
+ (UNSPEC_PRECR_SRA_PH_W 425)
+ (UNSPEC_PRECR_SRA_R_PH_W 426)
+ (UNSPEC_PREPEND 427)
+ (UNSPEC_SHRA_QB 428)
+ (UNSPEC_SHRA_R_QB 429)
+ (UNSPEC_SHRL_PH 430)
+ (UNSPEC_SUBU_PH 431)
+ (UNSPEC_SUBU_S_PH 432)
+ (UNSPEC_SUBUH_QB 433)
+ (UNSPEC_SUBUH_R_QB 434)
+ (UNSPEC_ADDQH_PH 435)
+ (UNSPEC_ADDQH_R_PH 436)
+ (UNSPEC_ADDQH_W 437)
+ (UNSPEC_ADDQH_R_W 438)
+ (UNSPEC_SUBQH_PH 439)
+ (UNSPEC_SUBQH_R_PH 440)
+ (UNSPEC_SUBQH_W 441)
+ (UNSPEC_SUBQH_R_W 442)
+ (UNSPEC_DPAX_W_PH 443)
+ (UNSPEC_DPSX_W_PH 444)
+ (UNSPEC_DPAQX_S_W_PH 445)
+ (UNSPEC_DPAQX_SA_W_PH 446)
+ (UNSPEC_DPSQX_S_W_PH 447)
+ (UNSPEC_DPSQX_SA_W_PH 448)
]
)
;; Attribute describing the processor. This attribute must match exactly
;; with the processor_type enumeration in mips.h.
(define_attr "cpu"
- "r3000,4kc,4kp,5kc,5kf,20kc,24k,24kx,m4k,r3900,r6000,r4000,r4100,r4111,r4120,r4130,r4300,r4600,r4650,r5000,r5400,r5500,r7000,r8000,r9000,sb1,sb1a,sr71000"
+ "r3000,4kc,4kp,5kc,5kf,20kc,24kc,24kf,24kx,m4k,r3900,r6000,r4000,r4100,r4111,r4120,r4130,r4300,r4600,r4650,r5000,r5400,r5500,r7000,r8000,r9000,sb1,sb1a,sr71000"
(const (symbol_ref "mips_tune")))
;; The type of hardware hazard associated with this instruction.
;; These processors have PRId values of 0x00004220 and 0x00004300,
;; respectively.
-(define_expand "mul<mode>3"
- [(set (match_operand:GPR 0 "register_operand")
- (mult:GPR (match_operand:GPR 1 "register_operand")
- (match_operand:GPR 2 "register_operand")))]
+(define_expand "mulsi3"
+ [(set (match_operand:SI 0 "register_operand")
+ (mult:SI (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "register_operand")))]
""
{
- if (GENERATE_MULT3_<MODE>)
- emit_insn (gen_mul<mode>3_mult3 (operands[0], operands[1], operands[2]));
- else if (!TARGET_FIX_R4000)
- emit_insn (gen_mul<mode>3_internal (operands[0], operands[1],
- operands[2]));
+ if (ISA_HAS_MUL3)
+ emit_insn (gen_mulsi3_mult3 (operands[0], operands[1], operands[2]));
+ else if (TARGET_FIX_R4000)
+ emit_insn (gen_mulsi3_r4000 (operands[0], operands[1], operands[2]));
else
- emit_insn (gen_mul<mode>3_r4000 (operands[0], operands[1], operands[2]));
+ emit_insn (gen_mulsi3_internal (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "muldi3"
+ [(set (match_operand:DI 0 "register_operand")
+ (mult:DI (match_operand:DI 1 "register_operand")
+ (match_operand:DI 2 "register_operand")))]
+ "TARGET_64BIT"
+{
+ if (TARGET_FIX_R4000)
+ emit_insn (gen_muldi3_r4000 (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_muldi3_internal (operands[0], operands[1], operands[2]));
DONE;
})
(match_operand:SI 2 "register_operand" "d,d")))
(clobber (match_scratch:SI 3 "=h,h"))
(clobber (match_scratch:SI 4 "=l,X"))]
- "GENERATE_MULT3_SI"
+ "ISA_HAS_MUL3"
{
if (which_alternative == 1)
return "mult\t%1,%2";
- if (TARGET_MAD
- || TARGET_MIPS5400
- || TARGET_MIPS5500
- || TARGET_MIPS7000
- || TARGET_MIPS9000
- || ISA_MIPS32
- || ISA_MIPS32R2
- || ISA_MIPS64)
- return "mul\t%0,%1,%2";
- return "mult\t%0,%1,%2";
+ if (TARGET_MIPS3900)
+ return "mult\t%0,%1,%2";
+ return "mul\t%0,%1,%2";
}
[(set_attr "type" "imul3,imul")
(set_attr "mode" "SI")])
-(define_insn "muldi3_mult3"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (mult:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "register_operand" "d")))
- (clobber (match_scratch:DI 3 "=h"))
- (clobber (match_scratch:DI 4 "=l"))]
- "TARGET_64BIT && GENERATE_MULT3_DI"
- "dmult\t%0,%1,%2"
- [(set_attr "type" "imul3")
- (set_attr "mode" "DI")])
-
;; If a register gets allocated to LO, and we spill to memory, the reload
;; will include a move from LO to a GPR. Merge it into the multiplication
;; if it can set the GPR directly.
(clobber (scratch:SI))])
(set (match_operand:SI 4 "register_operand")
(unspec [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))]
- "GENERATE_MULT3_SI && peep2_reg_dead_p (2, operands[0])"
+ "ISA_HAS_MUL3 && peep2_reg_dead_p (2, operands[0])"
[(parallel
[(set (match_dup 4)
(mult:SI (match_dup 1)
(clobber (match_operand:SI 3 "register_operand"))])
(set (match_operand:SI 4 "register_operand")
(unspec:SI [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))]
- "ISA_HAS_MACC && !GENERATE_MULT3_SI"
+ "ISA_HAS_MACC && !ISA_HAS_MUL3"
[(set (match_dup 0)
(const_int 0))
(parallel
(match_operand:SI 4 "macc_msac_operand"))
(clobber (match_operand:SI 5 "register_operand"))
(clobber (match_dup 1))])]
- "GENERATE_MULT3_SI
+ "ISA_HAS_MUL3
&& true_regnum (operands[1]) == LO_REGNUM
&& peep2_reg_dead_p (2, operands[1])
&& GP_REG_P (true_regnum (operands[3]))"
(match_dup 0)
(set (match_operand:SI 5 "register_operand")
(unspec:SI [(match_dup 1) (match_dup 4)] UNSPEC_MFHILO))]
- "GENERATE_MULT3_SI && peep2_reg_dead_p (3, operands[1])"
+ "ISA_HAS_MUL3 && peep2_reg_dead_p (3, operands[1])"
[(parallel [(set (match_dup 0)
(match_dup 6))
(clobber (match_dup 4))
[(set (match_operand:DI 0 "register_operand" "=x")
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
- "!TARGET_64BIT && !TARGET_FIX_R4000"
+ "!TARGET_64BIT && !TARGET_FIX_R4000 && !TARGET_DSPR2"
"mult<u>\t%1,%2"
[(set_attr "type" "imul")
(set_attr "mode" "SI")])
[(set_attr "type" "imul")
(set_attr "mode" "DI")])
-;; The R4650 supports a 32 bit multiply/ 64 bit accumulate
-;; instruction. The HI/LO registers are used as a 64 bit accumulator.
+;; The R4650 supports a 32-bit multiply/ 64-bit accumulate
+;; instruction. The HI/LO registers are used as a 64-bit accumulator.
(define_insn "madsi"
[(set (match_operand:SI 0 "register_operand" "+l")
(match_operand:ANYF 2 "register_operand" "f"))
(match_operand:ANYF 3 "register_operand" "f"))))]
"ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD
- && HONOR_SIGNED_ZEROS (<MODE>mode)"
+ && HONOR_SIGNED_ZEROS (<MODE>mode)
+ && !HONOR_NANS (<MODE>mode)"
"nmadd.<fmt>\t%0,%3,%1,%2"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
(match_operand:ANYF 2 "register_operand" "f"))
(match_operand:ANYF 3 "register_operand" "f")))]
"ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD
- && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ && !HONOR_SIGNED_ZEROS (<MODE>mode)
+ && !HONOR_NANS (<MODE>mode)"
"nmadd.<fmt>\t%0,%3,%1,%2"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
(match_operand:ANYF 3 "register_operand" "f"))
(match_operand:ANYF 1 "register_operand" "f"))))]
"ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD
- && HONOR_SIGNED_ZEROS (<MODE>mode)"
+ && HONOR_SIGNED_ZEROS (<MODE>mode)
+ && !HONOR_NANS (<MODE>mode)"
"nmsub.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
(mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
(match_operand:ANYF 3 "register_operand" "f"))))]
"ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD
- && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ && !HONOR_SIGNED_ZEROS (<MODE>mode)
+ && !HONOR_NANS (<MODE>mode)"
"nmsub.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
;; Do not use the integer abs macro instruction, since that signals an
;; exception on -2147483648 (sigh).
+;; abs.fmt is an arithmetic instruction and treats all NaN inputs as
+;; invalid; it does not clear their sign bits. We therefore can't use
+;; abs.fmt if the signs of NaNs matter.
+
(define_insn "abs<mode>2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(abs:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
- ""
+ "!HONOR_NANS (<MODE>mode)"
"abs.<fmt>\t%0,%1"
[(set_attr "type" "fabs")
(set_attr "mode" "<UNITMODE>")])
[(set_attr "type" "arith")
(set_attr "mode" "DI")])
+;; neg.fmt is an arithmetic instruction and treats all NaN inputs as
+;; invalid; it does not flip their sign bit. We therefore can't use
+;; neg.fmt if the signs of NaNs matter.
+
(define_insn "neg<mode>2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(neg:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
- ""
+ "!HONOR_NANS (<MODE>mode)"
"neg.<fmt>\t%0,%1"
[(set_attr "type" "fneg")
(set_attr "mode" "<UNITMODE>")])
(define_insn "*movdi_32bit"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*B*C*D,*B*C*D,*d,*m")
(match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))]
- "!TARGET_64BIT && !TARGET_MIPS16
+ "!TARGET_64BIT && !TARGET_FLOAT64 && !TARGET_MIPS16
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); }
(set_attr "mode" "DI")
(set_attr "length" "8,16,*,*,8,8,8,*,8,*")])
+(define_insn "*movdi_gp32_fp64"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*f,*f,*f,*d,*m")
+ (match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*f,*J*d,*m,*f,*f"))]
+ "!TARGET_64BIT && TARGET_FLOAT64 && !TARGET_MIPS16
+ && (register_operand (operands[0], DImode)
+ || reg_or_0_operand (operands[1], DImode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "arith,arith,load,store,mthilo,mfhilo,fmove,xfer,fpload,xfer,fpstore")
+ (set_attr "mode" "DI")
+ (set_attr "length" "8,16,*,*,8,8,4,8,*,8,*")])
+
(define_insn "*movdi_32bit_mips16"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d")
(match_operand:DI 1 "move_operand" "d,d,y,K,N,m,d,*x"))]
;; the sum of two general registers. We use two versions for each of
;; these four instructions: one where the two general registers are
;; SImode, and one where they are DImode. This is because general
-;; registers will be in SImode when they hold 32 bit values, but,
-;; since the 32 bit values are always sign extended, the [ls][wd]xc1
+;; registers will be in SImode when they hold 32-bit values, but,
+;; since the 32-bit values are always sign extended, the [ls][wd]xc1
;; instructions will still work correctly.
;; ??? Perhaps it would be better to support these instructions by
(set_attr "mode" "DF")
(set_attr "length" "4,4,*,*,*,4,4,4,*,*")])
+;; This pattern applies to both !TARGET_FLOAT64 and TARGET_FLOAT64.
(define_insn "*movdf_hardfloat_32bit"
[(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m")
(match_operand:DF 1 "move_operand" "f,G,m,f,G,*d,*f,*d*G,*m,*d"))]
[(set_attr "type" "xfer,fpstore")
(set_attr "mode" "SF")])
+;; Move operand 1 to the high word of operand 0 using mthc1, preserving the
+;; value in the low word.
+(define_insn "mthc1"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (unspec:DF [(match_operand:SI 1 "general_operand" "dJ")
+ (match_operand:DF 2 "register_operand" "0")]
+ UNSPEC_MTHC1))]
+ "TARGET_HARD_FLOAT && !TARGET_64BIT && ISA_HAS_MXHC1"
+ "mthc1\t%z1,%0"
+ [(set_attr "type" "xfer")
+ (set_attr "mode" "SF")])
+
+;; Move high word of operand 1 to operand 0 using mfhc1. The corresponding
+;; low-word move is done in the normal way.
+(define_insn "mfhc1"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:DF 1 "register_operand" "f")]
+ UNSPEC_MFHC1))]
+ "TARGET_HARD_FLOAT && !TARGET_64BIT && ISA_HAS_MXHC1"
+ "mfhc1\t%0,%1"
+ [(set_attr "type" "xfer")
+ (set_attr "mode" "SF")])
+
;; Insn to initialize $gp for n32/n64 abicalls. Operand 0 is the offset
;; of _gp from the start of this function. Operand 1 is the incoming
;; function address.
[(set (match_operand:GPR 0 "register_operand" "=d")
(rotatert:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:SI 2 "arith_operand" "dI")))]
- "ISA_HAS_ROTR_<MODE>"
+ "ISA_HAS_ROR"
{
if (GET_CODE (operands[2]) == CONST_INT)
gcc_assert (INTVAL (operands[2]) >= 0
; The MIPS DSP Instructions.
(include "mips-dsp.md")
+
+; The MIPS DSP REV 2 Instructions.
+
+(include "mips-dspr2.md")