From 118ea793126f7e628d11de81cd4d100785e104e8 Mon Sep 17 00:00:00 2001 From: Chao-ying Fu Date: Sat, 23 Jul 2005 08:36:54 +0000 Subject: [PATCH] mips-dsp.md: New file. * config/mips/mips-dsp.md: New file. * config/mips/mips-modes.def (V4QI, V2HI, CCDSP): New modes. * config/mips/mips.c (mips_function_type): Add types for DSP builtin functions. (mips_builtin_type): Add MIPS_BUILTIN_DIRECT_NO_TARGET and MIPS_BUILTIN_BPOSGE32. (mips_expand_builtin_direct): Add one parameter to indicate that builtin functions need to return a value. (mips_expand_builtin_bposge): New for expanding "bposge" builtin functions. (mips_regno_to_class): Add classes for 12 new DSP registers. (mips_subword): Change to check four HI registers. (mips_output_move): Output move to and from 6 new DSP accumulators. (override_options): Make sure -mdsp and -mips16 are not used together. Map 'A' to DSP_ACC_REGS and 'a' to ACC_REGS. Enable DSP accumulators for machine modes. (mips_conditional_register_usage): Disable 6 new DSP accumulators when !TARGET_DSP. (print_operand): Add 'q' for printing DSP accumulators. (mips_cannot_change_mode_class): Check ACC_REGS. (mips_secondary_reload_class): Check ACC_REGS. (mips_vector_mode_supported_p): Enable V2HI and V4QI when TARGET_DSP. (mips_register_move_cost): Check ACC_REGS. (CODE_FOR_mips_addq_ph, CODE_FOR_mips_addu_qb, CODE_FOR_mips_subq_ph) (CODE_FOR_mips_subu_qb): New code-aliasing macros. (DIRECT_NO_TARGET_BUILTIN, BPOSGE_BUILTIN): New macros. (dsp_bdesc): New array. (bdesc_arrays): Add DSP builtin function table. (mips_prepare_builtin_arg): Check predicate again after copy_to_mode_reg. (mips_expand_builtin): Add one more parameter to mips_expand_builtin_direct. Expand MIPS_BUILTIN_DIRECT_NO_TARGET and MIPS_BUILTIN_BPOSGE32. (mips_init_builtins): Initialize new function types. (mips_expand_builtin_direct): Check if builtin functions need to return a value and pass operands properly. (mips_expand_builtin_bposge): New function. * config/mips/mips.h (TARGET_CPU_CPP_BUILTINS): Add __mips_dsp. (ASM_SPEC): Map -mdsp to -mdsp in GAS. (FIRST_PSEUDO_REGISTER): Increase to 188. (FIXED_REGISTERS, CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS): Update for 12 new DSP registers. (DSP_ACC_REG_FIRST, DSP_ACC_REG_LAST, DSP_ACC_REG_NUM, AC1HI_REGNUM) (AC1LO_REGNUM, AC2HI_REGNUM, AC2LO_REGNUM, AC3HI_REGNUM, AC3LO_REGNUM): (DSP_ACC_REG_P, ACC_REG_P, ACC_HI_REG_P): New macros. (reg_class): Add DSP_ACC_REGS and ACC_REGS. (REG_CLASS_NAMES): Add names for DSP_ACC_REGS and ACC_REGS. (REG_CLASS_CONTENTS): Update for DSP_ACC_REGS, ACC_REGS and ALL_REGS. (REG_ALLOC_ORDER): Update for 12 new DSP registers. (mips_char_to_class): Add 'A' for DSP_ACC_REGS and 'a' for ACC_REGS. (UIMM6_OPERAND, IMM10_OPERAND): New macros. (EXTRA_CONSTRAINT_Y): Add YA and YB extra constraints. (REGISTER_NAMES): Add names for 12 new DSP registers. * config/mips/mips.md: Include mips-dsp.md. (UNSPEC_ADDQ, UNSPEC_ADDQ_S, UNSPEC_SUBQ, UNSPEC_SUBQ_S, UNSPEC_ADDSC) (UNSPEC_ADDWC, UNSPEC_MODSUB, UNSPEC_RADDU_W_QB, UNSPEC_ABSQ_S) (UNSPEC_PRECRQ_QB_PH, UNSPEC_PRECRQ_PH_W, UNSPEC_PRECRQ_RS_PH_W) (UNSPEC_PRECRQU_S_QB_PH, UNSPEC_PRECEQ_W_PHL, UNSPEC_PRECEQ_W_PHR) (UNSPEC_PRECEQU_PH_QBL, UNSPEC_PRECEQU_PH_QBR, UNSPEC_PRECEQU_PH_QBLA) (UNSPEC_PRECEQU_PH_QBRA, UNSPEC_PRECEU_PH_QBL, UNSPEC_PRECEU_PH_QBR) (UNSPEC_PRECEU_PH_QBLA, UNSPEC_PRECEU_PH_QBRA, UNSPEC_SHLL) (UNSPEC_SHLL_S, UNSPEC_SHRL_QB, UNSPEC_SHRA_PH, UNSPEC_SHRA_R) (UNSPEC_MULEU_S_PH_QBL, UNSPEC_MULEU_S_PH_QBR, UNSPEC_MULQ_RS_PH) (UNSPEC_MULEQ_S_W_PHL, UNSPEC_MULEQ_S_W_PHR, UNSPEC_DPAU_H_QBL) (UNSPEC_DPAU_H_QBR, UNSPEC_DPSU_H_QBL, UNSPEC_DPSU_H_QBR) (UNSPEC_DPAQ_S_W_PH, UNSPEC_DPSQ_S_W_PH, UNSPEC_MULSAQ_S_W_PH) (UNSPEC_DPAQ_SA_L_W, UNSPEC_DPSQ_SA_L_W, UNSPEC_MAQ_S_W_PHL) (UNSPEC_MAQ_S_W_PHR, UNSPEC_MAQ_SA_W_PHL, UNSPEC_MAQ_SA_W_PHR) (UNSPEC_BITREV, UNSPEC_INSV, UNSPEC_REPL_QB, UNSPEC_REPL_PH) (UNSPEC_CMP_EQ, UNSPEC_CMP_LT, UNSPEC_CMP_LE, UNSPEC_CMPGU_EQ_QB) (UNSPEC_CMPGU_LT_QB, UNSPEC_CMPGU_LE_QB, UNSPEC_PICK, UNSPEC_PACKRL_PH) (UNSPEC_EXTR_W, UNSPEC_EXTR_R_W, UNSPEC_EXTR_RS_W, UNSPEC_EXTR_S_H) (UNSPEC_EXTP, UNSPEC_EXTPDP, UNSPEC_SHILO, UNSPEC_MTHLIP, UNSPEC_WRDSP) (UNSPEC_RDDSP): New constants. (*movdi_32bit): Change 'x' to 'a' for ACC_REGS. (*movsi_internal): Change 'x' to 'a' for ACC_REGS. Add an A<-d alternative. * config/mips/mips.opt (-mdsp): New option. * config/mips/predicates.md (const_uimm6_operand, const_imm10_operand) (reg_imm10_operand): New predicates. * doc/extend.texi (MIPS DSP Built-in Functions): New section. * doc/invoke.texi (-mdsp): Document new option. From-SVN: r102307 --- gcc/ChangeLog | 85 ++ gcc/config/mips/mips-dsp.md | 1058 ++++++++++++++++ gcc/config/mips/mips-modes.def | 4 + gcc/config/mips/mips.c | 582 +++++++-- gcc/config/mips/mips.h | 77 +- gcc/config/mips/mips.md | 86 +- gcc/config/mips/mips.opt | 4 + gcc/config/mips/predicates.md | 12 + gcc/doc/extend.texi | 203 +++ gcc/doc/invoke.texi | 8 +- gcc/testsuite/ChangeLog | 5 + .../gcc.target/mips/mips32-dsp-type.c | 30 + gcc/testsuite/gcc.target/mips/mips32-dsp.c | 1092 +++++++++++++++++ 13 files changed, 3154 insertions(+), 92 deletions(-) create mode 100644 gcc/config/mips/mips-dsp.md create mode 100644 gcc/testsuite/gcc.target/mips/mips32-dsp-type.c create mode 100644 gcc/testsuite/gcc.target/mips/mips32-dsp.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 55e2f4a7adc..73d386b2503 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,88 @@ +2005-07-23 Chao-ying Fu + + * 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 * c-objc-common.c (c_cannot_inline_tree_fn): Add warning control diff --git a/gcc/config/mips/mips-dsp.md b/gcc/config/mips/mips-dsp.md new file mode 100644 index 00000000000..a61b23f0acd --- /dev/null +++ b/gcc/config/mips/mips-dsp.md @@ -0,0 +1,1058 @@ +(define_constants + [(CCDSP_PO_REGNUM 182) + (CCDSP_SC_REGNUM 183) + (CCDSP_CA_REGNUM 184) + (CCDSP_OU_REGNUM 185) + (CCDSP_CC_REGNUM 186) + (CCDSP_EF_REGNUM 187)]) + +;; This mode macro allows si, v2hi, v4qi for all possible modes in DSP ASE. +(define_mode_macro DSP [(SI "TARGET_DSP") + (V2HI "TARGET_DSP") + (V4QI "TARGET_DSP")]) + +;; This mode macro allows v2hi, v4qi for vector/SIMD data. +(define_mode_macro DSPV [(V2HI "TARGET_DSP") + (V4QI "TARGET_DSP")]) + +;; This mode macro allows si, v2hi for Q31 and V2Q15 fixed-point data. +(define_mode_macro DSPQ [(SI "TARGET_DSP") + (V2HI "TARGET_DSP")]) + +;; DSP instructions use q for fixed-point data, and u for integer in the infix. +(define_mode_attr dspfmt1 [(SI "q") (V2HI "q") (V4QI "u")]) + +;; DSP instructions use nothing for fixed-point data, and u for integer in +;; the infix. +(define_mode_attr dspfmt1_1 [(SI "") (V2HI "") (V4QI "u")]) + +;; DSP instructions use w, ph, qb in the postfix. +(define_mode_attr dspfmt2 [(SI "w") (V2HI "ph") (V4QI "qb")]) + +;; DSP shift masks for SI, V2HI, V4QI. +(define_mode_attr dspshift_mask [(SI "0x1f") (V2HI "0xf") (V4QI "0x7")]) + +;; MIPS DSP ASE Revision 0.98 3/24/2005 +;; Table 2-1. MIPS DSP ASE Instructions: Arithmetic +;; ADDQ* +(define_insn "add3" + [(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.\t%0,%1,%2" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +(define_insn "mips_add_s_" + [(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_s.\t%0,%1,%2" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +;; SUBQ* +(define_insn "sub3" + [(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.\t%0,%1,%2" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +(define_insn "mips_sub_s_" + [(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_s.\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_" + [(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.\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_" + [(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) ) + operands[2] = GEN_INT (INTVAL (operands[2]) & ); + return "shll.\t%0,%1,%2"; + } + return "shllv.\t%0,%1,%2"; +} + [(set_attr "type" "shift") + (set_attr "mode" "SI")]) + +(define_insn "mips_shll_s_" + [(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) ) + operands[2] = GEN_INT (INTVAL (operands[2]) & ); + return "shll_s.\t%0,%1,%2"; + } + return "shllv_s.\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_" + [(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) ) + operands[2] = GEN_INT (INTVAL (operands[2]) & ); + return "shra_r.\t%0,%1,%2"; + } + return "shrav_r.\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_eq_" + [(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.eq.\t%0,%1" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +(define_insn "mips_cmp_lt_" + [(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.lt.\t%0,%1" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +(define_insn "mips_cmp_le_" + [(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.le.\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_" + [(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.\t%0,%1,%2" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +;; PACKRL* +(define_insn "mips_packrl_ph" + [(set (match_operand:V2HI 0 "register_operand" "=d") + (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "d") + (match_operand:V2HI 2 "register_operand" "d")] + UNSPEC_PACKRL_PH))] + "TARGET_DSP" + "packrl.ph\t%0,%1,%2" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +;; Table 2-6. MIPS DSP ASE Instructions: Accumulator and DSPControl Access +;; EXTR* +(define_insn "mips_extr_w" + [(parallel + [(set (match_operand:SI 0 "register_operand" "=d,d") + (unspec:SI [(match_operand:DI 1 "register_operand" "a,a") + (match_operand:SI 2 "arith_operand" "I,d")] + UNSPEC_EXTR_W)) + (set (reg:CCDSP CCDSP_OU_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTR_W))])] + "TARGET_DSP && !TARGET_64BIT" +{ + if (which_alternative == 0) + { + if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + return "extr.w\t%0,%q1,%2"; + } + return "extrv.w\t%0,%q1,%2"; +} + [(set_attr "type" "mfhilo") + (set_attr "mode" "SI")]) + +(define_insn "mips_extr_r_w" + [(parallel + [(set (match_operand:SI 0 "register_operand" "=d,d") + (unspec:SI [(match_operand:DI 1 "register_operand" "a,a") + (match_operand:SI 2 "arith_operand" "I,d")] + UNSPEC_EXTR_R_W)) + (set (reg:CCDSP CCDSP_OU_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTR_R_W))])] + "TARGET_DSP && !TARGET_64BIT" +{ + if (which_alternative == 0) + { + if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + return "extr_r.w\t%0,%q1,%2"; + } + return "extrv_r.w\t%0,%q1,%2"; +} + [(set_attr "type" "mfhilo") + (set_attr "mode" "SI")]) + +(define_insn "mips_extr_rs_w" + [(parallel + [(set (match_operand:SI 0 "register_operand" "=d,d") + (unspec:SI [(match_operand:DI 1 "register_operand" "a,a") + (match_operand:SI 2 "arith_operand" "I,d")] + UNSPEC_EXTR_RS_W)) + (set (reg:CCDSP CCDSP_OU_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTR_RS_W))])] + "TARGET_DSP && !TARGET_64BIT" +{ + if (which_alternative == 0) + { + if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + return "extr_rs.w\t%0,%q1,%2"; + } + return "extrv_rs.w\t%0,%q1,%2"; +} + [(set_attr "type" "mfhilo") + (set_attr "mode" "SI")]) + +;; EXTR*_S.H +(define_insn "mips_extr_s_h" + [(parallel + [(set (match_operand:SI 0 "register_operand" "=d,d") + (unspec:SI [(match_operand:DI 1 "register_operand" "a,a") + (match_operand:SI 2 "arith_operand" "I,d")] + UNSPEC_EXTR_S_H)) + (set (reg:CCDSP CCDSP_OU_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTR_S_H))])] + "TARGET_DSP && !TARGET_64BIT" +{ + if (which_alternative == 0) + { + if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + return "extr_s.h\t%0,%q1,%2"; + } + return "extrv_s.h\t%0,%q1,%2"; +} + [(set_attr "type" "mfhilo") + (set_attr "mode" "SI")]) + +;; EXTP* +(define_insn "mips_extp" + [(parallel + [(set (match_operand:SI 0 "register_operand" "=d,d") + (unspec:SI [(match_operand:DI 1 "register_operand" "a,a") + (match_operand:SI 2 "arith_operand" "I,d") + (reg:CCDSP CCDSP_PO_REGNUM)] + UNSPEC_EXTP)) + (set (reg:CCDSP CCDSP_EF_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTP))])] + "TARGET_DSP && !TARGET_64BIT" +{ + if (which_alternative == 0) + { + if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + return "extp\t%0,%q1,%2"; + } + return "extpv\t%0,%q1,%2"; +} + [(set_attr "type" "mfhilo") + (set_attr "mode" "SI")]) + +(define_insn "mips_extpdp" + [(parallel + [(set (match_operand:SI 0 "register_operand" "=d,d") + (unspec:SI [(match_operand:DI 1 "register_operand" "a,a") + (match_operand:SI 2 "arith_operand" "I,d") + (reg:CCDSP CCDSP_PO_REGNUM)] + UNSPEC_EXTPDP)) + (set (reg:CCDSP CCDSP_PO_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2) + (reg:CCDSP CCDSP_PO_REGNUM)] UNSPEC_EXTPDP)) + (set (reg:CCDSP CCDSP_EF_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTPDP))])] + "TARGET_DSP && !TARGET_64BIT" +{ + if (which_alternative == 0) + { + if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + return "extpdp\t%0,%q1,%2"; + } + return "extpdpv\t%0,%q1,%2"; +} + [(set_attr "type" "mfhilo") + (set_attr "mode" "SI")]) + +;; SHILO* +(define_insn "mips_shilo" + [(set (match_operand:DI 0 "register_operand" "=a,a") + (unspec:DI [(match_operand:DI 1 "register_operand" "0,0") + (match_operand:SI 2 "arith_operand" "I,d")] + UNSPEC_SHILO))] + "TARGET_DSP && !TARGET_64BIT" +{ + if (which_alternative == 0) + { + if (INTVAL (operands[2]) < -32 || INTVAL (operands[2]) > 31) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); + return "shilo\t%q0,%2"; + } + return "shilov\t%q0,%2"; +} + [(set_attr "type" "mfhilo") + (set_attr "mode" "SI")]) + +;; MTHLIP* +(define_insn "mips_mthlip" + [(parallel + [(set (match_operand:DI 0 "register_operand" "=a") + (unspec:DI [(match_operand:DI 1 "register_operand" "0") + (match_operand:SI 2 "register_operand" "d") + (reg:CCDSP CCDSP_PO_REGNUM)] + UNSPEC_MTHLIP)) + (set (reg:CCDSP CCDSP_PO_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2) + (reg:CCDSP CCDSP_PO_REGNUM)] UNSPEC_MTHLIP))])] + "TARGET_DSP && !TARGET_64BIT" + "mthlip\t%2,%q0" + [(set_attr "type" "mfhilo") + (set_attr "mode" "SI")]) + +;; WRDSP +(define_insn "mips_wrdsp" + [(parallel + [(set (reg:CCDSP CCDSP_PO_REGNUM) + (unspec:CCDSP [(match_operand:SI 0 "register_operand" "d") + (match_operand:SI 1 "const_uimm6_operand" "YA")] + UNSPEC_WRDSP)) + (set (reg:CCDSP CCDSP_SC_REGNUM) + (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP)) + (set (reg:CCDSP CCDSP_CA_REGNUM) + (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP)) + (set (reg:CCDSP CCDSP_OU_REGNUM) + (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP)) + (set (reg:CCDSP CCDSP_CC_REGNUM) + (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP)) + (set (reg:CCDSP CCDSP_EF_REGNUM) + (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP))])] + "TARGET_DSP" + "wrdsp\t%0,%1" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +;; RDDSP +(define_insn "mips_rddsp" + [(set (match_operand:SI 0 "register_operand" "=d") + (unspec:SI [(match_operand:SI 1 "const_uimm6_operand" "YA") + (reg:CCDSP CCDSP_PO_REGNUM) + (reg:CCDSP CCDSP_SC_REGNUM) + (reg:CCDSP CCDSP_CA_REGNUM) + (reg:CCDSP CCDSP_OU_REGNUM) + (reg:CCDSP CCDSP_CC_REGNUM) + (reg:CCDSP CCDSP_EF_REGNUM)] + UNSPEC_RDDSP))] + "TARGET_DSP" + "rddsp\t%0,%1" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +;; Table 2-7. MIPS DSP ASE Instructions: Indexed-Load +;; L*X +(define_insn "mips_lbux" + [(set (match_operand:SI 0 "register_operand" "=d") + (zero_extend:SI (mem:QI (plus:SI (match_operand:SI 1 + "register_operand" "d") + (match_operand:SI 2 + "register_operand" "d")))))] + "TARGET_DSP" + "lbux\t%0,%2(%1)" + [(set_attr "type" "load") + (set_attr "mode" "SI") + (set_attr "length" "4")]) + +(define_insn "mips_lhx" + [(set (match_operand:SI 0 "register_operand" "=d") + (sign_extend:SI (mem:HI (plus:SI (match_operand:SI 1 + "register_operand" "d") + (match_operand:SI 2 + "register_operand" "d")))))] + "TARGET_DSP" + "lhx\t%0,%2(%1)" + [(set_attr "type" "load") + (set_attr "mode" "SI") + (set_attr "length" "4")]) + +(define_insn "mips_lwx" + [(set (match_operand:SI 0 "register_operand" "=d") + (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d"))))] + "TARGET_DSP" + "lwx\t%0,%2(%1)" + [(set_attr "type" "load") + (set_attr "mode" "SI") + (set_attr "length" "4")]) + +;; Table 2-8. MIPS DSP ASE Instructions: Branch +;; BPOSGE32 +(define_insn "mips_bposge" + [(set (pc) + (if_then_else + (ge:CCDSP (reg:CCDSP CCDSP_PO_REGNUM) + (match_operand:SI 0 "immediate_operand" "I")) + (label_ref (match_operand 1 "" "")) + (pc)))] + "TARGET_DSP" + "%*bposge%0\t%1%/" + [(set_attr "type" "branch") + (set_attr "mode" "none")]) + diff --git a/gcc/config/mips/mips-modes.def b/gcc/config/mips/mips-modes.def index 00dabdbc185..39c2f164978 100644 --- a/gcc/config/mips/mips-modes.def +++ b/gcc/config/mips/mips-modes.def @@ -28,6 +28,7 @@ FLOAT_MODE (TF, 16, mips_quad_format); /* Vector modes. */ VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */ +VECTOR_MODES (INT, 4); /* V4QI V2HI */ /* Paired single comparison instructions use 2 or 4 CC. */ CC_MODE (CCV2); @@ -37,3 +38,6 @@ ADJUST_ALIGNMENT (CCV2, 8); CC_MODE (CCV4); ADJUST_BYTESIZE (CCV4, 16); ADJUST_ALIGNMENT (CCV4, 16); + +/* For MIPS DSP control registers. */ +CC_MODE (CCDSP); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index c316ef1c30c..63eb6943b43 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -150,6 +150,35 @@ enum mips_function_type MIPS_DF_FTYPE_DF, MIPS_DF_FTYPE_DF_DF, + /* For MIPS DSP ASE */ + MIPS_DI_FTYPE_DI_SI, + MIPS_DI_FTYPE_DI_SI_SI, + MIPS_DI_FTYPE_DI_V2HI_V2HI, + MIPS_DI_FTYPE_DI_V4QI_V4QI, + MIPS_SI_FTYPE_DI_SI, + MIPS_SI_FTYPE_PTR_SI, + MIPS_SI_FTYPE_SI, + MIPS_SI_FTYPE_SI_SI, + MIPS_SI_FTYPE_V2HI, + MIPS_SI_FTYPE_V2HI_V2HI, + MIPS_SI_FTYPE_V4QI, + MIPS_SI_FTYPE_V4QI_V4QI, + MIPS_SI_FTYPE_VOID, + MIPS_V2HI_FTYPE_SI, + MIPS_V2HI_FTYPE_SI_SI, + MIPS_V2HI_FTYPE_V2HI, + MIPS_V2HI_FTYPE_V2HI_SI, + MIPS_V2HI_FTYPE_V2HI_V2HI, + MIPS_V2HI_FTYPE_V4QI, + MIPS_V2HI_FTYPE_V4QI_V2HI, + MIPS_V4QI_FTYPE_SI, + MIPS_V4QI_FTYPE_V2HI_V2HI, + MIPS_V4QI_FTYPE_V4QI_SI, + MIPS_V4QI_FTYPE_V4QI_V4QI, + MIPS_VOID_FTYPE_SI_SI, + MIPS_VOID_FTYPE_V2HI_V2HI, + MIPS_VOID_FTYPE_V4QI_V4QI, + /* The last type. */ MIPS_MAX_FTYPE_MAX }; @@ -162,6 +191,10 @@ enum mips_builtin_type operands 1 and above. */ MIPS_BUILTIN_DIRECT, + /* The builtin corresponds directly to an .md pattern. There is no return + value and the arguments are mapped to operands 0 and above. */ + MIPS_BUILTIN_DIRECT_NO_TARGET, + /* The builtin corresponds to a comparison instruction followed by a mips_cond_move_tf_ps pattern. The first two arguments are the values to compare and the second two arguments are the vector @@ -185,7 +218,10 @@ enum mips_builtin_type MIPS_BUILTIN_CMP_LOWER, /* As above, but the instruction only sets a single $fcc register. */ - MIPS_BUILTIN_CMP_SINGLE + MIPS_BUILTIN_CMP_SINGLE, + + /* For generating bposge32 branch instructions in MIPS32 DSP ASE. */ + MIPS_BUILTIN_BPOSGE32 }; /* Invokes MACRO (COND) for each c.cond.fmt condition. */ @@ -362,13 +398,14 @@ static rtx mips_prepare_builtin_arg (enum insn_code, unsigned int, tree *); static rtx mips_prepare_builtin_target (enum insn_code, unsigned int, rtx); static rtx mips_expand_builtin (tree, rtx, rtx, enum machine_mode, int); static void mips_init_builtins (void); -static rtx mips_expand_builtin_direct (enum insn_code, rtx, tree); +static rtx mips_expand_builtin_direct (enum insn_code, rtx, tree, bool); static rtx mips_expand_builtin_movtf (enum mips_builtin_type, enum insn_code, enum mips_fp_condition, rtx, tree); static rtx mips_expand_builtin_compare (enum mips_builtin_type, enum insn_code, enum mips_fp_condition, rtx, tree); +static rtx mips_expand_builtin_bposge (enum mips_builtin_type, rtx); /* Structure to be filled in by compute_frame_size with register save masks, and offsets for the current function. */ @@ -644,7 +681,10 @@ const enum reg_class mips_regno_to_class[] = COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, - COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS + COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, + DSP_ACC_REGS, DSP_ACC_REGS, DSP_ACC_REGS, DSP_ACC_REGS, + DSP_ACC_REGS, DSP_ACC_REGS, ALL_REGS, ALL_REGS, + ALL_REGS, ALL_REGS, ALL_REGS, ALL_REGS }; /* Map register constraint character to register class. */ @@ -2608,8 +2648,8 @@ mips_subword (rtx op, int high_p) { if (FP_REG_P (REGNO (op))) return gen_rtx_REG (word_mode, high_p ? REGNO (op) + 1 : REGNO (op)); - if (REGNO (op) == HI_REGNUM) - return gen_rtx_REG (word_mode, high_p ? HI_REGNUM : LO_REGNUM); + if (ACC_HI_REG_P (REGNO (op))) + return gen_rtx_REG (word_mode, high_p ? REGNO (op) : REGNO (op) + 1); } if (MEM_P (op)) @@ -2723,6 +2763,14 @@ mips_output_move (rtx dest, rtx src) if (MD_REG_P (REGNO (dest))) return "mt%0\t%z1"; + if (DSP_ACC_REG_P (REGNO (dest))) + { + static char retval[] = "mt__\t%z1,%q0"; + retval[2] = reg_names[REGNO (dest)][4]; + retval[3] = reg_names[REGNO (dest)][5]; + return retval; + } + if (FP_REG_P (REGNO (dest))) return (dbl_p ? "dmtc1\t%z1,%0" : "mtc1\t%z1,%0"); @@ -2741,6 +2789,14 @@ mips_output_move (rtx dest, rtx src) { if (src_code == REG) { + if (DSP_ACC_REG_P (REGNO (src))) + { + static char retval[] = "mf__\t%0,%q1"; + retval[2] = reg_names[REGNO (src)][4]; + retval[3] = reg_names[REGNO (src)][5]; + return retval; + } + if (ST_REG_P (REGNO (src)) && ISA_HAS_8CC) return "lui\t%0,0x3f80\n\tmovf\t%0,%.,%1"; @@ -4722,6 +4778,9 @@ override_options (void) if (TARGET_PAIRED_SINGLE_FLOAT && !ISA_MIPS64) error ("-mips3d/-mpaired-single must be used with -mips64"); + if (TARGET_MIPS16 && TARGET_DSP) + error ("-mips16 and -mdsp cannot be used together"); + mips_print_operand_punct['?'] = 1; mips_print_operand_punct['#'] = 1; mips_print_operand_punct['/'] = 1; @@ -4761,6 +4820,8 @@ override_options (void) mips_char_to_class['B'] = COP0_REGS; mips_char_to_class['C'] = COP2_REGS; mips_char_to_class['D'] = COP3_REGS; + mips_char_to_class['A'] = DSP_ACC_REGS; + mips_char_to_class['a'] = ACC_REGS; /* Set up array to map GCC register number to debug register number. Ignore the special purpose register numbers. */ @@ -4826,10 +4887,10 @@ override_options (void) /* Allow TFmode for CCmode reloads. */ || (ISA_HAS_8CC && mode == TFmode)); - else if (MD_REG_P (regno)) + else if (ACC_REG_P (regno)) temp = (INTEGRAL_MODE_P (mode) && (size <= UNITS_PER_WORD - || (regno == MD_REG_FIRST + || (ACC_HI_REG_P (regno) && size == 2 * UNITS_PER_WORD))); else if (ALL_COP_REG_P (regno)) @@ -4978,6 +5039,13 @@ override_options (void) void mips_conditional_register_usage (void) { + if (!TARGET_DSP) + { + int regno; + + for (regno = DSP_ACC_REG_FIRST; regno <= DSP_ACC_REG_LAST; regno++) + fixed_regs[regno] = call_used_regs[regno] = 1; + } if (!TARGET_HARD_FLOAT) { int regno; @@ -5122,6 +5190,7 @@ mips_debugger_offset (rtx addr, HOST_WIDE_INT offset) 'Y' for a CONST_INT X, print mips_fp_conditions[X] 'Z' print the operand and a comma for ISA_HAS_8CC, otherwise print nothing 'R' print the reloc associated with LO_SUM + 'q' print DSP accumulator registers The punctuation characters are: @@ -5372,6 +5441,22 @@ print_operand (FILE *file, rtx op, int letter) } } + else if (letter == 'q') + { + int regnum; + + if (code != REG) + fatal_insn ("PRINT_OPERAND, invalid insn for %%q", op); + + regnum = REGNO (op); + if (MD_REG_P (regnum)) + fprintf (file, "$ac0"); + else if (DSP_ACC_REG_P (regnum)) + fprintf (file, "$ac%c", reg_names[regnum][3]); + else + fatal_insn ("PRINT_OPERAND, invalid insn for %%q", op); + } + else if (code == REG || code == SUBREG) { register int regnum; @@ -7316,8 +7401,10 @@ mips_cannot_change_mode_class (enum machine_mode from, /* LO_REGNO == HI_REGNO + 1, so if a multi-word value is stored in LO and HI, the high word always comes first. We therefore can't allow values stored in HI to change between single-word - and multi-word modes. */ - if (reg_classes_intersect_p (HI_REG, class)) + and multi-word modes. + This rule applies to both the original HI/LO pair and the new + DSP accumulators. */ + if (reg_classes_intersect_p (ACC_REGS, class)) return true; } } @@ -7398,8 +7485,10 @@ mips_secondary_reload_class (enum reg_class class, } /* Copying from HI or LO to anywhere other than a general register - requires a general register. */ - if (class == HI_REG || class == LO_REG || class == MD_REGS) + requires a general register. + This rule applies to both the original HI/LO pair and the new + DSP accumulators. */ + if (reg_class_subset_p (class, ACC_REGS)) { if (TARGET_MIPS16 && in_p) { @@ -7408,7 +7497,7 @@ mips_secondary_reload_class (enum reg_class class, } return gp_reg_p ? NO_REGS : gr_regs; } - if (MD_REG_P (regno)) + if (ACC_REG_P (regno)) { if (TARGET_MIPS16 && ! in_p) { @@ -7519,10 +7608,18 @@ mips_valid_pointer_mode (enum machine_mode mode) static bool mips_vector_mode_supported_p (enum machine_mode mode) { - if (mode == V2SFmode && TARGET_PAIRED_SINGLE_FLOAT) - return true; - else - return false; + switch (mode) + { + case V2SFmode: + return TARGET_PAIRED_SINGLE_FLOAT; + + case V2HImode: + case V4QImode: + return TARGET_DSP; + + default: + return false; + } } /* If we can access small data directly (using gp-relative relocation @@ -8887,7 +8984,7 @@ mips_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, } else if (to == FP_REGS) return 4; - else if (to == HI_REG || to == LO_REG || to == MD_REGS) + else if (reg_class_subset_p (to, ACC_REGS)) { if (TARGET_MIPS16) return 12; @@ -8908,7 +9005,7 @@ mips_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, else if (to == ST_REGS) return 8; } - else if (from == HI_REG || from == LO_REG || from == MD_REGS) + else if (reg_class_subset_p (from, ACC_REGS)) { if (GR_REG_CLASS_P (to)) { @@ -9910,6 +10007,116 @@ static const struct builtin_description sb1_bdesc[] = DIRECT_BUILTIN (sqrt_ps, MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT) }; +/* Builtin functions for DSP ASE. */ + +#define CODE_FOR_mips_addq_ph CODE_FOR_addv2hi3 +#define CODE_FOR_mips_addu_qb CODE_FOR_addv4qi3 +#define CODE_FOR_mips_subq_ph CODE_FOR_subv2hi3 +#define CODE_FOR_mips_subu_qb CODE_FOR_subv4qi3 + +/* Define a MIPS_BUILTIN_DIRECT_NO_TARGET function for instruction + CODE_FOR_mips_. 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. 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); + if (TARGET_PAIRED_SINGLE_FLOAT) + { + 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] + = 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] + = 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_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); + 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_V2SF_FTYPE_SF_SF] - = build_function_type_list (V2SF_type_node, - float_type_node, float_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_INT_FTYPE_V2SF_V2SF] - = build_function_type_list (integer_type_node, - 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_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_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_INT_FTYPE_SF_SF] - = build_function_type_list (integer_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_INT_FTYPE_DF_DF] - = build_function_type_list (integer_type_node, - 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_SF_FTYPE_V2SF] - = build_function_type_list (float_type_node, V2SF_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] + = 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_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] + = 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); + types[MIPS_DF_FTYPE_DF_DF] + = build_function_type_list (double_type_node, + double_type_node, double_type_node, NULL_TREE); + } + + if (TARGET_DSP) + { + V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode); + V4QI_type_node = build_vector_type_for_mode (intQI_type_node, V4QImode); + + types[MIPS_V2HI_FTYPE_V2HI_V2HI] + = build_function_type_list (V2HI_type_node, + V2HI_type_node, V2HI_type_node, + NULL_TREE); + + types[MIPS_SI_FTYPE_SI_SI] + = build_function_type_list (intSI_type_node, + intSI_type_node, intSI_type_node, + NULL_TREE); + + types[MIPS_V4QI_FTYPE_V4QI_V4QI] + = build_function_type_list (V4QI_type_node, + V4QI_type_node, V4QI_type_node, + NULL_TREE); + + types[MIPS_SI_FTYPE_V4QI] + = build_function_type_list (intSI_type_node, + V4QI_type_node, + NULL_TREE); + + types[MIPS_V2HI_FTYPE_V2HI] + = build_function_type_list (V2HI_type_node, + V2HI_type_node, + NULL_TREE); + + types[MIPS_SI_FTYPE_SI] + = build_function_type_list (intSI_type_node, + intSI_type_node, + NULL_TREE); + + types[MIPS_V4QI_FTYPE_V2HI_V2HI] + = build_function_type_list (V4QI_type_node, + V2HI_type_node, V2HI_type_node, + NULL_TREE); + + types[MIPS_V2HI_FTYPE_SI_SI] + = build_function_type_list (V2HI_type_node, + intSI_type_node, intSI_type_node, + NULL_TREE); + + types[MIPS_SI_FTYPE_V2HI] + = build_function_type_list (intSI_type_node, + V2HI_type_node, + NULL_TREE); + + types[MIPS_V2HI_FTYPE_V4QI] + = build_function_type_list (V2HI_type_node, + V4QI_type_node, + NULL_TREE); + + types[MIPS_V4QI_FTYPE_V4QI_SI] + = build_function_type_list (V4QI_type_node, + V4QI_type_node, intSI_type_node, + NULL_TREE); + + types[MIPS_V2HI_FTYPE_V2HI_SI] + = build_function_type_list (V2HI_type_node, + V2HI_type_node, intSI_type_node, + NULL_TREE); + + types[MIPS_V2HI_FTYPE_V4QI_V2HI] + = build_function_type_list (V2HI_type_node, + V4QI_type_node, V2HI_type_node, + NULL_TREE); + + types[MIPS_SI_FTYPE_V2HI_V2HI] + = build_function_type_list (intSI_type_node, + V2HI_type_node, V2HI_type_node, + NULL_TREE); + + types[MIPS_DI_FTYPE_DI_V4QI_V4QI] + = build_function_type_list (intDI_type_node, + intDI_type_node, V4QI_type_node, V4QI_type_node, + NULL_TREE); + + types[MIPS_DI_FTYPE_DI_V2HI_V2HI] + = build_function_type_list (intDI_type_node, + intDI_type_node, V2HI_type_node, V2HI_type_node, + NULL_TREE); + + types[MIPS_DI_FTYPE_DI_SI_SI] + = build_function_type_list (intDI_type_node, + intDI_type_node, intSI_type_node, intSI_type_node, + NULL_TREE); + + types[MIPS_V4QI_FTYPE_SI] + = build_function_type_list (V4QI_type_node, + intSI_type_node, + NULL_TREE); + + types[MIPS_V2HI_FTYPE_SI] + = build_function_type_list (V2HI_type_node, + intSI_type_node, + NULL_TREE); + + types[MIPS_VOID_FTYPE_V4QI_V4QI] + = build_function_type_list (void_type_node, + V4QI_type_node, V4QI_type_node, + NULL_TREE); + + types[MIPS_SI_FTYPE_V4QI_V4QI] + = build_function_type_list (intSI_type_node, + V4QI_type_node, V4QI_type_node, + NULL_TREE); + + types[MIPS_VOID_FTYPE_V2HI_V2HI] + = build_function_type_list (void_type_node, + V2HI_type_node, V2HI_type_node, + NULL_TREE); + + types[MIPS_SI_FTYPE_DI_SI] + = build_function_type_list (intSI_type_node, + intDI_type_node, intSI_type_node, + NULL_TREE); + + types[MIPS_DI_FTYPE_DI_SI] + = build_function_type_list (intDI_type_node, + intDI_type_node, intSI_type_node, + NULL_TREE); + + types[MIPS_VOID_FTYPE_SI_SI] + = build_function_type_list (void_type_node, + intSI_type_node, intSI_type_node, + NULL_TREE); + + types[MIPS_SI_FTYPE_PTR_SI] + = build_function_type_list (intSI_type_node, + ptr_type_node, intSI_type_node, + NULL_TREE); + + types[MIPS_SI_FTYPE_VOID] + = build_function_type (intSI_type_node, void_list_node); + } /* Iterate through all of the bdesc arrays, initializing all of the builtin functions. */ @@ -10115,30 +10481,40 @@ mips_init_builtins (void) /* Expand a MIPS_BUILTIN_DIRECT function. ICODE is the code of the .md pattern and ARGLIST is the list of function arguments. TARGET, - if nonnull, suggests a good place to put the result. */ + if nonnull, suggests a good place to put the result. + HAS_TARGET indicates the function must return something. */ static rtx -mips_expand_builtin_direct (enum insn_code icode, rtx target, tree arglist) +mips_expand_builtin_direct (enum insn_code icode, rtx target, tree arglist, + bool has_target) { rtx ops[MAX_RECOG_OPERANDS]; - int i; + int i = 0; - target = mips_prepare_builtin_target (icode, 0, target); - for (i = 1; i < insn_data[icode].n_operands; i++) + if (has_target) + { + /* We save target to ops[0]. */ + ops[0] = mips_prepare_builtin_target (icode, 0, target); + i = 1; + } + + /* We need to test if arglist is not zero. Some instructions have extra + clobber registers. */ + for (; i < insn_data[icode].n_operands && arglist != 0; i++) ops[i] = mips_prepare_builtin_arg (icode, i, &arglist); - switch (insn_data[icode].n_operands) + switch (i) { case 2: - emit_insn (GEN_FCN (icode) (target, ops[1])); + emit_insn (GEN_FCN (icode) (ops[0], ops[1])); break; case 3: - emit_insn (GEN_FCN (icode) (target, ops[1], ops[2])); + emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2])); break; case 4: - emit_insn (GEN_FCN (icode) (target, ops[1], ops[2], ops[3])); + emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3])); break; default: @@ -10268,5 +10644,59 @@ mips_expand_builtin_compare (enum mips_builtin_type builtin_type, return target; } + +/* Expand a bposge builtin of type BUILTIN_TYPE. TARGET, if nonnull, + suggests a good place to put the boolean result. + + The sequence we want is + + li target, 0 + bposge* label1 + j label2 + label1: + li target, 1 + label2: */ + +static rtx +mips_expand_builtin_bposge (enum mips_builtin_type builtin_type, rtx target) +{ + rtx label1, label2, if_then_else; + rtx cmp_result; + int cmp_value; + + if (target == 0 || GET_MODE (target) != SImode) + target = gen_reg_rtx (SImode); + + cmp_result = gen_rtx_REG (CCDSPmode, CCDSP_PO_REGNUM); + + if (builtin_type == MIPS_BUILTIN_BPOSGE32) + cmp_value = 32; + else + gcc_assert (0); + + /* Move 0 to target */ + emit_move_insn (target, const0_rtx); + + /* Generate two labels */ + label1 = gen_label_rtx (); + label2 = gen_label_rtx (); + + /* Generate if_then_else */ + if_then_else + = gen_rtx_IF_THEN_ELSE (VOIDmode, + gen_rtx_fmt_ee (GE, CCDSPmode, + cmp_result, GEN_INT (cmp_value)), + gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx); + + emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else)); + emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, + gen_rtx_LABEL_REF (VOIDmode, label2))); + emit_barrier (); + emit_label (label1); + emit_move_insn (target, const1_rtx); + emit_label (label2); + + return target; +} #include "gt-mips.h" diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 8bb3d50b953..cc38e118dd6 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -316,6 +316,9 @@ extern const struct mips_rtx_cost_data *mips_cost; if (TARGET_MIPS3D) \ builtin_define ("__mips3d"); \ \ + if (TARGET_DSP) \ + builtin_define ("__mips_dsp"); \ + \ MIPS_CPP_SET_PROCESSOR ("_MIPS_ARCH", mips_arch_info); \ MIPS_CPP_SET_PROCESSOR ("_MIPS_TUNE", mips_tune_info); \ \ @@ -807,6 +810,7 @@ extern const struct mips_rtx_cost_data *mips_cost; %{mips32} %{mips32r2} %{mips64} \ %{mips16:%{!mno-mips16:-mips16}} %{mno-mips16:-no-mips16} \ %{mips3d:-mips3d} \ +%{mdsp} \ %{mfix-vr4120} %{mfix-vr4130} \ %(subtarget_asm_optimizing_spec) \ %(subtarget_asm_debugging_spec) \ @@ -1149,9 +1153,11 @@ extern const struct mips_rtx_cost_data *mips_cost; - ARG_POINTER_REGNUM - FRAME_POINTER_REGNUM - FAKE_CALL_REGNO (see the comment above load_callsi for details) - - 3 dummy entries that were used at various times in the past. */ + - 3 dummy entries that were used at various times in the past. + - 6 DSP accumulator registers (3 hi-lo pairs) for MIPS DSP ASE + - 6 DSP control registers */ -#define FIRST_PSEUDO_REGISTER 176 +#define FIRST_PSEUDO_REGISTER 188 /* By default, fix the kernel registers ($26 and $27), the global pointer ($28) and the stack pointer ($29). This can change @@ -1178,7 +1184,9 @@ extern const struct mips_rtx_cost_data *mips_cost; 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ /* COP3 registers */ \ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ + /* 6 DSP accumulator registers & 6 control registers */ \ + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 \ } @@ -1208,7 +1216,9 @@ extern const struct mips_rtx_cost_data *mips_cost; 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ /* COP3 registers */ \ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ + /* 6 DSP accumulator registers & 6 control registers */ \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \ } @@ -1231,7 +1241,9 @@ extern const struct mips_rtx_cost_data *mips_cost; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ /* COP3 registers */ \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + /* 6 DSP accumulator registers & 6 control registers */ \ + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 \ } /* Internal macros to classify a register number as to whether it's a @@ -1273,9 +1285,19 @@ extern const struct mips_rtx_cost_data *mips_cost; /* ALL_COP_REG_NUM assumes that COP0,2,and 3 are numbered consecutively. */ #define ALL_COP_REG_NUM (COP3_REG_LAST - COP0_REG_FIRST + 1) +#define DSP_ACC_REG_FIRST 176 +#define DSP_ACC_REG_LAST 181 +#define DSP_ACC_REG_NUM (DSP_ACC_REG_LAST - DSP_ACC_REG_FIRST + 1) + #define AT_REGNUM (GP_REG_FIRST + 1) #define HI_REGNUM (MD_REG_FIRST + 0) #define LO_REGNUM (MD_REG_FIRST + 1) +#define AC1HI_REGNUM (DSP_ACC_REG_FIRST + 0) +#define AC1LO_REGNUM (DSP_ACC_REG_FIRST + 1) +#define AC2HI_REGNUM (DSP_ACC_REG_FIRST + 2) +#define AC2LO_REGNUM (DSP_ACC_REG_FIRST + 3) +#define AC3HI_REGNUM (DSP_ACC_REG_FIRST + 4) +#define AC3LO_REGNUM (DSP_ACC_REG_FIRST + 5) /* FPSW_REGNUM is the single condition code used if !ISA_HAS_8CC. If ISA_HAS_8CC, it should not be used, and an arbitrary ST_REG @@ -1300,6 +1322,16 @@ extern const struct mips_rtx_cost_data *mips_cost; ((unsigned int) ((int) (REGNO) - COP3_REG_FIRST) < COP3_REG_NUM) #define ALL_COP_REG_P(REGNO) \ ((unsigned int) ((int) (REGNO) - COP0_REG_FIRST) < ALL_COP_REG_NUM) +/* Test if REGNO is one of the 6 new DSP accumulators. */ +#define DSP_ACC_REG_P(REGNO) \ + ((unsigned int) ((int) (REGNO) - DSP_ACC_REG_FIRST) < DSP_ACC_REG_NUM) +/* Test if REGNO is hi, lo, or one of the 6 new DSP accumulators. */ +#define ACC_REG_P(REGNO) \ + (MD_REG_P (REGNO) || DSP_ACC_REG_P (REGNO)) +/* Test if REGNO is HI or the first register of 3 new DSP accumulator pairs. */ +#define ACC_HI_REG_P(REGNO) \ + ((REGNO) == HI_REGNUM || (REGNO) == AC1HI_REGNUM || (REGNO) == AC2HI_REGNUM \ + || (REGNO) == AC3HI_REGNUM) #define FP_REG_RTX_P(X) (REG_P (X) && FP_REG_P (REGNO (X))) @@ -1442,6 +1474,8 @@ enum reg_class ALL_COP_REGS, ALL_COP_AND_GR_REGS, ST_REGS, /* status registers (fp status) */ + DSP_ACC_REGS, /* DSP accumulator registers */ + ACC_REGS, /* Hi/Lo and DSP accumulator registers */ ALL_REGS, /* all registers */ LIM_REG_CLASSES /* max value + 1 */ }; @@ -1482,6 +1516,8 @@ enum reg_class "ALL_COP_REGS", \ "ALL_COP_AND_GR_REGS", \ "ST_REGS", \ + "DSP_ACC_REGS", \ + "ACC_REGS", \ "ALL_REGS" \ } @@ -1523,7 +1559,9 @@ enum reg_class { 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x0000ffff }, \ { 0xffffffff, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x0000ffff }, \ { 0x00000000, 0x00000000, 0x000007f8, 0x00000000, 0x00000000, 0x00000000 }, /* status registers */ \ - { 0xffffffff, 0xffffffff, 0xffff07ff, 0xffffffff, 0xffffffff, 0x0000ffff } /* all registers */ \ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x003f0000 }, /* dsp accumulator registers */ \ + { 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x003f0000 }, /* hi/lo and dsp accumulator registers */ \ + { 0xffffffff, 0xffffffff, 0xffff07ff, 0xffffffff, 0xffffffff, 0x0fffffff } /* all registers */ \ } @@ -1584,7 +1622,8 @@ extern const enum reg_class mips_regno_to_class[]; 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, \ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, \ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, \ - 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175 \ + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, \ + 176,177,178,179,180,181,182,183,184,185,186,187 \ } /* ORDER_REGS_FOR_LOCAL_ALLOC is a macro which permits reg_alloc_order @@ -1615,12 +1654,24 @@ extern const enum reg_class mips_regno_to_class[]; 'B' Cop0 register 'C' Cop2 register 'D' Cop3 register + 'A' DSP accumulator registers + 'a' MD registers and DSP accumulator registers 'b' All registers */ extern enum reg_class mips_char_to_class[256]; #define REG_CLASS_FROM_LETTER(C) mips_char_to_class[(unsigned char)(C)] +/* True if VALUE is a unsigned 6-bit number. */ + +#define UIMM6_OPERAND(VALUE) \ + (((VALUE) & ~(unsigned HOST_WIDE_INT) 0x3f) == 0) + +/* True if VALUE is a signed 10-bit number. */ + +#define IMM10_OPERAND(VALUE) \ + ((unsigned HOST_WIDE_INT) (VALUE) + 0x200 < 0x400) + /* True if VALUE is a signed 16-bit number. */ #define SMALL_OPERAND(VALUE) \ @@ -1718,11 +1769,17 @@ extern enum reg_class mips_char_to_class[256]; This is true for all non-mips16 references (although it can sometimes be indirect if !TARGET_EXPLICIT_RELOCS). For mips16, it excludes stack and constant-pool references. - `YG' is for 0 valued vector constants. */ + `YG' is for 0 valued vector constants. + `YA' is for unsigned 6-bit constants. + `YB' is for signed 10-bit constants. */ #define EXTRA_CONSTRAINT_Y(OP,STR) \ (((STR)[1] == 'G') ? (GET_CODE (OP) == CONST_VECTOR \ && (OP) == CONST0_RTX (GET_MODE (OP))) \ + : ((STR)[1] == 'A') ? (GET_CODE (OP) == CONST_INT \ + && UIMM6_OPERAND (INTVAL (OP))) \ + : ((STR)[1] == 'B') ? (GET_CODE (OP) == CONST_INT \ + && IMM10_OPERAND (INTVAL (OP))) \ : FALSE) @@ -2386,7 +2443,9 @@ typedef struct mips_args { "$c3r0", "$c3r1", "$c3r2", "$c3r3", "$c3r4", "$c3r5", "$c3r6", "$c3r7", \ "$c3r8", "$c3r9", "$c3r10","$c3r11","$c3r12","$c3r13","$c3r14","$c3r15", \ "$c3r16","$c3r17","$c3r18","$c3r19","$c3r20","$c3r21","$c3r22","$c3r23", \ - "$c3r24","$c3r25","$c3r26","$c3r27","$c3r28","$c3r29","$c3r30","$c3r31" } + "$c3r24","$c3r25","$c3r26","$c3r27","$c3r28","$c3r29","$c3r30","$c3r31", \ + "$ac1hi","$ac1lo","$ac2hi","$ac2lo","$ac3hi","$ac3lo","$dsp_po","$dsp_sc", \ + "$dsp_ca","$dsp_ou","$dsp_cc","$dsp_ef" } /* List the "software" names for each register. Also list the numerical names for $fp and $sp. */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index bf4bc69e39c..a43a0c28847 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -72,6 +72,76 @@ (UNSPEC_RSQRT2 209) (UNSPEC_RECIP1 210) (UNSPEC_RECIP2 211) + + ;; MIPS DSP ASE Revision 0.98 3/24/2005 + (UNSPEC_ADDQ 300) + (UNSPEC_ADDQ_S 301) + (UNSPEC_SUBQ 302) + (UNSPEC_SUBQ_S 303) + (UNSPEC_ADDSC 304) + (UNSPEC_ADDWC 305) + (UNSPEC_MODSUB 306) + (UNSPEC_RADDU_W_QB 307) + (UNSPEC_ABSQ_S 308) + (UNSPEC_PRECRQ_QB_PH 309) + (UNSPEC_PRECRQ_PH_W 310) + (UNSPEC_PRECRQ_RS_PH_W 311) + (UNSPEC_PRECRQU_S_QB_PH 312) + (UNSPEC_PRECEQ_W_PHL 313) + (UNSPEC_PRECEQ_W_PHR 314) + (UNSPEC_PRECEQU_PH_QBL 315) + (UNSPEC_PRECEQU_PH_QBR 316) + (UNSPEC_PRECEQU_PH_QBLA 317) + (UNSPEC_PRECEQU_PH_QBRA 318) + (UNSPEC_PRECEU_PH_QBL 319) + (UNSPEC_PRECEU_PH_QBR 320) + (UNSPEC_PRECEU_PH_QBLA 321) + (UNSPEC_PRECEU_PH_QBRA 322) + (UNSPEC_SHLL 323) + (UNSPEC_SHLL_S 324) + (UNSPEC_SHRL_QB 325) + (UNSPEC_SHRA_PH 326) + (UNSPEC_SHRA_R 327) + (UNSPEC_MULEU_S_PH_QBL 328) + (UNSPEC_MULEU_S_PH_QBR 329) + (UNSPEC_MULQ_RS_PH 330) + (UNSPEC_MULEQ_S_W_PHL 331) + (UNSPEC_MULEQ_S_W_PHR 332) + (UNSPEC_DPAU_H_QBL 333) + (UNSPEC_DPAU_H_QBR 334) + (UNSPEC_DPSU_H_QBL 335) + (UNSPEC_DPSU_H_QBR 336) + (UNSPEC_DPAQ_S_W_PH 337) + (UNSPEC_DPSQ_S_W_PH 338) + (UNSPEC_MULSAQ_S_W_PH 339) + (UNSPEC_DPAQ_SA_L_W 340) + (UNSPEC_DPSQ_SA_L_W 341) + (UNSPEC_MAQ_S_W_PHL 342) + (UNSPEC_MAQ_S_W_PHR 343) + (UNSPEC_MAQ_SA_W_PHL 344) + (UNSPEC_MAQ_SA_W_PHR 345) + (UNSPEC_BITREV 346) + (UNSPEC_INSV 347) + (UNSPEC_REPL_QB 348) + (UNSPEC_REPL_PH 349) + (UNSPEC_CMP_EQ 350) + (UNSPEC_CMP_LT 351) + (UNSPEC_CMP_LE 352) + (UNSPEC_CMPGU_EQ_QB 353) + (UNSPEC_CMPGU_LT_QB 354) + (UNSPEC_CMPGU_LE_QB 355) + (UNSPEC_PICK 356) + (UNSPEC_PACKRL_PH 357) + (UNSPEC_EXTR_W 358) + (UNSPEC_EXTR_R_W 359) + (UNSPEC_EXTR_RS_W 360) + (UNSPEC_EXTR_S_H 361) + (UNSPEC_EXTP 362) + (UNSPEC_EXTPDP 363) + (UNSPEC_SHILO 364) + (UNSPEC_MTHLIP 365) + (UNSPEC_WRDSP 366) + (UNSPEC_RDDSP 367) ] ) @@ -3124,8 +3194,8 @@ (set_attr "mode" "")]) (define_insn "*movdi_32bit" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*x,*d,*B*C*D,*B*C*D,*d,*m") - (match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*x,*d,*m,*B*C*D,*B*C*D"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*B*C*D,*B*C*D,*d,*m") + (match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))] "!TARGET_64BIT && !TARGET_MIPS16 && (register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode))" @@ -3242,15 +3312,15 @@ ;; in FP registers (off by default, use -mdebugh to enable). (define_insn "*movsi_internal" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*d,*z,*x,*B*C*D,*B*C*D,*d,*m") - (match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*z,*d,*J*d,*d,*m,*B*C*D,*B*C*D"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m") + (match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*z,*d,*J*d,*A,*d,*m,*B*C*D,*B*C*D"))] "!TARGET_MIPS16 && (register_operand (operands[0], SImode) || reg_or_0_operand (operands[1], SImode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,xfer,xfer,mthilo,xfer,load,xfer,store") + [(set_attr "type" "arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,xfer,xfer,mthilo,mfhilo,xfer,load,xfer,store") (set_attr "mode" "SI") - (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,4,4,4,*,4,*")]) + (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,4,4,4,4,*,4,*")]) (define_insn "*movsi_mips16" [(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m") @@ -5353,3 +5423,7 @@ ; The MIPS Paired-Single Floating Point and MIPS-3D Instructions. (include "mips-ps-3d.md") + +; The MIPS DSP Instructions. + +(include "mips-dsp.md") diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt index 6bd719abbb0..737f5edecb1 100644 --- a/gcc/config/mips/mips.opt +++ b/gcc/config/mips/mips.opt @@ -55,6 +55,10 @@ mdouble-float Target Report RejectNegative InverseMask(SINGLE_FLOAT, DOUBLE_FLOAT) Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations +mdsp +Target Report Mask(DSP) +Use MIPS-DSP instructions + mdebug Target Var(TARGET_DEBUG_MODE) Undocumented diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md index 1fc3c6e43ed..e4e3805845f 100644 --- a/gcc/config/mips/predicates.md +++ b/gcc/config/mips/predicates.md @@ -34,6 +34,18 @@ (ior (match_operand 0 "const_arith_operand") (match_operand 0 "register_operand"))) +(define_predicate "const_uimm6_operand" + (and (match_code "const_int") + (match_test "UIMM6_OPERAND (INTVAL (op))"))) + +(define_predicate "const_imm10_operand" + (and (match_code "const_int") + (match_test "IMM10_OPERAND (INTVAL (op))"))) + +(define_predicate "reg_imm10_operand" + (ior (match_operand 0 "const_imm10_operand") + (match_operand 0 "register_operand"))) + (define_predicate "sle_operand" (and (match_code "const_int") (match_test "SMALL_OPERAND (INTVAL (op) + 1)"))) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 69bd151f84b..7e137950065 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -5777,6 +5777,7 @@ instructions, but allow the compiler to schedule those calls. * Blackfin Built-in Functions:: * FR-V Built-in Functions:: * X86 Built-in Functions:: +* MIPS DSP Built-in Functions:: * MIPS Paired-Single Support:: * PowerPC AltiVec Built-in Functions:: * SPARC VIS Built-in Functions:: @@ -6676,6 +6677,208 @@ v2sf __builtin_ia32_pswapdsf (v2sf) v2si __builtin_ia32_pswapdsi (v2si) @end smallexample +@node MIPS DSP Built-in Functions +@subsection MIPS DSP Built-in Functions + +The MIPS DSP Application-Specific Extension (ASE) includes new +instructions that are designed to improve the performance of DSP and +media applications. It provides instructions that operate on packed +8-bit integer data, Q15 fractional data and Q31 fractional data. + +GCC supports MIPS DSP operations using both the generic +vector extensions (@pxref{Vector Extensions}) and a collection of +MIPS-specific built-in functions. Both kinds of support are +enabled by the @option{-mdsp} command-line option. + +At present, GCC only provides support for operations on 32-bit +vectors. The vector type associated with 8-bit integer data is +usually called @code{v4i8} and the vector type associated with Q15 is +usually called @code{v2q15}. They can be defined in C as follows: + +@smallexample +typedef char v4i8 __attribute__ ((vector_size(4))); +typedef short v2q15 __attribute__ ((vector_size(4))); +@end smallexample + +@code{v4i8} and @code{v2q15} values are initialized in the same way as +aggregates. For example: + +@smallexample +v4i8 a = @{1, 2, 3, 4@}; +v4i8 b; +b = (v4i8) @{5, 6, 7, 8@}; + +v2q15 c = @{0x0fcb, 0x3a75@}; +v2q15 d; +d = (v2q15) @{0.1234 * 0x1.0p15, 0.4567 * 0x1.0p15@}; +@end smallexample + +@emph{Note:} The CPU's endianness determines the order in which values +are packed. On little-endian targets, the first value is the least +significant and the last value is the most significant. The opposite +order applies to big-endian targets. For example, the code above will +set the lowest byte of @code{a} to @code{1} on little-endian targets +and @code{4} on big-endian targets. + +@emph{Note:} Q15 and Q31 values must be initialized with their integer +representation. As shown in this example, the integer representation +of a Q15 value can be obtained by multiplying the fractional value by +@code{0x1.0p15}. The equivalent for Q31 values is to multiply by +@code{0x1.0p31}. + +The table below lists the @code{v4i8} and @code{v2q15} operations for which +hardware support exists. @code{a} and @code{b} are @code{v4i8} values, +and @code{c} and @code{d} are @code{v2q15} values. + +@multitable @columnfractions .50 .50 +@item C code @tab MIPS instruction +@item @code{a + b} @tab @code{addu.qb} +@item @code{c + d} @tab @code{addq.ph} +@item @code{a - b} @tab @code{subu.qb} +@item @code{c - d} @tab @code{subq.ph} +@end multitable + +It is easier to describe the DSP built-in functions if we first define +the following types: + +@smallexample +typedef int q31; +typedef int i32; +typedef long long a64; +@end smallexample + +@code{q31} and @code{i32} are actually the same as @code{int}, but we +use @code{q31} to indicate a Q31 fractional value and @code{i32} to +indicate a 32-bit integer value. Similarly, @code{a64} is the same as +@code{long long}, but we use @code{a64} to indicate values that will +be placed in one of the four DSP accumulators (@code{$ac0}, +@code{$ac1}, @code{$ac2} or @code{$ac3}). + +Also, some built-in functions prefer or require immediate numbers as +parameters, because the corresponding DSP instructions accept both immediate +numbers and register operands, or accept immediate numbers only. The +immediate parameters are listed as follows. + +@smallexample +imm0_7: 0 to 7. +imm0_15: 0 to 15. +imm0_31: 0 to 31. +imm0_63: 0 to 63. +imm0_255: 0 to 255. +imm_n32_31: -32 to 31. +imm_n512_511: -512 to 511. +@end smallexample + +The following built-in functions map directly to a particular MIPS DSP +instruction. Please refer to the architecture specification +for details on what each instruction does. + +@smallexample +v2q15 __builtin_mips_addq_ph (v2q15, v2q15) +v2q15 __builtin_mips_addq_s_ph (v2q15, v2q15) +q31 __builtin_mips_addq_s_w (q31, q31) +v4i8 __builtin_mips_addu_qb (v4i8, v4i8) +v4i8 __builtin_mips_addu_s_qb (v4i8, v4i8) +v2q15 __builtin_mips_subq_ph (v2q15, v2q15) +v2q15 __builtin_mips_subq_s_ph (v2q15, v2q15) +q31 __builtin_mips_subq_s_w (q31, q31) +v4i8 __builtin_mips_subu_qb (v4i8, v4i8) +v4i8 __builtin_mips_subu_s_qb (v4i8, v4i8) +i32 __builtin_mips_addsc (i32, i32) +i32 __builtin_mips_addwc (i32, i32) +i32 __builtin_mips_modsub (i32, i32) +i32 __builtin_mips_raddu_w_qb (v4i8) +v2q15 __builtin_mips_absq_s_ph (v2q15) +q31 __builtin_mips_absq_s_w (q31) +v4i8 __builtin_mips_precrq_qb_ph (v2q15, v2q15) +v2q15 __builtin_mips_precrq_ph_w (q31, q31) +v2q15 __builtin_mips_precrq_rs_ph_w (q31, q31) +v4i8 __builtin_mips_precrqu_s_qb_ph (v2q15, v2q15) +q31 __builtin_mips_preceq_w_phl (v2q15) +q31 __builtin_mips_preceq_w_phr (v2q15) +v2q15 __builtin_mips_precequ_ph_qbl (v4i8) +v2q15 __builtin_mips_precequ_ph_qbr (v4i8) +v2q15 __builtin_mips_precequ_ph_qbla (v4i8) +v2q15 __builtin_mips_precequ_ph_qbra (v4i8) +v2q15 __builtin_mips_preceu_ph_qbl (v4i8) +v2q15 __builtin_mips_preceu_ph_qbr (v4i8) +v2q15 __builtin_mips_preceu_ph_qbla (v4i8) +v2q15 __builtin_mips_preceu_ph_qbra (v4i8) +v4i8 __builtin_mips_shll_qb (v4i8, imm0_7) +v4i8 __builtin_mips_shll_qb (v4i8, i32) +v2q15 __builtin_mips_shll_ph (v2q15, imm0_15) +v2q15 __builtin_mips_shll_ph (v2q15, i32) +v2q15 __builtin_mips_shll_s_ph (v2q15, imm0_15) +v2q15 __builtin_mips_shll_s_ph (v2q15, i32) +q31 __builtin_mips_shll_s_w (q31, imm0_31) +q31 __builtin_mips_shll_s_w (q31, i32) +v4i8 __builtin_mips_shrl_qb (v4i8, imm0_7) +v4i8 __builtin_mips_shrl_qb (v4i8, i32) +v2q15 __builtin_mips_shra_ph (v2q15, imm0_15) +v2q15 __builtin_mips_shra_ph (v2q15, i32) +v2q15 __builtin_mips_shra_r_ph (v2q15, imm0_15) +v2q15 __builtin_mips_shra_r_ph (v2q15, i32) +q31 __builtin_mips_shra_r_w (q31, imm0_31) +q31 __builtin_mips_shra_r_w (q31, i32) +v2q15 __builtin_mips_muleu_s_ph_qbl (v4i8, v2q15) +v2q15 __builtin_mips_muleu_s_ph_qbr (v4i8, v2q15) +v2q15 __builtin_mips_mulq_rs_ph (v2q15, v2q15) +q31 __builtin_mips_muleq_s_w_phl (v2q15, v2q15) +q31 __builtin_mips_muleq_s_w_phr (v2q15, v2q15) +a64 __builtin_mips_dpau_h_qbl (a64, v4i8, v4i8) +a64 __builtin_mips_dpau_h_qbr (a64, v4i8, v4i8) +a64 __builtin_mips_dpsu_h_qbl (a64, v4i8, v4i8) +a64 __builtin_mips_dpsu_h_qbr (a64, v4i8, v4i8) +a64 __builtin_mips_dpaq_s_w_ph (a64, v2q15, v2q15) +a64 __builtin_mips_dpaq_sa_l_w (a64, q31, q31) +a64 __builtin_mips_dpsq_s_w_ph (a64, v2q15, v2q15) +a64 __builtin_mips_dpsq_sa_l_w (a64, q31, q31) +a64 __builtin_mips_mulsaq_s_w_ph (a64, v2q15, v2q15) +a64 __builtin_mips_maq_s_w_phl (a64, v2q15, v2q15) +a64 __builtin_mips_maq_s_w_phr (a64, v2q15, v2q15) +a64 __builtin_mips_maq_sa_w_phl (a64, v2q15, v2q15) +a64 __builtin_mips_maq_sa_w_phr (a64, v2q15, v2q15) +i32 __builtin_mips_bitrev (i32) +i32 __builtin_mips_insv (i32, i32) +v4i8 __builtin_mips_repl_qb (imm0_255) +v4i8 __builtin_mips_repl_qb (i32) +v2q15 __builtin_mips_repl_ph (imm_n512_511) +v2q15 __builtin_mips_repl_ph (i32) +void __builtin_mips_cmpu_eq_qb (v4i8, v4i8) +void __builtin_mips_cmpu_lt_qb (v4i8, v4i8) +void __builtin_mips_cmpu_le_qb (v4i8, v4i8) +i32 __builtin_mips_cmpgu_eq_qb (v4i8, v4i8) +i32 __builtin_mips_cmpgu_lt_qb (v4i8, v4i8) +i32 __builtin_mips_cmpgu_le_qb (v4i8, v4i8) +void __builtin_mips_cmp_eq_ph (v2q15, v2q15) +void __builtin_mips_cmp_lt_ph (v2q15, v2q15) +void __builtin_mips_cmp_le_ph (v2q15, v2q15) +v4i8 __builtin_mips_pick_qb (v4i8, v4i8) +v2q15 __builtin_mips_pick_ph (v2q15, v2q15) +v2q15 __builtin_mips_packrl_ph (v2q15, v2q15) +i32 __builtin_mips_extr_w (a64, imm0_31) +i32 __builtin_mips_extr_w (a64, i32) +i32 __builtin_mips_extr_r_w (a64, imm0_31) +i32 __builtin_mips_extr_s_h (a64, i32) +i32 __builtin_mips_extr_rs_w (a64, imm0_31) +i32 __builtin_mips_extr_rs_w (a64, i32) +i32 __builtin_mips_extr_s_h (a64, imm0_31) +i32 __builtin_mips_extr_r_w (a64, i32) +i32 __builtin_mips_extp (a64, imm0_31) +i32 __builtin_mips_extp (a64, i32) +i32 __builtin_mips_extpdp (a64, imm0_31) +i32 __builtin_mips_extpdp (a64, i32) +a64 __builtin_mips_shilo (a64, imm_n32_31) +a64 __builtin_mips_shilo (a64, i32) +a64 __builtin_mips_mthlip (a64, i32) +void __builtin_mips_wrdsp (i32, imm0_63) +i32 __builtin_mips_rddsp (imm0_63) +i32 __builtin_mips_lbux (void *, i32) +i32 __builtin_mips_lhx (void *, i32) +i32 __builtin_mips_lwx (void *, i32) +i32 __builtin_mips_bposge32 (void) +@end smallexample + @node MIPS Paired-Single Support @subsection MIPS Paired-Single Support diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 4685c636240..988f13b1dbd 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -572,7 +572,7 @@ Objective-C and Objective-C++ Dialects}. -mips16 -mno-mips16 -mabi=@var{abi} -mabicalls -mno-abicalls @gol -mxgot -mno-xgot -mgp32 -mgp64 -mfp32 -mfp64 @gol -mhard-float -msoft-float -msingle-float -mdouble-float @gol --mpaired-single -mips3d @gol +-mdsp -mpaired-single -mips3d @gol -mlong64 -mlong32 -msym32 -mno-sym32 @gol -G@var{num} -membedded-data -mno-embedded-data @gol -muninit-const-in-rodata -mno-uninit-const-in-rodata @gol @@ -10065,6 +10065,12 @@ operations. Assume that the floating-point coprocessor supports double-precision operations. This is the default. +@itemx -mdsp +@itemx -mno-dsp +@opindex mdsp +@opindex mno-dsp +Use (do not use) the MIPS DSP ASE. @xref{MIPS DSP Built-in Functions}. + @itemx -mpaired-single @itemx -mno-paired-single @opindex mpaired-single diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 82e606d2740..a14dccc70ab 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-07-23 Chao-ying Fu + + * gcc.target/mips/mips32-dsp-type.c: New test. + * gcc.target/mips/mips32-dsp.c: New test. + 2005-07-23 Oyvind Harboe PR testsuite/21073 diff --git a/gcc/testsuite/gcc.target/mips/mips32-dsp-type.c b/gcc/testsuite/gcc.target/mips/mips32-dsp-type.c new file mode 100644 index 00000000000..030a9552c0c --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/mips32-dsp-type.c @@ -0,0 +1,30 @@ +/* Test MIPS32 DSP instructions */ +/* { dg-do compile } */ +/* { dg-mips-options "-mips32 -mdsp" } */ +/* { dg-final { scan-assembler "addq.ph" } } */ +/* { dg-final { scan-assembler "addu.qb" } } */ +/* { dg-final { scan-assembler "subq.ph" } } */ +/* { dg-final { scan-assembler "subu.qb" } } */ + +typedef char v4qi __attribute__ ((vector_size(4))); +typedef short v2hi __attribute__ ((vector_size(4))); + +v2hi add_v2hi (v2hi a, v2hi b) +{ + return a + b; +} + +v4qi add_v4qi (v4qi a, v4qi b) +{ + return a + b; +} + +v2hi sub_v2hi (v2hi a, v2hi b) +{ + return a - b; +} + +v4qi sub_v4qi (v4qi a, v4qi b) +{ + return a - b; +} diff --git a/gcc/testsuite/gcc.target/mips/mips32-dsp.c b/gcc/testsuite/gcc.target/mips/mips32-dsp.c new file mode 100644 index 00000000000..cc38c1b798a --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/mips32-dsp.c @@ -0,0 +1,1092 @@ +/* Test MIPS32 DSP instructions */ +/* { dg-do compile } */ +/* { dg-mips-options "-mips32 -mdsp" } */ +/* { dg-final { scan-assembler "addq.ph" } } */ +/* { dg-final { scan-assembler "addq_s.ph" } } */ +/* { dg-final { scan-assembler "addq_s.w" } } */ +/* { dg-final { scan-assembler "addu.qb" } } */ +/* { dg-final { scan-assembler "addu_s.qb" } } */ +/* { dg-final { scan-assembler "subq.ph" } } */ +/* { dg-final { scan-assembler "subq_s.ph" } } */ +/* { dg-final { scan-assembler "subq_s.w" } } */ +/* { dg-final { scan-assembler "subu.qb" } } */ +/* { dg-final { scan-assembler "subu_s.qb" } } */ +/* { dg-final { scan-assembler "addsc" } } */ +/* { dg-final { scan-assembler "addwc" } } */ +/* { dg-final { scan-assembler "modsub" } } */ +/* { dg-final { scan-assembler "raddu.w.qb" } } */ +/* { dg-final { scan-assembler "absq_s.ph" } } */ +/* { dg-final { scan-assembler "absq_s.w" } } */ +/* { dg-final { scan-assembler "precrq.qb.ph" } } */ +/* { dg-final { scan-assembler "precrq.ph.w" } } */ +/* { dg-final { scan-assembler "precrq_rs.ph.w" } } */ +/* { dg-final { scan-assembler "precrqu_s.qb.ph" } } */ +/* { dg-final { scan-assembler "preceq.w.phl" } } */ +/* { dg-final { scan-assembler "preceq.w.phr" } } */ +/* { dg-final { scan-assembler "precequ.ph.qbl" } } */ +/* { dg-final { scan-assembler "precequ.ph.qbr" } } */ +/* { dg-final { scan-assembler "precequ.ph.qbla" } } */ +/* { dg-final { scan-assembler "precequ.ph.qbra" } } */ +/* { dg-final { scan-assembler "preceu.ph.qbl" } } */ +/* { dg-final { scan-assembler "preceu.ph.qbr" } } */ +/* { dg-final { scan-assembler "preceu.ph.qbla" } } */ +/* { dg-final { scan-assembler "preceu.ph.qbra" } } */ +/* { dg-final { scan-assembler "shllv?.qb" } } */ +/* { dg-final { scan-assembler "shllv?.ph" } } */ +/* { dg-final { scan-assembler "shllv?_s.ph" } } */ +/* { dg-final { scan-assembler "shllv?_s.w" } } */ +/* { dg-final { scan-assembler "shrlv?.qb" } } */ +/* { dg-final { scan-assembler "shrav?.ph" } } */ +/* { dg-final { scan-assembler "shrav?_r.ph" } } */ +/* { dg-final { scan-assembler "shrav?_r.w" } } */ +/* { dg-final { scan-assembler "muleu_s.ph.qbl" } } */ +/* { dg-final { scan-assembler "muleu_s.ph.qbr" } } */ +/* { dg-final { scan-assembler "mulq_rs.ph" } } */ +/* { dg-final { scan-assembler "muleq_s.w.phl" } } */ +/* { dg-final { scan-assembler "muleq_s.w.phr" } } */ +/* { dg-final { scan-assembler "dpau.h.qbl" } } */ +/* { dg-final { scan-assembler "dpau.h.qbr" } } */ +/* { dg-final { scan-assembler "dpsu.h.qbl" } } */ +/* { dg-final { scan-assembler "dpsu.h.qbr" } } */ +/* { dg-final { scan-assembler "dpaq_s.w.ph" } } */ +/* { dg-final { scan-assembler "dpsq_s.w.ph" } } */ +/* { dg-final { scan-assembler "mulsaq_s.w.ph" } } */ +/* { dg-final { scan-assembler "dpaq_sa.l.w" } } */ +/* { dg-final { scan-assembler "dpsq_sa.l.w" } } */ +/* { dg-final { scan-assembler "maq_s.w.phl" } } */ +/* { dg-final { scan-assembler "maq_s.w.phr" } } */ +/* { dg-final { scan-assembler "maq_sa.w.phl" } } */ +/* { dg-final { scan-assembler "maq_sa.w.phr" } } */ +/* { dg-final { scan-assembler "bitrev" } } */ +/* { dg-final { scan-assembler "insv" } } */ +/* { dg-final { scan-assembler "replv?.qb" } } */ +/* { dg-final { scan-assembler "repl.ph" } } */ +/* { dg-final { scan-assembler "replv.ph" } } */ +/* { dg-final { scan-assembler "cmpu.eq.qb" } } */ +/* { dg-final { scan-assembler "cmpu.lt.qb" } } */ +/* { dg-final { scan-assembler "cmpu.le.qb" } } */ +/* { dg-final { scan-assembler "cmpgu.eq.qb" } } */ +/* { dg-final { scan-assembler "cmpgu.lt.qb" } } */ +/* { dg-final { scan-assembler "cmpgu.le.qb" } } */ +/* { dg-final { scan-assembler "cmp.eq.ph" } } */ +/* { dg-final { scan-assembler "cmp.lt.ph" } } */ +/* { dg-final { scan-assembler "cmp.le.ph" } } */ +/* { dg-final { scan-assembler "pick.qb" } } */ +/* { dg-final { scan-assembler "pick.ph" } } */ +/* { dg-final { scan-assembler "packrl.ph" } } */ +/* { dg-final { scan-assembler "extrv?.w" } } */ +/* { dg-final { scan-assembler "extrv?_s.h" } } */ +/* { dg-final { scan-assembler "extrv?_r.w" } } */ +/* { dg-final { scan-assembler "extrv?_rs.w" } } */ +/* { dg-final { scan-assembler "extpv?" } } */ +/* { dg-final { scan-assembler "extpdpv?" } } */ +/* { dg-final { scan-assembler "shilov?" } } */ +/* { dg-final { scan-assembler "mthlip" } } */ +/* { dg-final { scan-assembler "mfhi" } } */ +/* { dg-final { scan-assembler "mflo" } } */ +/* { dg-final { scan-assembler "mthi" } } */ +/* { dg-final { scan-assembler "mtlo" } } */ +/* { dg-final { scan-assembler "wrdsp" } } */ +/* { dg-final { scan-assembler "rddsp" } } */ +/* { dg-final { scan-assembler "lbux?" } } */ +/* { dg-final { scan-assembler "lhx?" } } */ +/* { dg-final { scan-assembler "lwx?" } } */ +/* { dg-final { scan-assembler "bposge32" } } */ + +#include +#include + +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 (); +} +