mips-dsp.md: New file.
authorChao-ying Fu <fu@mips.com>
Sat, 23 Jul 2005 08:36:54 +0000 (08:36 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sat, 23 Jul 2005 08:36:54 +0000 (08:36 +0000)
* 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

13 files changed:
gcc/ChangeLog
gcc/config/mips/mips-dsp.md [new file with mode: 0644]
gcc/config/mips/mips-modes.def
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/config/mips/mips.opt
gcc/config/mips/predicates.md
gcc/doc/extend.texi
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/mips32-dsp-type.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/mips32-dsp.c [new file with mode: 0644]

index 55e2f4a7adca493e63876ede88541794d1707ba4..73d386b25038ef527f6d2f518d1262111e9fac6e 100644 (file)
@@ -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 (file)
index 0000000..a61b23f
--- /dev/null
@@ -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")])
+
index 00dabdbc18501658f2c0de2020ef1ebd7785b4b0..39c2f164978526e1ba9da0f5864e6f990bd8cba9 100644 (file)
@@ -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);
index c316ef1c30c1f33072260ad79ac2e5bf751c4979..63eb6943b4300aaa1b31718b9ba43eb520889362 100644 (file)
@@ -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;
+    }
 }
 \f
 /* 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;
+}
 \f
 #include "gt-mips.h"
index 8bb3d50b953dcc655f585492ed50bdd6229c4bd6..cc38e118dd6412bf1972c122586c0908bfdaaec8 100644 (file)
@@ -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.  */
index bf4bc69e39c4f9809a757da6eb91ed1a2f021b90..a43a0c288474296b1ecb49fb081788ea1b86fd20 100644 (file)
    (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)
   ]
 )
 
    (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))"
 ;; 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")
 ; The MIPS Paired-Single Floating Point and MIPS-3D Instructions.
 
 (include "mips-ps-3d.md")
+
+; The MIPS DSP Instructions.
+
+(include "mips-dsp.md")
index 6bd719abbb0f6a8069883efa376e94aded8bfe13..737f5edecb1881a06dcfcae824ae13544aa45702 100644 (file)
@@ -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
 
index 1fc3c6e43ed814c3fca5638cecdc4f2d1f98885d..e4e3805845f210d6460e3e4c7c529f47b28a1cf9 100644 (file)
   (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)")))
index 69bd151f84b681053686af4c9310f2408389cd66..7e137950065b4c0f278185c8706c095516c6260e 100644 (file)
@@ -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
 
index 4685c636240384925b3a7eb4e81a97d17b06fb49..988f13b1dbd24809e6d64907933704c6135e13d9 100644 (file)
@@ -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
index 82e606d2740c980a957162d2f8ffc09f0d531789..a14dccc70abe6bddc19cd3585454a352478b9206 100644 (file)
@@ -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 (file)
index 0000000..030a955
--- /dev/null
@@ -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 (file)
index 0000000..cc38c1b
--- /dev/null
@@ -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 ();
+}
+