aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorChao-ying Fu <fu@mips.com>2005-07-23 08:36:54 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2005-07-23 08:36:54 +0000
commit118ea793126f7e628d11de81cd4d100785e104e8 (patch)
treede53c7e62cba65c95a59ce4c1dcd2c4ffdcc6ffb /gcc
parent5887a1bb9c70faa8f917ea8f41600c61f462cfb8 (diff)
downloadgcc-118ea793126f7e628d11de81cd4d100785e104e8.zip
gcc-118ea793126f7e628d11de81cd4d100785e104e8.tar.gz
gcc-118ea793126f7e628d11de81cd4d100785e104e8.tar.bz2
mips-dsp.md: New file.
* config/mips/mips-dsp.md: New file. * config/mips/mips-modes.def (V4QI, V2HI, CCDSP): New modes. * config/mips/mips.c (mips_function_type): Add types for DSP builtin functions. (mips_builtin_type): Add MIPS_BUILTIN_DIRECT_NO_TARGET and MIPS_BUILTIN_BPOSGE32. (mips_expand_builtin_direct): Add one parameter to indicate that builtin functions need to return a value. (mips_expand_builtin_bposge): New for expanding "bposge" builtin functions. (mips_regno_to_class): Add classes for 12 new DSP registers. (mips_subword): Change to check four HI registers. (mips_output_move): Output move to and from 6 new DSP accumulators. (override_options): Make sure -mdsp and -mips16 are not used together. Map 'A' to DSP_ACC_REGS and 'a' to ACC_REGS. Enable DSP accumulators for machine modes. (mips_conditional_register_usage): Disable 6 new DSP accumulators when !TARGET_DSP. (print_operand): Add 'q' for printing DSP accumulators. (mips_cannot_change_mode_class): Check ACC_REGS. (mips_secondary_reload_class): Check ACC_REGS. (mips_vector_mode_supported_p): Enable V2HI and V4QI when TARGET_DSP. (mips_register_move_cost): Check ACC_REGS. (CODE_FOR_mips_addq_ph, CODE_FOR_mips_addu_qb, CODE_FOR_mips_subq_ph) (CODE_FOR_mips_subu_qb): New code-aliasing macros. (DIRECT_NO_TARGET_BUILTIN, BPOSGE_BUILTIN): New macros. (dsp_bdesc): New array. (bdesc_arrays): Add DSP builtin function table. (mips_prepare_builtin_arg): Check predicate again after copy_to_mode_reg. (mips_expand_builtin): Add one more parameter to mips_expand_builtin_direct. Expand MIPS_BUILTIN_DIRECT_NO_TARGET and MIPS_BUILTIN_BPOSGE32. (mips_init_builtins): Initialize new function types. (mips_expand_builtin_direct): Check if builtin functions need to return a value and pass operands properly. (mips_expand_builtin_bposge): New function. * config/mips/mips.h (TARGET_CPU_CPP_BUILTINS): Add __mips_dsp. (ASM_SPEC): Map -mdsp to -mdsp in GAS. (FIRST_PSEUDO_REGISTER): Increase to 188. (FIXED_REGISTERS, CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS): Update for 12 new DSP registers. (DSP_ACC_REG_FIRST, DSP_ACC_REG_LAST, DSP_ACC_REG_NUM, AC1HI_REGNUM) (AC1LO_REGNUM, AC2HI_REGNUM, AC2LO_REGNUM, AC3HI_REGNUM, AC3LO_REGNUM): (DSP_ACC_REG_P, ACC_REG_P, ACC_HI_REG_P): New macros. (reg_class): Add DSP_ACC_REGS and ACC_REGS. (REG_CLASS_NAMES): Add names for DSP_ACC_REGS and ACC_REGS. (REG_CLASS_CONTENTS): Update for DSP_ACC_REGS, ACC_REGS and ALL_REGS. (REG_ALLOC_ORDER): Update for 12 new DSP registers. (mips_char_to_class): Add 'A' for DSP_ACC_REGS and 'a' for ACC_REGS. (UIMM6_OPERAND, IMM10_OPERAND): New macros. (EXTRA_CONSTRAINT_Y): Add YA and YB extra constraints. (REGISTER_NAMES): Add names for 12 new DSP registers. * config/mips/mips.md: Include mips-dsp.md. (UNSPEC_ADDQ, UNSPEC_ADDQ_S, UNSPEC_SUBQ, UNSPEC_SUBQ_S, UNSPEC_ADDSC) (UNSPEC_ADDWC, UNSPEC_MODSUB, UNSPEC_RADDU_W_QB, UNSPEC_ABSQ_S) (UNSPEC_PRECRQ_QB_PH, UNSPEC_PRECRQ_PH_W, UNSPEC_PRECRQ_RS_PH_W) (UNSPEC_PRECRQU_S_QB_PH, UNSPEC_PRECEQ_W_PHL, UNSPEC_PRECEQ_W_PHR) (UNSPEC_PRECEQU_PH_QBL, UNSPEC_PRECEQU_PH_QBR, UNSPEC_PRECEQU_PH_QBLA) (UNSPEC_PRECEQU_PH_QBRA, UNSPEC_PRECEU_PH_QBL, UNSPEC_PRECEU_PH_QBR) (UNSPEC_PRECEU_PH_QBLA, UNSPEC_PRECEU_PH_QBRA, UNSPEC_SHLL) (UNSPEC_SHLL_S, UNSPEC_SHRL_QB, UNSPEC_SHRA_PH, UNSPEC_SHRA_R) (UNSPEC_MULEU_S_PH_QBL, UNSPEC_MULEU_S_PH_QBR, UNSPEC_MULQ_RS_PH) (UNSPEC_MULEQ_S_W_PHL, UNSPEC_MULEQ_S_W_PHR, UNSPEC_DPAU_H_QBL) (UNSPEC_DPAU_H_QBR, UNSPEC_DPSU_H_QBL, UNSPEC_DPSU_H_QBR) (UNSPEC_DPAQ_S_W_PH, UNSPEC_DPSQ_S_W_PH, UNSPEC_MULSAQ_S_W_PH) (UNSPEC_DPAQ_SA_L_W, UNSPEC_DPSQ_SA_L_W, UNSPEC_MAQ_S_W_PHL) (UNSPEC_MAQ_S_W_PHR, UNSPEC_MAQ_SA_W_PHL, UNSPEC_MAQ_SA_W_PHR) (UNSPEC_BITREV, UNSPEC_INSV, UNSPEC_REPL_QB, UNSPEC_REPL_PH) (UNSPEC_CMP_EQ, UNSPEC_CMP_LT, UNSPEC_CMP_LE, UNSPEC_CMPGU_EQ_QB) (UNSPEC_CMPGU_LT_QB, UNSPEC_CMPGU_LE_QB, UNSPEC_PICK, UNSPEC_PACKRL_PH) (UNSPEC_EXTR_W, UNSPEC_EXTR_R_W, UNSPEC_EXTR_RS_W, UNSPEC_EXTR_S_H) (UNSPEC_EXTP, UNSPEC_EXTPDP, UNSPEC_SHILO, UNSPEC_MTHLIP, UNSPEC_WRDSP) (UNSPEC_RDDSP): New constants. (*movdi_32bit): Change 'x' to 'a' for ACC_REGS. (*movsi_internal): Change 'x' to 'a' for ACC_REGS. Add an A<-d alternative. * config/mips/mips.opt (-mdsp): New option. * config/mips/predicates.md (const_uimm6_operand, const_imm10_operand) (reg_imm10_operand): New predicates. * doc/extend.texi (MIPS DSP Built-in Functions): New section. * doc/invoke.texi (-mdsp): Document new option. From-SVN: r102307
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog85
-rw-r--r--gcc/config/mips/mips-dsp.md1058
-rw-r--r--gcc/config/mips/mips-modes.def4
-rw-r--r--gcc/config/mips/mips.c590
-rw-r--r--gcc/config/mips/mips.h77
-rw-r--r--gcc/config/mips/mips.md86
-rw-r--r--gcc/config/mips/mips.opt4
-rw-r--r--gcc/config/mips/predicates.md12
-rw-r--r--gcc/doc/extend.texi203
-rw-r--r--gcc/doc/invoke.texi8
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/mips/mips32-dsp-type.c30
-rw-r--r--gcc/testsuite/gcc.target/mips/mips32-dsp.c1092
13 files changed, 3158 insertions, 96 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 55e2f4a..73d386b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,88 @@
+2005-07-23 Chao-ying Fu <fu@mips.com>
+
+ * config/mips/mips-dsp.md: New file.
+ * config/mips/mips-modes.def (V4QI, V2HI, CCDSP): New modes.
+ * config/mips/mips.c (mips_function_type): Add types for DSP builtin
+ functions.
+ (mips_builtin_type): Add MIPS_BUILTIN_DIRECT_NO_TARGET and
+ MIPS_BUILTIN_BPOSGE32.
+ (mips_expand_builtin_direct): Add one parameter to indicate that
+ builtin functions need to return a value.
+ (mips_expand_builtin_bposge): New for expanding "bposge" builtin
+ functions.
+ (mips_regno_to_class): Add classes for 12 new DSP registers.
+ (mips_subword): Change to check four HI registers.
+ (mips_output_move): Output move to and from 6 new DSP accumulators.
+ (override_options): Make sure -mdsp and -mips16 are not used together.
+ Map 'A' to DSP_ACC_REGS and 'a' to ACC_REGS. Enable DSP accumulators
+ for machine modes.
+ (mips_conditional_register_usage): Disable 6 new DSP accumulators
+ when !TARGET_DSP.
+ (print_operand): Add 'q' for printing DSP accumulators.
+ (mips_cannot_change_mode_class): Check ACC_REGS.
+ (mips_secondary_reload_class): Check ACC_REGS.
+ (mips_vector_mode_supported_p): Enable V2HI and V4QI when TARGET_DSP.
+ (mips_register_move_cost): Check ACC_REGS.
+ (CODE_FOR_mips_addq_ph, CODE_FOR_mips_addu_qb, CODE_FOR_mips_subq_ph)
+ (CODE_FOR_mips_subu_qb): New code-aliasing macros.
+ (DIRECT_NO_TARGET_BUILTIN, BPOSGE_BUILTIN): New macros.
+ (dsp_bdesc): New array.
+ (bdesc_arrays): Add DSP builtin function table.
+ (mips_prepare_builtin_arg): Check predicate again after
+ copy_to_mode_reg.
+ (mips_expand_builtin): Add one more parameter to
+ mips_expand_builtin_direct. Expand MIPS_BUILTIN_DIRECT_NO_TARGET and
+ MIPS_BUILTIN_BPOSGE32.
+ (mips_init_builtins): Initialize new function types.
+ (mips_expand_builtin_direct): Check if builtin functions need to
+ return a value and pass operands properly.
+ (mips_expand_builtin_bposge): New function.
+ * config/mips/mips.h (TARGET_CPU_CPP_BUILTINS): Add __mips_dsp.
+ (ASM_SPEC): Map -mdsp to -mdsp in GAS.
+ (FIRST_PSEUDO_REGISTER): Increase to 188.
+ (FIXED_REGISTERS, CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS):
+ Update for 12 new DSP registers.
+ (DSP_ACC_REG_FIRST, DSP_ACC_REG_LAST, DSP_ACC_REG_NUM, AC1HI_REGNUM)
+ (AC1LO_REGNUM, AC2HI_REGNUM, AC2LO_REGNUM, AC3HI_REGNUM, AC3LO_REGNUM):
+ (DSP_ACC_REG_P, ACC_REG_P, ACC_HI_REG_P): New macros.
+ (reg_class): Add DSP_ACC_REGS and ACC_REGS.
+ (REG_CLASS_NAMES): Add names for DSP_ACC_REGS and ACC_REGS.
+ (REG_CLASS_CONTENTS): Update for DSP_ACC_REGS, ACC_REGS and ALL_REGS.
+ (REG_ALLOC_ORDER): Update for 12 new DSP registers.
+ (mips_char_to_class): Add 'A' for DSP_ACC_REGS and 'a' for ACC_REGS.
+ (UIMM6_OPERAND, IMM10_OPERAND): New macros.
+ (EXTRA_CONSTRAINT_Y): Add YA and YB extra constraints.
+ (REGISTER_NAMES): Add names for 12 new DSP registers.
+ * config/mips/mips.md: Include mips-dsp.md.
+ (UNSPEC_ADDQ, UNSPEC_ADDQ_S, UNSPEC_SUBQ, UNSPEC_SUBQ_S, UNSPEC_ADDSC)
+ (UNSPEC_ADDWC, UNSPEC_MODSUB, UNSPEC_RADDU_W_QB, UNSPEC_ABSQ_S)
+ (UNSPEC_PRECRQ_QB_PH, UNSPEC_PRECRQ_PH_W, UNSPEC_PRECRQ_RS_PH_W)
+ (UNSPEC_PRECRQU_S_QB_PH, UNSPEC_PRECEQ_W_PHL, UNSPEC_PRECEQ_W_PHR)
+ (UNSPEC_PRECEQU_PH_QBL, UNSPEC_PRECEQU_PH_QBR, UNSPEC_PRECEQU_PH_QBLA)
+ (UNSPEC_PRECEQU_PH_QBRA, UNSPEC_PRECEU_PH_QBL, UNSPEC_PRECEU_PH_QBR)
+ (UNSPEC_PRECEU_PH_QBLA, UNSPEC_PRECEU_PH_QBRA, UNSPEC_SHLL)
+ (UNSPEC_SHLL_S, UNSPEC_SHRL_QB, UNSPEC_SHRA_PH, UNSPEC_SHRA_R)
+ (UNSPEC_MULEU_S_PH_QBL, UNSPEC_MULEU_S_PH_QBR, UNSPEC_MULQ_RS_PH)
+ (UNSPEC_MULEQ_S_W_PHL, UNSPEC_MULEQ_S_W_PHR, UNSPEC_DPAU_H_QBL)
+ (UNSPEC_DPAU_H_QBR, UNSPEC_DPSU_H_QBL, UNSPEC_DPSU_H_QBR)
+ (UNSPEC_DPAQ_S_W_PH, UNSPEC_DPSQ_S_W_PH, UNSPEC_MULSAQ_S_W_PH)
+ (UNSPEC_DPAQ_SA_L_W, UNSPEC_DPSQ_SA_L_W, UNSPEC_MAQ_S_W_PHL)
+ (UNSPEC_MAQ_S_W_PHR, UNSPEC_MAQ_SA_W_PHL, UNSPEC_MAQ_SA_W_PHR)
+ (UNSPEC_BITREV, UNSPEC_INSV, UNSPEC_REPL_QB, UNSPEC_REPL_PH)
+ (UNSPEC_CMP_EQ, UNSPEC_CMP_LT, UNSPEC_CMP_LE, UNSPEC_CMPGU_EQ_QB)
+ (UNSPEC_CMPGU_LT_QB, UNSPEC_CMPGU_LE_QB, UNSPEC_PICK, UNSPEC_PACKRL_PH)
+ (UNSPEC_EXTR_W, UNSPEC_EXTR_R_W, UNSPEC_EXTR_RS_W, UNSPEC_EXTR_S_H)
+ (UNSPEC_EXTP, UNSPEC_EXTPDP, UNSPEC_SHILO, UNSPEC_MTHLIP, UNSPEC_WRDSP)
+ (UNSPEC_RDDSP): New constants.
+ (*movdi_32bit): Change 'x' to 'a' for ACC_REGS.
+ (*movsi_internal): Change 'x' to 'a' for ACC_REGS. Add an
+ A<-d alternative.
+ * config/mips/mips.opt (-mdsp): New option.
+ * config/mips/predicates.md (const_uimm6_operand, const_imm10_operand)
+ (reg_imm10_operand): New predicates.
+ * doc/extend.texi (MIPS DSP Built-in Functions): New section.
+ * doc/invoke.texi (-mdsp): Document new option.
+
2005-07-22 DJ Delorie <dj@redhat.com>
* c-objc-common.c (c_cannot_inline_tree_fn): Add warning control
diff --git a/gcc/config/mips/mips-dsp.md b/gcc/config/mips/mips-dsp.md
new file mode 100644
index 0000000..a61b23f
--- /dev/null
+++ b/gcc/config/mips/mips-dsp.md
@@ -0,0 +1,1058 @@
+(define_constants
+ [(CCDSP_PO_REGNUM 182)
+ (CCDSP_SC_REGNUM 183)
+ (CCDSP_CA_REGNUM 184)
+ (CCDSP_OU_REGNUM 185)
+ (CCDSP_CC_REGNUM 186)
+ (CCDSP_EF_REGNUM 187)])
+
+;; This mode macro allows si, v2hi, v4qi for all possible modes in DSP ASE.
+(define_mode_macro DSP [(SI "TARGET_DSP")
+ (V2HI "TARGET_DSP")
+ (V4QI "TARGET_DSP")])
+
+;; This mode macro allows v2hi, v4qi for vector/SIMD data.
+(define_mode_macro DSPV [(V2HI "TARGET_DSP")
+ (V4QI "TARGET_DSP")])
+
+;; This mode macro allows si, v2hi for Q31 and V2Q15 fixed-point data.
+(define_mode_macro DSPQ [(SI "TARGET_DSP")
+ (V2HI "TARGET_DSP")])
+
+;; DSP instructions use q for fixed-point data, and u for integer in the infix.
+(define_mode_attr dspfmt1 [(SI "q") (V2HI "q") (V4QI "u")])
+
+;; DSP instructions use nothing for fixed-point data, and u for integer in
+;; the infix.
+(define_mode_attr dspfmt1_1 [(SI "") (V2HI "") (V4QI "u")])
+
+;; DSP instructions use w, ph, qb in the postfix.
+(define_mode_attr dspfmt2 [(SI "w") (V2HI "ph") (V4QI "qb")])
+
+;; DSP shift masks for SI, V2HI, V4QI.
+(define_mode_attr dspshift_mask [(SI "0x1f") (V2HI "0xf") (V4QI "0x7")])
+
+;; MIPS DSP ASE Revision 0.98 3/24/2005
+;; Table 2-1. MIPS DSP ASE Instructions: Arithmetic
+;; ADDQ*
+(define_insn "add<DSPV:mode>3"
+ [(parallel
+ [(set (match_operand:DSPV 0 "register_operand" "=d")
+ (plus:DSPV (match_operand:DSPV 1 "register_operand" "d")
+ (match_operand:DSPV 2 "register_operand" "d")))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDQ))])]
+ ""
+ "add<DSPV:dspfmt1>.<DSPV:dspfmt2>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_add<DSP:dspfmt1>_s_<DSP:dspfmt2>"
+ [(parallel
+ [(set (match_operand:DSP 0 "register_operand" "=d")
+ (unspec:DSP [(match_operand:DSP 1 "register_operand" "d")
+ (match_operand:DSP 2 "register_operand" "d")]
+ UNSPEC_ADDQ_S))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDQ_S))])]
+ ""
+ "add<DSP:dspfmt1>_s.<DSP:dspfmt2>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; SUBQ*
+(define_insn "sub<DSPV:mode>3"
+ [(parallel
+ [(set (match_operand:DSPV 0 "register_operand" "=d")
+ (minus:DSPV (match_operand:DSPV 1 "register_operand" "d")
+ (match_operand:DSPV 2 "register_operand" "d")))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBQ))])]
+ "TARGET_DSP"
+ "sub<DSPV:dspfmt1>.<DSPV:dspfmt2>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_sub<DSP:dspfmt1>_s_<DSP:dspfmt2>"
+ [(parallel
+ [(set (match_operand:DSP 0 "register_operand" "=d")
+ (unspec:DSP [(match_operand:DSP 1 "register_operand" "d")
+ (match_operand:DSP 2 "register_operand" "d")]
+ UNSPEC_SUBQ_S))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBQ_S))])]
+ "TARGET_DSP"
+ "sub<DSP:dspfmt1>_s.<DSP:dspfmt2>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; ADDSC
+(define_insn "mips_addsc"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")]
+ UNSPEC_ADDSC))
+ (set (reg:CCDSP CCDSP_CA_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDSC))])]
+ "TARGET_DSP"
+ "addsc\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; ADDWC
+(define_insn "mips_addwc"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")
+ (reg:CCDSP CCDSP_CA_REGNUM)]
+ UNSPEC_ADDWC))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDWC))])]
+ "TARGET_DSP"
+ "addwc\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; MODSUB
+(define_insn "mips_modsub"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")]
+ UNSPEC_MODSUB))]
+ "TARGET_DSP"
+ "modsub\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; RADDU*
+(define_insn "mips_raddu_w_qb"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_RADDU_W_QB))]
+ "TARGET_DSP"
+ "raddu.w.qb\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; ABSQ*
+(define_insn "mips_absq_s_<DSPQ:dspfmt2>"
+ [(parallel
+ [(set (match_operand:DSPQ 0 "register_operand" "=d")
+ (unspec:DSPQ [(match_operand:DSPQ 1 "register_operand" "d")]
+ UNSPEC_ABSQ_S))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1)] UNSPEC_ABSQ_S))])]
+ "TARGET_DSP"
+ "absq_s.<DSPQ:dspfmt2>\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PRECRQ*
+(define_insn "mips_precrq_qb_ph"
+ [(set (match_operand:V4QI 0 "register_operand" "=d")
+ (unspec:V4QI [(match_operand:V2HI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_PRECRQ_QB_PH))]
+ "TARGET_DSP"
+ "precrq.qb.ph\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_precrq_ph_w"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")]
+ UNSPEC_PRECRQ_PH_W))]
+ "TARGET_DSP"
+ "precrq.ph.w\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_precrq_rs_ph_w"
+ [(parallel
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")]
+ UNSPEC_PRECRQ_RS_PH_W))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)]
+ UNSPEC_PRECRQ_RS_PH_W))])]
+ "TARGET_DSP"
+ "precrq_rs.ph.w\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PRECRQU*
+(define_insn "mips_precrqu_s_qb_ph"
+ [(parallel
+ [(set (match_operand:V4QI 0 "register_operand" "=d")
+ (unspec:V4QI [(match_operand:V2HI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_PRECRQU_S_QB_PH))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)]
+ UNSPEC_PRECRQU_S_QB_PH))])]
+ "TARGET_DSP"
+ "precrqu_s.qb.ph\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PRECEQ*
+(define_insn "mips_preceq_w_phl"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V2HI 1 "register_operand" "d")]
+ UNSPEC_PRECEQ_W_PHL))]
+ "TARGET_DSP"
+ "preceq.w.phl\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_preceq_w_phr"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V2HI 1 "register_operand" "d")]
+ UNSPEC_PRECEQ_W_PHR))]
+ "TARGET_DSP"
+ "preceq.w.phr\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PRECEQU*
+(define_insn "mips_precequ_ph_qbl"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEQU_PH_QBL))]
+ "TARGET_DSP"
+ "precequ.ph.qbl\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_precequ_ph_qbr"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEQU_PH_QBR))]
+ "TARGET_DSP"
+ "precequ.ph.qbr\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_precequ_ph_qbla"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEQU_PH_QBLA))]
+ "TARGET_DSP"
+ "precequ.ph.qbla\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_precequ_ph_qbra"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEQU_PH_QBRA))]
+ "TARGET_DSP"
+ "precequ.ph.qbra\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PRECEU*
+(define_insn "mips_preceu_ph_qbl"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEU_PH_QBL))]
+ "TARGET_DSP"
+ "preceu.ph.qbl\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_preceu_ph_qbr"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEU_PH_QBR))]
+ "TARGET_DSP"
+ "preceu.ph.qbr\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_preceu_ph_qbla"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEU_PH_QBLA))]
+ "TARGET_DSP"
+ "preceu.ph.qbla\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_preceu_ph_qbra"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEU_PH_QBRA))]
+ "TARGET_DSP"
+ "preceu.ph.qbra\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; Table 2-2. MIPS DSP ASE Instructions: Shift
+;; SHLL*
+(define_insn "mips_shll_<DSPV:dspfmt2>"
+ [(parallel
+ [(set (match_operand:DSPV 0 "register_operand" "=d,d")
+ (unspec:DSPV [(match_operand:DSPV 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_SHLL))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SHLL))])]
+ "TARGET_DSP"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2])
+ & ~(unsigned HOST_WIDE_INT) <DSPV:dspshift_mask>)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & <DSPV:dspshift_mask>);
+ return "shll.<DSPV:dspfmt2>\t%0,%1,%2";
+ }
+ return "shllv.<DSPV:dspfmt2>\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_shll_s_<DSPQ:dspfmt2>"
+ [(parallel
+ [(set (match_operand:DSPQ 0 "register_operand" "=d,d")
+ (unspec:DSPQ [(match_operand:DSPQ 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_SHLL_S))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SHLL_S))])]
+ "TARGET_DSP"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2])
+ & ~(unsigned HOST_WIDE_INT) <DSPQ:dspshift_mask>)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & <DSPQ:dspshift_mask>);
+ return "shll_s.<DSPQ:dspfmt2>\t%0,%1,%2";
+ }
+ return "shllv_s.<DSPQ:dspfmt2>\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+;; SHRL*
+(define_insn "mips_shrl_qb"
+ [(set (match_operand:V4QI 0 "register_operand" "=d,d")
+ (unspec:V4QI [(match_operand:V4QI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_SHRL_QB))]
+ "TARGET_DSP"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x7)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x7);
+ return "shrl.qb\t%0,%1,%2";
+ }
+ return "shrlv.qb\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+;; SHRA*
+(define_insn "mips_shra_ph"
+ [(set (match_operand:V2HI 0 "register_operand" "=d,d")
+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_SHRA_PH))]
+ "TARGET_DSP"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xf)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0xf);
+ return "shra.ph\t%0,%1,%2";
+ }
+ return "shrav.ph\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_shra_r_<DSPQ:dspfmt2>"
+ [(set (match_operand:DSPQ 0 "register_operand" "=d,d")
+ (unspec:DSPQ [(match_operand:DSPQ 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_SHRA_R))]
+ "TARGET_DSP"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2])
+ & ~(unsigned HOST_WIDE_INT) <DSPQ:dspshift_mask>)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & <DSPQ:dspshift_mask>);
+ return "shra_r.<DSPQ:dspfmt2>\t%0,%1,%2";
+ }
+ return "shrav_r.<DSPQ:dspfmt2>\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+;; Table 2-3. MIPS DSP ASE Instructions: Multiply
+;; MULEU*
+(define_insn "mips_muleu_s_ph_qbl"
+ [(parallel
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_MULEU_S_PH_QBL))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_MULEU_S_PH_QBL))
+ (clobber (match_scratch:DI 3 "=x"))])]
+ "TARGET_DSP"
+ "muleu_s.ph.qbl\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_muleu_s_ph_qbr"
+ [(parallel
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_MULEU_S_PH_QBR))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_MULEU_S_PH_QBR))
+ (clobber (match_scratch:DI 3 "=x"))])]
+ "TARGET_DSP"
+ "muleu_s.ph.qbr\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "SI")])
+
+;; MULQ*
+(define_insn "mips_mulq_rs_ph"
+ [(parallel
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_MULQ_RS_PH))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_MULQ_RS_PH))
+ (clobber (match_scratch:DI 3 "=x"))])]
+ "TARGET_DSP"
+ "mulq_rs.ph\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "SI")])
+
+;; MULEQ*
+(define_insn "mips_muleq_s_w_phl"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V2HI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_MULEQ_S_W_PHL))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_MULEQ_S_W_PHL))
+ (clobber (match_scratch:DI 3 "=x"))])]
+ "TARGET_DSP"
+ "muleq_s.w.phl\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_muleq_s_w_phr"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V2HI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_MULEQ_S_W_PHR))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_MULEQ_S_W_PHR))
+ (clobber (match_scratch:DI 3 "=x"))])]
+ "TARGET_DSP"
+ "muleq_s.w.phr\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "SI")])
+
+;; DPAU*
+(define_insn "mips_dpau_h_qbl"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V4QI 2 "register_operand" "d")
+ (match_operand:V4QI 3 "register_operand" "d")]
+ UNSPEC_DPAU_H_QBL))]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpau.h.qbl\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_dpau_h_qbr"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V4QI 2 "register_operand" "d")
+ (match_operand:V4QI 3 "register_operand" "d")]
+ UNSPEC_DPAU_H_QBR))]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpau.h.qbr\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; DPSU*
+(define_insn "mips_dpsu_h_qbl"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V4QI 2 "register_operand" "d")
+ (match_operand:V4QI 3 "register_operand" "d")]
+ UNSPEC_DPSU_H_QBL))]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpsu.h.qbl\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_dpsu_h_qbr"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V4QI 2 "register_operand" "d")
+ (match_operand:V4QI 3 "register_operand" "d")]
+ UNSPEC_DPSU_H_QBR))]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpsu.h.qbr\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; DPAQ*
+(define_insn "mips_dpaq_s_w_ph"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_DPAQ_S_W_PH))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_DPAQ_S_W_PH))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpaq_s.w.ph\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; DPSQ*
+(define_insn "mips_dpsq_s_w_ph"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_DPSQ_S_W_PH))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_DPSQ_S_W_PH))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpsq_s.w.ph\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; MULSAQ*
+(define_insn "mips_mulsaq_s_w_ph"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_MULSAQ_S_W_PH))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_MULSAQ_S_W_PH))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "mulsaq_s.w.ph\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; DPAQ*
+(define_insn "mips_dpaq_sa_l_w"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:SI 2 "register_operand" "d")
+ (match_operand:SI 3 "register_operand" "d")]
+ UNSPEC_DPAQ_SA_L_W))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_DPAQ_SA_L_W))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpaq_sa.l.w\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; DPSQ*
+(define_insn "mips_dpsq_sa_l_w"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:SI 2 "register_operand" "d")
+ (match_operand:SI 3 "register_operand" "d")]
+ UNSPEC_DPSQ_SA_L_W))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_DPSQ_SA_L_W))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpsq_sa.l.w\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; MAQ*
+(define_insn "mips_maq_s_w_phl"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_MAQ_S_W_PHL))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_MAQ_S_W_PHL))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "maq_s.w.phl\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_maq_s_w_phr"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_MAQ_S_W_PHR))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_MAQ_S_W_PHR))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "maq_s.w.phr\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; MAQ_SA*
+(define_insn "mips_maq_sa_w_phl"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_MAQ_SA_W_PHL))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_MAQ_SA_W_PHL))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "maq_sa.w.phl\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_maq_sa_w_phr"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_MAQ_SA_W_PHR))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_MAQ_SA_W_PHR))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "maq_sa.w.phr\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; Table 2-4. MIPS DSP ASE Instructions: General Bit/Manipulation
+;; BITREV
+(define_insn "mips_bitrev"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "d")]
+ UNSPEC_BITREV))]
+ "TARGET_DSP"
+ "bitrev\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; INSV
+(define_insn "mips_insv"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "register_operand" "d")
+ (reg:CCDSP CCDSP_SC_REGNUM)
+ (reg:CCDSP CCDSP_PO_REGNUM)]
+ UNSPEC_INSV))]
+ "TARGET_DSP"
+ "insv\t%0,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; REPL*
+(define_insn "mips_repl_qb"
+ [(set (match_operand:V4QI 0 "register_operand" "=d,d")
+ (unspec:V4QI [(match_operand:SI 1 "arith_operand" "I,d")]
+ UNSPEC_REPL_QB))]
+ "TARGET_DSP"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[1]) & ~(unsigned HOST_WIDE_INT) 0xff)
+ operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
+ return "repl.qb\t%0,%1";
+ }
+ return "replv.qb\t%0,%1";
+}
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_repl_ph"
+ [(set (match_operand:V2HI 0 "register_operand" "=d,d")
+ (unspec:V2HI [(match_operand:SI 1 "reg_imm10_operand" "YB,d")]
+ UNSPEC_REPL_PH))]
+ "TARGET_DSP"
+ "@
+ repl.ph\t%0,%1
+ replv.ph\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; Table 2-5. MIPS DSP ASE Instructions: Compare-Pick
+;; CMPU.* CMP.*
+(define_insn "mips_cmp<DSPV:dspfmt1_1>_eq_<DSPV:dspfmt2>"
+ [(set (reg:CCDSP CCDSP_CC_REGNUM)
+ (unspec:CCDSP [(match_operand:DSPV 0 "register_operand" "d")
+ (match_operand:DSPV 1 "register_operand" "d")
+ (reg:CCDSP CCDSP_CC_REGNUM)]
+ UNSPEC_CMP_EQ))]
+ "TARGET_DSP"
+ "cmp<DSPV:dspfmt1_1>.eq.<DSPV:dspfmt2>\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_cmp<DSPV:dspfmt1_1>_lt_<DSPV:dspfmt2>"
+ [(set (reg:CCDSP CCDSP_CC_REGNUM)
+ (unspec:CCDSP [(match_operand:DSPV 0 "register_operand" "d")
+ (match_operand:DSPV 1 "register_operand" "d")
+ (reg:CCDSP CCDSP_CC_REGNUM)]
+ UNSPEC_CMP_LT))]
+ "TARGET_DSP"
+ "cmp<DSPV:dspfmt1_1>.lt.<DSPV:dspfmt2>\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_cmp<DSPV:dspfmt1_1>_le_<DSPV:dspfmt2>"
+ [(set (reg:CCDSP CCDSP_CC_REGNUM)
+ (unspec:CCDSP [(match_operand:DSPV 0 "register_operand" "d")
+ (match_operand:DSPV 1 "register_operand" "d")
+ (reg:CCDSP CCDSP_CC_REGNUM)]
+ UNSPEC_CMP_LE))]
+ "TARGET_DSP"
+ "cmp<DSPV:dspfmt1_1>.le.<DSPV:dspfmt2>\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_cmpgu_eq_qb"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V4QI 1 "register_operand" "d")
+ (match_operand:V4QI 2 "register_operand" "d")]
+ UNSPEC_CMPGU_EQ_QB))]
+ "TARGET_DSP"
+ "cmpgu.eq.qb\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_cmpgu_lt_qb"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V4QI 1 "register_operand" "d")
+ (match_operand:V4QI 2 "register_operand" "d")]
+ UNSPEC_CMPGU_LT_QB))]
+ "TARGET_DSP"
+ "cmpgu.lt.qb\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_cmpgu_le_qb"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V4QI 1 "register_operand" "d")
+ (match_operand:V4QI 2 "register_operand" "d")]
+ UNSPEC_CMPGU_LE_QB))]
+ "TARGET_DSP"
+ "cmpgu.le.qb\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PICK*
+(define_insn "mips_pick_<DSPV:dspfmt2>"
+ [(set (match_operand:DSPV 0 "register_operand" "=d")
+ (unspec:DSPV [(match_operand:DSPV 1 "register_operand" "d")
+ (match_operand:DSPV 2 "register_operand" "d")
+ (reg:CCDSP CCDSP_CC_REGNUM)]
+ UNSPEC_PICK))]
+ "TARGET_DSP"
+ "pick.<DSPV:dspfmt2>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PACKRL*
+(define_insn "mips_packrl_ph"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_PACKRL_PH))]
+ "TARGET_DSP"
+ "packrl.ph\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; Table 2-6. MIPS DSP ASE Instructions: Accumulator and DSPControl Access
+;; EXTR*
+(define_insn "mips_extr_w"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (unspec:SI [(match_operand:DI 1 "register_operand" "a,a")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_EXTR_W))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTR_W))])]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "extr.w\t%0,%q1,%2";
+ }
+ return "extrv.w\t%0,%q1,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_extr_r_w"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (unspec:SI [(match_operand:DI 1 "register_operand" "a,a")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_EXTR_R_W))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTR_R_W))])]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "extr_r.w\t%0,%q1,%2";
+ }
+ return "extrv_r.w\t%0,%q1,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_extr_rs_w"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (unspec:SI [(match_operand:DI 1 "register_operand" "a,a")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_EXTR_RS_W))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTR_RS_W))])]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "extr_rs.w\t%0,%q1,%2";
+ }
+ return "extrv_rs.w\t%0,%q1,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+;; EXTR*_S.H
+(define_insn "mips_extr_s_h"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (unspec:SI [(match_operand:DI 1 "register_operand" "a,a")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_EXTR_S_H))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTR_S_H))])]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "extr_s.h\t%0,%q1,%2";
+ }
+ return "extrv_s.h\t%0,%q1,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+;; EXTP*
+(define_insn "mips_extp"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (unspec:SI [(match_operand:DI 1 "register_operand" "a,a")
+ (match_operand:SI 2 "arith_operand" "I,d")
+ (reg:CCDSP CCDSP_PO_REGNUM)]
+ UNSPEC_EXTP))
+ (set (reg:CCDSP CCDSP_EF_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTP))])]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "extp\t%0,%q1,%2";
+ }
+ return "extpv\t%0,%q1,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_extpdp"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (unspec:SI [(match_operand:DI 1 "register_operand" "a,a")
+ (match_operand:SI 2 "arith_operand" "I,d")
+ (reg:CCDSP CCDSP_PO_REGNUM)]
+ UNSPEC_EXTPDP))
+ (set (reg:CCDSP CCDSP_PO_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)
+ (reg:CCDSP CCDSP_PO_REGNUM)] UNSPEC_EXTPDP))
+ (set (reg:CCDSP CCDSP_EF_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTPDP))])]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "extpdp\t%0,%q1,%2";
+ }
+ return "extpdpv\t%0,%q1,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+;; SHILO*
+(define_insn "mips_shilo"
+ [(set (match_operand:DI 0 "register_operand" "=a,a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_SHILO))]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) < -32 || INTVAL (operands[2]) > 31)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
+ return "shilo\t%q0,%2";
+ }
+ return "shilov\t%q0,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+;; MTHLIP*
+(define_insn "mips_mthlip"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:SI 2 "register_operand" "d")
+ (reg:CCDSP CCDSP_PO_REGNUM)]
+ UNSPEC_MTHLIP))
+ (set (reg:CCDSP CCDSP_PO_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)
+ (reg:CCDSP CCDSP_PO_REGNUM)] UNSPEC_MTHLIP))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "mthlip\t%2,%q0"
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+;; WRDSP
+(define_insn "mips_wrdsp"
+ [(parallel
+ [(set (reg:CCDSP CCDSP_PO_REGNUM)
+ (unspec:CCDSP [(match_operand:SI 0 "register_operand" "d")
+ (match_operand:SI 1 "const_uimm6_operand" "YA")]
+ UNSPEC_WRDSP))
+ (set (reg:CCDSP CCDSP_SC_REGNUM)
+ (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP))
+ (set (reg:CCDSP CCDSP_CA_REGNUM)
+ (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP))
+ (set (reg:CCDSP CCDSP_CC_REGNUM)
+ (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP))
+ (set (reg:CCDSP CCDSP_EF_REGNUM)
+ (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP))])]
+ "TARGET_DSP"
+ "wrdsp\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; RDDSP
+(define_insn "mips_rddsp"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "const_uimm6_operand" "YA")
+ (reg:CCDSP CCDSP_PO_REGNUM)
+ (reg:CCDSP CCDSP_SC_REGNUM)
+ (reg:CCDSP CCDSP_CA_REGNUM)
+ (reg:CCDSP CCDSP_OU_REGNUM)
+ (reg:CCDSP CCDSP_CC_REGNUM)
+ (reg:CCDSP CCDSP_EF_REGNUM)]
+ UNSPEC_RDDSP))]
+ "TARGET_DSP"
+ "rddsp\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; Table 2-7. MIPS DSP ASE Instructions: Indexed-Load
+;; L*X
+(define_insn "mips_lbux"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI (mem:QI (plus:SI (match_operand:SI 1
+ "register_operand" "d")
+ (match_operand:SI 2
+ "register_operand" "d")))))]
+ "TARGET_DSP"
+ "lbux\t%0,%2(%1)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SI")
+ (set_attr "length" "4")])
+
+(define_insn "mips_lhx"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (sign_extend:SI (mem:HI (plus:SI (match_operand:SI 1
+ "register_operand" "d")
+ (match_operand:SI 2
+ "register_operand" "d")))))]
+ "TARGET_DSP"
+ "lhx\t%0,%2(%1)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SI")
+ (set_attr "length" "4")])
+
+(define_insn "mips_lwx"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))))]
+ "TARGET_DSP"
+ "lwx\t%0,%2(%1)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SI")
+ (set_attr "length" "4")])
+
+;; Table 2-8. MIPS DSP ASE Instructions: Branch
+;; BPOSGE32
+(define_insn "mips_bposge"
+ [(set (pc)
+ (if_then_else
+ (ge:CCDSP (reg:CCDSP CCDSP_PO_REGNUM)
+ (match_operand:SI 0 "immediate_operand" "I"))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "TARGET_DSP"
+ "%*bposge%0\t%1%/"
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
diff --git a/gcc/config/mips/mips-modes.def b/gcc/config/mips/mips-modes.def
index 00dabdb..39c2f16 100644
--- a/gcc/config/mips/mips-modes.def
+++ b/gcc/config/mips/mips-modes.def
@@ -28,6 +28,7 @@ FLOAT_MODE (TF, 16, mips_quad_format);
/* Vector modes. */
VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */
+VECTOR_MODES (INT, 4); /* V4QI V2HI */
/* Paired single comparison instructions use 2 or 4 CC. */
CC_MODE (CCV2);
@@ -37,3 +38,6 @@ ADJUST_ALIGNMENT (CCV2, 8);
CC_MODE (CCV4);
ADJUST_BYTESIZE (CCV4, 16);
ADJUST_ALIGNMENT (CCV4, 16);
+
+/* For MIPS DSP control registers. */
+CC_MODE (CCDSP);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index c316ef1..63eb694 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -150,6 +150,35 @@ enum mips_function_type
MIPS_DF_FTYPE_DF,
MIPS_DF_FTYPE_DF_DF,
+ /* For MIPS DSP ASE */
+ MIPS_DI_FTYPE_DI_SI,
+ MIPS_DI_FTYPE_DI_SI_SI,
+ MIPS_DI_FTYPE_DI_V2HI_V2HI,
+ MIPS_DI_FTYPE_DI_V4QI_V4QI,
+ MIPS_SI_FTYPE_DI_SI,
+ MIPS_SI_FTYPE_PTR_SI,
+ MIPS_SI_FTYPE_SI,
+ MIPS_SI_FTYPE_SI_SI,
+ MIPS_SI_FTYPE_V2HI,
+ MIPS_SI_FTYPE_V2HI_V2HI,
+ MIPS_SI_FTYPE_V4QI,
+ MIPS_SI_FTYPE_V4QI_V4QI,
+ MIPS_SI_FTYPE_VOID,
+ MIPS_V2HI_FTYPE_SI,
+ MIPS_V2HI_FTYPE_SI_SI,
+ MIPS_V2HI_FTYPE_V2HI,
+ MIPS_V2HI_FTYPE_V2HI_SI,
+ MIPS_V2HI_FTYPE_V2HI_V2HI,
+ MIPS_V2HI_FTYPE_V4QI,
+ MIPS_V2HI_FTYPE_V4QI_V2HI,
+ MIPS_V4QI_FTYPE_SI,
+ MIPS_V4QI_FTYPE_V2HI_V2HI,
+ MIPS_V4QI_FTYPE_V4QI_SI,
+ MIPS_V4QI_FTYPE_V4QI_V4QI,
+ MIPS_VOID_FTYPE_SI_SI,
+ MIPS_VOID_FTYPE_V2HI_V2HI,
+ MIPS_VOID_FTYPE_V4QI_V4QI,
+
/* The last type. */
MIPS_MAX_FTYPE_MAX
};
@@ -162,6 +191,10 @@ enum mips_builtin_type
operands 1 and above. */
MIPS_BUILTIN_DIRECT,
+ /* The builtin corresponds directly to an .md pattern. There is no return
+ value and the arguments are mapped to operands 0 and above. */
+ MIPS_BUILTIN_DIRECT_NO_TARGET,
+
/* The builtin corresponds to a comparison instruction followed by
a mips_cond_move_tf_ps pattern. The first two arguments are the
values to compare and the second two arguments are the vector
@@ -185,7 +218,10 @@ enum mips_builtin_type
MIPS_BUILTIN_CMP_LOWER,
/* As above, but the instruction only sets a single $fcc register. */
- MIPS_BUILTIN_CMP_SINGLE
+ MIPS_BUILTIN_CMP_SINGLE,
+
+ /* For generating bposge32 branch instructions in MIPS32 DSP ASE. */
+ MIPS_BUILTIN_BPOSGE32
};
/* Invokes MACRO (COND) for each c.cond.fmt condition. */
@@ -362,13 +398,14 @@ static rtx mips_prepare_builtin_arg (enum insn_code, unsigned int, tree *);
static rtx mips_prepare_builtin_target (enum insn_code, unsigned int, rtx);
static rtx mips_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
static void mips_init_builtins (void);
-static rtx mips_expand_builtin_direct (enum insn_code, rtx, tree);
+static rtx mips_expand_builtin_direct (enum insn_code, rtx, tree, bool);
static rtx mips_expand_builtin_movtf (enum mips_builtin_type,
enum insn_code, enum mips_fp_condition,
rtx, tree);
static rtx mips_expand_builtin_compare (enum mips_builtin_type,
enum insn_code, enum mips_fp_condition,
rtx, tree);
+static rtx mips_expand_builtin_bposge (enum mips_builtin_type, rtx);
/* Structure to be filled in by compute_frame_size with register
save masks, and offsets for the current function. */
@@ -644,7 +681,10 @@ const enum reg_class mips_regno_to_class[] =
COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
- COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS
+ COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
+ DSP_ACC_REGS, DSP_ACC_REGS, DSP_ACC_REGS, DSP_ACC_REGS,
+ DSP_ACC_REGS, DSP_ACC_REGS, ALL_REGS, ALL_REGS,
+ ALL_REGS, ALL_REGS, ALL_REGS, ALL_REGS
};
/* Map register constraint character to register class. */
@@ -2608,8 +2648,8 @@ mips_subword (rtx op, int high_p)
{
if (FP_REG_P (REGNO (op)))
return gen_rtx_REG (word_mode, high_p ? REGNO (op) + 1 : REGNO (op));
- if (REGNO (op) == HI_REGNUM)
- return gen_rtx_REG (word_mode, high_p ? HI_REGNUM : LO_REGNUM);
+ if (ACC_HI_REG_P (REGNO (op)))
+ return gen_rtx_REG (word_mode, high_p ? REGNO (op) : REGNO (op) + 1);
}
if (MEM_P (op))
@@ -2723,6 +2763,14 @@ mips_output_move (rtx dest, rtx src)
if (MD_REG_P (REGNO (dest)))
return "mt%0\t%z1";
+ if (DSP_ACC_REG_P (REGNO (dest)))
+ {
+ static char retval[] = "mt__\t%z1,%q0";
+ retval[2] = reg_names[REGNO (dest)][4];
+ retval[3] = reg_names[REGNO (dest)][5];
+ return retval;
+ }
+
if (FP_REG_P (REGNO (dest)))
return (dbl_p ? "dmtc1\t%z1,%0" : "mtc1\t%z1,%0");
@@ -2741,6 +2789,14 @@ mips_output_move (rtx dest, rtx src)
{
if (src_code == REG)
{
+ if (DSP_ACC_REG_P (REGNO (src)))
+ {
+ static char retval[] = "mf__\t%0,%q1";
+ retval[2] = reg_names[REGNO (src)][4];
+ retval[3] = reg_names[REGNO (src)][5];
+ return retval;
+ }
+
if (ST_REG_P (REGNO (src)) && ISA_HAS_8CC)
return "lui\t%0,0x3f80\n\tmovf\t%0,%.,%1";
@@ -4722,6 +4778,9 @@ override_options (void)
if (TARGET_PAIRED_SINGLE_FLOAT && !ISA_MIPS64)
error ("-mips3d/-mpaired-single must be used with -mips64");
+ if (TARGET_MIPS16 && TARGET_DSP)
+ error ("-mips16 and -mdsp cannot be used together");
+
mips_print_operand_punct['?'] = 1;
mips_print_operand_punct['#'] = 1;
mips_print_operand_punct['/'] = 1;
@@ -4761,6 +4820,8 @@ override_options (void)
mips_char_to_class['B'] = COP0_REGS;
mips_char_to_class['C'] = COP2_REGS;
mips_char_to_class['D'] = COP3_REGS;
+ mips_char_to_class['A'] = DSP_ACC_REGS;
+ mips_char_to_class['a'] = ACC_REGS;
/* Set up array to map GCC register number to debug register number.
Ignore the special purpose register numbers. */
@@ -4826,10 +4887,10 @@ override_options (void)
/* Allow TFmode for CCmode reloads. */
|| (ISA_HAS_8CC && mode == TFmode));
- else if (MD_REG_P (regno))
+ else if (ACC_REG_P (regno))
temp = (INTEGRAL_MODE_P (mode)
&& (size <= UNITS_PER_WORD
- || (regno == MD_REG_FIRST
+ || (ACC_HI_REG_P (regno)
&& size == 2 * UNITS_PER_WORD)));
else if (ALL_COP_REG_P (regno))
@@ -4978,6 +5039,13 @@ override_options (void)
void
mips_conditional_register_usage (void)
{
+ if (!TARGET_DSP)
+ {
+ int regno;
+
+ for (regno = DSP_ACC_REG_FIRST; regno <= DSP_ACC_REG_LAST; regno++)
+ fixed_regs[regno] = call_used_regs[regno] = 1;
+ }
if (!TARGET_HARD_FLOAT)
{
int regno;
@@ -5122,6 +5190,7 @@ mips_debugger_offset (rtx addr, HOST_WIDE_INT offset)
'Y' for a CONST_INT X, print mips_fp_conditions[X]
'Z' print the operand and a comma for ISA_HAS_8CC, otherwise print nothing
'R' print the reloc associated with LO_SUM
+ 'q' print DSP accumulator registers
The punctuation characters are:
@@ -5372,6 +5441,22 @@ print_operand (FILE *file, rtx op, int letter)
}
}
+ else if (letter == 'q')
+ {
+ int regnum;
+
+ if (code != REG)
+ fatal_insn ("PRINT_OPERAND, invalid insn for %%q", op);
+
+ regnum = REGNO (op);
+ if (MD_REG_P (regnum))
+ fprintf (file, "$ac0");
+ else if (DSP_ACC_REG_P (regnum))
+ fprintf (file, "$ac%c", reg_names[regnum][3]);
+ else
+ fatal_insn ("PRINT_OPERAND, invalid insn for %%q", op);
+ }
+
else if (code == REG || code == SUBREG)
{
register int regnum;
@@ -7316,8 +7401,10 @@ mips_cannot_change_mode_class (enum machine_mode from,
/* LO_REGNO == HI_REGNO + 1, so if a multi-word value is stored
in LO and HI, the high word always comes first. We therefore
can't allow values stored in HI to change between single-word
- and multi-word modes. */
- if (reg_classes_intersect_p (HI_REG, class))
+ and multi-word modes.
+ This rule applies to both the original HI/LO pair and the new
+ DSP accumulators. */
+ if (reg_classes_intersect_p (ACC_REGS, class))
return true;
}
}
@@ -7398,8 +7485,10 @@ mips_secondary_reload_class (enum reg_class class,
}
/* Copying from HI or LO to anywhere other than a general register
- requires a general register. */
- if (class == HI_REG || class == LO_REG || class == MD_REGS)
+ requires a general register.
+ This rule applies to both the original HI/LO pair and the new
+ DSP accumulators. */
+ if (reg_class_subset_p (class, ACC_REGS))
{
if (TARGET_MIPS16 && in_p)
{
@@ -7408,7 +7497,7 @@ mips_secondary_reload_class (enum reg_class class,
}
return gp_reg_p ? NO_REGS : gr_regs;
}
- if (MD_REG_P (regno))
+ if (ACC_REG_P (regno))
{
if (TARGET_MIPS16 && ! in_p)
{
@@ -7519,10 +7608,18 @@ mips_valid_pointer_mode (enum machine_mode mode)
static bool
mips_vector_mode_supported_p (enum machine_mode mode)
{
- if (mode == V2SFmode && TARGET_PAIRED_SINGLE_FLOAT)
- return true;
- else
- return false;
+ switch (mode)
+ {
+ case V2SFmode:
+ return TARGET_PAIRED_SINGLE_FLOAT;
+
+ case V2HImode:
+ case V4QImode:
+ return TARGET_DSP;
+
+ default:
+ return false;
+ }
}
/* If we can access small data directly (using gp-relative relocation
@@ -8887,7 +8984,7 @@ mips_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
}
else if (to == FP_REGS)
return 4;
- else if (to == HI_REG || to == LO_REG || to == MD_REGS)
+ else if (reg_class_subset_p (to, ACC_REGS))
{
if (TARGET_MIPS16)
return 12;
@@ -8908,7 +9005,7 @@ mips_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
else if (to == ST_REGS)
return 8;
}
- else if (from == HI_REG || from == LO_REG || from == MD_REGS)
+ else if (reg_class_subset_p (from, ACC_REGS))
{
if (GR_REG_CLASS_P (to))
{
@@ -9910,6 +10007,116 @@ static const struct builtin_description sb1_bdesc[] =
DIRECT_BUILTIN (sqrt_ps, MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT)
};
+/* Builtin functions for DSP ASE. */
+
+#define CODE_FOR_mips_addq_ph CODE_FOR_addv2hi3
+#define CODE_FOR_mips_addu_qb CODE_FOR_addv4qi3
+#define CODE_FOR_mips_subq_ph CODE_FOR_subv2hi3
+#define CODE_FOR_mips_subu_qb CODE_FOR_subv4qi3
+
+/* Define a MIPS_BUILTIN_DIRECT_NO_TARGET function for instruction
+ CODE_FOR_mips_<INSN>. FUNCTION_TYPE and TARGET_FLAGS are
+ builtin_description fields. */
+#define DIRECT_NO_TARGET_BUILTIN(INSN, FUNCTION_TYPE, TARGET_FLAGS) \
+ { CODE_FOR_mips_ ## INSN, 0, "__builtin_mips_" #INSN, \
+ MIPS_BUILTIN_DIRECT_NO_TARGET, FUNCTION_TYPE, TARGET_FLAGS }
+
+/* Define __builtin_mips_bposge<VALUE>. <VALUE> is 32 for the MIPS32 DSP
+ branch instruction. TARGET_FLAGS is a builtin_description field. */
+#define BPOSGE_BUILTIN(VALUE, TARGET_FLAGS) \
+ { CODE_FOR_mips_bposge, 0, "__builtin_mips_bposge" #VALUE, \
+ MIPS_BUILTIN_BPOSGE ## VALUE, MIPS_SI_FTYPE_VOID, TARGET_FLAGS }
+
+static const struct builtin_description dsp_bdesc[] =
+{
+ DIRECT_BUILTIN (addq_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (addq_s_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (addq_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (addu_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (addu_s_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (subq_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (subq_s_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (subq_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (subu_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (subu_s_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (addsc, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (addwc, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (modsub, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (raddu_w_qb, MIPS_SI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (absq_s_ph, MIPS_V2HI_FTYPE_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (absq_s_w, MIPS_SI_FTYPE_SI, MASK_DSP),
+ DIRECT_BUILTIN (precrq_qb_ph, MIPS_V4QI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (precrq_ph_w, MIPS_V2HI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (precrq_rs_ph_w, MIPS_V2HI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (precrqu_s_qb_ph, MIPS_V4QI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (preceq_w_phl, MIPS_SI_FTYPE_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (preceq_w_phr, MIPS_SI_FTYPE_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (precequ_ph_qbl, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (precequ_ph_qbr, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (precequ_ph_qbla, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (precequ_ph_qbra, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (preceu_ph_qbl, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (preceu_ph_qbr, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (preceu_ph_qbla, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (preceu_ph_qbra, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (shll_qb, MIPS_V4QI_FTYPE_V4QI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shll_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shll_s_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shll_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shrl_qb, MIPS_V4QI_FTYPE_V4QI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shra_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shra_r_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shra_r_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (muleu_s_ph_qbl, MIPS_V2HI_FTYPE_V4QI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (muleu_s_ph_qbr, MIPS_V2HI_FTYPE_V4QI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (mulq_rs_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (muleq_s_w_phl, MIPS_SI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (muleq_s_w_phr, MIPS_SI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (dpau_h_qbl, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (dpau_h_qbr, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (dpsu_h_qbl, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (dpsu_h_qbr, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (dpaq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (dpsq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (mulsaq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (dpaq_sa_l_w, MIPS_DI_FTYPE_DI_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (dpsq_sa_l_w, MIPS_DI_FTYPE_DI_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (maq_s_w_phl, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (maq_s_w_phr, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (maq_sa_w_phl, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (maq_sa_w_phr, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (bitrev, MIPS_SI_FTYPE_SI, MASK_DSP),
+ DIRECT_BUILTIN (insv, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (repl_qb, MIPS_V4QI_FTYPE_SI, MASK_DSP),
+ DIRECT_BUILTIN (repl_ph, MIPS_V2HI_FTYPE_SI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmpu_eq_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmpu_lt_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmpu_le_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (cmpgu_eq_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (cmpgu_lt_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (cmpgu_le_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmp_eq_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmp_lt_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmp_le_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (pick_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (pick_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (packrl_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (extr_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extr_r_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extr_rs_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extr_s_h, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extp, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extpdp, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shilo, MIPS_DI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (mthlip, MIPS_DI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (wrdsp, MIPS_VOID_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (rddsp, MIPS_SI_FTYPE_SI, MASK_DSP),
+ DIRECT_BUILTIN (lbux, MIPS_SI_FTYPE_PTR_SI, MASK_DSP),
+ DIRECT_BUILTIN (lhx, MIPS_SI_FTYPE_PTR_SI, MASK_DSP),
+ DIRECT_BUILTIN (lwx, MIPS_SI_FTYPE_PTR_SI, MASK_DSP),
+ BPOSGE_BUILTIN (32, MASK_DSP)
+};
+
/* This helps provide a mapping from builtin function codes to bdesc
arrays. */
@@ -9929,7 +10136,8 @@ struct bdesc_map
static const struct bdesc_map bdesc_arrays[] =
{
{ mips_bdesc, ARRAY_SIZE (mips_bdesc), PROCESSOR_MAX },
- { sb1_bdesc, ARRAY_SIZE (sb1_bdesc), PROCESSOR_SB1 }
+ { sb1_bdesc, ARRAY_SIZE (sb1_bdesc), PROCESSOR_SB1 },
+ { dsp_bdesc, ARRAY_SIZE (dsp_bdesc), PROCESSOR_MAX }
};
/* Take the head of argument list *ARGLIST and convert it into a form
@@ -9946,7 +10154,15 @@ mips_prepare_builtin_arg (enum insn_code icode,
value = expand_expr (TREE_VALUE (*arglist), NULL_RTX, VOIDmode, 0);
mode = insn_data[icode].operand[op].mode;
if (!insn_data[icode].operand[op].predicate (value, mode))
- value = copy_to_mode_reg (mode, value);
+ {
+ value = copy_to_mode_reg (mode, value);
+ /* Check the predicate again. */
+ if (!insn_data[icode].operand[op].predicate (value, mode))
+ {
+ error ("invalid argument to builtin function");
+ return const0_rtx;
+ }
+ }
*arglist = TREE_CHAIN (*arglist);
return value;
@@ -10003,7 +10219,10 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
switch (type)
{
case MIPS_BUILTIN_DIRECT:
- return mips_expand_builtin_direct (icode, target, arglist);
+ return mips_expand_builtin_direct (icode, target, arglist, true);
+
+ case MIPS_BUILTIN_DIRECT_NO_TARGET:
+ return mips_expand_builtin_direct (icode, target, arglist, false);
case MIPS_BUILTIN_MOVT:
case MIPS_BUILTIN_MOVF:
@@ -10018,6 +10237,9 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
return mips_expand_builtin_compare (type, icode, bdesc[fcode].cond,
target, arglist);
+ case MIPS_BUILTIN_BPOSGE32:
+ return mips_expand_builtin_bposge (type, target);
+
default:
return 0;
}
@@ -10032,70 +10254,214 @@ mips_init_builtins (void)
const struct bdesc_map *m;
tree types[(int) MIPS_MAX_FTYPE_MAX];
tree V2SF_type_node;
+ tree V2HI_type_node;
+ tree V4QI_type_node;
unsigned int offset;
- /* We have only builtins for -mpaired-single and -mips3d. */
- if (!TARGET_PAIRED_SINGLE_FLOAT)
+ /* We have only builtins for -mpaired-single, -mips3d and -mdsp. */
+ if (!TARGET_PAIRED_SINGLE_FLOAT && !TARGET_DSP)
return;
- V2SF_type_node = build_vector_type_for_mode (float_type_node, V2SFmode);
-
- types[MIPS_V2SF_FTYPE_V2SF]
- = build_function_type_list (V2SF_type_node, V2SF_type_node, NULL_TREE);
-
- types[MIPS_V2SF_FTYPE_V2SF_V2SF]
- = build_function_type_list (V2SF_type_node,
- V2SF_type_node, V2SF_type_node, NULL_TREE);
-
- types[MIPS_V2SF_FTYPE_V2SF_V2SF_INT]
- = build_function_type_list (V2SF_type_node,
- V2SF_type_node, V2SF_type_node,
- integer_type_node, NULL_TREE);
-
- types[MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF]
- = build_function_type_list (V2SF_type_node,
- V2SF_type_node, V2SF_type_node,
- V2SF_type_node, V2SF_type_node, NULL_TREE);
+ if (TARGET_PAIRED_SINGLE_FLOAT)
+ {
+ V2SF_type_node = build_vector_type_for_mode (float_type_node, V2SFmode);
- types[MIPS_V2SF_FTYPE_SF_SF]
- = build_function_type_list (V2SF_type_node,
- float_type_node, float_type_node, NULL_TREE);
+ types[MIPS_V2SF_FTYPE_V2SF]
+ = build_function_type_list (V2SF_type_node, V2SF_type_node, NULL_TREE);
- types[MIPS_INT_FTYPE_V2SF_V2SF]
- = build_function_type_list (integer_type_node,
- V2SF_type_node, V2SF_type_node, NULL_TREE);
+ types[MIPS_V2SF_FTYPE_V2SF_V2SF]
+ = build_function_type_list (V2SF_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
- types[MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF]
- = build_function_type_list (integer_type_node,
- V2SF_type_node, V2SF_type_node,
- V2SF_type_node, V2SF_type_node, NULL_TREE);
+ types[MIPS_V2SF_FTYPE_V2SF_V2SF_INT]
+ = build_function_type_list (V2SF_type_node,
+ V2SF_type_node, V2SF_type_node,
+ integer_type_node, NULL_TREE);
- types[MIPS_INT_FTYPE_SF_SF]
- = build_function_type_list (integer_type_node,
- float_type_node, float_type_node, NULL_TREE);
+ types[MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF]
+ = build_function_type_list (V2SF_type_node,
+ V2SF_type_node, V2SF_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
- types[MIPS_INT_FTYPE_DF_DF]
- = build_function_type_list (integer_type_node,
- double_type_node, double_type_node, NULL_TREE);
+ types[MIPS_V2SF_FTYPE_SF_SF]
+ = build_function_type_list (V2SF_type_node,
+ float_type_node, float_type_node, NULL_TREE);
- types[MIPS_SF_FTYPE_V2SF]
- = build_function_type_list (float_type_node, V2SF_type_node, NULL_TREE);
+ types[MIPS_INT_FTYPE_V2SF_V2SF]
+ = build_function_type_list (integer_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
- types[MIPS_SF_FTYPE_SF]
- = build_function_type_list (float_type_node,
- float_type_node, NULL_TREE);
+ types[MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF]
+ = build_function_type_list (integer_type_node,
+ V2SF_type_node, V2SF_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
- types[MIPS_SF_FTYPE_SF_SF]
- = build_function_type_list (float_type_node,
- float_type_node, float_type_node, NULL_TREE);
+ types[MIPS_INT_FTYPE_SF_SF]
+ = build_function_type_list (integer_type_node,
+ float_type_node, float_type_node, NULL_TREE);
- types[MIPS_DF_FTYPE_DF]
- = build_function_type_list (double_type_node,
- double_type_node, NULL_TREE);
+ types[MIPS_INT_FTYPE_DF_DF]
+ = build_function_type_list (integer_type_node,
+ double_type_node, double_type_node, NULL_TREE);
- types[MIPS_DF_FTYPE_DF_DF]
- = build_function_type_list (double_type_node,
- double_type_node, double_type_node, NULL_TREE);
+ types[MIPS_SF_FTYPE_V2SF]
+ = build_function_type_list (float_type_node, V2SF_type_node, NULL_TREE);
+
+ types[MIPS_SF_FTYPE_SF]
+ = build_function_type_list (float_type_node,
+ float_type_node, NULL_TREE);
+
+ types[MIPS_SF_FTYPE_SF_SF]
+ = build_function_type_list (float_type_node,
+ float_type_node, float_type_node, NULL_TREE);
+
+ types[MIPS_DF_FTYPE_DF]
+ = build_function_type_list (double_type_node,
+ double_type_node, NULL_TREE);
+
+ types[MIPS_DF_FTYPE_DF_DF]
+ = build_function_type_list (double_type_node,
+ double_type_node, double_type_node, NULL_TREE);
+ }
+
+ if (TARGET_DSP)
+ {
+ V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
+ V4QI_type_node = build_vector_type_for_mode (intQI_type_node, V4QImode);
+
+ types[MIPS_V2HI_FTYPE_V2HI_V2HI]
+ = build_function_type_list (V2HI_type_node,
+ V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_SI_SI]
+ = build_function_type_list (intSI_type_node,
+ intSI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V4QI_FTYPE_V4QI_V4QI]
+ = build_function_type_list (V4QI_type_node,
+ V4QI_type_node, V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_V4QI]
+ = build_function_type_list (intSI_type_node,
+ V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_V2HI]
+ = build_function_type_list (V2HI_type_node,
+ V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_SI]
+ = build_function_type_list (intSI_type_node,
+ intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V4QI_FTYPE_V2HI_V2HI]
+ = build_function_type_list (V4QI_type_node,
+ V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_SI_SI]
+ = build_function_type_list (V2HI_type_node,
+ intSI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_V2HI]
+ = build_function_type_list (intSI_type_node,
+ V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_V4QI]
+ = build_function_type_list (V2HI_type_node,
+ V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V4QI_FTYPE_V4QI_SI]
+ = build_function_type_list (V4QI_type_node,
+ V4QI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_V2HI_SI]
+ = build_function_type_list (V2HI_type_node,
+ V2HI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_V4QI_V2HI]
+ = build_function_type_list (V2HI_type_node,
+ V4QI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_V2HI_V2HI]
+ = build_function_type_list (intSI_type_node,
+ V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_DI_FTYPE_DI_V4QI_V4QI]
+ = build_function_type_list (intDI_type_node,
+ intDI_type_node, V4QI_type_node, V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_DI_FTYPE_DI_V2HI_V2HI]
+ = build_function_type_list (intDI_type_node,
+ intDI_type_node, V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_DI_FTYPE_DI_SI_SI]
+ = build_function_type_list (intDI_type_node,
+ intDI_type_node, intSI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V4QI_FTYPE_SI]
+ = build_function_type_list (V4QI_type_node,
+ intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_SI]
+ = build_function_type_list (V2HI_type_node,
+ intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_VOID_FTYPE_V4QI_V4QI]
+ = build_function_type_list (void_type_node,
+ V4QI_type_node, V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_V4QI_V4QI]
+ = build_function_type_list (intSI_type_node,
+ V4QI_type_node, V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_VOID_FTYPE_V2HI_V2HI]
+ = build_function_type_list (void_type_node,
+ V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_DI_SI]
+ = build_function_type_list (intSI_type_node,
+ intDI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_DI_FTYPE_DI_SI]
+ = build_function_type_list (intDI_type_node,
+ intDI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_VOID_FTYPE_SI_SI]
+ = build_function_type_list (void_type_node,
+ intSI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_PTR_SI]
+ = build_function_type_list (intSI_type_node,
+ ptr_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_VOID]
+ = build_function_type (intSI_type_node, void_list_node);
+ }
/* Iterate through all of the bdesc arrays, initializing all of the
builtin functions. */
@@ -10115,30 +10481,40 @@ mips_init_builtins (void)
/* Expand a MIPS_BUILTIN_DIRECT function. ICODE is the code of the
.md pattern and ARGLIST is the list of function arguments. TARGET,
- if nonnull, suggests a good place to put the result. */
+ if nonnull, suggests a good place to put the result.
+ HAS_TARGET indicates the function must return something. */
static rtx
-mips_expand_builtin_direct (enum insn_code icode, rtx target, tree arglist)
+mips_expand_builtin_direct (enum insn_code icode, rtx target, tree arglist,
+ bool has_target)
{
rtx ops[MAX_RECOG_OPERANDS];
- int i;
+ int i = 0;
- target = mips_prepare_builtin_target (icode, 0, target);
- for (i = 1; i < insn_data[icode].n_operands; i++)
+ if (has_target)
+ {
+ /* We save target to ops[0]. */
+ ops[0] = mips_prepare_builtin_target (icode, 0, target);
+ i = 1;
+ }
+
+ /* We need to test if arglist is not zero. Some instructions have extra
+ clobber registers. */
+ for (; i < insn_data[icode].n_operands && arglist != 0; i++)
ops[i] = mips_prepare_builtin_arg (icode, i, &arglist);
- switch (insn_data[icode].n_operands)
+ switch (i)
{
case 2:
- emit_insn (GEN_FCN (icode) (target, ops[1]));
+ emit_insn (GEN_FCN (icode) (ops[0], ops[1]));
break;
case 3:
- emit_insn (GEN_FCN (icode) (target, ops[1], ops[2]));
+ emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2]));
break;
case 4:
- emit_insn (GEN_FCN (icode) (target, ops[1], ops[2], ops[3]));
+ emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3]));
break;
default:
@@ -10268,5 +10644,59 @@ mips_expand_builtin_compare (enum mips_builtin_type builtin_type,
return target;
}
+
+/* Expand a bposge builtin of type BUILTIN_TYPE. TARGET, if nonnull,
+ suggests a good place to put the boolean result.
+
+ The sequence we want is
+
+ li target, 0
+ bposge* label1
+ j label2
+ label1:
+ li target, 1
+ label2: */
+
+static rtx
+mips_expand_builtin_bposge (enum mips_builtin_type builtin_type, rtx target)
+{
+ rtx label1, label2, if_then_else;
+ rtx cmp_result;
+ int cmp_value;
+
+ if (target == 0 || GET_MODE (target) != SImode)
+ target = gen_reg_rtx (SImode);
+
+ cmp_result = gen_rtx_REG (CCDSPmode, CCDSP_PO_REGNUM);
+
+ if (builtin_type == MIPS_BUILTIN_BPOSGE32)
+ cmp_value = 32;
+ else
+ gcc_assert (0);
+
+ /* Move 0 to target */
+ emit_move_insn (target, const0_rtx);
+
+ /* Generate two labels */
+ label1 = gen_label_rtx ();
+ label2 = gen_label_rtx ();
+
+ /* Generate if_then_else */
+ if_then_else
+ = gen_rtx_IF_THEN_ELSE (VOIDmode,
+ gen_rtx_fmt_ee (GE, CCDSPmode,
+ cmp_result, GEN_INT (cmp_value)),
+ gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx);
+
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else));
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
+ gen_rtx_LABEL_REF (VOIDmode, label2)));
+ emit_barrier ();
+ emit_label (label1);
+ emit_move_insn (target, const1_rtx);
+ emit_label (label2);
+
+ return target;
+}
#include "gt-mips.h"
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 8bb3d50..cc38e11 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -316,6 +316,9 @@ extern const struct mips_rtx_cost_data *mips_cost;
if (TARGET_MIPS3D) \
builtin_define ("__mips3d"); \
\
+ if (TARGET_DSP) \
+ builtin_define ("__mips_dsp"); \
+ \
MIPS_CPP_SET_PROCESSOR ("_MIPS_ARCH", mips_arch_info); \
MIPS_CPP_SET_PROCESSOR ("_MIPS_TUNE", mips_tune_info); \
\
@@ -807,6 +810,7 @@ extern const struct mips_rtx_cost_data *mips_cost;
%{mips32} %{mips32r2} %{mips64} \
%{mips16:%{!mno-mips16:-mips16}} %{mno-mips16:-no-mips16} \
%{mips3d:-mips3d} \
+%{mdsp} \
%{mfix-vr4120} %{mfix-vr4130} \
%(subtarget_asm_optimizing_spec) \
%(subtarget_asm_debugging_spec) \
@@ -1149,9 +1153,11 @@ extern const struct mips_rtx_cost_data *mips_cost;
- ARG_POINTER_REGNUM
- FRAME_POINTER_REGNUM
- FAKE_CALL_REGNO (see the comment above load_callsi for details)
- - 3 dummy entries that were used at various times in the past. */
+ - 3 dummy entries that were used at various times in the past.
+ - 6 DSP accumulator registers (3 hi-lo pairs) for MIPS DSP ASE
+ - 6 DSP control registers */
-#define FIRST_PSEUDO_REGISTER 176
+#define FIRST_PSEUDO_REGISTER 188
/* By default, fix the kernel registers ($26 and $27), the global
pointer ($28) and the stack pointer ($29). This can change
@@ -1178,7 +1184,9 @@ extern const struct mips_rtx_cost_data *mips_cost;
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
/* COP3 registers */ \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* 6 DSP accumulator registers & 6 control registers */ \
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 \
}
@@ -1208,7 +1216,9 @@ extern const struct mips_rtx_cost_data *mips_cost;
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
/* COP3 registers */ \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* 6 DSP accumulator registers & 6 control registers */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \
}
@@ -1231,7 +1241,9 @@ extern const struct mips_rtx_cost_data *mips_cost;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
/* COP3 registers */ \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ /* 6 DSP accumulator registers & 6 control registers */ \
+ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 \
}
/* Internal macros to classify a register number as to whether it's a
@@ -1273,9 +1285,19 @@ extern const struct mips_rtx_cost_data *mips_cost;
/* ALL_COP_REG_NUM assumes that COP0,2,and 3 are numbered consecutively. */
#define ALL_COP_REG_NUM (COP3_REG_LAST - COP0_REG_FIRST + 1)
+#define DSP_ACC_REG_FIRST 176
+#define DSP_ACC_REG_LAST 181
+#define DSP_ACC_REG_NUM (DSP_ACC_REG_LAST - DSP_ACC_REG_FIRST + 1)
+
#define AT_REGNUM (GP_REG_FIRST + 1)
#define HI_REGNUM (MD_REG_FIRST + 0)
#define LO_REGNUM (MD_REG_FIRST + 1)
+#define AC1HI_REGNUM (DSP_ACC_REG_FIRST + 0)
+#define AC1LO_REGNUM (DSP_ACC_REG_FIRST + 1)
+#define AC2HI_REGNUM (DSP_ACC_REG_FIRST + 2)
+#define AC2LO_REGNUM (DSP_ACC_REG_FIRST + 3)
+#define AC3HI_REGNUM (DSP_ACC_REG_FIRST + 4)
+#define AC3LO_REGNUM (DSP_ACC_REG_FIRST + 5)
/* FPSW_REGNUM is the single condition code used if !ISA_HAS_8CC.
If ISA_HAS_8CC, it should not be used, and an arbitrary ST_REG
@@ -1300,6 +1322,16 @@ extern const struct mips_rtx_cost_data *mips_cost;
((unsigned int) ((int) (REGNO) - COP3_REG_FIRST) < COP3_REG_NUM)
#define ALL_COP_REG_P(REGNO) \
((unsigned int) ((int) (REGNO) - COP0_REG_FIRST) < ALL_COP_REG_NUM)
+/* Test if REGNO is one of the 6 new DSP accumulators. */
+#define DSP_ACC_REG_P(REGNO) \
+ ((unsigned int) ((int) (REGNO) - DSP_ACC_REG_FIRST) < DSP_ACC_REG_NUM)
+/* Test if REGNO is hi, lo, or one of the 6 new DSP accumulators. */
+#define ACC_REG_P(REGNO) \
+ (MD_REG_P (REGNO) || DSP_ACC_REG_P (REGNO))
+/* Test if REGNO is HI or the first register of 3 new DSP accumulator pairs. */
+#define ACC_HI_REG_P(REGNO) \
+ ((REGNO) == HI_REGNUM || (REGNO) == AC1HI_REGNUM || (REGNO) == AC2HI_REGNUM \
+ || (REGNO) == AC3HI_REGNUM)
#define FP_REG_RTX_P(X) (REG_P (X) && FP_REG_P (REGNO (X)))
@@ -1442,6 +1474,8 @@ enum reg_class
ALL_COP_REGS,
ALL_COP_AND_GR_REGS,
ST_REGS, /* status registers (fp status) */
+ DSP_ACC_REGS, /* DSP accumulator registers */
+ ACC_REGS, /* Hi/Lo and DSP accumulator registers */
ALL_REGS, /* all registers */
LIM_REG_CLASSES /* max value + 1 */
};
@@ -1482,6 +1516,8 @@ enum reg_class
"ALL_COP_REGS", \
"ALL_COP_AND_GR_REGS", \
"ST_REGS", \
+ "DSP_ACC_REGS", \
+ "ACC_REGS", \
"ALL_REGS" \
}
@@ -1523,7 +1559,9 @@ enum reg_class
{ 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x0000ffff }, \
{ 0xffffffff, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x0000ffff }, \
{ 0x00000000, 0x00000000, 0x000007f8, 0x00000000, 0x00000000, 0x00000000 }, /* status registers */ \
- { 0xffffffff, 0xffffffff, 0xffff07ff, 0xffffffff, 0xffffffff, 0x0000ffff } /* all registers */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x003f0000 }, /* dsp accumulator registers */ \
+ { 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x003f0000 }, /* hi/lo and dsp accumulator registers */ \
+ { 0xffffffff, 0xffffffff, 0xffff07ff, 0xffffffff, 0xffffffff, 0x0fffffff } /* all registers */ \
}
@@ -1584,7 +1622,8 @@ extern const enum reg_class mips_regno_to_class[];
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, \
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, \
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, \
- 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175 \
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, \
+ 176,177,178,179,180,181,182,183,184,185,186,187 \
}
/* ORDER_REGS_FOR_LOCAL_ALLOC is a macro which permits reg_alloc_order
@@ -1615,12 +1654,24 @@ extern const enum reg_class mips_regno_to_class[];
'B' Cop0 register
'C' Cop2 register
'D' Cop3 register
+ 'A' DSP accumulator registers
+ 'a' MD registers and DSP accumulator registers
'b' All registers */
extern enum reg_class mips_char_to_class[256];
#define REG_CLASS_FROM_LETTER(C) mips_char_to_class[(unsigned char)(C)]
+/* True if VALUE is a unsigned 6-bit number. */
+
+#define UIMM6_OPERAND(VALUE) \
+ (((VALUE) & ~(unsigned HOST_WIDE_INT) 0x3f) == 0)
+
+/* True if VALUE is a signed 10-bit number. */
+
+#define IMM10_OPERAND(VALUE) \
+ ((unsigned HOST_WIDE_INT) (VALUE) + 0x200 < 0x400)
+
/* True if VALUE is a signed 16-bit number. */
#define SMALL_OPERAND(VALUE) \
@@ -1718,11 +1769,17 @@ extern enum reg_class mips_char_to_class[256];
This is true for all non-mips16 references (although it can sometimes
be indirect if !TARGET_EXPLICIT_RELOCS). For mips16, it excludes
stack and constant-pool references.
- `YG' is for 0 valued vector constants. */
+ `YG' is for 0 valued vector constants.
+ `YA' is for unsigned 6-bit constants.
+ `YB' is for signed 10-bit constants. */
#define EXTRA_CONSTRAINT_Y(OP,STR) \
(((STR)[1] == 'G') ? (GET_CODE (OP) == CONST_VECTOR \
&& (OP) == CONST0_RTX (GET_MODE (OP))) \
+ : ((STR)[1] == 'A') ? (GET_CODE (OP) == CONST_INT \
+ && UIMM6_OPERAND (INTVAL (OP))) \
+ : ((STR)[1] == 'B') ? (GET_CODE (OP) == CONST_INT \
+ && IMM10_OPERAND (INTVAL (OP))) \
: FALSE)
@@ -2386,7 +2443,9 @@ typedef struct mips_args {
"$c3r0", "$c3r1", "$c3r2", "$c3r3", "$c3r4", "$c3r5", "$c3r6", "$c3r7", \
"$c3r8", "$c3r9", "$c3r10","$c3r11","$c3r12","$c3r13","$c3r14","$c3r15", \
"$c3r16","$c3r17","$c3r18","$c3r19","$c3r20","$c3r21","$c3r22","$c3r23", \
- "$c3r24","$c3r25","$c3r26","$c3r27","$c3r28","$c3r29","$c3r30","$c3r31" }
+ "$c3r24","$c3r25","$c3r26","$c3r27","$c3r28","$c3r29","$c3r30","$c3r31", \
+ "$ac1hi","$ac1lo","$ac2hi","$ac2lo","$ac3hi","$ac3lo","$dsp_po","$dsp_sc", \
+ "$dsp_ca","$dsp_ou","$dsp_cc","$dsp_ef" }
/* List the "software" names for each register. Also list the numerical
names for $fp and $sp. */
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index bf4bc69..a43a0c2 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -72,6 +72,76 @@
(UNSPEC_RSQRT2 209)
(UNSPEC_RECIP1 210)
(UNSPEC_RECIP2 211)
+
+ ;; MIPS DSP ASE Revision 0.98 3/24/2005
+ (UNSPEC_ADDQ 300)
+ (UNSPEC_ADDQ_S 301)
+ (UNSPEC_SUBQ 302)
+ (UNSPEC_SUBQ_S 303)
+ (UNSPEC_ADDSC 304)
+ (UNSPEC_ADDWC 305)
+ (UNSPEC_MODSUB 306)
+ (UNSPEC_RADDU_W_QB 307)
+ (UNSPEC_ABSQ_S 308)
+ (UNSPEC_PRECRQ_QB_PH 309)
+ (UNSPEC_PRECRQ_PH_W 310)
+ (UNSPEC_PRECRQ_RS_PH_W 311)
+ (UNSPEC_PRECRQU_S_QB_PH 312)
+ (UNSPEC_PRECEQ_W_PHL 313)
+ (UNSPEC_PRECEQ_W_PHR 314)
+ (UNSPEC_PRECEQU_PH_QBL 315)
+ (UNSPEC_PRECEQU_PH_QBR 316)
+ (UNSPEC_PRECEQU_PH_QBLA 317)
+ (UNSPEC_PRECEQU_PH_QBRA 318)
+ (UNSPEC_PRECEU_PH_QBL 319)
+ (UNSPEC_PRECEU_PH_QBR 320)
+ (UNSPEC_PRECEU_PH_QBLA 321)
+ (UNSPEC_PRECEU_PH_QBRA 322)
+ (UNSPEC_SHLL 323)
+ (UNSPEC_SHLL_S 324)
+ (UNSPEC_SHRL_QB 325)
+ (UNSPEC_SHRA_PH 326)
+ (UNSPEC_SHRA_R 327)
+ (UNSPEC_MULEU_S_PH_QBL 328)
+ (UNSPEC_MULEU_S_PH_QBR 329)
+ (UNSPEC_MULQ_RS_PH 330)
+ (UNSPEC_MULEQ_S_W_PHL 331)
+ (UNSPEC_MULEQ_S_W_PHR 332)
+ (UNSPEC_DPAU_H_QBL 333)
+ (UNSPEC_DPAU_H_QBR 334)
+ (UNSPEC_DPSU_H_QBL 335)
+ (UNSPEC_DPSU_H_QBR 336)
+ (UNSPEC_DPAQ_S_W_PH 337)
+ (UNSPEC_DPSQ_S_W_PH 338)
+ (UNSPEC_MULSAQ_S_W_PH 339)
+ (UNSPEC_DPAQ_SA_L_W 340)
+ (UNSPEC_DPSQ_SA_L_W 341)
+ (UNSPEC_MAQ_S_W_PHL 342)
+ (UNSPEC_MAQ_S_W_PHR 343)
+ (UNSPEC_MAQ_SA_W_PHL 344)
+ (UNSPEC_MAQ_SA_W_PHR 345)
+ (UNSPEC_BITREV 346)
+ (UNSPEC_INSV 347)
+ (UNSPEC_REPL_QB 348)
+ (UNSPEC_REPL_PH 349)
+ (UNSPEC_CMP_EQ 350)
+ (UNSPEC_CMP_LT 351)
+ (UNSPEC_CMP_LE 352)
+ (UNSPEC_CMPGU_EQ_QB 353)
+ (UNSPEC_CMPGU_LT_QB 354)
+ (UNSPEC_CMPGU_LE_QB 355)
+ (UNSPEC_PICK 356)
+ (UNSPEC_PACKRL_PH 357)
+ (UNSPEC_EXTR_W 358)
+ (UNSPEC_EXTR_R_W 359)
+ (UNSPEC_EXTR_RS_W 360)
+ (UNSPEC_EXTR_S_H 361)
+ (UNSPEC_EXTP 362)
+ (UNSPEC_EXTPDP 363)
+ (UNSPEC_SHILO 364)
+ (UNSPEC_MTHLIP 365)
+ (UNSPEC_WRDSP 366)
+ (UNSPEC_RDDSP 367)
]
)
@@ -3124,8 +3194,8 @@
(set_attr "mode" "<MODE>")])
(define_insn "*movdi_32bit"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*x,*d,*B*C*D,*B*C*D,*d,*m")
- (match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*x,*d,*m,*B*C*D,*B*C*D"))]
+ [(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
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
@@ -3242,15 +3312,15 @@
;; in FP registers (off by default, use -mdebugh to enable).
(define_insn "*movsi_internal"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*d,*z,*x,*B*C*D,*B*C*D,*d,*m")
- (match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*z,*d,*J*d,*d,*m,*B*C*D,*B*C*D"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m")
+ (match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*z,*d,*J*d,*A,*d,*m,*B*C*D,*B*C*D"))]
"!TARGET_MIPS16
&& (register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "type" "arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,xfer,xfer,mthilo,xfer,load,xfer,store")
+ [(set_attr "type" "arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,xfer,xfer,mthilo,mfhilo,xfer,load,xfer,store")
(set_attr "mode" "SI")
- (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,4,4,4,*,4,*")])
+ (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,4,4,4,4,*,4,*")])
(define_insn "*movsi_mips16"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m")
@@ -5353,3 +5423,7 @@
; The MIPS Paired-Single Floating Point and MIPS-3D Instructions.
(include "mips-ps-3d.md")
+
+; The MIPS DSP Instructions.
+
+(include "mips-dsp.md")
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index 6bd719a..737f5ed 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -55,6 +55,10 @@ mdouble-float
Target Report RejectNegative InverseMask(SINGLE_FLOAT, DOUBLE_FLOAT)
Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations
+mdsp
+Target Report Mask(DSP)
+Use MIPS-DSP instructions
+
mdebug
Target Var(TARGET_DEBUG_MODE) Undocumented
diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md
index 1fc3c6e..e4e3805 100644
--- a/gcc/config/mips/predicates.md
+++ b/gcc/config/mips/predicates.md
@@ -34,6 +34,18 @@
(ior (match_operand 0 "const_arith_operand")
(match_operand 0 "register_operand")))
+(define_predicate "const_uimm6_operand"
+ (and (match_code "const_int")
+ (match_test "UIMM6_OPERAND (INTVAL (op))")))
+
+(define_predicate "const_imm10_operand"
+ (and (match_code "const_int")
+ (match_test "IMM10_OPERAND (INTVAL (op))")))
+
+(define_predicate "reg_imm10_operand"
+ (ior (match_operand 0 "const_imm10_operand")
+ (match_operand 0 "register_operand")))
+
(define_predicate "sle_operand"
(and (match_code "const_int")
(match_test "SMALL_OPERAND (INTVAL (op) + 1)")))
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 69bd151..7e13795 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -5777,6 +5777,7 @@ instructions, but allow the compiler to schedule those calls.
* Blackfin Built-in Functions::
* FR-V Built-in Functions::
* X86 Built-in Functions::
+* MIPS DSP Built-in Functions::
* MIPS Paired-Single Support::
* PowerPC AltiVec Built-in Functions::
* SPARC VIS Built-in Functions::
@@ -6676,6 +6677,208 @@ v2sf __builtin_ia32_pswapdsf (v2sf)
v2si __builtin_ia32_pswapdsi (v2si)
@end smallexample
+@node MIPS DSP Built-in Functions
+@subsection MIPS DSP Built-in Functions
+
+The MIPS DSP Application-Specific Extension (ASE) includes new
+instructions that are designed to improve the performance of DSP and
+media applications. It provides instructions that operate on packed
+8-bit integer data, Q15 fractional data and Q31 fractional data.
+
+GCC supports MIPS DSP operations using both the generic
+vector extensions (@pxref{Vector Extensions}) and a collection of
+MIPS-specific built-in functions. Both kinds of support are
+enabled by the @option{-mdsp} command-line option.
+
+At present, GCC only provides support for operations on 32-bit
+vectors. The vector type associated with 8-bit integer data is
+usually called @code{v4i8} and the vector type associated with Q15 is
+usually called @code{v2q15}. They can be defined in C as follows:
+
+@smallexample
+typedef char v4i8 __attribute__ ((vector_size(4)));
+typedef short v2q15 __attribute__ ((vector_size(4)));
+@end smallexample
+
+@code{v4i8} and @code{v2q15} values are initialized in the same way as
+aggregates. For example:
+
+@smallexample
+v4i8 a = @{1, 2, 3, 4@};
+v4i8 b;
+b = (v4i8) @{5, 6, 7, 8@};
+
+v2q15 c = @{0x0fcb, 0x3a75@};
+v2q15 d;
+d = (v2q15) @{0.1234 * 0x1.0p15, 0.4567 * 0x1.0p15@};
+@end smallexample
+
+@emph{Note:} The CPU's endianness determines the order in which values
+are packed. On little-endian targets, the first value is the least
+significant and the last value is the most significant. The opposite
+order applies to big-endian targets. For example, the code above will
+set the lowest byte of @code{a} to @code{1} on little-endian targets
+and @code{4} on big-endian targets.
+
+@emph{Note:} Q15 and Q31 values must be initialized with their integer
+representation. As shown in this example, the integer representation
+of a Q15 value can be obtained by multiplying the fractional value by
+@code{0x1.0p15}. The equivalent for Q31 values is to multiply by
+@code{0x1.0p31}.
+
+The table below lists the @code{v4i8} and @code{v2q15} operations for which
+hardware support exists. @code{a} and @code{b} are @code{v4i8} values,
+and @code{c} and @code{d} are @code{v2q15} values.
+
+@multitable @columnfractions .50 .50
+@item C code @tab MIPS instruction
+@item @code{a + b} @tab @code{addu.qb}
+@item @code{c + d} @tab @code{addq.ph}
+@item @code{a - b} @tab @code{subu.qb}
+@item @code{c - d} @tab @code{subq.ph}
+@end multitable
+
+It is easier to describe the DSP built-in functions if we first define
+the following types:
+
+@smallexample
+typedef int q31;
+typedef int i32;
+typedef long long a64;
+@end smallexample
+
+@code{q31} and @code{i32} are actually the same as @code{int}, but we
+use @code{q31} to indicate a Q31 fractional value and @code{i32} to
+indicate a 32-bit integer value. Similarly, @code{a64} is the same as
+@code{long long}, but we use @code{a64} to indicate values that will
+be placed in one of the four DSP accumulators (@code{$ac0},
+@code{$ac1}, @code{$ac2} or @code{$ac3}).
+
+Also, some built-in functions prefer or require immediate numbers as
+parameters, because the corresponding DSP instructions accept both immediate
+numbers and register operands, or accept immediate numbers only. The
+immediate parameters are listed as follows.
+
+@smallexample
+imm0_7: 0 to 7.
+imm0_15: 0 to 15.
+imm0_31: 0 to 31.
+imm0_63: 0 to 63.
+imm0_255: 0 to 255.
+imm_n32_31: -32 to 31.
+imm_n512_511: -512 to 511.
+@end smallexample
+
+The following built-in functions map directly to a particular MIPS DSP
+instruction. Please refer to the architecture specification
+for details on what each instruction does.
+
+@smallexample
+v2q15 __builtin_mips_addq_ph (v2q15, v2q15)
+v2q15 __builtin_mips_addq_s_ph (v2q15, v2q15)
+q31 __builtin_mips_addq_s_w (q31, q31)
+v4i8 __builtin_mips_addu_qb (v4i8, v4i8)
+v4i8 __builtin_mips_addu_s_qb (v4i8, v4i8)
+v2q15 __builtin_mips_subq_ph (v2q15, v2q15)
+v2q15 __builtin_mips_subq_s_ph (v2q15, v2q15)
+q31 __builtin_mips_subq_s_w (q31, q31)
+v4i8 __builtin_mips_subu_qb (v4i8, v4i8)
+v4i8 __builtin_mips_subu_s_qb (v4i8, v4i8)
+i32 __builtin_mips_addsc (i32, i32)
+i32 __builtin_mips_addwc (i32, i32)
+i32 __builtin_mips_modsub (i32, i32)
+i32 __builtin_mips_raddu_w_qb (v4i8)
+v2q15 __builtin_mips_absq_s_ph (v2q15)
+q31 __builtin_mips_absq_s_w (q31)
+v4i8 __builtin_mips_precrq_qb_ph (v2q15, v2q15)
+v2q15 __builtin_mips_precrq_ph_w (q31, q31)
+v2q15 __builtin_mips_precrq_rs_ph_w (q31, q31)
+v4i8 __builtin_mips_precrqu_s_qb_ph (v2q15, v2q15)
+q31 __builtin_mips_preceq_w_phl (v2q15)
+q31 __builtin_mips_preceq_w_phr (v2q15)
+v2q15 __builtin_mips_precequ_ph_qbl (v4i8)
+v2q15 __builtin_mips_precequ_ph_qbr (v4i8)
+v2q15 __builtin_mips_precequ_ph_qbla (v4i8)
+v2q15 __builtin_mips_precequ_ph_qbra (v4i8)
+v2q15 __builtin_mips_preceu_ph_qbl (v4i8)
+v2q15 __builtin_mips_preceu_ph_qbr (v4i8)
+v2q15 __builtin_mips_preceu_ph_qbla (v4i8)
+v2q15 __builtin_mips_preceu_ph_qbra (v4i8)
+v4i8 __builtin_mips_shll_qb (v4i8, imm0_7)
+v4i8 __builtin_mips_shll_qb (v4i8, i32)
+v2q15 __builtin_mips_shll_ph (v2q15, imm0_15)
+v2q15 __builtin_mips_shll_ph (v2q15, i32)
+v2q15 __builtin_mips_shll_s_ph (v2q15, imm0_15)
+v2q15 __builtin_mips_shll_s_ph (v2q15, i32)
+q31 __builtin_mips_shll_s_w (q31, imm0_31)
+q31 __builtin_mips_shll_s_w (q31, i32)
+v4i8 __builtin_mips_shrl_qb (v4i8, imm0_7)
+v4i8 __builtin_mips_shrl_qb (v4i8, i32)
+v2q15 __builtin_mips_shra_ph (v2q15, imm0_15)
+v2q15 __builtin_mips_shra_ph (v2q15, i32)
+v2q15 __builtin_mips_shra_r_ph (v2q15, imm0_15)
+v2q15 __builtin_mips_shra_r_ph (v2q15, i32)
+q31 __builtin_mips_shra_r_w (q31, imm0_31)
+q31 __builtin_mips_shra_r_w (q31, i32)
+v2q15 __builtin_mips_muleu_s_ph_qbl (v4i8, v2q15)
+v2q15 __builtin_mips_muleu_s_ph_qbr (v4i8, v2q15)
+v2q15 __builtin_mips_mulq_rs_ph (v2q15, v2q15)
+q31 __builtin_mips_muleq_s_w_phl (v2q15, v2q15)
+q31 __builtin_mips_muleq_s_w_phr (v2q15, v2q15)
+a64 __builtin_mips_dpau_h_qbl (a64, v4i8, v4i8)
+a64 __builtin_mips_dpau_h_qbr (a64, v4i8, v4i8)
+a64 __builtin_mips_dpsu_h_qbl (a64, v4i8, v4i8)
+a64 __builtin_mips_dpsu_h_qbr (a64, v4i8, v4i8)
+a64 __builtin_mips_dpaq_s_w_ph (a64, v2q15, v2q15)
+a64 __builtin_mips_dpaq_sa_l_w (a64, q31, q31)
+a64 __builtin_mips_dpsq_s_w_ph (a64, v2q15, v2q15)
+a64 __builtin_mips_dpsq_sa_l_w (a64, q31, q31)
+a64 __builtin_mips_mulsaq_s_w_ph (a64, v2q15, v2q15)
+a64 __builtin_mips_maq_s_w_phl (a64, v2q15, v2q15)
+a64 __builtin_mips_maq_s_w_phr (a64, v2q15, v2q15)
+a64 __builtin_mips_maq_sa_w_phl (a64, v2q15, v2q15)
+a64 __builtin_mips_maq_sa_w_phr (a64, v2q15, v2q15)
+i32 __builtin_mips_bitrev (i32)
+i32 __builtin_mips_insv (i32, i32)
+v4i8 __builtin_mips_repl_qb (imm0_255)
+v4i8 __builtin_mips_repl_qb (i32)
+v2q15 __builtin_mips_repl_ph (imm_n512_511)
+v2q15 __builtin_mips_repl_ph (i32)
+void __builtin_mips_cmpu_eq_qb (v4i8, v4i8)
+void __builtin_mips_cmpu_lt_qb (v4i8, v4i8)
+void __builtin_mips_cmpu_le_qb (v4i8, v4i8)
+i32 __builtin_mips_cmpgu_eq_qb (v4i8, v4i8)
+i32 __builtin_mips_cmpgu_lt_qb (v4i8, v4i8)
+i32 __builtin_mips_cmpgu_le_qb (v4i8, v4i8)
+void __builtin_mips_cmp_eq_ph (v2q15, v2q15)
+void __builtin_mips_cmp_lt_ph (v2q15, v2q15)
+void __builtin_mips_cmp_le_ph (v2q15, v2q15)
+v4i8 __builtin_mips_pick_qb (v4i8, v4i8)
+v2q15 __builtin_mips_pick_ph (v2q15, v2q15)
+v2q15 __builtin_mips_packrl_ph (v2q15, v2q15)
+i32 __builtin_mips_extr_w (a64, imm0_31)
+i32 __builtin_mips_extr_w (a64, i32)
+i32 __builtin_mips_extr_r_w (a64, imm0_31)
+i32 __builtin_mips_extr_s_h (a64, i32)
+i32 __builtin_mips_extr_rs_w (a64, imm0_31)
+i32 __builtin_mips_extr_rs_w (a64, i32)
+i32 __builtin_mips_extr_s_h (a64, imm0_31)
+i32 __builtin_mips_extr_r_w (a64, i32)
+i32 __builtin_mips_extp (a64, imm0_31)
+i32 __builtin_mips_extp (a64, i32)
+i32 __builtin_mips_extpdp (a64, imm0_31)
+i32 __builtin_mips_extpdp (a64, i32)
+a64 __builtin_mips_shilo (a64, imm_n32_31)
+a64 __builtin_mips_shilo (a64, i32)
+a64 __builtin_mips_mthlip (a64, i32)
+void __builtin_mips_wrdsp (i32, imm0_63)
+i32 __builtin_mips_rddsp (imm0_63)
+i32 __builtin_mips_lbux (void *, i32)
+i32 __builtin_mips_lhx (void *, i32)
+i32 __builtin_mips_lwx (void *, i32)
+i32 __builtin_mips_bposge32 (void)
+@end smallexample
+
@node MIPS Paired-Single Support
@subsection MIPS Paired-Single Support
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4685c63..988f13b 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -572,7 +572,7 @@ Objective-C and Objective-C++ Dialects}.
-mips16 -mno-mips16 -mabi=@var{abi} -mabicalls -mno-abicalls @gol
-mxgot -mno-xgot -mgp32 -mgp64 -mfp32 -mfp64 @gol
-mhard-float -msoft-float -msingle-float -mdouble-float @gol
--mpaired-single -mips3d @gol
+-mdsp -mpaired-single -mips3d @gol
-mlong64 -mlong32 -msym32 -mno-sym32 @gol
-G@var{num} -membedded-data -mno-embedded-data @gol
-muninit-const-in-rodata -mno-uninit-const-in-rodata @gol
@@ -10065,6 +10065,12 @@ operations.
Assume that the floating-point coprocessor supports double-precision
operations. This is the default.
+@itemx -mdsp
+@itemx -mno-dsp
+@opindex mdsp
+@opindex mno-dsp
+Use (do not use) the MIPS DSP ASE. @xref{MIPS DSP Built-in Functions}.
+
@itemx -mpaired-single
@itemx -mno-paired-single
@opindex mpaired-single
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 82e606d..a14dccc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2005-07-23 Chao-ying Fu <fu@mips.com>
+
+ * gcc.target/mips/mips32-dsp-type.c: New test.
+ * gcc.target/mips/mips32-dsp.c: New test.
+
2005-07-23 Oyvind Harboe <oyvind.harboe@zylin.com>
PR testsuite/21073
diff --git a/gcc/testsuite/gcc.target/mips/mips32-dsp-type.c b/gcc/testsuite/gcc.target/mips/mips32-dsp-type.c
new file mode 100644
index 0000000..030a955
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mips32-dsp-type.c
@@ -0,0 +1,30 @@
+/* Test MIPS32 DSP instructions */
+/* { dg-do compile } */
+/* { dg-mips-options "-mips32 -mdsp" } */
+/* { dg-final { scan-assembler "addq.ph" } } */
+/* { dg-final { scan-assembler "addu.qb" } } */
+/* { dg-final { scan-assembler "subq.ph" } } */
+/* { dg-final { scan-assembler "subu.qb" } } */
+
+typedef char v4qi __attribute__ ((vector_size(4)));
+typedef short v2hi __attribute__ ((vector_size(4)));
+
+v2hi add_v2hi (v2hi a, v2hi b)
+{
+ return a + b;
+}
+
+v4qi add_v4qi (v4qi a, v4qi b)
+{
+ return a + b;
+}
+
+v2hi sub_v2hi (v2hi a, v2hi b)
+{
+ return a - b;
+}
+
+v4qi sub_v4qi (v4qi a, v4qi b)
+{
+ return a - b;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mips32-dsp.c b/gcc/testsuite/gcc.target/mips/mips32-dsp.c
new file mode 100644
index 0000000..cc38c1b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mips32-dsp.c
@@ -0,0 +1,1092 @@
+/* Test MIPS32 DSP instructions */
+/* { dg-do compile } */
+/* { dg-mips-options "-mips32 -mdsp" } */
+/* { dg-final { scan-assembler "addq.ph" } } */
+/* { dg-final { scan-assembler "addq_s.ph" } } */
+/* { dg-final { scan-assembler "addq_s.w" } } */
+/* { dg-final { scan-assembler "addu.qb" } } */
+/* { dg-final { scan-assembler "addu_s.qb" } } */
+/* { dg-final { scan-assembler "subq.ph" } } */
+/* { dg-final { scan-assembler "subq_s.ph" } } */
+/* { dg-final { scan-assembler "subq_s.w" } } */
+/* { dg-final { scan-assembler "subu.qb" } } */
+/* { dg-final { scan-assembler "subu_s.qb" } } */
+/* { dg-final { scan-assembler "addsc" } } */
+/* { dg-final { scan-assembler "addwc" } } */
+/* { dg-final { scan-assembler "modsub" } } */
+/* { dg-final { scan-assembler "raddu.w.qb" } } */
+/* { dg-final { scan-assembler "absq_s.ph" } } */
+/* { dg-final { scan-assembler "absq_s.w" } } */
+/* { dg-final { scan-assembler "precrq.qb.ph" } } */
+/* { dg-final { scan-assembler "precrq.ph.w" } } */
+/* { dg-final { scan-assembler "precrq_rs.ph.w" } } */
+/* { dg-final { scan-assembler "precrqu_s.qb.ph" } } */
+/* { dg-final { scan-assembler "preceq.w.phl" } } */
+/* { dg-final { scan-assembler "preceq.w.phr" } } */
+/* { dg-final { scan-assembler "precequ.ph.qbl" } } */
+/* { dg-final { scan-assembler "precequ.ph.qbr" } } */
+/* { dg-final { scan-assembler "precequ.ph.qbla" } } */
+/* { dg-final { scan-assembler "precequ.ph.qbra" } } */
+/* { dg-final { scan-assembler "preceu.ph.qbl" } } */
+/* { dg-final { scan-assembler "preceu.ph.qbr" } } */
+/* { dg-final { scan-assembler "preceu.ph.qbla" } } */
+/* { dg-final { scan-assembler "preceu.ph.qbra" } } */
+/* { dg-final { scan-assembler "shllv?.qb" } } */
+/* { dg-final { scan-assembler "shllv?.ph" } } */
+/* { dg-final { scan-assembler "shllv?_s.ph" } } */
+/* { dg-final { scan-assembler "shllv?_s.w" } } */
+/* { dg-final { scan-assembler "shrlv?.qb" } } */
+/* { dg-final { scan-assembler "shrav?.ph" } } */
+/* { dg-final { scan-assembler "shrav?_r.ph" } } */
+/* { dg-final { scan-assembler "shrav?_r.w" } } */
+/* { dg-final { scan-assembler "muleu_s.ph.qbl" } } */
+/* { dg-final { scan-assembler "muleu_s.ph.qbr" } } */
+/* { dg-final { scan-assembler "mulq_rs.ph" } } */
+/* { dg-final { scan-assembler "muleq_s.w.phl" } } */
+/* { dg-final { scan-assembler "muleq_s.w.phr" } } */
+/* { dg-final { scan-assembler "dpau.h.qbl" } } */
+/* { dg-final { scan-assembler "dpau.h.qbr" } } */
+/* { dg-final { scan-assembler "dpsu.h.qbl" } } */
+/* { dg-final { scan-assembler "dpsu.h.qbr" } } */
+/* { dg-final { scan-assembler "dpaq_s.w.ph" } } */
+/* { dg-final { scan-assembler "dpsq_s.w.ph" } } */
+/* { dg-final { scan-assembler "mulsaq_s.w.ph" } } */
+/* { dg-final { scan-assembler "dpaq_sa.l.w" } } */
+/* { dg-final { scan-assembler "dpsq_sa.l.w" } } */
+/* { dg-final { scan-assembler "maq_s.w.phl" } } */
+/* { dg-final { scan-assembler "maq_s.w.phr" } } */
+/* { dg-final { scan-assembler "maq_sa.w.phl" } } */
+/* { dg-final { scan-assembler "maq_sa.w.phr" } } */
+/* { dg-final { scan-assembler "bitrev" } } */
+/* { dg-final { scan-assembler "insv" } } */
+/* { dg-final { scan-assembler "replv?.qb" } } */
+/* { dg-final { scan-assembler "repl.ph" } } */
+/* { dg-final { scan-assembler "replv.ph" } } */
+/* { dg-final { scan-assembler "cmpu.eq.qb" } } */
+/* { dg-final { scan-assembler "cmpu.lt.qb" } } */
+/* { dg-final { scan-assembler "cmpu.le.qb" } } */
+/* { dg-final { scan-assembler "cmpgu.eq.qb" } } */
+/* { dg-final { scan-assembler "cmpgu.lt.qb" } } */
+/* { dg-final { scan-assembler "cmpgu.le.qb" } } */
+/* { dg-final { scan-assembler "cmp.eq.ph" } } */
+/* { dg-final { scan-assembler "cmp.lt.ph" } } */
+/* { dg-final { scan-assembler "cmp.le.ph" } } */
+/* { dg-final { scan-assembler "pick.qb" } } */
+/* { dg-final { scan-assembler "pick.ph" } } */
+/* { dg-final { scan-assembler "packrl.ph" } } */
+/* { dg-final { scan-assembler "extrv?.w" } } */
+/* { dg-final { scan-assembler "extrv?_s.h" } } */
+/* { dg-final { scan-assembler "extrv?_r.w" } } */
+/* { dg-final { scan-assembler "extrv?_rs.w" } } */
+/* { dg-final { scan-assembler "extpv?" } } */
+/* { dg-final { scan-assembler "extpdpv?" } } */
+/* { dg-final { scan-assembler "shilov?" } } */
+/* { dg-final { scan-assembler "mthlip" } } */
+/* { dg-final { scan-assembler "mfhi" } } */
+/* { dg-final { scan-assembler "mflo" } } */
+/* { dg-final { scan-assembler "mthi" } } */
+/* { dg-final { scan-assembler "mtlo" } } */
+/* { dg-final { scan-assembler "wrdsp" } } */
+/* { dg-final { scan-assembler "rddsp" } } */
+/* { dg-final { scan-assembler "lbux?" } } */
+/* { dg-final { scan-assembler "lhx?" } } */
+/* { dg-final { scan-assembler "lwx?" } } */
+/* { dg-final { scan-assembler "bposge32" } } */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+typedef char v4i8 __attribute__ ((vector_size(4)));
+typedef short v2q15 __attribute__ ((vector_size(4)));
+
+typedef int q31;
+typedef int i32;
+typedef long long a64;
+
+void test_MIPS_DSP();
+
+char array[100];
+int little_endian;
+
+int main()
+{
+ int i;
+
+ union { long long ll; int i[2]; } endianness_test;
+ endianness_test.ll = 1;
+ little_endian = endianness_test.i[0];
+
+ for (i = 0; i < 100; i++)
+ array[i] = i;
+
+ test_MIPS_DSP();
+
+ exit (0);
+}
+
+v2q15 add_v2q15 (v2q15 a, v2q15 b)
+{
+ return __builtin_mips_addq_ph (a, b);
+}
+
+v4i8 add_v4i8 (v4i8 a, v4i8 b)
+{
+ return __builtin_mips_addu_qb (a, b);
+}
+
+v2q15 sub_v2q15 (v2q15 a, v2q15 b)
+{
+ return __builtin_mips_subq_ph (a, b);
+}
+
+v4i8 sub_v4i8 (v4i8 a, v4i8 b)
+{
+ return __builtin_mips_subu_qb (a, b);
+}
+
+void test_MIPS_DSP()
+{
+ v4i8 v4i8_a,v4i8_b,v4i8_c,v4i8_r,v4i8_s;
+ v2q15 v2q15_a,v2q15_b,v2q15_c,v2q15_r,v2q15_s;
+ q31 q31_a,q31_b,q31_c,q31_r,q31_s;
+ i32 i32_a,i32_b,i32_c,i32_r,i32_s;
+ a64 a64_a,a64_b,a64_c,a64_r,a64_s;
+
+ void *ptr_a;
+ int r,s;
+ long long lr,ls;
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ v2q15_b = (v2q15) {0x6f89, 0x1111};
+ v2q15_s = (v2q15) {0x81bd, 0x6789};
+ v2q15_r = add_v2q15 (v2q15_a, v2q15_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ v2q15_b = (v2q15) {0x6f89, 0x1111};
+ v2q15_s = (v2q15) {0x7fff, 0x6789};
+ v2q15_r = __builtin_mips_addq_s_ph (v2q15_a, v2q15_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ q31_a = 0x70000000;
+ q31_b = 0x71234567;
+ q31_s = 0x7fffffff;
+ q31_r = __builtin_mips_addq_s_w (q31_a, q31_b);
+ if(q31_r != q31_s)
+ abort ();
+
+ v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+ v4i8_b = (v4i8) {0xff, 0x89, 0x11, 0x11};
+ v4i8_s = (v4i8) {0xf1, 0xbd, 0x67, 0x89};
+ v4i8_r = add_v4i8 (v4i8_a, v4i8_b);
+ r = (int) v4i8_r;
+ s = (int) v4i8_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+ v4i8_b = (v4i8) {0xff, 0x89, 0x11, 0x11};
+ v4i8_s = (v4i8) {0xff, 0xbd, 0x67, 0x89};
+ v4i8_r = __builtin_mips_addu_s_qb (v4i8_a, v4i8_b);
+ r = (int) v4i8_r;
+ s = (int) v4i8_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ v2q15_b = (v2q15) {0x6f89, 0x1111};
+ v2q15_s = (v2q15) {0xa2ab, 0x4567};
+ v2q15_r = sub_v2q15 (v2q15_a, v2q15_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x8000, 0x5678};
+ v2q15_b = (v2q15) {0x6f89, 0x1111};
+ v2q15_s = (v2q15) {0x8000, 0x4567};
+ v2q15_r = __builtin_mips_subq_s_ph (v2q15_a, v2q15_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ q31_a = 0x70000000;
+ q31_b = 0x71234567;
+ q31_s = 0xfedcba99;
+ q31_r = __builtin_mips_subq_s_w (q31_a, q31_b);
+ if(q31_r != q31_s)
+ abort ();
+
+ v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+ v4i8_b = (v4i8) {0xff, 0x89, 0x11, 0x11};
+ v4i8_s = (v4i8) {0xf3, 0xab, 0x45, 0x67};
+ v4i8_r = sub_v4i8 (v4i8_a, v4i8_b);
+ r = (int) v4i8_r;
+ s = (int) v4i8_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+ v4i8_b = (v4i8) {0xff, 0x89, 0x11, 0x11};
+ v4i8_s = (v4i8) {0x0, 0x0, 0x45, 0x67};
+ v4i8_r = __builtin_mips_subu_s_qb (v4i8_a, v4i8_b);
+ r = (int) v4i8_r;
+ s = (int) v4i8_s;
+ if(r != s)
+ abort ();
+
+ i32_a = 0xf5678900;
+ i32_b = 0x7abcdef0;
+ i32_s = 0x702467f0;
+ i32_r = __builtin_mips_addsc (i32_a, i32_b);
+ if(i32_r != i32_s)
+ abort ();
+
+ i32_a = 0x75678900;
+ i32_b = 0x7abcdef0;
+ i32_s = 0xf02467f1;
+ i32_r = __builtin_mips_addwc (i32_a, i32_b);
+ if(i32_r != i32_s)
+ abort ();
+
+ i32_a = 0;
+ i32_b = 0x00000901;
+ i32_s = 9;
+ i32_r = __builtin_mips_modsub (i32_a, i32_b);
+ if(i32_r != i32_s)
+ abort ();
+
+ v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+ i32_s = 0x1f4;
+ i32_r = __builtin_mips_raddu_w_qb (v4i8_a);
+ if(i32_r != i32_s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x8000, 0x8134};
+ v2q15_s = (v2q15) {0x7fff, 0x7ecc};
+ v2q15_r = __builtin_mips_absq_s_ph (v2q15_a);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ q31_a = (q31) 0x80000000;
+ q31_s = (q31) 0x7fffffff;
+ q31_r = __builtin_mips_absq_s_w (q31_a);
+ if(q31_r != q31_s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x9999, 0x5612};
+ v2q15_b = (v2q15) {0x5612, 0x3333};
+ if (little_endian)
+ v4i8_s = (v4i8) {0x56, 0x33, 0x99, 0x56};
+ else
+ v4i8_s = (v4i8) {0x99, 0x56, 0x56, 0x33};
+ v4i8_r = __builtin_mips_precrq_qb_ph (v2q15_a, v2q15_b);
+ r = (int) v4i8_r;
+ s = (int) v4i8_s;
+ if(r != s)
+ abort ();
+
+ q31_a = 0x12348678;
+ q31_b = 0x44445555;
+ if (little_endian)
+ v2q15_s = (v2q15) {0x4444, 0x1234};
+ else
+ v2q15_s = (v2q15) {0x1234, 0x4444};
+ v2q15_r = __builtin_mips_precrq_ph_w (q31_a, q31_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ q31_a = 0x12348678;
+ q31_b = 0x44445555;
+ if (little_endian)
+ v2q15_s = (v2q15) {0x4444, 0x1235};
+ else
+ v2q15_s = (v2q15) {0x1235, 0x4444};
+ v2q15_r = __builtin_mips_precrq_rs_ph_w (q31_a, q31_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x9999, 0x5612};
+ v2q15_b = (v2q15) {0x5612, 0x3333};
+ if (little_endian)
+ v4i8_s = (v4i8) {0xac, 0x66, 0x00, 0xac};
+ else
+ v4i8_s = (v4i8) {0x00, 0xac, 0xac, 0x66};
+ v4i8_r = __builtin_mips_precrqu_s_qb_ph (v2q15_a, v2q15_b);
+ r = (int) v4i8_r;
+ s = (int) v4i8_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x3589, 0x4444};
+ if (little_endian)
+ q31_s = 0x44440000;
+ else
+ q31_s = 0x35890000;
+ q31_r = __builtin_mips_preceq_w_phl (v2q15_a);
+ if(q31_r != q31_s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x3589, 0x4444};
+ if (little_endian)
+ q31_s = 0x35890000;
+ else
+ q31_s = 0x44440000;
+ q31_r = __builtin_mips_preceq_w_phr (v2q15_a);
+ if(q31_r != q31_s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+ if (little_endian)
+ v2q15_s = (v2q15) {0x2b00, 0x1980};
+ else
+ v2q15_s = (v2q15) {0x0900, 0x2b00};
+ v2q15_r = __builtin_mips_precequ_ph_qbl (v4i8_a);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+ if (little_endian)
+ v2q15_s = (v2q15) {0x0900, 0x2b00};
+ else
+ v2q15_s = (v2q15) {0x2b00, 0x1980};
+ v2q15_r = __builtin_mips_precequ_ph_qbr (v4i8_a);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+ if (little_endian)
+ v2q15_s = (v2q15) {0x2b00, 0x1980};
+ else
+ v2q15_s = (v2q15) {0x0900, 0x2b00};
+ v2q15_r = __builtin_mips_precequ_ph_qbla (v4i8_a);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+ if (little_endian)
+ v2q15_s = (v2q15) {0x0900, 0x2b00};
+ else
+ v2q15_s = (v2q15) {0x2b00, 0x1980};
+ v2q15_r = __builtin_mips_precequ_ph_qbra (v4i8_a);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+ if (little_endian)
+ v2q15_s = (v2q15) {0x56, 0x33};
+ else
+ v2q15_s = (v2q15) {0x12, 0x56};
+ v2q15_r = __builtin_mips_preceu_ph_qbl (v4i8_a);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+ if (little_endian)
+ v2q15_s = (v2q15) {0x12, 0x56};
+ else
+ v2q15_s = (v2q15) {0x56, 0x33};
+ v2q15_r = __builtin_mips_preceu_ph_qbr (v4i8_a);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x99, 0x56, 0x33};
+ if (little_endian)
+ v2q15_s = (v2q15) {0x99, 0x33};
+ else
+ v2q15_s = (v2q15) {0x12, 0x56};
+ v2q15_r = __builtin_mips_preceu_ph_qbla (v4i8_a);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x99, 0x56, 0x33};
+ if (little_endian)
+ v2q15_s = (v2q15) {0x12, 0x56};
+ else
+ v2q15_s = (v2q15) {0x99, 0x33};
+ v2q15_r = __builtin_mips_preceu_ph_qbra (v4i8_a);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+ v4i8_s = (v4i8) {0xc8, 0xd0, 0x58, 0xe0};
+ v4i8_r = __builtin_mips_shll_qb (v4i8_a, 2);
+ r = (int) v4i8_r;
+ s = (int) v4i8_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+ i32_b = 1;
+ v4i8_s = (v4i8) {0xe4, 0x68, 0xac, 0xf0};
+ v4i8_r = __builtin_mips_shll_qb (v4i8_a, i32_b);
+ r = (int) v4i8_r;
+ s = (int) v4i8_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ v2q15_s = (v2q15) {0x48d0, 0x59e0};
+ v2q15_r = __builtin_mips_shll_ph (v2q15_a, 2);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ i32_b = 1;
+ v2q15_s = (v2q15) {0x2468, 0xacf0};
+ v2q15_r = __builtin_mips_shll_ph (v2q15_a, i32_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ v2q15_s = (v2q15) {0x48d0, 0x7fff};
+ v2q15_r = __builtin_mips_shll_s_ph (v2q15_a, 2);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ i32_b = 1;
+ v2q15_s = (v2q15) {0x2468, 0x7fff};
+ v2q15_r = __builtin_mips_shll_s_ph (v2q15_a, i32_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ q31_a = 0x70000000;
+ q31_s = 0x7fffffff;
+ q31_r = __builtin_mips_shll_s_w (q31_a, 2);
+ if(q31_r != q31_s)
+ abort ();
+
+ q31_a = 0x70000000;
+ i32_b = 1;
+ q31_s = 0x7fffffff;
+ q31_r = __builtin_mips_shll_s_w (q31_a, i32_b);
+ if(q31_r != q31_s)
+ abort ();
+
+ v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+ v4i8_s = (v4i8) {0x3c, 0xd, 0x15, 0x1e};
+ v4i8_r = __builtin_mips_shrl_qb (v4i8_a, 2);
+ r = (int) v4i8_r;
+ s = (int) v4i8_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+ i32_b = 1;
+ v4i8_s = (v4i8) {0x79, 0x1a, 0x2b, 0x3c};
+ v4i8_r = __builtin_mips_shrl_qb (v4i8_a, i32_b);
+ r = (int) v4i8_r;
+ s = (int) v4i8_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ v2q15_s = (v2q15) {0x48d, 0x159e};
+ v2q15_r = __builtin_mips_shra_ph (v2q15_a, 2);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ i32_b = 1;
+ v2q15_s = (v2q15) {0x91a, 0x2b3c};
+ v2q15_r = __builtin_mips_shra_ph (v2q15_a, i32_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ v2q15_s = (v2q15) {0x48d, 0x159e};
+ v2q15_r = __builtin_mips_shra_r_ph (v2q15_a, 2);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ i32_b = 3;
+ v2q15_s = (v2q15) {0x247, 0xacf};
+ v2q15_r = __builtin_mips_shra_r_ph (v2q15_a, i32_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ q31_a = 0x70000000;
+ q31_s = 0x1c000000;
+ q31_r = __builtin_mips_shra_r_w (q31_a, 2);
+ if(q31_r != q31_s)
+ abort ();
+
+ q31_a = 0x70000004;
+ i32_b = 3;
+ q31_s = 0x0e000001;
+ q31_r = __builtin_mips_shra_r_w (q31_a, i32_b);
+ if(q31_r != q31_s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x1, 0x2, 0x3, 0x4};
+ v2q15_b = (v2q15) {0x6f89, 0x1111};
+ if (little_endian)
+ v2q15_s = (v2q15) {0xffff, 0x4444};
+ else
+ v2q15_s = (v2q15) {0x6f89, 0x2222};
+ v2q15_r = __builtin_mips_muleu_s_ph_qbl (v4i8_a, v2q15_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x1, 0x2, 0x3, 0x4};
+ v2q15_b = (v2q15) {0x6f89, 0x1111};
+ if (little_endian)
+ v2q15_s = (v2q15) {0x6f89, 0x2222};
+ else
+ v2q15_s = (v2q15) {0xffff, 0x4444};
+ v2q15_r = __builtin_mips_muleu_s_ph_qbr (v4i8_a, v2q15_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ v2q15_b = (v2q15) {0x6f89, 0x1111};
+ v2q15_s = (v2q15) {0x0fdd, 0x0b87};
+ v2q15_r = __builtin_mips_mulq_rs_ph (v2q15_a, v2q15_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x8000, 0x8000};
+ v2q15_b = (v2q15) {0x8000, 0x8000};
+ q31_s = 0x7fffffff;
+ q31_r = __builtin_mips_muleq_s_w_phl (v2q15_a, v2q15_b);
+ if(q31_r != q31_s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x8000, 0x8000};
+ v2q15_b = (v2q15) {0x8000, 0x8000};
+ q31_s = 0x7fffffff;
+ q31_r = __builtin_mips_muleq_s_w_phr (v2q15_a, v2q15_b);
+ if(q31_r != q31_s)
+ abort ();
+
+#ifndef __mips64
+ a64_a = 0x22221111;
+ v4i8_b = (v4i8) {0x12, 0x34, 0x56, 0x78};
+ v4i8_c = (v4i8) {0xaa, 0x89, 0x11, 0x34};
+ if (little_endian)
+ a64_s = 0x22222f27;
+ else
+ a64_s = 0x222238d9;
+ a64_r = __builtin_mips_dpau_h_qbl (a64_a, v4i8_b, v4i8_c);
+ if(a64_r != a64_s)
+ abort ();
+
+ a64_a = 0x22221111;
+ v4i8_b = (v4i8) {0x12, 0x34, 0x56, 0x78};
+ v4i8_c = (v4i8) {0xaa, 0x89, 0x11, 0x34};
+ if (little_endian)
+ a64_s = 0x222238d9;
+ else
+ a64_s = 0x22222f27;
+ a64_r = __builtin_mips_dpau_h_qbr (a64_a, v4i8_b, v4i8_c);
+ if(a64_r != a64_s)
+ abort ();
+
+ a64_a = 0x22221111;
+ v4i8_b = (v4i8) {0x12, 0x34, 0x56, 0x78};
+ v4i8_c = (v4i8) {0xaa, 0x89, 0x11, 0x34};
+ if (little_endian)
+ a64_s = 0x2221f2fb;
+ else
+ a64_s = 0x2221e949;
+ a64_r = __builtin_mips_dpsu_h_qbl (a64_a, v4i8_b, v4i8_c);
+ if(a64_r != a64_s)
+ abort ();
+
+ a64_a = 0x22221111;
+ v4i8_b = (v4i8) {0x12, 0x34, 0x56, 0x78};
+ v4i8_c = (v4i8) {0xaa, 0x89, 0x11, 0x34};
+ if (little_endian)
+ a64_s = 0x2221e949;
+ else
+ a64_s = 0x2221f2fb;
+ a64_r = __builtin_mips_dpsu_h_qbr (a64_a, v4i8_b, v4i8_c);
+ if(a64_r != a64_s)
+ abort ();
+
+ a64_a = 0x00001111;
+ v2q15_b = (v2q15) {0x8000, 0x5678};
+ v2q15_c = (v2q15) {0x8000, 0x1111};
+ a64_s = 0x8b877d00;
+ a64_r = __builtin_mips_dpaq_s_w_ph (a64_a, v2q15_b, v2q15_c);
+ if(a64_r != a64_s)
+ abort ();
+
+ a64_a = 0x00001111;
+ v2q15_b = (v2q15) {0x8000, 0x5678};
+ v2q15_c = (v2q15) {0x8000, 0x1111};
+ a64_s = 0xffffffff7478a522LL;
+ a64_r = __builtin_mips_dpsq_s_w_ph (a64_a, v2q15_b, v2q15_c);
+ if(a64_r != a64_s)
+ abort ();
+
+ a64_a = 0x00001111;
+ v2q15_b = (v2q15) {0x8000, 0x5678};
+ v2q15_c = (v2q15) {0x8000, 0x1111};
+ if (little_endian)
+ a64_s = 0xffffffff8b877d02LL;
+ else
+ a64_s = 0x7478a520;
+ a64_r = __builtin_mips_mulsaq_s_w_ph (a64_a, v2q15_b, v2q15_c);
+ if(a64_r != a64_s)
+ abort ();
+
+ a64_a = 0x00001111;
+ q31_b = 0x80000000;
+ q31_c = 0x80000000;
+ a64_s = 0x7fffffffffffffffLL;
+ a64_r = __builtin_mips_dpaq_sa_l_w (a64_a, q31_b, q31_c);
+ if(a64_r != a64_s)
+ abort ();
+
+ a64_a = 0x00001111;
+ q31_b = 0x80000000;
+ q31_c = 0x80000000;
+ a64_s = 0x8000000000001112LL;
+ a64_r = __builtin_mips_dpsq_sa_l_w (a64_a, q31_b, q31_c);
+ if(a64_r != a64_s)
+ abort ();
+
+ a64_a = 0x00001111;
+ v2q15_b = (v2q15) {0x8000, 0x1};
+ v2q15_c = (v2q15) {0x8000, 0x2};
+ if (little_endian)
+ a64_s = 0x1115;
+ else
+ a64_s = 0x80001110;
+ a64_r = __builtin_mips_maq_s_w_phl (a64_a, v2q15_b, v2q15_c);
+ if(a64_r != a64_s)
+ abort ();
+
+ a64_a = 0x00001111;
+ v2q15_b = (v2q15) {0x8000, 0x1};
+ v2q15_c = (v2q15) {0x8000, 0x2};
+ if (little_endian)
+ a64_s = 0x80001110;
+ else
+ a64_s = 0x1115;
+ a64_r = __builtin_mips_maq_s_w_phr (a64_a, v2q15_b, v2q15_c);
+ if(a64_r != a64_s)
+ abort ();
+
+ a64_a = 0x00001111;
+ v2q15_b = (v2q15) {0x8000, 0x1};
+ v2q15_c = (v2q15) {0x8000, 0x2};
+ if (little_endian)
+ a64_s = 0x1115;
+ else
+ a64_s = 0x7fffffff;
+ a64_r = __builtin_mips_maq_sa_w_phl (a64_a, v2q15_b, v2q15_c);
+ if(a64_r != a64_s)
+ abort ();
+
+ a64_a = 0x00001111;
+ v2q15_b = (v2q15) {0x8000, 0x1};
+ v2q15_c = (v2q15) {0x8000, 0x2};
+ if (little_endian)
+ a64_s = 0x7fffffff;
+ else
+ a64_s = 0x1115;
+ a64_r = __builtin_mips_maq_sa_w_phr (a64_a, v2q15_b, v2q15_c);
+ if(a64_r != a64_s)
+ abort ();
+#endif
+
+ i32_a = 0x12345678;
+ i32_s = 0x00001e6a;
+ i32_r = __builtin_mips_bitrev (i32_a);
+ if(i32_r != i32_s)
+ abort ();
+
+ i32_a = 0x00000208; // pos is 8, size is 4
+ __builtin_mips_wrdsp (i32_a, 31);
+ i32_a = 0x12345678;
+ i32_b = 0x87654321;
+ i32_s = 0x12345178;
+ i32_r = __builtin_mips_insv (i32_a, i32_b);
+ if(i32_r != i32_s)
+ abort ();
+
+ v4i8_s = (v4i8) {1, 1, 1, 1};
+ v4i8_r = __builtin_mips_repl_qb (1);
+ r = (int) v4i8_r;
+ s = (int) v4i8_s;
+ if(r != s)
+ abort ();
+
+ i32_a = 99;
+ v4i8_s = (v4i8) {99, 99, 99, 99};
+ v4i8_r = __builtin_mips_repl_qb (i32_a);
+ r = (int) v4i8_r;
+ s = (int) v4i8_s;
+ if(r != s)
+ abort ();
+
+ v2q15_s = (v2q15) {30, 30};
+ v2q15_r = __builtin_mips_repl_ph (30);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ i32_a = 0x5612;
+ v2q15_s = (v2q15) {0x5612, 0x5612};
+ v2q15_r = __builtin_mips_repl_ph (i32_a);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+ v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+ if (little_endian)
+ i32_s = 0x03000000;
+ else
+ i32_s = 0x0c000000;
+ __builtin_mips_cmpu_eq_qb (v4i8_a, v4i8_b);
+ i32_r = __builtin_mips_rddsp (16);
+ if (i32_r != i32_s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+ v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+ if (little_endian)
+ i32_s = 0x04000000;
+ else
+ i32_s = 0x02000000;
+ __builtin_mips_cmpu_lt_qb (v4i8_a, v4i8_b);
+ i32_r = __builtin_mips_rddsp (16);
+ if (i32_r != i32_s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+ v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+ if (little_endian)
+ i32_s = 0x07000000;
+ else
+ i32_s = 0x0e000000;
+ __builtin_mips_cmpu_le_qb (v4i8_a, v4i8_b);
+ i32_r = __builtin_mips_rddsp (16);
+ if (i32_r != i32_s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+ v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+ if (little_endian)
+ i32_s = 0x3;
+ else
+ i32_s = 0xc;
+ i32_r=__builtin_mips_cmpgu_eq_qb (v4i8_a, v4i8_b);
+ if (i32_r != i32_s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+ v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+ if (little_endian)
+ i32_s = 0x4;
+ else
+ i32_s = 0x2;
+ i32_r = __builtin_mips_cmpgu_lt_qb (v4i8_a, v4i8_b);
+ if (i32_r != i32_s)
+ abort ();
+
+ v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+ v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+ if (little_endian)
+ i32_s = 0x7;
+ else
+ i32_s = 0xe;
+ i32_r = __builtin_mips_cmpgu_le_qb (v4i8_a, v4i8_b);
+ if (i32_r != i32_s)
+ abort ();
+
+ __builtin_mips_wrdsp (0,31); // Clear all condition code bits.
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ v2q15_b = (v2q15) {0x1234, 0x7856};
+ if (little_endian)
+ i32_s = 0x01000000;
+ else
+ i32_s = 0x02000000;
+ __builtin_mips_cmp_eq_ph (v2q15_a, v2q15_b);
+ i32_r = __builtin_mips_rddsp (16);
+ if (i32_r != i32_s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ v2q15_b = (v2q15) {0x1234, 0x7856};
+ if (little_endian)
+ i32_s = 0x02000000;
+ else
+ i32_s = 0x01000000;
+ __builtin_mips_cmp_lt_ph (v2q15_a, v2q15_b);
+ i32_r = __builtin_mips_rddsp (16);
+ if (i32_r != i32_s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ v2q15_b = (v2q15) {0x1234, 0x7856};
+ i32_s = 0x03000000;
+ __builtin_mips_cmp_le_ph (v2q15_a, v2q15_b);
+ i32_r = __builtin_mips_rddsp (16);
+ if (i32_r != i32_s)
+ abort ();
+
+ i32_a = 0x0a000000; // cc: 0000 1010
+ __builtin_mips_wrdsp (i32_a, 31);
+ v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+ v4i8_b = (v4i8) {0x21, 0x43, 0x65, 0x87};
+ if (little_endian)
+ v4i8_s = (v4i8) {0x21, 0x34, 0x65, 0x78};
+ else
+ v4i8_s = (v4i8) {0x12, 0x43, 0x56, 0x87};
+ v4i8_r = __builtin_mips_pick_qb (v4i8_a, v4i8_b);
+ r = (int) v4i8_r;
+ s = (int) v4i8_s;
+ if(r != s)
+ abort ();
+
+ i32_a = 0x02000000; // cc: 0000 0010
+ __builtin_mips_wrdsp (i32_a, 31);
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ v2q15_b = (v2q15) {0x2143, 0x6587};
+ if (little_endian)
+ v2q15_s = (v2q15) {0x2143, 0x5678};
+ else
+ v2q15_s = (v2q15) {0x1234, 0x6587};
+ v2q15_r = __builtin_mips_pick_ph (v2q15_a, v2q15_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+ v2q15_a = (v2q15) {0x1234, 0x5678};
+ v2q15_b = (v2q15) {0x1234, 0x7856};
+ if (little_endian)
+ v2q15_s = (v2q15) {0x7856, 0x1234};
+ else
+ v2q15_s = (v2q15) {0x5678, 0x1234};
+ v2q15_r = __builtin_mips_packrl_ph (v2q15_a, v2q15_b);
+ r = (int) v2q15_r;
+ s = (int) v2q15_s;
+ if(r != s)
+ abort ();
+
+#ifndef __mips64
+ a64_a = 0x1234567887654321LL;
+ i32_s = 0x88765432;
+ i32_r = __builtin_mips_extr_w (a64_a, 4);
+ if(i32_r != i32_s)
+ abort ();
+
+ a64_a = 0x1234567887658321LL;
+ i32_s = 0x56788766;
+ i32_r = __builtin_mips_extr_r_w (a64_a, 16);
+ if(i32_r != i32_s)
+ abort ();
+
+ a64_a = 0x12345677fffffff8LL;
+ i32_s = 0x7fffffff;
+ i32_r = __builtin_mips_extr_rs_w (a64_a, 4);
+ if(i32_r != i32_s)
+ abort ();
+
+ a64_a = 0x1234567887658321LL;
+ i32_s = 0x7fff;
+ i32_r = __builtin_mips_extr_s_h (a64_a, 16);
+ if(i32_r != i32_s)
+ abort ();
+
+ a64_a = 0x0000007887658321LL;
+ i32_b = 24;
+ i32_s = 0x7887;
+ i32_r = __builtin_mips_extr_s_h (a64_a, i32_b);
+ if(i32_r != i32_s)
+ abort ();
+
+ a64_a = 0x1234567887654321LL;
+ i32_b = 4;
+ i32_s = 0x88765432;
+ i32_r = __builtin_mips_extr_w (a64_a, i32_b);
+ if(i32_r != i32_s)
+ abort ();
+
+ a64_a = 0x1234567887658321LL;
+ i32_b = 16;
+ i32_s = 0x56788766;
+ i32_r = __builtin_mips_extr_r_w (a64_a, i32_b);
+ if(i32_r != i32_s)
+ abort ();
+
+ a64_a = 0x12345677fffffff8LL;
+ i32_b = 4;
+ i32_s = 0x7fffffff;
+ i32_r = __builtin_mips_extr_rs_w (a64_a, i32_b);
+ if(i32_r != i32_s)
+ abort ();
+
+ i32_a = 0x0000021f; // pos is 31
+ __builtin_mips_wrdsp (i32_a, 31);
+ a64_a = 0x1234567887654321LL;
+ i32_s = 8;
+ i32_r = __builtin_mips_extp (a64_a, 3); // extract 4 bits
+ if(i32_r != i32_s)
+ abort ();
+
+ i32_a = 0x0000021f; // pos is 31
+ __builtin_mips_wrdsp (i32_a, 31);
+ a64_a = 0x1234567887654321LL;
+ i32_b = 7; // size is 8. NOTE!! we should use 7
+ i32_s = 0x87;
+ i32_r = __builtin_mips_extp (a64_a, i32_b);
+ if(i32_r != i32_s)
+ abort ();
+
+ i32_a = 0x0000021f; // pos is 31
+ __builtin_mips_wrdsp (i32_a, 31);
+ a64_a = 0x1234567887654321LL;
+ i32_s = 8;
+ i32_r = __builtin_mips_extpdp (a64_a, 3); // extract 4 bits
+ if(i32_r != i32_s)
+ abort ();
+
+ i32_s = 0x0000021b; // pos is 27
+ i32_r = __builtin_mips_rddsp (31);
+ if (i32_r != i32_s)
+ abort ();
+
+ i32_a = 0x0000021f; // pos is 31
+ __builtin_mips_wrdsp (i32_a, 31);
+ a64_a = 0x1234567887654321LL;
+ i32_b = 11; // size is 12. NOTE!!! We should use 11
+ i32_s = 0x876;
+ i32_r = __builtin_mips_extpdp (a64_a, i32_b);
+ if(i32_r != i32_s)
+ abort ();
+
+ i32_s = 0x00000213; // pos is 19
+ i32_r = __builtin_mips_rddsp (31);
+ if (i32_r != i32_s)
+ abort ();
+
+ a64_a = 0x1234567887654321LL;
+ a64_s = 0x0012345678876543LL;
+ a64_r = __builtin_mips_shilo (a64_a, 8);
+ if(a64_r != a64_s)
+ abort ();
+
+ a64_a = 0x1234567887654321LL;
+ i32_b = -16;
+ a64_s = 0x5678876543210000LL;
+ a64_r = __builtin_mips_shilo (a64_a, i32_b);
+ if(a64_r != a64_s)
+ abort ();
+
+ i32_a = 0x0;
+ __builtin_mips_wrdsp (i32_a, 31);
+ a64_a = 0x1234567887654321LL;
+ i32_b = 0x11112222;
+ a64_s = 0x8765432111112222LL;
+ a64_r = __builtin_mips_mthlip (a64_a, i32_b);
+ if(a64_r != a64_s)
+ abort ();
+ i32_s = 32;
+ i32_r = __builtin_mips_rddsp (31);
+ if(i32_r != i32_s)
+ abort ();
+#endif
+
+ i32_a = 0x1357a468;
+ __builtin_mips_wrdsp (i32_a, 63);
+ i32_s = 0x03572428;
+ i32_r = __builtin_mips_rddsp (63);
+ if(i32_r != i32_s)
+ abort ();
+
+ ptr_a = &array;
+ i32_b = 37;
+ i32_s = 37;
+ i32_r = __builtin_mips_lbux (ptr_a, i32_b);
+ if(i32_r != i32_s)
+ abort ();
+
+ ptr_a = &array;
+ i32_b = 38;
+ if (little_endian)
+ i32_s = 0x2726;
+ else
+ i32_s = 0x2627;
+ i32_r = __builtin_mips_lhx (ptr_a, i32_b);
+ if(i32_r != i32_s)
+ abort ();
+
+ ptr_a = &array;
+ i32_b = 40;
+ if (little_endian)
+ i32_s = 0x2b2a2928;
+ else
+ i32_s = 0x28292a2b;
+ i32_r = __builtin_mips_lwx (ptr_a, i32_b);
+ if(i32_r != i32_s)
+ abort ();
+
+ i32_a = 0x00000220; // pos is 32, size is 4
+ __builtin_mips_wrdsp (i32_a, 63);
+ i32_s = 1;
+ i32_r = __builtin_mips_bposge32 ();
+ if(i32_r != i32_s)
+ abort ();
+}
+