All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support
@ 2012-08-21  6:53 Jia Liu
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 01/13] target-mips-ase-dsp: Add internal functions Jia Liu
                   ` (12 more replies)
  0 siblings, 13 replies; 20+ messages in thread
From: Jia Liu @ 2012-08-21  6:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

This is MIPS ASE DSP instructions support for QEMU. These instructions
are grouped according to "Chapter 4. MIPS DSP ASE Instruction Summary"
in MIPS ASE DSP manual [1][2].

[1] MIPS32® Architecture for Programmers VolumeIV-e: The MIPS® DSP
    Application-Specific Extension to the MIPS32®Architecture
    http://www.mips.com/products/product-materials/processor/mips-architecture/

[2] MIPS64® Architecture for Programmers VolumeIV-e: The MIPS® DSP
    Application-Specific Extention to the MIPS64® Architecture
    http://www.mips.com/products/product-materials/processor/mips-architecture/

Signed-off-by: Jia Liu <proljc@gmail.com>
---

Version History:
v6:
Addressed Siarhei Siamashka's review comments:
- make internal function mipsdsp_mul_u8_u16 more clean

- fix MFHI MFLO MTHI MTLO, make mips64 linux run OK

v5:
Addressed Richard's review comments:
- bug shooting with --enanle-debug-tcg

- add check_insn for each DSP instructions
- MIPS64 ASE DSP support

v4:
Addressed Richard's review comments:
- split transalte.
- tested on i386 machine.
- delete all global env usage so that we don't need to include dyngen-exec.h.
- fix DEF_HELPER_FLAGS_N error.
- fix all ERRORS and WARNINGS found by ./scripts/checkpatch.pl.
- make sample if() code clearer.
- combine helper_cmpgu_cond_* and helper_cmpgdu_cond_*.
- fix bitrev.
- implement repl* and load with no helper.
- using TCG_COND_GE instead of TCG_COND_GT in OPC_BPOSGE32.

Thanks WeiRen for prereviewing and lots of suggestion.

v3:
Addressed Peter's review comments:
- split these changes into more patches.
- add "ULL" suffix for constants which are more than 32 bits wide.

Addressed WeiRen's review comments:
- split these changes into 12 patches.
- more suitable subject and description for every patch.

Addressed Richard's review comments:
- use DEF_HELPER_FLAGS_N instead of DEF_HELPER_N in some insns.
- put most DSP helpers into dsp_helper.c

- fix two testcases error.

v2:
Addressed Stefan's review comments:
- fixed coding style.
- changed acc into unsigned int form int and no initialization in translation.
- added return value in testcases.

v1:
- add MIPS ASE DSP Support.

Jia Liu (13):
  target-mips-ase-dsp: Add internal functions
  target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO
    rather than using a fix number
  target-mips-ase-dsp: Add branch instructions
  target-mips-ase-dsp: Add load instructions
  target-mips-ase-dsp: Add arithmetic instructions
  target-mips-ase-dsp: Add GPR Based shift instructions
  target-mips-ase-dsp: Add multiply instructions
  target-mips-ase-dsp: Add bit/manipulation instructions
  target-mips-ase-dsp: Add compare pick instructions
  target-mips-ase-dsp: Add MIPS ASE DSP Accumulator and DSPControl
    Access instructions
  target-mips-ase-dsp: Add MIPS[32|64] ASE DSP[R1|R2] generic cpu model
  target-mips-ase-dsp: Add testcases
  target-mips-ase-dsp: Change TODO

 target-mips/Makefile.objs                      |    2 +-
 target-mips/TODO                               |    2 -
 target-mips/dsp_helper.c                       | 8261 ++++++++++++++++++++++++
 target-mips/helper.h                           |  396 ++
 target-mips/translate.c                        | 2906 ++++++++-
 target-mips/translate_init.c                   |   55 +
 tests/tcg/mips/mips32-dsp/Makefile             |  134 +
 tests/tcg/mips/mips32-dsp/absq_s_ph.c          |   31 +
 tests/tcg/mips/mips32-dsp/absq_s_w.c           |   37 +
 tests/tcg/mips/mips32-dsp/addq_ph.c            |   30 +
 tests/tcg/mips/mips32-dsp/addq_s_ph.c          |   30 +
 tests/tcg/mips/mips32-dsp/addsc.c              |   30 +
 tests/tcg/mips/mips32-dsp/addu_qb.c            |   30 +
 tests/tcg/mips/mips32-dsp/addu_s_qb.c          |   30 +
 tests/tcg/mips/mips32-dsp/addwc.c              |   30 +
 tests/tcg/mips/mips32-dsp/bitrev.c             |   20 +
 tests/tcg/mips/mips32-dsp/bposge32.c           |   44 +
 tests/tcg/mips/mips32-dsp/cmp_eq_ph.c          |   35 +
 tests/tcg/mips/mips32-dsp/cmp_le_ph.c          |   35 +
 tests/tcg/mips/mips32-dsp/cmp_lt_ph.c          |   35 +
 tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c        |   31 +
 tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c        |   31 +
 tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c        |   31 +
 tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c         |   35 +
 tests/tcg/mips/mips32-dsp/cmpu_le_qb.c         |   35 +
 tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c         |   35 +
 tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c        |   31 +
 tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c        |   31 +
 tests/tcg/mips/mips32-dsp/dpau_h_qbl.c         |   27 +
 tests/tcg/mips/mips32-dsp/dpau_h_qbr.c         |   27 +
 tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c        |   27 +
 tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c        |   31 +
 tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c         |   27 +
 tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c         |   27 +
 tests/tcg/mips/mips32-dsp/extp.c               |   44 +
 tests/tcg/mips/mips32-dsp/extpdp.c             |   46 +
 tests/tcg/mips/mips32-dsp/extpdpv.c            |   47 +
 tests/tcg/mips/mips32-dsp/extpv.c              |   45 +
 tests/tcg/mips/mips32-dsp/extr_r_w.c           |   25 +
 tests/tcg/mips/mips32-dsp/extr_rs_w.c          |   25 +
 tests/tcg/mips/mips32-dsp/extr_s_h.c           |   25 +
 tests/tcg/mips/mips32-dsp/extr_w.c             |   25 +
 tests/tcg/mips/mips32-dsp/extrv_r_w.c          |   29 +
 tests/tcg/mips/mips32-dsp/extrv_rs_w.c         |   29 +
 tests/tcg/mips/mips32-dsp/extrv_s_h.c          |   29 +
 tests/tcg/mips/mips32-dsp/extrv_w.c            |   29 +
 tests/tcg/mips/mips32-dsp/insv.c               |   23 +
 tests/tcg/mips/mips32-dsp/lbux.c               |   25 +
 tests/tcg/mips/mips32-dsp/lhx.c                |   25 +
 tests/tcg/mips/mips32-dsp/lwx.c                |   25 +
 tests/tcg/mips/mips32-dsp/madd.c               |   31 +
 tests/tcg/mips/mips32-dsp/maddu.c              |   31 +
 tests/tcg/mips/mips32-dsp/main.c               |    6 +
 tests/tcg/mips/mips32-dsp/maq_s_w_phl.c        |   31 +
 tests/tcg/mips/mips32-dsp/maq_s_w_phr.c        |   31 +
 tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c       |   31 +
 tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c       |   31 +
 tests/tcg/mips/mips32-dsp/mfhi.c               |   21 +
 tests/tcg/mips/mips32-dsp/mflo.c               |   21 +
 tests/tcg/mips/mips32-dsp/modsub.c             |   30 +
 tests/tcg/mips/mips32-dsp/msub.c               |   30 +
 tests/tcg/mips/mips32-dsp/msubu.c              |   30 +
 tests/tcg/mips/mips32-dsp/mthi.c               |   21 +
 tests/tcg/mips/mips32-dsp/mthlip.c             |   34 +
 tests/tcg/mips/mips32-dsp/mtlo.c               |   21 +
 tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c      |   40 +
 tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c     |   25 +
 tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c     |   25 +
 tests/tcg/mips/mips32-dsp/mulq_rs_ph.c         |   25 +
 tests/tcg/mips/mips32-dsp/mult.c               |   24 +
 tests/tcg/mips/mips32-dsp/multu.c              |   24 +
 tests/tcg/mips/mips32-dsp/out                  |  110 +
 tests/tcg/mips/mips32-dsp/packrl_ph.c          |   21 +
 tests/tcg/mips/mips32-dsp/pick_ph.c            |   23 +
 tests/tcg/mips/mips32-dsp/pick_qb.c            |   23 +
 tests/tcg/mips/mips32-dsp/preceq_w_phl.c       |   20 +
 tests/tcg/mips/mips32-dsp/preceq_w_phr.c       |   20 +
 tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c     |   20 +
 tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c    |   20 +
 tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c     |   20 +
 tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c    |   20 +
 tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c      |   20 +
 tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c     |   20 +
 tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c      |   20 +
 tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c     |   20 +
 tests/tcg/mips/mips32-dsp/precrq_ph_w.c        |   21 +
 tests/tcg/mips/mips32-dsp/precrq_qb_ph.c       |   21 +
 tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c     |   21 +
 tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c    |   21 +
 tests/tcg/mips/mips32-dsp/raddu_w_qb.c         |   20 +
 tests/tcg/mips/mips32-dsp/rddsp.c              |   54 +
 tests/tcg/mips/mips32-dsp/repl_ph.c            |   23 +
 tests/tcg/mips/mips32-dsp/repl_qb.c            |   16 +
 tests/tcg/mips/mips32-dsp/replv_ph.c           |   19 +
 tests/tcg/mips/mips32-dsp/replv_qb.c           |   19 +
 tests/tcg/mips/mips32-dsp/shilo.c              |   27 +
 tests/tcg/mips/mips32-dsp/shilov.c             |   29 +
 tests/tcg/mips/mips32-dsp/shll_ph.c            |   24 +
 tests/tcg/mips/mips32-dsp/shll_qb.c            |   23 +
 tests/tcg/mips/mips32-dsp/shll_s_ph.c          |   24 +
 tests/tcg/mips/mips32-dsp/shll_s_w.c           |   24 +
 tests/tcg/mips/mips32-dsp/shllv_ph.c           |   25 +
 tests/tcg/mips/mips32-dsp/shllv_qb.c           |   24 +
 tests/tcg/mips/mips32-dsp/shllv_s_ph.c         |   25 +
 tests/tcg/mips/mips32-dsp/shllv_s_w.c          |   25 +
 tests/tcg/mips/mips32-dsp/shra_ph.c            |   20 +
 tests/tcg/mips/mips32-dsp/shra_r_ph.c          |   20 +
 tests/tcg/mips/mips32-dsp/shra_r_w.c           |   20 +
 tests/tcg/mips/mips32-dsp/shrav_ph.c           |   21 +
 tests/tcg/mips/mips32-dsp/shrav_r_ph.c         |   21 +
 tests/tcg/mips/mips32-dsp/shrav_r_w.c          |   21 +
 tests/tcg/mips/mips32-dsp/shrl_qb.c            |   20 +
 tests/tcg/mips/mips32-dsp/shrlv_qb.c           |   21 +
 tests/tcg/mips/mips32-dsp/subq_ph.c            |   25 +
 tests/tcg/mips/mips32-dsp/subq_s_ph.c          |   25 +
 tests/tcg/mips/mips32-dsp/subq_s_w.c           |   25 +
 tests/tcg/mips/mips32-dsp/subu_qb.c            |   25 +
 tests/tcg/mips/mips32-dsp/subu_s_qb.c          |   25 +
 tests/tcg/mips/mips32-dsp/wrdsp.c              |   54 +
 tests/tcg/mips/mips32-dspr2/Makefile           |   72 +
 tests/tcg/mips/mips32-dspr2/absq_s_qb.c        |   35 +
 tests/tcg/mips/mips32-dspr2/addqh_ph.c         |   30 +
 tests/tcg/mips/mips32-dspr2/addqh_r_ph.c       |   30 +
 tests/tcg/mips/mips32-dspr2/addqh_r_w.c        |   34 +
 tests/tcg/mips/mips32-dspr2/addqh_w.c          |   34 +
 tests/tcg/mips/mips32-dspr2/addu_ph.c          |   30 +
 tests/tcg/mips/mips32-dspr2/addu_s_ph.c        |   30 +
 tests/tcg/mips/mips32-dspr2/adduh_qb.c         |   30 +
 tests/tcg/mips/mips32-dspr2/adduh_r_qb.c       |   30 +
 tests/tcg/mips/mips32-dspr2/append.c           |   30 +
 tests/tcg/mips/mips32-dspr2/balign.c           |   30 +
 tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c     |   37 +
 tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c     |   37 +
 tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c     |   37 +
 tests/tcg/mips/mips32-dspr2/dpa_w_ph.c         |   27 +
 tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c     |   57 +
 tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c    |   31 +
 tests/tcg/mips/mips32-dspr2/dpax_w_ph.c        |   27 +
 tests/tcg/mips/mips32-dspr2/dps_w_ph.c         |   27 +
 tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c     |   31 +
 tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c    |   31 +
 tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c        |   27 +
 tests/tcg/mips/mips32-dspr2/mul_ph.c           |   25 +
 tests/tcg/mips/mips32-dspr2/mul_s_ph.c         |   25 +
 tests/tcg/mips/mips32-dspr2/muleq_s_w_phl.c    |   40 +
 tests/tcg/mips/mips32-dspr2/mulq_rs_w.c        |   36 +
 tests/tcg/mips/mips32-dspr2/mulq_s_ph.c        |   25 +
 tests/tcg/mips/mips32-dspr2/mulq_s_w.c         |   36 +
 tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c       |   29 +
 tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c    |   29 +
 tests/tcg/mips/mips32-dspr2/precr_qb_ph.c      |   21 +
 tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c   |   32 +
 tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c |   32 +
 tests/tcg/mips/mips32-dspr2/prepend.c          |   30 +
 tests/tcg/mips/mips32-dspr2/shra_qb.c          |   30 +
 tests/tcg/mips/mips32-dspr2/shra_r_qb.c        |   30 +
 tests/tcg/mips/mips32-dspr2/shrav_qb.c         |   32 +
 tests/tcg/mips/mips32-dspr2/shrav_r_qb.c       |   32 +
 tests/tcg/mips/mips32-dspr2/shrl_ph.c          |   20 +
 tests/tcg/mips/mips32-dspr2/shrlv_ph.c         |   21 +
 tests/tcg/mips/mips32-dspr2/subqh_ph.c         |   21 +
 tests/tcg/mips/mips32-dspr2/subqh_r_ph.c       |   21 +
 tests/tcg/mips/mips32-dspr2/subqh_r_w.c        |   21 +
 tests/tcg/mips/mips32-dspr2/subqh_w.c          |   21 +
 tests/tcg/mips/mips32-dspr2/subu_ph.c          |   25 +
 tests/tcg/mips/mips32-dspr2/subu_s_ph.c        |   25 +
 tests/tcg/mips/mips32-dspr2/subuh_qb.c         |   21 +
 tests/tcg/mips/mips32-dspr2/subuh_r_qb.c       |   21 +
 tests/tcg/mips/mips64-dsp/Makefile             |  304 +
 tests/tcg/mips/mips64-dsp/absq_s_ob.c          |   63 +
 tests/tcg/mips/mips64-dsp/absq_s_ph.c          |   37 +
 tests/tcg/mips/mips64-dsp/absq_s_pw.c          |   66 +
 tests/tcg/mips/mips64-dsp/absq_s_qh.c          |   40 +
 tests/tcg/mips/mips64-dsp/absq_s_w.c           |   48 +
 tests/tcg/mips/mips64-dsp/addq_ph.c            |   37 +
 tests/tcg/mips/mips64-dsp/addq_pw.c            |   26 +
 tests/tcg/mips/mips64-dsp/addq_qh.c            |   28 +
 tests/tcg/mips/mips64-dsp/addq_s_ph.c          |   37 +
 tests/tcg/mips/mips64-dsp/addq_s_pw.c          |   45 +
 tests/tcg/mips/mips64-dsp/addq_s_qh.c          |   26 +
 tests/tcg/mips/mips64-dsp/addsc.c              |   37 +
 tests/tcg/mips/mips64-dsp/addu_ob.c            |   27 +
 tests/tcg/mips/mips64-dsp/addu_qb.c            |   37 +
 tests/tcg/mips/mips64-dsp/addu_s_ob.c          |   27 +
 tests/tcg/mips/mips64-dsp/addu_s_qb.c          |   38 +
 tests/tcg/mips/mips64-dsp/addwc.c              |   37 +
 tests/tcg/mips/mips64-dsp/bitrev.c             |   23 +
 tests/tcg/mips/mips64-dsp/bposge32.c           |   50 +
 tests/tcg/mips/mips64-dsp/bposge64.c           |   50 +
 tests/tcg/mips/mips64-dsp/cmp_eq_ph.c          |   42 +
 tests/tcg/mips/mips64-dsp/cmp_eq_pw.c          |   27 +
 tests/tcg/mips/mips64-dsp/cmp_eq_qh.c          |   27 +
 tests/tcg/mips/mips64-dsp/cmp_le_ph.c          |   40 +
 tests/tcg/mips/mips64-dsp/cmp_le_pw.c          |   27 +
 tests/tcg/mips/mips64-dsp/cmp_le_qh.c          |   27 +
 tests/tcg/mips/mips64-dsp/cmp_lt_ph.c          |   41 +
 tests/tcg/mips/mips64-dsp/cmp_lt_pw.c          |   27 +
 tests/tcg/mips/mips64-dsp/cmp_lt_qh.c          |   27 +
 tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c        |   24 +
 tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c        |   38 +
 tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c        |   24 +
 tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c        |   37 +
 tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c        |   24 +
 tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c        |   38 +
 tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c         |   27 +
 tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c         |   42 +
 tests/tcg/mips/mips64-dsp/cmpu_le_ob.c         |   26 +
 tests/tcg/mips/mips64-dsp/cmpu_le_qb.c         |   41 +
 tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c         |   26 +
 tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c         |   42 +
 tests/tcg/mips/mips64-dsp/dappend.c            |   37 +
 tests/tcg/mips/mips64-dsp/dextp.c              |   33 +
 tests/tcg/mips/mips64-dsp/dextpdp.c            |   37 +
 tests/tcg/mips/mips64-dsp/dextpdpv.c           |   38 +
 tests/tcg/mips/mips64-dsp/dextpv.c             |   34 +
 tests/tcg/mips/mips64-dsp/dextr_l.c            |   27 +
 tests/tcg/mips/mips64-dsp/dextr_r_l.c          |   32 +
 tests/tcg/mips/mips64-dsp/dextr_r_w.c          |   32 +
 tests/tcg/mips/mips64-dsp/dextr_rs_l.c         |   31 +
 tests/tcg/mips/mips64-dsp/dextr_rs_w.c         |   31 +
 tests/tcg/mips/mips64-dsp/dextr_s_h.c          |   31 +
 tests/tcg/mips/mips64-dsp/dextr_w.c            |   27 +
 tests/tcg/mips/mips64-dsp/dextrv_l.c           |   28 +
 tests/tcg/mips/mips64-dsp/dextrv_r_l.c         |   33 +
 tests/tcg/mips/mips64-dsp/dextrv_r_w.c         |   33 +
 tests/tcg/mips/mips64-dsp/dextrv_rs_l.c        |   32 +
 tests/tcg/mips/mips64-dsp/dextrv_rs_w.c        |   32 +
 tests/tcg/mips/mips64-dsp/dextrv_s_h.c         |   32 +
 tests/tcg/mips/mips64-dsp/dextrv_w.c           |   28 +
 tests/tcg/mips/mips64-dsp/dinsv.c              |   25 +
 tests/tcg/mips/mips64-dsp/dmadd.c              |   57 +
 tests/tcg/mips/mips64-dsp/dmaddu.c             |   56 +
 tests/tcg/mips/mips64-dsp/dmsub.c              |   59 +
 tests/tcg/mips/mips64-dsp/dmsubu.c             |   59 +
 tests/tcg/mips/mips64-dsp/dmthlip.c            |   32 +
 tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c        |   32 +
 tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c        |   57 +
 tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c       |   62 +
 tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c        |   32 +
 tests/tcg/mips/mips64-dsp/dpau_h_obl.c         |   59 +
 tests/tcg/mips/mips64-dsp/dpau_h_obr.c         |   59 +
 tests/tcg/mips/mips64-dsp/dpau_h_qbl.c         |   29 +
 tests/tcg/mips/mips64-dsp/dpau_h_qbr.c         |   29 +
 tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c        |   29 +
 tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c        |   33 +
 tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c       |   39 +
 tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c        |   32 +
 tests/tcg/mips/mips64-dsp/dpsu_h_obl.c         |   32 +
 tests/tcg/mips/mips64-dsp/dpsu_h_obr.c         |   32 +
 tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c         |   29 +
 tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c         |   29 +
 tests/tcg/mips/mips64-dsp/dshilo.c             |   31 +
 tests/tcg/mips/mips64-dsp/dshilov.c            |   32 +
 tests/tcg/mips/mips64-dsp/extp.c               |   50 +
 tests/tcg/mips/mips64-dsp/extpdp.c             |   51 +
 tests/tcg/mips/mips64-dsp/extpdpv.c            |   52 +
 tests/tcg/mips/mips64-dsp/extpv.c              |   51 +
 tests/tcg/mips/mips64-dsp/extr_r_w.c           |   27 +
 tests/tcg/mips/mips64-dsp/extr_rs_w.c          |   27 +
 tests/tcg/mips/mips64-dsp/extr_s_h.c           |   27 +
 tests/tcg/mips/mips64-dsp/extr_w.c             |   27 +
 tests/tcg/mips/mips64-dsp/extrv_r_w.c          |   31 +
 tests/tcg/mips/mips64-dsp/extrv_rs_w.c         |   31 +
 tests/tcg/mips/mips64-dsp/extrv_s_h.c          |   31 +
 tests/tcg/mips/mips64-dsp/extrv_w.c            |   31 +
 tests/tcg/mips/mips64-dsp/head.S               |   10 +
 tests/tcg/mips/mips64-dsp/insv.c               |   26 +
 tests/tcg/mips/mips64-dsp/io.h                 |   22 +
 tests/tcg/mips/mips64-dsp/lbux.c               |   27 +
 tests/tcg/mips/mips64-dsp/ldx.c                |   27 +
 tests/tcg/mips/mips64-dsp/lhx.c                |   27 +
 tests/tcg/mips/mips64-dsp/lwx.c                |   27 +
 tests/tcg/mips/mips64-dsp/madd.c               |   33 +
 tests/tcg/mips/mips64-dsp/maddu.c              |   33 +
 tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c        |   56 +
 tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c        |   56 +
 tests/tcg/mips/mips64-dsp/maq_s_w_phl.c        |   33 +
 tests/tcg/mips/mips64-dsp/maq_s_w_phr.c        |   33 +
 tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c       |   62 +
 tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c       |   62 +
 tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c       |   63 +
 tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c       |   63 +
 tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c       |   33 +
 tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c       |   33 +
 tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c      |   64 +
 tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c      |   64 +
 tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c      |   64 +
 tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c      |   64 +
 tests/tcg/mips/mips64-dsp/mfhi.c               |   24 +
 tests/tcg/mips/mips64-dsp/mflo.c               |   24 +
 tests/tcg/mips/mips64-dsp/mips_boot.lds        |   31 +
 tests/tcg/mips/mips64-dsp/modsub.c             |   37 +
 tests/tcg/mips/mips64-dsp/msub.c               |   32 +
 tests/tcg/mips/mips64-dsp/msubu.c              |   32 +
 tests/tcg/mips/mips64-dsp/mthi.c               |   24 +
 tests/tcg/mips/mips64-dsp/mthlip.c             |   35 +
 tests/tcg/mips/mips64-dsp/mtlo.c               |   22 +
 tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c     |   55 +
 tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c     |   24 +
 tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c      |   45 +
 tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c     |   27 +
 tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c     |   27 +
 tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c     |   25 +
 tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c     |   25 +
 tests/tcg/mips/mips64-dsp/mulq_rs_ph.c         |   27 +
 tests/tcg/mips/mips64-dsp/mulq_rs_qh.c         |   33 +
 tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c      |   59 +
 tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c      |   57 +
 tests/tcg/mips/mips64-dsp/mult.c               |   26 +
 tests/tcg/mips/mips64-dsp/multu.c              |   26 +
 tests/tcg/mips/mips64-dsp/out                  |  231 +
 tests/tcg/mips/mips64-dsp/packrl_ph.c          |   24 +
 tests/tcg/mips/mips64-dsp/packrl_pw.c          |   24 +
 tests/tcg/mips/mips64-dsp/pick_ob.c            |   27 +
 tests/tcg/mips/mips64-dsp/pick_ph.c            |   26 +
 tests/tcg/mips/mips64-dsp/pick_pw.c            |   28 +
 tests/tcg/mips/mips64-dsp/pick_qb.c            |   26 +
 tests/tcg/mips/mips64-dsp/pick_qh.c            |   28 +
 tests/tcg/mips/mips64-dsp/preceq_l_pwl.c       |   24 +
 tests/tcg/mips/mips64-dsp/preceq_l_pwr.c       |   24 +
 tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c      |   21 +
 tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c     |   23 +
 tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c      |   21 +
 tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c     |   23 +
 tests/tcg/mips/mips64-dsp/preceq_w_phl.c       |   23 +
 tests/tcg/mips/mips64-dsp/preceq_w_phr.c       |   23 +
 tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c     |   23 +
 tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c    |   23 +
 tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c     |   23 +
 tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c    |   23 +
 tests/tcg/mips/mips64-dsp/precequ_qh_obl.c     |   22 +
 tests/tcg/mips/mips64-dsp/precequ_qh_obla.c    |   22 +
 tests/tcg/mips/mips64-dsp/precequ_qh_obr.c     |   24 +
 tests/tcg/mips/mips64-dsp/precequ_qh_obra.c    |   24 +
 tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c      |   23 +
 tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c     |   23 +
 tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c      |   23 +
 tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c     |   23 +
 tests/tcg/mips/mips64-dsp/preceu_qh_obl.c      |   22 +
 tests/tcg/mips/mips64-dsp/preceu_qh_obla.c     |   22 +
 tests/tcg/mips/mips64-dsp/preceu_qh_obr.c      |   23 +
 tests/tcg/mips/mips64-dsp/preceu_qh_obra.c     |   23 +
 tests/tcg/mips/mips64-dsp/precr_ob_qh.c        |   25 +
 tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c    |   40 +
 tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c  |   40 +
 tests/tcg/mips/mips64-dsp/precrq_ob_qh.c       |   25 +
 tests/tcg/mips/mips64-dsp/precrq_ph_w.c        |   24 +
 tests/tcg/mips/mips64-dsp/precrq_pw_l.c        |   25 +
 tests/tcg/mips/mips64-dsp/precrq_qb_ph.c       |   24 +
 tests/tcg/mips/mips64-dsp/precrq_qh_pw.c       |   25 +
 tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c     |   24 +
 tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c    |   25 +
 tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c    |   27 +
 tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c    |   24 +
 tests/tcg/mips/mips64-dsp/prependd.c           |   37 +
 tests/tcg/mips/mips64-dsp/prependw.c           |   37 +
 tests/tcg/mips/mips64-dsp/printf.c             |  266 +
 tests/tcg/mips/mips64-dsp/raddu_l_ob.c         |   22 +
 tests/tcg/mips/mips64-dsp/raddu_w_qb.c         |   23 +
 tests/tcg/mips/mips64-dsp/rddsp.c              |   53 +
 tests/tcg/mips/mips64-dsp/repl_ob.c            |   21 +
 tests/tcg/mips/mips64-dsp/repl_ph.c            |   30 +
 tests/tcg/mips/mips64-dsp/repl_pw.c            |   34 +
 tests/tcg/mips/mips64-dsp/repl_qb.c            |   19 +
 tests/tcg/mips/mips64-dsp/repl_qh.c            |   34 +
 tests/tcg/mips/mips64-dsp/replv_ob.c           |   23 +
 tests/tcg/mips/mips64-dsp/replv_ph.c           |   22 +
 tests/tcg/mips/mips64-dsp/replv_pw.c           |   23 +
 tests/tcg/mips/mips64-dsp/replv_qb.c           |   22 +
 tests/tcg/mips/mips64-dsp/shilo.c              |   29 +
 tests/tcg/mips/mips64-dsp/shilov.c             |   31 +
 tests/tcg/mips/mips64-dsp/shll_ob.c            |   26 +
 tests/tcg/mips/mips64-dsp/shll_ph.c            |   26 +
 tests/tcg/mips/mips64-dsp/shll_pw.c            |   26 +
 tests/tcg/mips/mips64-dsp/shll_qb.c            |   26 +
 tests/tcg/mips/mips64-dsp/shll_qh.c            |   26 +
 tests/tcg/mips/mips64-dsp/shll_s_ph.c          |   26 +
 tests/tcg/mips/mips64-dsp/shll_s_pw.c          |   26 +
 tests/tcg/mips/mips64-dsp/shll_s_qh.c          |   26 +
 tests/tcg/mips/mips64-dsp/shll_s_w.c           |   26 +
 tests/tcg/mips/mips64-dsp/shllv_ob.c           |   27 +
 tests/tcg/mips/mips64-dsp/shllv_ph.c           |   27 +
 tests/tcg/mips/mips64-dsp/shllv_pw.c           |   27 +
 tests/tcg/mips/mips64-dsp/shllv_qb.c           |   27 +
 tests/tcg/mips/mips64-dsp/shllv_qh.c           |   27 +
 tests/tcg/mips/mips64-dsp/shllv_s_ph.c         |   27 +
 tests/tcg/mips/mips64-dsp/shllv_s_pw.c         |   27 +
 tests/tcg/mips/mips64-dsp/shllv_s_qh.c         |   27 +
 tests/tcg/mips/mips64-dsp/shllv_s_w.c          |   27 +
 tests/tcg/mips/mips64-dsp/shra_ob.c            |   22 +
 tests/tcg/mips/mips64-dsp/shra_ph.c            |   23 +
 tests/tcg/mips/mips64-dsp/shra_pw.c            |   22 +
 tests/tcg/mips/mips64-dsp/shra_qh.c            |   24 +
 tests/tcg/mips/mips64-dsp/shra_r_ob.c          |   22 +
 tests/tcg/mips/mips64-dsp/shra_r_ph.c          |   23 +
 tests/tcg/mips/mips64-dsp/shra_r_pw.c          |   22 +
 tests/tcg/mips/mips64-dsp/shra_r_qh.c          |   23 +
 tests/tcg/mips/mips64-dsp/shra_r_w.c           |   23 +
 tests/tcg/mips/mips64-dsp/shrav_ph.c           |   24 +
 tests/tcg/mips/mips64-dsp/shrav_pw.c           |   23 +
 tests/tcg/mips/mips64-dsp/shrav_qh.c           |   24 +
 tests/tcg/mips/mips64-dsp/shrav_r_ph.c         |   24 +
 tests/tcg/mips/mips64-dsp/shrav_r_pw.c         |   23 +
 tests/tcg/mips/mips64-dsp/shrav_r_qh.c         |   24 +
 tests/tcg/mips/mips64-dsp/shrav_r_w.c          |   24 +
 tests/tcg/mips/mips64-dsp/shrl_ob.c            |   23 +
 tests/tcg/mips/mips64-dsp/shrl_qb.c            |   23 +
 tests/tcg/mips/mips64-dsp/shrl_qh.c            |   22 +
 tests/tcg/mips/mips64-dsp/shrlv_ob.c           |   24 +
 tests/tcg/mips/mips64-dsp/shrlv_qb.c           |   24 +
 tests/tcg/mips/mips64-dsp/shrlv_qh.c           |   23 +
 tests/tcg/mips/mips64-dsp/subq_ph.c            |   27 +
 tests/tcg/mips/mips64-dsp/subq_pw.c            |   44 +
 tests/tcg/mips/mips64-dsp/subq_qh.c            |   26 +
 tests/tcg/mips/mips64-dsp/subq_s_ph.c          |   27 +
 tests/tcg/mips/mips64-dsp/subq_s_pw.c          |   45 +
 tests/tcg/mips/mips64-dsp/subq_s_qh.c          |   44 +
 tests/tcg/mips/mips64-dsp/subq_s_w.c           |   27 +
 tests/tcg/mips/mips64-dsp/subu_ob.c            |   26 +
 tests/tcg/mips/mips64-dsp/subu_qb.c            |   27 +
 tests/tcg/mips/mips64-dsp/subu_s_ob.c          |   26 +
 tests/tcg/mips/mips64-dsp/subu_s_qb.c          |   27 +
 tests/tcg/mips/mips64-dsp/wrdsp.c              |   48 +
 tests/tcg/mips/mips64-dspr2/.directory         |    2 +
 tests/tcg/mips/mips64-dspr2/Makefile           |  117 +
 tests/tcg/mips/mips64-dspr2/absq_s_qb.c        |   42 +
 tests/tcg/mips/mips64-dspr2/addqh_ph.c         |   35 +
 tests/tcg/mips/mips64-dspr2/addqh_r_ph.c       |   35 +
 tests/tcg/mips/mips64-dspr2/addqh_r_w.c        |   38 +
 tests/tcg/mips/mips64-dspr2/addqh_w.c          |   39 +
 tests/tcg/mips/mips64-dspr2/addu_ph.c          |   35 +
 tests/tcg/mips/mips64-dspr2/addu_qh.c          |   41 +
 tests/tcg/mips/mips64-dspr2/addu_s_ph.c        |   35 +
 tests/tcg/mips/mips64-dspr2/addu_s_qh.c        |   41 +
 tests/tcg/mips/mips64-dspr2/adduh_ob.c         |   21 +
 tests/tcg/mips/mips64-dspr2/adduh_qb.c         |   35 +
 tests/tcg/mips/mips64-dspr2/adduh_r_ob.c       |   21 +
 tests/tcg/mips/mips64-dspr2/adduh_r_qb.c       |   35 +
 tests/tcg/mips/mips64-dspr2/append.c           |   35 +
 tests/tcg/mips/mips64-dspr2/balign.c           |   35 +
 tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c     |   26 +
 tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c     |   41 +
 tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c     |   26 +
 tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c     |   48 +
 tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c     |   26 +
 tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c     |   48 +
 tests/tcg/mips/mips64-dspr2/dbalign.c          |   23 +
 tests/tcg/mips/mips64-dspr2/dpa_w_ph.c         |   32 +
 tests/tcg/mips/mips64-dspr2/dpa_w_qh.c         |   56 +
 tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c     |   74 +
 tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c    |   42 +
 tests/tcg/mips/mips64-dspr2/dpax_w_ph.c        |   32 +
 tests/tcg/mips/mips64-dspr2/dps_w_ph.c         |   28 +
 tests/tcg/mips/mips64-dspr2/dps_w_qh.c         |   55 +
 tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c     |   31 +
 tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c    |   30 +
 tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c        |   28 +
 tests/tcg/mips/mips64-dspr2/head.S             |   10 +
 tests/tcg/mips/mips64-dspr2/io.h               |   22 +
 tests/tcg/mips/mips64-dspr2/mips_boot.lds      |   31 +
 tests/tcg/mips/mips64-dspr2/mul_ph.c           |   26 +
 tests/tcg/mips/mips64-dspr2/mul_s_ph.c         |   26 +
 tests/tcg/mips/mips64-dspr2/muleq_s_w_phl.c    |   42 +
 tests/tcg/mips/mips64-dspr2/mulq_rs_w.c        |   40 +
 tests/tcg/mips/mips64-dspr2/mulq_s_ph.c        |   26 +
 tests/tcg/mips/mips64-dspr2/mulq_s_w.c         |   40 +
 tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c       |   30 +
 tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c    |   30 +
 tests/tcg/mips/mips64-dspr2/precr_qb_ph.c      |   23 +
 tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c   |   37 +
 tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c |   37 +
 tests/tcg/mips/mips64-dspr2/prepend.c          |   35 +
 tests/tcg/mips/mips64-dspr2/printf.c           |  266 +
 tests/tcg/mips/mips64-dspr2/shra_qb.c          |   35 +
 tests/tcg/mips/mips64-dspr2/shra_r_qb.c        |   35 +
 tests/tcg/mips/mips64-dspr2/shrav_ob.c         |   22 +
 tests/tcg/mips/mips64-dspr2/shrav_qb.c         |   37 +
 tests/tcg/mips/mips64-dspr2/shrav_r_ob.c       |   22 +
 tests/tcg/mips/mips64-dspr2/shrav_r_qb.c       |   37 +
 tests/tcg/mips/mips64-dspr2/shrl_ph.c          |   22 +
 tests/tcg/mips/mips64-dspr2/shrlv_ph.c         |   23 +
 tests/tcg/mips/mips64-dspr2/subqh_ph.c         |   23 +
 tests/tcg/mips/mips64-dspr2/subqh_r_ph.c       |   23 +
 tests/tcg/mips/mips64-dspr2/subqh_r_w.c        |   23 +
 tests/tcg/mips/mips64-dspr2/subqh_w.c          |   23 +
 tests/tcg/mips/mips64-dspr2/subu_ph.c          |   26 +
 tests/tcg/mips/mips64-dspr2/subu_qh.c          |   24 +
 tests/tcg/mips/mips64-dspr2/subu_s_ph.c        |   25 +
 tests/tcg/mips/mips64-dspr2/subu_s_qh.c        |   24 +
 tests/tcg/mips/mips64-dspr2/subuh_ob.c         |   23 +
 tests/tcg/mips/mips64-dspr2/subuh_qb.c         |   23 +
 tests/tcg/mips/mips64-dspr2/subuh_r_ob.c       |   23 +
 tests/tcg/mips/mips64-dspr2/subuh_r_qb.c       |   23 +
 493 files changed, 27666 insertions(+), 68 deletions(-)
 create mode 100644 target-mips/dsp_helper.c
 create mode 100644 tests/tcg/mips/mips32-dsp/Makefile
 create mode 100644 tests/tcg/mips/mips32-dsp/absq_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/absq_s_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/addq_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/addq_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/addsc.c
 create mode 100644 tests/tcg/mips/mips32-dsp/addu_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/addu_s_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/addwc.c
 create mode 100644 tests/tcg/mips/mips32-dsp/bitrev.c
 create mode 100644 tests/tcg/mips/mips32-dsp/bposge32.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmp_eq_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmp_le_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmp_lt_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmpu_le_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpau_h_qbl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpau_h_qbr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extp.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extpdp.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extpdpv.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extpv.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extr_r_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extr_rs_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extr_s_h.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extr_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extrv_r_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extrv_rs_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extrv_s_h.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extrv_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/insv.c
 create mode 100644 tests/tcg/mips/mips32-dsp/lbux.c
 create mode 100644 tests/tcg/mips/mips32-dsp/lhx.c
 create mode 100644 tests/tcg/mips/mips32-dsp/lwx.c
 create mode 100644 tests/tcg/mips/mips32-dsp/madd.c
 create mode 100644 tests/tcg/mips/mips32-dsp/maddu.c
 create mode 100644 tests/tcg/mips/mips32-dsp/main.c
 create mode 100644 tests/tcg/mips/mips32-dsp/maq_s_w_phl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/maq_s_w_phr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mfhi.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mflo.c
 create mode 100644 tests/tcg/mips/mips32-dsp/modsub.c
 create mode 100644 tests/tcg/mips/mips32-dsp/msub.c
 create mode 100644 tests/tcg/mips/mips32-dsp/msubu.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mthi.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mthlip.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mtlo.c
 create mode 100644 tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mulq_rs_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mult.c
 create mode 100644 tests/tcg/mips/mips32-dsp/multu.c
 create mode 100644 tests/tcg/mips/mips32-dsp/out
 create mode 100644 tests/tcg/mips/mips32-dsp/packrl_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/pick_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/pick_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/preceq_w_phl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/preceq_w_phr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c
 create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c
 create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precrq_ph_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precrq_qb_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/raddu_w_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/rddsp.c
 create mode 100644 tests/tcg/mips/mips32-dsp/repl_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/repl_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/replv_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/replv_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shilo.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shilov.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shll_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shll_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shll_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shll_s_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shllv_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shllv_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shllv_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shllv_s_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shra_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shra_r_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shra_r_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shrav_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shrav_r_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shrav_r_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shrl_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shrlv_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/subq_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/subq_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/subq_s_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/subu_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/subu_s_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/wrdsp.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/Makefile
 create mode 100644 tests/tcg/mips/mips32-dspr2/absq_s_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_r_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_r_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/addu_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/addu_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/adduh_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/adduh_r_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/append.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/balign.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpa_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpax_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dps_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mul_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mul_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/muleq_s_w_phl.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mulq_rs_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mulq_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mulq_s_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/precr_qb_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/prepend.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/shra_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/shra_r_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/shrav_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/shrav_r_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/shrl_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/shrlv_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_r_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_r_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subu_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subu_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subuh_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subuh_r_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/Makefile
 create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addq_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addq_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addq_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addq_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addq_s_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addq_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addsc.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addu_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addu_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addu_s_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addu_s_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addwc.c
 create mode 100644 tests/tcg/mips/mips64-dsp/bitrev.c
 create mode 100644 tests/tcg/mips/mips64-dsp/bposge32.c
 create mode 100644 tests/tcg/mips/mips64-dsp/bposge64.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_eq_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_eq_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_eq_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_le_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_le_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_le_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_lt_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_lt_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_lt_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_le_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_le_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dappend.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextp.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextpdp.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextpdpv.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextpv.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_r_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_rs_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_rs_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_s_h.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_r_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_rs_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_rs_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_s_h.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dinsv.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dmadd.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dmaddu.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dmsub.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dmsubu.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dmthlip.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpau_h_obl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpau_h_obr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpau_h_qbl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpau_h_qbr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsu_h_obl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsu_h_obr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dshilo.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dshilov.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extp.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extpdp.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extpdpv.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extpv.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extr_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extr_rs_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extr_s_h.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extr_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extrv_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extrv_rs_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extrv_s_h.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extrv_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/head.S
 create mode 100644 tests/tcg/mips/mips64-dsp/insv.c
 create mode 100644 tests/tcg/mips/mips64-dsp/io.h
 create mode 100644 tests/tcg/mips/mips64-dsp/lbux.c
 create mode 100644 tests/tcg/mips/mips64-dsp/ldx.c
 create mode 100644 tests/tcg/mips/mips64-dsp/lhx.c
 create mode 100644 tests/tcg/mips/mips64-dsp/lwx.c
 create mode 100644 tests/tcg/mips/mips64-dsp/madd.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maddu.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_phl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_phr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mfhi.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mflo.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mips_boot.lds
 create mode 100644 tests/tcg/mips/mips64-dsp/modsub.c
 create mode 100644 tests/tcg/mips/mips64-dsp/msub.c
 create mode 100644 tests/tcg/mips/mips64-dsp/msubu.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mthi.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mthlip.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mtlo.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mulq_rs_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mulq_rs_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mult.c
 create mode 100644 tests/tcg/mips/mips64-dsp/multu.c
 create mode 100644 tests/tcg/mips/mips64-dsp/out
 create mode 100644 tests/tcg/mips/mips64-dsp/packrl_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/packrl_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/pick_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/pick_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/pick_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/pick_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/pick_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_l_pwl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_l_pwr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_w_phl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_w_phr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_qh_obl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_qh_obla.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_qh_obr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_qh_obra.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_qh_obl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_qh_obla.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_qh_obr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_qh_obra.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precr_ob_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_ob_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_ph_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_pw_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_qb_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_qh_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/prependd.c
 create mode 100644 tests/tcg/mips/mips64-dsp/prependw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/printf.c
 create mode 100644 tests/tcg/mips/mips64-dsp/raddu_l_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/raddu_w_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/rddsp.c
 create mode 100644 tests/tcg/mips/mips64-dsp/repl_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/repl_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/repl_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/repl_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/repl_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/replv_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/replv_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/replv_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/replv_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shilo.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shilov.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_s_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_s_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_s_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_s_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_r_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_r_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_r_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrl_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrl_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrl_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrlv_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrlv_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrlv_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_s_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_s_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subu_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subu_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subu_s_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subu_s_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/wrdsp.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/.directory
 create mode 100644 tests/tcg/mips/mips64-dspr2/Makefile
 create mode 100644 tests/tcg/mips/mips64-dspr2/absq_s_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addqh_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addqh_r_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addqh_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addqh_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addu_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addu_qh.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addu_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addu_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/adduh_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/adduh_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/adduh_r_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/adduh_r_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/append.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/balign.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dbalign.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpa_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpa_w_qh.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpax_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dps_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dps_w_qh.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/head.S
 create mode 100644 tests/tcg/mips/mips64-dspr2/io.h
 create mode 100644 tests/tcg/mips/mips64-dspr2/mips_boot.lds
 create mode 100644 tests/tcg/mips/mips64-dspr2/mul_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/mul_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/muleq_s_w_phl.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/mulq_rs_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/mulq_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/mulq_s_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/precr_qb_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/prepend.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/printf.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shra_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shra_r_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shrav_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shrav_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shrav_r_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shrav_r_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shrl_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shrlv_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subqh_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subqh_r_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subqh_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subqh_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subu_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subu_qh.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subu_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subu_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subuh_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subuh_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subuh_r_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subuh_r_qb.c

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v6 01/13] target-mips-ase-dsp: Add internal functions
  2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
@ 2012-08-21  6:53 ` Jia Liu
  2012-08-23 13:31   ` Aurelien Jarno
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 02/13] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Jia Liu
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 20+ messages in thread
From: Jia Liu @ 2012-08-21  6:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Add internal functions using by MIPS ASE DSP instructions.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/Makefile.objs |    2 +-
 target-mips/dsp_helper.c  | 1277 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1278 insertions(+), 1 deletion(-)
 create mode 100644 target-mips/dsp_helper.c

diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs
index 2e0e093..55b252d 100644
--- a/target-mips/Makefile.objs
+++ b/target-mips/Makefile.objs
@@ -1,4 +1,4 @@
-obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += translate.o dsp_helper.o op_helper.o helper.o cpu.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
new file mode 100644
index 0000000..a7d6c7e
--- /dev/null
+++ b/target-mips/dsp_helper.c
@@ -0,0 +1,1277 @@
+/*
+ * MIPS ASE DSP Instruction emulation helpers for QEMU.
+ *
+ * Copyright (c) 2012  Jia Liu <proljc@gmail.com>
+ *                     Dongxue Zhang <elat.era@gmail.com>
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+
+/*** MIPS DSP internal functions begin ***/
+static inline int not_word_value(target_long value)
+{
+    target_ulong temp;
+
+    temp = (target_long)(int32_t)(value & 0xFFFFFFFF);
+    if (value == temp) {
+        return 0;
+    } else {
+        return 1;
+    }
+}
+
+static inline void set_DSPControl_overflow_flag(CPUMIPSState *env,
+                                                uint32_t flag, int position)
+{
+    env->active_tc.DSPControl |= (target_ulong)flag << position;
+}
+
+static inline void set_DSPControl_carryflag(CPUMIPSState *env, uint32_t flag)
+{
+    env->active_tc.DSPControl |= (target_ulong)flag << 13;
+}
+
+static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
+{
+    uint32_t flag;
+
+    flag = (env->active_tc.DSPControl >> 13) & 0x01;
+
+    return flag;
+}
+
+static inline void set_DSPControl_24(CPUMIPSState *env, uint32_t flag, int len)
+{
+  uint32_t filter;
+
+  filter = ((0x01 << len) - 1) << 24;
+  filter = ~filter;
+
+  env->active_tc.DSPControl &= filter;
+  env->active_tc.DSPControl |= (target_ulong)flag << 24;
+}
+
+static inline uint32_t get_DSPControl_24(CPUMIPSState *env, int len)
+{
+  uint32_t cond;
+  uint32_t filter;
+
+  filter = (0x01 << len) - 1;
+
+  cond = (env->active_tc.DSPControl >> 24) & filter;
+
+  return cond;
+}
+
+static inline void set_DSPControl_pos(CPUMIPSState *env, uint32_t pos)
+{
+    target_ulong dspc;
+
+    dspc = env->active_tc.DSPControl;
+#ifndef TARGET_MIPS64
+    dspc = dspc & 0xFFFFFFC0;
+    dspc |= pos;
+#else
+    dspc = dspc & 0xFFFFFF80;
+    dspc |= pos;
+#endif
+    env->active_tc.DSPControl = dspc;
+}
+
+static inline uint32_t get_DSPControl_pos(CPUMIPSState *env)
+{
+    target_ulong dspc;
+    uint32_t pos;
+
+    dspc = env->active_tc.DSPControl;
+
+#ifndef TARGET_MIPS64
+    pos = dspc & 0x3F;
+#else
+    pos = dspc & 0x7F;
+#endif
+
+    return pos;
+}
+
+static inline void set_DSPControl_efi(CPUMIPSState *env, uint32_t flag)
+{
+    env->active_tc.DSPControl &= 0xFFFFBFFF;
+    env->active_tc.DSPControl |= (target_ulong)flag << 14;
+}
+
+/* get abs value */
+static inline int8_t mipsdsp_sat_abs_u8(CPUMIPSState *env, uint8_t a)
+{
+    int8_t temp;
+    temp = a;
+
+    if (a == 0x80) {
+        set_DSPControl_overflow_flag(env, 1, 20);
+        temp = 0x7f;
+    } else {
+        if ((a & 0x80) == 0x80) {
+            temp = -temp;
+        }
+    }
+
+    return temp;
+}
+
+static inline int16_t mipsdsp_sat_abs_u16(CPUMIPSState *env, uint16_t a)
+{
+    int16_t temp;
+    temp = a;
+
+    if (a == 0x8000) {
+        set_DSPControl_overflow_flag(env, 1, 20);
+        temp = 0x7fff;
+    } else {
+        if ((a & 0x8000) == 0x8000) {
+            temp = -temp;
+        }
+    }
+
+    return temp;
+}
+
+static inline int32_t mipsdsp_sat_abs_u32(CPUMIPSState *env, uint32_t a)
+{
+    int32_t temp;
+    temp = a;
+
+    if (a == 0x80000000) {
+        set_DSPControl_overflow_flag(env, 1, 20);
+        temp = 0x7FFFFFFF;
+    } else {
+        if ((a & 0x80000000) == 0x80000000) {
+            temp = -temp;
+        }
+    }
+
+    return temp;
+}
+
+/* get sum value */
+static inline int16_t mipsdsp_add_i16(CPUMIPSState *env, int16_t a, int16_t b)
+{
+    int16_t tempS;
+    int32_t tempI, temp15, temp16;
+
+    tempS = a + b;
+    tempI = a + b;
+    temp15 = (tempI & 0x8000) >> 15;
+    temp16 = (tempI & 0x10000) >> 16;
+
+    if (temp15 != temp16) {
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+
+    return tempS;
+}
+
+static inline int16_t mipsdsp_sat_add_i16(CPUMIPSState *env,
+                                          int16_t a, int16_t b)
+{
+    int16_t tempS;
+    int32_t tempI, temp15, temp16;
+
+    tempS = a + b;
+    tempI = (int32_t)a + (int32_t)b;
+    temp15 = (tempI & 0x8000) >> 15;
+    temp16 = (tempI & 0x10000) >> 16;
+
+    if (temp15 != temp16) {
+        if (temp16 == 0) {
+            tempS = 0x7FFF;
+        } else {
+            tempS = 0x8000;
+        }
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+
+    return tempS;
+}
+
+static inline int32_t mipsdsp_sat_add_i32(CPUMIPSState *env,
+                                          int32_t a, int32_t b)
+{
+    int32_t tempI;
+    int64_t tempL, temp31, temp32;
+
+    tempI = a + b;
+    tempL = (int64_t)a + (int64_t)b;
+    temp31 = (tempL & 0x80000000) >> 31;
+    temp32 = (tempL & 0x100000000ull) >> 32;
+
+    if (temp31 != temp32) {
+        if (temp32 == 0) {
+            tempI = 0x7FFFFFFF;
+        } else {
+            tempI = 0x80000000;
+        }
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+
+    return tempI;
+}
+
+static inline uint8_t mipsdsp_add_u8(CPUMIPSState *env, uint8_t a, uint8_t b)
+{
+    uint8_t  result;
+    uint16_t tempA, tempB, temp;
+
+    tempA = a;
+    tempB = b;
+    temp = tempA + tempB;
+    result = temp & 0xFF;
+
+    if ((temp & 0x0100) == 0x0100) {
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+
+    return result;
+}
+
+static inline uint16_t mipsdsp_add_u16(CPUMIPSState *env,
+                                       uint16_t a, uint16_t b)
+{
+    uint16_t result;
+    uint32_t tempA, tempB, temp;
+
+    tempA = a;
+    tempB = b;
+    temp = tempA + tempB;
+    result = temp & 0xFFFF;
+
+    if ((temp & 0x00010000) == 0x00010000) {
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+
+    return result;
+}
+
+static inline uint8_t mipsdsp_sat_add_u8(CPUMIPSState *env,
+                                         uint8_t a, uint8_t b)
+{
+    uint8_t  result;
+    uint16_t tempA, tempB, temp;
+
+    tempA = a;
+    tempB = b;
+    temp = tempA + tempB;
+    result = temp & 0xFF;
+
+    if ((0x0100 & temp) == 0x0100) {
+        result = 0xFF;
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+
+    return result;
+}
+
+static inline uint16_t mipsdsp_sat_add_u16(CPUMIPSState *env,
+                                           uint16_t a, uint16_t b)
+{
+    uint16_t result;
+    uint32_t tempA, tempB, temp;
+
+    tempA = a;
+    tempB = b;
+    temp = tempA + tempB;
+    result = temp & 0xFFFF;
+
+    if ((0x00010000 & temp) == 0x00010000) {
+        result = 0xFFFF;
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+
+    return result;
+}
+
+static inline int32_t mipsdsp_sat32_acc_q31(CPUMIPSState *env,
+                                            int32_t acc, int32_t a)
+{
+    int64_t tempA, temp;
+    int32_t temp32, temp31, result;
+    int64_t temp_sum;
+
+#ifndef TARGET_MIPS64
+    temp = ((uint64_t)env->active_tc.HI[acc] << 32) |
+           (uint64_t)env->active_tc.LO[acc];
+#else
+    temp = (uint64_t)env->active_tc.LO[acc];
+#endif
+    tempA = (int64_t)a;
+
+    temp_sum = tempA + temp;
+
+    temp32 = (temp_sum >> 32) & 0x01;
+    temp31 = (temp_sum >> 31) & 0x01;
+    result = temp_sum & 0xFFFFFFFF;
+
+    if (temp32 != temp31) {
+        if (temp32 == 0) {
+            result = 0x80000000;
+        } else {
+            result = 0x7FFFFFFF;
+        }
+        set_DSPControl_overflow_flag(env, 1, 16 + acc);
+    }
+
+    return result;
+}
+
+/* a[0] is LO, a[1] is HI. */
+static inline void mipsdsp_sat64_acc_add_q63(CPUMIPSState *env,
+                                             int64_t *ret,
+                                             int32_t ac,
+                                             int64_t *a)
+{
+    uint32_t temp64, temp63;
+    int64_t temp[3];
+    int64_t acc[3];
+    int64_t temp_sum;
+
+    temp[0] = a[0];
+    temp[1] = a[1];
+    if (((temp[1] >> 63) & 0x01) == 0) {
+        temp[2] = 0x00;
+    } else {
+        temp[2] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+    if (((acc[1] >> 63) & 0x01) == 0) {
+        acc[2] = 0x00;
+    } else {
+        acc[2] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    temp_sum = temp[0] + acc[0];
+    if (((uint64_t)temp_sum < (uint64_t)temp[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)acc[0])) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+    temp[0] = temp_sum;
+
+    temp_sum = temp[1] + acc[1];
+    if (((uint64_t)temp_sum < (uint64_t)temp[1]) &&
+       ((uint64_t)temp_sum < (uint64_t)acc[1])) {
+        temp[2] += 1;
+    }
+
+    temp[1] = temp_sum;
+    temp[2] += acc[2];
+    temp64 = temp[1] & 0x01;
+    temp63 = (temp[0] >> 63) & 0x01;
+
+    if (temp64 != temp63) {
+        if (temp64 == 1) {
+            ret[0] = 0x8000000000000000ull;
+            ret[1] = 0xFFFFFFFFFFFFFFFFull;
+        } else {
+            ret[0] = 0x0;
+            ret[1] = 0x7FFFFFFFFFFFFFFFull;
+        }
+        set_DSPControl_overflow_flag(env, 1, 16 + ac);
+    } else {
+        ret[0] = temp[0];
+        ret[1] = temp[1];
+    }
+}
+
+/* a[0] is LO, a[1] is HI. */
+static inline void mipsdsp_sat64_acc_sub_q63(CPUMIPSState *env,
+                                             int64_t *ret,
+                                             int32_t ac,
+                                             int64_t *a)
+{
+    uint32_t temp64, temp63;
+    int64_t temp[3];
+    int64_t acc[3];
+    int64_t temp_sum;
+
+    temp[0] = a[0];
+    temp[1] = a[1];
+    if (((temp[1] >> 63) & 0x01) == 0) {
+        temp[2] = 0x00;
+    } else {
+        temp[2] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+    if (((acc[1] >> 63) & 0x01) == 0) {
+        acc[2] = 0x00;
+    } else {
+        acc[2] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    temp_sum = acc[0] - temp[0];
+    if ((uint64_t)temp_sum > (uint64_t)acc[0]) {
+        acc[1] -= 1;
+        if (acc[1] == 0xFFFFFFFFFFFFFFFFull) {
+            acc[2] -= 1;
+        }
+    }
+    acc[0] = temp_sum;
+
+    temp_sum = acc[1] - temp[1];
+    if ((uint64_t)temp_sum > (uint64_t)acc[1]) {
+        acc[2] -= 1;
+    }
+    acc[1] = temp_sum;
+    acc[2] -= temp[2];
+
+    temp64 = acc[1] & 0x01;
+    temp63 = (acc[0] >> 63) & 0x01;
+
+    if (temp64 != temp63) {
+        if (temp64 == 1) {
+            ret[0] = 0x8000000000000000ull;
+            ret[1] = 0xFFFFFFFFFFFFFFFFull;
+        } else {
+            ret[0] = 0x0;
+            ret[1] = 0x7FFFFFFFFFFFFFFFull;
+        }
+        set_DSPControl_overflow_flag(env, 1, 16 + ac);
+    } else {
+        ret[0] = acc[0];
+        ret[1] = acc[1];
+    }
+}
+
+static inline int32_t mipsdsp_mul_i16_i16(CPUMIPSState *env,
+                                          int16_t a, int16_t b)
+{
+    int32_t temp, tempA, tempB;
+
+    tempA = a;
+    tempB = b;
+    temp = tempA * tempB;
+
+    if ((temp > 0x7FFF) || (temp < 0xFFFF8000)) {
+        set_DSPControl_overflow_flag(env, 1, 21);
+    }
+    temp &= 0x0000FFFF;
+
+    return temp;
+}
+
+static inline int32_t mipsdsp_sat16_mul_i16_i16(CPUMIPSState *env,
+                                                int16_t a, int16_t b)
+{
+    int32_t temp, tempA, tempB;
+
+    tempA = a;
+    tempB = b;
+    temp = tempA * tempB;
+
+    if (temp > 0x7FFF) {
+        temp = 0x00007FFF;
+        set_DSPControl_overflow_flag(env, 1, 21);
+    } else if (temp < 0x00007FFF) {
+        temp = 0xFFFF8000;
+        set_DSPControl_overflow_flag(env, 1, 21);
+    }
+    temp &= 0x0000FFFF;
+
+    return temp;
+}
+
+static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(CPUMIPSState *env,
+                                                         uint16_t a, uint16_t b)
+{
+    int16_t tempA, tempB;
+    int32_t temp;
+
+    tempA = a;
+    tempB = b;
+
+    if ((a == 0x8000) && (b == 0x8000)) {
+        temp = 0x7FFFFFFF;
+        set_DSPControl_overflow_flag(env, 1, 21);
+    } else {
+        temp = ((int32_t)tempA * (int32_t)tempB) << 1;
+    }
+
+    return temp;
+}
+
+/* right shift */
+static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
+{
+    int32_t temp, tempA, tempB;
+    int16_t result;
+
+    tempA = a;
+    tempB = b;
+    temp = tempA + tempB;
+    result = (temp >> 1) & 0xFFFF;
+
+    return result;
+}
+
+/* round right shift */
+static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b)
+{
+    int32_t temp, tempA, tempB;
+    int16_t result;
+
+    tempA = a;
+    tempB = b;
+    temp = tempA + tempB;
+    temp += 1;
+    result = (temp >> 1) & 0xFFFF;
+
+    return result;
+}
+
+static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b)
+{
+    int64_t temp, tempA, tempB;
+    int32_t result;
+
+    tempA = a;
+    tempB = b;
+    temp = tempA + tempB;
+    result = (temp >> 1) & 0xFFFFFFFF;
+
+    return result;
+}
+
+static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b)
+{
+    int64_t temp, tempA, tempB;
+    int32_t result;
+    tempA = a;
+    tempB = b;
+
+    temp = tempA + tempB;
+    temp += 1;
+    result = (temp >> 1) & 0xFFFFFFFF;
+
+    return result;
+}
+
+static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b)
+{
+    uint16_t tempA, tempB, temp;
+    uint8_t  result;
+
+    tempA = a;
+    tempB = b;
+    temp = tempA + tempB;
+    result = (temp >> 1) & 0x00FF;
+
+    return result;
+}
+
+static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b)
+{
+    uint16_t tempA, tempB, temp;
+    uint8_t  result;
+
+    tempA = a;
+    tempB = b;
+    temp = tempA + tempB + 1;
+    result = (temp >> 1) & 0x00FF;
+
+    return result;
+}
+
+static inline int64_t mipsdsp_rashift_short_acc(CPUMIPSState *env,
+                                                int32_t ac,
+                                                int32_t shift)
+{
+    int32_t sign, temp31;
+    int64_t temp, acc;
+
+    sign = (env->active_tc.HI[ac] >> 31) & 0x01;
+    acc = ((int64_t)env->active_tc.HI[ac] << 32) |
+          ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
+    if (shift == 0) {
+        temp = acc;
+    } else {
+        if (sign == 0) {
+            temp = (((int64_t)0x01 << (32 - shift + 1)) - 1) & (acc >> shift);
+        } else {
+            temp = ((((int64_t)0x01 << (shift + 1)) - 1) << (32 - shift)) |
+                   (acc >> shift);
+        }
+    }
+
+    temp31 = (temp >> 31) & 0x01;
+    if (sign != temp31) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    return temp;
+}
+
+/*  128 bits long. p[0] is LO, p[1] is HI. */
+static inline void mipsdsp__rashift_short_acc(CPUMIPSState *env,
+                                              int64_t *p,
+                                              int32_t ac,
+                                              int32_t shift)
+{
+    int64_t acc;
+
+    acc = ((int64_t)env->active_tc.HI[ac] << 32) |
+          ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
+    if (shift == 0) {
+        p[0] = acc << 1;
+        p[1] = (acc >> 63) & 0x01;
+    } else {
+        p[0] = acc >> (shift - 1);
+        p[1] = 0;
+    }
+}
+
+/* 128 bits long. p[0] is LO, p[1] is HI */
+static inline void mipsdsp_rashift_acc(CPUMIPSState *env,
+                                       uint64_t *p,
+                                       uint32_t ac,
+                                       uint32_t shift)
+{
+    uint64_t tempB, tempA;
+
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+    shift = shift & 0x1F;
+
+    if (shift == 0) {
+        p[1] = tempB;
+        p[0] = tempA;
+    } else {
+        p[0] = (tempB << (64 - shift)) | (tempA >> shift);
+        p[1] = (int64_t)tempB >> shift;
+    }
+}
+
+/* FIXME
+ * if ( shift5..0 = 0 ) then
+ *   temp128..0 ← ( HI[ac]0 || LO[ac]63..0 || 0 )
+ * else
+ *   sign ← HI[ac]63
+ *   temp128..0 ←
+ *           signshift || (( HI[ac]63..0 || LO[ac]63..0 ) >> shift5..0) ||
+ *   LO[ac]shift-1
+ * endif
+ * return temp128..0
+ * endfunction _shiftAccRightArithmetic
+ */
+/* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/
+static inline void mipsdsp__rashift_acc(CPUMIPSState *env,
+                                       uint64_t *p,
+                                       uint32_t ac,
+                                       uint32_t shift)
+{
+    uint64_t tempB, tempA;
+
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+    shift = shift & 0x3F;
+
+    if (shift == 0) {
+        p[2] = tempB >> 63;
+        p[1] = (tempB << 1) | (tempA >> 63);
+        p[0] = tempA << 1;
+    } else {
+        p[0] = (tempB << (64 - shift)) | (tempA >> shift);
+        p[1] = (int64_t)tempB >> shift;
+        if (((tempB >> 63) & 0x01) == 1) {
+            p[2] = 0xFfffFfffFfffFfffull;
+        } else {
+            p[2] = 0x0;
+        }
+    }
+}
+
+static inline int32_t mipsdsp_mul_q15_q15(CPUMIPSState *env,
+                                          int32_t ac, uint16_t a, uint16_t b)
+{
+    uint16_t tempA, tempB;
+    int32_t temp;
+
+    tempA = a;
+    tempB = b;
+
+    if ((a == 0x8000) && (b == 0x8000)) {
+        temp = 0x7FFFFFFF;
+        set_DSPControl_overflow_flag(env, 1, 16 + ac);
+    } else {
+        temp = ((uint32_t)tempA * (uint32_t)tempB) << 1;
+    }
+
+    return temp;
+}
+
+static inline int64_t mipsdsp_mul_q31_q31(CPUMIPSState *env,
+                                          int32_t ac, uint32_t a, uint32_t b)
+{
+    uint32_t tempA, tempB;
+    uint64_t temp;
+
+    tempA = a;
+    tempB = b;
+
+    if ((a == 0x80000000) && (b == 0x80000000)) {
+        temp = 0x7FFFFFFFFFFFFFFFull;
+        set_DSPControl_overflow_flag(env, 1, 16 + ac);
+    } else {
+        temp = ((uint64_t)tempA * (uint64_t)tempB) << 1;
+    }
+
+    return temp;
+}
+
+static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b)
+{
+    uint16_t temp;
+    temp = (uint16_t)a * (uint16_t)b;
+
+    return temp;
+}
+
+static inline uint16_t mipsdsp_mul_u8_u16(CPUMIPSState *env,
+                                          uint8_t a, uint16_t b)
+{
+    uint16_t tempS;
+    uint32_t tempI, tempA, tempB;
+
+    tempA = a;
+    tempB = b;
+    tempI = tempA * tempB;
+    if (tempI > 0x0000FFFF) {
+        tempI = 0x0000FFFF;
+        set_DSPControl_overflow_flag(env, 1, 21);
+    }
+    tempS = tempI & 0x0000FFFF;
+
+    return tempS;
+}
+
+static inline uint64_t mipsdsp_mul_u32_u32(CPUMIPSState *env,
+                                           uint32_t a, uint32_t b)
+{
+  uint64_t temp;
+
+  temp = (uint64_t)a * (uint64_t)b;
+
+  return temp;
+}
+
+static inline int16_t mipsdsp_rndq15_mul_q15_q15(CPUMIPSState *env,
+                                                 uint16_t a, uint16_t b)
+{
+    uint16_t result;
+    uint32_t temp;
+
+    if ((a == 0x8000) && (b == 0x8000)) {
+        temp = 0x7FFF0000;
+        set_DSPControl_overflow_flag(env, 1, 21);
+    } else {
+        temp = (a * b) << 1;
+        temp = temp + 0x00008000;
+    }
+    result = (temp & 0xFFFF0000) >> 16;
+
+    return result;
+}
+
+static inline int32_t mipsdsp_sat16_mul_q15_q15(CPUMIPSState *env,
+                                                uint16_t a, uint16_t b)
+{
+    int16_t tempA, tempB;
+    int32_t temp;
+
+    tempA = a;
+    tempB = b;
+
+    if ((a == 0x8000) && (b == 0x8000)) {
+        temp = 0x7FFF0000;
+        set_DSPControl_overflow_flag(env, 1, 21);
+    } else {
+        temp = ((uint32_t)tempA * (uint32_t)tempB);
+        temp = temp << 1;
+    }
+    temp = (temp >> 16) & 0x0000FFFF;
+
+    return temp;
+}
+
+static inline uint16_t mipsdsp_trunc16_sat16_round(CPUMIPSState *env,
+                                                   uint32_t a)
+{
+    uint16_t result;
+    uint32_t temp32, temp31;
+    int64_t temp;
+
+    temp = (int32_t)a + 0x00008000;
+    temp32 = (temp >> 32) & 0x01;
+    temp31 = (temp >> 31) & 0x01;
+
+    if (temp32 != temp31) {
+        temp = 0x7FFFFFFF;
+        set_DSPControl_overflow_flag(env, 1, 22);
+    }
+    result = (temp >> 16) & 0xFFFF;
+
+    return result;
+}
+
+static inline uint8_t mipsdsp_sat8_reduce_precision(CPUMIPSState *env,
+                                                    uint16_t a)
+{
+    uint8_t  result;
+    uint16_t mag;
+    uint32_t sign;
+
+    sign = (a >> 15) & 0x01;
+    mag = a & 0x7FFF;
+
+    if (sign == 0) {
+        if (mag > 0x7F80) {
+            result = 0xFF;
+            set_DSPControl_overflow_flag(env, 1, 22);
+        } else {
+            result = (mag >> 7) & 0xFFFF;
+        }
+    } else {
+        result = 0x00;
+        set_DSPControl_overflow_flag(env, 1, 22);
+    }
+
+    return result;
+}
+
+static inline uint8_t mipsdsp_lshift8(CPUMIPSState *env, uint8_t a, uint8_t s)
+{
+    uint8_t sign;
+    uint8_t temp, discard;
+
+    if (s == 0) {
+        temp = a;
+    } else {
+        sign = (a >> 7) & 0x01;
+        temp = a << s;
+        if (sign != 0) {
+            discard = (((0x01 << (8 - s)) - 1) << s) |
+                      ((a >> (6 - (s - 1))) & ((0x01 << s) - 1));
+        } else {
+            discard = a >> (6 - (s - 1));
+        }
+
+        if (discard != 0x00) {
+            set_DSPControl_overflow_flag(env, 1, 22);
+        }
+    }
+
+    return temp;
+}
+
+static inline uint8_t mipsdsp_rshift8(uint8_t a, uint8_t s)
+{
+    uint8_t temp;
+    if (s == 0) {
+        temp = a;
+    } else {
+        temp = a >> s;
+    }
+    return temp;
+}
+
+static inline uint16_t mipsdsp_lshift16(CPUMIPSState *env,
+                                        uint16_t a, uint8_t s)
+{
+    uint8_t  sign;
+    uint16_t temp, discard;
+
+    if (s == 0) {
+        temp = a;
+    } else {
+        sign = (a >> 15) & 0x01;
+        temp = a << s;
+        if (sign != 0) {
+            discard = (((0x01 << (16 - s)) - 1) << s) |
+                      ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
+        } else {
+            discard = a >> (14 - (s - 1));
+        }
+
+        if ((discard != 0x0000) && (discard != 0xFFFF)) {
+            set_DSPControl_overflow_flag(env, 1, 22);
+        }
+    }
+
+    return temp;
+}
+
+
+static inline uint32_t mipsdsp_lshift32(CPUMIPSState *env,
+                                        uint32_t a, uint8_t s)
+{
+    uint32_t temp, discard;
+
+    if (s == 0) {
+        temp = a;
+    } else {
+        temp = a << s;
+        discard = (int32_t)a >> (31 - (s - 1));
+
+        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
+            set_DSPControl_overflow_flag(env, 1, 22);
+        }
+    }
+
+    return temp;
+}
+
+static inline uint16_t mipsdsp_sat16_lshift(CPUMIPSState *env,
+                                            uint16_t a, uint8_t s)
+{
+    uint8_t  sign;
+    uint16_t temp, discard;
+
+    if (s == 0) {
+        temp = a;
+    } else {
+        sign = (a >> 15) & 0x01;
+        temp = a << s;
+        if (sign != 0) {
+            discard = (((0x01 << (16 - s)) - 1) << s) |
+                      ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
+        } else {
+            discard = a >> (14 - (s - 1));
+        }
+
+        if ((discard != 0x0000) && (discard != 0xFFFF)) {
+            temp = (sign == 0) ? 0x7FFF : 0x8000;
+            set_DSPControl_overflow_flag(env, 1, 22);
+        }
+    }
+
+    return temp;
+}
+
+static inline uint32_t mipsdsp_sat32_lshift(CPUMIPSState *env,
+                                            uint32_t a, uint8_t s)
+{
+    uint8_t  sign;
+    uint32_t temp, discard;
+
+    if (s == 0) {
+        temp = a;
+    } else {
+        sign = (a >> 31) & 0x01;
+        temp = a << s;
+        if (sign != 0) {
+            discard = (((0x01 << (32 - s)) - 1) << s) |
+                      ((a >> (30 - (s - 1))) & ((0x01 << s) - 1));
+        } else {
+            discard = a >> (30 - (s - 1));
+        }
+
+        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
+            temp = (sign == 0) ? 0x7FFFFFFF : 0x80000000;
+            set_DSPControl_overflow_flag(env, 1, 22);
+        }
+    }
+
+    return temp;
+}
+
+static inline uint16_t mipsdsp_rashift16(uint16_t a, uint8_t s)
+{
+    int16_t i, temp;
+
+    i = a;
+    if (s == 0) {
+        temp = a;
+    } else {
+        temp = i >> s;
+    }
+
+    return temp;
+}
+
+static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s)
+{
+    int16_t  i, result;
+    uint32_t temp;
+
+    i = a;
+    if (s == 0) {
+        temp = (uint32_t)a << 1;
+    } else {
+        temp = (int32_t)i >> (s - 1);
+    }
+    temp   = temp + 1;
+    result = temp >> 1;
+
+    return result;
+}
+
+static inline uint32_t mipsdsp_rashift32(uint32_t a, uint8_t s)
+{
+    int32_t i, temp;
+
+    i = a;
+    if (s == 0) {
+        temp = a;
+    } else {
+        temp = i >> s;
+    }
+
+    return temp;
+}
+
+static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s)
+{
+    int32_t i;
+    int64_t temp;
+    uint32_t result;
+
+    i = a;
+    if (s == 0) {
+        temp = a << 1;
+    } else {
+        temp = (int64_t)i >> (s - 1);
+    }
+    temp += 1;
+    result = (temp >> 1) & 0x00000000FFFFFFFFull;
+
+    return result;
+}
+
+static inline uint16_t mipsdsp_sub_i16(CPUMIPSState *env, int16_t a, int16_t b)
+{
+    uint8_t  temp16, temp15;
+    uint16_t result;
+    int32_t  temp;
+
+    temp = (int32_t)a - (int32_t)b;
+    temp16 = (temp >> 16) & 0x01;
+    temp15 = (temp >> 15) & 0x01;
+    if (temp16 != temp15) {
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+    result = temp & 0x0000FFFF;
+
+    return result;
+}
+
+static inline uint16_t mipsdsp_sat16_sub(CPUMIPSState *env,
+                                         int16_t a, int16_t b)
+{
+    uint8_t  temp16, temp15;
+    uint16_t result;
+    int32_t  temp;
+
+    temp = (int32_t)a - (int32_t)b;
+    temp16 = (temp >> 16) & 0x01;
+    temp15 = (temp >> 15) & 0x01;
+    if (temp16 != temp15) {
+        if (temp16 == 0) {
+            temp = 0x7FFF;
+        } else {
+            temp = 0x8000;
+        }
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+    result = temp & 0x0000FFFF;
+
+    return result;
+}
+
+static inline uint32_t mipsdsp_sat32_sub(CPUMIPSState *env,
+                                         int32_t a, int32_t b)
+{
+    uint8_t  temp32, temp31;
+    uint32_t result;
+    int64_t  temp;
+
+    temp = (int64_t)a - (int64_t)b;
+    temp32 = (temp >> 32) & 0x01;
+    temp31 = (temp >> 31) & 0x01;
+    if (temp32 != temp31) {
+        if (temp32 == 0) {
+            temp = 0x7FFFFFFF;
+        } else {
+            temp = 0x80000000;
+        }
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+    result = temp & 0x00000000FFFFFFFFull;
+
+    return result;
+}
+
+static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b)
+{
+    int32_t  temp;
+    uint16_t result;
+
+    temp = (int32_t)a - (int32_t)b;
+    result = (temp >> 1) & 0x0000FFFF;
+
+    return result;
+}
+
+static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b)
+{
+    int32_t  temp;
+    uint16_t result;
+
+    temp = (int32_t)a - (int32_t)b;
+    temp += 1;
+    result = (temp >> 1) & 0x0000FFFF;
+
+    return result;
+}
+
+static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b)
+{
+    int64_t  temp;
+    uint32_t result;
+
+    temp   = (int64_t)a - (int64_t)b;
+    result = (temp >> 1) & 0x00000000FFFFFFFFull;
+
+    return result;
+}
+
+static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b)
+{
+    int64_t  temp;
+    uint32_t result;
+
+    temp = (int64_t)a - (int64_t)b;
+    temp += 1;
+    result = (temp >> 1) & 0x00000000FFFFFFFFull;
+
+    return result;
+}
+
+static inline uint16_t mipsdsp_sub_u16_u16(CPUMIPSState *env,
+                                           uint16_t a, uint16_t b)
+{
+    uint8_t  temp16;
+    uint16_t result;
+    uint32_t temp;
+
+    temp = (uint32_t)a - (uint32_t)b;
+    temp16 = (temp >> 16) & 0x01;
+    if (temp16 == 1) {
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+    result = temp & 0x0000FFFF;
+    return result;
+}
+
+static inline uint16_t mipsdsp_satu16_sub_u16_u16(CPUMIPSState *env,
+                                                  uint16_t a, uint16_t b)
+{
+    uint8_t  temp16;
+    uint16_t result;
+    uint32_t temp;
+
+    temp   = (uint32_t)a - (uint32_t)b;
+    temp16 = (temp >> 16) & 0x01;
+
+    if (temp16 == 1) {
+        temp = 0x0000;
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+    result = temp & 0x0000FFFF;
+
+    return result;
+}
+
+static inline uint8_t mipsdsp_sub_u8(CPUMIPSState *env, uint8_t a, uint8_t b)
+{
+    uint8_t  result, temp8;
+    uint16_t temp;
+
+    temp = (uint16_t)a - (uint16_t)b;
+    temp8 = (temp >> 8) & 0x01;
+    if (temp8 == 1) {
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+    result = temp & 0x00FF;
+
+    return result;
+}
+
+static inline uint8_t mipsdsp_satu8_sub(CPUMIPSState *env, uint8_t a, uint8_t b)
+{
+    uint8_t  result, temp8;
+    uint16_t temp;
+
+    temp = (uint16_t)a - (uint16_t)b;
+    temp8 = (temp >> 8) & 0x01;
+    if (temp8 == 1) {
+        temp = 0x00;
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+    result = temp & 0x00FF;
+
+    return result;
+}
+
+static inline uint32_t mipsdsp_sub32(CPUMIPSState *env, int32_t a, int32_t b)
+{
+    uint32_t result, temp32, temp31;
+    int64_t temp;
+
+    temp = (int64_t)a - (int64_t)b;
+    temp32 = (temp >> 32) & 0x01;
+    temp31 = (temp >> 31) & 0x01;
+    if (temp32 != temp31) {
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+    result = temp & 0xFFFFFFFF;
+
+    return result;
+}
+
+static inline int32_t mipsdsp_add_i32(CPUMIPSState *env, int32_t a, int32_t b)
+{
+    int32_t result;
+    int32_t temp32, temp31;
+    int64_t aL, bL;
+    int64_t temp;
+
+    aL = (int64_t)a;
+    bL = (int64_t)b;
+    temp = aL + bL;
+
+    temp32 = (temp >> 32) & 0x01;
+    temp31 = (temp >> 31) & 0x01;
+    if (temp32 != temp31) {
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+    result = temp & 0xFFFFFFFF;
+
+    return result;
+}
+/*** MIPS DSP internal functions end ***/
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v6 02/13] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number
  2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 01/13] target-mips-ase-dsp: Add internal functions Jia Liu
@ 2012-08-21  6:53 ` Jia Liu
  2012-08-23 13:33   ` Aurelien Jarno
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 03/13] target-mips-ase-dsp: Add branch instructions Jia Liu
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 20+ messages in thread
From: Jia Liu @ 2012-08-21  6:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/translate.c |  107 +++++++++++++++++++++++++++++++++++------------
 1 file changed, 81 insertions(+), 26 deletions(-)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 47daf85..0793153 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -5,6 +5,7 @@
  *  Copyright (c) 2006 Marius Groeger (FPU operations)
  *  Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
  *  Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
+ *  Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -1972,6 +1973,7 @@ static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
 {
     const char *opn = "hilo";
+    unsigned int acc;
 
     if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
         /* Treat as NOP. */
@@ -1980,25 +1982,71 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
     }
     switch (opc) {
     case OPC_MFHI:
-        tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
+        acc = ((ctx->opcode) >> 21) & 0x03;
+#if defined(TARGET_MIPS64)
+        if (acc == 0) {
+            tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
+        } else {
+            tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
+        }
+#else
+        tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
+#endif
         opn = "mfhi";
         break;
     case OPC_MFLO:
-        tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
+        acc = ((ctx->opcode) >> 21) & 0x03;
+#if defined(TARGET_MIPS64)
+        if (acc == 0) {
+            tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
+        } else {
+            tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
+        }
+#else
+        tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
+#endif
         opn = "mflo";
         break;
     case OPC_MTHI:
-        if (reg != 0)
-            tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
-        else
-            tcg_gen_movi_tl(cpu_HI[0], 0);
+        acc = ((ctx->opcode) >> 11) & 0x03;
+#if defined(TARGET_MIPS64)
+        if (reg != 0) {
+            if (acc == 0) {
+                tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
+            } else {
+                tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
+            }
+        } else {
+            tcg_gen_movi_tl(cpu_HI[acc], 0);
+        }
+#else
+        if (reg != 0) {
+            tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
+        } else {
+            tcg_gen_movi_tl(cpu_HI[acc], 0);
+        }
+#endif
         opn = "mthi";
         break;
     case OPC_MTLO:
-        if (reg != 0)
-            tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
-        else
-            tcg_gen_movi_tl(cpu_LO[0], 0);
+        acc = ((ctx->opcode) >> 11) & 0x03;
+#if defined(TARGET_MIPS64)
+        if (reg != 0) {
+            if (acc == 0) {
+                tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
+            } else {
+                tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
+            }
+        } else {
+            tcg_gen_movi_tl(cpu_LO[acc], 0);
+        }
+#else
+        if (reg != 0) {
+            tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
+        } else {
+            tcg_gen_movi_tl(cpu_LO[acc], 0);
+        }
+#endif
         opn = "mtlo";
         break;
     }
@@ -2011,6 +2059,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
 {
     const char *opn = "mul/div";
     TCGv t0, t1;
+    unsigned int acc;
 
     switch (opc) {
     case OPC_DIV:
@@ -2073,6 +2122,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
         {
             TCGv_i64 t2 = tcg_temp_new_i64();
             TCGv_i64 t3 = tcg_temp_new_i64();
+            acc = ((ctx->opcode) >> 11) & 0x03;
 
             tcg_gen_ext_tl_i64(t2, t0);
             tcg_gen_ext_tl_i64(t3, t1);
@@ -2082,8 +2132,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
             tcg_gen_shri_i64(t2, t2, 32);
             tcg_gen_trunc_i64_tl(t1, t2);
             tcg_temp_free_i64(t2);
-            tcg_gen_ext32s_tl(cpu_LO[0], t0);
-            tcg_gen_ext32s_tl(cpu_HI[0], t1);
+            tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+            tcg_gen_ext32s_tl(cpu_HI[acc], t1);
         }
         opn = "mult";
         break;
@@ -2091,6 +2141,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
         {
             TCGv_i64 t2 = tcg_temp_new_i64();
             TCGv_i64 t3 = tcg_temp_new_i64();
+            acc = ((ctx->opcode) >> 11) & 0x03;
 
             tcg_gen_ext32u_tl(t0, t0);
             tcg_gen_ext32u_tl(t1, t1);
@@ -2102,8 +2153,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
             tcg_gen_shri_i64(t2, t2, 32);
             tcg_gen_trunc_i64_tl(t1, t2);
             tcg_temp_free_i64(t2);
-            tcg_gen_ext32s_tl(cpu_LO[0], t0);
-            tcg_gen_ext32s_tl(cpu_HI[0], t1);
+            tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+            tcg_gen_ext32s_tl(cpu_HI[acc], t1);
         }
         opn = "multu";
         break;
@@ -2150,19 +2201,20 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
         {
             TCGv_i64 t2 = tcg_temp_new_i64();
             TCGv_i64 t3 = tcg_temp_new_i64();
+            acc = ((ctx->opcode) >> 11) & 0x03;
 
             tcg_gen_ext_tl_i64(t2, t0);
             tcg_gen_ext_tl_i64(t3, t1);
             tcg_gen_mul_i64(t2, t2, t3);
-            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
+            tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
             tcg_gen_add_i64(t2, t2, t3);
             tcg_temp_free_i64(t3);
             tcg_gen_trunc_i64_tl(t0, t2);
             tcg_gen_shri_i64(t2, t2, 32);
             tcg_gen_trunc_i64_tl(t1, t2);
             tcg_temp_free_i64(t2);
-            tcg_gen_ext32s_tl(cpu_LO[0], t0);
-            tcg_gen_ext32s_tl(cpu_HI[0], t1);
+            tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+            tcg_gen_ext32s_tl(cpu_HI[acc], t1);
         }
         opn = "madd";
         break;
@@ -2170,21 +2222,22 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
        {
             TCGv_i64 t2 = tcg_temp_new_i64();
             TCGv_i64 t3 = tcg_temp_new_i64();
+            acc = ((ctx->opcode) >> 11) & 0x03;
 
             tcg_gen_ext32u_tl(t0, t0);
             tcg_gen_ext32u_tl(t1, t1);
             tcg_gen_extu_tl_i64(t2, t0);
             tcg_gen_extu_tl_i64(t3, t1);
             tcg_gen_mul_i64(t2, t2, t3);
-            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
+            tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
             tcg_gen_add_i64(t2, t2, t3);
             tcg_temp_free_i64(t3);
             tcg_gen_trunc_i64_tl(t0, t2);
             tcg_gen_shri_i64(t2, t2, 32);
             tcg_gen_trunc_i64_tl(t1, t2);
             tcg_temp_free_i64(t2);
-            tcg_gen_ext32s_tl(cpu_LO[0], t0);
-            tcg_gen_ext32s_tl(cpu_HI[0], t1);
+            tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+            tcg_gen_ext32s_tl(cpu_HI[acc], t1);
         }
         opn = "maddu";
         break;
@@ -2192,19 +2245,20 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
         {
             TCGv_i64 t2 = tcg_temp_new_i64();
             TCGv_i64 t3 = tcg_temp_new_i64();
+            acc = ((ctx->opcode) >> 11) & 0x03;
 
             tcg_gen_ext_tl_i64(t2, t0);
             tcg_gen_ext_tl_i64(t3, t1);
             tcg_gen_mul_i64(t2, t2, t3);
-            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
+            tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
             tcg_gen_sub_i64(t2, t3, t2);
             tcg_temp_free_i64(t3);
             tcg_gen_trunc_i64_tl(t0, t2);
             tcg_gen_shri_i64(t2, t2, 32);
             tcg_gen_trunc_i64_tl(t1, t2);
             tcg_temp_free_i64(t2);
-            tcg_gen_ext32s_tl(cpu_LO[0], t0);
-            tcg_gen_ext32s_tl(cpu_HI[0], t1);
+            tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+            tcg_gen_ext32s_tl(cpu_HI[acc], t1);
         }
         opn = "msub";
         break;
@@ -2212,21 +2266,22 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
         {
             TCGv_i64 t2 = tcg_temp_new_i64();
             TCGv_i64 t3 = tcg_temp_new_i64();
+            acc = ((ctx->opcode) >> 11) & 0x03;
 
             tcg_gen_ext32u_tl(t0, t0);
             tcg_gen_ext32u_tl(t1, t1);
             tcg_gen_extu_tl_i64(t2, t0);
             tcg_gen_extu_tl_i64(t3, t1);
             tcg_gen_mul_i64(t2, t2, t3);
-            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
+            tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
             tcg_gen_sub_i64(t2, t3, t2);
             tcg_temp_free_i64(t3);
             tcg_gen_trunc_i64_tl(t0, t2);
             tcg_gen_shri_i64(t2, t2, 32);
             tcg_gen_trunc_i64_tl(t1, t2);
             tcg_temp_free_i64(t2);
-            tcg_gen_ext32s_tl(cpu_LO[0], t0);
-            tcg_gen_ext32s_tl(cpu_HI[0], t1);
+            tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+            tcg_gen_ext32s_tl(cpu_HI[acc], t1);
         }
         opn = "msubu";
         break;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v6 03/13] target-mips-ase-dsp: Add branch instructions
  2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 01/13] target-mips-ase-dsp: Add internal functions Jia Liu
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 02/13] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Jia Liu
@ 2012-08-21  6:53 ` Jia Liu
  2012-08-23 14:18   ` Aurelien Jarno
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 04/13] target-mips-ase-dsp: Add load instructions Jia Liu
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 20+ messages in thread
From: Jia Liu @ 2012-08-21  6:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Add MIPS ASE DSP Branch instructions.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/translate.c |   52 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 48 insertions(+), 4 deletions(-)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 0793153..b049238 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -332,6 +332,14 @@ enum {
     OPC_DSHD     = (0x05 << 6) | OPC_DBSHFL,
 };
 
+/* MIPS DSP REGIMM opcodes */
+enum {
+    OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
+#if defined(TARGET_MIPS64)
+    OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
+#endif
+};
+
 /* Coprocessor 0 (rs field) */
 #define MASK_CP0(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
 
@@ -2798,6 +2806,24 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
         }
         btgt = ctx->pc + insn_bytes + offset;
         break;
+    case OPC_BPOSGE32:
+        tcg_gen_mov_tl(t0, cpu_dspctrl);
+#if defined(TARGET_MIPS64)
+        tcg_gen_andi_tl(t0, t0, 0x7F);
+#else
+        tcg_gen_andi_tl(t0, t0, 0x3F);
+#endif
+        bcond_compute = 1;
+        btgt = ctx->pc + insn_bytes + offset;
+        break;
+#if defined(TARGET_MIPS64)
+    case OPC_BPOSGE64:
+        tcg_gen_mov_tl(t0, cpu_dspctrl);
+        tcg_gen_andi_tl(t0, t0, 0x7F);
+        bcond_compute = 1;
+        btgt = ctx->pc + insn_bytes + offset;
+        break;
+#endif
     case OPC_J:
     case OPC_JAL:
     case OPC_JALX:
@@ -2986,6 +3012,16 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
             tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
             MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
             goto likely;
+        case OPC_BPOSGE32:
+            tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
+            MIPS_DEBUG("bposge32 %s, " TARGET_FMT_lx, t0, btgt);
+            goto not_likely;
+#if defined(TARGET_MIPS64)
+        case OPC_BPOSGE64:
+            tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
+            MIPS_DEBUG("bposge64 %s, " TARGET_FMT_lx, t0, btgt);
+            goto not_likely;
+#endif
         case OPC_BLTZALS:
         case OPC_BLTZAL:
             ctx->hflags |= (opc == OPC_BLTZALS
@@ -11222,10 +11258,6 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
                                 (ctx->opcode >> 18) & 0x7, imm << 1);
             *is_branch = 1;
             break;
-        case BPOSGE64:
-        case BPOSGE32:
-            /* MIPS DSP: not implemented */
-            /* Fall through */
         default:
             MIPS_INVAL("pool32i");
             generate_exception(ctx, EXCP_RI);
@@ -12134,6 +12166,18 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             check_insn(env, ctx, ISA_MIPS32R2);
             /* Treat as NOP. */
             break;
+        case OPC_BPOSGE32:    /* MIPS DSP branch */
+            check_insn(env, ctx, ASE_DSP);
+            gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
+            *is_branch = 1;
+            break;
+#if defined(TARGET_MIPS64)
+        case OPC_BPOSGE64:
+            check_insn(env, ctx, ASE_DSP);
+            gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
+            *is_branch = 1;
+            break;
+#endif
         default:            /* Invalid */
             MIPS_INVAL("regimm");
             generate_exception(ctx, EXCP_RI);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v6 04/13] target-mips-ase-dsp: Add load instructions
  2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
                   ` (2 preceding siblings ...)
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 03/13] target-mips-ase-dsp: Add branch instructions Jia Liu
@ 2012-08-21  6:53 ` Jia Liu
  2012-08-23 14:23   ` Aurelien Jarno
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 05/13] target-mips-ase-dsp: Add arithmetic instructions Jia Liu
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 20+ messages in thread
From: Jia Liu @ 2012-08-21  6:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Add MIPS ASE DSP Load instructions.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/translate.c |   69 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index b049238..f154f09 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -313,6 +313,9 @@ enum {
     OPC_MODU_G_2E   = 0x23 | OPC_SPECIAL3,
     OPC_DMOD_G_2E   = 0x26 | OPC_SPECIAL3,
     OPC_DMODU_G_2E  = 0x27 | OPC_SPECIAL3,
+
+    /* MIPS DSP Load */
+    OPC_LX_DSP         = 0x0A | OPC_SPECIAL3,
 };
 
 /* BSHFL opcodes */
@@ -340,6 +343,17 @@ enum {
 #endif
 };
 
+#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+/* MIPS DSP Load */
+enum {
+    OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
+    OPC_LHX  = (0x04 << 6) | OPC_LX_DSP,
+    OPC_LWX  = (0x00 << 6) | OPC_LX_DSP,
+#if defined(TARGET_MIPS64)
+    OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
+#endif
+};
+
 /* Coprocessor 0 (rs field) */
 #define MASK_CP0(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
 
@@ -12124,6 +12138,61 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             check_insn(env, ctx, INSN_LOONGSON2E);
             gen_loongson_integer(ctx, op1, rd, rs, rt);
             break;
+        case OPC_LX_DSP:
+            op2 = MASK_LX(ctx->opcode);
+            switch (op2) {
+            case OPC_LBUX:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv addr = tcg_temp_new();
+
+                    save_cpu_state(ctx, 1);
+                    gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]);
+                    op_ld_lbu(cpu_gpr[rd], addr, ctx);
+                    tcg_temp_free(addr);
+                    break;
+                }
+            case OPC_LHX:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv addr = tcg_temp_new();
+
+                    save_cpu_state(ctx, 1);
+                    gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]);
+                    op_ld_lh(cpu_gpr[rd], addr, ctx);
+                    tcg_temp_free(addr);
+                    break;
+                }
+            case OPC_LWX:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv addr = tcg_temp_new();
+
+                    save_cpu_state(ctx, 1);
+                    gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]);
+                    op_ld_lw(cpu_gpr[rd], addr, ctx);
+                    tcg_temp_free(addr);
+                    break;
+                }
+#if defined(TARGET_MIPS64)
+            case OPC_LDX:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv addr = tcg_temp_new();
+
+                    save_cpu_state(ctx, 1);
+                    gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]);
+                    op_ld_ld(cpu_gpr[rd], addr, ctx);
+                    tcg_temp_free(addr);
+                    break;
+                }
+#endif
+            default:            /* Invalid */
+                MIPS_INVAL("MASK LX");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v6 05/13] target-mips-ase-dsp: Add arithmetic instructions
  2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
                   ` (3 preceding siblings ...)
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 04/13] target-mips-ase-dsp: Add load instructions Jia Liu
@ 2012-08-21  6:53 ` Jia Liu
  2012-08-23 14:28   ` Aurelien Jarno
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 06/13] target-mips-ase-dsp: Add GPR Based shift instructions Jia Liu
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 20+ messages in thread
From: Jia Liu @ 2012-08-21  6:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Add MIPS ASE DSP Arithmetic instructions.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/dsp_helper.c | 1929 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/helper.h     |  132 ++++
 target-mips/translate.c  |  675 ++++++++++++++++
 3 files changed, 2736 insertions(+)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index a7d6c7e..486b22f 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -1275,3 +1275,1932 @@ static inline int32_t mipsdsp_add_i32(CPUMIPSState *env, int32_t a, int32_t b)
     return result;
 }
 /*** MIPS DSP internal functions end ***/
+
+#define MIPSDSP_LHI 0xFFFFFFFF00000000ull
+#define MIPSDSP_LLO 0x00000000FFFFFFFFull
+#define MIPSDSP_HI  0xFFFF0000
+#define MIPSDSP_LO  0x0000FFFF
+#define MIPSDSP_Q3  0xFF000000
+#define MIPSDSP_Q2  0x00FF0000
+#define MIPSDSP_Q1  0x0000FF00
+#define MIPSDSP_Q0  0x000000FF
+
+/** DSP Arithmetic Sub-class insns **/
+target_ulong helper_addq_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int16_t  rsh, rsl, rth, rtl, temph, templ;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    temph = mipsdsp_add_i16(env, rsh, rth);
+    templ = mipsdsp_add_i16(env, rsl, rtl);
+    rd = ((unsigned int)temph << 16) | ((unsigned int)templ & 0xFFFF);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addq_s_ph(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl, temph, templ;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    temph = mipsdsp_sat_add_i16(env, rsh, rth);
+    templ = mipsdsp_sat_add_i16(env, rsl, rtl);
+    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & 0xFFFF);
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_addq_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_add_i16(env, rs3, rt3);
+    tempC = mipsdsp_add_i16(env, rs2, rt2);
+    tempB = mipsdsp_add_i16(env, rs1, rt1);
+    tempA = mipsdsp_add_i16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+      ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_addq_s_qh(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sat_add_i16(env, rs3, rt3);
+    tempC = mipsdsp_sat_add_i16(env, rs2, rt2);
+    tempB = mipsdsp_sat_add_i16(env, rs1, rt1);
+    tempA = mipsdsp_sat_add_i16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+      ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_addq_s_w(CPUMIPSState *env,
+                             target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    rd = mipsdsp_sat_add_i32(env, rs, rt);
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_addq_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_add_i32(env, rs1, rt1);
+    tempA = mipsdsp_add_i32(env, rs0, rt0);
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_addq_s_pw(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_sat_add_i32(env, rs1, rt1);
+    tempA = mipsdsp_sat_add_i32(env, rs0, rt0);
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_addu_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    uint8_t  rs0, rs1, rs2, rs3;
+    uint8_t  rt0, rt1, rt2, rt3;
+    uint8_t  temp0, temp1, temp2, temp3;
+
+    rs0 =  rs & MIPSDSP_Q0;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+    rt0 =  rt & MIPSDSP_Q0;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+    temp0 = mipsdsp_add_u8(env, rs0, rt0);
+    temp1 = mipsdsp_add_u8(env, rs1, rt1);
+    temp2 = mipsdsp_add_u8(env, rs2, rt2);
+    temp3 = mipsdsp_add_u8(env, rs3, rt3);
+
+    rd = (((uint32_t)temp3 << 24) & MIPSDSP_Q3) |
+         (((uint32_t)temp2 << 16) & MIPSDSP_Q2) |
+         (((uint32_t)temp1 <<  8) & MIPSDSP_Q1) |
+         ((uint32_t)temp0         & MIPSDSP_Q0);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addu_s_qb(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    uint8_t rs0, rs1, rs2, rs3;
+    uint8_t rt0, rt1, rt2, rt3;
+    uint8_t temp0, temp1, temp2, temp3;
+
+    rs0 =  rs & MIPSDSP_Q0;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+    rt0 =  rt & MIPSDSP_Q0;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+    temp0 = mipsdsp_sat_add_u8(env, rs0, rt0);
+    temp1 = mipsdsp_sat_add_u8(env, rs1, rt1);
+    temp2 = mipsdsp_sat_add_u8(env, rs2, rt2);
+    temp3 = mipsdsp_sat_add_u8(env, rs3, rt3);
+
+    rd = (((uint8_t)temp3 << 24) & MIPSDSP_Q3) |
+         (((uint8_t)temp2 << 16) & MIPSDSP_Q2) |
+         (((uint8_t)temp1 <<  8) & MIPSDSP_Q1) |
+         ((uint8_t)temp0         & MIPSDSP_Q0);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_adduh_qb(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    uint8_t  rs0, rs1, rs2, rs3;
+    uint8_t  rt0, rt1, rt2, rt3;
+    uint8_t  temp0, temp1, temp2, temp3;
+
+    rs0 =  rs & MIPSDSP_Q0;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+    rt0 =  rt & MIPSDSP_Q0;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+    temp0 = mipsdsp_rshift1_add_u8(rs0, rt0);
+    temp1 = mipsdsp_rshift1_add_u8(rs1, rt1);
+    temp2 = mipsdsp_rshift1_add_u8(rs2, rt2);
+    temp3 = mipsdsp_rshift1_add_u8(rs3, rt3);
+
+    rd = (((uint32_t)temp3 << 24) & MIPSDSP_Q3) |
+         (((uint32_t)temp2 << 16) & MIPSDSP_Q2) |
+         (((uint32_t)temp1 <<  8) & MIPSDSP_Q1) |
+         ((uint32_t)temp0         & MIPSDSP_Q0);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_adduh_r_qb(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    uint8_t  rs0, rs1, rs2, rs3;
+    uint8_t  rt0, rt1, rt2, rt3;
+    uint8_t  temp0, temp1, temp2, temp3;
+
+    rs0 =  rs & MIPSDSP_Q0;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+    rt0 =  rt & MIPSDSP_Q0;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+    temp0 = mipsdsp_rrshift1_add_u8(rs0, rt0);
+    temp1 = mipsdsp_rrshift1_add_u8(rs1, rt1);
+    temp2 = mipsdsp_rrshift1_add_u8(rs2, rt2);
+    temp3 = mipsdsp_rrshift1_add_u8(rs3, rt3);
+
+    rd = (((uint32_t)temp3 << 24) & MIPSDSP_Q3) |
+         (((uint32_t)temp2 << 16) & MIPSDSP_Q2) |
+         (((uint32_t)temp1 <<  8) & MIPSDSP_Q1) |
+         ((uint32_t)temp0         & MIPSDSP_Q0);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addu_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl, temph, templ;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    temph = mipsdsp_add_u16(env, rsh, rth);
+    templ = mipsdsp_add_u16(env, rsl, rtl);
+    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addu_s_ph(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl, temph, templ;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    temph = mipsdsp_sat_add_u16(env, rsh, rth);
+    templ = mipsdsp_sat_add_u16(env, rsl, rtl);
+    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addqh_ph(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    int16_t rsh, rsl, rth, rtl, temph, templ;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    temph = mipsdsp_rshift1_add_q16(rsh, rth);
+    templ = mipsdsp_rshift1_add_q16(rsl, rtl);
+    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addqh_r_ph(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    int16_t rsh, rsl, rth, rtl, temph, templ;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    temph = mipsdsp_rrshift1_add_q16(rsh, rth);
+    templ = mipsdsp_rrshift1_add_q16(rsl, rtl);
+    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addqh_w(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+
+    rd = mipsdsp_rshift1_add_q32(rs, rt);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addqh_r_w(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+
+    rd = mipsdsp_rrshift1_add_q32(rs, rt);
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_addu_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_add_u8(env, rs_t[i], rt_t[i]);
+    }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_addu_s_ob(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_sat_add_u8(env, rs_t[i], rt_t[i]);
+    }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_adduh_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_rshift1_add_u8(rs_t[i], rt_t[i]);
+    }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_adduh_r_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_rrshift1_add_u8(rs_t[i], rt_t[i]);
+    }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_addu_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_add_u16(env, rs3, rt3);
+    tempC = mipsdsp_add_u16(env, rs2, rt2);
+    tempB = mipsdsp_add_u16(env, rs1, rt1);
+    tempA = mipsdsp_add_u16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_addu_s_qh(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sat_add_u16(env, rs3, rt3);
+    tempC = mipsdsp_sat_add_u16(env, rs2, rt2);
+    tempB = mipsdsp_sat_add_u16(env, rs1, rt1);
+    tempA = mipsdsp_sat_add_u16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_subq_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl;
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_sub_i16(env, rsh, rth);
+    tempA = mipsdsp_sub_i16(env, rsl, rtl);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subq_s_ph(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl;
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_sat16_sub(env, rsh, rth);
+    tempA = mipsdsp_sat16_sub(env, rsl, rtl);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_subq_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sub_i16(env, rs3, rt3);
+    tempC = mipsdsp_sub_i16(env, rs2, rt2);
+    tempB = mipsdsp_sub_i16(env, rs1, rt1);
+    tempA = mipsdsp_sub_i16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+      ((uint64_t)tempB << 16) | (uint64_t)tempA;
+    return temp;
+}
+
+target_ulong helper_subq_s_qh(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sat16_sub(env, rs3, rt3);
+    tempC = mipsdsp_sat16_sub(env, rs2, rt2);
+    tempB = mipsdsp_sat16_sub(env, rs1, rt1);
+    tempA = mipsdsp_sat16_sub(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+    return temp;
+}
+#endif
+
+target_ulong helper_subq_s_w(CPUMIPSState *env,
+                             target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+
+    rd = mipsdsp_sat32_sub(env, rs, rt);
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_subq_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_sub32(env, rs1, rt1);
+    tempA = mipsdsp_sub32(env, rs0, rt0);
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+    return temp;
+}
+
+target_ulong helper_subq_s_pw(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_sat32_sub(env, rs1, rt1);
+    tempA = mipsdsp_sat32_sub(env, rs0, rt0);
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+    return temp;
+}
+#endif
+
+target_ulong helper_subu_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint8_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    tempD = mipsdsp_sub_u8(env, rs3, rt3);
+    tempC = mipsdsp_sub_u8(env, rs2, rt2);
+    tempB = mipsdsp_sub_u8(env, rs1, rt1);
+    tempA = mipsdsp_sub_u8(env, rs0, rt0);
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subu_s_qb(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint8_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    tempD = mipsdsp_satu8_sub(env, rs3, rt3);
+    tempC = mipsdsp_satu8_sub(env, rs2, rt2);
+    tempB = mipsdsp_satu8_sub(env, rs1, rt1);
+    tempA = mipsdsp_satu8_sub(env, rs0, rt0);
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subuh_qb(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint8_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    tempD = ((uint16_t)rs3 - (uint16_t)rt3) >> 1;
+    tempC = ((uint16_t)rs2 - (uint16_t)rt2) >> 1;
+    tempB = ((uint16_t)rs1 - (uint16_t)rt1) >> 1;
+    tempA = ((uint16_t)rs0 - (uint16_t)rt0) >> 1;
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_ulong)rd;
+}
+
+target_ulong helper_subuh_r_qb(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint8_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    tempD = ((uint16_t)rs3 - (uint16_t)rt3 + 1) >> 1;
+    tempC = ((uint16_t)rs2 - (uint16_t)rt2 + 1) >> 1;
+    tempB = ((uint16_t)rs1 - (uint16_t)rt1 + 1) >> 1;
+    tempA = ((uint16_t)rs0 - (uint16_t)rt0 + 1) >> 1;
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_ulong)rd;
+}
+
+target_ulong helper_subu_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_sub_u16_u16(env, rth, rsh);
+    tempA = mipsdsp_sub_u16_u16(env, rtl, rsl);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subu_s_ph(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_satu16_sub_u16_u16(env, rth, rsh);
+    tempA = mipsdsp_satu16_sub_u16_u16(env, rtl, rsl);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subqh_ph(target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl;
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_rshift1_sub_q16(rsh, rth);
+    tempA = mipsdsp_rshift1_sub_q16(rsl, rtl);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subqh_r_ph(target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl;
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_rrshift1_sub_q16(rsh, rth);
+    tempA = mipsdsp_rrshift1_sub_q16(rsl, rtl);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subqh_w(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+
+    rd = mipsdsp_rshift1_sub_q32(rs, rt);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_subqh_r_w(target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+
+    rd = mipsdsp_rrshift1_sub_q32(rs, rt);
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_subu_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_sub_u8(env, rs_t[i], rt_t[i]);
+    }
+
+    for (i = 0; i < 8; i++) {
+        result += (uint64_t)temp[i] << (i * 8);
+    }
+
+    return result;
+}
+
+target_ulong helper_subu_s_ob(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_satu8_sub(env, rs_t[i], rt_t[i]);
+    }
+
+    for (i = 0; i < 8; i++) {
+        result += (uint64_t)temp[i] << (i * 8);
+    }
+
+    return result;
+}
+
+target_ulong helper_subuh_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = ((uint16_t)rs_t[i] - (uint16_t)rt_t[i]) >> 1;
+      }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_subuh_r_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = ((uint16_t)rs_t[i] - (uint16_t)rt_t[i] + 1) >> 1;
+    }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_subu_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sub_u16_u16(env, rs3, rt3);
+    tempC = mipsdsp_sub_u16_u16(env, rs2, rt2);
+    tempB = mipsdsp_sub_u16_u16(env, rs1, rt1);
+    tempA = mipsdsp_sub_u16_u16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+      ((uint64_t)tempB << 16) | (uint64_t)tempA;
+    return temp;
+}
+
+
+target_ulong helper_subu_s_qh(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_satu16_sub_u16_u16(env, rs3, rt3);
+    tempC = mipsdsp_satu16_sub_u16_u16(env, rs2, rt2);
+    tempB = mipsdsp_satu16_sub_u16_u16(env, rs1, rt1);
+    tempA = mipsdsp_satu16_sub_u16_u16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+    return temp;
+}
+#endif
+
+target_ulong helper_addsc(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    uint64_t temp, tempRs, tempRt;
+    int32_t flag;
+
+    tempRs = (uint64_t)rs & MIPSDSP_LLO;
+    tempRt = (uint64_t)rt & MIPSDSP_LLO;
+
+    temp = tempRs + tempRt;
+    flag = (temp & 0x0100000000ull) >> 32;
+    set_DSPControl_carryflag(env, flag);
+    rd = temp & MIPSDSP_LLO;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_addwc(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    int32_t temp32, temp31;
+    int64_t rsL, rtL, tempL;
+
+    rsL = (int32_t)rs;
+    rtL = (int32_t)rt;
+    tempL = rsL + rtL + get_DSPControl_carryflag(env);
+    temp31 = (tempL >> 31) & 0x01;
+    temp32 = (tempL >> 32) & 0x01;
+
+    if (temp31 != temp32) {
+        set_DSPControl_overflow_flag(env, 1, 20);
+    }
+
+    rd = tempL & MIPSDSP_LLO;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_modsub(target_ulong rs, target_ulong rt)
+{
+    int32_t decr;
+    uint16_t lastindex;
+    target_ulong rd;
+
+    decr = rt & MIPSDSP_Q0;
+    lastindex = (rt >> 8) & MIPSDSP_LO;
+
+    if ((rs & MIPSDSP_LLO) == 0x00000000) {
+        rd = (target_ulong)lastindex;
+    } else {
+        rd = rs - decr;
+    }
+
+    return rd;
+}
+
+target_ulong helper_raddu_w_qb(target_ulong rs)
+{
+    uint8_t  rs3, rs2, rs1, rs0;
+    uint16_t temp;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    temp = (uint16_t)rs3 + (uint16_t)rs2 + (uint16_t)rs1 + (uint16_t)rs0;
+    rd = temp;
+
+    return (target_ulong)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_raddu_l_ob(target_ulong rs)
+{
+    int i;
+    uint16_t rs_t[8];
+    uint64_t temp;
+
+    temp = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        temp += (uint64_t)rs_t[i];
+    }
+
+    return temp;
+}
+#endif
+
+target_ulong helper_absq_s_qb(CPUMIPSState *env, target_ulong rt)
+{
+    uint32_t rd;
+    int8_t tempD, tempC, tempB, tempA;
+
+    tempD = (rt & MIPSDSP_Q3) >> 24;
+    tempC = (rt & MIPSDSP_Q2) >> 16;
+    tempB = (rt & MIPSDSP_Q1) >>  8;
+    tempA =  rt & MIPSDSP_Q0;
+
+    rd = (((uint32_t)mipsdsp_sat_abs_u8 (env, tempD) << 24) & MIPSDSP_Q3) |
+         (((uint32_t)mipsdsp_sat_abs_u8 (env, tempC) << 16) & MIPSDSP_Q2) |
+         (((uint32_t)mipsdsp_sat_abs_u8 (env, tempB) <<  8) & MIPSDSP_Q1) |
+         ((uint32_t)mipsdsp_sat_abs_u8 (env, tempA) & MIPSDSP_Q0);
+
+    return (target_ulong)rd;
+}
+
+target_ulong helper_absq_s_ph(CPUMIPSState *env, target_ulong rt)
+{
+    uint32_t rd;
+    int16_t tempA, tempB;
+
+    tempA = (rt & MIPSDSP_HI) >> 16;
+    tempB =  rt & MIPSDSP_LO;
+
+    rd = ((uint32_t)mipsdsp_sat_abs_u16 (env, tempA) << 16) |
+         ((uint32_t)(mipsdsp_sat_abs_u16 (env, tempB)) & 0xFFFF);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_absq_s_w(CPUMIPSState *env, target_ulong rt)
+{
+    uint32_t rd;
+    int32_t temp;
+
+    temp = rt;
+    rd = mipsdsp_sat_abs_u32(env, temp);
+
+    return (target_ulong)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_absq_s_ob(CPUMIPSState *env, target_ulong rt)
+{
+    uint8_t tempH, tempG, tempF, tempE;
+    uint8_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    tempH = (rt >> 56) & MIPSDSP_Q0;
+    tempG = (rt >> 48) & MIPSDSP_Q0;
+    tempF = (rt >> 40) & MIPSDSP_Q0;
+    tempE = (rt >> 32) & MIPSDSP_Q0;
+    tempD = (rt >> 24) & MIPSDSP_Q0;
+    tempC = (rt >> 16) & MIPSDSP_Q0;
+    tempB = (rt >> 8) & MIPSDSP_Q0;
+    tempA = rt & MIPSDSP_Q0;
+
+    tempH = mipsdsp_sat_abs_u8(env, tempH);
+    tempG = mipsdsp_sat_abs_u8(env, tempG);
+    tempF = mipsdsp_sat_abs_u8(env, tempF);
+    tempE = mipsdsp_sat_abs_u8(env, tempE);
+    tempD = mipsdsp_sat_abs_u8(env, tempD);
+    tempC = mipsdsp_sat_abs_u8(env, tempC);
+    tempB = mipsdsp_sat_abs_u8(env, tempB);
+    tempA = mipsdsp_sat_abs_u8(env, tempA);
+
+    temp = ((uint64_t)tempH << 56) | ((uint64_t)tempG << 48) |
+           ((uint64_t)tempF << 40) | ((uint64_t)tempE << 32) |
+           ((uint64_t)tempD << 24) | ((uint64_t)tempC << 16) |
+           ((uint64_t)tempB << 8) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_absq_s_qh(CPUMIPSState *env, target_ulong rt)
+{
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    tempD = (rt >> 48) & MIPSDSP_LO;
+    tempC = (rt >> 32) & MIPSDSP_LO;
+    tempB = (rt >> 16) & MIPSDSP_LO;
+    tempA = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sat_abs_u16(env, tempD);
+    tempC = mipsdsp_sat_abs_u16(env, tempC);
+    tempB = mipsdsp_sat_abs_u16(env, tempB);
+    tempA = mipsdsp_sat_abs_u16(env, tempA);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_absq_s_pw(CPUMIPSState *env, target_ulong rt)
+{
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    tempB = (rt >> 32) & MIPSDSP_LLO;
+    tempA = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_sat_abs_u32(env, tempB);
+    tempA = mipsdsp_sat_abs_u32(env, tempA);
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_precr_qb_ph(target_ulong rs, target_ulong rt)
+{
+    uint8_t  rs2, rs0, rt2, rt0;
+    uint32_t rd;
+
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs0 =  rs & MIPSDSP_Q0;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt0 =  rt & MIPSDSP_Q0;
+    rd = ((uint32_t)rs2 << 24) | ((uint32_t)rs0 << 16) |
+         ((uint32_t)rt2 <<  8) | (uint32_t)rt0;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_precrq_qb_ph(target_ulong rs, target_ulong rt)
+{
+    uint8_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    tempD = (rs & MIPSDSP_Q3) >> 24;
+    tempC = (rs & MIPSDSP_Q1) >>  8;
+    tempB = (rt & MIPSDSP_Q3) >> 24;
+    tempA = (rt & MIPSDSP_Q1) >>  8;
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs,
+                                   target_ulong rt)
+{
+    uint16_t tempB, tempA;
+
+    if (sa == 0) {
+        tempB = rt & MIPSDSP_LO;
+        tempA = rs & MIPSDSP_LO;
+    } else {
+        tempB = ((int32_t)rt >> sa) & MIPSDSP_LO;
+        tempA = ((int32_t)rs >> sa) & MIPSDSP_LO;
+    }
+    rt = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rt;
+}
+
+target_ulong helper_precr_sra_r_ph_w(uint32_t sa,
+                                     target_ulong rs, target_ulong rt)
+{
+    uint64_t tempB, tempA;
+
+    if (sa == 0) {
+        tempB = (rt & MIPSDSP_LO) << 1;
+        tempA = (rs & MIPSDSP_LO) << 1;
+    } else {
+        tempB = ((int32_t)rt >> (sa - 1)) + 1;
+        tempA = ((int32_t)rs >> (sa - 1)) + 1;
+    }
+    rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rt;
+}
+
+target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt)
+{
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    tempB = (rs & MIPSDSP_HI) >> 16;
+    tempA = (rt & MIPSDSP_HI) >> 16;
+    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_precrq_rs_ph_w(CPUMIPSState *env,
+                                   target_ulong rs, target_ulong rt)
+{
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    tempB = mipsdsp_trunc16_sat16_round(env, rs);
+    tempA = mipsdsp_trunc16_sat16_round(env, rt);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs6, rs4, rs2, rs0;
+    uint8_t rt6, rt4, rt2, rt0;
+    uint64_t temp;
+
+    rs6 = (rs >> 48) & MIPSDSP_Q0;
+    rs4 = (rs >> 32) & MIPSDSP_Q0;
+    rs2 = (rs >> 16) & MIPSDSP_Q0;
+    rs0 = rs & MIPSDSP_Q0;
+    rt6 = (rt >> 48) & MIPSDSP_Q0;
+    rt4 = (rt >> 32) & MIPSDSP_Q0;
+    rt2 = (rt >> 16) & MIPSDSP_Q0;
+    rt0 = rt & MIPSDSP_Q0;
+
+    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
+           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
+           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
+           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
+
+    return temp;
+}
+
+target_ulong helper_precr_sra_qh_pw(target_ulong rs, target_ulong rt,
+                                    uint32_t sa)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t result;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    if (sa == 0) {
+        tempD = rt2;
+        tempC = rt0;
+        tempB = rs2;
+        tempA = rs0;
+    } else {
+        tempD = (int16_t)rt3 >> sa;
+        tempC = (int16_t)rt1 >> sa;
+        tempB = (int16_t)rs3 >> sa;
+        tempA = (int16_t)rs1 >> sa;
+    }
+
+    result = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+             ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return result;
+}
+
+
+target_ulong helper_precr_sra_r_qh_pw(target_ulong rs, target_ulong rt,
+                                      uint32_t sa)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t result;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    if (sa == 0) {
+        tempD = rt2 << 1;
+        tempC = rt0 << 1;
+        tempB = rs2 << 1;
+        tempA = rs0 << 1;
+    } else {
+        tempD = (((int16_t)rt3 >> sa) + 1) >> 1;
+        tempC = (((int16_t)rt1 >> sa) + 1) >> 1;
+        tempB = (((int16_t)rs3 >> sa) + 1) >> 1;
+        tempA = (((int16_t)rs1 >> sa) + 1) >> 1;
+    }
+
+    result = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+             ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return result;
+}
+
+target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs6, rs4, rs2, rs0;
+    uint8_t rt6, rt4, rt2, rt0;
+    uint64_t temp;
+
+    rs6 = (rs >> 56) & MIPSDSP_Q0;
+    rs4 = (rs >> 40) & MIPSDSP_Q0;
+    rs2 = (rs >> 24) & MIPSDSP_Q0;
+    rs0 = (rs >> 8) & MIPSDSP_Q0;
+    rt6 = (rt >> 56) & MIPSDSP_Q0;
+    rt4 = (rt >> 40) & MIPSDSP_Q0;
+    rt2 = (rt >> 24) & MIPSDSP_Q0;
+    rt0 = (rt >> 8) & MIPSDSP_Q0;
+
+    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
+           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
+           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
+           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
+
+    return temp;
+}
+
+target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt)
+{
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    tempD = (rs >> 48) & MIPSDSP_LO;
+    tempC = (rs >> 16) & MIPSDSP_LO;
+    tempB = (rt >> 48) & MIPSDSP_LO;
+    tempA = (rt >> 16) & MIPSDSP_LO;
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_precrq_rs_qh_pw(CPUMIPSState *env,
+                                    target_ulong rs, target_ulong rt)
+{
+    uint32_t rs2, rs0;
+    uint32_t rt2, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs2 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt2 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempD = mipsdsp_trunc16_sat16_round(env, rs2);
+    tempC = mipsdsp_trunc16_sat16_round(env, rs0);
+    tempB = mipsdsp_trunc16_sat16_round(env, rt2);
+    tempA = mipsdsp_trunc16_sat16_round(env, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt)
+{
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    tempB = (rs >> 32) & MIPSDSP_LLO;
+    tempA = (rt >> 32) & MIPSDSP_LLO;
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_precrqu_s_qb_ph(CPUMIPSState *env,
+                                    target_ulong rs, target_ulong rt)
+{
+    uint8_t  tempD, tempC, tempB, tempA;
+    uint16_t rsh, rsl, rth, rtl;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sat8_reduce_precision(env, rsh);
+    tempC = mipsdsp_sat8_reduce_precision(env, rsl);
+    tempB = mipsdsp_sat8_reduce_precision(env, rth);
+    tempA = mipsdsp_sat8_reduce_precision(env, rtl);
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_precrqu_s_ob_qh(CPUMIPSState *env,
+                                    target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    temp[7] = mipsdsp_sat8_reduce_precision(env, rs3);
+    temp[6] = mipsdsp_sat8_reduce_precision(env, rs2);
+    temp[5] = mipsdsp_sat8_reduce_precision(env, rs1);
+    temp[4] = mipsdsp_sat8_reduce_precision(env, rs0);
+    temp[3] = mipsdsp_sat8_reduce_precision(env, rt3);
+    temp[2] = mipsdsp_sat8_reduce_precision(env, rt2);
+    temp[1] = mipsdsp_sat8_reduce_precision(env, rt1);
+    temp[0] = mipsdsp_sat8_reduce_precision(env, rt0);
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+#endif
+
+target_ulong helper_preceq_w_phl(target_ulong rt)
+{
+    uint32_t rd;
+
+    rd = rt & MIPSDSP_HI;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_preceq_w_phr(target_ulong rt)
+{
+    uint16_t rtl;
+    uint32_t rd;
+
+    rtl = rt & MIPSDSP_LO;
+    rd  = rtl << 16;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_preceq_pw_qhl(target_ulong rt)
+{
+    uint16_t tempB, tempA;
+    uint32_t tempBI, tempAI;
+    uint64_t temp;
+
+    tempB = (rt >> 48) & MIPSDSP_LO;
+    tempA = (rt >> 32) & MIPSDSP_LO;
+
+    tempBI = (uint32_t)tempB << 16;
+    tempAI = (uint32_t)tempA << 16;
+
+    temp = ((uint64_t)tempBI << 32) | ((uint64_t)tempAI);
+
+    return temp;
+}
+
+target_ulong helper_preceq_pw_qhr(target_ulong rt)
+{
+    uint16_t tempB, tempA;
+    uint32_t tempBI, tempAI;
+    uint64_t temp;
+
+    tempB = (rt >> 16) & MIPSDSP_LO;
+    tempA = rt & MIPSDSP_LO;
+
+    tempBI = (uint32_t)tempB << 16;
+    tempAI = (uint32_t)tempA << 16;
+
+    temp = ((uint64_t)tempBI << 32) | ((uint64_t)tempAI);
+
+    return temp;
+}
+
+target_ulong helper_preceq_pw_qhla(target_ulong rt)
+{
+    uint16_t tempB, tempA;
+    uint32_t tempBI, tempAI;
+    uint64_t temp;
+
+    tempB = (rt >> 48) & MIPSDSP_LO;
+    tempA = (rt >> 16) & MIPSDSP_LO;
+
+    tempBI = (uint32_t)tempB << 16;
+    tempAI = (uint32_t)tempA << 16;
+
+    temp = ((uint64_t)tempBI << 32) | ((uint64_t)tempAI);
+
+    return temp;
+}
+
+target_ulong helper_preceq_pw_qhra(target_ulong rt)
+{
+    uint16_t tempB, tempA;
+    uint32_t tempBI, tempAI;
+    uint64_t temp;
+
+    tempB = (rt >> 32) & MIPSDSP_LO;
+    tempA = rt & MIPSDSP_LO;
+
+    tempBI = (uint32_t)tempB << 16;
+    tempAI = (uint32_t)tempA << 16;
+
+    temp = ((uint64_t)tempBI << 32) | ((uint64_t)tempAI);
+
+    return temp;
+}
+
+target_ulong helper_preceq_l_pwl(target_ulong rt)
+{
+    uint64_t temp;
+    temp = rt & MIPSDSP_LHI;
+    return temp;
+}
+
+target_ulong helper_preceq_l_pwr(target_ulong rt)
+{
+    uint64_t temp;
+    temp = rt << 32;
+    return temp;
+}
+#endif
+
+target_ulong helper_precequ_ph_qbl(target_ulong rt)
+{
+    uint8_t  rt3, rt2;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+
+    tempB = (uint16_t)rt3 << 7;
+    tempA = (uint16_t)rt2 << 7;
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_precequ_ph_qbr(target_ulong rt)
+{
+    uint8_t  rt1, rt0;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt1 = (rt & MIPSDSP_Q1) >> 8;
+    rt0 =  rt & MIPSDSP_Q0;
+    tempB = (uint16_t)rt1 << 7;
+    tempA = (uint16_t)rt0 << 7;
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_precequ_ph_qbla(target_ulong rt)
+{
+    uint8_t  rt3, rt1;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+
+    tempB = (uint16_t)rt3 << 7;
+    tempA = (uint16_t)rt1 << 7;
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_precequ_ph_qbra(target_ulong rt)
+{
+    uint8_t  rt2, rt0;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt0 =  rt & MIPSDSP_Q0;
+    tempB = (uint16_t)rt2 << 7;
+    tempA = (uint16_t)rt0 << 7;
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_precequ_qh_obl(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 56) & MIPSDSP_Q0;
+    tempCC = (rt >> 48) & MIPSDSP_Q0;
+    tempBC = (rt >> 40) & MIPSDSP_Q0;
+    tempAC = (rt >> 32) & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC << 7;
+    tempCS = (uint16_t)tempCC << 7;
+    tempBS = (uint16_t)tempBC << 7;
+    tempAS = (uint16_t)tempAC << 7;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+
+target_ulong helper_precequ_qh_obr(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 24) & MIPSDSP_Q0;
+    tempCC = (rt >> 16) & MIPSDSP_Q0;
+    tempBC = (rt >> 8) & MIPSDSP_Q0;
+    tempAC = rt & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC << 7;
+    tempCS = (uint16_t)tempCC << 7;
+    tempBS = (uint16_t)tempBC << 7;
+    tempAS = (uint16_t)tempAC << 7;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+
+target_ulong helper_precequ_qh_obla(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 56) & MIPSDSP_Q0;
+    tempCC = (rt >> 40) & MIPSDSP_Q0;
+    tempBC = (rt >> 24) & MIPSDSP_Q0;
+    tempAC = (rt >> 8) & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC << 7;
+    tempCS = (uint16_t)tempCC << 7;
+    tempBS = (uint16_t)tempBC << 7;
+    tempAS = (uint16_t)tempAC << 7;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+
+target_ulong helper_precequ_qh_obra(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 48) & MIPSDSP_Q0;
+    tempCC = (rt >> 32) & MIPSDSP_Q0;
+    tempBC = (rt >> 16) & MIPSDSP_Q0;
+    tempAC = rt & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC << 7;
+    tempCS = (uint16_t)tempCC << 7;
+    tempBS = (uint16_t)tempBC << 7;
+    tempAS = (uint16_t)tempAC << 7;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+#endif
+
+target_ulong helper_preceu_ph_qbl(target_ulong rt)
+{
+    uint8_t  rt3, rt2;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    tempB = (uint16_t) rt3;
+    tempA = (uint16_t) rt2;
+    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_preceu_ph_qbr(target_ulong rt)
+{
+    uint8_t  rt1, rt0;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt1 = (rt & MIPSDSP_Q1) >> 8;
+    rt0 =  rt & MIPSDSP_Q0;
+    tempB = (uint16_t) rt1;
+    tempA = (uint16_t) rt0;
+    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_preceu_ph_qbla(target_ulong rt)
+{
+    uint8_t  rt3, rt1;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    tempB = (uint16_t) rt3;
+    tempA = (uint16_t) rt1;
+    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_preceu_ph_qbra(target_ulong rt)
+{
+    uint8_t  rt2, rt0;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt0 =  rt & MIPSDSP_Q0;
+    tempB = (uint16_t)rt2;
+    tempA = (uint16_t)rt0;
+    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_preceu_qh_obl(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 56) & MIPSDSP_Q0;
+    tempCC = (rt >> 48) & MIPSDSP_Q0;
+    tempBC = (rt >> 40) & MIPSDSP_Q0;
+    tempAC = (rt >> 32) & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC;
+    tempCS = (uint16_t)tempCC;
+    tempBS = (uint16_t)tempBC;
+    tempAS = (uint16_t)tempAC;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+
+target_ulong helper_preceu_qh_obr(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 24) & MIPSDSP_Q0;
+    tempCC = (rt >> 16) & MIPSDSP_Q0;
+    tempBC = (rt >> 8) & MIPSDSP_Q0;
+    tempAC = rt & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC;
+    tempCS = (uint16_t)tempCC;
+    tempBS = (uint16_t)tempBC;
+    tempAS = (uint16_t)tempAC;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+
+target_ulong helper_preceu_qh_obla(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 56) & MIPSDSP_Q0;
+    tempCC = (rt >> 40) & MIPSDSP_Q0;
+    tempBC = (rt >> 24) & MIPSDSP_Q0;
+    tempAC = (rt >> 8) & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC;
+    tempCS = (uint16_t)tempCC;
+    tempBS = (uint16_t)tempBC;
+    tempAS = (uint16_t)tempAC;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+
+target_ulong helper_preceu_qh_obra(target_ulong rt)
+{
+    uint8_t tempDC, tempCC, tempBC, tempAC;
+    uint16_t tempDS, tempCS, tempBS, tempAS;
+    uint64_t temp;
+
+    tempDC = (rt >> 48) & MIPSDSP_Q0;
+    tempCC = (rt >> 32) & MIPSDSP_Q0;
+    tempBC = (rt >> 16) & MIPSDSP_Q0;
+    tempAC = rt & MIPSDSP_Q0;
+
+    tempDS = (uint16_t)tempDC;
+    tempCS = (uint16_t)tempCC;
+    tempBS = (uint16_t)tempBC;
+    tempAS = (uint16_t)tempAC;
+
+    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
+           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
+    return temp;
+}
+#endif
+
+#undef MIPSDSP_LHI
+#undef MIPSDSP_LLO
+#undef MIPSDSP_HI
+#undef MIPSDSP_LO
+#undef MIPSDSP_Q3
+#undef MIPSDSP_Q2
+#undef MIPSDSP_Q1
+#undef MIPSDSP_Q0
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 76fb451..0607105 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -297,4 +297,136 @@ DEF_HELPER_0(rdhwr_ccres, tl)
 DEF_HELPER_1(pmon, void, int)
 DEF_HELPER_0(wait, void)
 
+/*** MIPS DSP ***/
+/* DSP Arithmetic Sub-class insns */
+DEF_HELPER_FLAGS_3(addq_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addq_s_ph, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(addq_qh, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addq_s_qh, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(addq_s_w, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(addq_pw, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addq_s_pw, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(addu_qb, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addu_s_qb, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(adduh_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(adduh_r_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(addu_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addu_s_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(addqh_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(addqh_r_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(addqh_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(addqh_r_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(addu_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addu_s_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(adduh_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(adduh_r_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(addu_qh, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addu_s_qh, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(subq_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subq_s_ph, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(subq_qh, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subq_s_qh, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(subq_s_w, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(subq_pw, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subq_s_pw, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(subu_qb, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subu_s_qb, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(subuh_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(subuh_r_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(subu_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subu_s_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(subqh_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(subqh_r_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(subqh_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(subqh_r_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(subu_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subu_s_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(subuh_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(subuh_r_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(subu_qh, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(subu_s_qh, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(addsc, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(addwc, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(modsub, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_1(raddu_w_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_1(raddu_l_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#endif
+DEF_HELPER_FLAGS_2(absq_s_qb, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(absq_s_ph, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(absq_s_w, 0, tl, env, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_2(absq_s_ob, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(absq_s_qh, 0, tl, env, tl)
+DEF_HELPER_FLAGS_2(absq_s_pw, 0, tl, env, tl)
+#endif
+DEF_HELPER_FLAGS_2(precr_qb_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(precrq_qb_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(precr_sra_ph_w, TCG_CALL_CONST | TCG_CALL_PURE,
+                   tl, i32, tl, tl)
+DEF_HELPER_FLAGS_3(precr_sra_r_ph_w, TCG_CALL_CONST | TCG_CALL_PURE,
+                   tl, i32, tl, tl)
+DEF_HELPER_FLAGS_2(precrq_ph_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(precrq_rs_ph_w, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_2(precr_ob_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(precr_sra_qh_pw,
+                   TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+DEF_HELPER_FLAGS_3(precr_sra_r_qh_pw,
+                   TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+DEF_HELPER_FLAGS_2(precrq_ob_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(precrq_qh_pw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(precrq_rs_qh_pw,
+                   TCG_CALL_CONST | TCG_CALL_PURE, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(precrq_pw_l, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(precrqu_s_qb_ph, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(precrqu_s_ob_qh,
+                   TCG_CALL_CONST | TCG_CALL_PURE, tl, env, tl, tl)
+
+#endif
+DEF_HELPER_FLAGS_1(preceq_w_phl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceq_w_phr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_1(preceq_pw_qhl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceq_pw_qhr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceq_pw_qhla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceq_pw_qhra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceq_l_pwl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceq_l_pwr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#endif
+DEF_HELPER_FLAGS_1(precequ_ph_qbl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(precequ_ph_qbr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(precequ_ph_qbla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(precequ_ph_qbra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_1(precequ_qh_obl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(precequ_qh_obr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(precequ_qh_obla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(precequ_qh_obra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#endif
+DEF_HELPER_FLAGS_1(preceu_ph_qbl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceu_ph_qbr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceu_ph_qbla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceu_ph_qbra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_1(preceu_qh_obl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceu_qh_obr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceu_qh_obla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_1(preceu_qh_obra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+#endif
+
 #include "def-helper.h"
diff --git a/target-mips/translate.c b/target-mips/translate.c
index f154f09..0ea9131 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -316,6 +316,21 @@ enum {
 
     /* MIPS DSP Load */
     OPC_LX_DSP         = 0x0A | OPC_SPECIAL3,
+    /* MIPS DSP Arithmetic */
+    OPC_ADDU_QB_DSP    = 0x10 | OPC_SPECIAL3,
+#if defined(TARGET_MIPS64)
+    OPC_ADDU_OB_DSP    = 0x14 | OPC_SPECIAL3,
+#endif
+    OPC_ABSQ_S_PH_DSP  = 0x12 | OPC_SPECIAL3,
+#if defined(TARGET_MIPS64)
+    OPC_ABSQ_S_QH_DSP  = 0x16 | OPC_SPECIAL3,
+#endif
+    /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E.  */
+    /* OPC_ADDUH_QB_DSP   = 0x18 | OPC_SPECIAL3,  */
+    OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
+#if defined(TARGET_MIPS64)
+    OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
+#endif
 };
 
 /* BSHFL opcodes */
@@ -354,6 +369,144 @@ enum {
 #endif
 };
 
+#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_ADDQ_PH        = (0x0A << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDQ_S_PH      = (0x0E << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDQ_S_W       = (0x16 << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDU_QB        = (0x00 << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDU_S_QB      = (0x04 << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDU_PH        = (0x08 << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDU_S_PH      = (0x0C << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBQ_PH        = (0x0B << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBQ_S_PH      = (0x0F << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBQ_S_W       = (0x17 << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBU_QB        = (0x01 << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBU_S_QB      = (0x05 << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBU_PH        = (0x09 << 6) | OPC_ADDU_QB_DSP,
+    OPC_SUBU_S_PH      = (0x0D << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDSC          = (0x10 << 6) | OPC_ADDU_QB_DSP,
+    OPC_ADDWC          = (0x11 << 6) | OPC_ADDU_QB_DSP,
+    OPC_MODSUB         = (0x12 << 6) | OPC_ADDU_QB_DSP,
+    OPC_RADDU_W_QB     = (0x14 << 6) | OPC_ADDU_QB_DSP,
+};
+
+#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
+#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_ADDUH_QB   = (0x00 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_ADDQH_PH   = (0x08 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
+    OPC_ADDQH_W    = (0x10 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_ADDQH_R_W  = (0x12 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_SUBUH_QB   = (0x01 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_SUBQH_PH   = (0x09 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
+    OPC_SUBQH_W    = (0x11 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_SUBQH_R_W  = (0x13 << 6) | OPC_ADDUH_QB_DSP,
+};
+
+#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_ABSQ_S_QB       = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_ABSQ_S_PH       = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_ABSQ_S_W        = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEQ_W_PHL    = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEQ_W_PHR    = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEQU_PH_QBL  = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEQU_PH_QBR  = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEU_PH_QBL   = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEU_PH_QBR   = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEU_PH_QBLA  = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_PRECEU_PH_QBRA  = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
+};
+
+#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_PRECR_QB_PH      = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PRECRQ_QB_PH     = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PRECR_SRA_PH_W   = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PRECRQ_PH_W      = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PRECRQ_RS_PH_W   = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PRECRQU_S_QB_PH  = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
+};
+
+#if defined(TARGET_MIPS64)
+#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_PRECEQ_L_PWL    = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQ_L_PWR    = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQ_PW_QHL   = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQ_PW_QHR   = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQ_PW_QHLA  = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQ_PW_QHRA  = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQU_QH_OBL  = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQU_QH_OBR  = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEU_QH_OBL   = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEU_QH_OBR   = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEU_QH_OBLA  = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_PRECEU_QH_OBRA  = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_ABSQ_S_OB       = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_ABSQ_S_PW       = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_ABSQ_S_QH       = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
+};
+#endif
+
+#if defined(TARGET_MIPS64)
+#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_RADDU_L_OB     = (0x14 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBQ_PW        = (0x13 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBQ_S_PW      = (0x17 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBQ_QH        = (0x0B << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBQ_S_QH      = (0x0F << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBU_OB        = (0x01 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBU_S_OB      = (0x05 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBU_QH        = (0x09 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBU_S_QH      = (0x0D << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBUH_OB       = (0x19 << 6) | OPC_ADDU_OB_DSP,
+    OPC_SUBUH_R_OB     = (0x1B << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDQ_PW        = (0x12 << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDQ_S_PW      = (0x16 << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDQ_QH        = (0x0A << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDQ_S_QH      = (0x0E << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDU_OB        = (0x00 << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDU_S_OB      = (0x04 << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDU_QH        = (0x08 << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDU_S_QH      = (0x0C << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDUH_OB       = (0x18 << 6) | OPC_ADDU_OB_DSP,
+    OPC_ADDUH_R_OB     = (0x1A << 6) | OPC_ADDU_OB_DSP,
+};
+#endif
+
+#if defined(TARGET_MIPS64)
+#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Arithmetic Sub-class */
+    OPC_PRECR_OB_QH       = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECR_SRA_QH_PW   = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECRQ_OB_QH      = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECRQ_PW_L       = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECRQ_QH_PW      = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECRQ_RS_QH_PW   = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PRECRQU_S_OB_QH   = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
+};
+#endif
+
 /* Coprocessor 0 (rs field) */
 #define MASK_CP0(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
 
@@ -12134,6 +12287,72 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             break;
         case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
         case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
+        /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
+         * the same mask and op1. */
+            if (op1 == OPC_MULT_G_2E) {
+                int is_mult_g_2e = 0;
+                op2 = MASK_ADDUH_QB(ctx->opcode);
+                switch (op2) {
+                case  OPC_ADDUH_QB:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_adduh_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_ADDUH_R_QB:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_adduh_r_qb(cpu_gpr[rd],
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_ADDQH_PH:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_addqh_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_ADDQH_R_PH:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_addqh_r_ph(cpu_gpr[rd], cpu_gpr[rs],
+                                          cpu_gpr[rt]);
+                    break;
+                case  OPC_ADDQH_W:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_addqh_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_ADDQH_R_W:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_addqh_r_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_SUBUH_QB:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_subuh_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_SUBUH_R_QB:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_subuh_r_qb(cpu_gpr[rd],
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_SUBQH_PH:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_subqh_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_SUBQH_R_PH:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_subqh_r_ph(cpu_gpr[rd],
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_SUBQH_W:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_subqh_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_SUBQH_R_W:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_subqh_r_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                default:
+                    is_mult_g_2e = 1;
+                    break;
+                }
+                if (is_mult_g_2e == 0) {
+                    break;
+                }
+            }
         case OPC_MOD_G_2E ... OPC_MODU_G_2E:
             check_insn(env, ctx, INSN_LOONGSON2E);
             gen_loongson_integer(ctx, op1, rd, rs, rt);
@@ -12193,6 +12412,213 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 break;
             }
             break;
+        case OPC_ABSQ_S_PH_DSP:
+            op2 = MASK_ABSQ_S_PH(ctx->opcode);
+            switch (op2) {
+            case OPC_ABSQ_S_QB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_absq_s_qb(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
+                break;
+            case OPC_ABSQ_S_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_absq_s_ph(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
+                break;
+            case OPC_ABSQ_S_W:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_absq_s_w(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_W_PHL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_w_phl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_W_PHR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_w_phr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_PH_QBL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_ph_qbl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_PH_QBR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_ph_qbr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_PH_QBLA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_ph_qbla(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_PH_QBRA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_ph_qbra(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_PH_QBL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_ph_qbl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_PH_QBR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_ph_qbr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_PH_QBLA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_ph_qbla(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_PH_QBRA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_ph_qbra(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK ABSQ_S.PH");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+        case OPC_ADDU_QB_DSP:
+            op2 = MASK_ADDU_QB(ctx->opcode);
+            switch (op2) {
+            case OPC_ADDQ_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_ph(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDQ_S_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_s_ph(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDQ_S_W:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_s_w(cpu_gpr[rd], cpu_env,
+                                    cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addu_qb(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_S_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addu_s_qb(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_addu_ph(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_S_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_addu_s_ph(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBQ_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_ph(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBQ_S_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_s_ph(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBQ_S_W:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_s_w(cpu_gpr[rd], cpu_env,
+                                    cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subu_qb(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_S_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subu_s_qb(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_subu_ph(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_S_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_subu_s_ph(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDSC:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addsc(cpu_gpr[rd], cpu_env,
+                                 cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDWC:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addwc(cpu_gpr[rd], cpu_env,
+                                 cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_MODSUB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_modsub(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_RADDU_W_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_raddu_w_qb(cpu_gpr[rd], cpu_gpr[rs]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK ADDU.QB");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+        case OPC_CMPU_EQ_QB_DSP:
+            op2 = MASK_CMPU_EQ_QB(ctx->opcode);
+            switch (op2) {
+            case OPC_PRECR_QB_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_precr_qb_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQ_QB_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_qb_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PRECR_SRA_PH_W:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_precr_sra_ph_w(cpu_gpr[rt], temp_rd,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_PRECR_SRA_R_PH_W:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_precr_sra_r_ph_w(cpu_gpr[rt], temp_rd,
+                                            cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_PRECRQ_PH_W:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_ph_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQ_RS_PH_W:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_rs_ph_w(cpu_gpr[rd], cpu_env,
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQU_S_QB_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrqu_s_qb_ph(cpu_gpr[rd], cpu_env,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK CMPU.EQ.QB");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
@@ -12213,6 +12639,255 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             gen_loongson_integer(ctx, op1, rd, rs, rt);
             break;
 #endif
+#if defined(TARGET_MIPS64)
+        case OPC_ABSQ_S_QH_DSP:
+            op2 = MASK_ABSQ_S_QH(ctx->opcode);
+            switch (op2) {
+            case OPC_PRECEQ_L_PWL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_l_pwl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_L_PWR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_l_pwr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_PW_QHL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_pw_qhl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_PW_QHR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_pw_qhr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_PW_QHLA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_pw_qhla(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQ_PW_QHRA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceq_pw_qhra(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_QH_OBL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_qh_obl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_QH_OBR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_qh_obr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_QH_OBLA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_qh_obla(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEQU_QH_OBRA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precequ_qh_obra(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_QH_OBL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_qh_obl(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_QH_OBR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_qh_obr(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_QH_OBLA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_qh_obla(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_PRECEU_QH_OBRA:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_preceu_qh_obra(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_ABSQ_S_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_absq_s_ob(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
+                break;
+            case OPC_ABSQ_S_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_absq_s_pw(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
+                break;
+            case OPC_ABSQ_S_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_absq_s_qh(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK ABSQ_S.QH");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+#endif
+#if defined(TARGET_MIPS64)
+        case OPC_ADDU_OB_DSP:
+            op2 = MASK_ADDU_OB(ctx->opcode);
+            switch (op2) {
+            case OPC_RADDU_L_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_raddu_l_ob(cpu_gpr[rd], cpu_gpr[rs]);
+                break;
+            case OPC_SUBQ_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_pw(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBQ_S_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_s_pw(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBQ_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_qh(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBQ_S_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subq_s_qh(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subu_ob(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_S_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subu_s_ob(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subu_qh(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBU_S_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_subu_s_qh(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBUH_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_subuh_ob(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_SUBUH_R_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_subuh_r_ob(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDQ_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_pw(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDQ_S_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_s_pw(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDQ_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_qh(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDQ_S_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addq_s_qh(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addu_ob(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_S_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_addu_s_ob(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_QH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_addu_qh(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDU_S_QH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_addu_s_qh(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDUH_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_adduh_ob(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_ADDUH_R_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_adduh_r_ob(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK ADDU.OB");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+#endif
+#if defined(TARGET_MIPS64)
+        case OPC_CMPU_EQ_OB_DSP:
+            op2 = MASK_CMPU_EQ_OB(ctx->opcode);
+            switch (op2) {
+            case OPC_PRECR_OB_QH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_precr_ob_qh(cpu_gpr[rd], cpu_gpr[rs],
+                                       cpu_gpr[rt]);
+                break;
+            case OPC_PRECR_SRA_QH_PW:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rd);
+                    gen_helper_precr_sra_qh_pw(cpu_gpr[rt], cpu_gpr[rs],
+                                               cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_PRECR_SRA_R_QH_PW:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rd);
+                    gen_helper_precr_sra_r_qh_pw(cpu_gpr[rt], cpu_gpr[rs],
+                                                 cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_PRECRQ_OB_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_ob_qh(cpu_gpr[rd], cpu_gpr[rs],
+                                        cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQ_PW_L:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_pw_l(cpu_gpr[rd], cpu_gpr[rs],
+                                       cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQ_QH_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_qh_pw(cpu_gpr[rd], cpu_gpr[rs],
+                                        cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQ_RS_QH_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrq_rs_qh_pw(cpu_gpr[rd], cpu_env,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PRECRQU_S_OB_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_precrqu_s_ob_qh(cpu_gpr[rd], cpu_env,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK CMPU.EQ.OB");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+#endif
         default:            /* Invalid */
             MIPS_INVAL("special3");
             generate_exception(ctx, EXCP_RI);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v6 06/13] target-mips-ase-dsp: Add GPR Based shift instructions
  2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
                   ` (4 preceding siblings ...)
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 05/13] target-mips-ase-dsp: Add arithmetic instructions Jia Liu
@ 2012-08-21  6:53 ` Jia Liu
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 07/13] target-mips-ase-dsp: Add multiply instructions Jia Liu
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Jia Liu @ 2012-08-21  6:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Add MIPS ASE DSP GPR-Based Shift instructions.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/dsp_helper.c |  991 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/helper.h     |   62 +++
 target-mips/translate.c  |  359 +++++++++++++++++
 3 files changed, 1412 insertions(+)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 486b22f..8e7bccb 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -3196,6 +3196,997 @@ target_ulong helper_preceu_qh_obra(target_ulong rt)
 }
 #endif
 
+/** DSP GPR-Based Shift Sub-class insns **/
+target_ulong helper_shll_qb(CPUMIPSState *env, uint32_t sa, target_ulong rt)
+{
+    uint8_t  rt3, rt2, rt1, rt0;
+    uint8_t  tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    tempD = mipsdsp_lshift8(env, rt3, sa);
+    tempC = mipsdsp_lshift8(env, rt2, sa);
+    tempB = mipsdsp_lshift8(env, rt1, sa);
+    tempA = mipsdsp_lshift8(env, rt0, sa);
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | ((uint32_t)tempA);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shllv_qb(CPUMIPSState *env,
+                             target_ulong rs, target_ulong rt)
+{
+    uint8_t  rs2_0;
+    uint8_t  rt3, rt2, rt1, rt0;
+    uint8_t  tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rs2_0 = rs & 0x07;
+    rt3   = (rt & MIPSDSP_Q3) >> 24;
+    rt2   = (rt & MIPSDSP_Q2) >> 16;
+    rt1   = (rt & MIPSDSP_Q1) >>  8;
+    rt0   =  rt & MIPSDSP_Q0;
+
+    tempD = mipsdsp_lshift8(env, rt3, rs2_0);
+    tempC = mipsdsp_lshift8(env, rt2, rs2_0);
+    tempB = mipsdsp_lshift8(env, rt1, rs2_0);
+    tempA = mipsdsp_lshift8(env, rt0, rs2_0);
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_shll_ob(CPUMIPSState *env, target_ulong rt, uint32_t sa)
+{
+    int i;
+    uint8_t rt_t[8];
+    uint8_t temp_t[8];
+    uint64_t temp;
+
+    sa = sa & 0x07;
+    temp = 0;
+
+    for (i = 0; i < 8; i++) {
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp_t[i] = mipsdsp_lshift8(env, rt_t[i], sa);
+
+        temp |= (uint64_t)temp_t[i] << (8 * i);
+    }
+
+    return temp;
+}
+
+target_ulong helper_shllv_ob(CPUMIPSState *env,
+                             target_ulong rt, target_ulong sa)
+{
+    int i;
+    uint8_t rt_t[8];
+    uint8_t temp_t[8];
+    uint64_t temp;
+
+    sa = sa & 0x07;
+    temp = 0;
+
+    for (i = 0; i < 8; i++) {
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp_t[i] = mipsdsp_lshift8(env, rt_t[i], sa);
+
+        temp |= (uint64_t)temp_t[i] << (8 * i);
+    }
+
+    return temp;
+}
+#endif
+
+target_ulong helper_shll_ph(CPUMIPSState *env, uint32_t sa, target_ulong rt)
+{
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_lshift16(env, rth, sa);
+    tempA = mipsdsp_lshift16(env, rtl, sa);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shllv_ph(CPUMIPSState *env,
+                             target_ulong rs, target_ulong rt)
+{
+    uint8_t  rs3_0;
+    uint16_t rth, rtl, tempB, tempA;
+    uint32_t rd;
+
+    rth   = (rt & MIPSDSP_HI) >> 16;
+    rtl   =  rt & MIPSDSP_LO;
+    rs3_0 = rs & 0x0F;
+
+    tempB = mipsdsp_lshift16(env, rth, rs3_0);
+    tempA = mipsdsp_lshift16(env, rtl, rs3_0);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shll_s_ph(CPUMIPSState *env, uint32_t sa, target_ulong rt)
+{
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_sat16_lshift(env, rth, sa);
+    tempA = mipsdsp_sat16_lshift(env, rtl, sa);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shllv_s_ph(CPUMIPSState *env,
+                               target_ulong rs, target_ulong rt)
+{
+    uint8_t  rs3_0;
+    uint16_t rth, rtl, tempB, tempA;
+    uint32_t rd;
+
+    rth   = (rt & MIPSDSP_HI) >> 16;
+    rtl   =  rt & MIPSDSP_LO;
+    rs3_0 = rs & 0x0F;
+
+    tempB = mipsdsp_sat16_lshift(env, rth, rs3_0);
+    tempA = mipsdsp_sat16_lshift(env, rtl, rs3_0);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_shll_qh(CPUMIPSState *env, target_ulong rt, uint32_t sa)
+{
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    sa = sa & 0x0F;
+
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_lshift16(env, rt3, sa);
+    tempC = mipsdsp_lshift16(env, rt2, sa);
+    tempB = mipsdsp_lshift16(env, rt1, sa);
+    tempA = mipsdsp_lshift16(env, rt0, sa);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_shllv_qh(CPUMIPSState *env,
+                             target_ulong rt, target_ulong sa)
+{
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    sa = sa & 0x0F;
+
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_lshift16(env, rt3, sa);
+    tempC = mipsdsp_lshift16(env, rt2, sa);
+    tempB = mipsdsp_lshift16(env, rt1, sa);
+    tempA = mipsdsp_lshift16(env, rt0, sa);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_shll_s_qh(CPUMIPSState *env, target_ulong rt, uint32_t sa)
+{
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    sa = sa & 0x0F;
+
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sat16_lshift(env, rt3, sa);
+    tempC = mipsdsp_sat16_lshift(env, rt2, sa);
+    tempB = mipsdsp_sat16_lshift(env, rt1, sa);
+    tempA = mipsdsp_sat16_lshift(env, rt0, sa);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_shllv_s_qh(CPUMIPSState *env,
+                               target_ulong rt, target_ulong sa)
+{
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    sa = sa & 0x0F;
+
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sat16_lshift(env, rt3, sa);
+    tempC = mipsdsp_sat16_lshift(env, rt2, sa);
+    tempB = mipsdsp_sat16_lshift(env, rt1, sa);
+    tempA = mipsdsp_sat16_lshift(env, rt0, sa);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_shll_s_w(CPUMIPSState *env, uint32_t sa, target_ulong rt)
+{
+    uint32_t temp, rd;
+
+    temp = mipsdsp_sat32_lshift(env, rt, sa);
+    rd   = temp;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shllv_s_w(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint8_t  rs4_0;
+    uint32_t rd;
+
+    rs4_0 = rs & 0x1F;
+    rd = mipsdsp_sat32_lshift(env, rt, rs4_0);
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_shll_pw(CPUMIPSState *env, target_ulong rt, uint32_t sa)
+{
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_lshift32(env, rt1, sa);
+    tempA = mipsdsp_lshift32(env, rt0, sa);
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_shllv_pw(CPUMIPSState *env,
+                             target_ulong rt, target_ulong sa)
+{
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    sa = sa & 0x1F;
+
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_lshift32(env, rt1, sa);
+    tempA = mipsdsp_lshift32(env, rt0, sa);
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_shll_s_pw(CPUMIPSState *env, target_ulong rt, uint32_t sa)
+{
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_sat32_lshift(env, rt1, sa);
+    tempA = mipsdsp_sat32_lshift(env, rt0, sa);
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_shllv_s_pw(CPUMIPSState *env,
+                               target_ulong rt, target_ulong sa)
+{
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    sa = sa & 0x1F;
+
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_sat32_lshift(env, rt1, sa);
+    tempA = mipsdsp_sat32_lshift(env, rt0, sa);
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_shrl_qb(uint32_t sa, target_ulong rt)
+{
+    uint8_t  rt3, rt2, rt1, rt0;
+    uint8_t  tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    tempD = mipsdsp_rshift8(rt3, sa);
+    tempC = mipsdsp_rshift8(rt2, sa);
+    tempB = mipsdsp_rshift8(rt1, sa);
+    tempA = mipsdsp_rshift8(rt0, sa);
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shrlv_qb(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs2_0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint8_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rs2_0 = rs & 0x07;
+    rt3   = (rt & MIPSDSP_Q3) >> 24;
+    rt2   = (rt & MIPSDSP_Q2) >> 16;
+    rt1   = (rt & MIPSDSP_Q1) >>  8;
+    rt0   =  rt & MIPSDSP_Q0;
+
+    tempD = mipsdsp_rshift8(rt3, rs2_0);
+    tempC = mipsdsp_rshift8(rt2, rs2_0);
+    tempB = mipsdsp_rshift8(rt1, rs2_0);
+    tempA = mipsdsp_rshift8(rt0, rs2_0);
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shrl_ph(uint32_t sa, target_ulong rt)
+{
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    tempB = rth >> sa;
+    tempA = rtl >> sa;
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shrlv_ph(target_ulong rs, target_ulong rt)
+{
+    uint8_t  rs3_0;
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rs3_0 = rs & 0x0F;
+    rth   = (rt & MIPSDSP_HI) >> 16;
+    rtl   =  rt & MIPSDSP_LO;
+
+    tempB = rth >> rs3_0;
+    tempA = rtl >> rs3_0;
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_shrl_ob(target_ulong rt, uint32_t sa)
+{
+    int i;
+    uint8_t rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    sa = sa & 0x07;
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_rshift8(rt_t[i], sa);
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_shrlv_ob(target_ulong rt, target_ulong sa)
+{
+    int i;
+    uint8_t rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    sa = sa & 0x07;
+    result = 0;
+
+    for (i = 0; i < 8; i++) {
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_rshift8(rt_t[i], sa);
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_shrl_qh(target_ulong rt, uint32_t sa)
+{
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    sa = sa & 0x0F;
+
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = rt3 >> sa;
+    tempC = rt2 >> sa;
+    tempB = rt1 >> sa;
+    tempA = rt0 >> sa;
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_shrlv_qh(target_ulong rt, target_ulong sa)
+{
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    sa = sa & 0x0F;
+
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = rt3 >> sa;
+    tempC = rt2 >> sa;
+    tempB = rt1 >> sa;
+    tempA = rt0 >> sa;
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_shra_qb(uint32_t sa, target_ulong rt)
+{
+    int8_t  rt3, rt2, rt1, rt0;
+    uint8_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    tempD = rt3 >> sa;
+    tempC = rt2 >> sa;
+    tempB = rt1 >> sa;
+    tempA = rt0 >> sa;
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+          ((uint32_t)tempB << 8) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shra_r_qb(uint32_t sa, target_ulong rt)
+{
+    int8_t  rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    if (sa == 0) {
+        tempD = rt3 & 0x00FF;
+        tempC = rt2 & 0x00FF;
+        tempB = rt1 & 0x00FF;
+        tempA = rt0 & 0x00FF;
+    } else {
+        tempD = ((int16_t)rt3 >> (sa - 1)) + 1;
+        tempC = ((int16_t)rt2 >> (sa - 1)) + 1;
+        tempB = ((int16_t)rt1 >> (sa - 1)) + 1;
+        tempA = ((int16_t)rt0 >> (sa - 1)) + 1;
+    }
+
+    rd = ((uint32_t)((tempD >> 1) & 0x00FF) << 24) |
+         ((uint32_t)((tempC >> 1) & 0x00FF) << 16) |
+         ((uint32_t)((tempB >> 1) & 0x00FF) <<  8) |
+         (uint32_t)((tempA >>  1) & 0x00FF) ;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shrav_qb(target_ulong rs, target_ulong rt)
+{
+    uint8_t  rs2_0;
+    int8_t   rt3, rt2, rt1, rt0;
+    uint8_t  tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rs2_0 = rs & 0x07;
+    rt3   = (rt & MIPSDSP_Q3) >> 24;
+    rt2   = (rt & MIPSDSP_Q2) >> 16;
+    rt1   = (rt & MIPSDSP_Q1) >>  8;
+    rt0   =  rt & MIPSDSP_Q0;
+
+    if (rs2_0 == 0) {
+        tempD = rt3;
+        tempC = rt2;
+        tempB = rt1;
+        tempA = rt0;
+    } else {
+        tempD = rt3 >> rs2_0;
+        tempC = rt2 >> rs2_0;
+        tempB = rt1 >> rs2_0;
+        tempA = rt0 >> rs2_0;
+    }
+
+    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
+         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shrav_r_qb(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs2_0;
+    int8_t  rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint32_t rd;
+
+    rs2_0 = rs & 0x07;
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    if (rs2_0 == 0) {
+        tempD = (int16_t)rt3 << 1;
+        tempC = (int16_t)rt2 << 1;
+        tempB = (int16_t)rt1 << 1;
+        tempA = (int16_t)rt0 << 1;
+    } else {
+        tempD = ((int16_t)rt3 >> (rs2_0 - 1)) + 1;
+        tempC = ((int16_t)rt2 >> (rs2_0 - 1)) + 1;
+        tempB = ((int16_t)rt1 >> (rs2_0 - 1)) + 1;
+        tempA = ((int16_t)rt0 >> (rs2_0 - 1)) + 1;
+    }
+
+    rd = ((uint32_t)((tempD >> 1) & 0x00FF) << 24) |
+         ((uint32_t)((tempC >> 1) & 0x00FF) << 16) |
+         ((uint32_t)((tempB >> 1) & 0x00FF) <<  8) |
+         (uint32_t)((tempA >>  1) & 0x00FF) ;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_shra_ob(target_ulong rt, uint32_t sa)
+{
+    int i;
+    int8_t rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+    sa = sa & 0x07;
+
+    for (i = 0; i < 8; i++) {
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = rt_t[i] >> sa;
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_shrav_ob(target_ulong rt, target_ulong sa)
+{
+    int i;
+    int8_t rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+    sa = sa & 0x07;
+
+    for (i = 0; i < 8; i++) {
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = rt_t[i] >> sa;
+        result |= (uint64_t)temp[i] << (8 * i);
+      }
+
+    return result;
+}
+
+target_ulong helper_shra_r_ob(target_ulong rt, uint32_t sa)
+{
+    int i;
+    int8_t rt_t[8];
+    int16_t rt_t_S[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+    sa = sa & 0x07;
+
+    if (sa == 0) {
+        result = rt;
+    } else {
+        for (i = 0; i < 8; i++) {
+            rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+            rt_t_S[i] = ((int16_t)rt_t[i] >> (sa - 1)) + 1;
+            temp[i] = (rt_t_S[i] >> 1) & MIPSDSP_Q0;
+            result |= (uint64_t)temp[i] << (8 * i);
+        }
+    }
+
+    return result;
+}
+
+target_ulong helper_shrav_r_ob(target_ulong rt, target_ulong sa)
+{
+    int i;
+    int8_t rt_t[8];
+    int16_t rt_t_S[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+    sa = sa & 0x07;
+
+    if (sa == 0) {
+        result = rt;
+    } else {
+        for (i = 0; i < 8; i++) {
+            rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+            rt_t_S[i] = ((int16_t)rt_t[i] >> (sa - 1)) + 1;
+            temp[i] = (rt_t_S[i] >> 1) & MIPSDSP_Q0;
+            result |= (uint64_t)temp[i] << (8 * i);
+        }
+    }
+
+    return result;
+}
+#endif
+
+target_ulong helper_shra_ph(uint32_t sa, target_ulong rt)
+{
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_rashift16(rth, sa);
+    tempA = mipsdsp_rashift16(rtl, sa);
+    rd = ((uint32_t)tempB << 16) | (uint32_t) tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shrav_ph(target_ulong rs, target_ulong rt)
+{
+    uint8_t  rs3_0;
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rs3_0 = rs & 0x0F;
+    rth   = (rt & MIPSDSP_HI) >> 16;
+    rtl   =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_rashift16(rth, rs3_0);
+    tempA = mipsdsp_rashift16(rtl, rs3_0);
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shra_r_ph(uint32_t sa, target_ulong rt)
+{
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_rnd16_rashift(rth, sa);
+    tempA = mipsdsp_rnd16_rashift(rtl, sa);
+    rd = ((uint32_t)tempB << 16) | (uint32_t) tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shrav_r_ph(target_ulong rs, target_ulong rt)
+{
+    uint8_t  rs3_0;
+    uint16_t rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t rd;
+
+    rs3_0 = rs & 0x0F;
+    rth   = (rt & MIPSDSP_HI) >> 16;
+    rtl   =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_rnd16_rashift(rth, rs3_0);
+    tempA = mipsdsp_rnd16_rashift(rtl, rs3_0);
+
+    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shra_r_w(uint32_t sa, target_ulong rt)
+{
+    uint32_t rd;
+
+    rd = mipsdsp_rnd32_rashift(rt, sa);
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_shrav_r_w(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs4_0;
+    uint32_t rd;
+
+    rs4_0 = rs & 0x1F;
+    rd = mipsdsp_rnd32_rashift(rt, rs4_0);
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_shra_qh(target_ulong rt, uint32_t sa)
+{
+    int32_t rt3, rt2, rt1, rt0;
+    uint32_t tempD, tempC, tempB, tempA;
+    uint64_t result;
+
+    result = 0;
+    sa = sa & 0xF;
+
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_rashift16(rt3, sa);
+    tempC = mipsdsp_rashift16(rt2, sa);
+    tempB = mipsdsp_rashift16(rt1, sa);
+    tempA = mipsdsp_rashift16(rt0, sa);
+
+    result = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+             ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return result;
+}
+
+target_ulong helper_shrav_qh(target_ulong rt, target_ulong sa)
+{
+    int32_t rt3, rt2, rt1, rt0;
+    uint32_t tempD, tempC, tempB, tempA;
+    uint64_t result;
+
+    result = 0;
+    sa = sa & 0xF;
+
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_rashift16(rt3, sa);
+    tempC = mipsdsp_rashift16(rt2, sa);
+    tempB = mipsdsp_rashift16(rt1, sa);
+    tempA = mipsdsp_rashift16(rt0, sa);
+
+    result = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+             ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return result;
+}
+
+
+target_ulong helper_shra_r_qh(target_ulong rt, uint32_t sa)
+{
+    int32_t rt3, rt2, rt1, rt0;
+    uint32_t tempD, tempC, tempB, tempA;
+    uint64_t result;
+
+    result = 0;
+    sa = sa & 0xF;
+
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_rnd16_rashift(rt3, sa);
+    tempC = mipsdsp_rnd16_rashift(rt2, sa);
+    tempB = mipsdsp_rnd16_rashift(rt1, sa);
+    tempA = mipsdsp_rnd16_rashift(rt0, sa);
+
+    result = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+             ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return result;
+}
+
+target_ulong helper_shrav_r_qh(target_ulong rt, target_ulong sa)
+{
+    int32_t rt3, rt2, rt1, rt0;
+    uint32_t tempD, tempC, tempB, tempA;
+    uint64_t result;
+
+    result = 0;
+    sa = sa & 0xF;
+
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_rnd16_rashift(rt3, sa);
+    tempC = mipsdsp_rnd16_rashift(rt2, sa);
+    tempB = mipsdsp_rnd16_rashift(rt1, sa);
+    tempA = mipsdsp_rnd16_rashift(rt0, sa);
+
+    result = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+             ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return result;
+}
+
+target_ulong helper_shra_pw(target_ulong rt, uint32_t sa)
+{
+    int32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t result;
+
+    result = 0;
+
+    /* FIXME, it seems like document error. */
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_rashift32(rt1, sa);
+    tempA = mipsdsp_rashift32(rt0, sa);
+
+    result = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return result;
+}
+
+target_ulong helper_shrav_pw(target_ulong rt, target_ulong sa)
+{
+    int32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t result;
+
+    result = 0;
+    sa = sa & 0x1F;
+
+    /* FIXME, it seems like document error. */
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_rashift32(rt1, sa);
+    tempA = mipsdsp_rashift32(rt0, sa);
+
+    result = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return result;
+}
+
+target_ulong helper_shra_r_pw(target_ulong rt, uint32_t sa)
+{
+    int32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t result;
+
+    result = 0;
+
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_rnd32_rashift(rt1, sa);
+    tempA = mipsdsp_rnd32_rashift(rt0, sa);
+
+    result = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return result;
+}
+
+target_ulong helper_shrav_r_pw(target_ulong rt, target_ulong sa)
+{
+    int32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t result;
+
+    result = 0;
+    sa = sa & 0x1F;
+
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = mipsdsp_rnd32_rashift(rt1, sa);
+    tempA = mipsdsp_rnd32_rashift(rt0, sa);
+
+    result = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return result;
+}
+#endif
+
 #undef MIPSDSP_LHI
 #undef MIPSDSP_LLO
 #undef MIPSDSP_HI
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 0607105..7046380 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -429,4 +429,66 @@ DEF_HELPER_FLAGS_1(preceu_qh_obla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
 DEF_HELPER_FLAGS_1(preceu_qh_obra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
 #endif
 
+/* DSP GPR-Based Shift Sub-class insns */
+DEF_HELPER_FLAGS_3(shll_qb, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(shllv_qb, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(shll_ob, 0, tl, env, tl, i32)
+DEF_HELPER_FLAGS_3(shllv_ob, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(shll_ph, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(shllv_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(shll_s_ph, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(shllv_s_ph, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(shll_qh, 0, tl, env, tl, i32)
+DEF_HELPER_FLAGS_3(shllv_qh, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(shll_s_qh, 0, tl, env, tl, i32)
+DEF_HELPER_FLAGS_3(shllv_s_qh, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(shll_s_w, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(shllv_s_w, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(shll_pw, 0, tl, env, tl, i32)
+DEF_HELPER_FLAGS_3(shllv_pw, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(shll_s_pw, 0, tl, env, tl, i32)
+DEF_HELPER_FLAGS_3(shllv_s_pw, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_2(shrl_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, i32, tl)
+DEF_HELPER_FLAGS_2(shrlv_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(shrl_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, i32, tl)
+DEF_HELPER_FLAGS_2(shrlv_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_2(shrl_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, i32)
+DEF_HELPER_FLAGS_2(shrlv_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(shrl_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, i32)
+DEF_HELPER_FLAGS_2(shrlv_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#endif
+DEF_HELPER_FLAGS_2(shra_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, i32, tl)
+DEF_HELPER_FLAGS_2(shra_r_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, i32, tl)
+DEF_HELPER_FLAGS_2(shrav_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(shrav_r_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_2(shra_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, i32)
+DEF_HELPER_FLAGS_2(shrav_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(shra_r_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, i32)
+DEF_HELPER_FLAGS_2(shrav_r_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#endif
+DEF_HELPER_FLAGS_2(shra_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, i32, tl)
+DEF_HELPER_FLAGS_2(shrav_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(shra_r_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, i32, tl)
+DEF_HELPER_FLAGS_2(shrav_r_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(shra_r_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, i32, tl)
+DEF_HELPER_FLAGS_2(shrav_r_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_2(shra_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, i32)
+DEF_HELPER_FLAGS_2(shrav_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(shra_r_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, i32)
+DEF_HELPER_FLAGS_2(shrav_r_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(shra_pw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, i32)
+DEF_HELPER_FLAGS_2(shrav_pw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(shra_r_pw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, i32)
+DEF_HELPER_FLAGS_2(shrav_r_pw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#endif
+
 #include "def-helper.h"
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 0ea9131..fa26bb1 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -331,6 +331,18 @@ enum {
 #if defined(TARGET_MIPS64)
     OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
 #endif
+    /* MIPS DSP GPR-Based Shift Sub-class */
+    OPC_SHLL_QB_DSP    = 0x13 | OPC_SPECIAL3,
+#if defined(TARGET_MIPS64)
+    OPC_SHLL_OB_DSP    = 0x17 | OPC_SPECIAL3,
+#endif
+    /* MIPS DSP Multiply Sub-class insns */
+    /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP.  */
+    /* OPC_MUL_PH_DSP     = 0x18 | OPC_SPECIAL3,  */
+    OPC_DPA_W_PH_DSP   = 0x30 | OPC_SPECIAL3,
+#if defined(TARGET_MIPS64)
+    OPC_DPAQ_W_QH_DSP  = 0x34 | OPC_SPECIAL3,
+#endif
 };
 
 /* BSHFL opcodes */
@@ -439,6 +451,32 @@ enum {
     OPC_PRECRQ_RS_PH_W   = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
     OPC_PRECRQU_S_QB_PH  = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
 };
+#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP GPR-Based Shift Sub-class */
+    OPC_SHLL_QB    = (0x00 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHLLV_QB   = (0x02 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHLL_PH    = (0x08 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHLLV_PH   = (0x0A << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHLL_S_PH  = (0x0C << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHLL_S_W   = (0x14 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHLLV_S_W  = (0x16 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRL_QB    = (0x01 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRLV_QB   = (0x03 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRL_PH    = (0x19 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRLV_PH   = (0x1B << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRA_QB    = (0x04 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRA_R_QB  = (0x05 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRAV_QB   = (0x06 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRA_PH    = (0x09 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRAV_PH   = (0x0B << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRA_R_PH  = (0x0D << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRA_R_W   = (0x15 << 6) | OPC_SHLL_QB_DSP,
+    OPC_SHRAV_R_W  = (0x17 << 6) | OPC_SHLL_QB_DSP,
+};
 
 #if defined(TARGET_MIPS64)
 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
@@ -507,6 +545,39 @@ enum {
 };
 #endif
 
+#if defined(TARGET_MIPS64)
+#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP GPR-Based Shift Sub-class */
+    OPC_SHLL_PW    = (0x10 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHLL_S_PW  = (0x14 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHLLV_OB   = (0x02 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHLLV_PW   = (0x12 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHLLV_QH   = (0x0A << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRA_PW    = (0x11 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRA_R_PW  = (0x15 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRAV_OB   = (0x06 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRAV_PW   = (0x13 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRAV_QH   = (0x0B << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRLV_OB   = (0x03 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRLV_QH   = (0x1B << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHLL_OB    = (0x00 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHLL_QH    = (0x08 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHLL_S_QH  = (0x0C << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRA_OB    = (0x04 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRA_R_OB  = (0x05 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRA_QH    = (0x09 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRA_R_QH  = (0x0D << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRL_OB    = (0x01 << 6) | OPC_SHLL_OB_DSP,
+    OPC_SHRL_QH    = (0x19 << 6) | OPC_SHLL_OB_DSP,
+};
+#endif
+
 /* Coprocessor 0 (rs field) */
 #define MASK_CP0(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
 
@@ -12619,6 +12690,117 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 break;
             }
             break;
+        case OPC_SHLL_QB_DSP:
+            {
+                TCGv_i32 temp_rs = tcg_const_i32(rs);
+                op2 = MASK_SHLL_QB(ctx->opcode);
+                switch (op2) {
+                case OPC_SHLL_QB:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shll_qb(cpu_gpr[rd], cpu_env,
+                                       temp_rs, cpu_gpr[rt]);
+                    break;
+                case OPC_SHLLV_QB:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shllv_qb(cpu_gpr[rd], cpu_env,
+                                        cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case OPC_SHLL_PH:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shll_ph(cpu_gpr[rd], cpu_env,
+                                       temp_rs, cpu_gpr[rt]);
+                    break;
+                case OPC_SHLLV_PH:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shllv_ph(cpu_gpr[rd], cpu_env,
+                                        cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case OPC_SHLL_S_PH:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shll_s_ph(cpu_gpr[rd], cpu_env,
+                                         temp_rs, cpu_gpr[rt]);
+                    break;
+                case OPC_SHLLV_S_PH:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shllv_s_ph(cpu_gpr[rd], cpu_env,
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case OPC_SHLL_S_W:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shll_s_w(cpu_gpr[rd], cpu_env,
+                                        temp_rs, cpu_gpr[rt]);
+                    break;
+                case OPC_SHLLV_S_W:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shllv_s_w(cpu_gpr[rd], cpu_env,
+                                         cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case OPC_SHRL_QB:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shrl_qb(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                    break;
+                case OPC_SHRLV_QB:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shrlv_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case OPC_SHRL_PH:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_shrl_ph(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                    break;
+                case OPC_SHRLV_PH:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_shrlv_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case OPC_SHRA_QB:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_shra_qb(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                    break;
+                case OPC_SHRA_R_QB:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_shra_r_qb(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                    break;
+                case OPC_SHRAV_QB:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_shrav_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case OPC_SHRAV_R_QB:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_shrav_r_qb(cpu_gpr[rd], cpu_gpr[rs],
+                                          cpu_gpr[rt]);
+                    break;
+                case OPC_SHRA_PH:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shra_ph(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                    break;
+                case OPC_SHRA_R_PH:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shra_r_ph(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                    break;
+                case OPC_SHRAV_PH:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shrav_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case OPC_SHRAV_R_PH:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shrav_r_ph(cpu_gpr[rd], cpu_gpr[rs],
+                                          cpu_gpr[rt]);
+                    break;
+                case OPC_SHRA_R_W:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shra_r_w(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+                    break;
+                case OPC_SHRAV_R_W:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_shrav_r_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                default:            /* Invalid */
+                    MIPS_INVAL("MASK SHLL.QB");
+                    generate_exception(ctx, EXCP_RI);
+                    break;
+                }
+                tcg_temp_free_i32(temp_rs);
+                break;
+            }
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
@@ -12888,6 +13070,183 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             }
             break;
 #endif
+#if defined(TARGET_MIPS64)
+        case OPC_SHLL_OB_DSP:
+            op2 = MASK_SHLL_OB(ctx->opcode);
+            switch (op2) {
+            case OPC_SHLL_PW:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rs);
+                    gen_helper_shll_pw(cpu_gpr[rd], cpu_env,
+                                       cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_SHLLV_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_shllv_pw(cpu_gpr[rd], cpu_env,
+                                    cpu_gpr[rt], cpu_gpr[rs]);
+                break;
+            case OPC_SHLL_S_PW:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rs);
+                    gen_helper_shll_s_pw(cpu_gpr[rd], cpu_env,
+                                         cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_SHLLV_S_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_shllv_s_pw(cpu_gpr[rd], cpu_env,
+                                      cpu_gpr[rt], cpu_gpr[rs]);
+                break;
+            case OPC_SHLL_OB:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rs);
+                    gen_helper_shll_ob(cpu_gpr[rd], cpu_env,
+                                       cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_SHLLV_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_shllv_ob(cpu_gpr[rd], cpu_env,
+                                    cpu_gpr[rt], cpu_gpr[rs]);
+                break;
+            case OPC_SHLL_QH:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rs);
+                    gen_helper_shll_qh(cpu_gpr[rd], cpu_env,
+                                       cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_SHLLV_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_shllv_qh(cpu_gpr[rd], cpu_env,
+                                    cpu_gpr[rt], cpu_gpr[rs]);
+                break;
+            case OPC_SHLL_S_QH:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rs);
+                    gen_helper_shll_s_qh(cpu_gpr[rd], cpu_env,
+                                         cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_SHLLV_S_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_shllv_s_qh(cpu_gpr[rd], cpu_env,
+                                      cpu_gpr[rt], cpu_gpr[rs]);
+                break;
+            case OPC_SHRA_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rs);
+                    gen_helper_shra_ob(cpu_gpr[rd], cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_SHRAV_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_shrav_ob(cpu_gpr[rd], cpu_gpr[rt], cpu_gpr[rs]);
+                break;
+            case OPC_SHRA_R_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rs);
+                    gen_helper_shra_r_ob(cpu_gpr[rd], cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_SHRAV_R_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_shrav_r_ob(cpu_gpr[rd], cpu_gpr[rt], cpu_gpr[rs]);
+                break;
+            case OPC_SHRA_PW:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rs);
+                    gen_helper_shra_pw(cpu_gpr[rd], cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_SHRAV_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_shrav_pw(cpu_gpr[rd], cpu_gpr[rt], cpu_gpr[rs]);
+                break;
+            case OPC_SHRA_R_PW:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rs);
+                    gen_helper_shra_r_pw(cpu_gpr[rd], cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_SHRAV_R_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_shrav_r_pw(cpu_gpr[rd], cpu_gpr[rt], cpu_gpr[rs]);
+                break;
+            case OPC_SHRA_QH:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rs);
+                    gen_helper_shra_qh(cpu_gpr[rd], cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_SHRAV_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_shrav_qh(cpu_gpr[rd], cpu_gpr[rt], cpu_gpr[rs]);
+                break;
+            case OPC_SHRA_R_QH:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rs);
+                    gen_helper_shra_r_qh(cpu_gpr[rd], cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_SHRAV_R_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_shrav_r_qh(cpu_gpr[rd], cpu_gpr[rt], cpu_gpr[rs]);
+                break;
+            case OPC_SHRL_OB:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rs);
+                    gen_helper_shrl_ob(cpu_gpr[rd], cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_SHRLV_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_shrlv_ob(cpu_gpr[rd], cpu_gpr[rt], cpu_gpr[rs]);
+                break;
+            case OPC_SHRL_QH:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rs);
+                    gen_helper_shrl_qh(cpu_gpr[rd], cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_SHRLV_QH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_shrlv_qh(cpu_gpr[rd], cpu_gpr[rt], cpu_gpr[rs]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK SHLL.OB");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+          break;
+#endif
         default:            /* Invalid */
             MIPS_INVAL("special3");
             generate_exception(ctx, EXCP_RI);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v6 07/13] target-mips-ase-dsp: Add multiply instructions
  2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
                   ` (5 preceding siblings ...)
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 06/13] target-mips-ase-dsp: Add GPR Based shift instructions Jia Liu
@ 2012-08-21  6:53 ` Jia Liu
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 08/13] target-mips-ase-dsp: Add bit/manipulation instructions Jia Liu
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Jia Liu @ 2012-08-21  6:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Add MIPS ASE DSP Multiply instructions.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/dsp_helper.c | 2024 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/helper.h     |   91 +++
 target-mips/translate.c  |  503 ++++++++++++
 3 files changed, 2618 insertions(+)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 8e7bccb..ff51d2f 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -4187,6 +4187,2030 @@ target_ulong helper_shrav_r_pw(target_ulong rt, target_ulong sa)
 }
 #endif
 
+/** DSP Multiply Sub-class insns **/
+target_ulong helper_muleu_s_ph_qbl(CPUMIPSState *env,
+                                   target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2;
+    uint16_t tempB, tempA, rth, rtl;
+    uint32_t temp;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_mul_u8_u16(env, rs3, rth);
+    tempA = mipsdsp_mul_u8_u16(env, rs2, rtl);
+    temp = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+    rd = temp;
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_muleu_s_ph_qbr(CPUMIPSState *env,
+                                   target_ulong rs, target_ulong rt)
+{
+    uint8_t  rs1, rs0;
+    uint16_t tempB, tempA;
+    uint16_t rth,   rtl;
+    uint32_t temp;
+    uint32_t rd;
+
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_mul_u8_u16(env, rs1, rth);
+    tempA = mipsdsp_mul_u8_u16(env, rs0, rtl);
+    temp = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+    rd = temp;
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_muleu_s_qh_obl(CPUMIPSState *env,
+                                   target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 56) & MIPSDSP_Q0;
+    rs2 = (rs >> 48) & MIPSDSP_Q0;
+    rs1 = (rs >> 40) & MIPSDSP_Q0;
+    rs0 = (rs >> 32) & MIPSDSP_Q0;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_mul_u8_u16(env, rs3, rt3);
+    tempC = mipsdsp_mul_u8_u16(env, rs2, rt2);
+    tempB = mipsdsp_mul_u8_u16(env, rs1, rt1);
+    tempA = mipsdsp_mul_u8_u16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+    return temp;
+}
+
+target_ulong helper_muleu_s_qh_obr(CPUMIPSState *env,
+                                   target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 24) & MIPSDSP_Q0;
+    rs2 = (rs >> 16) & MIPSDSP_Q0;
+    rs1 = (rs >> 8) & MIPSDSP_Q0;
+    rs0 = rs & MIPSDSP_Q0;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_mul_u8_u16(env, rs3, rt3);
+    tempC = mipsdsp_mul_u8_u16(env, rs2, rt2);
+    tempB = mipsdsp_mul_u8_u16(env, rs1, rt1);
+    tempA = mipsdsp_mul_u8_u16(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+target_ulong helper_mulq_rs_ph(CPUMIPSState *env,
+                               target_ulong rs, target_ulong rt)
+{
+    int16_t tempB, tempA, rsh, rsl, rth, rtl;
+    int32_t temp;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_rndq15_mul_q15_q15(env, rsh, rth);
+    tempA = mipsdsp_rndq15_mul_q15_q15(env, rsl, rtl);
+    temp = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+    rd = temp;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_mulq_rs_qh(CPUMIPSState *env,
+                               target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_rndq15_mul_q15_q15(env, rs3, rt3);
+    tempC = mipsdsp_rndq15_mul_q15_q15(env, rs2, rt2);
+    tempB = mipsdsp_rndq15_mul_q15_q15(env, rs1, rt1);
+    tempA = mipsdsp_rndq15_mul_q15_q15(env, rs0, rt0);
+
+    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+           ((uint64_t)tempB << 16) | (uint64_t)tempA;
+    return temp;
+}
+#endif
+
+target_ulong helper_muleq_s_w_phl(CPUMIPSState *env,
+                                  target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rth;
+    int32_t temp;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    temp = mipsdsp_mul_q15_q15_overflowflag21(env, rsh, rth);
+    rd = temp;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_muleq_s_w_phr(CPUMIPSState *env,
+                                  target_ulong rs, target_ulong rt)
+{
+    int16_t rsl, rtl;
+    int32_t temp;
+    uint32_t rd;
+
+    rsl = rs & MIPSDSP_LO;
+    rtl = rt & MIPSDSP_LO;
+    temp = mipsdsp_mul_q15_q15_overflowflag21(env, rsl, rtl);
+    rd = temp;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_muleq_s_pw_qhl(CPUMIPSState *env,
+                                   target_ulong rs, target_ulong rt)
+{
+    uint16_t rsB, rsA;
+    uint16_t rtB, rtA;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rsB = (rs >> 48) & MIPSDSP_LO;
+    rsA = (rs >> 32) & MIPSDSP_LO;
+    rtB = (rt >> 48) & MIPSDSP_LO;
+    rtA = (rt >> 32) & MIPSDSP_LO;
+
+    tempB = mipsdsp_mul_q15_q15(env, 5, rsB, rtB);
+    tempA = mipsdsp_mul_q15_q15(env, 5, rsA, rtA);
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+
+target_ulong helper_muleq_s_pw_qhr(CPUMIPSState *env,
+                                   target_ulong rs, target_ulong rt)
+{
+    uint16_t rsB, rsA;
+    uint16_t rtB, rtA;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rsB = (rs >> 16) & MIPSDSP_LO;
+    rsA = rs & MIPSDSP_LO;
+    rtB = (rt >> 16) & MIPSDSP_LO;
+    rtA = rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_mul_q15_q15(env, 5, rsB, rtB);
+    tempA = mipsdsp_mul_q15_q15(env, 5, rsA, rtA);
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
+void helper_dpau_h_qbl(CPUMIPSState *env,
+                       uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2;
+    uint8_t rt3, rt2;
+    uint16_t tempB, tempA;
+    uint64_t tempC, tempBL, tempAL, dotp;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    tempB = mipsdsp_mul_u8_u8(rs3, rt3);
+    tempA = mipsdsp_mul_u8_u8(rs2, rt2);
+    tempBL = tempB;
+    tempAL = tempA;
+    dotp = tempBL + tempAL;
+    tempC = (((uint64_t)env->active_tc.HI[ac] << 32) |
+             ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) + dotp;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((tempC & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO);
+}
+
+void helper_dpau_h_qbr(CPUMIPSState *env,
+                       uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    uint8_t rs1, rs0;
+    uint8_t rt1, rt0;
+    uint16_t tempB, tempA;
+    uint64_t tempC, tempBL, tempAL, dotp;
+
+    rs1 = (rs & MIPSDSP_Q1) >> 8;
+    rt1 = (rt & MIPSDSP_Q1) >> 8;
+    rs0 = (rs & MIPSDSP_Q0);
+    rt0 = (rt & MIPSDSP_Q0);
+    tempB = mipsdsp_mul_u8_u8(rs1, rt1);
+    tempA = mipsdsp_mul_u8_u8(rs0, rt0);
+    tempBL = tempB;
+    tempAL = tempA;
+    dotp = tempBL + tempAL;
+    tempC = (((uint64_t)env->active_tc.HI[ac] << 32) |
+             ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) + dotp;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((tempC & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_dpau_h_obl(CPUMIPSState *env,
+                       target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    uint8_t rs7, rs6, rs5, rs4;
+    uint8_t rt7, rt6, rt5, rt4;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp[2];
+    uint64_t acc[2];
+    uint64_t temp_sum;
+
+    temp[0] = 0;
+    temp[1] = 0;
+
+    rs7 = (rs >> 56) & MIPSDSP_Q0;
+    rs6 = (rs >> 48) & MIPSDSP_Q0;
+    rs5 = (rs >> 40) & MIPSDSP_Q0;
+    rs4 = (rs >> 32) & MIPSDSP_Q0;
+    rt7 = (rt >> 56) & MIPSDSP_Q0;
+    rt6 = (rt >> 48) & MIPSDSP_Q0;
+    rt5 = (rt >> 40) & MIPSDSP_Q0;
+    rt4 = (rt >> 32) & MIPSDSP_Q0;
+
+    tempD = mipsdsp_mul_u8_u8(rs7, rt7);
+    tempC = mipsdsp_mul_u8_u8(rs6, rt6);
+    tempB = mipsdsp_mul_u8_u8(rs5, rt5);
+    tempA = mipsdsp_mul_u8_u8(rs4, rt4);
+
+    temp[0] = (uint64_t)tempD + (uint64_t)tempC +
+      (uint64_t)tempB + (uint64_t)tempA;
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = acc[0] + temp[0];
+
+    if (temp_sum < acc[0] && temp_sum < temp[0]) {
+        temp[1] += 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] += acc[1];
+
+    env->active_tc.HI[ac] = temp[1];
+    env->active_tc.LO[ac] = temp[0];
+}
+
+void helper_dpau_h_obr(CPUMIPSState *env,
+                       target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t temp[2];
+    uint64_t acc[2];
+    uint64_t temp_sum;
+
+    temp[0] = 0;
+    temp[1] = 0;
+
+    rs3 = (rs >> 24) & MIPSDSP_Q0;
+    rs2 = (rs >> 16) & MIPSDSP_Q0;
+    rs1 = (rs >> 8) & MIPSDSP_Q0;
+    rs0 = rs & MIPSDSP_Q0;
+    rt3 = (rt >> 24) & MIPSDSP_Q0;
+    rt2 = (rt >> 16) & MIPSDSP_Q0;
+    rt1 = (rt >> 8) & MIPSDSP_Q0;
+    rt0 = rt & MIPSDSP_Q0;
+
+    tempD = mipsdsp_mul_u8_u8(rs3, rt3);
+    tempC = mipsdsp_mul_u8_u8(rs2, rt2);
+    tempB = mipsdsp_mul_u8_u8(rs1, rt1);
+    tempA = mipsdsp_mul_u8_u8(rs0, rt0);
+
+    temp[0] = (uint64_t)tempD + (uint64_t)tempC +
+              (uint64_t)tempB + (uint64_t)tempA;
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = acc[0] + temp[0];
+
+    if (temp_sum < acc[0] && temp_sum < temp[0]) {
+        temp[1] += 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] += acc[1];
+
+    env->active_tc.HI[ac] = temp[1];
+    env->active_tc.LO[ac] = temp[0];
+}
+#endif
+
+void helper_dpsu_h_qbl(CPUMIPSState *env,
+                       uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    uint8_t  rs3, rs2, rt3, rt2;
+    uint16_t tempB,  tempA;
+    uint64_t dotp, tempBL, tempAL, tempC;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+
+    tempB = mipsdsp_mul_u8_u8(rs3, rt3);
+    tempA = mipsdsp_mul_u8_u8(rs2, rt2);
+    tempBL = tempB & 0xFFFF;
+    tempAL = tempA & 0xFFFF;
+
+    dotp   = tempBL + tempAL;
+    tempC  = ((uint64_t)env->active_tc.HI[ac] << 32) |
+             ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    tempC -= dotp;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((tempC & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO);
+}
+
+void helper_dpsu_h_qbr(CPUMIPSState *env,
+                       uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    uint8_t  rs1, rs0, rt1, rt0;
+    uint16_t tempB,  tempA;
+    uint64_t dotp, tempBL, tempAL, tempC;
+
+    rs1 = (rs & MIPSDSP_Q1) >> 8;
+    rs0 = (rs & MIPSDSP_Q0);
+    rt1 = (rt & MIPSDSP_Q1) >> 8;
+    rt0 = (rt & MIPSDSP_Q0);
+
+    tempB = mipsdsp_mul_u8_u8(rs1, rt1);
+    tempA = mipsdsp_mul_u8_u8(rs0, rt0);
+    tempBL = tempB & 0xFFFF;
+    tempAL = tempA & 0xFFFF;
+
+    dotp   = tempBL + tempAL;
+    tempC  = ((uint64_t)env->active_tc.HI[ac] << 32) |
+             ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    tempC -= dotp;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((tempC & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_dpsu_h_obl(CPUMIPSState *env,
+                       target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    uint8_t rs7, rs6, rs5, rs4;
+    uint8_t rt7, rt6, rt5, rt4;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t acc[2];
+    uint64_t temp[2];
+    uint64_t temp_sum;
+
+    temp[0] = 0;
+    temp[1] = 0;
+
+    rs7 = (rs >> 56) & MIPSDSP_Q0;
+    rs6 = (rs >> 48) & MIPSDSP_Q0;
+    rs5 = (rs >> 40) & MIPSDSP_Q0;
+    rs4 = (rs >> 32) & MIPSDSP_Q0;
+    rt7 = (rt >> 56) & MIPSDSP_Q0;
+    rt6 = (rt >> 48) & MIPSDSP_Q0;
+    rt5 = (rt >> 40) & MIPSDSP_Q0;
+    rt4 = (rt >> 32) & MIPSDSP_Q0;
+
+    tempD = mipsdsp_mul_u8_u8(rs7, rt7);
+    tempC = mipsdsp_mul_u8_u8(rs6, rt6);
+    tempB = mipsdsp_mul_u8_u8(rs5, rt5);
+    tempA = mipsdsp_mul_u8_u8(rs4, rt4);
+
+    temp[0] = (uint64_t)tempD + (uint64_t)tempC +
+              (uint64_t)tempB + (uint64_t)tempA;
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = acc[0] - temp[0];
+    if (temp_sum > acc[0]) {
+        acc[1] -= 1;
+    }
+    acc[0] = temp_sum;
+    acc[1] -= temp[1];
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+
+void helper_dpsu_h_obr(CPUMIPSState *env,
+                       target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t acc[2];
+    uint64_t temp[2];
+    uint64_t temp_sum;
+
+    temp[0] = 0;
+    temp[1] = 0;
+
+    rs3 = (rs >> 24) & MIPSDSP_Q0;
+    rs2 = (rs >> 16) & MIPSDSP_Q0;
+    rs1 = (rs >> 8) & MIPSDSP_Q0;
+    rs0 = rs & MIPSDSP_Q0;
+    rt3 = (rt >> 24) & MIPSDSP_Q0;
+    rt2 = (rt >> 16) & MIPSDSP_Q0;
+    rt1 = (rt >> 8) & MIPSDSP_Q0;
+    rt0 = rt & MIPSDSP_Q0;
+
+    tempD = mipsdsp_mul_u8_u8(rs3, rt3);
+    tempC = mipsdsp_mul_u8_u8(rs2, rt2);
+    tempB = mipsdsp_mul_u8_u8(rs1, rt1);
+    tempA = mipsdsp_mul_u8_u8(rs0, rt0);
+
+    temp[0] = (uint64_t)tempD + (uint64_t)tempC +
+              (uint64_t)tempB + (uint64_t)tempA;
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = acc[0] - temp[0];
+    if (temp_sum > acc[0]) {
+        acc[1] -= 1;
+    }
+    acc[0] = temp_sum;
+    acc[1] -= temp[1];
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+#endif
+
+void helper_dpa_w_ph(CPUMIPSState *env,
+                     uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl;
+    int32_t  tempA, tempB;
+    int64_t  acc, tempAL, tempBL;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = (int32_t)rsh * (int32_t)rth;
+    tempA = (int32_t)rsl * (int32_t)rtl;
+    tempBL = tempB;
+    tempAL = tempA;
+
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    acc += tempBL + tempAL;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_dpa_w_qh(CPUMIPSState *env,
+                     target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int32_t rs3, rs2, rs1, rs0;
+    int32_t rt3, rt2, rt1, rt0;
+    int32_t tempD, tempC, tempB, tempA;
+    int64_t acc[2];
+    int64_t temp[2];
+    int64_t temp_sum;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = rs3 * rt3;
+    tempC = rs2 * rt2;
+    tempB = rs1 * rt1;
+    tempA = rs0 * rt0;
+
+    temp[0] = (int64_t)tempD + (int64_t)tempC +
+              (int64_t)tempB + (int64_t)tempA;
+    temp[0] = (int64_t)(temp[0] << 31) >> 31;
+
+    if (((temp[0] >> 63) & 0x01) == 0) {
+        temp[1] = 0;
+    } else {
+        temp[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[1] = env->active_tc.HI[ac];
+    acc[0] = env->active_tc.LO[ac];
+
+    temp_sum = acc[0] + temp[0];
+    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)temp[0])) {
+        temp[1] += 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] += acc[1];
+
+    env->active_tc.HI[ac] = temp[1];
+    env->active_tc.LO[ac] = temp[0];
+}
+#endif
+
+void helper_dpax_w_ph(CPUMIPSState *env,
+                      uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl;
+    int32_t tempB, tempA;
+    int64_t acc, dotp, tempBL, tempAL;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB  = (uint32_t)rsh * (uint32_t)rth;
+    tempA  = (uint32_t)rsl * (uint32_t)rtl;
+    tempBL = tempB;
+    tempAL = tempA;
+    dotp =  tempBL + tempAL;
+    acc  =  ((uint64_t)env->active_tc.HI[ac] << 32) |
+            ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    acc  += dotp;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO);
+}
+
+void helper_dpaq_s_w_ph(CPUMIPSState *env,
+                        uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t tempB, tempA;
+    int64_t acc, dotp, tempBL, tempAL;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_mul_q15_q15(env, ac, rsh, rth);
+    tempA = mipsdsp_mul_q15_q15(env, ac, rsl, rtl);
+    tempBL = tempB;
+    tempAL = tempA;
+    dotp = tempBL + tempAL;
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    acc += dotp;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_dpaq_s_w_qh(CPUMIPSState *env,
+                        target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int32_t rs3, rs2, rs1, rs0;
+    int32_t rt3, rt2, rt1, rt0;
+    int32_t tempD, tempC, tempB, tempA;
+    int64_t temp[2];
+    int64_t acc[2];
+    int64_t temp_sum;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_mul_q15_q15(env, ac, rs3, rt3);
+    tempC = mipsdsp_mul_q15_q15(env, ac, rs2, rt2);
+    tempB = mipsdsp_mul_q15_q15(env, ac, rs1, rt1);
+    tempA = mipsdsp_mul_q15_q15(env, ac, rs0, rt0);
+
+    temp[0] = (int64_t)tempD + (int64_t)tempC +
+              (int64_t)tempB + (int64_t)tempA;
+    if (((temp[0] >> 63) & 0x01) == 0) {
+        temp[1] = 0x00;
+    } else {
+        temp[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = temp[0] + acc[0];
+    if ((temp_sum < temp[0]) && (temp_sum < acc[0])) {
+        temp[1] += 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] += acc[1];
+
+    env->active_tc.HI[ac] = temp[1];
+    env->active_tc.LO[ac] = temp[0];
+}
+#endif
+
+void helper_dpaqx_s_w_ph(CPUMIPSState *env,
+                         uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl;
+    int32_t tempB, tempA;
+    int64_t acc, dotp, tempBL, tempAL;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_mul_q15_q15(env, ac, rsh, rtl);
+    tempA = mipsdsp_mul_q15_q15(env, ac, rsl, rth);
+    tempBL = tempB;
+    tempAL = tempA;
+    dotp = tempBL + tempAL;
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    acc += dotp;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO);
+}
+
+void helper_dpaqx_sa_w_ph(CPUMIPSState *env,
+                          uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t tempB, tempA, tempC62_31, tempC63;
+    int64_t acc, dotp, tempBL, tempAL, tempC;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_mul_q15_q15(env, ac, rsh, rtl);
+    tempA = mipsdsp_mul_q15_q15(env, ac, rsl, rth);
+    tempBL = tempB;
+    tempAL = tempA;
+    dotp = tempBL + tempAL;
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    tempC = acc + dotp;
+    tempC63 = (tempC >> 63) & 0x01;
+    tempC62_31 = (tempC >> 31) & 0xFFFFFFFF;
+
+    if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) {
+        tempC = 0x7FFFFFFF;
+        set_DSPControl_overflow_flag(env, 1, 16 + ac);
+    }
+
+    if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) {
+        tempC = 0xFFFFFFFF80000000ull;
+        set_DSPControl_overflow_flag(env, 1, 16 + ac);
+    }
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((tempC & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO);
+}
+
+void helper_dps_w_ph(CPUMIPSState *env,
+                     uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl;
+    int32_t tempB, tempA;
+    int64_t acc, dotp, tempBL, tempAL;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB  = (int32_t)rsh * (int32_t)rth;
+    tempA  = (int32_t)rsl * (int32_t)rtl;
+    tempBL = tempB;
+    tempAL = tempA;
+    dotp =  tempBL + tempAL;
+    acc  =  ((uint64_t)env->active_tc.HI[ac] << 32) |
+            ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    acc  -= dotp;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_dps_w_qh(CPUMIPSState *env,
+                     target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int16_t rs3, rs2, rs1, rs0;
+    int16_t rt3, rt2, rt1, rt0;
+    int32_t tempD, tempC, tempB, tempA;
+    int64_t acc[2];
+    int64_t temp[2];
+    int64_t temp_sum;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = (int32_t)rs3 * (int32_t)rt3;
+    tempC = (int32_t)rs2 * (int32_t)rt2;
+    tempB = (int32_t)rs1 * (int32_t)rt1;
+    tempA = (int32_t)rs0 * (int32_t)rt0;
+
+    temp[0] = (int64_t)tempD + (int64_t)tempC +
+              (int64_t)tempB + (int64_t)tempA;
+
+    temp[0] = (int64_t)(temp[0] << 31) >> 31;
+    if (((temp[0] >> 32) & 0x01) == 0) {
+        temp[1] = 0x00;
+    } else {
+        temp[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = acc[0] - temp[0];
+    if ((uint64_t)temp_sum > (uint64_t)acc[0]) {
+        acc[1] -= 1;
+    }
+    acc[0] = temp_sum;
+    acc[1] -= temp[1];
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+#endif
+
+void helper_dpsx_w_ph(CPUMIPSState *env,
+                      uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl;
+    int32_t  tempB,  tempA;
+    int64_t acc, dotp, tempBL, tempAL;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = (int32_t)rsh * (int32_t)rtl;
+    tempA = (int32_t)rsl * (int32_t)rth;
+    tempBL = tempB;
+    tempAL = tempA;
+    dotp = tempBL + tempAL;
+
+    acc  = ((uint64_t)env->active_tc.HI[ac] << 32) |
+           ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    acc -= dotp;
+    env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO);
+}
+
+void helper_dpsq_s_w_ph(CPUMIPSState *env,
+                        uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t tempB, tempA;
+    int64_t acc, dotp, tempBL, tempAL;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_mul_q15_q15(env, ac, rsh, rth);
+    tempA = mipsdsp_mul_q15_q15(env, ac, rsl, rtl);
+    tempBL = tempB;
+    tempAL = tempA;
+    dotp = tempBL + tempAL;
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+           ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    acc -= dotp;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_dpsq_s_w_qh(CPUMIPSState *env,
+                        target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int16_t rs3, rs2, rs1, rs0;
+    int16_t rt3, rt2, rt1, rt0;
+    int32_t tempD, tempC, tempB, tempA;
+    int64_t acc[2];
+    int64_t temp[2];
+    int64_t temp_sum;
+
+    temp[0] = 0;
+    temp[1] = 0;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_mul_q15_q15(env, ac, rs3, rt3);
+    tempC = mipsdsp_mul_q15_q15(env, ac, rs2, rt2);
+    tempB = mipsdsp_mul_q15_q15(env, ac, rs1, rt1);
+    tempA = mipsdsp_mul_q15_q15(env, ac, rs0, rt0);
+
+    temp[0] = (int64_t)tempD + (int64_t)tempC +
+              (int64_t)tempB + (int64_t)tempA;
+    if (((temp[0] >> 63) & 0x01) == 0) {
+        temp[1] = 0x00;
+    } else {
+        temp[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = acc[0] - temp[0];
+    if ((uint64_t)temp_sum > (uint64_t)acc[0]) {
+        acc[1] -= 1;
+    }
+    acc[0] = temp_sum;
+    acc[1] -= temp[1];
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+#endif
+
+void helper_dpsqx_s_w_ph(CPUMIPSState *env,
+                         uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t tempB, tempA;
+    int64_t dotp, tempC, tempBL, tempAL;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_mul_q15_q15(env, ac, rsh, rtl);
+    tempA = mipsdsp_mul_q15_q15(env, ac, rsl, rth);
+    tempBL = tempB;
+    tempAL = tempA;
+    dotp = tempBL + tempAL;
+    tempC = (((uint64_t)env->active_tc.HI[ac] << 32) |
+            ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) - dotp;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((tempC & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO);
+}
+
+void helper_dpsqx_sa_w_ph(CPUMIPSState *env,
+                          uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t tempB, tempA, tempC63, tempC62_31;
+    int64_t dotp, tempBL, tempAL, tempC;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_mul_q15_q15(env, ac, rsh, rtl);
+    tempA = mipsdsp_mul_q15_q15(env, ac, rsl, rth);
+
+    tempBL = tempB;
+    tempAL = tempA;
+    dotp   = tempBL + tempAL;
+    tempC  = ((uint64_t)env->active_tc.HI[ac] << 32) |
+             ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    tempC -= dotp;
+
+    tempC63 = (tempC >> 63) & 0x01;
+    tempC62_31 = (tempC >> 31) & 0xFFFFFFFF;
+
+    if ((tempC63 == 0) && (tempC62_31 != 0)) {
+        tempC = 0x7FFFFFFF;
+        set_DSPControl_overflow_flag(env, 1, 16 + ac);
+    }
+
+    if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) {
+        tempC = 0xFFFFFFFF80000000ull;
+        set_DSPControl_overflow_flag(env, 1, 16 + ac);
+    }
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((tempC & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO);
+}
+
+void helper_mulsaq_s_w_ph(CPUMIPSState *env,
+                          uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t tempB, tempA;
+    int64_t tempBL, tempAL, acc, dotp;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_mul_q15_q15(env, ac, rsh, rth);
+    tempA = mipsdsp_mul_q15_q15(env, ac, rsl, rtl);
+    tempBL = tempB;
+    tempAL = tempA;
+    dotp = tempBL - tempAL;
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    dotp = dotp + acc;
+    env->active_tc.HI[ac] = (target_long)(int32_t)((dotp & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(dotp & MIPSDSP_LLO);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_mulsaq_s_w_qh(CPUMIPSState *env,
+                          target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int16_t rs3, rs2, rs1, rs0;
+    int16_t rt3, rt2, rt1, rt0;
+    int32_t tempD, tempC, tempB, tempA;
+    int64_t acc[2];
+    int64_t temp[2];
+    int64_t temp_sum;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_mul_q15_q15(env, ac, rs3, rt3);
+    tempC = mipsdsp_mul_q15_q15(env, ac, rs2, rt2);
+    tempB = mipsdsp_mul_q15_q15(env, ac, rs1, rt1);
+    tempA = mipsdsp_mul_q15_q15(env, ac, rs0, rt0);
+
+    temp[0] = ((int32_t)tempD - (int32_t)tempC) +
+              ((int32_t)tempB - (int32_t)tempA);
+    temp[0] = (int64_t)(temp[0] << 30) >> 30;
+    if (((temp[0] >> 33) & 0x01) == 0) {
+        temp[1] = 0x00;
+    } else {
+        temp[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = acc[0] + temp[0];
+    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)temp[0])) {
+        acc[1] += 1;
+    }
+    acc[0] = temp_sum;
+    acc[1] += temp[1];
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+#endif
+
+void helper_dpaq_sa_l_w(CPUMIPSState *env,
+                        uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    int32_t temp64, temp63, tempacc63, tempdotp63, tempDL63;
+    int64_t dotp, acc;
+    int64_t tempDL[2];
+    uint64_t temp;
+
+    dotp = mipsdsp_mul_q31_q31(env, ac, rs, rt);
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    tempDL[0] = acc + dotp;
+
+    tempacc63  = (acc >> 63) & 0x01;
+    tempdotp63 = (dotp >> 63) & 0x01;
+    tempDL63   = (tempDL[0] >> 63) & 0x01;
+
+    if (((tempacc63 == 1) && (tempdotp63 == 1)) |
+        (((tempacc63 == 1) || (tempdotp63 == 1)) && tempDL63 == 0)) {
+        tempDL[1] = 1;
+    } else {
+        tempDL[1] = 0;
+    }
+
+    temp = tempDL[0];
+    temp64 = tempDL[1] & 0x01;
+    temp63 = (tempDL[0] >> 63) & 0x01;
+
+    if (temp64 != temp63) {
+        if (temp64 == 1) {
+            temp = 0x8000000000000000ull;
+        } else {
+            temp = 0x7FFFFFFFFFFFFFFFull;
+        }
+
+        set_DSPControl_overflow_flag(env, 1, 16 + ac);
+    }
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((temp & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(temp & MIPSDSP_LLO);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_dpaq_sa_l_pw(CPUMIPSState *env,
+                         target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int32_t rs1, rs0;
+    int32_t rt1, rt0;
+    int64_t tempB[2], tempA[2];
+    int64_t temp[2];
+    int64_t acc[2];
+    int64_t temp_sum;
+
+    temp[0] = 0;
+    temp[1] = 0;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB[0] = mipsdsp_mul_q31_q31(env, ac, rs1, rt1);
+    tempA[0] = mipsdsp_mul_q31_q31(env, ac, rs0, rt0);
+
+    if (((tempB[0] >> 63) & 0x01) == 0) {
+        tempB[1] = 0x00;
+    } else {
+        tempB[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    if (((tempA[0] >> 63) & 0x01) == 0) {
+        tempA[1] = 0x00;
+    } else {
+        tempA[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    temp_sum = tempB[0] + tempA[0];
+    if (((uint64_t)temp_sum < (uint64_t)tempB[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)tempA[0])) {
+        temp[1] += 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] += tempB[1] + tempA[1];
+
+    mipsdsp_sat64_acc_add_q63(env, acc, ac, temp);
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+#endif
+
+void helper_dpsq_sa_l_w(CPUMIPSState *env,
+                        uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    int32_t temp64, temp63, tempacc63, tempdotp63, tempDL63;
+    int64_t dotp, acc;
+    int64_t tempDL[2];
+    uint64_t temp;
+
+    dotp = mipsdsp_mul_q31_q31(env, ac, rs, rt);
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    tempDL[0] = acc - dotp;
+
+    tempacc63  = (acc >> 63) & 0x01;
+    tempdotp63 = (dotp >> 63) & 0x01;
+    tempDL63   = (tempDL[0] >> 63) & 0x01;
+
+    if (((tempacc63 == 1) && (tempdotp63 == 0)) |
+        (((tempacc63 == 1) || (tempdotp63 == 0)) && tempDL63 == 0)) {
+        tempDL[1] = 1;
+    } else {
+        tempDL[1] = 0;
+    }
+
+    temp = tempDL[0];
+    temp64 = tempDL[1] & 0x01;
+    temp63 = (tempDL[0] >> 63) & 0x01;
+    if (temp64 != temp63) {
+        if (temp64 == 1) {
+            temp = 0x8000000000000000ull;
+        } else {
+            temp = 0x7FFFFFFFFFFFFFFFull;
+        }
+        set_DSPControl_overflow_flag(env, 1, ac + 16);
+    }
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((temp & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(temp & MIPSDSP_LLO);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_dpsq_sa_l_pw(CPUMIPSState *env,
+                         target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int32_t rs1, rs0;
+    int32_t rt1, rt0;
+    int64_t tempB[2], tempA[2];
+    int64_t temp[2];
+    int64_t acc[2];
+    int64_t temp_sum;
+
+    temp[0] = 0x00;
+    temp[1] = 0x00;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB[0] = mipsdsp_mul_q31_q31(env, ac, rs1, rt1);
+    tempA[0] = mipsdsp_mul_q31_q31(env, ac, rs0, rt0);
+
+    if (((tempB[0] >> 31) & 0x01) == 0) {
+        tempB[1] = 0x00;
+    } else {
+        tempB[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    if (((tempA[0] >> 31) & 0x01) == 0) {
+        tempA[1] = 0x00;
+    } else {
+        tempA[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    temp_sum = tempB[0] + tempA[0];
+    if (((uint64_t)temp_sum < (uint64_t)tempB[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)tempA[0])) {
+        temp[1] += 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] += tempA[1] + tempB[1];
+
+    mipsdsp_sat64_acc_sub_q63(env, acc, ac, temp);
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+
+void helper_mulsaq_s_l_pw(CPUMIPSState *env,
+                          target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int32_t rs1, rs0;
+    int32_t rt1, rt0;
+    int64_t tempB[2], tempA[2];
+    int64_t temp[2];
+    int64_t acc[2];
+    int64_t temp_sum;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB[0] = mipsdsp_mul_q31_q31(env, ac, rs1, rt1);
+    tempA[0] = mipsdsp_mul_q31_q31(env, ac, rs0, rt0);
+
+    if (((tempB[0] >> 63) & 0x01) == 0) {
+        tempB[1] = 0x00;
+    } else {
+        tempB[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    if (((tempA[0] >> 63) & 0x01) == 0) {
+        tempA[1] = 0x00;
+    } else {
+        tempA[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = tempB[0] - tempA[0];
+    if ((uint64_t)temp_sum > (uint64_t)tempB[0]) {
+        tempB[1] -= 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] = tempB[1] - tempA[1];
+
+    if ((temp[1] & 0x01) == 0) {
+        temp[1] = 0x00;
+    } else {
+        temp[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    temp_sum = acc[0] + temp[0];
+    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)temp[0])) {
+        acc[1] += 1;
+    }
+    acc[0] = temp_sum;
+    acc[1] += temp[1];
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+#endif
+
+void helper_maq_s_w_phl(CPUMIPSState *env,
+                        uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rth;
+    int32_t  tempA;
+    int64_t tempL, tempAL, acc;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    tempA  = mipsdsp_mul_q15_q15(env, ac, rsh, rth);
+    tempAL = tempA;
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    tempL  = tempAL + acc;
+    env->active_tc.HI[ac] = (target_long)(int32_t)((tempL & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(tempL & MIPSDSP_LLO);
+}
+
+void helper_maq_s_w_phr(CPUMIPSState *env,
+                        uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    int16_t rsl, rtl;
+    int32_t tempA;
+    int64_t tempL, tempAL, acc;
+
+    rsl = rs & MIPSDSP_LO;
+    rtl = rt & MIPSDSP_LO;
+    tempA  = mipsdsp_mul_q15_q15(env, ac, rsl, rtl);
+    tempAL = tempA;
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    tempL = tempAL + acc;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((tempL & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(tempL & MIPSDSP_LLO);
+}
+
+void helper_maq_sa_w_phl(CPUMIPSState *env, uint32_t ac,
+                         target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rth;
+    int32_t tempA;
+    int64_t tempAL;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    tempA = mipsdsp_mul_q15_q15(env, ac, rsh, rth);
+    tempA = mipsdsp_sat32_acc_q31(env, ac, tempA);
+    tempAL = tempA;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((tempAL & MIPSDSP_LHI) >>
+                                                   32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(tempAL & MIPSDSP_LLO);
+}
+
+void helper_maq_sa_w_phr(CPUMIPSState *env, uint32_t ac,
+                         target_ulong rs, target_ulong rt)
+{
+    int16_t rsl, rtl;
+    int32_t tempA;
+    int64_t tempAL;
+
+    rsl = rs & MIPSDSP_LO;
+    rtl = rt & MIPSDSP_LO;
+
+    tempA = mipsdsp_mul_q15_q15(env, ac, rsl, rtl);
+    tempA = mipsdsp_sat32_acc_q31(env, ac, tempA);
+    tempAL = tempA;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((tempAL & MIPSDSP_LHI) >>
+                                                   32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(tempAL & MIPSDSP_LLO);
+}
+
+/***************************************************************
+ * In manual, GPR[rd](..0) <- tempB(15..0) || tempA(15..0),
+ * I'm not sure its means zero extend or sign extend.
+ * Now treat it as zero extend.
+ ***************************************************************/
+target_ulong helper_mul_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_mul_i16_i16(env, rsh, rth);
+    tempA = mipsdsp_mul_i16_i16(env, rsl, rtl);
+
+    rd = ((tempB & MIPSDSP_LO) << 16) | (tempA & MIPSDSP_LO);
+
+    return (target_ulong)rd;
+}
+
+/***************************************************************
+ * In manual, GPR[rd](..0) <- tempB(15..0) || tempA(15..0),
+ * I'm not sure its means zero extend or sign extend.
+ * Now treat it as zero extend.
+ ***************************************************************/
+target_ulong helper_mul_s_ph(CPUMIPSState *env,
+                             target_ulong rs, target_ulong rt)
+{
+    int16_t  rsh, rsl, rth, rtl;
+    int32_t  tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+    tempB = mipsdsp_sat16_mul_i16_i16(env, rsh, rth);
+    tempA = mipsdsp_sat16_mul_i16_i16(env, rsl, rtl);
+
+    rd = ((tempB & MIPSDSP_LO) << 16) | (tempA & MIPSDSP_LO);
+
+    return (target_ulong)rd;
+}
+
+target_ulong helper_mulq_s_ph(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t temp, tempB, tempA;
+    uint32_t rd;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = mipsdsp_sat16_mul_q15_q15(env, rsh, rth);
+    tempA = mipsdsp_sat16_mul_q15_q15(env, rsl, rtl);
+    temp = ((tempB & MIPSDSP_LO) << 16) | (tempA & MIPSDSP_LO);
+    rd = temp;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_mulq_s_w(CPUMIPSState *env,
+                             target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    int32_t tempI;
+    int64_t tempL;
+
+    if ((rs == 0x80000000) && (rt == 0x80000000)) {
+        tempL = 0x7FFFFFFF00000000ull;
+        set_DSPControl_overflow_flag(env, 1, 21);
+    } else {
+        tempL  = ((int64_t)rs * (int64_t)rt) << 1;
+    }
+    tempI = (tempL & MIPSDSP_LHI) >> 32;
+    rd = tempI;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_mulq_rs_w(CPUMIPSState *env,
+                              target_ulong rs, target_ulong rt)
+{
+    uint32_t rd;
+    uint32_t rs_t, rt_t;
+    uint32_t tempI;
+    int64_t tempL;
+
+    rs_t = rs & MIPSDSP_LLO;
+    rt_t = rt & MIPSDSP_LLO;
+
+    if ((rs_t == 0x80000000) && (rt_t == 0x80000000)) {
+        tempL = 0x7FFFFFFF00000000ull;
+        set_DSPControl_overflow_flag(env, 1, 21);
+    } else {
+        tempL  = ((int64_t)rs_t * (int64_t)rt_t) << 1;
+        tempL += 0x80000000ull;
+    }
+    tempI = (tempL & MIPSDSP_LHI) >> 32;
+    rd = tempI;
+
+    return (target_long)(int32_t)rd;
+}
+
+void helper_mulsa_w_ph(CPUMIPSState *env,
+                       uint32_t ac, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl;
+    int32_t tempB, tempA;
+    int64_t dotp, acc, tempBL, tempAL;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempB = (int32_t)rsh * (int32_t)rth;
+    tempA = (int32_t)rsl * (int32_t)rtl;
+    tempBL = tempB;
+    tempAL = tempA;
+
+    dotp = tempBL - tempAL;
+    acc  = ((int64_t)env->active_tc.HI[ac] << 32) |
+           ((int64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    acc = acc + dotp;
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_maq_s_w_qhll(CPUMIPSState *env,
+                         target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int16_t rs_t, rt_t;
+    int32_t temp_mul;
+    int64_t temp[2];
+    int64_t acc[2];
+    int64_t temp_sum;
+
+    temp[0] = 0;
+    temp[1] = 0;
+
+    rs_t = (rs >> 48) & MIPSDSP_LO;
+    rt_t = (rt >> 48) & MIPSDSP_LO;
+    temp_mul = mipsdsp_mul_q15_q15(env, ac, rs_t, rt_t);
+
+    temp[0] = (int64_t)temp_mul;
+    if (((temp[0] >> 63) & 0x01) == 0) {
+        temp[1] = 0x00;
+    } else {
+        temp[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = acc[0] + temp[0];
+    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)temp[0])) {
+        acc[1] += 1;
+    }
+    acc[0] = temp_sum;
+    acc[1] += temp[1];
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+
+void helper_maq_s_w_qhlr(CPUMIPSState *env,
+                         target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int16_t rs_t, rt_t;
+    int32_t temp_mul;
+    int64_t temp[2];
+    int64_t acc[2];
+    int64_t temp_sum;
+
+    temp[0] = 0;
+    temp[1] = 0;
+
+    rs_t = (rs >> 32) & MIPSDSP_LO;
+    rt_t = (rt >> 32) & MIPSDSP_LO;
+    temp_mul = mipsdsp_mul_q15_q15(env, ac, rs_t, rt_t);
+
+    temp[0] = (int64_t)temp_mul;
+    if (((temp[0] >> 63) & 0x01) == 0) {
+        temp[1] = 0x00;
+    } else {
+        temp[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = acc[0] + temp[0];
+    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)temp[0])) {
+        acc[1] += 1;
+    }
+    acc[0] = temp_sum;
+    acc[1] += temp[1];
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+
+void helper_maq_s_w_qhrl(CPUMIPSState *env,
+                         target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int16_t rs_t, rt_t;
+    int32_t temp_mul;
+    int64_t temp[2];
+    int64_t acc[2];
+    int64_t temp_sum;
+
+    temp[0] = 0;
+    temp[1] = 0;
+
+    rs_t = (rs >> 16) & MIPSDSP_LO;
+    rt_t = (rt >> 16) & MIPSDSP_LO;
+    temp_mul = mipsdsp_mul_q15_q15(env, ac, rs_t, rt_t);
+
+    temp[0] = (int64_t)temp_mul;
+    if (((temp[0] >> 63) & 0x01) == 0) {
+        temp[1] = 0x00;
+    } else {
+        temp[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = acc[0] + temp[0];
+    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)temp[0])) {
+        acc[1] += 1;
+    }
+    acc[0] = temp_sum;
+    acc[1] += temp[1];
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+
+void helper_maq_s_w_qhrr(CPUMIPSState *env,
+                         target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int16_t rs_t, rt_t;
+    int32_t temp_mul;
+    int64_t temp[2];
+    int64_t acc[2];
+    int64_t temp_sum;
+
+    temp[0] = 0;
+    temp[1] = 0;
+
+    rs_t = rs & MIPSDSP_LO;
+    rt_t = rt & MIPSDSP_LO;
+    temp_mul = mipsdsp_mul_q15_q15(env, ac, rs_t, rt_t);
+
+    temp[0] = (int64_t)temp_mul;
+    if (((temp[0] >> 63) & 0x01) == 0) {
+        temp[1] = 0x00;
+    } else {
+        temp[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = acc[0] + temp[0];
+    if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)temp[0])) {
+        acc[1] += 1;
+    }
+    acc[0] = temp_sum;
+    acc[1] += temp[1];
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+
+void helper_maq_sa_w_qhll(CPUMIPSState *env,
+                          target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int16_t rs_t, rt_t;
+    int32_t temp;
+    int64_t acc[2];
+
+    rs_t = (rs >> 48) & MIPSDSP_LO;
+    rt_t = (rt >> 48) & MIPSDSP_LO;
+    temp = mipsdsp_mul_q15_q15(env, ac, rs_t, rt_t);
+    temp = mipsdsp_sat32_acc_q31(env, ac, temp);
+
+    acc[0] = (int64_t)(int32_t)temp;
+    if (((acc[0] >> 63) & 0x01) == 0) {
+        acc[1] = 0x00;
+    } else {
+        acc[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+
+void helper_maq_sa_w_qhlr(CPUMIPSState *env,
+                          target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int16_t rs_t, rt_t;
+    int32_t temp;
+    int64_t acc[2];
+
+    rs_t = (rs >> 32) & MIPSDSP_LO;
+    rt_t = (rt >> 32) & MIPSDSP_LO;
+    temp = mipsdsp_mul_q15_q15(env, ac, rs_t, rt_t);
+    temp = mipsdsp_sat32_acc_q31(env, ac, temp);
+
+    acc[0] = (int64_t)temp;
+    if (((acc[0] >> 63) & 0x01) == 0) {
+        acc[1] = 0x00;
+    } else {
+        acc[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+
+void helper_maq_sa_w_qhrl(CPUMIPSState *env,
+                          target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int16_t rs_t, rt_t;
+    int32_t temp;
+    int64_t acc[2];
+
+    rs_t = (rs >> 16) & MIPSDSP_LO;
+    rt_t = (rt >> 16) & MIPSDSP_LO;
+    temp = mipsdsp_mul_q15_q15(env, ac, rs_t, rt_t);
+    temp = mipsdsp_sat32_acc_q31(env, ac, temp);
+
+    acc[0] = (int64_t)temp;
+    if (((acc[0] >> 63) & 0x01) == 0) {
+        acc[1] = 0x00;
+    } else {
+        acc[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+
+void helper_maq_sa_w_qhrr(CPUMIPSState *env,
+                          target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int16_t rs_t, rt_t;
+    int32_t temp;
+    int64_t acc[2];
+
+    rs_t = rs & MIPSDSP_LO;
+    rt_t = rt & MIPSDSP_LO;
+    temp = mipsdsp_mul_q15_q15(env, ac, rs_t, rt_t);
+    temp = mipsdsp_sat32_acc_q31(env, ac, temp);
+
+    acc[0] = (int64_t)temp;
+    if (((acc[0] >> 63) & 0x01) == 0) {
+        acc[1] = 0x00;
+    } else {
+        acc[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+
+void helper_maq_s_l_pwl(CPUMIPSState *env,
+                        target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int32_t rs_t, rt_t;
+    int64_t temp[2];
+    int64_t acc[2];
+    int64_t temp_sum;
+
+    temp[0] = 0;
+    temp[1] = 0;
+
+    rs_t = (rs >> 32) & MIPSDSP_LLO;
+    rt_t = (rt >> 32) & MIPSDSP_LLO;
+
+    temp[0] = mipsdsp_mul_q31_q31(env, ac, rs_t, rt_t);
+    if (((temp[0] >> 63) & 0x01) == 0) {
+        temp[1] = 0x00;
+    } else {
+        temp[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = acc[0] + temp[0];
+    if (((uint64_t)temp_sum < (uint64_t)temp[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)acc[0])) {
+        acc[1] += 1;
+    }
+    acc[0] = temp_sum;
+    acc[1] += temp[1];
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+
+void helper_maq_s_l_pwr(CPUMIPSState *env,
+                        target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int32_t rs_t, rt_t;
+    int64_t temp[2];
+    int64_t acc[2];
+    int64_t temp_sum;
+
+    temp[0] = 0;
+    temp[1] = 0;
+
+    rs_t = rs & MIPSDSP_LLO;
+    rt_t = rt & MIPSDSP_LLO;
+
+    temp[0] = mipsdsp_mul_q31_q31(env, ac, rs_t, rt_t);
+    if (((temp[0] >> 63) & 0x01) == 0) {
+        temp[1] = 0x00;
+    } else {
+        temp[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+
+    temp_sum = acc[0] + temp[0];
+    if (((uint64_t)temp_sum < (uint64_t)temp[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)acc[0])) {
+        acc[1] += 1;
+    }
+    acc[0] = temp_sum;
+    acc[1] += temp[1];
+
+    env->active_tc.HI[ac] = acc[1];
+    env->active_tc.LO[ac] = acc[0];
+}
+
+void helper_dmadd(CPUMIPSState *env,
+                  target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int32_t rs1, rs0;
+    int32_t rt1, rt0;
+    int32_t tempB, tempA;
+    int64_t tempBL[2], tempAL[2];
+    int64_t acc[2];
+    int64_t temp[2];
+    int64_t temp_sum;
+
+    temp[0] = 0x00;
+    temp[1] = 0x00;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = rs1 * rt1;
+    tempA = rs0 * rt0;
+
+    tempBL[0] = (int64_t)tempB;
+    tempAL[0] = (int64_t)tempA;
+
+    if (((tempBL[0] >> 63) & 0x01) == 0) {
+        tempBL[1] = 0x0;
+    } else {
+        tempBL[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    if (((tempAL[0] >> 63) & 0x01) == 0) {
+        tempAL[1] = 0x0;
+    } else {
+        tempAL[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[1] = env->active_tc.HI[ac];
+    acc[0] = env->active_tc.LO[ac];
+
+    temp_sum = tempBL[0] + tempAL[0];
+    if (((uint64_t)temp_sum < (uint64_t)tempBL[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)tempAL[0])) {
+        temp[1] += 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] += tempBL[1] + tempAL[1];
+
+    temp_sum = temp[0] + acc[0];
+    if (((uint64_t)temp_sum < (uint64_t)temp[0]) &&
+       ((uint64_t)temp_sum < (uint64_t)acc[0])) {
+        temp[1] += 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] += acc[1];
+
+    env->active_tc.HI[ac] = temp[1];
+    env->active_tc.LO[ac] = temp[0];
+}
+
+void helper_dmaddu(CPUMIPSState *env,
+                   target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint64_t tempBL[2], tempAL[2];
+    uint64_t acc[2];
+    uint64_t temp[2];
+    uint64_t temp_sum;
+
+    temp[0] = 0x00;
+    temp[1] = 0x00;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempBL[0] = mipsdsp_mul_u32_u32(env, rs1, rt1);
+    tempAL[0] = mipsdsp_mul_u32_u32(env, rs0, rt0);
+    tempBL[1] = 0;
+    tempAL[1] = 0;
+
+    acc[1] = env->active_tc.HI[ac];
+    acc[0] = env->active_tc.LO[ac];
+
+    temp_sum = tempBL[0] + tempAL[0];
+    if ((temp_sum < tempBL[0]) && (temp_sum < tempAL[0])) {
+        temp[1] += 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] += tempBL[1] + tempAL[1];
+
+    temp_sum = temp[0] + acc[0];
+    if ((temp_sum < temp[0]) && (temp_sum < acc[0])) {
+        temp[1] += 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] += acc[1];
+
+    env->active_tc.HI[ac] = temp[1];
+    env->active_tc.LO[ac] = temp[0];
+}
+
+void helper_dmsub(CPUMIPSState *env,
+                  target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    int32_t rs1, rs0;
+    int32_t rt1, rt0;
+    int32_t tempB, tempA;
+    int64_t tempBL[2], tempAL[2];
+    int64_t acc[2];
+    int64_t temp[2];
+    int64_t temp_sum;
+
+    temp[0] = 0x00;
+    temp[1] = 0x00;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempB = rs1 * rt1;
+    tempA = rs0 * rt0;
+
+    tempBL[0] = (int64_t)tempB;
+    tempAL[0] = (int64_t)tempA;
+
+    if (((tempBL[0] >> 63) & 0x01) == 0) {
+        tempBL[1] = 0x0;
+    } else {
+        tempBL[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    if (((tempAL[0] >> 63) & 0x01) == 0) {
+        tempAL[1] = 0x0;
+    } else {
+        tempAL[1] = 0xFFFFFFFFFFFFFFFFull;
+    }
+
+    acc[1] = env->active_tc.HI[ac];
+    acc[0] = env->active_tc.LO[ac];
+
+    temp_sum = acc[0] - tempBL[0];
+    if ((uint64_t)temp_sum > (uint64_t)acc[0]) {
+        temp[1] -= 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] += acc[1] - tempBL[1];
+
+    temp_sum = temp[0] - tempAL[0];
+    if ((uint64_t)temp_sum > (uint64_t)temp[0]) {
+        temp[1] -= 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] -= tempAL[1];
+
+    env->active_tc.HI[ac] = temp[1];
+    env->active_tc.LO[ac] = temp[0];
+}
+
+void helper_dmsubu(CPUMIPSState *env,
+                   target_ulong rs, target_ulong rt, uint32_t ac)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint64_t tempBL[2], tempAL[2];
+    uint64_t acc[2];
+    uint64_t temp[2];
+    uint64_t temp_sum;
+
+    temp[0] = 0x00;
+    temp[1] = 0x00;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempBL[0] = mipsdsp_mul_u32_u32(env, rs1, rt1);
+    tempAL[0] = mipsdsp_mul_u32_u32(env, rs0, rt0);
+    tempBL[1] = 0;
+    tempAL[1] = 0;
+
+    acc[1] = env->active_tc.HI[ac];
+    acc[0] = env->active_tc.LO[ac];
+
+    temp_sum = acc[0] - tempBL[0];
+    if (temp_sum > acc[0]) {
+        temp[1] -= 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] += acc[1] - tempBL[1];
+
+    temp_sum = temp[0] - tempAL[0];
+    if ((uint64_t)temp_sum > (uint64_t)temp[0]) {
+        temp[1] -= 1;
+    }
+    temp[0] = temp_sum;
+    temp[1] -= tempAL[1];
+
+    env->active_tc.HI[ac] = temp[1];
+    env->active_tc.LO[ac] = temp[0];
+}
+#endif
+
 #undef MIPSDSP_LHI
 #undef MIPSDSP_LLO
 #undef MIPSDSP_HI
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 7046380..69bcb6c 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -491,4 +491,95 @@ DEF_HELPER_FLAGS_2(shra_r_pw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, i32)
 DEF_HELPER_FLAGS_2(shrav_r_pw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
 #endif
 
+/* DSP Multiply Sub-class insns */
+DEF_HELPER_FLAGS_3(muleu_s_ph_qbl, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(muleu_s_ph_qbr, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(muleu_s_qh_obl, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(muleu_s_qh_obr, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(mulq_rs_ph, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(mulq_rs_qh, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(muleq_s_w_phl, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(muleq_s_w_phr, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(muleq_s_pw_qhl, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(muleq_s_pw_qhr, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_4(dpau_h_qbl, 0, void, env, i32, tl, tl)
+DEF_HELPER_FLAGS_4(dpau_h_qbr, 0, void, env, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpau_h_obl, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(dpau_h_obr, 0, void, env, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_4(dpsu_h_qbl, 0, void, env, i32, tl, tl)
+DEF_HELPER_FLAGS_4(dpsu_h_qbr, 0, void, env, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpsu_h_obl, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(dpsu_h_obr, 0, void, env, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_4(dpa_w_ph, 0, void, env, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpa_w_qh, 0, void, env, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_4(dpax_w_ph, 0, void, env, i32, tl, tl)
+DEF_HELPER_FLAGS_4(dpaq_s_w_ph, 0, void, env, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpaq_s_w_qh, 0, void, env, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_4(dpaqx_s_w_ph, 0, void, env, i32, tl, tl)
+DEF_HELPER_FLAGS_4(dpaqx_sa_w_ph, 0, void, env, i32, tl, tl)
+DEF_HELPER_FLAGS_4(dps_w_ph, 0, void, env, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dps_w_qh, 0, void, env, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_4(dpsx_w_ph, 0, void, env, i32, tl, tl)
+DEF_HELPER_FLAGS_4(dpsq_s_w_ph, 0, void, env, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpsq_s_w_qh, 0, void, env, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_4(dpsqx_s_w_ph, 0, void, env, i32, tl, tl)
+DEF_HELPER_FLAGS_4(dpsqx_sa_w_ph, 0, void, env, i32, tl, tl)
+DEF_HELPER_FLAGS_4(mulsaq_s_w_ph, 0, void, env, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(mulsaq_s_w_qh, 0, void, env, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_4(dpaq_sa_l_w, 0, void, env, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpaq_sa_l_pw, 0, void, env, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_4(dpsq_sa_l_w, 0, void, env, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpsq_sa_l_pw, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(mulsaq_s_l_pw, 0, void, env, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_4(maq_s_w_phl, 0, void, env, i32, tl, tl)
+DEF_HELPER_FLAGS_4(maq_s_w_phr, 0, void, env, i32, tl, tl)
+DEF_HELPER_FLAGS_4(maq_sa_w_phl, 0, void, env, i32, tl, tl)
+DEF_HELPER_FLAGS_4(maq_sa_w_phr, 0, void, env, i32, tl, tl)
+DEF_HELPER_FLAGS_3(mul_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(mul_s_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(mulq_s_ph, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(mulq_s_w, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(mulq_rs_w, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_4(mulsa_w_ph, 0, void, env, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(maq_s_w_qhll, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(maq_s_w_qhlr, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(maq_s_w_qhrl, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(maq_s_w_qhrr, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(maq_sa_w_qhll, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(maq_sa_w_qhlr, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(maq_sa_w_qhrl, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(maq_sa_w_qhrr, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(maq_s_l_pwl, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(maq_s_l_pwr, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(dmadd, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(dmaddu, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(dmsub, 0, void, env, tl, tl, i32)
+DEF_HELPER_FLAGS_4(dmsubu, 0, void, env, tl, tl, i32)
+#endif
+
 #include "def-helper.h"
diff --git a/target-mips/translate.c b/target-mips/translate.c
index fa26bb1..d8f83e0 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -402,6 +402,13 @@ enum {
     OPC_ADDWC          = (0x11 << 6) | OPC_ADDU_QB_DSP,
     OPC_MODSUB         = (0x12 << 6) | OPC_ADDU_QB_DSP,
     OPC_RADDU_W_QB     = (0x14 << 6) | OPC_ADDU_QB_DSP,
+    /* MIPS DSP Multiply Sub-class insns */
+    OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
+    OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
+    OPC_MULQ_RS_PH     = (0x1F << 6) | OPC_ADDU_QB_DSP,
+    OPC_MULEQ_S_W_PHL  = (0x1C << 6) | OPC_ADDU_QB_DSP,
+    OPC_MULEQ_S_W_PHR  = (0x1D << 6) | OPC_ADDU_QB_DSP,
+    OPC_MULQ_S_PH      = (0x1E << 6) | OPC_ADDU_QB_DSP,
 };
 
 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
@@ -420,6 +427,11 @@ enum {
     OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
     OPC_SUBQH_W    = (0x11 << 6) | OPC_ADDUH_QB_DSP,
     OPC_SUBQH_R_W  = (0x13 << 6) | OPC_ADDUH_QB_DSP,
+    /* MIPS DSP Multiply Sub-class insns */
+    OPC_MUL_PH     = (0x0C << 6) | OPC_ADDUH_QB_DSP,
+    OPC_MUL_S_PH   = (0x0E << 6) | OPC_ADDUH_QB_DSP,
+    OPC_MULQ_S_W   = (0x16 << 6) | OPC_ADDUH_QB_DSP,
+    OPC_MULQ_RS_W  = (0x17 << 6) | OPC_ADDUH_QB_DSP,
 };
 
 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
@@ -451,6 +463,7 @@ enum {
     OPC_PRECRQ_RS_PH_W   = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
     OPC_PRECRQU_S_QB_PH  = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
 };
+
 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
     /* MIPS DSP GPR-Based Shift Sub-class */
@@ -478,6 +491,33 @@ enum {
     OPC_SHRAV_R_W  = (0x17 << 6) | OPC_SHLL_QB_DSP,
 };
 
+#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Multiply Sub-class insns */
+    OPC_DPAU_H_QBL    = (0x03 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPAU_H_QBR    = (0x07 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPSU_H_QBL    = (0x0B << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPSU_H_QBR    = (0x0F << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPA_W_PH      = (0x00 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPAX_W_PH     = (0x08 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPAQ_S_W_PH   = (0x04 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPAQX_S_W_PH  = (0x18 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPS_W_PH      = (0x01 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPSX_W_PH          = (0x09 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPSQ_S_W_PH   = (0x05 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPSQX_S_W_PH  = (0x19 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
+    OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPAQ_SA_L_W   = (0x0C << 6) | OPC_DPA_W_PH_DSP,
+    OPC_DPSQ_SA_L_W   = (0x0D << 6) | OPC_DPA_W_PH_DSP,
+    OPC_MAQ_S_W_PHL   = (0x14 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_MAQ_S_W_PHR   = (0x16 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_MAQ_SA_W_PHL  = (0x10 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_MAQ_SA_W_PHR  = (0x12 << 6) | OPC_DPA_W_PH_DSP,
+    OPC_MULSA_W_PH    = (0x02 << 6) | OPC_DPA_W_PH_DSP,
+};
+
 #if defined(TARGET_MIPS64)
 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
@@ -505,6 +545,12 @@ enum {
 #if defined(TARGET_MIPS64)
 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
+    /* MIPS DSP Multiply Sub-class insns */
+    OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
+    OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
+    OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
+    OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
+    OPC_MULQ_RS_QH     = (0x1F << 6) | OPC_ADDU_OB_DSP,
     /* MIPS DSP Arithmetic Sub-class */
     OPC_RADDU_L_OB     = (0x14 << 6) | OPC_ADDU_OB_DSP,
     OPC_SUBQ_PW        = (0x13 << 6) | OPC_ADDU_OB_DSP,
@@ -546,6 +592,39 @@ enum {
 #endif
 
 #if defined(TARGET_MIPS64)
+#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Multiply Sub-class insns */
+    OPC_DMADD         = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_DMADDU        = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_DMSUB         = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_DMSUBU        = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_DPA_W_QH      = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_DPAQ_S_W_QH   = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_DPAQ_SA_L_PW  = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_DPAU_H_OBL    = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_DPAU_H_OBR    = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_DPS_W_QH      = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_DPSQ_S_W_QH   = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_DPSQ_SA_L_PW  = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_DPSU_H_OBL    = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_DPSU_H_OBR    = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_MAQ_S_L_PWL   = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_MAQ_S_L_PWR   = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_MAQ_S_W_QHLL  = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_MAQ_S_W_QHLR  = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_MAQ_S_W_QHRL  = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_MAQ_S_W_QHRR  = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
+    OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
+};
+#endif
+
+#if defined(TARGET_MIPS64)
 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
     /* MIPS DSP GPR-Based Shift Sub-class */
@@ -12416,6 +12495,22 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                     check_insn(env, ctx, ASE_DSPR2);
                     gen_helper_subqh_r_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
                     break;
+                case  OPC_MUL_PH:
+                    gen_helper_mul_ph(cpu_gpr[rd], cpu_env,
+                                      cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case  OPC_MUL_S_PH:
+                    gen_helper_mul_s_ph(cpu_gpr[rd], cpu_env,
+                                        cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case OPC_MULQ_S_W:
+                    gen_helper_mulq_s_w(cpu_gpr[rd], cpu_env,
+                                        cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                case OPC_MULQ_RS_W:
+                    gen_helper_mulq_rs_w(cpu_gpr[rd], cpu_env,
+                                         cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
                 default:
                     is_mult_g_2e = 1;
                     break;
@@ -12635,6 +12730,36 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 check_insn(env, ctx, ASE_DSP);
                 gen_helper_raddu_w_qb(cpu_gpr[rd], cpu_gpr[rs]);
                 break;
+            case OPC_MULEU_S_PH_QBL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_muleu_s_ph_qbl(cpu_gpr[rd], cpu_env,
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_MULEU_S_PH_QBR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_muleu_s_ph_qbr(cpu_gpr[rd], cpu_env,
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_MULQ_RS_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_mulq_rs_ph(cpu_gpr[rd], cpu_env,
+                                      cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_MULEQ_S_W_PHL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_muleq_s_w_phl(cpu_gpr[rd], cpu_env,
+                                         cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_MULEQ_S_W_PHR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_muleq_s_w_phr(cpu_gpr[rd], cpu_env,
+                                         cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_MULQ_S_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_mulq_s_ph(cpu_gpr[rd], cpu_env,
+                                     cpu_gpr[rs], cpu_gpr[rt]);
+                break;
             default:            /* Invalid */
                 MIPS_INVAL("MASK ADDU.QB");
                 generate_exception(ctx, EXCP_RI);
@@ -12801,6 +12926,213 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 tcg_temp_free_i32(temp_rs);
                 break;
             }
+        case OPC_DPA_W_PH_DSP:
+            op2 = MASK_DPA_W_PH(ctx->opcode);
+            switch (op2) {
+            case OPC_DPAU_H_QBL:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpau_h_qbl(cpu_env, temp_rd,
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPAU_H_QBR:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpau_h_qbr(cpu_env, temp_rd,
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPSU_H_QBL:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpsu_h_qbl(cpu_env, temp_rd,
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPSU_H_QBR:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpsu_h_qbr(cpu_env, temp_rd,
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPA_W_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpa_w_ph(cpu_env, temp_rd,
+                                        cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPAX_W_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpax_w_ph(cpu_env, temp_rd,
+                                         cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPAQ_S_W_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpaq_s_w_ph(cpu_env, temp_rd,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPAQX_S_W_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpaqx_s_w_ph(cpu_env, temp_rd,
+                                            cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPAQX_SA_W_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpaqx_sa_w_ph(cpu_env, temp_rd,
+                                             cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPS_W_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dps_w_ph(cpu_env, temp_rd,
+                                        cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPSX_W_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpsx_w_ph(cpu_env, temp_rd,
+                                         cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPSQ_S_W_PH:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpsq_s_w_ph(cpu_env, temp_rd,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPSQX_S_W_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpsqx_s_w_ph(cpu_env, temp_rd,
+                                            cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPSQX_SA_W_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpsqx_sa_w_ph(cpu_env, temp_rd,
+                                             cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_MULSAQ_S_W_PH:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_mulsaq_s_w_ph(cpu_env, temp_rd,
+                                             cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPAQ_SA_L_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpaq_sa_l_w(cpu_env, temp_rd,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_DPSQ_SA_L_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_dpsq_sa_l_w(cpu_env, temp_rd,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_MAQ_S_W_PHL:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_maq_s_w_phl(cpu_env, temp_rd,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_MAQ_S_W_PHR:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_maq_s_w_phr(cpu_env, temp_rd,
+                                           cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_MAQ_SA_W_PHL:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_maq_sa_w_phl(cpu_env, temp_rd,
+                                            cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_MAQ_SA_W_PHR:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_maq_sa_w_phr(cpu_env, temp_rd,
+                                            cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_MULSA_W_PH:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_mulsa_w_ph(cpu_env, temp_rd,
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            default:            /* Invalid */
+                MIPS_INVAL("MASK DPAW.PH");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
@@ -12904,6 +13236,31 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_ADDU_OB_DSP:
             op2 = MASK_ADDU_OB(ctx->opcode);
             switch (op2) {
+            case OPC_MULEQ_S_PW_QHL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_muleq_s_pw_qhl(cpu_gpr[rd], cpu_env,
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_MULEQ_S_PW_QHR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_muleq_s_pw_qhr(cpu_gpr[rd], cpu_env,
+                                          cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_MULEU_S_QH_OBL:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_muleu_s_qh_obl(cpu_gpr[rd],
+                                          cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_MULEU_S_QH_OBR:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_muleu_s_qh_obr(cpu_gpr[rd],
+                                          cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_MULQ_RS_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_mulq_rs_qh(cpu_gpr[rd], cpu_env,
+                                      cpu_gpr[rs], cpu_gpr[rt]);
+                break;
             case OPC_RADDU_L_OB:
                 check_insn(env, ctx, ASE_DSP);
                 gen_helper_raddu_l_ob(cpu_gpr[rd], cpu_gpr[rs]);
@@ -13071,6 +13428,152 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             break;
 #endif
 #if defined(TARGET_MIPS64)
+        case OPC_DPAQ_W_QH_DSP:
+            {
+                int ac = rd & 0x03;
+                TCGv_i32 ac_v = tcg_const_i32(ac);
+
+                op2 = MASK_DPAQ_W_QH(ctx->opcode);
+
+                switch (op2) {
+                case OPC_DMADD:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_dmadd(cpu_env, cpu_gpr[rs], cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_DMADDU:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_dmaddu(cpu_env, cpu_gpr[rs],
+                                      cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_DMSUB:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_dmsub(cpu_env, cpu_gpr[rs], cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_DMSUBU:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_dmsubu(cpu_env, cpu_gpr[rs],
+                                      cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_DPA_W_QH:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_dpa_w_qh(cpu_env, cpu_gpr[rs],
+                                        cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_DPAQ_S_W_QH:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_dpaq_s_w_qh(cpu_env, cpu_gpr[rs],
+                                           cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_DPAQ_SA_L_PW:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_dpaq_sa_l_pw(cpu_env, cpu_gpr[rs],
+                                            cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_DPAU_H_OBL:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_dpau_h_obl(cpu_env, cpu_gpr[rs],
+                                          cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_DPAU_H_OBR:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_dpau_h_obr(cpu_env, cpu_gpr[rs],
+                                          cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_DPS_W_QH:
+                    check_insn(env, ctx, ASE_DSPR2);
+                    gen_helper_dps_w_qh(cpu_env, cpu_gpr[rs],
+                                        cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_DPSQ_S_W_QH:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_dpsq_s_w_qh(cpu_env, cpu_gpr[rs],
+                                           cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_DPSQ_SA_L_PW:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_dpsq_sa_l_pw(cpu_env, cpu_gpr[rs],
+                                            cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_DPSU_H_OBL:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_dpsu_h_obl(cpu_env, cpu_gpr[rs],
+                                          cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_DPSU_H_OBR:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_dpsu_h_obr(cpu_env, cpu_gpr[rs],
+                                          cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_MAQ_S_L_PWL:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_maq_s_l_pwl(cpu_env, cpu_gpr[rs],
+                                           cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_MAQ_S_L_PWR:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_maq_s_l_pwr(cpu_env, cpu_gpr[rs],
+                                           cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_MAQ_S_W_QHLL:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_maq_s_w_qhll(cpu_env, cpu_gpr[rs],
+                                            cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_MAQ_SA_W_QHLL:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_maq_sa_w_qhll(cpu_env, cpu_gpr[rs],
+                                             cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_MAQ_S_W_QHLR:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_maq_s_w_qhlr(cpu_env, cpu_gpr[rs],
+                                            cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_MAQ_SA_W_QHLR:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_maq_sa_w_qhlr(cpu_env, cpu_gpr[rs],
+                                             cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_MAQ_S_W_QHRL:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_maq_s_w_qhrl(cpu_env, cpu_gpr[rs],
+                                            cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_MAQ_SA_W_QHRL:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_maq_sa_w_qhrl(cpu_env, cpu_gpr[rs],
+                                             cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_MAQ_S_W_QHRR:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_maq_s_w_qhrr(cpu_env, cpu_gpr[rs],
+                                            cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_MAQ_SA_W_QHRR:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_maq_sa_w_qhrr(cpu_env, cpu_gpr[rs],
+                                             cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_MULSAQ_S_L_PW:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_mulsaq_s_l_pw(cpu_env, cpu_gpr[rs],
+                                             cpu_gpr[rt], ac_v);
+                    break;
+                case OPC_MULSAQ_S_W_QH:
+                    check_insn(env, ctx, ASE_DSP);
+                    gen_helper_mulsaq_s_w_qh(cpu_env, cpu_gpr[rs],
+                                             cpu_gpr[rt], ac_v);
+                    break;
+                default:            /* Invalid */
+                    MIPS_INVAL("MASK DPAQ.W.QH");
+                    generate_exception(ctx, EXCP_RI);
+                    break;
+                }
+                tcg_temp_free_i32(ac_v);
+                break;
+            }
+#endif
+#if defined(TARGET_MIPS64)
         case OPC_SHLL_OB_DSP:
             op2 = MASK_SHLL_OB(ctx->opcode);
             switch (op2) {
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v6 08/13] target-mips-ase-dsp: Add bit/manipulation instructions
  2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
                   ` (6 preceding siblings ...)
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 07/13] target-mips-ase-dsp: Add multiply instructions Jia Liu
@ 2012-08-21  6:53 ` Jia Liu
  2012-08-23 14:48   ` Aurelien Jarno
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 09/13] target-mips-ase-dsp: Add compare pick instructions Jia Liu
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 20+ messages in thread
From: Jia Liu @ 2012-08-21  6:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Add MIPS ASE DSP Bit/Manipulation instructions.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/dsp_helper.c |   79 +++++++++++++
 target-mips/helper.h     |    7 ++
 target-mips/translate.c  |  289 +++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 374 insertions(+), 1 deletion(-)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index ff51d2f..4564d9c 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -6211,6 +6211,85 @@ void helper_dmsubu(CPUMIPSState *env,
 }
 #endif
 
+/** DSP Bit/Manipulation Sub-class insns **/
+target_ulong helper_bitrev(target_ulong rt)
+{
+    int32_t temp;
+    uint32_t rd;
+    int i, last;
+
+    temp = rt & MIPSDSP_LO;
+    rd = 0;
+    for (i = 0; i < 16; i++) {
+        last = temp % 2;
+        temp = temp >> 1;
+        rd = rd | (last << (15 - i));
+    }
+
+    return (target_ulong)rd;
+}
+
+target_ulong helper_insv(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t pos, size, msb, lsb, rs_f, rt_f;
+    uint32_t temp, temprs, temprt;
+    uint32_t rs_notword, rt_notword;
+    target_ulong dspc;
+
+    dspc = env->active_tc.DSPControl;
+    pos  = dspc & 0x1F;
+    size = (dspc >> 7) & 0x1F;
+    msb  = pos + size - 1;
+    lsb  = pos;
+
+    rs_notword = not_word_value(rs);
+    rt_notword = not_word_value(rt);
+
+    if ((lsb > msb) || (rs_notword == 1) || (rt_notword == 1)) {
+        return rt;
+    }
+
+    rs_f = (((int32_t)0x01 << (msb - lsb + 1 + 1)) - 1) << lsb;
+    rt_f = rs_f ^ 0xFFFFFFFF;
+    temprs = rs & rs_f;
+    temprt = rt & rt_f;
+    temp = temprs | temprt;
+
+    return (target_long)(int32_t)temp;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dinsv(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    target_ulong dspctrl;
+    target_ulong filter;
+    uint8_t pos, size;
+    uint8_t msb, lsb;
+    uint64_t temp;
+
+    temp = rt;
+    dspctrl = env->active_tc.DSPControl;
+    pos = dspctrl & 0x7F;
+    size = (dspctrl >> 7) & 0x3F;
+
+    msb = pos + size - 1;
+    lsb = pos;
+
+    if ((lsb > msb) || (msb > 63)) {
+        return temp;
+    }
+
+    temp = 0;
+    filter = ((target_ulong)0x01 << size) - 1;
+    filter = filter << pos;
+
+    temp |= rs & filter;
+    temp |= rt & (~filter);
+
+    return temp;
+}
+#endif
+
 #undef MIPSDSP_LHI
 #undef MIPSDSP_LLO
 #undef MIPSDSP_HI
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 69bcb6c..df86ef9 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -582,4 +582,11 @@ DEF_HELPER_FLAGS_4(dmsub, 0, void, env, tl, tl, i32)
 DEF_HELPER_FLAGS_4(dmsubu, 0, void, env, tl, tl, i32)
 #endif
 
+/* DSP Bit/Manipulation Sub-class insns */
+DEF_HELPER_FLAGS_1(bitrev, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
+DEF_HELPER_FLAGS_3(insv, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dinsv, 0, tl, env, tl, tl);
+#endif
+
 #include "def-helper.h"
diff --git a/target-mips/translate.c b/target-mips/translate.c
index d8f83e0..1a9df0f 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -343,6 +343,11 @@ enum {
 #if defined(TARGET_MIPS64)
     OPC_DPAQ_W_QH_DSP  = 0x34 | OPC_SPECIAL3,
 #endif
+    /* DSP Bit/Manipulation Sub-class */
+    OPC_INSV_DSP       = 0x0C | OPC_SPECIAL3,
+#if defined(TARGET_MIPS64)
+    OPC_DINSV_DSP      = 0x0D | OPC_SPECIAL3,
+#endif
 };
 
 /* BSHFL opcodes */
@@ -450,6 +455,12 @@ enum {
     OPC_PRECEU_PH_QBR   = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
     OPC_PRECEU_PH_QBLA  = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
     OPC_PRECEU_PH_QBRA  = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
+    /* DSP Bit/Manipulation Sub-class */
+    OPC_BITREV          = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_REPL_QB         = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_REPLV_QB        = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_REPL_PH         = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
+    OPC_REPLV_PH        = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
 };
 
 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
@@ -518,6 +529,12 @@ enum {
     OPC_MULSA_W_PH    = (0x02 << 6) | OPC_DPA_W_PH_DSP,
 };
 
+#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* DSP Bit/Manipulation Sub-class */
+    OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
+};
+
 #if defined(TARGET_MIPS64)
 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
@@ -539,6 +556,13 @@ enum {
     OPC_ABSQ_S_OB       = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
     OPC_ABSQ_S_PW       = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
     OPC_ABSQ_S_QH       = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
+    /* DSP Bit/Manipulation Sub-class */
+    OPC_REPL_OB         = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_REPL_PW         = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_REPL_QH         = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_REPLV_OB        = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_REPLV_PW        = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
+    OPC_REPLV_QH        = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
 };
 #endif
 
@@ -592,6 +616,14 @@ enum {
 #endif
 
 #if defined(TARGET_MIPS64)
+#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* DSP Bit/Manipulation Sub-class */
+    OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
+};
+#endif
+
+#if defined(TARGET_MIPS64)
 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
     /* MIPS DSP Multiply Sub-class insns */
@@ -12633,6 +12665,116 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 check_insn(env, ctx, ASE_DSP);
                 gen_helper_preceu_ph_qbra(cpu_gpr[rd], cpu_gpr[rt]);
                 break;
+            case OPC_BITREV:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_bitrev(cpu_gpr[rd], cpu_gpr[rt]);
+                break;
+            case OPC_REPL_QB:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv imm3, imm2, imm1, imm0, temp_rd;
+                    temp_rd = tcg_const_tl(0);
+
+                    imm = (ctx->opcode >> 16) & 0xFF;
+                    imm3 = tcg_const_tl(imm);
+                    imm2 = tcg_const_tl(imm);
+                    imm1 = tcg_const_tl(imm);
+                    imm0 = tcg_const_tl(imm);
+                    tcg_gen_shli_tl(imm3, imm3, 24);
+                    tcg_gen_shli_tl(imm2, imm2, 16);
+                    tcg_gen_shli_tl(imm1, imm1, 8);
+                    tcg_gen_or_tl(temp_rd, temp_rd, imm3);
+                    tcg_gen_or_tl(temp_rd, temp_rd, imm2);
+                    tcg_gen_or_tl(temp_rd, temp_rd, imm1);
+                    tcg_gen_or_tl(temp_rd, temp_rd, imm0);
+#if defined(TARGET_MIPS64)
+                    tcg_gen_ext32s_i64(temp_rd, temp_rd);
+#endif
+                    gen_store_gpr(temp_rd, rd);
+                    tcg_temp_free(temp_rd);
+                    tcg_temp_free(imm3);
+                    tcg_temp_free(imm2);
+                    tcg_temp_free(imm1);
+                    tcg_temp_free(imm0);
+                    break;
+                }
+            case OPC_REPLV_QB:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv rt3, rt2, rt1, rt0, temp_rd;
+                    temp_rd = tcg_const_tl(0);
+
+                    rt3 = tcg_const_tl(0);
+                    rt2 = tcg_const_tl(0);
+                    rt1 = tcg_const_tl(0);
+                    rt0 = tcg_const_tl(0);
+
+                    tcg_gen_andi_tl(rt3, cpu_gpr[rt], 0xFF);
+                    tcg_gen_andi_tl(rt2, cpu_gpr[rt], 0xFF);
+                    tcg_gen_andi_tl(rt1, cpu_gpr[rt], 0xFF);
+                    tcg_gen_andi_tl(rt0, cpu_gpr[rt], 0xFF);
+
+                    tcg_gen_shli_tl(rt3, rt3, 24);
+                    tcg_gen_shli_tl(rt2, rt2, 16);
+                    tcg_gen_shli_tl(rt1, rt1, 8);
+
+                    tcg_gen_or_tl(temp_rd, temp_rd, rt3);
+                    tcg_gen_or_tl(temp_rd, temp_rd, rt2);
+                    tcg_gen_or_tl(temp_rd, temp_rd, rt1);
+                    tcg_gen_or_tl(temp_rd, temp_rd, rt0);
+#if defined(TARGET_MIPS64)
+                    tcg_gen_ext32s_i64(temp_rd, temp_rd);
+#endif
+                    gen_store_gpr(temp_rd, rd);
+
+                    tcg_temp_free(temp_rd);
+                    tcg_temp_free(rt3);
+                    tcg_temp_free(rt2);
+                    tcg_temp_free(rt1);
+                    tcg_temp_free(rt0);
+                     break;
+                }
+            case OPC_REPL_PH:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv immhi, immlo, temp_rd;
+                    temp_rd = tcg_const_tl(0);
+
+                    imm = (ctx->opcode >> 16) & 0x03FF;
+                    immhi = tcg_const_tl(imm);
+                    immlo = tcg_const_tl(imm);
+                    tcg_gen_shli_tl(immhi, immhi, 16);
+                    tcg_gen_or_tl(temp_rd, immhi, immlo);
+#if defined(TARGET_MIPS64)
+                    tcg_gen_ext32s_i64(temp_rd, temp_rd);
+#endif
+                    gen_store_gpr(temp_rd, rd);
+                    tcg_temp_free(temp_rd);
+                    tcg_temp_free(immhi);
+                    tcg_temp_free(immlo);
+                    break;
+                }
+            case OPC_REPLV_PH:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv rt0, rt1, temp_rd;
+                    temp_rd = tcg_const_tl(0);
+
+                    rt0 = tcg_const_tl(0);
+                    rt1 = tcg_const_tl(0);
+                    tcg_gen_andi_tl(rt0, cpu_gpr[rt], 0xFFFF);
+                    tcg_gen_andi_tl(rt1, cpu_gpr[rt], 0xFFFF);
+                    tcg_gen_shli_tl(rt1, rt1, 16);
+                    tcg_gen_or_tl(temp_rd, rt1, rt0);
+#if defined(TARGET_MIPS64)
+                    tcg_gen_ext32s_i64(temp_rd, temp_rd);
+#endif
+                    gen_store_gpr(temp_rd, rd);
+                    tcg_temp_free(temp_rd);
+                    tcg_temp_free(rt0);
+                    tcg_temp_free(rt1);
+                    break;
+                }
             default:            /* Invalid */
                 MIPS_INVAL("MASK ABSQ_S.PH");
                 generate_exception(ctx, EXCP_RI);
@@ -13133,6 +13275,22 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 break;
             }
             break;
+        case OPC_INSV_DSP:
+            op2 = MASK_INSV(ctx->opcode);
+            switch (op2) {
+            case OPC_INSV:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    gen_helper_insv(cpu_gpr[rt], cpu_env,
+                                    cpu_gpr[rs], cpu_gpr[rt]);
+                    break;
+                }
+            default:            /* Invalid */
+                MIPS_INVAL("MASK INSV");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
@@ -13213,6 +13371,119 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 check_insn(env, ctx, ASE_DSP);
                 gen_helper_preceu_qh_obra(cpu_gpr[rd], cpu_gpr[rt]);
                 break;
+            case OPC_REPL_OB:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int i;
+                    TCGv_i64 immv, temp_rd;
+                    temp_rd = tcg_const_i64(0);
+
+                    imm = (ctx->opcode >> 16) & 0xFF;
+                    immv = tcg_const_i64(imm);
+
+                    tcg_gen_or_i64(temp_rd, temp_rd, immv);
+                    for (i = 0; i < 7; i++) {
+                        tcg_gen_shli_i64(temp_rd, temp_rd, 8);
+                        tcg_gen_or_i64(temp_rd, temp_rd, immv);
+                    }
+                    gen_store_gpr(temp_rd, rd);
+                    break;
+                }
+            case OPC_REPL_PW:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i64 temp = tcg_temp_new_i64();
+
+                    imm = (ctx->opcode >> 16) & 0x03FF;
+                    imm = (int16_t)(imm << 6) >> 6;
+
+                    tcg_gen_movi_i64(temp,
+                                     (uint64_t)(uint32_t)(int32_t)imm);
+                    tcg_gen_shli_i64(temp, temp, 32);
+                    tcg_gen_ori_i64(temp, temp,
+                                    (uint64_t)(uint32_t)(int32_t)imm);
+
+                    gen_store_gpr(temp, rd);
+
+                    tcg_temp_free_i64(temp);
+                    break;
+                }
+            case OPC_REPL_QH:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i64 temp = tcg_temp_new_i64();
+
+                    imm = (ctx->opcode >> 16) & 0x03FF;
+                    imm = (int16_t)(imm << 6) >> 6;
+
+                    tcg_gen_movi_i64(temp, (uint64_t)(uint16_t)imm);
+                    tcg_gen_shli_i64(temp, temp, 16);
+                    tcg_gen_ori_i64(temp, temp, (uint64_t)(uint16_t)imm);
+                    tcg_gen_shli_i64(temp, temp, 16);
+                    tcg_gen_ori_i64(temp, temp, (uint64_t)(uint16_t)imm);
+                    tcg_gen_shli_i64(temp, temp, 16);
+                    tcg_gen_ori_i64(temp, temp, (uint64_t)(uint16_t)imm);
+
+                    gen_store_gpr(temp, rd);
+
+                    tcg_temp_free_i64(temp);
+                    break;
+                }
+            case OPC_REPLV_OB:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int i;
+                    TCGv_i64 immv, temp_rd;
+                    immv = tcg_const_i64(0);
+                    temp_rd = tcg_const_i64(0);
+
+                    tcg_gen_ori_i64(immv, cpu_gpr[rt], 0xFF);
+                    tcg_gen_or_i64(temp_rd, temp_rd, immv);
+                    for (i = 0; i < 7; i++) {
+                        tcg_gen_shli_i64(temp_rd, temp_rd, 8);
+                        tcg_gen_or_i64(temp_rd, temp_rd, immv);
+                    }
+                    gen_store_gpr(temp_rd, rd);
+                    tcg_temp_free_i64(immv);
+                    tcg_temp_free_i64(temp_rd);
+                    break;
+                }
+            case OPC_REPLV_PW:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i64 imm_v;
+                    imm_v = tcg_const_i64(0);
+
+                    tcg_gen_ori_i64(imm_v, cpu_gpr[rt], 0xFFFFFFFF);
+                    tcg_gen_ext32s_i64(cpu_gpr[rd], imm_v);
+
+                    tcg_temp_free_i64(imm_v);
+                    break;
+                }
+            case OPC_REPLV_QH:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i64 imm_v;
+                    TCGv_i64 temp_rd;
+
+                    imm_v = tcg_const_i64(0);
+                    temp_rd = tcg_const_i64(0);
+                    tcg_gen_ori_i64(imm_v, cpu_gpr[rt], 0xffff);
+
+                    tcg_gen_or_i64(temp_rd, temp_rd, imm_v);
+                    tcg_gen_shli_i64(temp_rd, temp_rd, 16);
+                    tcg_gen_or_i64(temp_rd, temp_rd, imm_v);
+                    tcg_gen_shli_i64(temp_rd, temp_rd, 16);
+                    tcg_gen_or_i64(temp_rd, temp_rd, imm_v);
+                    tcg_gen_shli_i64(temp_rd, temp_rd, 16);
+                    tcg_gen_or_i64(temp_rd, temp_rd, imm_v);
+
+                    gen_store_gpr(temp_rd, rd);
+
+                    tcg_temp_free_i64(imm_v);
+                    tcg_temp_free_i64(temp_rd);
+                    break;
+                }
             case OPC_ABSQ_S_OB:
                 check_insn(env, ctx, ASE_DSPR2);
                 gen_helper_absq_s_ob(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
@@ -13574,6 +13845,22 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             }
 #endif
 #if defined(TARGET_MIPS64)
+        case OPC_DINSV_DSP:
+            op2 = MASK_INSV(ctx->opcode);
+            switch (op2) {
+            case OPC_DINSV:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_dinsv(cpu_gpr[rt], cpu_env,
+                                 cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK DINSV");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+#endif
+#if defined(TARGET_MIPS64)
         case OPC_SHLL_OB_DSP:
             op2 = MASK_SHLL_OB(ctx->opcode);
             switch (op2) {
@@ -13748,7 +14035,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 generate_exception(ctx, EXCP_RI);
                 break;
             }
-          break;
+            break;
 #endif
         default:            /* Invalid */
             MIPS_INVAL("special3");
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v6 09/13] target-mips-ase-dsp: Add compare pick instructions
  2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
                   ` (7 preceding siblings ...)
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 08/13] target-mips-ase-dsp: Add bit/manipulation instructions Jia Liu
@ 2012-08-21  6:53 ` Jia Liu
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 10/13] target-mips-ase-dsp: Add MIPS ASE DSP Accumulator and DSPControl Access instructions Jia Liu
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Jia Liu @ 2012-08-21  6:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Add MIPS ASE DSP Compare-Pick instructions.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/dsp_helper.c |  917 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/helper.h     |   52 +++
 target-mips/translate.c  |  323 ++++++++++++++++
 3 files changed, 1292 insertions(+)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 4564d9c..f41808e 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -6290,6 +6290,923 @@ target_ulong helper_dinsv(CPUMIPSState *env, target_ulong rs, target_ulong rt)
 }
 #endif
 
+/** DSP Compare-Pick Sub-class insns **/
+void helper_cmpu_eq_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+    uint32_t flag;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    cc3 = (rs3 == rt3);
+    cc2 = (rs2 == rt2);
+    cc1 = (rs1 == rt1);
+    cc0 = (rs0 == rt0);
+
+    flag = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+    set_DSPControl_24(env, flag, 4);
+}
+
+void helper_cmpu_lt_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+    uint32_t flag;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    cc3 = (rs3 < rt3);
+    cc2 = (rs2 < rt2);
+    cc1 = (rs1 < rt1);
+    cc0 = (rs0 < rt0);
+
+    flag = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+    set_DSPControl_24(env, flag, 4);
+}
+
+void helper_cmpu_le_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+    uint32_t flag;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    cc3 = (rs3 <= rt3);
+    cc2 = (rs2 <= rt2);
+    cc1 = (rs1 <= rt1);
+    cc0 = (rs0 <= rt0);
+
+    flag = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+    set_DSPControl_24(env, flag, 4);
+}
+
+
+target_ulong helper_cmpgu_eq_qb(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint8_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+    uint32_t temp;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    cc3 = (rs3 == rt3);
+    cc2 = (rs2 == rt2);
+    cc1 = (rs1 == rt1);
+    cc0 = (rs0 == rt0);
+
+    temp = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+    rd = temp;
+
+    return (target_ulong)rd;
+}
+
+target_ulong helper_cmpgu_lt_qb(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+    uint32_t temp;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    cc3 = (rs3 < rt3);
+    cc2 = (rs2 < rt2);
+    cc1 = (rs1 < rt1);
+    cc0 = (rs0 < rt0);
+
+    temp = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+    rd = temp;
+
+    return (target_ulong)rd;
+}
+
+target_ulong helper_cmpgu_le_qb(target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+    uint32_t temp;
+    uint32_t rd;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    cc3 = (rs3 <= rt3);
+    cc2 = (rs2 <= rt2);
+    cc1 = (rs1 <= rt1);
+    cc0 = (rs0 <= rt0);
+
+    temp = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+    rd = temp;
+
+    return (target_ulong)rd;
+}
+
+void helper_cmp_eq_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t flag;
+    int32_t ccA = 0, ccB = 0;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    ccB = (rsh == rth);
+    ccA = (rsl == rtl);
+
+    flag = (ccB << 1) | ccA;
+    set_DSPControl_24(env, flag, 2);
+}
+
+void helper_cmp_lt_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t flag;
+    int32_t ccA = 0, ccB = 0;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    ccB = (rsh < rth);
+    ccA = (rsl < rtl);
+
+    flag = (ccB << 1) | ccA;
+    set_DSPControl_24(env, flag, 2);
+}
+
+void helper_cmp_le_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int16_t rsh, rsl, rth, rtl;
+    int32_t flag;
+    int32_t ccA = 0, ccB = 0;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    ccB = (rsh <= rth);
+    ccA = (rsl <= rtl);
+
+    flag = (ccB << 1) | ccA;
+    set_DSPControl_24(env, flag, 2);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_cmpu_eq_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] == rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+
+    set_DSPControl_24(env, cond, 8);
+}
+
+void helper_cmpu_lt_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] < rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+
+    set_DSPControl_24(env, cond, 8);
+}
+
+void helper_cmpu_le_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] <= rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+
+    set_DSPControl_24(env, cond, 8);
+}
+
+target_ulong helper_cmpgdu_eq_ob(CPUMIPSState *env,
+                                 target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+    uint64_t temp;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] == rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+
+    set_DSPControl_24(env, cond, 8);
+    temp = (uint64_t)cond;
+
+    return temp;
+}
+
+target_ulong helper_cmpgdu_lt_ob(CPUMIPSState *env,
+                                 target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+    uint64_t temp;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] < rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+
+    set_DSPControl_24(env, cond, 8);
+    temp = (uint64_t)cond;
+
+    return temp;
+}
+
+target_ulong helper_cmpgdu_le_ob(CPUMIPSState *env,
+                                 target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+    uint64_t temp;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] <= rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+
+    set_DSPControl_24(env, cond, 8);
+    temp = (uint64_t)cond;
+
+    return temp;
+}
+
+target_ulong helper_cmpgu_eq_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+    uint64_t temp;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] == rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+    temp = (uint64_t)cond;
+
+    return temp;
+}
+
+target_ulong helper_cmpgu_lt_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+    uint64_t temp;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] < rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+    temp = (uint64_t)cond;
+
+    return temp;
+}
+
+target_ulong helper_cmpgu_le_ob(target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint8_t rs_t[8], rt_t[8];
+    uint32_t cond;
+    uint64_t temp;
+
+    cond = 0;
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        if (rs_t[i] <= rt_t[i]) {
+            cond |= 0x01 << i;
+        }
+    }
+    temp = (uint64_t)cond;
+
+    return temp;
+}
+
+void helper_cmp_eq_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint32_t cond;
+
+    cond = 0;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    if (rs3 == rt3) {
+        cond |= 0x08;
+    }
+
+    if (rs2 == rt2) {
+        cond |= 0x04;
+    }
+
+    if (rs1 == rt1) {
+        cond |= 0x02;
+    }
+
+    if (rs0 == rt0) {
+        cond |= 0x01;
+    }
+
+    set_DSPControl_24(env, cond, 4);
+}
+
+void helper_cmp_lt_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint32_t cond;
+
+    cond = 0;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    if (rs3 < rt3) {
+        cond |= 0x08;
+    }
+
+    if (rs2 < rt2) {
+        cond |= 0x04;
+    }
+
+    if (rs1 < rt1) {
+        cond |= 0x02;
+    }
+
+    if (rs0 < rt0) {
+        cond |= 0x01;
+    }
+
+    set_DSPControl_24(env, cond, 4);
+}
+
+void helper_cmp_le_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint32_t cond;
+
+    cond = 0;
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    if (rs3 <= rt3) {
+        cond |= 0x08;
+    }
+
+    if (rs2 <= rt2) {
+        cond |= 0x04;
+    }
+
+    if (rs1 <= rt1) {
+        cond |= 0x02;
+    }
+
+    if (rs0 <= rt0) {
+        cond |= 0x01;
+    }
+
+    set_DSPControl_24(env, cond, 4);
+}
+
+void helper_cmp_eq_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t cond;
+
+    cond = 0;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    if (rs1 == rt1) {
+        cond |= 0x2;
+    }
+
+    if (rs0 == rt0) {
+        cond |= 0x1;
+    }
+
+    set_DSPControl_24(env, cond, 2);
+}
+
+void helper_cmp_lt_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t cond;
+
+    cond = 0;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    if (rs1 < rt1) {
+        cond |= 0x2;
+    }
+
+    if (rs0 < rt0) {
+        cond |= 0x1;
+    }
+
+    set_DSPControl_24(env, cond, 2);
+}
+
+void helper_cmp_le_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t cond;
+
+    cond = 0;
+
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    if (rs1 <= rt1) {
+        cond |= 0x2;
+    }
+
+    if (rs0 <= rt0) {
+        cond |= 0x1;
+    }
+
+    set_DSPControl_24(env, cond, 2);
+}
+#endif
+
+target_ulong helper_pick_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint8_t rs3, rs2, rs1, rs0;
+    uint8_t rt3, rt2, rt1, rt0;
+    uint8_t tp3, tp2, tp1, tp0;
+
+    uint32_t dsp27, dsp26, dsp25, dsp24, rd;
+    target_ulong dsp;
+
+    rs3 = (rs & MIPSDSP_Q3) >> 24;
+    rs2 = (rs & MIPSDSP_Q2) >> 16;
+    rs1 = (rs & MIPSDSP_Q1) >>  8;
+    rs0 =  rs & MIPSDSP_Q0;
+    rt3 = (rt & MIPSDSP_Q3) >> 24;
+    rt2 = (rt & MIPSDSP_Q2) >> 16;
+    rt1 = (rt & MIPSDSP_Q1) >>  8;
+    rt0 =  rt & MIPSDSP_Q0;
+
+    dsp = env->active_tc.DSPControl;
+    dsp27 = (dsp >> 27) & 0x01;
+    dsp26 = (dsp >> 26) & 0x01;
+    dsp25 = (dsp >> 25) & 0x01;
+    dsp24 = (dsp >> 24) & 0x01;
+
+    tp3 = dsp27 == 1 ? rs3 : rt3;
+    tp2 = dsp26 == 1 ? rs2 : rt2;
+    tp1 = dsp25 == 1 ? rs1 : rt1;
+    tp0 = dsp24 == 1 ? rs0 : rt0;
+
+    rd = ((uint32_t)tp3 << 24) |
+         ((uint32_t)tp2 << 16) |
+         ((uint32_t)tp1 <<  8) |
+         (uint32_t)tp0;
+
+    return (target_long)(int32_t)rd;
+}
+
+target_ulong helper_pick_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint16_t rsh, rsl, rth, rtl;
+    uint16_t tempB, tempA;
+    uint32_t dsp25, dsp24;
+    uint32_t rd;
+    target_ulong dsp;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    dsp = env->active_tc.DSPControl;
+    dsp25 = (dsp >> 25) & 0x01;
+    dsp24 = (dsp >> 24) & 0x01;
+
+    tempB = (dsp25 == 1) ? rsh : rth;
+    tempA = (dsp24 == 1) ? rsl : rtl;
+    rd = (((uint32_t)tempB << 16) & MIPSDSP_HI) | (uint32_t)tempA;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_pick_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    int i;
+    uint32_t cond;
+    uint8_t rs_t[8], rt_t[8];
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+    cond = get_DSPControl_24(env, 8);
+
+    for (i = 0; i < 8; i++) {
+        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+
+        temp[i] = (cond % 2) == 1 ? rs_t[i] : rt_t[i];
+        cond = cond / 2;
+    }
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_pick_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t cond;
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+    uint64_t result;
+
+    cond = get_DSPControl_24(env, 4);
+
+    rs3 = (rs >> 48) & MIPSDSP_LO;
+    rs2 = (rs >> 32) & MIPSDSP_LO;
+    rs1 = (rs >> 16) & MIPSDSP_LO;
+    rs0 = rs & MIPSDSP_LO;
+    rt3 = (rt >> 48) & MIPSDSP_LO;
+    rt2 = (rt >> 32) & MIPSDSP_LO;
+    rt1 = (rt >> 16) & MIPSDSP_LO;
+    rt0 = rt & MIPSDSP_LO;
+
+    tempA = ((cond % 2) == 1) ? rs0 : rt0;
+    cond = cond / 2;
+    tempB = ((cond % 2) == 1) ? rs1 : rt1;
+    cond = cond / 2;
+    tempC = ((cond % 2) == 1) ? rs2 : rt2;
+    cond = cond / 2;
+    tempD = ((cond % 2) == 1) ? rs3 : rt3;
+
+    result = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
+             ((uint64_t)tempB << 16) | (uint64_t)tempA;
+
+    return result;
+}
+
+target_ulong helper_pick_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
+{
+    uint32_t cond;
+    uint32_t rs1, rs0;
+    uint32_t rt1, rt0;
+    uint32_t tempB, tempA;
+    uint64_t result;
+
+    cond = get_DSPControl_24(env, 2);
+    rs1 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempA = ((cond % 2) == 1) ? rs0 : rt0;
+    cond = cond / 2;
+    tempB = ((cond % 2) == 1) ? rs1 : rt1;
+
+    result = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return result;
+}
+#endif
+
+target_ulong helper_append(target_ulong rt, target_ulong rs, uint32_t sa)
+{
+    int len;
+    uint32_t temp;
+
+    len = sa & 0x1F;
+
+    if (len == 0) {
+        temp = rt;
+    } else {
+        temp = (rt << len) | (rs & (((uint32_t)0x01 << len) - 1));
+    }
+    rt = temp;
+
+    return (target_long)(int32_t)temp;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dappend(target_ulong rs, target_ulong rt, uint32_t sa)
+{
+    uint32_t filter;
+    uint64_t temp;
+
+    filter = 0;
+    temp = 0;
+
+    if (sa == 0) {
+        temp = rt;
+    } else {
+        filter = (0x01 << sa) - 1;
+        temp = rt << sa;
+        temp |= rs & filter;
+    }
+
+    return temp;
+}
+
+#endif
+
+target_ulong helper_prepend(uint32_t sa, target_ulong rs, target_ulong rt)
+{
+    uint32_t temp;
+
+    if (sa == 0) {
+        temp = rt;
+    } else {
+        temp = (rs << (32 - sa)) | rt >> sa;
+    }
+
+    rt = temp;
+
+    return (target_long)(int32_t)rt;
+}
+
+#if defined(TARGET_MIPS64)
+/*
+ * The instruction describtion really confused me.
+ *
+ * Description:
+ * The shift argument is provided by the instruction argument,
+ * sa, interpreted as an unsigned five-bit integer and biased
+ * by 32, allowing shift amounts between 32 and 63.
+ *
+ * Operation:
+ * shift5..0 ← 1 || sa4..0
+ * if ( shift = 0 ) then
+ *
+ * Why put 1 at sa5, and test shift is equal zero or not?
+ *
+ */
+target_ulong helper_prependd(target_ulong rs, target_ulong rt, uint32_t sa)
+{
+    uint32_t shift;
+    uint64_t temp;
+
+    shift = sa & 0x10;
+
+    if (shift == 0) {
+        temp = rt;
+    } else {
+        temp = (rs << (64 - shift)) | (rt >> shift);
+    }
+
+    return temp;
+}
+
+target_ulong helper_prependw(target_ulong rs, target_ulong rt, uint32_t sa)
+{
+    uint32_t shift;
+    uint64_t temp;
+
+    shift = sa;
+
+    if (shift == 0) {
+        temp = rt;
+    } else {
+        temp = (rs << (64 - shift)) | (rt >> shift);
+    }
+
+    return temp;
+}
+#endif
+
+target_ulong helper_balign(uint32_t bp, target_ulong rt, target_ulong rs)
+{
+    uint32_t temp;
+    bp = bp & 0x03;
+
+    if (bp == 0 || bp == 2) {
+        return rt;
+    } else {
+        temp = (rt << (8 * bp)) | (rs >> (8 * (4 - bp)));
+    }
+    rt = temp;
+
+    return (target_long)(int32_t)rt;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dbalign(target_ulong rs, target_ulong rt, uint32_t sa)
+{
+    uint8_t bp;
+    uint64_t temp;
+
+    bp = sa & 0x07;
+
+    if ((bp == 0) || (bp == 2) || (bp == 4)) {
+        temp = rt;
+    } else {
+        temp = (rt << (8 * bp)) | (rs >> (8 * (8 - bp)));
+    }
+
+    return temp;
+}
+
+#endif
+
+target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt)
+{
+    uint16_t rsl, rth;
+    uint32_t rd;
+
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rd = (rsl << 16) | rth;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt)
+{
+    uint32_t rs0, rt1;
+    uint32_t tempB, tempA;
+    uint64_t temp;
+
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+
+    tempB = rs0;
+    tempA = rt1;
+
+    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
+
+    return temp;
+}
+#endif
+
 #undef MIPSDSP_LHI
 #undef MIPSDSP_LLO
 #undef MIPSDSP_HI
diff --git a/target-mips/helper.h b/target-mips/helper.h
index df86ef9..273501c 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -589,4 +589,56 @@ DEF_HELPER_FLAGS_3(insv, 0, tl, env, tl, tl)
 DEF_HELPER_FLAGS_3(dinsv, 0, tl, env, tl, tl);
 #endif
 
+/* DSP Compare-Pick Sub-class insns */
+DEF_HELPER_FLAGS_3(cmpu_eq_qb, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpu_lt_qb, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpu_le_qb, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_2(cmpgu_eq_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(cmpgu_lt_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(cmpgu_le_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_eq_ph, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_lt_ph, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_le_ph, 0, void, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(cmpu_eq_ob, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpu_lt_ob, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpu_le_ob, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpgdu_eq_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpgdu_lt_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmpgdu_le_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_2(cmpgu_eq_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(cmpgu_lt_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(cmpgu_le_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_eq_qh, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_lt_qh, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_le_qh, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_eq_pw, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_lt_pw, 0, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(cmp_le_pw, 0, void, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(pick_qb, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(pick_ph, 0, tl, env, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(pick_ob, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(pick_qh, 0, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(pick_pw, 0, tl, env, tl, tl)
+#endif
+DEF_HELPER_FLAGS_3(append, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dappend, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_3(prepend, TCG_CALL_CONST | TCG_CALL_PURE, tl, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(prependd, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+DEF_HELPER_FLAGS_3(prependw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_3(balign, TCG_CALL_CONST | TCG_CALL_PURE, tl, i32, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dbalign, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
+#endif
+DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_2(packrl_pw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#endif
+
 #include "def-helper.h"
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 1a9df0f..b493582 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -348,6 +348,11 @@ enum {
 #if defined(TARGET_MIPS64)
     OPC_DINSV_DSP      = 0x0D | OPC_SPECIAL3,
 #endif
+    /* MIPS DSP Compare-Pick Sub-class */
+    OPC_APPEND_DSP     = 0x31 | OPC_SPECIAL3,
+#if defined(TARGET_MIPS64)
+    OPC_DAPPEND_DSP    = 0x35 | OPC_SPECIAL3,
+#endif
 };
 
 /* BSHFL opcodes */
@@ -473,6 +478,22 @@ enum {
     OPC_PRECRQ_PH_W      = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
     OPC_PRECRQ_RS_PH_W   = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
     OPC_PRECRQU_S_QB_PH  = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
+    /* DSP Compare-Pick Sub-class */
+    OPC_CMPU_EQ_QB       = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPU_LT_QB       = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPU_LE_QB       = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPGU_EQ_QB      = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPGU_LT_QB      = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPGU_LE_QB      = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPGDU_EQ_QB     = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPGDU_LT_QB     = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMPGDU_LE_QB     = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMP_EQ_PH        = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMP_LT_PH        = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_CMP_LE_PH        = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PICK_QB          = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PICK_PH          = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
+    OPC_PACKRL_PH        = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
 };
 
 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
@@ -535,6 +556,14 @@ enum {
     OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
 };
 
+#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Compare-Pick Sub-class */
+    OPC_APPEND  = (0x00 << 6) | OPC_APPEND_DSP,
+    OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
+    OPC_BALIGN  = (0x10 << 6) | OPC_APPEND_DSP,
+};
+
 #if defined(TARGET_MIPS64)
 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
@@ -603,6 +632,26 @@ enum {
 #if defined(TARGET_MIPS64)
 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
+    /* DSP Compare-Pick Sub-class */
+    OPC_CMP_EQ_PW         = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMP_LT_PW         = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMP_LE_PW         = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMP_EQ_QH         = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMP_LT_QH         = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMP_LE_QH         = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPGDU_EQ_OB      = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPGDU_LT_OB      = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPGDU_LE_OB      = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPGU_EQ_OB       = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPGU_LT_OB       = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPGU_LE_OB       = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPU_EQ_OB        = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPU_LT_OB        = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_CMPU_LE_OB        = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PACKRL_PW         = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PICK_OB           = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PICK_PW           = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
+    OPC_PICK_QH           = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
     /* MIPS DSP Arithmetic Sub-class */
     OPC_PRECR_OB_QH       = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
     OPC_PRECR_SRA_QH_PW   = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
@@ -616,6 +665,17 @@ enum {
 #endif
 
 #if defined(TARGET_MIPS64)
+#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* DSP Compare-Pick Sub-class */
+    OPC_DAPPEND  = (0x00 << 6) | OPC_DAPPEND_DSP,
+    OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
+    OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
+    OPC_DBALIGN  = (0x10 << 6) | OPC_DAPPEND_DSP,
+};
+#endif
+
+#if defined(TARGET_MIPS64)
 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
     /* DSP Bit/Manipulation Sub-class */
@@ -12951,6 +13011,101 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 gen_helper_precrqu_s_qb_ph(cpu_gpr[rd], cpu_env,
                                            cpu_gpr[rs], cpu_gpr[rt]);
                 break;
+            case OPC_CMPU_EQ_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpu_eq_qb(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPU_LT_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpu_lt_qb(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPU_LE_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpu_le_qb(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGU_EQ_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpgu_eq_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGU_LT_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpgu_lt_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGU_LE_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpgu_le_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGDU_EQ_QB:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv dspc, t0;
+                    dspc = tcg_const_tl(0);
+                    t0 = tcg_const_tl(0);
+                    gen_helper_cmpgu_eq_qb(dspc, cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_gen_mov_tl(cpu_gpr[rd], dspc);
+                    tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
+                    tcg_gen_shli_tl(t0, dspc, 24);
+                    tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t0);
+                    tcg_temp_free(dspc);
+                    tcg_temp_free(t0);
+                    break;
+                }
+            case OPC_CMPGDU_LT_QB:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv dspc, t0;
+                    dspc = tcg_const_tl(0);
+                    t0 = tcg_const_tl(0);
+                    gen_helper_cmpgu_lt_qb(dspc, cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_gen_mov_tl(cpu_gpr[rd], dspc);
+                    tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
+                    tcg_gen_shli_tl(t0, dspc, 24);
+                    tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t0);
+                    tcg_temp_free(dspc);
+                    tcg_temp_free(t0);
+                    break;
+                }
+            case OPC_CMPGDU_LE_QB:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv dspc, t0;
+                    dspc = tcg_const_tl(0);
+                    t0 = tcg_const_tl(0);
+                    gen_helper_cmpgu_le_qb(dspc, cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_gen_mov_tl(cpu_gpr[rd], dspc);
+                    tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
+                    tcg_gen_shli_tl(t0, dspc, 24);
+                    tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t0);
+                    tcg_temp_free(dspc);
+                    tcg_temp_free(t0);
+                    break;
+                }
+            case OPC_CMP_EQ_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_eq_ph(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_LT_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_lt_ph(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_LE_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_le_ph(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PICK_QB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_pick_qb(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PICK_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_pick_ph(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PACKRL_PH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_packrl_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
             default:            /* Invalid */
                 MIPS_INVAL("MASK CMPU.EQ.QB");
                 generate_exception(ctx, EXCP_RI);
@@ -13291,6 +13446,42 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 break;
             }
             break;
+        case OPC_APPEND_DSP:
+            op2 = MASK_APPEND(ctx->opcode);
+            switch (op2) {
+            case OPC_APPEND:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_append(cpu_gpr[rt], cpu_gpr[rt],
+                                      cpu_gpr[rs], temp_rd);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_PREPEND:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_prepend(cpu_gpr[rt], temp_rd,
+                                       cpu_gpr[rs], cpu_gpr[rt]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_BALIGN:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_balign(cpu_gpr[rt], temp_rd,
+                                      cpu_gpr[rt], cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            default:            /* Invalid */
+                MIPS_INVAL("MASK APPEND");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
@@ -13643,6 +13834,91 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_CMPU_EQ_OB_DSP:
             op2 = MASK_CMPU_EQ_OB(ctx->opcode);
             switch (op2) {
+            case OPC_CMP_EQ_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_eq_pw(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_LT_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_lt_pw(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_LE_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_le_pw(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_EQ_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_eq_qh(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_LT_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_lt_qh(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMP_LE_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmp_le_qh(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGDU_EQ_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_cmpgdu_eq_ob(cpu_gpr[rd], cpu_env,
+                                        cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGDU_LT_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_cmpgdu_lt_ob(cpu_gpr[rd], cpu_env,
+                                        cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGDU_LE_OB:
+                check_insn(env, ctx, ASE_DSPR2);
+                gen_helper_cmpgdu_le_ob(cpu_gpr[rd], cpu_env,
+                                        cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPGU_EQ_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpgu_eq_ob(cpu_gpr[rd], cpu_gpr[rs],
+                                       cpu_gpr[rt]);
+                break;
+            case OPC_CMPGU_LT_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpgu_lt_ob(cpu_gpr[rd], cpu_gpr[rs],
+                                       cpu_gpr[rt]);
+                break;
+            case OPC_CMPGU_LE_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpgu_le_ob(cpu_gpr[rd], cpu_gpr[rs],
+                                       cpu_gpr[rt]);
+                break;
+            case OPC_CMPU_EQ_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpu_eq_ob(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPU_LT_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpu_lt_ob(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_CMPU_LE_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_cmpu_le_ob(cpu_env, cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PACKRL_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_packrl_pw(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PICK_OB:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_pick_ob(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PICK_PW:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_pick_pw(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
+            case OPC_PICK_QH:
+                check_insn(env, ctx, ASE_DSP);
+                gen_helper_pick_qh(cpu_gpr[rd], cpu_env,
+                                   cpu_gpr[rs], cpu_gpr[rt]);
+                break;
             case OPC_PRECR_OB_QH:
                 check_insn(env, ctx, ASE_DSPR2);
                 gen_helper_precr_ob_qh(cpu_gpr[rd], cpu_gpr[rs],
@@ -13699,6 +13975,53 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             break;
 #endif
 #if defined(TARGET_MIPS64)
+        case OPC_DAPPEND_DSP:
+            op2 = MASK_DAPPEND(ctx->opcode);
+            switch (op2) {
+            case OPC_DAPPEND:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rd);
+                    gen_helper_dappend(cpu_gpr[rt], cpu_gpr[rs],
+                                       cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_PREPENDD:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rd);
+                    gen_helper_prependd(cpu_gpr[rt], cpu_gpr[rs],
+                                        cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_PREPENDW:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                    TCGv_i32 sa_v = tcg_const_i32(rd);
+                    gen_helper_prependw(cpu_gpr[rt], cpu_gpr[rs],
+                                        cpu_gpr[rt], sa_v);
+                    tcg_temp_free_i32(sa_v);
+                    break;
+                }
+            case OPC_DBALIGN:
+                check_insn(env, ctx, ASE_DSPR2);
+                {
+                  TCGv_i32 sa_v = tcg_const_i32(rd);
+                  gen_helper_dbalign(cpu_gpr[rt], cpu_gpr[rs],
+                                     cpu_gpr[rt], sa_v);
+                  tcg_temp_free_i32(sa_v);
+                  break;
+                }
+            default:            /* Invalid */
+                MIPS_INVAL("MASK DAPPEND");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+#endif
+#if defined(TARGET_MIPS64)
         case OPC_DPAQ_W_QH_DSP:
             {
                 int ac = rd & 0x03;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v6 10/13] target-mips-ase-dsp: Add MIPS ASE DSP Accumulator and DSPControl Access instructions
  2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
                   ` (8 preceding siblings ...)
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 09/13] target-mips-ase-dsp: Add compare pick instructions Jia Liu
@ 2012-08-21  6:53 ` Jia Liu
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 11/13] target-mips-ase-dsp: Add MIPS[32|64] ASE DSP[R1|R2] generic cpu model Jia Liu
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Jia Liu @ 2012-08-21  6:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Add MIPS ASE DSP Accumulator and DSPControl Access instructions.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/dsp_helper.c | 1044 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/helper.h     |   52 +++
 target-mips/translate.c  |  461 ++++++++++++++++++++
 3 files changed, 1557 insertions(+)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index f41808e..332e7c2 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -7207,6 +7207,1050 @@ target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt)
 }
 #endif
 
+/** DSP Accumulator and DSPControl Access Sub-class insns **/
+target_ulong helper_extr_w(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    int32_t tempI;
+    int64_t tempDL[2];
+
+    mipsdsp__rashift_short_acc(env, tempDL, ac, shift);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    tempI = (tempDL[0] >> 1) & MIPSDSP_LLO;
+
+    tempDL[0] += 1;
+    if (tempDL[0] == 0) {
+        tempDL[1] += 1;
+    }
+
+    if ((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) &&
+        (!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI))) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    return (target_long)tempI;
+}
+
+target_ulong helper_extr_r_w(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    int32_t tempI;
+    int64_t tempDL[2];
+
+    mipsdsp__rashift_short_acc(env, tempDL, ac, shift);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    tempDL[0] += 1;
+    if (tempDL[0] == 0) {
+        tempDL[1] += 1;
+    }
+
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+    tempI = tempDL[0] >> 1;
+
+    return (target_long)tempI;
+}
+
+target_ulong helper_extr_rs_w(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    int32_t tempI, temp64;
+    int64_t tempDL[2];
+
+    mipsdsp__rashift_short_acc(env, tempDL, ac, shift);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+    tempDL[0] += 1;
+    if (tempDL[0] == 0) {
+        tempDL[1] += 1;
+    }
+    tempI = tempDL[0] >> 1;
+
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        temp64 = tempDL[1];
+        if (temp64 == 0) {
+            tempI = 0x7FFFFFFF;
+        } else {
+            tempI = 0x80000000;
+        }
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    return (target_long)tempI;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dextr_w(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint64_t temp[3];
+    uint64_t result;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    result = (int64_t)(int32_t)(temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextr_r_w(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xfffFfffFfffFfffFull)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (int64_t)(int32_t)(temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextr_rs_w(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xFFFFFFFFFFFFFFFFull)) {
+        if (temp128 == 0) {
+            temp[0] = 0x0FFFFFFFF;
+        } else {
+            temp[0] = 0x0100000000;
+        }
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (int64_t)(int32_t)(temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextr_l(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint64_t temp[3];
+    uint64_t result;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextr_r_l(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xfffFfffFfffFfffFull)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextr_rs_l(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xFFFFFFFFFFFFFFFFull)) {
+        if (temp128 == 0) {
+            temp[1] &= 0xFFFFFFFFFFFFFFFEull;
+            temp[0] |= 0xFFFFFFFFFFFFFFFEull;
+        } else {
+            temp[1] |= 0x01;
+            temp[0] &= 0x01;
+        }
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+#endif
+
+target_ulong helper_extr_s_h(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    int64_t temp;
+    uint32_t tempI;
+
+    temp = mipsdsp_rashift_short_acc(env, ac, shift);
+    if (temp > 0x0000000000007FFFull) {
+        temp = 0x00007FFF;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    } else if (temp < 0xFFFFFFFFFFFF8000ull) {
+        temp = 0xFFFF8000;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    tempI = temp & 0xFFFFFFFF;
+    return (target_long)(int32_t)tempI;
+}
+
+target_ulong helper_extrv_s_h(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    uint32_t rd;
+    int32_t shift, tempI;
+    int64_t tempL;
+
+    shift = rs & 0x0F;
+    tempL = mipsdsp_rashift_short_acc(env, ac, shift);
+    if (tempL > 0x000000000007FFFull) {
+        tempI = 0x00007FFF;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    } else if (tempL < 0xFFFFFFFFFFF8000ull) {
+        tempI = 0xFFFF8000;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+    rd = tempI;
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dextr_s_h(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    int64_t temp[2];
+    uint32_t temp127;
+    uint64_t result;
+
+    mipsdsp_rashift_acc(env, (uint64_t *)temp, ac, shift);
+
+    temp127 = (temp[1] >> 63) & 0x01;
+
+    if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) {
+        temp[0] &= 0xFFFF0000;
+        temp[0] |= 0x00007FFF;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    } else if ((temp127 == 1) &&
+            (temp[1] < 0xFFFFFFFFFFFFFFFFll
+             || temp[0] < 0xFFFFFFFFFFFF1000ll)) {
+        temp[0] &= 0xFFFF0000;
+        temp[0] |= 0x00008000;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (int64_t)(int16_t)(temp[0] & MIPSDSP_LO);
+
+    return result;
+}
+
+target_ulong helper_dextrv_s_h(CPUMIPSState *env,
+                               uint32_t ac, target_ulong shift)
+{
+    int64_t temp[2];
+    uint32_t temp127;
+    uint64_t result;
+
+    shift = shift & 0x1F;
+    mipsdsp_rashift_acc(env, (uint64_t *)temp, ac, shift);
+
+    temp127 = (temp[1] >> 63) & 0x01;
+
+    if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) {
+        temp[0] &= 0xFFFF0000;
+        temp[0] |= 0x00007FFF;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    } else if ((temp127 == 1) &&
+            (temp[1] < 0xFFFFFFFFFFFFFFFFull
+             || temp[0] < 0xFFFFFFFFFFFF1000ull)) {
+        temp[0] &= 0xFFFF0000;
+        temp[0] |= 0x00008000;
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (int64_t)(int16_t)(temp[0] & MIPSDSP_LO);
+
+    return result;
+}
+#endif
+
+target_ulong helper_extrv_w(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    int32_t shift, tempI;
+    int64_t tempDL[2];
+
+    shift = rs & 0x0F;
+    mipsdsp__rashift_short_acc(env, tempDL, ac, shift);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    tempI = tempDL[0] >> 1;
+
+    tempDL[0] += 1;
+    if (tempDL[0] == 0) {
+        tempDL[1] += 1;
+    }
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    return (target_long)tempI;
+}
+
+target_ulong helper_extrv_r_w(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    int32_t shift, tempI;
+    int64_t tempDL[2];
+
+    shift = rs & 0x0F;
+    mipsdsp__rashift_short_acc(env, tempDL, ac, shift);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    tempDL[0] += 1;
+    if (tempDL[0] == 0) {
+        tempDL[1] += 1;
+    }
+
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+    tempI = tempDL[0] >> 1;
+
+    return (target_long)tempI;
+}
+
+target_ulong helper_extrv_rs_w(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    int32_t shift, tempI;
+    int64_t tempDL[2];
+
+    shift = rs & 0x0F;
+    mipsdsp__rashift_short_acc(env, tempDL, ac, shift);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    tempDL[0] += 1;
+    if (tempDL[0] == 0) {
+        tempDL[1] += 1;
+    }
+    tempI = tempDL[0] >> 1;
+
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        if (tempDL[1] == 0) {
+            tempI = 0x7FFFFFFF;
+        } else {
+            tempI = 0x80000000;
+        }
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    return (target_long)tempI;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dextrv_w(CPUMIPSState *env, uint32_t ac, target_ulong shift)
+{
+    uint64_t temp[3];
+    uint64_t result;
+
+    shift = shift & 0x1F;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    result = (int64_t)(int32_t)(temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextrv_r_w(CPUMIPSState *env,
+                               uint32_t ac, target_ulong shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    shift = shift & 0x1F;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xfffFfffFfffFfffFull)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (int64_t)(int32_t)(temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextrv_rs_w(CPUMIPSState *env,
+                                uint32_t ac, target_ulong shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    shift = shift & 0x1F;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xFFFFFFFFFFFFFFFFull)) {
+        if (temp128 == 0) {
+            temp[0] |= 0x0FFFFFFFF;
+        } else {
+            temp[0] = 0x0100000000;
+        }
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (int64_t)(int32_t)(temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextrv_l(CPUMIPSState *env, uint32_t ac, target_ulong shift)
+{
+    uint64_t temp[3];
+    uint64_t result;
+
+    shift = shift & 0x1F;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextrv_r_l(CPUMIPSState *env,
+                               uint32_t ac, target_ulong shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    shift = shift & 0x1F;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xfffFfffFfffFfffFull)) {
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextrv_rs_l(CPUMIPSState *env,
+                                uint32_t ac, target_ulong shift)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    uint64_t result;
+
+    shift = shift & 0x1F;
+
+    mipsdsp__rashift_acc(env, temp, ac, shift);
+
+    temp[0] += 1;
+    if (temp[0] == 0) {
+        temp[1] += 1;
+        if (temp[1] == 0) {
+            temp[2] += 1;
+        }
+    }
+
+    temp128 = temp[2] & 0x01;
+
+    if ((temp128 != 0 || temp[1] != 0) &&
+       (temp128 != 1 || temp[1] != 0xFFFFFFFFFFFFFFFFull)) {
+        if (temp128 == 0) {
+            temp[1] &= 0xFFFFFFFFFFFFFFFEull;
+            temp[0] |= 0xFFFFFFFFFFFFFFFEull;
+        } else {
+            temp[1] |= 0x01;
+            temp[0] &= 0x01;
+        }
+        set_DSPControl_overflow_flag(env, 1, 23);
+    }
+
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+#endif
+
+target_ulong helper_extp(CPUMIPSState *env, uint32_t ac, uint32_t size)
+{
+    int32_t start_pos;
+    int sub;
+    uint32_t temp;
+    uint64_t acc;
+
+    temp = 0;
+    start_pos = get_DSPControl_pos(env);
+    sub = start_pos - (size + 1);
+    if (sub >= -1) {
+        acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+              ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+        temp = (acc >> (start_pos - size)) &
+               (((uint32_t)0x01 << (size + 1)) - 1);
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return (target_ulong)temp;
+}
+
+target_ulong helper_extpv(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    int32_t start_pos, size;
+    uint32_t temp;
+    uint64_t acc;
+
+    temp = 0;
+    start_pos = get_DSPControl_pos(env);
+    size = rs & 0x1F;
+
+    if (start_pos - (size + 1) >= -1) {
+        acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
+              ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+        temp = (acc >> (start_pos - size)) &
+               (((uint32_t)0x01 << (size + 1)) - 1);
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return (target_ulong)temp;
+}
+
+target_ulong helper_extpdp(CPUMIPSState *env, uint32_t ac, uint32_t size)
+{
+    int32_t start_pos;
+    int sub;
+    uint32_t temp;
+    uint64_t acc;
+
+    temp = 0;
+    start_pos = get_DSPControl_pos(env);
+    sub = start_pos - (size + 1);
+    if (sub >= -1) {
+        acc  = ((uint64_t)env->active_tc.HI[ac] << 32) |
+               ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+        temp = (acc >> (start_pos - size)) &
+               (((uint32_t)0x01 << (size + 1)) - 1);
+
+        set_DSPControl_pos(env, start_pos - (size + 1));
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return (target_ulong)temp;
+}
+
+target_ulong helper_extpdpv(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    int32_t start_pos, size;
+    uint32_t temp;
+    uint64_t acc;
+
+    temp = 0;
+    start_pos = get_DSPControl_pos(env);
+    size = rs & 0x1F;
+
+    if (start_pos - (size + 1) >= -1) {
+        acc  = ((uint64_t)env->active_tc.HI[ac] << 32) |
+               ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+        temp = (acc >> (start_pos - size)) & (((int)0x01 << (size + 1)) - 1);
+        set_DSPControl_pos(env, start_pos - (size + 1));
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return (target_ulong)temp;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dextp(CPUMIPSState *env, uint32_t ac, uint32_t size)
+{
+    int start_pos;
+    int len;
+    int sub;
+    uint64_t tempB, tempA;
+    uint64_t temp;
+
+    temp = 0;
+
+    size = size & 0x3F;
+    start_pos = get_DSPControl_pos(env);
+    len = start_pos - size;
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+
+    sub = start_pos - (size + 1);
+
+    if (sub >= -1) {
+        temp = (tempB << (64 - len)) | (tempA >> len);
+        temp = temp & ((0x01 << (size + 1)) - 1);
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return temp;
+}
+
+target_ulong helper_dextpv(CPUMIPSState *env, uint32_t ac, target_ulong size)
+{
+    uint8_t start_pos;
+    uint8_t len;
+    int sub;
+    uint64_t tempB, tempA;
+    uint64_t temp;
+
+    temp = 0;
+
+    size = size & 0x3F;
+    start_pos = get_DSPControl_pos(env);
+    len = start_pos - size;
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+
+    sub = start_pos - (size + 1);
+
+    if (sub >= -1) {
+        temp = (tempB << (64 - len)) | (tempA >> len);
+        temp = temp & ((0x01 << (size + 1)) - 1);
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return temp;
+}
+
+target_ulong helper_dextpdp(CPUMIPSState *env, uint32_t ac, uint32_t size)
+{
+    int start_pos;
+    int len;
+    int sub;
+    uint64_t tempB, tempA;
+    uint64_t temp;
+
+    temp = 0;
+    start_pos = get_DSPControl_pos(env);
+    len = start_pos - size;
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+
+    sub = start_pos - (size + 1);
+
+    if (sub >= -1) {
+        temp = (tempB << (64 - len)) | (tempA >> len);
+        temp = temp & ((0x01 << (size + 1)) - 1);
+        set_DSPControl_pos(env, sub);
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return temp;
+}
+
+target_ulong helper_dextpdpv(CPUMIPSState *env, uint32_t ac, target_ulong size)
+{
+    int start_pos;
+    int len;
+    int sub;
+    uint64_t tempB, tempA;
+    uint64_t temp;
+
+    temp = 0;
+    start_pos = get_DSPControl_pos(env);
+    size = size & 0x3F;
+    len = start_pos - size;
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+
+    sub = start_pos - (size + 1);
+
+    if (sub >= -1) {
+        temp = (tempB << (64 - len)) | (tempA >> len);
+        temp = temp & ((0x01 << (size + 1)) - 1);
+        set_DSPControl_pos(env, sub);
+        set_DSPControl_efi(env, 0);
+    } else {
+        set_DSPControl_efi(env, 1);
+    }
+
+    return temp;
+}
+#endif
+
+void helper_shilo(CPUMIPSState *env, uint32_t ac, uint32_t shift)
+{
+    uint8_t  sign;
+    uint64_t temp, acc;
+
+    shift = (int32_t)((int32_t)shift << 26) >> 26;
+    sign  = (shift >>  5) & 0x01;
+    shift = (sign == 0) ? shift : -shift;
+    acc = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) |
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+
+    if (shift == 0) {
+        temp = acc;
+    } else {
+        if (sign == 0) {
+            temp = acc >> shift;
+        } else {
+            temp = acc << shift;
+        }
+    }
+
+    env->active_tc.HI[ac] = (target_long)(int32_t)((temp & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_long)(int32_t)(temp & MIPSDSP_LLO);
+}
+
+void helper_shilov(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    uint8_t sign;
+    int8_t  rs5_0;
+    uint64_t temp, acc;
+
+    rs5_0 = rs & 0x3F;
+    rs    = (int8_t)(rs5_0 << 2) >> 2;
+    sign  = (rs5_0 >> 5) & 0x01;
+    rs5_0 = (sign == 0) ? rs : -rs;
+    acc   = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) |
+            ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+    if (rs5_0 == 0) {
+        temp = acc;
+    } else {
+        if (sign == 0) {
+            temp = acc >> rs5_0;
+        } else {
+            temp = acc << rs5_0;
+        }
+    }
+
+    env->active_tc.HI[ac] = (target_ulong)(int32_t)((temp & MIPSDSP_LHI) >> 32);
+    env->active_tc.LO[ac] = (target_ulong)(int32_t)(temp & MIPSDSP_LLO);
+}
+
+#if defined(TARGET_MIPS64)
+void helper_dshilo(CPUMIPSState *env, uint32_t shift, uint32_t ac)
+{
+    uint8_t shift6;
+    int8_t shift_t;
+    uint64_t tempB, tempA;
+
+    shift6 = (shift >> 6) & 0x01;
+    shift_t = (shift6 << 7) | (uint8_t)shift;
+    shift_t = shift6 == 0 ? shift_t : -shift_t;
+
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+
+    if (shift_t != 0) {
+        if (shift6 == 0) {
+            tempA = (tempB << (64 - shift)) | (tempA >> shift);
+            tempB = tempB >> shift;
+        } else {
+            tempB = (tempB << shift) | (tempA >> (64 - shift));
+            tempA = tempA << shift;
+        }
+    }
+
+    env->active_tc.HI[ac] = tempB;
+    env->active_tc.LO[ac] = tempA;
+}
+
+void helper_dshilov(CPUMIPSState *env, target_ulong shift, uint32_t ac)
+{
+    uint8_t shift6;
+    int8_t shift_t;
+    uint64_t tempB, tempA;
+
+    shift6 = (shift >> 6) & 0x01;
+    shift_t = (shift6 << 7) | ((uint8_t)shift & 0x7F);
+    shift_t = shift6 == 0 ? shift_t : -shift_t;
+
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+
+    if (shift_t != 0) {
+        if (shift6 == 0) {
+            tempA = (tempB << (64 - shift)) | (tempA >> shift);
+            tempB = tempB >> shift;
+        } else {
+            tempB = (tempB << shift) | (tempA >> (64 - shift));
+            tempA = tempA << shift;
+        }
+    }
+
+    env->active_tc.HI[ac] = tempB;
+    env->active_tc.LO[ac] = tempA;
+}
+#endif
+void helper_mthlip(CPUMIPSState *env, uint32_t ac, target_ulong rs)
+{
+    int32_t tempA, tempB, pos;
+
+    tempA = rs;
+    tempB = env->active_tc.LO[ac];
+    env->active_tc.HI[ac] = (target_long)tempB;
+    env->active_tc.LO[ac] = (target_long)tempA;
+    pos = get_DSPControl_pos(env);
+
+    if (pos > 32) {
+        return;
+    } else {
+        set_DSPControl_pos(env, pos + 32);
+    }
+}
+
+#if defined(TARGET_MIPS64)
+void helper_dmthlip(CPUMIPSState *env, target_ulong rs, uint32_t ac)
+{
+    uint8_t ac_t;
+    uint8_t pos;
+    uint64_t tempB, tempA;
+
+    ac_t = ac & 0x3;
+
+    tempA = rs;
+    tempB = env->active_tc.LO[ac_t];
+
+    env->active_tc.HI[ac_t] = tempB;
+    env->active_tc.LO[ac_t] = tempA;
+
+    pos = get_DSPControl_pos(env);
+
+    if (pos <= 64) {
+        pos = pos + 64;
+        set_DSPControl_pos(env, pos);
+    }
+}
+#endif
+
+void helper_wrdsp(CPUMIPSState *env, target_ulong rs, uint32_t mask_num)
+{
+    uint8_t  mask[6];
+    uint8_t  i;
+    uint32_t newbits, overwrite;
+    target_ulong dsp;
+
+    newbits   = 0x00;
+    overwrite = 0xFFFFFFFF;
+    dsp = env->active_tc.DSPControl;
+
+    for (i = 0; i < 6; i++) {
+        mask[i] = (mask_num >> i) & 0x01;
+    }
+
+    if (mask[0] == 1) {
+#if defined(TARGET_MIPS64)
+        overwrite &= 0xFFFFFF80;
+        newbits   &= 0xFFFFFF80;
+        newbits   |= 0x0000007F & rs;
+#else
+        overwrite &= 0xFFFFFFC0;
+        newbits   &= 0xFFFFFFC0;
+        newbits   |= 0x0000003F & rs;
+#endif
+    }
+
+    if (mask[1] == 1) {
+        overwrite &= 0xFFFFE07F;
+        newbits   &= 0xFFFFE07F;
+        newbits   |= 0x00001F80 & rs;
+    }
+
+    if (mask[2] == 1) {
+        overwrite &= 0xFFFFDFFF;
+        newbits   &= 0xFFFFDFFF;
+        newbits   |= 0x00002000 & rs;
+    }
+
+    if (mask[3] == 1) {
+        overwrite &= 0xFF00FFFF;
+        newbits   &= 0xFF00FFFF;
+        newbits   |= 0x00FF0000 & rs;
+    }
+
+    if (mask[4] == 1) {
+        overwrite &= 0x00FFFFFF;
+        newbits   &= 0x00FFFFFF;
+        newbits   |= 0xFF000000 & rs;
+    }
+
+    if (mask[5] == 1) {
+        overwrite &= 0xFFFFBFFF;
+        newbits   &= 0xFFFFBFFF;
+        newbits   |= 0x00004000 & rs;
+    }
+
+    dsp = dsp & overwrite;
+    dsp = dsp | newbits;
+    env->active_tc.DSPControl = dsp;
+}
+
+target_ulong helper_rddsp(CPUMIPSState *env, uint32_t masknum)
+{
+    uint8_t  mask[6];
+    uint32_t ruler, i;
+    target_ulong temp;
+    target_ulong dsp;
+
+    ruler = 0x01;
+    for (i = 0; i < 6; i++) {
+        mask[i] = (masknum & ruler) >> i ;
+        ruler = ruler << 1;
+    }
+
+    temp  = 0x00;
+    dsp = env->active_tc.DSPControl;
+
+    if (mask[0] == 1) {
+#if defined(TARGET_MIPS64)
+        temp |= dsp & 0x7F;
+#else
+        temp |= dsp & 0x3F;
+#endif
+    }
+
+    if (mask[1] == 1) {
+        temp |= dsp & 0x1F80;
+    }
+
+    if (mask[2] == 1) {
+        temp |= dsp & 0x2000;
+    }
+
+    if (mask[3] == 1) {
+        temp |= dsp & 0x00FF0000;
+    }
+
+    if (mask[4] == 1) {
+        temp |= dsp & 0xFF000000;
+    }
+
+    if (mask[5] == 1) {
+        temp |= dsp & 0x4000;
+    }
+
+    return temp;
+}
+
 #undef MIPSDSP_LHI
 #undef MIPSDSP_LLO
 #undef MIPSDSP_HI
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 273501c..754fad5 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -641,4 +641,56 @@ DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
 DEF_HELPER_FLAGS_2(packrl_pw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
 #endif
 
+/* DSP Accumulator and DSPControl Access Sub-class insns */
+DEF_HELPER_FLAGS_3(extr_w, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(extr_r_w, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(extr_rs_w, 0, tl, env, i32, i32)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dextr_w, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextr_r_w, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextr_rs_w, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextr_l, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextr_r_l, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextr_rs_l, 0, tl, env, i32, i32)
+#endif
+DEF_HELPER_FLAGS_3(extr_s_h, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(extrv_s_h, 0, tl, env, i32, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dextr_s_h, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextrv_s_h, 0, tl, env, i32, tl)
+#endif
+DEF_HELPER_FLAGS_3(extrv_w, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(extrv_r_w, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(extrv_rs_w, 0, tl, env, i32, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dextrv_w, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(dextrv_r_w, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(dextrv_rs_w, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(dextrv_l, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(dextrv_r_l, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(dextrv_rs_l, 0, tl, env, i32, tl)
+#endif
+DEF_HELPER_FLAGS_3(extp, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(extpv, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(extpdp, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(extpdpv, 0, tl, env, i32, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dextp, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextpv, 0, tl, env, i32, tl)
+DEF_HELPER_FLAGS_3(dextpdp, 0, tl, env, i32, i32)
+DEF_HELPER_FLAGS_3(dextpdpv, 0, tl, env, i32, tl)
+#endif
+DEF_HELPER_FLAGS_3(shilo, 0, void, env, i32, i32)
+DEF_HELPER_FLAGS_3(shilov, 0, void, env, i32, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dshilo, 0, void, env, i32, i32)
+DEF_HELPER_FLAGS_3(dshilov, 0, void, env, tl, i32)
+#endif
+DEF_HELPER_FLAGS_3(mthlip, 0, void, env, i32, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dmthlip, 0, void, env, tl, i32)
+#endif
+DEF_HELPER_FLAGS_3(wrdsp, 0, void, env, tl, i32)
+DEF_HELPER_FLAGS_2(rddsp, 0, tl, env, i32)
+
 #include "def-helper.h"
diff --git a/target-mips/translate.c b/target-mips/translate.c
index b493582..577944e 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -353,6 +353,11 @@ enum {
 #if defined(TARGET_MIPS64)
     OPC_DAPPEND_DSP    = 0x35 | OPC_SPECIAL3,
 #endif
+    /* MIPS DSP Accumulator and DSPControl Access Sub-class */
+    OPC_EXTR_W_DSP     = 0x38 | OPC_SPECIAL3,
+#if defined(TARGET_MIPS64)
+    OPC_DEXTR_W_DSP    = 0x3C | OPC_SPECIAL3,
+#endif
 };
 
 /* BSHFL opcodes */
@@ -564,6 +569,28 @@ enum {
     OPC_BALIGN  = (0x10 << 6) | OPC_APPEND_DSP,
 };
 
+#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Accumulator and DSPControl Access Sub-class */
+    OPC_EXTR_W     = (0x00 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTR_R_W   = (0x04 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTR_RS_W  = (0x06 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTR_S_H   = (0x0E << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTRV_S_H  = (0x0F << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTRV_W    = (0x01 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTRV_R_W  = (0x05 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTP       = (0x02 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTPV      = (0x03 << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTPDP     = (0x0A << 6) | OPC_EXTR_W_DSP,
+    OPC_EXTPDPV    = (0x0B << 6) | OPC_EXTR_W_DSP,
+    OPC_SHILO      = (0x1A << 6) | OPC_EXTR_W_DSP,
+    OPC_SHILOV     = (0x1B << 6) | OPC_EXTR_W_DSP,
+    OPC_MTHLIP     = (0x1F << 6) | OPC_EXTR_W_DSP,
+    OPC_WRDSP      = (0x13 << 6) | OPC_EXTR_W_DSP,
+    OPC_RDDSP      = (0x12 << 6) | OPC_EXTR_W_DSP,
+};
+
 #if defined(TARGET_MIPS64)
 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
@@ -676,6 +703,34 @@ enum {
 #endif
 
 #if defined(TARGET_MIPS64)
+#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
+enum {
+    /* MIPS DSP Accumulator and DSPControl Access Sub-class */
+    OPC_DMTHLIP     = (0x1F << 6) | OPC_DEXTR_W_DSP,
+    OPC_DSHILO      = (0x1A << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTP       = (0x02 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTPDP     = (0x0A << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTPDPV    = (0x0B << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTPV      = (0x03 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_L     = (0x10 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_R_L   = (0x14 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_RS_L  = (0x16 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_W     = (0x00 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_R_W   = (0x04 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_RS_W  = (0x06 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTR_S_H   = (0x0E << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_L    = (0x11 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_R_L  = (0x15 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_S_H  = (0x0F << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_W    = (0x01 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_R_W  = (0x05 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
+    OPC_DSHILOV     = (0x1B << 6) | OPC_DEXTR_W_DSP,
+};
+#endif
+
+#if defined(TARGET_MIPS64)
 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
     /* DSP Bit/Manipulation Sub-class */
@@ -13482,6 +13537,178 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 break;
             }
             break;
+        case OPC_EXTR_W_DSP:
+            op2 = MASK_EXTR_W(ctx->opcode);
+            switch (op2) {
+            case OPC_EXTR_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    TCGv_i32 temp_rs = tcg_const_i32(rs);
+                    gen_helper_extr_w(cpu_gpr[rt], cpu_env, temp_rd, temp_rs);
+                    tcg_temp_free_i32(temp_rd);
+                    tcg_temp_free_i32(temp_rs);
+                    break;
+                }
+            case OPC_EXTR_R_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    TCGv_i32 temp_rs = tcg_const_i32(rs);
+                    gen_helper_extr_r_w(cpu_gpr[rt], cpu_env, temp_rd, temp_rs);
+                    tcg_temp_free_i32(temp_rd);
+                    tcg_temp_free_i32(temp_rs);
+                    break;
+                }
+            case OPC_EXTR_RS_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    TCGv_i32 temp_rs = tcg_const_i32(rs);
+                    gen_helper_extr_rs_w(cpu_gpr[rt], cpu_env,
+                                         temp_rd, temp_rs);
+                    tcg_temp_free_i32(temp_rd);
+                    tcg_temp_free_i32(temp_rs);
+                    break;
+                }
+            case OPC_EXTR_S_H:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    TCGv_i32 temp_rs = tcg_const_i32(rs);
+                    gen_helper_extr_s_h(cpu_gpr[rt], cpu_env, temp_rd, temp_rs);
+                    tcg_temp_free_i32(temp_rd);
+                    tcg_temp_free_i32(temp_rs);
+                    break;
+                }
+            case OPC_EXTRV_S_H:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_extrv_s_h(cpu_gpr[rt], cpu_env,
+                                         temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_EXTRV_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_extrv_w(cpu_gpr[rt], cpu_env,
+                                       temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_EXTRV_R_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_extrv_r_w(cpu_gpr[rt], cpu_env,
+                                         temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_EXTRV_RS_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_extrv_rs_w(cpu_gpr[rt], cpu_env,
+                                          temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_EXTP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    TCGv_i32 temp_rs = tcg_const_i32(rs);
+                    gen_helper_extp(cpu_gpr[rt], cpu_env, temp_rd, temp_rs);
+                    tcg_temp_free_i32(temp_rd);
+                    tcg_temp_free_i32(temp_rs);
+                    break;
+                }
+            case OPC_EXTPV:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_extpv(cpu_gpr[rt], cpu_env,
+                                     temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_EXTPDP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    TCGv_i32 temp_rs = tcg_const_i32(rs);
+                    gen_helper_extpdp(cpu_gpr[rt], cpu_env, temp_rd, temp_rs);
+                    tcg_temp_free_i32(temp_rd);
+                    tcg_temp_free_i32(temp_rs);
+                    break;
+                }
+            case OPC_EXTPDPV:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_extpdpv(cpu_gpr[rt], cpu_env,
+                                       temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_SHILO:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_imm;
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    imm = (ctx->opcode >> 20) & 0x3F;
+                    temp_imm = tcg_const_i32(imm);
+                    gen_helper_shilo(cpu_env, temp_rd, temp_imm);
+                    tcg_temp_free_i32(temp_imm);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_SHILOV:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_shilov(cpu_env, temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_MTHLIP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_rd = tcg_const_i32(rd);
+                    gen_helper_mthlip(cpu_env, temp_rd, cpu_gpr[rs]);
+                    tcg_temp_free_i32(temp_rd);
+                    break;
+                }
+            case OPC_WRDSP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_imm;
+                    imm = (ctx->opcode >> 11) & 0x3FF;
+                    temp_imm = tcg_const_i32(imm);
+                    gen_helper_wrdsp(cpu_env, cpu_gpr[rs], temp_imm);
+                    tcg_temp_free_i32(temp_imm);
+                    break;
+                }
+            case OPC_RDDSP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 temp_imm;
+                    imm = (ctx->opcode >> 16) & 0x03FF;
+                    temp_imm = tcg_const_i32(imm);
+                    gen_helper_rddsp(cpu_gpr[rd], cpu_env, temp_imm);
+                    tcg_temp_free_i32(temp_imm);
+                    break;
+                }
+            default:            /* Invalid */
+                MIPS_INVAL("MASK EXTR.W");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
@@ -14022,6 +14249,240 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             break;
 #endif
 #if defined(TARGET_MIPS64)
+        case OPC_DEXTR_W_DSP:
+            op2 = MASK_DEXTR_W(ctx->opcode);
+            switch (op2) {
+            case OPC_DMTHLIP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    TCGv_i32 ac_v = tcg_const_i32(rd);
+                    gen_helper_dmthlip(cpu_env, cpu_gpr[rs], ac_v);
+                    tcg_temp_free_i32(ac_v);
+                    break;
+                }
+            case OPC_DSHILO:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int shift = (ctx->opcode >> 19) & 0x7F;
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 shift_v = tcg_const_i32(shift);
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+
+                    gen_helper_dshilo(cpu_env, shift_v, ac_v);
+
+                    tcg_temp_free_i32(shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    break;
+                }
+            case OPC_DSHILOV:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    gen_helper_dshilov(cpu_env, cpu_gpr[rs], ac_v);
+                    tcg_temp_free_i32(ac_v);
+                    break;
+                }
+            case OPC_DEXTP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 size_v = tcg_const_i32(rs);
+                    gen_helper_dextp(cpu_gpr[rt], cpu_env, ac_v, size_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(size_v);
+                    break;
+                }
+            case OPC_DEXTPV:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    gen_helper_dextpv(cpu_gpr[rt], cpu_env,
+                                      ac_v, cpu_gpr[rs]);
+                    tcg_temp_free_i32(ac_v);
+                    break;
+                }
+            case OPC_DEXTPDP:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 size_v = tcg_const_i32(rs);
+                    gen_helper_dextpdp(cpu_gpr[rt], cpu_env, ac_v, size_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(size_v);
+                    break;
+                }
+            case OPC_DEXTPDPV:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    gen_helper_dextpdpv(cpu_gpr[rt], cpu_env,
+                                        ac_v, cpu_gpr[rs]);
+                    tcg_temp_free_i32(ac_v);
+                    break;
+                }
+            case OPC_DEXTR_L:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_l(cpu_gpr[rt], cpu_env, ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTR_R_L:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_r_l(cpu_gpr[rt], cpu_env, ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTR_RS_L:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_rs_l(cpu_gpr[rt], cpu_env,
+                                          ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTR_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_w(cpu_gpr[rt], cpu_env, ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTR_R_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_r_w(cpu_gpr[rt], cpu_env, ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTR_RS_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_rs_w(cpu_gpr[rt], cpu_env, ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTR_S_H:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextr_s_h(cpu_gpr[rt], cpu_env, ac_v, shift_v);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTRV_S_H:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                    int ac = (ctx->opcode >> 11) & 0x03;
+                    TCGv_i32 ac_v = tcg_const_i32(ac);
+                    TCGv_i32 shift_v = tcg_const_i32(rs);
+                    gen_helper_dextrv_s_h(cpu_gpr[rt], cpu_env,
+                                          ac_v, cpu_gpr[rs]);
+                    tcg_temp_free_i32(ac_v);
+                    tcg_temp_free_i32(shift_v);
+                    break;
+                }
+            case OPC_DEXTRV_L:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                  int ac = (ctx->opcode >> 11) & 0x03;
+                  TCGv_i32 ac_v = tcg_const_i32(ac);
+                  gen_helper_dextrv_l(cpu_gpr[rt], cpu_env,
+                                      ac_v, cpu_gpr[rs]);
+                  tcg_temp_free_i32(ac_v);
+                  break;
+                }
+            case OPC_DEXTRV_R_L:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                  int ac = (ctx->opcode >> 11) & 0x03;
+                  TCGv_i32 ac_v = tcg_const_i32(ac);
+                  gen_helper_dextrv_r_l(cpu_gpr[rt], cpu_env,
+                                        ac_v, cpu_gpr[rs]);
+                  tcg_temp_free_i32(ac_v);
+                  break;
+                }
+            case OPC_DEXTRV_RS_L:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                  int ac = (ctx->opcode >> 11) & 0x03;
+                  TCGv_i32 ac_v = tcg_const_i32(ac);
+                  gen_helper_dextrv_rs_l(cpu_gpr[rt], cpu_env,
+                                         ac_v, cpu_gpr[rs]);
+                  tcg_temp_free_i32(ac_v);
+                  break;
+                }
+            case OPC_DEXTRV_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                  int ac = (ctx->opcode >> 11) & 0x03;
+                  TCGv_i32 ac_v = tcg_const_i32(ac);
+                  gen_helper_dextrv_w(cpu_gpr[rt], cpu_env,
+                                      ac_v, cpu_gpr[rs]);
+                  tcg_temp_free_i32(ac_v);
+                  break;
+                }
+            case OPC_DEXTRV_R_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                  int ac = (ctx->opcode >> 11) & 0x03;
+                  TCGv_i32 ac_v = tcg_const_i32(ac);
+                  gen_helper_dextrv_r_w(cpu_gpr[rt], cpu_env,
+                                        ac_v, cpu_gpr[rs]);
+                  tcg_temp_free_i32(ac_v);
+                  break;
+                }
+            case OPC_DEXTRV_RS_W:
+                check_insn(env, ctx, ASE_DSP);
+                {
+                  int ac = (ctx->opcode >> 11) & 0x03;
+                  TCGv_i32 ac_v = tcg_const_i32(ac);
+                  gen_helper_dextrv_rs_w(cpu_gpr[rt], cpu_env,
+                                         ac_v, cpu_gpr[rs]);
+                  tcg_temp_free_i32(ac_v);
+                  break;
+                }
+            default:            /* Invalid */
+                MIPS_INVAL("MASK EXTR.W");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+#endif
+#if defined(TARGET_MIPS64)
         case OPC_DPAQ_W_QH_DSP:
             {
                 int ac = rd & 0x03;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v6 11/13] target-mips-ase-dsp: Add MIPS[32|64] ASE DSP[R1|R2] generic cpu model
  2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
                   ` (9 preceding siblings ...)
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 10/13] target-mips-ase-dsp: Add MIPS ASE DSP Accumulator and DSPControl Access instructions Jia Liu
@ 2012-08-21  6:53 ` Jia Liu
  2012-08-21  9:32 ` [Qemu-devel] [PATCH v6 12/13] target-mips-ase-dsp: Add testcases Jia Liu
  2012-08-21  9:34 ` [Qemu-devel] [PATCH v6 13/13] target-mips-ase-dsp: Change TODO Jia Liu
  12 siblings, 0 replies; 20+ messages in thread
From: Jia Liu @ 2012-08-21  6:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Add MIPS[32|64] ASE DSP[R1|R2] generic cpu model for test.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/translate_init.c |   55 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index c39138f..547fa00 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -311,6 +311,32 @@ static const mips_def_t mips_defs[] =
         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT,
         .mmu_type = MMU_TYPE_R4000,
     },
+    {
+        /* A generic CPU providing MIPS32 ASE DSP Release 2 features.
+           FIXME: Eventually this should be replaced by a real CPU model. */
+        .name = "mips32dspr2",
+        .CP0_PRid = 0x00019300,
+        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
+                    (MMU_TYPE_R4000 << CP0C0_MT),
+        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
+                       (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
+                       (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
+                       (1 << CP0C1_CA),
+        .CP0_Config2 = MIPS_CONFIG2,
+        .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
+        .CP0_LLAddr_rw_bitmask = 0,
+        .CP0_LLAddr_shift = 4,
+        .SYNCI_Step = 32,
+        .CCRes = 2,
+        /* No DSP implemented. */
+        .CP0_Status_rw_bitmask = 0x3678FF1F,
+        .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
+                    (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
+        .SEGBITS = 32,
+        .PABITS = 32,
+        .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2,
+        .mmu_type = MMU_TYPE_R4000,
+    },
 #if defined(TARGET_MIPS64)
     {
         .name = "R4000",
@@ -484,6 +510,35 @@ static const mips_def_t mips_defs[] =
       .insn_flags = CPU_LOONGSON2F,
       .mmu_type = MMU_TYPE_R4000,
     },
+    {
+        /* A generic CPU providing MIPS64 ASE DSP Release 2 features.
+           FIXME: Eventually this should be replaced by a real CPU model. */
+        .name = "mips64dspr2",
+        /* We emulate a later version of the 20Kc, earlier ones had a broken
+           WAIT instruction. */
+        .CP0_PRid = 0x000182a0,
+        .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) |
+                    (MMU_TYPE_R4000 << CP0C0_MT) | (1 << CP0C0_VI),
+        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (47 << CP0C1_MMU) |
+                       (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
+                       (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
+                       (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
+        .CP0_Config2 = MIPS_CONFIG2,
+        .CP0_Config3 = MIPS_CONFIG3,
+        .CP0_LLAddr_rw_bitmask = 0,
+        .CP0_LLAddr_shift = 0,
+        .SYNCI_Step = 32,
+        .CCRes = 1,
+        .CP0_Status_rw_bitmask = 0x36FBFFFF,
+        /* The 20Kc has F64 / L / W but doesn't use the fcr0 bits. */
+        .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) |
+                    (1 << FCR0_D) | (1 << FCR0_S) |
+                    (0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .SEGBITS = 40,
+        .PABITS = 36,
+        .insn_flags = CPU_MIPS64R2 | ASE_DSP | ASE_DSPR2,
+        .mmu_type = MMU_TYPE_R4000,
+    },
 
 #endif
 };
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v6 12/13] target-mips-ase-dsp: Add testcases
  2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
                   ` (10 preceding siblings ...)
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 11/13] target-mips-ase-dsp: Add MIPS[32|64] ASE DSP[R1|R2] generic cpu model Jia Liu
@ 2012-08-21  9:32 ` Jia Liu
  2012-08-21  9:34 ` [Qemu-devel] [PATCH v6 13/13] target-mips-ase-dsp: Change TODO Jia Liu
  12 siblings, 0 replies; 20+ messages in thread
From: Jia Liu @ 2012-08-21  9:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Add MIPS ASE DSP testcases.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 tests/tcg/mips/mips32-dsp/Makefile             |  134 +++++++++++
 tests/tcg/mips/mips32-dsp/absq_s_ph.c          |   31 +++
 tests/tcg/mips/mips32-dsp/absq_s_w.c           |   37 +++
 tests/tcg/mips/mips32-dsp/addq_ph.c            |   30 +++
 tests/tcg/mips/mips32-dsp/addq_s_ph.c          |   30 +++
 tests/tcg/mips/mips32-dsp/addsc.c              |   30 +++
 tests/tcg/mips/mips32-dsp/addu_qb.c            |   30 +++
 tests/tcg/mips/mips32-dsp/addu_s_qb.c          |   30 +++
 tests/tcg/mips/mips32-dsp/addwc.c              |   30 +++
 tests/tcg/mips/mips32-dsp/bitrev.c             |   20 ++
 tests/tcg/mips/mips32-dsp/bposge32.c           |   44 ++++
 tests/tcg/mips/mips32-dsp/cmp_eq_ph.c          |   35 +++
 tests/tcg/mips/mips32-dsp/cmp_le_ph.c          |   35 +++
 tests/tcg/mips/mips32-dsp/cmp_lt_ph.c          |   35 +++
 tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c        |   31 +++
 tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c        |   31 +++
 tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c        |   31 +++
 tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c         |   35 +++
 tests/tcg/mips/mips32-dsp/cmpu_le_qb.c         |   35 +++
 tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c         |   35 +++
 tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c        |   31 +++
 tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c        |   31 +++
 tests/tcg/mips/mips32-dsp/dpau_h_qbl.c         |   27 +++
 tests/tcg/mips/mips32-dsp/dpau_h_qbr.c         |   27 +++
 tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c        |   27 +++
 tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c        |   31 +++
 tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c         |   27 +++
 tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c         |   27 +++
 tests/tcg/mips/mips32-dsp/extp.c               |   44 ++++
 tests/tcg/mips/mips32-dsp/extpdp.c             |   46 ++++
 tests/tcg/mips/mips32-dsp/extpdpv.c            |   47 ++++
 tests/tcg/mips/mips32-dsp/extpv.c              |   45 ++++
 tests/tcg/mips/mips32-dsp/extr_r_w.c           |   25 ++
 tests/tcg/mips/mips32-dsp/extr_rs_w.c          |   25 ++
 tests/tcg/mips/mips32-dsp/extr_s_h.c           |   25 ++
 tests/tcg/mips/mips32-dsp/extr_w.c             |   25 ++
 tests/tcg/mips/mips32-dsp/extrv_r_w.c          |   29 +++
 tests/tcg/mips/mips32-dsp/extrv_rs_w.c         |   29 +++
 tests/tcg/mips/mips32-dsp/extrv_s_h.c          |   29 +++
 tests/tcg/mips/mips32-dsp/extrv_w.c            |   29 +++
 tests/tcg/mips/mips32-dsp/insv.c               |   23 ++
 tests/tcg/mips/mips32-dsp/lbux.c               |   25 ++
 tests/tcg/mips/mips32-dsp/lhx.c                |   25 ++
 tests/tcg/mips/mips32-dsp/lwx.c                |   25 ++
 tests/tcg/mips/mips32-dsp/madd.c               |   31 +++
 tests/tcg/mips/mips32-dsp/maddu.c              |   31 +++
 tests/tcg/mips/mips32-dsp/main.c               |    6 +
 tests/tcg/mips/mips32-dsp/maq_s_w_phl.c        |   31 +++
 tests/tcg/mips/mips32-dsp/maq_s_w_phr.c        |   31 +++
 tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c       |   31 +++
 tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c       |   31 +++
 tests/tcg/mips/mips32-dsp/mfhi.c               |   21 ++
 tests/tcg/mips/mips32-dsp/mflo.c               |   21 ++
 tests/tcg/mips/mips32-dsp/modsub.c             |   30 +++
 tests/tcg/mips/mips32-dsp/msub.c               |   30 +++
 tests/tcg/mips/mips32-dsp/msubu.c              |   30 +++
 tests/tcg/mips/mips32-dsp/mthi.c               |   21 ++
 tests/tcg/mips/mips32-dsp/mthlip.c             |   34 +++
 tests/tcg/mips/mips32-dsp/mtlo.c               |   21 ++
 tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c      |   40 ++++
 tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c     |   25 ++
 tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c     |   25 ++
 tests/tcg/mips/mips32-dsp/mulq_rs_ph.c         |   25 ++
 tests/tcg/mips/mips32-dsp/mult.c               |   24 ++
 tests/tcg/mips/mips32-dsp/multu.c              |   24 ++
 tests/tcg/mips/mips32-dsp/out                  |  110 +++++++++
 tests/tcg/mips/mips32-dsp/packrl_ph.c          |   21 ++
 tests/tcg/mips/mips32-dsp/pick_ph.c            |   23 ++
 tests/tcg/mips/mips32-dsp/pick_qb.c            |   23 ++
 tests/tcg/mips/mips32-dsp/preceq_w_phl.c       |   20 ++
 tests/tcg/mips/mips32-dsp/preceq_w_phr.c       |   20 ++
 tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c     |   20 ++
 tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c    |   20 ++
 tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c     |   20 ++
 tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c    |   20 ++
 tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c      |   20 ++
 tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c     |   20 ++
 tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c      |   20 ++
 tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c     |   20 ++
 tests/tcg/mips/mips32-dsp/precrq_ph_w.c        |   21 ++
 tests/tcg/mips/mips32-dsp/precrq_qb_ph.c       |   21 ++
 tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c     |   21 ++
 tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c    |   21 ++
 tests/tcg/mips/mips32-dsp/raddu_w_qb.c         |   20 ++
 tests/tcg/mips/mips32-dsp/rddsp.c              |   54 +++++
 tests/tcg/mips/mips32-dsp/repl_ph.c            |   23 ++
 tests/tcg/mips/mips32-dsp/repl_qb.c            |   16 ++
 tests/tcg/mips/mips32-dsp/replv_ph.c           |   19 ++
 tests/tcg/mips/mips32-dsp/replv_qb.c           |   19 ++
 tests/tcg/mips/mips32-dsp/shilo.c              |   27 +++
 tests/tcg/mips/mips32-dsp/shilov.c             |   29 +++
 tests/tcg/mips/mips32-dsp/shll_ph.c            |   24 ++
 tests/tcg/mips/mips32-dsp/shll_qb.c            |   23 ++
 tests/tcg/mips/mips32-dsp/shll_s_ph.c          |   24 ++
 tests/tcg/mips/mips32-dsp/shll_s_w.c           |   24 ++
 tests/tcg/mips/mips32-dsp/shllv_ph.c           |   25 ++
 tests/tcg/mips/mips32-dsp/shllv_qb.c           |   24 ++
 tests/tcg/mips/mips32-dsp/shllv_s_ph.c         |   25 ++
 tests/tcg/mips/mips32-dsp/shllv_s_w.c          |   25 ++
 tests/tcg/mips/mips32-dsp/shra_ph.c            |   20 ++
 tests/tcg/mips/mips32-dsp/shra_r_ph.c          |   20 ++
 tests/tcg/mips/mips32-dsp/shra_r_w.c           |   20 ++
 tests/tcg/mips/mips32-dsp/shrav_ph.c           |   21 ++
 tests/tcg/mips/mips32-dsp/shrav_r_ph.c         |   21 ++
 tests/tcg/mips/mips32-dsp/shrav_r_w.c          |   21 ++
 tests/tcg/mips/mips32-dsp/shrl_qb.c            |   20 ++
 tests/tcg/mips/mips32-dsp/shrlv_qb.c           |   21 ++
 tests/tcg/mips/mips32-dsp/subq_ph.c            |   25 ++
 tests/tcg/mips/mips32-dsp/subq_s_ph.c          |   25 ++
 tests/tcg/mips/mips32-dsp/subq_s_w.c           |   25 ++
 tests/tcg/mips/mips32-dsp/subu_qb.c            |   25 ++
 tests/tcg/mips/mips32-dsp/subu_s_qb.c          |   25 ++
 tests/tcg/mips/mips32-dsp/wrdsp.c              |   54 +++++
 tests/tcg/mips/mips32-dspr2/Makefile           |   72 ++++++
 tests/tcg/mips/mips32-dspr2/absq_s_qb.c        |   35 +++
 tests/tcg/mips/mips32-dspr2/addqh_ph.c         |   30 +++
 tests/tcg/mips/mips32-dspr2/addqh_r_ph.c       |   30 +++
 tests/tcg/mips/mips32-dspr2/addqh_r_w.c        |   34 +++
 tests/tcg/mips/mips32-dspr2/addqh_w.c          |   34 +++
 tests/tcg/mips/mips32-dspr2/addu_ph.c          |   30 +++
 tests/tcg/mips/mips32-dspr2/addu_s_ph.c        |   30 +++
 tests/tcg/mips/mips32-dspr2/adduh_qb.c         |   30 +++
 tests/tcg/mips/mips32-dspr2/adduh_r_qb.c       |   30 +++
 tests/tcg/mips/mips32-dspr2/append.c           |   30 +++
 tests/tcg/mips/mips32-dspr2/balign.c           |   30 +++
 tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c     |   37 +++
 tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c     |   37 +++
 tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c     |   37 +++
 tests/tcg/mips/mips32-dspr2/dpa_w_ph.c         |   27 +++
 tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c     |   57 +++++
 tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c    |   31 +++
 tests/tcg/mips/mips32-dspr2/dpax_w_ph.c        |   27 +++
 tests/tcg/mips/mips32-dspr2/dps_w_ph.c         |   27 +++
 tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c     |   31 +++
 tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c    |   31 +++
 tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c        |   27 +++
 tests/tcg/mips/mips32-dspr2/mul_ph.c           |   25 ++
 tests/tcg/mips/mips32-dspr2/mul_s_ph.c         |   25 ++
 tests/tcg/mips/mips32-dspr2/muleq_s_w_phl.c    |   40 ++++
 tests/tcg/mips/mips32-dspr2/mulq_rs_w.c        |   36 +++
 tests/tcg/mips/mips32-dspr2/mulq_s_ph.c        |   25 ++
 tests/tcg/mips/mips32-dspr2/mulq_s_w.c         |   36 +++
 tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c       |   29 +++
 tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c    |   29 +++
 tests/tcg/mips/mips32-dspr2/precr_qb_ph.c      |   21 ++
 tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c   |   32 +++
 tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c |   32 +++
 tests/tcg/mips/mips32-dspr2/prepend.c          |   30 +++
 tests/tcg/mips/mips32-dspr2/shra_qb.c          |   30 +++
 tests/tcg/mips/mips32-dspr2/shra_r_qb.c        |   30 +++
 tests/tcg/mips/mips32-dspr2/shrav_qb.c         |   32 +++
 tests/tcg/mips/mips32-dspr2/shrav_r_qb.c       |   32 +++
 tests/tcg/mips/mips32-dspr2/shrl_ph.c          |   20 ++
 tests/tcg/mips/mips32-dspr2/shrlv_ph.c         |   21 ++
 tests/tcg/mips/mips32-dspr2/subqh_ph.c         |   21 ++
 tests/tcg/mips/mips32-dspr2/subqh_r_ph.c       |   21 ++
 tests/tcg/mips/mips32-dspr2/subqh_r_w.c        |   21 ++
 tests/tcg/mips/mips32-dspr2/subqh_w.c          |   21 ++
 tests/tcg/mips/mips32-dspr2/subu_ph.c          |   25 ++
 tests/tcg/mips/mips32-dspr2/subu_s_ph.c        |   25 ++
 tests/tcg/mips/mips32-dspr2/subuh_qb.c         |   21 ++
 tests/tcg/mips/mips32-dspr2/subuh_r_qb.c       |   21 ++
 tests/tcg/mips/mips64-dsp/Makefile             |  304 ++++++++++++++++++++++++
 tests/tcg/mips/mips64-dsp/absq_s_ob.c          |   63 +++++
 tests/tcg/mips/mips64-dsp/absq_s_ph.c          |   37 +++
 tests/tcg/mips/mips64-dsp/absq_s_pw.c          |   66 +++++
 tests/tcg/mips/mips64-dsp/absq_s_qh.c          |   40 ++++
 tests/tcg/mips/mips64-dsp/absq_s_w.c           |   48 ++++
 tests/tcg/mips/mips64-dsp/addq_ph.c            |   37 +++
 tests/tcg/mips/mips64-dsp/addq_pw.c            |   26 ++
 tests/tcg/mips/mips64-dsp/addq_qh.c            |   28 +++
 tests/tcg/mips/mips64-dsp/addq_s_ph.c          |   37 +++
 tests/tcg/mips/mips64-dsp/addq_s_pw.c          |   45 ++++
 tests/tcg/mips/mips64-dsp/addq_s_qh.c          |   26 ++
 tests/tcg/mips/mips64-dsp/addsc.c              |   37 +++
 tests/tcg/mips/mips64-dsp/addu_ob.c            |   27 +++
 tests/tcg/mips/mips64-dsp/addu_qb.c            |   37 +++
 tests/tcg/mips/mips64-dsp/addu_s_ob.c          |   27 +++
 tests/tcg/mips/mips64-dsp/addu_s_qb.c          |   38 +++
 tests/tcg/mips/mips64-dsp/addwc.c              |   37 +++
 tests/tcg/mips/mips64-dsp/bitrev.c             |   23 ++
 tests/tcg/mips/mips64-dsp/bposge32.c           |   50 ++++
 tests/tcg/mips/mips64-dsp/bposge64.c           |   50 ++++
 tests/tcg/mips/mips64-dsp/cmp_eq_ph.c          |   42 ++++
 tests/tcg/mips/mips64-dsp/cmp_eq_pw.c          |   27 +++
 tests/tcg/mips/mips64-dsp/cmp_eq_qh.c          |   27 +++
 tests/tcg/mips/mips64-dsp/cmp_le_ph.c          |   40 ++++
 tests/tcg/mips/mips64-dsp/cmp_le_pw.c          |   27 +++
 tests/tcg/mips/mips64-dsp/cmp_le_qh.c          |   27 +++
 tests/tcg/mips/mips64-dsp/cmp_lt_ph.c          |   41 ++++
 tests/tcg/mips/mips64-dsp/cmp_lt_pw.c          |   27 +++
 tests/tcg/mips/mips64-dsp/cmp_lt_qh.c          |   27 +++
 tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c        |   24 ++
 tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c        |   38 +++
 tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c        |   24 ++
 tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c        |   37 +++
 tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c        |   24 ++
 tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c        |   38 +++
 tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c         |   27 +++
 tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c         |   42 ++++
 tests/tcg/mips/mips64-dsp/cmpu_le_ob.c         |   26 ++
 tests/tcg/mips/mips64-dsp/cmpu_le_qb.c         |   41 ++++
 tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c         |   26 ++
 tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c         |   42 ++++
 tests/tcg/mips/mips64-dsp/dappend.c            |   37 +++
 tests/tcg/mips/mips64-dsp/dextp.c              |   33 +++
 tests/tcg/mips/mips64-dsp/dextpdp.c            |   37 +++
 tests/tcg/mips/mips64-dsp/dextpdpv.c           |   38 +++
 tests/tcg/mips/mips64-dsp/dextpv.c             |   34 +++
 tests/tcg/mips/mips64-dsp/dextr_l.c            |   27 +++
 tests/tcg/mips/mips64-dsp/dextr_r_l.c          |   32 +++
 tests/tcg/mips/mips64-dsp/dextr_r_w.c          |   32 +++
 tests/tcg/mips/mips64-dsp/dextr_rs_l.c         |   31 +++
 tests/tcg/mips/mips64-dsp/dextr_rs_w.c         |   31 +++
 tests/tcg/mips/mips64-dsp/dextr_s_h.c          |   31 +++
 tests/tcg/mips/mips64-dsp/dextr_w.c            |   27 +++
 tests/tcg/mips/mips64-dsp/dextrv_l.c           |   28 +++
 tests/tcg/mips/mips64-dsp/dextrv_r_l.c         |   33 +++
 tests/tcg/mips/mips64-dsp/dextrv_r_w.c         |   33 +++
 tests/tcg/mips/mips64-dsp/dextrv_rs_l.c        |   32 +++
 tests/tcg/mips/mips64-dsp/dextrv_rs_w.c        |   32 +++
 tests/tcg/mips/mips64-dsp/dextrv_s_h.c         |   32 +++
 tests/tcg/mips/mips64-dsp/dextrv_w.c           |   28 +++
 tests/tcg/mips/mips64-dsp/dinsv.c              |   25 ++
 tests/tcg/mips/mips64-dsp/dmadd.c              |   57 +++++
 tests/tcg/mips/mips64-dsp/dmaddu.c             |   56 +++++
 tests/tcg/mips/mips64-dsp/dmsub.c              |   59 +++++
 tests/tcg/mips/mips64-dsp/dmsubu.c             |   59 +++++
 tests/tcg/mips/mips64-dsp/dmthlip.c            |   32 +++
 tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c        |   32 +++
 tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c        |   57 +++++
 tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c       |   62 +++++
 tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c        |   32 +++
 tests/tcg/mips/mips64-dsp/dpau_h_obl.c         |   59 +++++
 tests/tcg/mips/mips64-dsp/dpau_h_obr.c         |   59 +++++
 tests/tcg/mips/mips64-dsp/dpau_h_qbl.c         |   29 +++
 tests/tcg/mips/mips64-dsp/dpau_h_qbr.c         |   29 +++
 tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c        |   29 +++
 tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c        |   33 +++
 tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c       |   39 +++
 tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c        |   32 +++
 tests/tcg/mips/mips64-dsp/dpsu_h_obl.c         |   32 +++
 tests/tcg/mips/mips64-dsp/dpsu_h_obr.c         |   32 +++
 tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c         |   29 +++
 tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c         |   29 +++
 tests/tcg/mips/mips64-dsp/dshilo.c             |   31 +++
 tests/tcg/mips/mips64-dsp/dshilov.c            |   32 +++
 tests/tcg/mips/mips64-dsp/extp.c               |   50 ++++
 tests/tcg/mips/mips64-dsp/extpdp.c             |   51 ++++
 tests/tcg/mips/mips64-dsp/extpdpv.c            |   52 ++++
 tests/tcg/mips/mips64-dsp/extpv.c              |   51 ++++
 tests/tcg/mips/mips64-dsp/extr_r_w.c           |   27 +++
 tests/tcg/mips/mips64-dsp/extr_rs_w.c          |   27 +++
 tests/tcg/mips/mips64-dsp/extr_s_h.c           |   27 +++
 tests/tcg/mips/mips64-dsp/extr_w.c             |   27 +++
 tests/tcg/mips/mips64-dsp/extrv_r_w.c          |   31 +++
 tests/tcg/mips/mips64-dsp/extrv_rs_w.c         |   31 +++
 tests/tcg/mips/mips64-dsp/extrv_s_h.c          |   31 +++
 tests/tcg/mips/mips64-dsp/extrv_w.c            |   31 +++
 tests/tcg/mips/mips64-dsp/head.S               |   10 +
 tests/tcg/mips/mips64-dsp/insv.c               |   26 ++
 tests/tcg/mips/mips64-dsp/io.h                 |   22 ++
 tests/tcg/mips/mips64-dsp/lbux.c               |   27 +++
 tests/tcg/mips/mips64-dsp/ldx.c                |   27 +++
 tests/tcg/mips/mips64-dsp/lhx.c                |   27 +++
 tests/tcg/mips/mips64-dsp/lwx.c                |   27 +++
 tests/tcg/mips/mips64-dsp/madd.c               |   33 +++
 tests/tcg/mips/mips64-dsp/maddu.c              |   33 +++
 tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c        |   56 +++++
 tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c        |   56 +++++
 tests/tcg/mips/mips64-dsp/maq_s_w_phl.c        |   33 +++
 tests/tcg/mips/mips64-dsp/maq_s_w_phr.c        |   33 +++
 tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c       |   62 +++++
 tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c       |   62 +++++
 tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c       |   63 +++++
 tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c       |   63 +++++
 tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c       |   33 +++
 tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c       |   33 +++
 tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c      |   64 +++++
 tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c      |   64 +++++
 tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c      |   64 +++++
 tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c      |   64 +++++
 tests/tcg/mips/mips64-dsp/mfhi.c               |   24 ++
 tests/tcg/mips/mips64-dsp/mflo.c               |   24 ++
 tests/tcg/mips/mips64-dsp/mips_boot.lds        |   31 +++
 tests/tcg/mips/mips64-dsp/modsub.c             |   37 +++
 tests/tcg/mips/mips64-dsp/msub.c               |   32 +++
 tests/tcg/mips/mips64-dsp/msubu.c              |   32 +++
 tests/tcg/mips/mips64-dsp/mthi.c               |   24 ++
 tests/tcg/mips/mips64-dsp/mthlip.c             |   35 +++
 tests/tcg/mips/mips64-dsp/mtlo.c               |   22 ++
 tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c     |   55 +++++
 tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c     |   24 ++
 tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c      |   45 ++++
 tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c     |   27 +++
 tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c     |   27 +++
 tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c     |   25 ++
 tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c     |   25 ++
 tests/tcg/mips/mips64-dsp/mulq_rs_ph.c         |   27 +++
 tests/tcg/mips/mips64-dsp/mulq_rs_qh.c         |   33 +++
 tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c      |   59 +++++
 tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c      |   57 +++++
 tests/tcg/mips/mips64-dsp/mult.c               |   26 ++
 tests/tcg/mips/mips64-dsp/multu.c              |   26 ++
 tests/tcg/mips/mips64-dsp/out                  |  231 ++++++++++++++++++
 tests/tcg/mips/mips64-dsp/packrl_ph.c          |   24 ++
 tests/tcg/mips/mips64-dsp/packrl_pw.c          |   24 ++
 tests/tcg/mips/mips64-dsp/pick_ob.c            |   27 +++
 tests/tcg/mips/mips64-dsp/pick_ph.c            |   26 ++
 tests/tcg/mips/mips64-dsp/pick_pw.c            |   28 +++
 tests/tcg/mips/mips64-dsp/pick_qb.c            |   26 ++
 tests/tcg/mips/mips64-dsp/pick_qh.c            |   28 +++
 tests/tcg/mips/mips64-dsp/preceq_l_pwl.c       |   24 ++
 tests/tcg/mips/mips64-dsp/preceq_l_pwr.c       |   24 ++
 tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c      |   21 ++
 tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c     |   23 ++
 tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c      |   21 ++
 tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c     |   23 ++
 tests/tcg/mips/mips64-dsp/preceq_w_phl.c       |   23 ++
 tests/tcg/mips/mips64-dsp/preceq_w_phr.c       |   23 ++
 tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c     |   23 ++
 tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c    |   23 ++
 tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c     |   23 ++
 tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c    |   23 ++
 tests/tcg/mips/mips64-dsp/precequ_qh_obl.c     |   22 ++
 tests/tcg/mips/mips64-dsp/precequ_qh_obla.c    |   22 ++
 tests/tcg/mips/mips64-dsp/precequ_qh_obr.c     |   24 ++
 tests/tcg/mips/mips64-dsp/precequ_qh_obra.c    |   24 ++
 tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c      |   23 ++
 tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c     |   23 ++
 tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c      |   23 ++
 tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c     |   23 ++
 tests/tcg/mips/mips64-dsp/preceu_qh_obl.c      |   22 ++
 tests/tcg/mips/mips64-dsp/preceu_qh_obla.c     |   22 ++
 tests/tcg/mips/mips64-dsp/preceu_qh_obr.c      |   23 ++
 tests/tcg/mips/mips64-dsp/preceu_qh_obra.c     |   23 ++
 tests/tcg/mips/mips64-dsp/precr_ob_qh.c        |   25 ++
 tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c    |   40 ++++
 tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c  |   40 ++++
 tests/tcg/mips/mips64-dsp/precrq_ob_qh.c       |   25 ++
 tests/tcg/mips/mips64-dsp/precrq_ph_w.c        |   24 ++
 tests/tcg/mips/mips64-dsp/precrq_pw_l.c        |   25 ++
 tests/tcg/mips/mips64-dsp/precrq_qb_ph.c       |   24 ++
 tests/tcg/mips/mips64-dsp/precrq_qh_pw.c       |   25 ++
 tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c     |   24 ++
 tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c    |   25 ++
 tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c    |   27 +++
 tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c    |   24 ++
 tests/tcg/mips/mips64-dsp/prependd.c           |   37 +++
 tests/tcg/mips/mips64-dsp/prependw.c           |   37 +++
 tests/tcg/mips/mips64-dsp/printf.c             |  266 +++++++++++++++++++++
 tests/tcg/mips/mips64-dsp/raddu_l_ob.c         |   22 ++
 tests/tcg/mips/mips64-dsp/raddu_w_qb.c         |   23 ++
 tests/tcg/mips/mips64-dsp/rddsp.c              |   53 +++++
 tests/tcg/mips/mips64-dsp/repl_ob.c            |   21 ++
 tests/tcg/mips/mips64-dsp/repl_ph.c            |   30 +++
 tests/tcg/mips/mips64-dsp/repl_pw.c            |   34 +++
 tests/tcg/mips/mips64-dsp/repl_qb.c            |   19 ++
 tests/tcg/mips/mips64-dsp/repl_qh.c            |   34 +++
 tests/tcg/mips/mips64-dsp/replv_ob.c           |   23 ++
 tests/tcg/mips/mips64-dsp/replv_ph.c           |   22 ++
 tests/tcg/mips/mips64-dsp/replv_pw.c           |   23 ++
 tests/tcg/mips/mips64-dsp/replv_qb.c           |   22 ++
 tests/tcg/mips/mips64-dsp/shilo.c              |   29 +++
 tests/tcg/mips/mips64-dsp/shilov.c             |   31 +++
 tests/tcg/mips/mips64-dsp/shll_ob.c            |   26 ++
 tests/tcg/mips/mips64-dsp/shll_ph.c            |   26 ++
 tests/tcg/mips/mips64-dsp/shll_pw.c            |   26 ++
 tests/tcg/mips/mips64-dsp/shll_qb.c            |   26 ++
 tests/tcg/mips/mips64-dsp/shll_qh.c            |   26 ++
 tests/tcg/mips/mips64-dsp/shll_s_ph.c          |   26 ++
 tests/tcg/mips/mips64-dsp/shll_s_pw.c          |   26 ++
 tests/tcg/mips/mips64-dsp/shll_s_qh.c          |   26 ++
 tests/tcg/mips/mips64-dsp/shll_s_w.c           |   26 ++
 tests/tcg/mips/mips64-dsp/shllv_ob.c           |   27 +++
 tests/tcg/mips/mips64-dsp/shllv_ph.c           |   27 +++
 tests/tcg/mips/mips64-dsp/shllv_pw.c           |   27 +++
 tests/tcg/mips/mips64-dsp/shllv_qb.c           |   27 +++
 tests/tcg/mips/mips64-dsp/shllv_qh.c           |   27 +++
 tests/tcg/mips/mips64-dsp/shllv_s_ph.c         |   27 +++
 tests/tcg/mips/mips64-dsp/shllv_s_pw.c         |   27 +++
 tests/tcg/mips/mips64-dsp/shllv_s_qh.c         |   27 +++
 tests/tcg/mips/mips64-dsp/shllv_s_w.c          |   27 +++
 tests/tcg/mips/mips64-dsp/shra_ob.c            |   22 ++
 tests/tcg/mips/mips64-dsp/shra_ph.c            |   23 ++
 tests/tcg/mips/mips64-dsp/shra_pw.c            |   22 ++
 tests/tcg/mips/mips64-dsp/shra_qh.c            |   24 ++
 tests/tcg/mips/mips64-dsp/shra_r_ob.c          |   22 ++
 tests/tcg/mips/mips64-dsp/shra_r_ph.c          |   23 ++
 tests/tcg/mips/mips64-dsp/shra_r_pw.c          |   22 ++
 tests/tcg/mips/mips64-dsp/shra_r_qh.c          |   23 ++
 tests/tcg/mips/mips64-dsp/shra_r_w.c           |   23 ++
 tests/tcg/mips/mips64-dsp/shrav_ph.c           |   24 ++
 tests/tcg/mips/mips64-dsp/shrav_pw.c           |   23 ++
 tests/tcg/mips/mips64-dsp/shrav_qh.c           |   24 ++
 tests/tcg/mips/mips64-dsp/shrav_r_ph.c         |   24 ++
 tests/tcg/mips/mips64-dsp/shrav_r_pw.c         |   23 ++
 tests/tcg/mips/mips64-dsp/shrav_r_qh.c         |   24 ++
 tests/tcg/mips/mips64-dsp/shrav_r_w.c          |   24 ++
 tests/tcg/mips/mips64-dsp/shrl_ob.c            |   23 ++
 tests/tcg/mips/mips64-dsp/shrl_qb.c            |   23 ++
 tests/tcg/mips/mips64-dsp/shrl_qh.c            |   22 ++
 tests/tcg/mips/mips64-dsp/shrlv_ob.c           |   24 ++
 tests/tcg/mips/mips64-dsp/shrlv_qb.c           |   24 ++
 tests/tcg/mips/mips64-dsp/shrlv_qh.c           |   23 ++
 tests/tcg/mips/mips64-dsp/subq_ph.c            |   27 +++
 tests/tcg/mips/mips64-dsp/subq_pw.c            |   44 ++++
 tests/tcg/mips/mips64-dsp/subq_qh.c            |   26 ++
 tests/tcg/mips/mips64-dsp/subq_s_ph.c          |   27 +++
 tests/tcg/mips/mips64-dsp/subq_s_pw.c          |   45 ++++
 tests/tcg/mips/mips64-dsp/subq_s_qh.c          |   44 ++++
 tests/tcg/mips/mips64-dsp/subq_s_w.c           |   27 +++
 tests/tcg/mips/mips64-dsp/subu_ob.c            |   26 ++
 tests/tcg/mips/mips64-dsp/subu_qb.c            |   27 +++
 tests/tcg/mips/mips64-dsp/subu_s_ob.c          |   26 ++
 tests/tcg/mips/mips64-dsp/subu_s_qb.c          |   27 +++
 tests/tcg/mips/mips64-dsp/wrdsp.c              |   48 ++++
 tests/tcg/mips/mips64-dspr2/.directory         |    2 +
 tests/tcg/mips/mips64-dspr2/Makefile           |  117 +++++++++
 tests/tcg/mips/mips64-dspr2/absq_s_qb.c        |   42 ++++
 tests/tcg/mips/mips64-dspr2/addqh_ph.c         |   35 +++
 tests/tcg/mips/mips64-dspr2/addqh_r_ph.c       |   35 +++
 tests/tcg/mips/mips64-dspr2/addqh_r_w.c        |   38 +++
 tests/tcg/mips/mips64-dspr2/addqh_w.c          |   39 +++
 tests/tcg/mips/mips64-dspr2/addu_ph.c          |   35 +++
 tests/tcg/mips/mips64-dspr2/addu_qh.c          |   41 ++++
 tests/tcg/mips/mips64-dspr2/addu_s_ph.c        |   35 +++
 tests/tcg/mips/mips64-dspr2/addu_s_qh.c        |   41 ++++
 tests/tcg/mips/mips64-dspr2/adduh_ob.c         |   21 ++
 tests/tcg/mips/mips64-dspr2/adduh_qb.c         |   35 +++
 tests/tcg/mips/mips64-dspr2/adduh_r_ob.c       |   21 ++
 tests/tcg/mips/mips64-dspr2/adduh_r_qb.c       |   35 +++
 tests/tcg/mips/mips64-dspr2/append.c           |   35 +++
 tests/tcg/mips/mips64-dspr2/balign.c           |   35 +++
 tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c     |   26 ++
 tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c     |   41 ++++
 tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c     |   26 ++
 tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c     |   48 ++++
 tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c     |   26 ++
 tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c     |   48 ++++
 tests/tcg/mips/mips64-dspr2/dbalign.c          |   23 ++
 tests/tcg/mips/mips64-dspr2/dpa_w_ph.c         |   32 +++
 tests/tcg/mips/mips64-dspr2/dpa_w_qh.c         |   56 +++++
 tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c     |   74 ++++++
 tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c    |   42 ++++
 tests/tcg/mips/mips64-dspr2/dpax_w_ph.c        |   32 +++
 tests/tcg/mips/mips64-dspr2/dps_w_ph.c         |   28 +++
 tests/tcg/mips/mips64-dspr2/dps_w_qh.c         |   55 +++++
 tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c     |   31 +++
 tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c    |   30 +++
 tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c        |   28 +++
 tests/tcg/mips/mips64-dspr2/head.S             |   10 +
 tests/tcg/mips/mips64-dspr2/io.h               |   22 ++
 tests/tcg/mips/mips64-dspr2/mips_boot.lds      |   31 +++
 tests/tcg/mips/mips64-dspr2/mul_ph.c           |   26 ++
 tests/tcg/mips/mips64-dspr2/mul_s_ph.c         |   26 ++
 tests/tcg/mips/mips64-dspr2/muleq_s_w_phl.c    |   42 ++++
 tests/tcg/mips/mips64-dspr2/mulq_rs_w.c        |   40 ++++
 tests/tcg/mips/mips64-dspr2/mulq_s_ph.c        |   26 ++
 tests/tcg/mips/mips64-dspr2/mulq_s_w.c         |   40 ++++
 tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c       |   30 +++
 tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c    |   30 +++
 tests/tcg/mips/mips64-dspr2/precr_qb_ph.c      |   23 ++
 tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c   |   37 +++
 tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c |   37 +++
 tests/tcg/mips/mips64-dspr2/prepend.c          |   35 +++
 tests/tcg/mips/mips64-dspr2/printf.c           |  266 +++++++++++++++++++++
 tests/tcg/mips/mips64-dspr2/shra_qb.c          |   35 +++
 tests/tcg/mips/mips64-dspr2/shra_r_qb.c        |   35 +++
 tests/tcg/mips/mips64-dspr2/shrav_ob.c         |   22 ++
 tests/tcg/mips/mips64-dspr2/shrav_qb.c         |   37 +++
 tests/tcg/mips/mips64-dspr2/shrav_r_ob.c       |   22 ++
 tests/tcg/mips/mips64-dspr2/shrav_r_qb.c       |   37 +++
 tests/tcg/mips/mips64-dspr2/shrl_ph.c          |   22 ++
 tests/tcg/mips/mips64-dspr2/shrlv_ph.c         |   23 ++
 tests/tcg/mips/mips64-dspr2/subqh_ph.c         |   23 ++
 tests/tcg/mips/mips64-dspr2/subqh_r_ph.c       |   23 ++
 tests/tcg/mips/mips64-dspr2/subqh_r_w.c        |   23 ++
 tests/tcg/mips/mips64-dspr2/subqh_w.c          |   23 ++
 tests/tcg/mips/mips64-dspr2/subu_ph.c          |   26 ++
 tests/tcg/mips/mips64-dspr2/subu_qh.c          |   24 ++
 tests/tcg/mips/mips64-dspr2/subu_s_ph.c        |   25 ++
 tests/tcg/mips/mips64-dspr2/subu_s_qh.c        |   24 ++
 tests/tcg/mips/mips64-dspr2/subuh_ob.c         |   23 ++
 tests/tcg/mips/mips64-dspr2/subuh_qb.c         |   23 ++
 tests/tcg/mips/mips64-dspr2/subuh_r_ob.c       |   23 ++
 tests/tcg/mips/mips64-dspr2/subuh_r_qb.c       |   23 ++
 487 files changed, 16112 insertions(+)
 create mode 100644 tests/tcg/mips/mips32-dsp/Makefile
 create mode 100644 tests/tcg/mips/mips32-dsp/absq_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/absq_s_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/addq_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/addq_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/addsc.c
 create mode 100644 tests/tcg/mips/mips32-dsp/addu_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/addu_s_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/addwc.c
 create mode 100644 tests/tcg/mips/mips32-dsp/bitrev.c
 create mode 100644 tests/tcg/mips/mips32-dsp/bposge32.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmp_eq_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmp_le_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmp_lt_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmpu_le_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpau_h_qbl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpau_h_qbr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extp.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extpdp.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extpdpv.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extpv.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extr_r_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extr_rs_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extr_s_h.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extr_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extrv_r_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extrv_rs_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extrv_s_h.c
 create mode 100644 tests/tcg/mips/mips32-dsp/extrv_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/insv.c
 create mode 100644 tests/tcg/mips/mips32-dsp/lbux.c
 create mode 100644 tests/tcg/mips/mips32-dsp/lhx.c
 create mode 100644 tests/tcg/mips/mips32-dsp/lwx.c
 create mode 100644 tests/tcg/mips/mips32-dsp/madd.c
 create mode 100644 tests/tcg/mips/mips32-dsp/maddu.c
 create mode 100644 tests/tcg/mips/mips32-dsp/main.c
 create mode 100644 tests/tcg/mips/mips32-dsp/maq_s_w_phl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/maq_s_w_phr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mfhi.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mflo.c
 create mode 100644 tests/tcg/mips/mips32-dsp/modsub.c
 create mode 100644 tests/tcg/mips/mips32-dsp/msub.c
 create mode 100644 tests/tcg/mips/mips32-dsp/msubu.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mthi.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mthlip.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mtlo.c
 create mode 100644 tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mulq_rs_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/mult.c
 create mode 100644 tests/tcg/mips/mips32-dsp/multu.c
 create mode 100644 tests/tcg/mips/mips32-dsp/out
 create mode 100644 tests/tcg/mips/mips32-dsp/packrl_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/pick_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/pick_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/preceq_w_phl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/preceq_w_phr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c
 create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c
 create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c
 create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c
 create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precrq_ph_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precrq_qb_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/raddu_w_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/rddsp.c
 create mode 100644 tests/tcg/mips/mips32-dsp/repl_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/repl_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/replv_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/replv_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shilo.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shilov.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shll_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shll_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shll_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shll_s_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shllv_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shllv_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shllv_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shllv_s_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shra_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shra_r_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shra_r_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shrav_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shrav_r_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shrav_r_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shrl_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/shrlv_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/subq_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/subq_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dsp/subq_s_w.c
 create mode 100644 tests/tcg/mips/mips32-dsp/subu_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/subu_s_qb.c
 create mode 100644 tests/tcg/mips/mips32-dsp/wrdsp.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/Makefile
 create mode 100644 tests/tcg/mips/mips32-dspr2/absq_s_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_r_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_r_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/addu_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/addu_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/adduh_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/adduh_r_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/append.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/balign.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpa_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpax_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dps_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mul_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mul_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/muleq_s_w_phl.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mulq_rs_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mulq_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mulq_s_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/precr_qb_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/prepend.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/shra_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/shra_r_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/shrav_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/shrav_r_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/shrl_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/shrlv_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_r_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_r_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_w.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subu_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subu_s_ph.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subuh_qb.c
 create mode 100644 tests/tcg/mips/mips32-dspr2/subuh_r_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/Makefile
 create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/absq_s_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addq_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addq_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addq_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addq_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addq_s_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addq_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addsc.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addu_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addu_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addu_s_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addu_s_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/addwc.c
 create mode 100644 tests/tcg/mips/mips64-dsp/bitrev.c
 create mode 100644 tests/tcg/mips/mips64-dsp/bposge32.c
 create mode 100644 tests/tcg/mips/mips64-dsp/bposge64.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_eq_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_eq_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_eq_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_le_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_le_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_le_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_lt_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_lt_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmp_lt_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_le_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_le_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dappend.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextp.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextpdp.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextpdpv.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextpv.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_r_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_rs_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_rs_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_s_h.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextr_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_r_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_rs_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_rs_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_s_h.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dextrv_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dinsv.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dmadd.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dmaddu.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dmsub.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dmsubu.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dmthlip.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpau_h_obl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpau_h_obr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpau_h_qbl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpau_h_qbr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsu_h_obl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsu_h_obr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dshilo.c
 create mode 100644 tests/tcg/mips/mips64-dsp/dshilov.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extp.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extpdp.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extpdpv.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extpv.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extr_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extr_rs_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extr_s_h.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extr_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extrv_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extrv_rs_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extrv_s_h.c
 create mode 100644 tests/tcg/mips/mips64-dsp/extrv_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/head.S
 create mode 100644 tests/tcg/mips/mips64-dsp/insv.c
 create mode 100644 tests/tcg/mips/mips64-dsp/io.h
 create mode 100644 tests/tcg/mips/mips64-dsp/lbux.c
 create mode 100644 tests/tcg/mips/mips64-dsp/ldx.c
 create mode 100644 tests/tcg/mips/mips64-dsp/lhx.c
 create mode 100644 tests/tcg/mips/mips64-dsp/lwx.c
 create mode 100644 tests/tcg/mips/mips64-dsp/madd.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maddu.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_phl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_phr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mfhi.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mflo.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mips_boot.lds
 create mode 100644 tests/tcg/mips/mips64-dsp/modsub.c
 create mode 100644 tests/tcg/mips/mips64-dsp/msub.c
 create mode 100644 tests/tcg/mips/mips64-dsp/msubu.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mthi.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mthlip.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mtlo.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mulq_rs_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mulq_rs_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/mult.c
 create mode 100644 tests/tcg/mips/mips64-dsp/multu.c
 create mode 100644 tests/tcg/mips/mips64-dsp/out
 create mode 100644 tests/tcg/mips/mips64-dsp/packrl_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/packrl_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/pick_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/pick_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/pick_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/pick_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/pick_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_l_pwl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_l_pwr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_w_phl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceq_w_phr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_qh_obl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_qh_obla.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_qh_obr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precequ_qh_obra.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_qh_obl.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_qh_obla.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_qh_obr.c
 create mode 100644 tests/tcg/mips/mips64-dsp/preceu_qh_obra.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precr_ob_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_ob_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_ph_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_pw_l.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_qb_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_qh_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/prependd.c
 create mode 100644 tests/tcg/mips/mips64-dsp/prependw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/printf.c
 create mode 100644 tests/tcg/mips/mips64-dsp/raddu_l_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/raddu_w_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/rddsp.c
 create mode 100644 tests/tcg/mips/mips64-dsp/repl_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/repl_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/repl_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/repl_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/repl_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/replv_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/replv_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/replv_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/replv_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shilo.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shilov.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_s_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shll_s_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_s_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shllv_s_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shra_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_r_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_r_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_r_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrav_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrl_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrl_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrl_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrlv_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrlv_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/shrlv_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_s_pw.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subq_s_w.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subu_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subu_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subu_s_ob.c
 create mode 100644 tests/tcg/mips/mips64-dsp/subu_s_qb.c
 create mode 100644 tests/tcg/mips/mips64-dsp/wrdsp.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/.directory
 create mode 100644 tests/tcg/mips/mips64-dspr2/Makefile
 create mode 100644 tests/tcg/mips/mips64-dspr2/absq_s_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addqh_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addqh_r_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addqh_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addqh_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addu_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addu_qh.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addu_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/addu_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/adduh_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/adduh_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/adduh_r_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/adduh_r_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/append.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/balign.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dbalign.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpa_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpa_w_qh.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpax_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dps_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dps_w_qh.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/head.S
 create mode 100644 tests/tcg/mips/mips64-dspr2/io.h
 create mode 100644 tests/tcg/mips/mips64-dspr2/mips_boot.lds
 create mode 100644 tests/tcg/mips/mips64-dspr2/mul_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/mul_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/muleq_s_w_phl.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/mulq_rs_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/mulq_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/mulq_s_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/precr_qb_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/prepend.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/printf.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shra_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shra_r_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shrav_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shrav_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shrav_r_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shrav_r_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shrl_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/shrlv_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subqh_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subqh_r_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subqh_r_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subqh_w.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subu_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subu_qh.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subu_s_ph.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subu_s_qh.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subuh_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subuh_qb.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subuh_r_ob.c
 create mode 100644 tests/tcg/mips/mips64-dspr2/subuh_r_qb.c

diff --git a/tests/tcg/mips/mips32-dsp/Makefile b/tests/tcg/mips/mips32-dsp/Makefile
new file mode 100644
index 0000000..aa6f9e6
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/Makefile
@@ -0,0 +1,134 @@
+-include ../../config-host.mak
+
+CROSS=mips64el-unknown-linux-gnu-
+
+SIM=qemu-mipsel
+SIM_FLAGS=-cpu mips32dspr2
+
+CC      = $(CROSS)gcc
+CFLAGS  = -mabi=32 -march=mips32r2 -mgp32 -mdsp -static
+
+TESTCASES = absq_s_ph.tst
+TESTCASES += absq_s_w.tst
+TESTCASES += addq_ph.tst
+TESTCASES += addq_s_ph.tst
+TESTCASES += addsc.tst
+TESTCASES += addu_qb.tst
+TESTCASES += addu_s_qb.tst
+TESTCASES += addwc.tst
+TESTCASES += bitrev.tst
+TESTCASES += bposge32.tst
+TESTCASES += cmp_eq_ph.tst
+TESTCASES += cmpgu_eq_qb.tst
+TESTCASES += cmpgu_le_qb.tst
+TESTCASES += cmpgu_lt_qb.tst
+TESTCASES += cmp_le_ph.tst
+TESTCASES += cmp_lt_ph.tst
+TESTCASES += cmpu_eq_qb.tst
+TESTCASES += cmpu_le_qb.tst
+TESTCASES += cmpu_lt_qb.tst
+TESTCASES += dpaq_sa_l_w.tst
+TESTCASES += dpaq_s_w_ph.tst
+TESTCASES += dpau_h_qbl.tst
+TESTCASES += dpau_h_qbr.tst
+TESTCASES += dpsq_sa_l_w.tst
+TESTCASES += dpsq_s_w_ph.tst
+TESTCASES += dpsu_h_qbl.tst
+TESTCASES += dpsu_h_qbr.tst
+TESTCASES += extp.tst
+TESTCASES += extpdp.tst
+TESTCASES += extpdpv.tst
+TESTCASES += extpv.tst
+TESTCASES += extr_rs_w.tst
+TESTCASES += extr_r_w.tst
+TESTCASES += extr_s_h.tst
+TESTCASES += extrv_rs_w.tst
+TESTCASES += extrv_r_w.tst
+TESTCASES += extrv_s_h.tst
+TESTCASES += extrv_w.tst
+TESTCASES += extr_w.tst
+TESTCASES += insv.tst
+TESTCASES += lbux.tst
+TESTCASES += lhx.tst
+TESTCASES += lwx.tst
+TESTCASES += madd.tst
+TESTCASES += maddu.tst
+TESTCASES += maq_sa_w_phl.tst
+TESTCASES += maq_sa_w_phr.tst
+TESTCASES += maq_s_w_phl.tst
+TESTCASES += maq_s_w_phr.tst
+TESTCASES += mfhi.tst
+TESTCASES += mflo.tst
+TESTCASES += modsub.tst
+TESTCASES += msub.tst
+TESTCASES += msubu.tst
+TESTCASES += mthi.tst
+TESTCASES += mthlip.tst
+TESTCASES += mtlo.tst
+TESTCASES += muleq_s_w_phr.tst
+TESTCASES += muleu_s_ph_qbl.tst
+TESTCASES += muleu_s_ph_qbr.tst
+TESTCASES += mulq_rs_ph.tst
+TESTCASES += mult.tst
+TESTCASES += multu.tst
+TESTCASES += packrl_ph.tst
+TESTCASES += pick_ph.tst
+TESTCASES += pick_qb.tst
+TESTCASES += precequ_ph_qbla.tst
+TESTCASES += precequ_ph_qbl.tst
+TESTCASES += precequ_ph_qbra.tst
+TESTCASES += precequ_ph_qbr.tst
+TESTCASES += preceq_w_phl.tst
+TESTCASES += preceq_w_phr.tst
+TESTCASES += preceu_ph_qbla.tst
+TESTCASES += preceu_ph_qbl.tst
+TESTCASES += preceu_ph_qbra.tst
+TESTCASES += preceu_ph_qbr.tst
+TESTCASES += precrq_ph_w.tst
+TESTCASES += precrq_qb_ph.tst
+TESTCASES += precrq_rs_ph_w.tst
+TESTCASES += precrqu_s_qb_ph.tst
+TESTCASES += raddu_w_qb.tst
+TESTCASES += rddsp.tst
+TESTCASES += repl_ph.tst
+TESTCASES += repl_qb.tst
+TESTCASES += replv_ph.tst
+TESTCASES += replv_qb.tst
+TESTCASES += shilo.tst
+TESTCASES += shilov.tst
+TESTCASES += shll_ph.tst
+TESTCASES += shll_qb.tst
+TESTCASES += shll_s_ph.tst
+TESTCASES += shll_s_w.tst
+TESTCASES += shllv_ph.tst
+TESTCASES += shllv_qb.tst
+TESTCASES += shllv_s_ph.tst
+TESTCASES += shllv_s_w.tst
+TESTCASES += shra_ph.tst
+TESTCASES += shra_r_ph.tst
+TESTCASES += shra_r_w.tst
+TESTCASES += shrav_ph.tst
+TESTCASES += shrav_r_ph.tst
+TESTCASES += shrav_r_w.tst
+TESTCASES += shrl_qb.tst
+TESTCASES += shrlv_qb.tst
+TESTCASES += subq_ph.tst
+TESTCASES += subq_s_ph.tst
+TESTCASES += subq_s_w.tst
+TESTCASES += subu_qb.tst
+TESTCASES += subu_s_qb.tst
+TESTCASES += wrdsp.tst
+
+all: $(TESTCASES)
+
+%.tst: %.c
+	$(CC) $(CFLAGS) $< -o $@
+
+check: $(TESTCASES)
+	@for case in $(TESTCASES); do \
+        echo $(SIM) $(SIM_FLAGS) ./$$case;\
+        $(SIM) $(SIM_FLAGS) ./$$case; \
+	done
+
+clean:
+	$(RM) -rf $(TESTCASES)
diff --git a/tests/tcg/mips/mips32-dsp/absq_s_ph.c b/tests/tcg/mips/mips32-dsp/absq_s_ph.c
new file mode 100644
index 0000000..aa84112
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/absq_s_ph.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt     = 0x10017EFD;
+    result = 0x10017EFD;
+
+    __asm
+        ("absq_s.ph %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    rt     = 0x8000A536;
+    result = 0x7FFF5ACA;
+
+    __asm
+        ("absq_s.ph %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/absq_s_w.c b/tests/tcg/mips/mips32-dsp/absq_s_w.c
new file mode 100644
index 0000000..3f52a48
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/absq_s_w.c
@@ -0,0 +1,37 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt     = 0x80000000;
+    result = 0x7FFFFFFF;
+    __asm
+        ("absq_s.w %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    rt     = 0x80030000;
+    result = 0x7FFD0000;
+    __asm
+        ("absq_s.w %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    rt     = 0x31036080;
+    result = 0x31036080;
+    __asm
+        ("absq_s.w %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/addq_ph.c b/tests/tcg/mips/mips32-dsp/addq_ph.c
new file mode 100644
index 0000000..2d9b6fc
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/addq_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0xFFFFFFFF;
+    rt     = 0x10101010;
+    result = 0x100F100F;
+    __asm
+        ("addq.ph   %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(result == rd);
+
+    rs     = 0x3712847D;
+    rt     = 0x0031AF2D;
+    result = 0x374333AA;
+    __asm
+        ("addq.ph   %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/addq_s_ph.c b/tests/tcg/mips/mips32-dsp/addq_s_ph.c
new file mode 100644
index 0000000..ace1ecd
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/addq_s_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0xFFFFFFFF;
+    rt     = 0x10101010;
+    result = 0x100F100F;
+    __asm
+        ("addq_s.ph   %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(result == rd);
+
+    rs     = 0x3712847D;
+    rt     = 0x0031AF2D;
+    result = 0x37438000;
+    __asm
+        ("addq_s.ph   %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/addsc.c b/tests/tcg/mips/mips32-dsp/addsc.c
new file mode 100644
index 0000000..9ad974a
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/addsc.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x0000000F;
+    rt     = 0x00000001;
+    result = 0x00000010;
+    __asm
+        ("addsc %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    rs     = 0xFFFF0FFF;
+    rt     = 0x00010111;
+    result = 0x00001110;
+    __asm
+        ("addsc %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/addu_qb.c b/tests/tcg/mips/mips32-dsp/addu_qb.c
new file mode 100644
index 0000000..1b98e5e
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/addu_qb.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x00FF00FF;
+    rt     = 0x00010001;
+    result = 0x00000000;
+    __asm
+        ("addu.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    rs     = 0xFFFF1111;
+    rt     = 0x00020001;
+    result = 0xFF011112;
+    __asm
+        ("addu.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/addu_s_qb.c b/tests/tcg/mips/mips32-dsp/addu_s_qb.c
new file mode 100644
index 0000000..46717ee
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/addu_s_qb.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x10FF01FF;
+    rt     = 0x10010001;
+    result = 0x20FF01FF;
+    __asm
+        ("addu_s.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    rs     = 0xFFFF1111;
+    rt     = 0x00020001;
+    result = 0xFFFF1112;
+    __asm
+        ("addu_s.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/addwc.c b/tests/tcg/mips/mips32-dsp/addwc.c
new file mode 100644
index 0000000..d47ac65
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/addwc.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x10FF01FF;
+    rt     = 0x10010001;
+    result = 0x21000200;
+    __asm
+        ("addwc %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    rs     = 0xFFFF1111;
+    rt     = 0x00020001;
+    result = 0x00011112;
+    __asm
+        ("addwc %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/bitrev.c b/tests/tcg/mips/mips32-dsp/bitrev.c
new file mode 100644
index 0000000..04d8a38
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/bitrev.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt     = 0x12345678;
+    result = 0x00001E6A;
+
+    __asm
+        ("bitrev %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/bposge32.c b/tests/tcg/mips/mips32-dsp/bposge32.c
new file mode 100644
index 0000000..d25417e
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/bposge32.c
@@ -0,0 +1,44 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int dsp, sum;
+    int result;
+
+    dsp =  0x20;
+    sum = 0x01;
+    result = 0x02;
+
+    __asm
+        ("wrdsp %1\n\t"
+         "bposge32 test1\n\t"
+         "nop\n\t"
+         "addi %0, 0xA2\n\t"
+         "nop\n\t"
+         "test1:\n\t"
+         "addi %0, 0x01\n\t"
+         : "+r"(sum)
+         : "r"(dsp)
+        );
+    assert(sum == result);
+
+    dsp =  0x10;
+    sum = 0x01;
+    result = 0xA4;
+
+    __asm
+        ("wrdsp %1\n\t"
+         "bposge32 test2\n\t"
+         "nop\n\t"
+         "addi %0, 0xA2\n\t"
+         "nop\n\t"
+         "test2:\n\t"
+         "addi %0, 0x01\n\t"
+         : "+r"(sum)
+         : "r"(dsp)
+        );
+    assert(sum == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmp_eq_ph.c b/tests/tcg/mips/mips32-dsp/cmp_eq_ph.c
new file mode 100644
index 0000000..957bd88
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmp_eq_ph.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x11777066;
+    rt     = 0x55AA33FF;
+    result = 0x00;
+    __asm
+        ("cmp.eq.ph %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    rd = (rd >> 24) & 0x03;
+    assert(rd == result);
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x03;
+    __asm
+        ("cmp.eq.ph %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    rd = (rd >> 24) & 0x03;
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmp_le_ph.c b/tests/tcg/mips/mips32-dsp/cmp_le_ph.c
new file mode 100644
index 0000000..356f156
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmp_le_ph.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x11777066;
+    rt     = 0x55AA33FF;
+    result = 0x02;
+    __asm
+        ("cmp.le.ph %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    rd = (rd >> 24) & 0x03;
+    assert(rd == result);
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x03;
+    __asm
+        ("cmp.le.ph %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    rd = (rd >> 24) & 0x03;
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmp_lt_ph.c b/tests/tcg/mips/mips32-dsp/cmp_lt_ph.c
new file mode 100644
index 0000000..3fb4827
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmp_lt_ph.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x11777066;
+    rt     = 0x55AA33FF;
+    result = 0x02;
+    __asm
+        ("cmp.lt.ph %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    rd = (rd >> 24) & 0x03;
+    assert(rd == result);
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x00;
+    __asm
+        ("cmp.lt.ph %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    rd = (rd >> 24) & 0x03;
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c b/tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c
new file mode 100644
index 0000000..2615c84
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x11777066;
+    rt     = 0x55AA70FF;
+    result = 0x02;
+    __asm
+        ("cmpgu.eq.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    assert(rd == result);
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x0F;
+    __asm
+        ("cmpgu.eq.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c b/tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c
new file mode 100644
index 0000000..65d0813
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x11777066;
+    rt     = 0x55AA70FF;
+    result = 0x0F;
+    __asm
+        ("cmpgu.le.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    assert(rd == result);
+
+    rs     = 0x11777066;
+    rt     = 0x11766066;
+    result = 0x09;
+    __asm
+        ("cmpgu.le.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c b/tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c
new file mode 100644
index 0000000..7dddad9
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x11777066;
+    rt     = 0x55AA70FF;
+    result = 0x0D;
+    __asm
+        ("cmpgu.lt.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    assert(rd == result);
+
+    rs     = 0x11777066;
+    rt     = 0x11766066;
+    result = 0x00;
+    __asm
+        ("cmpgu.lt.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c b/tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c
new file mode 100644
index 0000000..680f2a1
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int dsp;
+    int result;
+
+    rs         = 0x11777066;
+    rt         = 0x55AA70FF;
+    result     = 0x02;
+    __asm
+        ("cmpu.eq.qb %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    assert(dsp == result);
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x0F;
+    __asm
+        ("cmpu.eq.qb %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    assert(dsp == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmpu_le_qb.c b/tests/tcg/mips/mips32-dsp/cmpu_le_qb.c
new file mode 100644
index 0000000..43cfa50
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmpu_le_qb.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int dsp;
+    int result;
+
+    rs         = 0x11777066;
+    rt         = 0x55AA70FF;
+    result     = 0x0F;
+    __asm
+        ("cmpu.le.qb %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    assert(dsp == result);
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x0F;
+    __asm
+        ("cmpu.le.qb %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    assert(dsp == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c b/tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c
new file mode 100644
index 0000000..074ca5b
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int dsp;
+    int result;
+
+    rs         = 0x11777066;
+    rt         = 0x55AA70FF;
+    result     = 0x0D;
+    __asm
+        ("cmpu.lt.qb %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    assert(dsp == result);
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x00;
+    __asm
+        ("cmpu.lt.qb %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    assert(dsp == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c b/tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c
new file mode 100644
index 0000000..a6425b6
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt, dsp;
+    int ach = 0, acl = 0;
+    int resulth, resultl, resultdsp;
+
+    rs        = 0x800000FF;
+    rt        = 0x80000002;
+    resulth   = 0x00;
+    resultl   = 0x800003FB;
+    resultdsp = 0x01;
+    __asm
+        ("mthi        %0, $ac1\n\t"
+         "mtlo        %1, $ac1\n\t"
+         "dpaq_s.w.ph $ac1, %3, %4\n\t"
+         "mfhi        %0,   $ac1\n\t"
+         "mflo        %1,   $ac1\n\t"
+         "rddsp       %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = dsp >> 17 & 0x01;
+    assert(dsp == resultdsp);
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c b/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c
new file mode 100644
index 0000000..02bac2a
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt, dsp;
+    int ach = 0, acl = 0;
+    int resulth, resultl, resultdsp;
+
+    rs        = 0x800000FF;
+    rt        = 0x80000002;
+    resulth   = 0x7FFFFFFF;
+    resultl   = 0xFFFFFFFF;
+    resultdsp = 0x01;
+    __asm
+        ("mthi        %0, $ac1\n\t"
+         "mtlo        %0, $ac1\n\t"
+         "dpaq_sa.l.w $ac1, %3, %4\n\t"
+         "mfhi        %0,   $ac1\n\t"
+         "mflo        %1,   $ac1\n\t"
+         "rddsp       %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x01;
+    assert(dsp == resultdsp);
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpau_h_qbl.c b/tests/tcg/mips/mips32-dsp/dpau_h_qbl.c
new file mode 100644
index 0000000..6017b5e
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpau_h_qbl.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int ach = 5, acl = 3;
+    int resulth, resultl;
+
+    rs        = 0x800000FF;
+    rt        = 0x80000002;
+    resulth   = 0x05;
+    resultl   = 0x4003;
+    __asm
+        ("mthi       %0, $ac1\n\t"
+         "mtlo       %1, $ac1\n\t"
+         "dpau.h.qbl $ac1, %2, %3\n\t"
+         "mfhi       %0,   $ac1\n\t"
+         "mflo       %1,   $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpau_h_qbr.c b/tests/tcg/mips/mips32-dsp/dpau_h_qbr.c
new file mode 100644
index 0000000..e4abb2e
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpau_h_qbr.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int ach = 5, acl = 3;
+    int resulth, resultl;
+
+    rs        = 0x800000FF;
+    rt        = 0x80000002;
+    resulth   = 0x05;
+    resultl   = 0x0201;
+    __asm
+        ("mthi       %0, $ac1\n\t"
+         "mtlo       %1, $ac1\n\t"
+         "dpau.h.qbr $ac1, %2, %3\n\t"
+         "mfhi       %0,   $ac1\n\t"
+         "mflo       %1,   $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c b/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c
new file mode 100644
index 0000000..70ad443
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int ach = 5, acl = 5;
+    int resulth, resultl;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x04;
+    resultl = 0xEE9794A3;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsq_s.w.ph $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c b/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c
new file mode 100644
index 0000000..3d6b24c
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt, dsp;
+    int ach = 5, acl = 5;
+    int resulth, resultl, resultdsp;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x7FFFFFFF;
+    resultl = 0xFFFFFFFF;
+    resultdsp = 0x01;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsq_sa.l.w $ac1, %3, %4\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x01;
+    assert(dsp == resultdsp);
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c b/tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c
new file mode 100644
index 0000000..94e2bf6
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int ach = 5, acl = 5;
+    int resulth, resultl;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x04;
+    resultl = 0xFFFFFEE5;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsu.h.qbl $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c b/tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c
new file mode 100644
index 0000000..a1e6635
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int ach = 5, acl = 5;
+    int resulth, resultl;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x04;
+    resultl = 0xFFFFE233;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsu.h.qbr $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extp.c b/tests/tcg/mips/mips32-dsp/extp.c
new file mode 100644
index 0000000..21a67af
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extp.c
@@ -0,0 +1,44 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, ach, acl, dsp;
+    int result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    result = 0x000C;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extp %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 14) & 0x01;
+    assert(dsp == 0);
+    assert(result == rt);
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x01;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extp %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 14) & 0x01;
+    assert(dsp == 1);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extpdp.c b/tests/tcg/mips/mips32-dsp/extpdp.c
new file mode 100644
index 0000000..15ba082
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extpdp.c
@@ -0,0 +1,46 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, ach, acl, dsp, pos, efi;
+    int result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    result = 0x000C;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extpdp %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    pos =  dsp & 0x3F;
+    efi = (dsp >> 14) & 0x01;
+    assert(pos == 3);
+    assert(efi == 0);
+    assert(result == rt);
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x01;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extpdp %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    efi = (dsp >> 14) & 0x01;
+    assert(efi == 1);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extpdpv.c b/tests/tcg/mips/mips32-dsp/extpdpv.c
new file mode 100644
index 0000000..f5774ee
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extpdpv.c
@@ -0,0 +1,47 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, rs, ach, acl, dsp, pos, efi;
+    int result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    rs  = 0x03;
+    result = 0x000C;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extpdpv %0, $ac1, %4\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl), "r"(rs)
+        );
+    pos =  dsp & 0x3F;
+    efi = (dsp >> 14) & 0x01;
+    assert(pos == 3);
+    assert(efi == 0);
+    assert(result == rt);
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x01;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extpdpv %0, $ac1, %4\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl), "r"(rs)
+        );
+    efi = (dsp >> 14) & 0x01;
+    assert(efi == 1);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extpv.c b/tests/tcg/mips/mips32-dsp/extpv.c
new file mode 100644
index 0000000..401b94a
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extpv.c
@@ -0,0 +1,45 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, ac, ach, acl, dsp;
+    int result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    ac  = 0x03;
+    result = 0x000C;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extpv %0, $ac1, %4\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl), "r"(ac)
+        );
+    dsp = (dsp >> 14) & 0x01;
+    assert(dsp == 0);
+    assert(result == rt);
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x01;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extpv %0, $ac1, %4\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl), "r"(ac)
+        );
+    dsp = (dsp >> 14) & 0x01;
+    assert(dsp == 1);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extr_r_w.c b/tests/tcg/mips/mips32-dsp/extr_r_w.c
new file mode 100644
index 0000000..570dfbd
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extr_r_w.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, ach, acl, dsp;
+    int result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    result = 0xA0001699;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extr_r.w %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    assert(dsp == 1);
+    assert(result == rt);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extr_rs_w.c b/tests/tcg/mips/mips32-dsp/extr_rs_w.c
new file mode 100644
index 0000000..a0bf7b4
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extr_rs_w.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, ach, acl, dsp;
+    int result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    result = 0x7FFFFFFF;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extr_rs.w %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    assert(dsp == 1);
+    assert(result == rt);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extr_s_h.c b/tests/tcg/mips/mips32-dsp/extr_s_h.c
new file mode 100644
index 0000000..c863f29
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extr_s_h.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, ach, acl, dsp;
+    int result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    result = 0x00007FFF;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extr_s.h %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    assert(dsp == 1);
+    assert(result == rt);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extr_w.c b/tests/tcg/mips/mips32-dsp/extr_w.c
new file mode 100644
index 0000000..40994cb
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extr_w.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, ach, acl, dsp;
+    int result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    result = 0xA0001699;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extr.w %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    assert(dsp == 1);
+    assert(result == rt);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extrv_r_w.c b/tests/tcg/mips/mips32-dsp/extrv_r_w.c
new file mode 100644
index 0000000..43aba53
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extrv_r_w.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, rs, ach, acl, dsp;
+    int result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    rs  = 0x03;
+    result = 0xA0001699;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "extrv_r.w %0, $ac1, %2\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(rs), "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    assert(dsp == 1);
+    assert(result == rt);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extrv_rs_w.c b/tests/tcg/mips/mips32-dsp/extrv_rs_w.c
new file mode 100644
index 0000000..60e0d43
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extrv_rs_w.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, rs, ach, acl, dsp;
+    int result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    rs  = 0x03;
+    result = 0x7FFFFFFF;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "extrv_rs.w %0, $ac1, %2\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(rs), "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    assert(dsp == 1);
+    assert(result == rt);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extrv_s_h.c b/tests/tcg/mips/mips32-dsp/extrv_s_h.c
new file mode 100644
index 0000000..c7f70e3
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extrv_s_h.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, rs, ach, acl, dsp;
+    int result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    rs  = 0x03;
+    result = 0x00007FFF;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "extrv_s.h %0, $ac1, %2\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(rs), "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    assert(dsp == 1);
+    assert(result == rt);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extrv_w.c b/tests/tcg/mips/mips32-dsp/extrv_w.c
new file mode 100644
index 0000000..c63a25c
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extrv_w.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, rs, ach, acl, dsp;
+    int result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    rs  = 0x03;
+    result = 0xA0001699;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "extrv.w %0, $ac1, %2\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(rs), "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    assert(dsp == 1);
+    assert(result == rt);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/insv.c b/tests/tcg/mips/mips32-dsp/insv.c
new file mode 100644
index 0000000..7e3b047
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/insv.c
@@ -0,0 +1,23 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, rs, dsp;
+    int result;
+
+    /* msb = 10, lsb = 5 */
+    dsp    = 0x305;
+    rt     = 0x12345678;
+    rs     = 0x87654321;
+    result = 0x12345338;
+    __asm
+        ("wrdsp %2, 0x03\n\t"
+         "insv  %0, %1\n\t"
+         : "+r"(rt)
+         : "r"(rs), "r"(dsp)
+        );
+    assert(rt == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/lbux.c b/tests/tcg/mips/mips32-dsp/lbux.c
new file mode 100644
index 0000000..b6a502d
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/lbux.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <assert.h>
+
+int main(void)
+{
+    int value, rd;
+    int *p;
+    unsigned long long addr, index;
+    int result;
+
+    value  = 0xBCDEF389;
+    p = &value;
+    addr = (unsigned long long)p;
+    index  = 0;
+    result = value & 0xFF;
+    __asm
+        ("lbux %0, %1(%2)\n\t"
+         : "=r"(rd)
+         : "r"(index), "r"(addr)
+        );
+
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/lhx.c b/tests/tcg/mips/mips32-dsp/lhx.c
new file mode 100644
index 0000000..0b948e4
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/lhx.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <assert.h>
+
+int main(void)
+{
+    int value, rd;
+    int *p;
+    unsigned long long addr, index;
+    int result;
+
+    value  = 0xBCDEF389;
+    p = &value;
+    addr = (unsigned long long)p;
+    index  = 0;
+    result = 0xFFFFF389;
+    __asm
+        ("lhx %0, %1(%2)\n\t"
+         : "=r"(rd)
+         : "r"(index), "r"(addr)
+        );
+
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/lwx.c b/tests/tcg/mips/mips32-dsp/lwx.c
new file mode 100644
index 0000000..ff9c4a9
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/lwx.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <assert.h>
+
+int main(void)
+{
+    int value, rd;
+    int *p;
+    unsigned long long addr, index;
+    int result;
+
+    value  = 0xBCDEF389;
+    p = &value;
+    addr = (unsigned long long)p;
+    index  = 0;
+    result = 0xBCDEF389;
+    __asm
+        ("lwx %0, %1(%2)\n\t"
+         : "=r"(rd)
+         : "r"(index), "r"(addr)
+        );
+
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/madd.c b/tests/tcg/mips/mips32-dsp/madd.c
new file mode 100644
index 0000000..af4bfcf
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/madd.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, rs;
+    int achi, acli;
+    int acho, aclo;
+    int resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0x01;
+    rt  = 0x01;
+    resulth = 0x05;
+    resultl = 0xB4CC;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "madd $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    assert(resulth == acho);
+    assert(resultl == aclo);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/maddu.c b/tests/tcg/mips/mips32-dsp/maddu.c
new file mode 100644
index 0000000..af4bfcf
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/maddu.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, rs;
+    int achi, acli;
+    int acho, aclo;
+    int resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0x01;
+    rt  = 0x01;
+    resulth = 0x05;
+    resultl = 0xB4CC;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "madd $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    assert(resulth == acho);
+    assert(resultl == aclo);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/main.c b/tests/tcg/mips/mips32-dsp/main.c
new file mode 100644
index 0000000..b296b20
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/main.c
@@ -0,0 +1,6 @@
+#include<stdio.h>
+
+int main()
+{
+    printf("hello world\n");
+}
diff --git a/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c b/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c
new file mode 100644
index 0000000..f5de818
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, rs;
+    int achi, acli;
+    int acho, aclo;
+    int resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0xFF060000;
+    rt  = 0xCB000000;
+    resulth = 0x04;
+    resultl = 0x947438CB;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_s.w.phl $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    assert(resulth == acho);
+    assert(resultl == aclo);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c b/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c
new file mode 100644
index 0000000..8336f00
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, rs;
+    int achi, acli;
+    int acho, aclo;
+    int resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0xFF06;
+    rt  = 0xCB00;
+    resulth = 0x04;
+    resultl = 0x947438CB;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_s.w.phr $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    assert(resulth == acho);
+    assert(resultl == aclo);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c b/tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c
new file mode 100644
index 0000000..35c5bfb
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, rs;
+    int achi, acli;
+    int acho, aclo;
+    int resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0xFF060000;
+    rt  = 0xCB000000;
+    resulth = 0xFFFFFFFF;
+    resultl = 0x80000000;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_sa.w.phl $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    assert(resulth == acho);
+    assert(resultl == aclo);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c b/tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c
new file mode 100644
index 0000000..45ba792
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rt, rs;
+    int achi, acli;
+    int acho, aclo;
+    int resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0xFF06;
+    rt  = 0xCB00;
+    resulth = 0xFFFFFFFF;
+    resultl = 0x80000000;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_sa.w.phr $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    assert(resulth == acho);
+    assert(resultl == aclo);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mfhi.c b/tests/tcg/mips/mips32-dsp/mfhi.c
new file mode 100644
index 0000000..43a8066
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mfhi.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int achi, acho;
+    int result;
+
+    achi   = 0x004433;
+    result = 0x004433;
+
+    __asm
+        ("mthi %1, $ac1\n\t"
+         "mfhi %0, $ac1\n\t"
+         : "=r"(acho)
+         : "r"(achi)
+        );
+    assert(result == acho);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mflo.c b/tests/tcg/mips/mips32-dsp/mflo.c
new file mode 100644
index 0000000..caeafdb
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mflo.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int acli, aclo;
+    int result;
+
+    acli   = 0x004433;
+    result = 0x004433;
+
+    __asm
+        ("mthi %1, $ac1\n\t"
+         "mfhi %0, $ac1\n\t"
+         : "=r"(aclo)
+         : "r"(acli)
+        );
+    assert(result == aclo);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/modsub.c b/tests/tcg/mips/mips32-dsp/modsub.c
new file mode 100644
index 0000000..c294eeb
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/modsub.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0xFFFFFFFF;
+    rt     = 0x000000FF;
+    result = 0xFFFFFF00;
+    __asm
+        ("modsub %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(result == rd);
+
+    rs     = 0x00000000;
+    rt     = 0x00CD1FFF;
+    result = 0x0000CD1F;
+    __asm
+        ("modsub %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/msub.c b/tests/tcg/mips/mips32-dsp/msub.c
new file mode 100644
index 0000000..5779e6f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/msub.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int achi, acli, rs, rt;
+    int acho, aclo;
+    int resulth, resultl;
+
+    rs      = 0x00BBAACC;
+    rt      = 0x0B1C3D2F;
+    achi    = 0x00004433;
+    acli    = 0xFFCC0011;
+    resulth = 0xFFF81F29;
+    resultl = 0xB355089D;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "msub $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    assert(acho == resulth);
+    assert(aclo == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/msubu.c b/tests/tcg/mips/mips32-dsp/msubu.c
new file mode 100644
index 0000000..e0f9b5a
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/msubu.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int achi, acli, rs, rt;
+    int acho, aclo;
+    int resulth, resultl;
+
+    rs      = 0x00BBAACC;
+    rt      = 0x0B1C3D2F;
+    achi    = 0x00004433;
+    acli    = 0xFFCC0011;
+    resulth = 0xFFF81F29;
+    resultl = 0xB355089D;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "msubu $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    assert(acho == resulth);
+    assert(aclo == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mthi.c b/tests/tcg/mips/mips32-dsp/mthi.c
new file mode 100644
index 0000000..43a8066
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mthi.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int achi, acho;
+    int result;
+
+    achi   = 0x004433;
+    result = 0x004433;
+
+    __asm
+        ("mthi %1, $ac1\n\t"
+         "mfhi %0, $ac1\n\t"
+         : "=r"(acho)
+         : "r"(achi)
+        );
+    assert(result == acho);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mthlip.c b/tests/tcg/mips/mips32-dsp/mthlip.c
new file mode 100644
index 0000000..74e83bf
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mthlip.c
@@ -0,0 +1,34 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, ach, acl, dsp;
+    int result, resulth, resultl;
+
+    dsp = 0x07;
+    ach = 0x05;
+    acl = 0xB4CB;
+    rs  = 0x00FFBBAA;
+    resulth = 0xB4CB;
+    resultl = 0x00FFBBAA;
+    result  = 0x27;
+
+    __asm
+        ("wrdsp %0, 0x01\n\t"
+         "mthi %1, $ac1\n\t"
+         "mtlo %2, $ac1\n\t"
+         "mthlip %3, $ac1\n\t"
+         "mfhi %1, $ac1\n\t"
+         "mflo %2, $ac1\n\t"
+         "rddsp %0\n\t"
+         : "+r"(dsp), "+r"(ach), "+r"(acl)
+         : "r"(rs)
+        );
+    dsp = dsp & 0x3F;
+    assert(dsp == result);
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mtlo.c b/tests/tcg/mips/mips32-dsp/mtlo.c
new file mode 100644
index 0000000..caeafdb
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mtlo.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int acli, aclo;
+    int result;
+
+    acli   = 0x004433;
+    result = 0x004433;
+
+    __asm
+        ("mthi %1, $ac1\n\t"
+         "mfhi %0, $ac1\n\t"
+         : "=r"(aclo)
+         : "r"(acli)
+        );
+    assert(result == aclo);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c b/tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c
new file mode 100644
index 0000000..8066d7d
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c
@@ -0,0 +1,40 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x8000;
+    rt = 0x8000;
+    result = 0x7FFFFFFF;
+    resultdsp = 1;
+
+    __asm
+        ("muleq_s.w.phr %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    assert(rd  == result);
+    assert(dsp == resultdsp);
+
+    rs = 0x1234;
+    rt = 0x4321;
+    result = 0x98be968;
+    resultdsp = 1;
+
+    __asm
+        ("muleq_s.w.phr %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    assert(rd  == result);
+    assert(dsp == resultdsp);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c b/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c
new file mode 100644
index 0000000..66a3828
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x80001234;
+    rt = 0x80004321;
+    result = 0xFFFF0000;
+    resultdsp = 1;
+
+    __asm
+        ("muleu_s.ph.qbl %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    assert(rd  == result);
+    assert(dsp == resultdsp);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c b/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c
new file mode 100644
index 0000000..4cc6c8f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x8000;
+    rt = 0x80004321;
+    result = 0xFFFF0000;
+    resultdsp = 1;
+
+    __asm
+        ("muleu_s.ph.qbr %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    assert(rd  == result);
+    assert(dsp == resultdsp);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c b/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c
new file mode 100644
index 0000000..c720603
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x80001234;
+    rt = 0x80004321;
+    result = 0x7FFF098C;
+    resultdsp = 1;
+
+    __asm
+        ("mulq_rs.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    assert(rd  == result);
+    assert(dsp == resultdsp);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mult.c b/tests/tcg/mips/mips32-dsp/mult.c
new file mode 100644
index 0000000..15e6fde
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mult.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt, ach, acl;
+    int result, resulth, resultl;
+
+    rs  = 0x00FFBBAA;
+    rt  = 0x4B231000;
+    resulth = 0x4b0f01;
+    resultl = 0x71f8a000;
+    __asm
+        ("mult $ac1, %2, %3\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(ach), "=r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/multu.c b/tests/tcg/mips/mips32-dsp/multu.c
new file mode 100644
index 0000000..15e6fde
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/multu.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt, ach, acl;
+    int result, resulth, resultl;
+
+    rs  = 0x00FFBBAA;
+    rt  = 0x4B231000;
+    resulth = 0x4b0f01;
+    resultl = 0x71f8a000;
+    __asm
+        ("mult $ac1, %2, %3\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(ach), "=r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/out b/tests/tcg/mips/mips32-dsp/out
new file mode 100644
index 0000000..d0781ba
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/out
@@ -0,0 +1,110 @@
+qemu-mipsel -cpu mips32dspr2 ./absq_s_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./absq_s_w.tst
+qemu-mipsel -cpu mips32dspr2 ./addq_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./addq_s_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./addsc.tst
+qemu-mipsel -cpu mips32dspr2 ./addu_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./addu_s_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./addwc.tst
+qemu-mipsel -cpu mips32dspr2 ./bitrev.tst
+qemu-mipsel -cpu mips32dspr2 ./bposge32.tst
+qemu-mipsel -cpu mips32dspr2 ./cmp_eq_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./cmpgu_eq_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./cmpgu_le_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./cmpgu_lt_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./cmp_le_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./cmp_lt_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./cmpu_eq_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./cmpu_le_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./cmpu_lt_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./dpaq_sa_l_w.tst
+qemu-mipsel -cpu mips32dspr2 ./dpaq_s_w_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./dpau_h_qbl.tst
+qemu-mipsel -cpu mips32dspr2 ./dpau_h_qbr.tst
+qemu-mipsel -cpu mips32dspr2 ./dpsq_sa_l_w.tst
+qemu-mipsel -cpu mips32dspr2 ./dpsq_s_w_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./dpsu_h_qbl.tst
+qemu-mipsel -cpu mips32dspr2 ./dpsu_h_qbr.tst
+qemu-mipsel -cpu mips32dspr2 ./extp.tst
+qemu-mipsel -cpu mips32dspr2 ./extpdp.tst
+qemu-mipsel -cpu mips32dspr2 ./extpdpv.tst
+qemu-mipsel -cpu mips32dspr2 ./extpv.tst
+qemu-mipsel -cpu mips32dspr2 ./extr_rs_w.tst
+qemu-mipsel -cpu mips32dspr2 ./extr_r_w.tst
+qemu-mipsel -cpu mips32dspr2 ./extr_s_h.tst
+qemu-mipsel -cpu mips32dspr2 ./extrv_rs_w.tst
+qemu-mipsel -cpu mips32dspr2 ./extrv_r_w.tst
+qemu-mipsel -cpu mips32dspr2 ./extrv_s_h.tst
+qemu-mipsel -cpu mips32dspr2 ./extrv_w.tst
+qemu-mipsel -cpu mips32dspr2 ./extr_w.tst
+qemu-mipsel -cpu mips32dspr2 ./insv.tst
+qemu-mipsel -cpu mips32dspr2 ./lbux.tst
+qemu-mipsel -cpu mips32dspr2 ./lhx.tst
+qemu-mipsel -cpu mips32dspr2 ./lwx.tst
+qemu-mipsel -cpu mips32dspr2 ./madd.tst
+qemu-mipsel -cpu mips32dspr2 ./maddu.tst
+qemu-mipsel -cpu mips32dspr2 ./maq_sa_w_phl.tst
+qemu-mipsel -cpu mips32dspr2 ./maq_sa_w_phr.tst
+qemu-mipsel -cpu mips32dspr2 ./maq_s_w_phl.tst
+qemu-mipsel -cpu mips32dspr2 ./maq_s_w_phr.tst
+qemu-mipsel -cpu mips32dspr2 ./mfhi.tst
+qemu-mipsel -cpu mips32dspr2 ./mflo.tst
+qemu-mipsel -cpu mips32dspr2 ./modsub.tst
+qemu-mipsel -cpu mips32dspr2 ./msub.tst
+qemu-mipsel -cpu mips32dspr2 ./msubu.tst
+qemu-mipsel -cpu mips32dspr2 ./mthi.tst
+qemu-mipsel -cpu mips32dspr2 ./mthlip.tst
+qemu-mipsel -cpu mips32dspr2 ./mtlo.tst
+qemu-mipsel -cpu mips32dspr2 ./muleq_s_w_phr.tst
+qemu-mipsel -cpu mips32dspr2 ./muleu_s_ph_qbl.tst
+qemu-mipsel -cpu mips32dspr2 ./muleu_s_ph_qbr.tst
+qemu-mipsel -cpu mips32dspr2 ./mulq_rs_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./mult.tst
+qemu-mipsel -cpu mips32dspr2 ./multu.tst
+qemu-mipsel -cpu mips32dspr2 ./packrl_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./pick_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./pick_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./precequ_ph_qbla.tst
+qemu-mipsel -cpu mips32dspr2 ./precequ_ph_qbl.tst
+qemu-mipsel -cpu mips32dspr2 ./precequ_ph_qbra.tst
+qemu-mipsel -cpu mips32dspr2 ./precequ_ph_qbr.tst
+qemu-mipsel -cpu mips32dspr2 ./preceq_w_phl.tst
+qemu-mipsel -cpu mips32dspr2 ./preceq_w_phr.tst
+qemu-mipsel -cpu mips32dspr2 ./preceu_ph_qbla.tst
+qemu-mipsel -cpu mips32dspr2 ./preceu_ph_qbl.tst
+qemu-mipsel -cpu mips32dspr2 ./preceu_ph_qbra.tst
+qemu-mipsel -cpu mips32dspr2 ./preceu_ph_qbr.tst
+qemu-mipsel -cpu mips32dspr2 ./precrq_ph_w.tst
+qemu-mipsel -cpu mips32dspr2 ./precrq_qb_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./precrq_rs_ph_w.tst
+qemu-mipsel -cpu mips32dspr2 ./precrqu_s_qb_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./raddu_w_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./rddsp.tst
+qemu-mipsel -cpu mips32dspr2 ./repl_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./repl_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./replv_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./replv_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./shilo.tst
+qemu-mipsel -cpu mips32dspr2 ./shilov.tst
+qemu-mipsel -cpu mips32dspr2 ./shll_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./shll_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./shll_s_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./shll_s_w.tst
+qemu-mipsel -cpu mips32dspr2 ./shllv_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./shllv_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./shllv_s_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./shllv_s_w.tst
+qemu-mipsel -cpu mips32dspr2 ./shra_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./shra_r_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./shra_r_w.tst
+qemu-mipsel -cpu mips32dspr2 ./shrav_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./shrav_r_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./shrav_r_w.tst
+qemu-mipsel -cpu mips32dspr2 ./shrl_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./shrlv_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./subq_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./subq_s_ph.tst
+qemu-mipsel -cpu mips32dspr2 ./subq_s_w.tst
+qemu-mipsel -cpu mips32dspr2 ./subu_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./subu_s_qb.tst
+qemu-mipsel -cpu mips32dspr2 ./wrdsp.tst
diff --git a/tests/tcg/mips/mips32-dsp/packrl_ph.c b/tests/tcg/mips/mips32-dsp/packrl_ph.c
new file mode 100644
index 0000000..1f8e699
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/packrl_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x56788765;
+
+    __asm
+        ("packrl.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/pick_ph.c b/tests/tcg/mips/mips32-dsp/pick_ph.c
new file mode 100644
index 0000000..73342cb
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/pick_ph.c
@@ -0,0 +1,23 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    dsp = 0x0A000000;
+    result = 0x12344321;
+
+    __asm
+        ("wrdsp %3, 0x10\n\t"
+         "pick.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt), "r"(dsp)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/pick_qb.c b/tests/tcg/mips/mips32-dsp/pick_qb.c
new file mode 100644
index 0000000..052cc58
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/pick_qb.c
@@ -0,0 +1,23 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    dsp = 0x0A000000;
+    result = 0x12655621;
+
+    __asm
+        ("wrdsp %3, 0x10\n\t"
+         "pick.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt), "r"(dsp)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/preceq_w_phl.c b/tests/tcg/mips/mips32-dsp/preceq_w_phl.c
new file mode 100644
index 0000000..bf70bf7
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/preceq_w_phl.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x87654321;
+    result = 0x87650000;
+
+    __asm
+        ("preceq.w.phl %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/preceq_w_phr.c b/tests/tcg/mips/mips32-dsp/preceq_w_phr.c
new file mode 100644
index 0000000..3f885ef
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/preceq_w_phr.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x87654321;
+    result = 0x43210000;
+
+    __asm
+        ("preceq.w.phr %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c b/tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c
new file mode 100644
index 0000000..63b7a95
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x87654321;
+    result = 0x43803280;
+
+    __asm
+        ("precequ.ph.qbl %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c b/tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c
new file mode 100644
index 0000000..31627f0
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x87654321;
+    result = 0x43802180;
+
+    __asm
+        ("precequ.ph.qbla %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c b/tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c
new file mode 100644
index 0000000..b6f72d3
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x87654321;
+    result = 0x21801080;
+
+    __asm
+        ("precequ.ph.qbr %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c b/tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c
new file mode 100644
index 0000000..4764fd0
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x87654321;
+    result = 0x32801080;
+
+    __asm
+        ("precequ.ph.qbra %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c b/tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c
new file mode 100644
index 0000000..fa95c26
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x87654321;
+    result = 0x00870065;
+
+    __asm
+        ("preceu.ph.qbl %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c b/tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c
new file mode 100644
index 0000000..021f21a
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x87654321;
+    result = 0x00870043;
+
+    __asm
+        ("preceu.ph.qbla %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c b/tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c
new file mode 100644
index 0000000..03df18c
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x87654321;
+    result = 0x00430021;
+
+    __asm
+        ("preceu.ph.qbr %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c b/tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c
new file mode 100644
index 0000000..6343276
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x87654321;
+    result = 0x00650021;
+
+    __asm
+        ("preceu.ph.qbra %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precrq_ph_w.c b/tests/tcg/mips/mips32-dsp/precrq_ph_w.c
new file mode 100644
index 0000000..25d45f1
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precrq_ph_w.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x12348765;
+
+    __asm
+        ("precrq.ph.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precrq_qb_ph.c b/tests/tcg/mips/mips32-dsp/precrq_qb_ph.c
new file mode 100644
index 0000000..fe23acc
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precrq_qb_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x12568743;
+
+    __asm
+        ("precrq.qb.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c b/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c
new file mode 100644
index 0000000..87214b8
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x12348765;
+
+    __asm
+        ("precrq_rs.ph.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c b/tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c
new file mode 100644
index 0000000..9a459cc
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x24AC0086;
+
+    __asm
+        ("precrqu_s.qb.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/raddu_w_qb.c b/tests/tcg/mips/mips32-dsp/raddu_w_qb.c
new file mode 100644
index 0000000..77a983c
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/raddu_w_qb.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs;
+    int result;
+
+    rs = 0x12345678;
+    result = 0x114;
+
+    __asm
+        ("raddu.w.qb %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rs)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/rddsp.c b/tests/tcg/mips/mips32-dsp/rddsp.c
new file mode 100644
index 0000000..e8948ec
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/rddsp.c
@@ -0,0 +1,54 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int dsp_i, dsp_o;
+    int ccond_i, outflag_i, efi_i, c_i, scount_i, pos_i;
+    int ccond_o, outflag_o, efi_o, c_o, scount_o, pos_o;
+    int ccond_r, outflag_r, efi_r, c_r, scount_r, pos_r;
+
+    ccond_i   = 0x000000BC;/* 4 */
+    outflag_i = 0x0000001B;/* 3 */
+    efi_i     = 0x00000001;/* 5 */
+    c_i       = 0x00000001;/* 2 */
+    scount_i  = 0x0000000F;/* 1 */
+    pos_i     = 0x0000000C;/* 0 */
+
+    dsp_i = (ccond_i   << 24) | \
+            (outflag_i << 16) | \
+            (efi_i     << 14) | \
+            (c_i       << 13) | \
+            (scount_i  <<  7) | \
+            pos_i;
+
+    ccond_r   = ccond_i;
+    outflag_r = outflag_i;
+    efi_r     = efi_i;
+    c_r       = c_i;
+    scount_r  = scount_i;
+    pos_r     = pos_i;
+
+    __asm
+        ("wrdsp %1, 0x3F\n\t"
+         "rddsp %0, 0x3F\n\t"
+         : "=r"(dsp_o)
+         : "r"(dsp_i)
+        );
+
+    ccond_o   = (dsp_o >> 24) & 0xFF;
+    outflag_o = (dsp_o >> 16) & 0xFF;
+    efi_o     = (dsp_o >> 14) & 0x01;
+    c_o       = (dsp_o >> 14) & 0x01;
+    scount_o  = (dsp_o >>  7) & 0x3F;
+    pos_o     =  dsp_o & 0x1F;
+
+    assert(ccond_o   == ccond_r);
+    assert(outflag_o == outflag_r);
+    assert(efi_o     == efi_r);
+    assert(c_o       == c_r);
+    assert(scount_o  == scount_r);
+    assert(pos_o     == pos_r);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/repl_ph.c b/tests/tcg/mips/mips32-dsp/repl_ph.c
new file mode 100644
index 0000000..2107495
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/repl_ph.c
@@ -0,0 +1,23 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, result;
+
+    result = 0x01BF01BF;
+    __asm
+        ("repl.ph %0, 0x1BF\n\t"
+         : "=r"(rd)
+        );
+    assert(rd == result);
+
+    result = 0x01FF01FF;
+    __asm
+        ("repl.ph %0, 0x01FF\n\t"
+         : "=r"(rd)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/repl_qb.c b/tests/tcg/mips/mips32-dsp/repl_qb.c
new file mode 100644
index 0000000..6631393
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/repl_qb.c
@@ -0,0 +1,16 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, result;
+
+    result = 0xBFBFBFBF;
+    __asm
+        ("repl.qb %0, 0xBF\n\t"
+         : "=r"(rd)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/replv_ph.c b/tests/tcg/mips/mips32-dsp/replv_ph.c
new file mode 100644
index 0000000..07fb15f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/replv_ph.c
@@ -0,0 +1,19 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x12345678;
+    result = 0x56785678;
+    __asm
+        ("replv.ph %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/replv_qb.c b/tests/tcg/mips/mips32-dsp/replv_qb.c
new file mode 100644
index 0000000..dd1271f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/replv_qb.c
@@ -0,0 +1,19 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt     = 0x12345678;
+    result = 0x78787878;
+    __asm
+        ("replv.qb %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shilo.c b/tests/tcg/mips/mips32-dsp/shilo.c
new file mode 100644
index 0000000..b686616
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shilo.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int ach, acl;
+    int resulth, resultl;
+
+    ach = 0xBBAACCFF;
+    acl = 0x1C3B001D;
+
+    resulth = 0x17755;
+    resultl = 0x99fe3876;
+
+    __asm
+        ("mthi %0, $ac1\n\t"
+         "mtlo %1, $ac1\n\t"
+         "shilo $ac1, 0x0F\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shilov.c b/tests/tcg/mips/mips32-dsp/shilov.c
new file mode 100644
index 0000000..f186032
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shilov.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, ach, acl;
+    int resulth, resultl;
+
+    rs  = 0x0F;
+    ach = 0xBBAACCFF;
+    acl = 0x1C3B001D;
+
+    resulth = 0x17755;
+    resultl = 0x99fe3876;
+
+    __asm
+        ("mthi %0, $ac1\n\t"
+         "mtlo %1, $ac1\n\t"
+         "shilov $ac1, %2\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shll_ph.c b/tests/tcg/mips/mips32-dsp/shll_ph.c
new file mode 100644
index 0000000..b8f1ff5
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shll_ph.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt, dsp;
+    int result, resultdsp;
+
+    rt        = 0x12345678;
+    result    = 0xA000C000;
+    resultdsp = 1;
+
+    __asm
+        ("shll.ph %0, %2, 0x0B\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shll_qb.c b/tests/tcg/mips/mips32-dsp/shll_qb.c
new file mode 100644
index 0000000..d79814c
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shll_qb.c
@@ -0,0 +1,23 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt, dsp;
+    int result, resultdsp;
+
+    rt     = 0x87654321;
+    result = 0x38281808;
+    resultdsp = 0x01;
+
+    __asm
+        ("shll.qb %0, %2, 0x03\n\t"
+         "rddsp   %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shll_s_ph.c b/tests/tcg/mips/mips32-dsp/shll_s_ph.c
new file mode 100644
index 0000000..910fea3
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shll_s_ph.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt, dsp;
+    int result, resultdsp;
+
+    rt        = 0x12345678;
+    result    = 0x7FFF7FFF;
+    resultdsp = 0x01;
+
+    __asm
+        ("shll_s.ph %0, %2, 0x0B\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shll_s_w.c b/tests/tcg/mips/mips32-dsp/shll_s_w.c
new file mode 100644
index 0000000..c42c168
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shll_s_w.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt, dsp;
+    int result, resultdsp;
+
+    rt        = 0x12345678;
+    result    = 0x7FFFFFFF;
+    resultdsp = 0x01;
+
+    __asm
+        ("shll_s.w %0, %2, 0x0B\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shllv_ph.c b/tests/tcg/mips/mips32-dsp/shllv_ph.c
new file mode 100644
index 0000000..b0fcae8
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shllv_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs        = 0x0B;
+    rt        = 0x12345678;
+    result    = 0xA000C000;
+    resultdsp = 1;
+
+    __asm
+        ("shllv.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shllv_qb.c b/tests/tcg/mips/mips32-dsp/shllv_qb.c
new file mode 100644
index 0000000..0bcc24c
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shllv_qb.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs     = 0x03;
+    rt     = 0x87654321;
+    result = 0x38281808;
+    resultdsp = 0x01;
+
+    __asm
+        ("shllv.qb %0, %2, %3\n\t"
+         "rddsp   %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shllv_s_ph.c b/tests/tcg/mips/mips32-dsp/shllv_s_ph.c
new file mode 100644
index 0000000..a6d61b1
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shllv_s_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs        = 0x0B;
+    rt        = 0x12345678;
+    result    = 0x7FFF7FFF;
+    resultdsp = 0x01;
+
+    __asm
+        ("shllv_s.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shllv_s_w.c b/tests/tcg/mips/mips32-dsp/shllv_s_w.c
new file mode 100644
index 0000000..69c896d
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shllv_s_w.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs        = 0x0B;
+    rt        = 0x12345678;
+    result    = 0x7FFFFFFF;
+    resultdsp = 0x01;
+
+    __asm
+        ("shllv_s.w %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shra_ph.c b/tests/tcg/mips/mips32-dsp/shra_ph.c
new file mode 100644
index 0000000..be7711a
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shra_ph.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt     = 0x87654321;
+    result = 0xF0EC0864;
+
+    __asm
+        ("shra.ph %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shra_r_ph.c b/tests/tcg/mips/mips32-dsp/shra_r_ph.c
new file mode 100644
index 0000000..bb64683
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shra_r_ph.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt     = 0x87654321;
+    result = 0xF0ED0864;
+
+    __asm
+        ("shra_r.ph %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shra_r_w.c b/tests/tcg/mips/mips32-dsp/shra_r_w.c
new file mode 100644
index 0000000..b94748c
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shra_r_w.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt     = 0x87654321;
+    result = 0xF0ECA864;
+
+    __asm
+        ("shra_r.w %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shrav_ph.c b/tests/tcg/mips/mips32-dsp/shrav_ph.c
new file mode 100644
index 0000000..a4db736
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shrav_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x03;
+    rt     = 0x87654321;
+    result = 0xF0EC0864;
+
+    __asm
+        ("shrav.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shrav_r_ph.c b/tests/tcg/mips/mips32-dsp/shrav_r_ph.c
new file mode 100644
index 0000000..f6d3c70
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shrav_r_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x03;
+    rt     = 0x87654321;
+    result = 0xF0ED0864;
+
+    __asm
+        ("shrav_r.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shrav_r_w.c b/tests/tcg/mips/mips32-dsp/shrav_r_w.c
new file mode 100644
index 0000000..1841381
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shrav_r_w.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x03;
+    rt     = 0x87654321;
+    result = 0xF0ECA864;
+
+    __asm
+        ("shrav_r.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shrl_qb.c b/tests/tcg/mips/mips32-dsp/shrl_qb.c
new file mode 100644
index 0000000..ccc991f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shrl_qb.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt     = 0x12345678;
+    result = 0x00010203;
+
+    __asm
+        ("shrl.qb %0, %1, 0x05\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shrlv_qb.c b/tests/tcg/mips/mips32-dsp/shrlv_qb.c
new file mode 100644
index 0000000..4b0a826
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shrlv_qb.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x05;
+    rt     = 0x12345678;
+    result = 0x00010203;
+
+    __asm
+        ("shrlv.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/subq_ph.c b/tests/tcg/mips/mips32-dsp/subq_ph.c
new file mode 100644
index 0000000..e9d349a
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/subq_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0x8ACF1357;
+    resultdsp = 0x01;
+
+    __asm
+        ("subq.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/subq_s_ph.c b/tests/tcg/mips/mips32-dsp/subq_s_ph.c
new file mode 100644
index 0000000..56fed9b
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/subq_s_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0x7FFF1357;
+    resultdsp = 0x01;
+
+    __asm
+        ("subq_s.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/subq_s_w.c b/tests/tcg/mips/mips32-dsp/subq_s_w.c
new file mode 100644
index 0000000..f44f36e
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/subq_s_w.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0x7FFFFFFF;
+    resultdsp = 0x01;
+
+    __asm
+        ("subq_s.w %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/subu_qb.c b/tests/tcg/mips/mips32-dsp/subu_qb.c
new file mode 100644
index 0000000..4209096
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/subu_qb.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0x8BCF1357;
+    resultdsp = 0x01;
+
+    __asm
+        ("subu.qb %0, %2, %3\n\t"
+         "rddsp   %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/subu_s_qb.c b/tests/tcg/mips/mips32-dsp/subu_s_qb.c
new file mode 100644
index 0000000..3d65053
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/subu_s_qb.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0x00001357;
+    resultdsp = 0x01;
+
+    __asm
+        ("subu_s.qb %0, %2, %3\n\t"
+         "rddsp   %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/wrdsp.c b/tests/tcg/mips/mips32-dsp/wrdsp.c
new file mode 100644
index 0000000..e8948ec
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/wrdsp.c
@@ -0,0 +1,54 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int dsp_i, dsp_o;
+    int ccond_i, outflag_i, efi_i, c_i, scount_i, pos_i;
+    int ccond_o, outflag_o, efi_o, c_o, scount_o, pos_o;
+    int ccond_r, outflag_r, efi_r, c_r, scount_r, pos_r;
+
+    ccond_i   = 0x000000BC;/* 4 */
+    outflag_i = 0x0000001B;/* 3 */
+    efi_i     = 0x00000001;/* 5 */
+    c_i       = 0x00000001;/* 2 */
+    scount_i  = 0x0000000F;/* 1 */
+    pos_i     = 0x0000000C;/* 0 */
+
+    dsp_i = (ccond_i   << 24) | \
+            (outflag_i << 16) | \
+            (efi_i     << 14) | \
+            (c_i       << 13) | \
+            (scount_i  <<  7) | \
+            pos_i;
+
+    ccond_r   = ccond_i;
+    outflag_r = outflag_i;
+    efi_r     = efi_i;
+    c_r       = c_i;
+    scount_r  = scount_i;
+    pos_r     = pos_i;
+
+    __asm
+        ("wrdsp %1, 0x3F\n\t"
+         "rddsp %0, 0x3F\n\t"
+         : "=r"(dsp_o)
+         : "r"(dsp_i)
+        );
+
+    ccond_o   = (dsp_o >> 24) & 0xFF;
+    outflag_o = (dsp_o >> 16) & 0xFF;
+    efi_o     = (dsp_o >> 14) & 0x01;
+    c_o       = (dsp_o >> 14) & 0x01;
+    scount_o  = (dsp_o >>  7) & 0x3F;
+    pos_o     =  dsp_o & 0x1F;
+
+    assert(ccond_o   == ccond_r);
+    assert(outflag_o == outflag_r);
+    assert(efi_o     == efi_r);
+    assert(c_o       == c_r);
+    assert(scount_o  == scount_r);
+    assert(pos_o     == pos_r);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/Makefile b/tests/tcg/mips/mips32-dspr2/Makefile
new file mode 100644
index 0000000..d266bf2
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/Makefile
@@ -0,0 +1,72 @@
+-include ../../config-host.mak
+
+CROSS=mips64el-unknown-linux-gnu-
+
+SIM=qemu-mipsel
+SIM_FLAGS=-cpu mips32dspr2
+
+CC      = $(CROSS)gcc
+CFLAGS  = -mabi=32 -march=mips32r2 -mgp32 -mdspr2 -static
+
+TESTCASES = absq_s_qb.tst
+TESTCASES += addqh_ph.tst
+TESTCASES += addqh_r_ph.tst
+TESTCASES += addqh_r_w.tst
+TESTCASES += addqh_w.tst
+TESTCASES += adduh_qb.tst
+TESTCASES += adduh_r_qb.tst
+TESTCASES += addu_ph.tst
+TESTCASES += addu_s_ph.tst
+TESTCASES += append.tst
+TESTCASES += balign.tst
+TESTCASES += cmpgdu_eq_qb.tst
+TESTCASES += cmpgdu_le_qb.tst
+TESTCASES += cmpgdu_lt_qb.tst
+TESTCASES += dpaqx_sa_w_ph.tst
+TESTCASES += dpa_w_ph.tst
+TESTCASES += dpax_w_ph.tst
+TESTCASES += dpaqx_s_w_ph.tst
+TESTCASES += dpsqx_sa_w_ph.tst
+TESTCASES += dpsqx_s_w_ph.tst
+TESTCASES += dps_w_ph.tst
+TESTCASES += dpsx_w_ph.tst
+TESTCASES += muleq_s_w_phl.tst
+TESTCASES += mul_ph.tst
+TESTCASES += mulq_rs_w.tst
+TESTCASES += mulq_s_ph.tst
+TESTCASES += mulq_s_w.tst
+TESTCASES += mulsaq_s_w_ph.tst
+TESTCASES += mulsa_w_ph.tst
+TESTCASES += mul_s_ph.tst
+TESTCASES += precr_qb_ph.tst
+TESTCASES += precr_sra_ph_w.tst
+TESTCASES += precr_sra_r_ph_w.tst
+TESTCASES += prepend.tst
+TESTCASES += shra_qb.tst
+TESTCASES += shra_r_qb.tst
+TESTCASES += shrav_qb.tst
+TESTCASES += shrav_r_qb.tst
+TESTCASES += shrl_ph.tst
+TESTCASES += shrlv_ph.tst
+TESTCASES += subqh_ph.tst
+TESTCASES += subqh_r_ph.tst
+TESTCASES += subqh_r_w.tst
+TESTCASES += subqh_w.tst
+TESTCASES += subuh_qb.tst
+TESTCASES += subuh_r_qb.tst
+TESTCASES += subu_ph.tst
+TESTCASES += subu_s_ph.tst
+
+all: $(TESTCASES)
+
+%.tst: %.c
+	$(CC) $(CFLAGS) $< -o $@
+
+check: $(TESTCASES)
+	@for case in $(TESTCASES); do \
+        echo $(SIM) $(SIM_FLAGS) ./$$case;\
+		$(SIM) $(SIM_FLAGS) ./$$case; \
+	done
+
+clean:
+	$(RM) -rf $(TESTCASES)
diff --git a/tests/tcg/mips/mips32-dspr2/absq_s_qb.c b/tests/tcg/mips/mips32-dspr2/absq_s_qb.c
new file mode 100644
index 0000000..af4683f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/absq_s_qb.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int input, result, dsp;
+    int hope;
+
+    input = 0x701BA35E;
+    hope  = 0x701B5D5E;
+
+    __asm
+        ("absq_s.qb %0, %1\n\t"
+         : "=r"(result)
+         : "r"(input)
+        );
+    assert(result == hope);
+
+
+    input = 0x801BA35E;
+    hope  = 0x7F1B5D5E;
+
+    __asm
+        ("absq_s.qb %0, %2\n\t"
+         "rddsp %1\n\t"
+         : "=r"(result), "=r"(dsp)
+         : "r"(input)
+        );
+    dsp = dsp >> 20;
+    dsp &= 0x01;
+    assert(dsp == 1);
+    assert(result == hope);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/addqh_ph.c b/tests/tcg/mips/mips32-dspr2/addqh_ph.c
new file mode 100644
index 0000000..11f8597
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/addqh_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x706A13FE;
+    rt     = 0x13065174;
+    result = 0x41B832B9;
+    __asm
+        ("addqh.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    rs     = 0x01000100;
+    rt     = 0x02000100;
+    result = 0x01800100;
+    __asm
+        ("addqh.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/addqh_r_ph.c b/tests/tcg/mips/mips32-dspr2/addqh_r_ph.c
new file mode 100644
index 0000000..ab91c0f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/addqh_r_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x706A13FE;
+    rt     = 0x13065174;
+    result = 0x41B832B9;
+    __asm
+        ("addqh_r.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    rs     = 0x01000100;
+    rt     = 0x02000100;
+    result = 0x01800100;
+    __asm
+        ("addqh_r.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/addqh_r_w.c b/tests/tcg/mips/mips32-dspr2/addqh_r_w.c
new file mode 100644
index 0000000..75a75c5
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/addqh_r_w.c
@@ -0,0 +1,34 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x00000010;
+    rt     = 0x00000001;
+    result = 0x00000009;
+
+    __asm
+        ("addqh_r.w  %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    assert(rd == result);
+
+    rs     = 0xFFFFFFFE;
+    rt     = 0x00000001;
+    result = 0x00000000;
+
+    __asm
+        ("addqh_r.w  %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/addqh_w.c b/tests/tcg/mips/mips32-dspr2/addqh_w.c
new file mode 100644
index 0000000..de6926e
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/addqh_w.c
@@ -0,0 +1,34 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x00000010;
+    rt     = 0x00000001;
+    result = 0x00000008;
+
+    __asm
+        ("addqh.w  %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    assert(rd == result);
+
+    rs     = 0xFFFFFFFE;
+    rt     = 0x00000001;
+    result = 0xFFFFFFFF;
+
+    __asm
+        ("addqh.w  %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/addu_ph.c b/tests/tcg/mips/mips32-dspr2/addu_ph.c
new file mode 100644
index 0000000..01efb3d
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/addu_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x00FF00FF;
+    rt     = 0x00010001;
+    result = 0x01000100;
+    __asm
+        ("addu.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    rs     = 0xFFFF1111;
+    rt     = 0x00020001;
+    result = 0x00011112;
+    __asm
+        ("addu.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/addu_s_ph.c b/tests/tcg/mips/mips32-dspr2/addu_s_ph.c
new file mode 100644
index 0000000..51cc2ac
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/addu_s_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x00FE00FE;
+    rt     = 0x00020001;
+    result = 0x010000FF;
+    __asm
+        ("addu_s.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    rs     = 0xFFFF1111;
+    rt     = 0x00020001;
+    result = 0xFFFF1112;
+    __asm
+        ("addu_s.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/adduh_qb.c b/tests/tcg/mips/mips32-dspr2/adduh_qb.c
new file mode 100644
index 0000000..a1f5d63
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/adduh_qb.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0xFF0055AA;
+    rt     = 0x0113421B;
+    result = 0x80094B62;
+    __asm
+        ("adduh.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    rs     = 0xFFFF0FFF;
+    rt     = 0x00010111;
+    result = 0x7F800888;
+    __asm
+        ("adduh.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/adduh_r_qb.c b/tests/tcg/mips/mips32-dspr2/adduh_r_qb.c
new file mode 100644
index 0000000..81e98c1
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/adduh_r_qb.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0xFF0055AA;
+    rt     = 0x01112211;
+    result = 0x80093C5E;
+    __asm
+        ("adduh_r.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    rs     = 0xFFFF0FFF;
+    rt     = 0x00010111;
+    result = 0x80800888;
+    __asm
+        ("adduh_r.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/append.c b/tests/tcg/mips/mips32-dspr2/append.c
new file mode 100644
index 0000000..9a91e16
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/append.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int result;
+
+    rs     = 0xFF0055AA;
+    rt     = 0x0113421B;
+    result = 0x02268436;
+    __asm
+        ("append %0, %1, 0x01\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    assert(rt == result);
+
+    rs     = 0xFFFF0FFF;
+    rt     = 0x00010111;
+    result = 0x0010111F;
+    __asm
+        ("append %0, %1, 0x04\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    assert(rt == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/balign.c b/tests/tcg/mips/mips32-dspr2/balign.c
new file mode 100644
index 0000000..537cf04
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/balign.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int result;
+
+    rs     = 0xFF0055AA;
+    rt     = 0x0113421B;
+    result = 0x13421BFF;
+    __asm
+        ("balign %0, %1, 0x01\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    assert(rt == result);
+
+    rs     = 0xFFFF0FFF;
+    rt     = 0x00010111;
+    result = 0x11FFFF0F;
+    __asm
+        ("balign %0, %1, 0x03\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    assert(rt == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c b/tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c
new file mode 100644
index 0000000..fccd975
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c
@@ -0,0 +1,37 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int dsp;
+    int result;
+
+    rs         = 0x11777066;
+    rt         = 0x55AA70FF;
+    result     = 0x02;
+    __asm
+        ("cmpgdu.eq.qb %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    assert(rd  == result);
+    assert(dsp == result);
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x0F;
+    __asm
+        ("cmpgdu.eq.qb %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    assert(rd  == result);
+    assert(dsp == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c b/tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c
new file mode 100644
index 0000000..a0ecdca
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c
@@ -0,0 +1,37 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int dsp;
+    int result;
+
+    rs         = 0x11777066;
+    rt         = 0x55AA70FF;
+    result     = 0x0F;
+    __asm
+        ("cmpgdu.le.qb %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    assert(rd  == result);
+    assert(dsp == result);
+
+    rs     = 0x11777066;
+    rt     = 0x11707066;
+    result = 0x0B;
+    __asm
+        ("cmpgdu.le.qb %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    assert(rd  == result);
+    assert(dsp == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c b/tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c
new file mode 100644
index 0000000..dba99e3
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c
@@ -0,0 +1,37 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int dsp;
+    int result;
+
+    rs         = 0x11777066;
+    rt         = 0x55AA70FF;
+    result     = 0x0D;
+    __asm
+        ("cmpgdu.lt.qb %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    assert(rd  == result);
+    assert(dsp == result);
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x00;
+    __asm
+        ("cmpgdu.lt.qb %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    assert(rd  == result);
+    assert(dsp == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c
new file mode 100644
index 0000000..d2bf3be
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int ach = 5, acl = 5;
+    int resulth, resultl;
+
+    rs     = 0x00FF00FF;
+    rt     = 0x00010002;
+    resulth = 0x05;
+    resultl = 0x0302;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpa.w.ph $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c
new file mode 100644
index 0000000..841808d
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c
@@ -0,0 +1,57 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt, dsp;
+    int ach = 5, acl = 5;
+    int resulth, resultl, resultdsp;
+
+    rs     = 0x800000FF;
+    rt     = 0x00018000;
+    resulth = 0x05;
+    resultl = 0x80000202;
+    resultdsp = 0x01;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpaqx_s.w.ph $ac1, %3, %4\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x01;
+    assert(dsp == resultdsp);
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    ach    = 5;
+    acl    = 5;
+    rs     = 0x00FF00FF;
+    rt     = 0x00010002;
+    resulth = 0x05;
+    resultl = 0x05FF;
+    /***********************************************************
+     * Because of we set outflag at last time, although this
+     * time we set nothing, but it is stay the last time value.
+     **********************************************************/
+    resultdsp = 0x01;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpaqx_s.w.ph $ac1, %3, %4\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x01;
+    assert(dsp == resultdsp);
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c
new file mode 100644
index 0000000..65d3993
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt, dsp;
+    int ach = 5, acl = 5;
+    int resulth, resultl, resultdsp;
+
+    rs     = 0x00FF00FF;
+    rt     = 0x00010002;
+    resulth = 0x00;
+    resultl = 0x7FFFFFFF;
+    resultdsp = 0x01;
+    __asm
+        ("wrdsp %2\n\t"
+         "mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpaqx_sa.w.ph $ac1, %3, %4\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "+r"(ach), "+r"(acl), "+r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    assert(dsp >> (16 + 1) == resultdsp);
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c
new file mode 100644
index 0000000..f756997
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int ach = 5, acl = 5;
+    int resulth, resultl;
+
+    rs     = 0x00FF00FF;
+    rt     = 0x00010002;
+    resulth = 0x05;
+    resultl = 0x0302;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpax.w.ph $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dps_w_ph.c b/tests/tcg/mips/mips32-dspr2/dps_w_ph.c
new file mode 100644
index 0000000..8303643
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dps_w_ph.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int ach = 5, acl = 5;
+    int resulth, resultl;
+
+    rs     = 0x00FF00FF;
+    rt     = 0x00010002;
+    resulth = 0x04;
+    resultl = 0xFFFFFD08;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dps.w.ph $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c
new file mode 100644
index 0000000..0f26071
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt, dsp;
+    int ach = 5, acl = 5;
+    int resulth, resultl, resultdsp;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x04;
+    resultl = 0xAEA3E09B;
+    resultdsp = 0x00;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsqx_s.w.ph $ac1, %3, %4\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x01;
+    assert(dsp == resultdsp);
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c
new file mode 100644
index 0000000..4688caf
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt, dsp;
+    int ach = 5, acl = 5;
+    int resulth, resultl, resultdsp;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x00;
+    resultl = 0x7FFFFFFF;
+    resultdsp = 0x01;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsqx_sa.w.ph $ac1, %3, %4\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x01;
+    assert(dsp == resultdsp);
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c
new file mode 100644
index 0000000..6db59a4
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int ach = 5, acl = 5;
+    int resulth, resultl;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x04;
+    resultl = 0xD751F050;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsx.w.ph $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mul_ph.c b/tests/tcg/mips/mips32-dspr2/mul_ph.c
new file mode 100644
index 0000000..fc91f5d
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mul_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x03FB1234;
+    rt = 0x0BCC4321;
+    result = 0xF504F4B4;
+    resultdsp = 1;
+
+    __asm
+        ("mul.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    assert(rd  == result);
+    assert(dsp == resultdsp);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mul_s_ph.c b/tests/tcg/mips/mips32-dspr2/mul_s_ph.c
new file mode 100644
index 0000000..949ea5e
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mul_s_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x03FB1234;
+    rt = 0x0BCC4321;
+    result = 0x7fff7FFF;
+    resultdsp = 1;
+
+    __asm
+        ("mul_s.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    assert(rd  == result);
+    assert(dsp == resultdsp);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/muleq_s_w_phl.c b/tests/tcg/mips/mips32-dspr2/muleq_s_w_phl.c
new file mode 100644
index 0000000..4e3262f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/muleq_s_w_phl.c
@@ -0,0 +1,40 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x80001234;
+    rt = 0x80004321;
+    result = 0x7FFFFFFF;
+    resultdsp = 1;
+
+    __asm
+        ("muleq_s.w.phl %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    assert(rd  == result);
+    assert(dsp == resultdsp);
+
+    rs = 0x12340000;
+    rt = 0x43210000;
+    result = 0x98be968;
+    resultdsp = 1;
+
+    __asm
+        ("muleq_s.w.phl %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    assert(rd  == result);
+    assert(dsp == resultdsp);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mulq_rs_w.c b/tests/tcg/mips/mips32-dspr2/mulq_rs_w.c
new file mode 100644
index 0000000..669405f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mulq_rs_w.c
@@ -0,0 +1,36 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x80001234;
+    rt = 0x80004321;
+    result = 0x80005555;
+
+    __asm
+        ("mulq_rs.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd  == result);
+
+    rs = 0x80000000;
+    rt = 0x80000000;
+    result = 0x7FFFFFFF;
+    resultdsp = 1;
+
+    __asm
+        ("mulq_rs.w %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    assert(rd  == result);
+    assert(dsp == resultdsp);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mulq_s_ph.c b/tests/tcg/mips/mips32-dspr2/mulq_s_ph.c
new file mode 100644
index 0000000..d0f7674
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mulq_s_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x80001234;
+    rt = 0x80004321;
+    result = 0x7FFF098B;
+    resultdsp = 1;
+
+    __asm
+        ("mulq_s.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    assert(rd  == result);
+    assert(dsp == resultdsp);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mulq_s_w.c b/tests/tcg/mips/mips32-dspr2/mulq_s_w.c
new file mode 100644
index 0000000..df148b7
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mulq_s_w.c
@@ -0,0 +1,36 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x80001234;
+    rt = 0x80004321;
+    result = 0x80005555;
+
+    __asm
+        ("mulq_s.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd  == result);
+
+    rs = 0x80000000;
+    rt = 0x80000000;
+    result = 0x7FFFFFFF;
+    resultdsp = 1;
+
+    __asm
+        ("mulq_s.w %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    assert(rd  == result);
+    assert(dsp == resultdsp);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c b/tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c
new file mode 100644
index 0000000..a694093
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt, ach, acl;
+    int resulth, resultl;
+
+    ach = 0x05;
+    acl = 0x00BBDDCC;
+    rs = 0x80001234;
+    rt = 0x80004321;
+    resulth = 0x05;
+    resultl = 0x3BF5E918;
+
+    __asm
+        ("mthi %0, $ac1\n\t"
+         "mtlo %1, $ac1\n\t"
+         "mulsa.w.ph $ac1, %2, %3\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c b/tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c
new file mode 100644
index 0000000..06c91a4
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt, ach, acl;
+    int resulth, resultl;
+
+    ach = 0x05;
+    acl = 0x00BBDDCC;
+    rs = 0x80001234;
+    rt = 0x80004321;
+    resulth = 0x05;
+    resultl = 0x772ff463;
+
+    __asm
+        ("mthi %0, $ac1\n\t"
+         "mtlo %1, $ac1\n\t"
+         "mulsaq_s.w.ph $ac1, %2, %3\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    assert(ach == resulth);
+    assert(acl == resultl);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/precr_qb_ph.c b/tests/tcg/mips/mips32-dspr2/precr_qb_ph.c
new file mode 100644
index 0000000..3a2b3fd
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/precr_qb_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x34786521;
+
+    __asm
+        ("precr.qb.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(result == rd);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c b/tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c
new file mode 100644
index 0000000..5c9baab
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c
@@ -0,0 +1,32 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x43215678;
+
+    __asm
+        ("precr_sra.ph.w %0, %1, 0x00\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    assert(result == rt);
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0xFFFF0000;
+
+    __asm
+        ("precr_sra.ph.w %0, %1, 0x1F\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    assert(result == rt);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c b/tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c
new file mode 100644
index 0000000..6474a10
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c
@@ -0,0 +1,32 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x43215678;
+
+    __asm
+        ("precr_sra_r.ph.w %0, %1, 0x00\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    assert(result == rt);
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0xFFFF0000;
+
+    __asm
+        ("precr_sra_r.ph.w %0, %1, 0x1F\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    assert(result == rt);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/prepend.c b/tests/tcg/mips/mips32-dspr2/prepend.c
new file mode 100644
index 0000000..f6bcd47
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/prepend.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x87654321;
+    __asm
+        ("prepend %0, %1, 0x00\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    assert(rt == result);
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0xACF10ECA;
+    __asm
+        ("prepend %0, %1, 0x0F\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    assert(rt == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/shra_qb.c b/tests/tcg/mips/mips32-dspr2/shra_qb.c
new file mode 100644
index 0000000..48193de
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/shra_qb.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x12345678;
+    result = 0x02060A0F;
+
+    __asm
+        ("shra.qb %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    rt = 0x87654321;
+    result = 0xF00C0804;
+
+    __asm
+        ("shra.qb %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/shra_r_qb.c b/tests/tcg/mips/mips32-dspr2/shra_r_qb.c
new file mode 100644
index 0000000..29afa0e
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/shra_r_qb.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x12345678;
+    result = 0x02070B0F;
+
+    __asm
+        ("shra_r.qb %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    rt = 0x87654321;
+    result = 0xF10D0804;
+
+    __asm
+        ("shra_r.qb %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/shrav_qb.c b/tests/tcg/mips/mips32-dspr2/shrav_qb.c
new file mode 100644
index 0000000..b21e1b7
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/shrav_qb.c
@@ -0,0 +1,32 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x03;
+    rt = 0x12345678;
+    result = 0x02060A0F;
+
+    __asm
+        ("shrav.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    assert(rd == result);
+
+    rs = 0x03;
+    rt = 0x87654321;
+    result = 0xF00C0804;
+
+    __asm
+        ("shrav.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/shrav_r_qb.c b/tests/tcg/mips/mips32-dspr2/shrav_r_qb.c
new file mode 100644
index 0000000..9ea8aa0
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/shrav_r_qb.c
@@ -0,0 +1,32 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x03;
+    rt = 0x12345678;
+    result = 0x02070B0F;
+
+    __asm
+        ("shrav_r.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    assert(rd == result);
+
+    rs = 0x03;
+    rt = 0x87654321;
+    result = 0xF10D0804;
+
+    __asm
+        ("shrav_r.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/shrl_ph.c b/tests/tcg/mips/mips32-dspr2/shrl_ph.c
new file mode 100644
index 0000000..724b9a7
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/shrl_ph.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt     = 0x12345678;
+    result = 0x009102B3;
+
+    __asm
+        ("shrl.ph %0, %1, 0x05\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/shrlv_ph.c b/tests/tcg/mips/mips32-dspr2/shrlv_ph.c
new file mode 100644
index 0000000..ac79aa6
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/shrlv_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs     = 0x05;
+    rt     = 0x12345678;
+    result = 0x009102B3;
+
+    __asm
+        ("shrlv.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subqh_ph.c b/tests/tcg/mips/mips32-dspr2/subqh_ph.c
new file mode 100644
index 0000000..dbc0967
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subqh_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x456709AB;
+
+    __asm
+        ("subqh.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subqh_r_ph.c b/tests/tcg/mips/mips32-dspr2/subqh_r_ph.c
new file mode 100644
index 0000000..24ef0f1
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subqh_r_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x456809AC;
+
+    __asm
+        ("subqh_r.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subqh_r_w.c b/tests/tcg/mips/mips32-dspr2/subqh_r_w.c
new file mode 100644
index 0000000..d460f86
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subqh_r_w.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x456789AC;
+
+    __asm
+        ("subqh_r.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subqh_w.c b/tests/tcg/mips/mips32-dspr2/subqh_w.c
new file mode 100644
index 0000000..42be3de
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subqh_w.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x456789AB;
+
+    __asm
+        ("subqh.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subu_ph.c b/tests/tcg/mips/mips32-dspr2/subu_ph.c
new file mode 100644
index 0000000..b9cf138
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subu_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0x7531ECA9;
+    resultdsp = 0x01;
+
+    __asm
+        ("subu.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subu_s_ph.c b/tests/tcg/mips/mips32-dspr2/subu_s_ph.c
new file mode 100644
index 0000000..a3b034f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subu_s_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0x75310000;
+    resultdsp = 0x01;
+
+    __asm
+        ("subu_s.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subuh_qb.c b/tests/tcg/mips/mips32-dspr2/subuh_qb.c
new file mode 100644
index 0000000..92cfc76
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subuh_qb.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0xC5E7092B;
+
+    __asm
+        ("subuh.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subuh_r_qb.c b/tests/tcg/mips/mips32-dspr2/subuh_r_qb.c
new file mode 100644
index 0000000..d9e6f2f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subuh_r_qb.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt;
+    int result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0xC6E80A2C;
+
+    __asm
+        ("subuh_r.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    assert(rd == result);
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/Makefile b/tests/tcg/mips/mips64-dsp/Makefile
new file mode 100644
index 0000000..ef8a87f
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/Makefile
@@ -0,0 +1,304 @@
+
+CROSS_COMPILE	?= mips64el-unknown-linux-gnu-
+
+SIM = qemu-system-mips64el
+SIMFLAGS = -nographic -cpu mips64dspr2 -kernel
+
+AS      = $(CROSS_COMPILE)as
+LD      = $(CROSS_COMPILE)ld
+CC      = $(CROSS_COMPILE)gcc
+AR      = $(CROSS_COMPILE)ar
+NM      = $(CROSS_COMPILE)nm
+STRIP       = $(CROSS_COMPILE)strip
+RANLIB      = $(CROSS_COMPILE)ranlib
+OBJCOPY     = $(CROSS_COMPILE)objcopy
+OBJDUMP     = $(CROSS_COMPILE)objdump
+
+VECTORS_OBJ ?= ./head.o ./printf.o
+
+HEAD_FLAGS ?= -nostdinc -mabi=64 -G 0 -mno-abicalls -fno-pic -pipe \
+              -msoft-float -march=mips64 -Wa,-mips64 -Wa,--trap \
+              -msym32 -DKBUILD_64BIT_SYM32 -I./
+
+CFLAGS ?= -nostdinc -mabi=64 -G 0 -mno-abicalls -fno-pic -fno-builtin  \
+          -pipe -march=mips64r2 -mgp64 -mdsp -static -Wa,--trap -msym32 \
+          -DKBUILD_64BIT_SYM32 -I./
+
+LDFLAGS = -T./mips_boot.lds -L./
+FLAGS = -nostdlib -mabi=64 -march=mips64r2 -mgp64 -mdsp
+
+
+#TESTCASES = absq_s_ob.tst
+TESTCASES = absq_s_ph.tst
+TESTCASES += absq_s_pw.tst
+TESTCASES += absq_s_qh.tst
+TESTCASES += absq_s_w.tst
+TESTCASES += addq_ph.tst
+TESTCASES += addq_pw.tst
+TESTCASES += addq_qh.tst
+TESTCASES += addq_s_ph.tst
+TESTCASES += addq_s_pw.tst
+TESTCASES += addq_s_qh.tst
+TESTCASES += addsc.tst
+TESTCASES += addu_ob.tst
+TESTCASES += addu_qb.tst
+TESTCASES += addu_s_ob.tst
+TESTCASES += addu_s_qb.tst
+TESTCASES += addwc.tst
+TESTCASES += bitrev.tst
+TESTCASES += bposge32.tst
+TESTCASES += bposge64.tst
+TESTCASES += cmp_eq_ph.tst
+TESTCASES += cmp_eq_pw.tst
+TESTCASES += cmp_eq_qh.tst
+TESTCASES += cmpgu_eq_ob.tst
+TESTCASES += cmpgu_eq_qb.tst
+TESTCASES += cmpgu_le_ob.tst
+TESTCASES += cmpgu_le_qb.tst
+TESTCASES += cmpgu_lt_ob.tst
+TESTCASES += cmpgu_lt_qb.tst
+TESTCASES += cmp_le_ph.tst
+TESTCASES += cmp_le_pw.tst
+TESTCASES += cmp_le_qh.tst
+TESTCASES += cmp_lt_ph.tst
+TESTCASES += cmp_lt_pw.tst
+TESTCASES += cmp_lt_qh.tst
+TESTCASES += cmpu_eq_ob.tst
+TESTCASES += cmpu_eq_qb.tst
+TESTCASES += cmpu_le_ob.tst
+TESTCASES += cmpu_le_qb.tst
+TESTCASES += cmpu_lt_ob.tst
+TESTCASES += cmpu_lt_qb.tst
+#TESTCASES += dappend.tst
+TESTCASES += dextp.tst
+TESTCASES += dextpdp.tst
+TESTCASES += dextpdpv.tst
+TESTCASES += dextpv.tst
+TESTCASES += dextr_l.tst
+TESTCASES += dextr_r_l.tst
+TESTCASES += dextr_rs_l.tst
+TESTCASES += dextr_rs_w.tst
+TESTCASES += dextr_r_w.tst
+TESTCASES += dextr_s_h.tst
+TESTCASES += dextrv_l.tst
+TESTCASES += dextrv_r_l.tst
+TESTCASES += dextrv_rs_l.tst
+TESTCASES += dextrv_rs_w.tst
+TESTCASES += dextrv_r_w.tst
+TESTCASES += dextrv_s_h.tst
+TESTCASES += dextrv_w.tst
+TESTCASES += dextr_w.tst
+TESTCASES += dinsv.tst
+TESTCASES += dmadd.tst
+TESTCASES += dmaddu.tst
+TESTCASES += dmsub.tst
+TESTCASES += dmsubu.tst
+TESTCASES += dmthlip.tst
+TESTCASES += dpaq_sa_l_pw.tst
+TESTCASES += dpaq_sa_l_w.tst
+TESTCASES += dpaq_s_w_ph.tst
+TESTCASES += dpaq_s_w_qh.tst
+TESTCASES += dpau_h_obl.tst
+TESTCASES += dpau_h_obr.tst
+TESTCASES += dpau_h_qbl.tst
+TESTCASES += dpau_h_qbr.tst
+TESTCASES += dpsq_sa_l_pw.tst
+TESTCASES += dpsq_sa_l_w.tst
+TESTCASES += dpsq_s_w_ph.tst
+TESTCASES += dpsq_s_w_qh.tst
+TESTCASES += dpsu_h_obl.tst
+TESTCASES += dpsu_h_obr.tst
+TESTCASES += dpsu_h_qbl.tst
+TESTCASES += dpsu_h_qbr.tst
+TESTCASES += dshilo.tst
+TESTCASES += dshilov.tst
+TESTCASES += extp.tst
+TESTCASES += extpdp.tst
+TESTCASES += extpdpv.tst
+TESTCASES += extpv.tst
+TESTCASES += extr_rs_w.tst
+TESTCASES += extr_r_w.tst
+TESTCASES += extr_s_h.tst
+TESTCASES += extrv_rs_w.tst
+TESTCASES += extrv_r_w.tst
+TESTCASES += extrv_s_h.tst
+TESTCASES += extrv_w.tst
+TESTCASES += extr_w.tst
+TESTCASES += insv.tst
+TESTCASES += lbux.tst
+TESTCASES += lhx.tst
+TESTCASES += lwx.tst
+TESTCASES += ldx.tst
+TESTCASES += madd.tst
+TESTCASES += maddu.tst
+TESTCASES += maq_sa_w_phl.tst
+TESTCASES += maq_sa_w_phr.tst
+TESTCASES += maq_sa_w_qhll.tst
+TESTCASES += maq_sa_w_qhlr.tst
+TESTCASES += maq_sa_w_qhrl.tst
+TESTCASES += maq_sa_w_qhrr.tst
+TESTCASES += maq_s_l_pwl.tst
+TESTCASES += maq_s_l_pwr.tst
+TESTCASES += maq_s_w_phl.tst
+TESTCASES += maq_s_w_phr.tst
+TESTCASES += maq_s_w_qhll.tst
+TESTCASES += maq_s_w_qhlr.tst
+TESTCASES += maq_s_w_qhrl.tst
+TESTCASES += maq_s_w_qhrr.tst
+TESTCASES += mfhi.tst
+TESTCASES += mflo.tst
+TESTCASES += modsub.tst
+TESTCASES += msub.tst
+TESTCASES += msubu.tst
+TESTCASES += mthi.tst
+TESTCASES += mthlip.tst
+TESTCASES += mtlo.tst
+TESTCASES += muleq_s_pw_qhl.tst
+TESTCASES += muleq_s_pw_qhr.tst
+TESTCASES += muleq_s_w_phr.tst
+TESTCASES += muleu_s_ph_qbl.tst
+TESTCASES += muleu_s_ph_qbr.tst
+TESTCASES += muleu_s_qh_obl.tst
+TESTCASES += muleu_s_qh_obr.tst
+TESTCASES += mulq_rs_ph.tst
+TESTCASES += mulq_rs_qh.tst
+TESTCASES += mulsaq_s_l_pw.tst
+TESTCASES += mulsaq_s_w_qh.tst
+TESTCASES += mult.tst
+TESTCASES += multu.tst
+TESTCASES += packrl_ph.tst
+TESTCASES += packrl_pw.tst
+TESTCASES += pick_ob.tst
+TESTCASES += pick_ph.tst
+TESTCASES += pick_pw.tst
+TESTCASES += pick_qb.tst
+TESTCASES += pick_qh.tst
+#TESTCASES += preceq_l_pwl.tst
+#TESTCASES += preceq_l_pwr.tst
+TESTCASES += preceq_pw_qhla.tst
+TESTCASES += preceq_pw_qhl.tst
+TESTCASES += preceq_pw_qhra.tst
+TESTCASES += preceq_pw_qhr.tst
+TESTCASES += precequ_ph_qbla.tst
+TESTCASES += precequ_ph_qbl.tst
+TESTCASES += precequ_ph_qbra.tst
+TESTCASES += precequ_ph_qbr.tst
+#TESTCASES += precequ_qh_obla.tst
+#TESTCASES += precequ_qh_obl.tst
+#TESTCASES += precequ_qh_obra.tst
+#TESTCASES += precequ_qh_obr.tst
+TESTCASES += preceq_w_phl.tst
+TESTCASES += preceq_w_phr.tst
+TESTCASES += preceu_ph_qbla.tst
+TESTCASES += preceu_ph_qbl.tst
+TESTCASES += preceu_ph_qbra.tst
+TESTCASES += preceu_ph_qbr.tst
+TESTCASES += preceu_qh_obla.tst
+TESTCASES += preceu_qh_obl.tst
+TESTCASES += preceu_qh_obra.tst
+TESTCASES += preceu_qh_obr.tst
+#TESTCASES += precr_ob_qh.tst
+TESTCASES += precrq_ob_qh.tst
+TESTCASES += precrq_ph_w.tst
+TESTCASES += precrq_pw_l.tst
+TESTCASES += precrq_qb_ph.tst
+TESTCASES += precrq_qh_pw.tst
+TESTCASES += precrq_rs_ph_w.tst
+TESTCASES += precrq_rs_qh_pw.tst
+TESTCASES += precrqu_s_ob_qh.tst
+TESTCASES += precrqu_s_qb_ph.tst
+#TESTCASES += precr_sra_qh_pw.tst
+#TESTCASES += precr_sra_r_qh_pw.tst
+#TESTCASES += prependd.tst
+#TESTCASES += prependw.tst
+#TESTCASES += raddu_l_ob.tst
+TESTCASES += raddu_w_qb.tst
+TESTCASES += rddsp.tst
+TESTCASES += repl_ob.tst
+TESTCASES += repl_ph.tst
+TESTCASES += repl_pw.tst
+TESTCASES += repl_qb.tst
+TESTCASES += repl_qh.tst
+TESTCASES += replv_ob.tst
+TESTCASES += replv_ph.tst
+TESTCASES += replv_pw.tst
+TESTCASES += replv_qb.tst
+TESTCASES += shilo.tst
+TESTCASES += shilov.tst
+TESTCASES += shll_ob.tst
+TESTCASES += shll_ph.tst
+TESTCASES += shll_pw.tst
+TESTCASES += shll_qb.tst
+TESTCASES += shll_qh.tst
+TESTCASES += shll_s_ph.tst
+TESTCASES += shll_s_pw.tst
+TESTCASES += shll_s_qh.tst
+TESTCASES += shll_s_w.tst
+TESTCASES += shllv_ob.tst
+TESTCASES += shllv_ph.tst
+TESTCASES += shllv_pw.tst
+TESTCASES += shllv_qb.tst
+TESTCASES += shllv_qh.tst
+TESTCASES += shllv_s_ph.tst
+TESTCASES += shllv_s_pw.tst
+TESTCASES += shllv_s_qh.tst
+TESTCASES += shllv_s_w.tst
+#TESTCASES += shra_ob.tst
+TESTCASES += shra_ph.tst
+TESTCASES += shra_pw.tst
+TESTCASES += shra_qh.tst
+#TESTCASES += shra_r_ob.tst
+TESTCASES += shra_r_ph.tst
+TESTCASES += shra_r_pw.tst
+TESTCASES += shra_r_qh.tst
+TESTCASES += shra_r_w.tst
+TESTCASES += shrav_ph.tst
+TESTCASES += shrav_pw.tst
+TESTCASES += shrav_qh.tst
+TESTCASES += shrav_r_ph.tst
+TESTCASES += shrav_r_pw.tst
+TESTCASES += shrav_r_qh.tst
+TESTCASES += shrav_r_w.tst
+TESTCASES += shrl_ob.tst
+TESTCASES += shrl_qb.tst
+#TESTCASES += shrl_qh.tst
+TESTCASES += shrlv_ob.tst
+TESTCASES += shrlv_qb.tst
+#TESTCASES += shrlv_qh.tst
+TESTCASES += subq_ph.tst
+TESTCASES += subq_pw.tst
+TESTCASES += subq_qh.tst
+TESTCASES += subq_s_ph.tst
+TESTCASES += subq_s_pw.tst
+TESTCASES += subq_s_qh.tst
+TESTCASES += subq_s_w.tst
+TESTCASES += subu_ob.tst
+TESTCASES += subu_qb.tst
+TESTCASES += subu_s_ob.tst
+TESTCASES += subu_s_qb.tst
+TESTCASES += wrdsp.tst
+
+all: build
+
+head.o : head.S
+	$(Q)$(CC) $(HEAD_FLAGS) -D"STACK_TOP=0xffffffff80200000" -c $< -o $@
+
+%.o  : %.S
+	$(CC) $(CFLAGS) -c $< -o $@
+
+%.o  : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
+%.tst: %.o $(VECTORS_OBJ)
+	$(CC) $(VECTORS_OBJ) $(FLAGS) $(LDFLAGS) $< -o $@
+
+build: $(VECTORS_OBJ) $(MIPSSOC_LIB) $(TESTCASES)
+
+check:  $(VECTORS_OBJ) $(MIPSSOC_LIB) $(TESTCASES)
+	@for case in $(TESTCASES); do \
+		echo $(SIM) $(SIMFLAGS) ./$$case; \
+		$(SIM) $(SIMFLAGS) ./$$case & (sleep 1; killall $(SIM)); \
+	done
+
+clean:
+	$(Q)rm -f *.o *.tst *.a
diff --git a/tests/tcg/mips/mips64-dsp/absq_s_ob.c b/tests/tcg/mips/mips64-dsp/absq_s_ob.c
new file mode 100644
index 0000000..6214031
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/absq_s_ob.c
@@ -0,0 +1,63 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result, dspcontrol;
+    rt = 0x7F7F7F7F7F7F7F7F;
+    result = 0x7F7F7F7F7F7F7F7F;
+
+
+    __asm
+        (".set mips64\n\t"
+         "absq_s.ob %0 %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("absq_s.ob test 1 error\n");
+
+        return -1;
+    }
+
+    __asm
+        ("rddsp %0\n\t"
+         : "=r"(rd)
+        );
+    rd >> 20;
+    rd = rd & 0x1;
+    if (rd != 0) {
+        printf("absq_s.ob test 1 dspcontrol overflow flag error\n");
+
+        return -1;
+    }
+
+    rt = 0x80FFFFFFFFFFFFFF;
+    result = 0x7F01010101010101;
+
+    __asm
+        ("absq_s.ob %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("absq_s.ob test 2 error\n");
+
+        return -1;
+    }
+
+    __asm
+        ("rddsp %0\n\t"
+         : "=r"(rd)
+        );
+    rd = rd >> 20;
+    rd = rd & 0x1;
+    if (rd != 1) {
+        printf("absq_s.ob test 2 dspcontrol overflow flag error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/tests/tcg/mips/mips64-dsp/absq_s_ph.c b/tests/tcg/mips/mips64-dsp/absq_s_ph.c
new file mode 100644
index 0000000..238416d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/absq_s_ph.c
@@ -0,0 +1,37 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt     = 0x10017EFD;
+    result = 0x10017EFD;
+
+    __asm
+        ("absq_s.ph %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("absq_s.ph wrong\n");
+
+        return -1;
+    }
+
+    rt     = 0x8000A536;
+    result = 0x7FFF5ACA;
+
+    __asm
+        ("absq_s.ph %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("absq_s.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/absq_s_pw.c b/tests/tcg/mips/mips64-dsp/absq_s_pw.c
new file mode 100644
index 0000000..48fc763
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/absq_s_pw.c
@@ -0,0 +1,66 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result, dspcontrol;
+    rd = 0;
+    rt = 0x7F7F7F7F7F7F7F7F;
+    result = 0x7F7F7F7F7F7F7F7F;
+
+
+    __asm
+        ("absq_s.pw %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("absq_s.pw test 1 error\n");
+
+        return -1;
+    }
+
+    rd = 0;
+    __asm
+        ("rddsp %0\n\t"
+         : "=r"(rd)
+        );
+    rd >> 20;
+    rd = rd & 0x1;
+    if (rd != 0) {
+        printf("absq_s.pw test 1 dspcontrol overflow flag error\n");
+
+        return -1;
+    }
+
+    rd = 0;
+    rt = 0x80000000FFFFFFFF;
+    result = 0x7FFFFFFF00000001;
+
+    __asm
+        ("absq_s.pw %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("absq_s.pw test 2 error\n");
+
+        return -1;
+    }
+
+    rd = 0;
+    __asm
+        ("rddsp %0\n\t"
+         : "=r"(rd)
+        );
+    rd = rd >> 20;
+    rd = rd & 0x1;
+    if (rd != 1) {
+        printf("absq_s.pw test 2 dspcontrol overflow flag error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/tests/tcg/mips/mips64-dsp/absq_s_qh.c b/tests/tcg/mips/mips64-dsp/absq_s_qh.c
new file mode 100644
index 0000000..9001a9e
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/absq_s_qh.c
@@ -0,0 +1,40 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result, dspcontrol;
+    rd = 0;
+    rt = 0x7F7F7F7F7F7F7F7F;
+    result = 0x7F7F7F7F7F7F7F7F;
+
+
+    __asm
+        ("absq_s.qh %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("absq_s.qh test 1 error\n");
+
+        return -1;
+    }
+
+    rd = 0;
+    rt = 0x8000FFFFFFFFFFFF;
+    result = 0x7FFF000100000001;
+
+    __asm
+        ("absq_s.pw %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("absq_s.rw test 2 error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/tests/tcg/mips/mips64-dsp/absq_s_w.c b/tests/tcg/mips/mips64-dsp/absq_s_w.c
new file mode 100644
index 0000000..414c8bd
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/absq_s_w.c
@@ -0,0 +1,48 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt     = 0x80000000;
+    result = 0x7FFFFFFF;
+    __asm
+        ("absq_s.w %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("absq_s_w.ph wrong\n");
+
+        return -1;
+    }
+
+    rt     = 0x80030000;
+    result = 0x7FFD0000;
+    __asm
+        ("absq_s.w %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("absq_s_w.ph wrong\n");
+
+        return -1;
+    }
+
+    rt     = 0x31036080;
+    result = 0x31036080;
+    __asm
+        ("absq_s.w %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("absq_s_w.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/addq_ph.c b/tests/tcg/mips/mips64-dsp/addq_ph.c
new file mode 100644
index 0000000..212d3d9
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/addq_ph.c
@@ -0,0 +1,37 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0xFFFFFFFF;
+    rt     = 0x10101010;
+    result = 0x100F100F;
+    __asm
+        ("addq.ph   %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addq.ph wrong\n");
+
+        return -1;
+    }
+
+    rs     = 0x3712847D;
+    rt     = 0x0031AF2D;
+    result = 0x374333AA;
+    __asm
+        ("addq.ph   %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addq.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/addq_pw.c b/tests/tcg/mips/mips64-dsp/addq_pw.c
new file mode 100644
index 0000000..e170256
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/addq_pw.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+    rs = 0x123456787FFFFFFF;
+    rt = 0x1111111100000001;
+    result = 0x2345678980000000;
+    dspresult = 0x1;
+
+    __asm
+        ("addq.pw %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("addq.pw error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/addq_qh.c b/tests/tcg/mips/mips64-dsp/addq_qh.c
new file mode 100644
index 0000000..415f743
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/addq_qh.c
@@ -0,0 +1,28 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+
+    rs = 0x123456787FFF0000;
+    rt = 0x1111111100010000;
+    result = 0x2345678980000000;
+    dspresult = 0x1;
+
+    __asm
+        ("addq.qh %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("addq.qh error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/addq_s_ph.c b/tests/tcg/mips/mips64-dsp/addq_s_ph.c
new file mode 100644
index 0000000..5cc94c4
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/addq_s_ph.c
@@ -0,0 +1,37 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0xFFFFFFFF;
+    rt     = 0x10101010;
+    result = 0x100F100F;
+    __asm
+        ("addq_s.ph   %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addq_s.ph wrong\n");
+
+        return -1;
+    }
+
+    rs     = 0x3712847D;
+    rt     = 0x0031AF2D;
+    result = 0x37438000;
+    __asm
+        ("addq_s.ph   %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addq_s.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/addq_s_pw.c b/tests/tcg/mips/mips64-dsp/addq_s_pw.c
new file mode 100644
index 0000000..6cd2314
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/addq_s_pw.c
@@ -0,0 +1,45 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+    rs = 0x123456787FFFFFFF;
+    rt = 0x1111111100000001;
+    result = 0x234567897FFFFFFF;
+    dspresult = 0x1;
+
+    __asm
+        ("addq_s.pw %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("addq_s.pw error\n");
+
+        return -1;
+    }
+
+    rs = 0x7FFFFFFFE00000FF;
+    rt = 0x00000001200000DD;
+    result = 0x7FFFFFFF000001DC;
+    dspresult = 0x01;
+
+    __asm
+        ("addq_s.pw %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("addq_s.pw error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/addq_s_qh.c b/tests/tcg/mips/mips64-dsp/addq_s_qh.c
new file mode 100644
index 0000000..3057ce6
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/addq_s_qh.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+    rs = 0x123456787FFF0000;
+    rt = 0x1111111100020000;
+    result = 0x234567897FFF0000;
+    dspresult = 0x1;
+
+    __asm
+        ("addq_s.qh %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("addq_s.qh error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/addsc.c b/tests/tcg/mips/mips64-dsp/addsc.c
new file mode 100644
index 0000000..c753376
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/addsc.c
@@ -0,0 +1,37 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x0000000F;
+    rt     = 0x00000001;
+    result = 0x00000010;
+    __asm
+        ("addsc %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addsc wrong\n");
+
+        return -1;
+    }
+
+    rs     = 0xFFFF0FFF;
+    rt     = 0x00010111;
+    result = 0x00001110;
+    __asm
+        ("addsc %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addsc wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/addu_ob.c b/tests/tcg/mips/mips64-dsp/addu_ob.c
new file mode 100644
index 0000000..1069e68
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/addu_ob.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+    rs = 0x123456789ABCDEF0;
+    rt = 0x3456123498DEF390;
+    result = 0x468A68AC329AD180;
+    dspresult = 0x01;
+
+    __asm
+        ("addu.ob %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("addu.ob error\n\t");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/addu_qb.c b/tests/tcg/mips/mips64-dsp/addu_qb.c
new file mode 100644
index 0000000..a5ecdcd
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/addu_qb.c
@@ -0,0 +1,37 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x00FF00FF;
+    rt     = 0x00010001;
+    result = 0x00000000;
+    __asm
+        ("addu.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addu.qb wrong\n");
+
+        return -1;
+    }
+
+    rs     = 0xFFFF1111;
+    rt     = 0x00020001;
+    result = 0xFFFFFFFFFF011112;
+    __asm
+        ("addu.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addu.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/addu_s_ob.c b/tests/tcg/mips/mips64-dsp/addu_s_ob.c
new file mode 100644
index 0000000..e89a463
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/addu_s_ob.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+    rs = 0x123456789ABCDEF0;
+    rt = 0x3456123498DEF390;
+    result = 0x468A68ACFFFFFFFF;
+    dspresult = 0x01;
+
+    __asm
+        ("addu_s.ob %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("addu_s.ob error\n\t");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/addu_s_qb.c b/tests/tcg/mips/mips64-dsp/addu_s_qb.c
new file mode 100644
index 0000000..7a09965
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/addu_s_qb.c
@@ -0,0 +1,38 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x10FF01FF;
+    rt     = 0x10010001;
+    result = 0x20FF01FF;
+    __asm
+        ("addu_s.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addu_s.qb error 1\n");
+
+        return -1;
+    }
+
+    rs     = 0xFFFFFFFFFFFF1111;
+    rt     = 0x00020001;
+    result = 0xFFFFFFFFFFFF1112;
+    __asm
+        ("addu_s.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addu_s.qb error 2\n");
+
+        return -1;
+    }
+
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/addwc.c b/tests/tcg/mips/mips64-dsp/addwc.c
new file mode 100644
index 0000000..fb3ef11
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/addwc.c
@@ -0,0 +1,37 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x10FF01FF;
+    rt     = 0x10010001;
+    result = 0x21000200;
+    __asm
+        ("addwc %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addwc wrong\n");
+
+        return -1;
+    }
+
+    rs     = 0xFFFF1111;
+    rt     = 0x00020001;
+    result = 0x00011112;
+    __asm
+        ("addwc %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addwc wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/bitrev.c b/tests/tcg/mips/mips64-dsp/bitrev.c
new file mode 100644
index 0000000..ac24ef3
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/bitrev.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt     = 0x12345678;
+    result = 0x00001E6A;
+
+    __asm
+        ("bitrev %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("bitrev wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/bposge32.c b/tests/tcg/mips/mips64-dsp/bposge32.c
new file mode 100644
index 0000000..97bce44
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/bposge32.c
@@ -0,0 +1,50 @@
+#include "io.h"
+
+int main(void)
+{
+    long long dsp, sum;
+    long long result;
+
+    dsp =  0x20;
+    sum = 0x01;
+    result = 0x02;
+
+    __asm
+        ("wrdsp %1\n\t"
+         "bposge32 test1\n\t"
+         "nop\n\t"
+         "addi %0, 0xA2\n\t"
+         "nop\n\t"
+         "test1:\n\t"
+         "addi %0, 0x01\n\t"
+         : "+r"(sum)
+         : "r"(dsp)
+        );
+    if (sum != result) {
+        printf("bposge32 wrong\n");
+
+        return -1;
+    }
+
+    dsp =  0x10;
+    sum = 0x01;
+    result = 0xA4;
+
+    __asm
+        ("wrdsp %1\n\t"
+         "bposge32 test2\n\t"
+         "nop\n\t"
+         "addi %0, 0xA2\n\t"
+         "nop\n\t"
+         "test2:\n\t"
+         "addi %0, 0x01\n\t"
+         : "+r"(sum)
+         : "r"(dsp)
+        );
+    if (sum != result) {
+        printf("bposge32 wrong\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/bposge64.c b/tests/tcg/mips/mips64-dsp/bposge64.c
new file mode 100644
index 0000000..961fb61
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/bposge64.c
@@ -0,0 +1,50 @@
+#include "io.h"
+
+int main(void)
+{
+    long long dsp, sum;
+    long long result;
+
+    dsp =  0x40;
+    sum = 0x01;
+    result = 0x02;
+
+    __asm
+        ("wrdsp %1\n\t"
+         "bposge32 test1\n\t"
+         "nop\n\t"
+         "addi %0, 0xA2\n\t"
+         "nop\n\t"
+         "test1:\n\t"
+         "addi %0, 0x01\n\t"
+         : "+r"(sum)
+         : "r"(dsp)
+        );
+    if (sum != result) {
+        printf("bposge32 wrong\n");
+
+        return -1;
+    }
+
+    dsp =  0x10;
+    sum = 0x01;
+    result = 0xA4;
+
+    __asm
+        ("wrdsp %1\n\t"
+         "bposge32 test2\n\t"
+         "nop\n\t"
+         "addi %0, 0xA2\n\t"
+         "nop\n\t"
+         "test2:\n\t"
+         "addi %0, 0x01\n\t"
+         : "+r"(sum)
+         : "r"(dsp)
+        );
+    if (sum != result) {
+        printf("bposge32 wrong\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmp_eq_ph.c b/tests/tcg/mips/mips64-dsp/cmp_eq_ph.c
new file mode 100644
index 0000000..63069d0
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmp_eq_ph.c
@@ -0,0 +1,42 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x11777066;
+    rt     = 0x55AA33FF;
+    result = 0x00;
+    __asm
+        ("cmp.eq.ph %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    rd = (rd >> 24) & 0x03;
+    if (rd != result) {
+        printf("cmp.eq.ph wrong\n");
+
+        return -1;
+    }
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x03;
+    __asm
+        ("cmp.eq.ph %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    rd = (rd >> 24) & 0x03;
+    if (rd != result) {
+        printf("cmp.eq.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmp_eq_pw.c b/tests/tcg/mips/mips64-dsp/cmp_eq_pw.c
new file mode 100644
index 0000000..46e3417
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmp_eq_pw.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+  long long rs, rt, dspreg, dspresult;
+
+  rs = 0x123456789ABCDEF0;
+  rt = 0x123456789ABCDEFF;
+  dspresult = 0x02;
+
+  __asm
+      ("cmp.eq.pw %1, %2\n\t"
+       "rddsp %0\n\t"
+       : "=r"(dspreg)
+       : "r"(rs), "r"(rt)
+      );
+
+  dspreg = ((dspreg >> 24) & 0x03);
+
+  if (dspreg != dspresult) {
+    printf("cmp.eq.pw error\n");
+
+    return -1;
+  }
+
+  return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmp_eq_qh.c b/tests/tcg/mips/mips64-dsp/cmp_eq_qh.c
new file mode 100644
index 0000000..7b5381c
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmp_eq_qh.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+  long long rs, rt, dspreg, dspresult;
+
+  rs = 0x123456789ABCDEF0;
+  rt = 0x123456789ABCDEFF;
+  dspresult = 0x0E;
+
+  __asm
+      ("cmp.eq.qh %1, %2\n\t"
+        "rddsp %0\n\t"
+        : "=r"(dspreg)
+        : "r"(rs), "r"(rt)
+       );
+
+  dspreg = ((dspreg >> 24) & 0x0F);
+
+  if (dspreg != dspresult) {
+    printf("cmp.eq.qh error\n");
+
+    return -1;
+  }
+
+  return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmp_le_ph.c b/tests/tcg/mips/mips64-dsp/cmp_le_ph.c
new file mode 100644
index 0000000..12d24f1
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmp_le_ph.c
@@ -0,0 +1,40 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x11777066;
+    rt     = 0x55AA33FF;
+    result = 0x02;
+    __asm
+        ("cmp.le.ph %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    rd = (rd >> 24) & 0x03;
+    if (rd != result) {
+        printf("cmp.le.ph wrong\n");
+
+        return -1;
+    }
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x03;
+    __asm
+        ("cmp.le.ph %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    rd = (rd >> 24) & 0x03;
+    if (rd != result) {
+        printf("cmp.le.ph wrong\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmp_le_pw.c b/tests/tcg/mips/mips64-dsp/cmp_le_pw.c
new file mode 100644
index 0000000..51bdec4
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmp_le_pw.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, dspreg, dspresult;
+
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEFF;
+    dspresult = 0x03;
+
+    __asm
+        ("cmp.le.pw %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = ((dspreg >> 24) & 0x03);
+
+    if (dspreg != dspresult) {
+        printf("cmp.le.pw error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmp_le_qh.c b/tests/tcg/mips/mips64-dsp/cmp_le_qh.c
new file mode 100644
index 0000000..0dff2b1
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmp_le_qh.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, dspreg, dspresult;
+
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEFF;
+    dspresult = 0x0F;
+
+    __asm
+        ("cmp.le.qh %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = ((dspreg >> 24) & 0x0F);
+
+    if (dspreg != dspresult) {
+        printf("cmp.le.qh error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmp_lt_ph.c b/tests/tcg/mips/mips64-dsp/cmp_lt_ph.c
new file mode 100644
index 0000000..1d91228
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmp_lt_ph.c
@@ -0,0 +1,41 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x11777066;
+    rt     = 0x55AA33FF;
+    result = 0x02;
+    __asm
+        ("cmp.lt.ph %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    rd = (rd >> 24) & 0x03;
+    if (rd != result) {
+        printf("cmp.lt.ph wrong\n");
+
+        return -1;
+    }
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x00;
+    __asm
+        ("cmp.lt.ph %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    rd = (rd >> 24) & 0x03;
+    if (rd != result) {
+        printf("cmp.lt.ph2 wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmp_lt_pw.c b/tests/tcg/mips/mips64-dsp/cmp_lt_pw.c
new file mode 100644
index 0000000..9c7f8a2
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmp_lt_pw.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, dspreg, dspresult;
+
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEFF;
+    dspresult = 0x01;
+
+    __asm
+        ("cmp.lt.pw %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = ((dspreg >> 24) & 0x03);
+
+    if (dspreg != dspresult) {
+        printf("cmp.lt.pw error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmp_lt_qh.c b/tests/tcg/mips/mips64-dsp/cmp_lt_qh.c
new file mode 100644
index 0000000..56fee15
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmp_lt_qh.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, dspreg, dspresult;
+
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEFF;
+    dspresult = 0x01;
+
+    __asm
+        ("cmp.lt.qh %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = ((dspreg >> 24) & 0x0F);
+
+    if (dspreg != dspresult) {
+        printf("cmp.lt.qh error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c b/tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c
new file mode 100644
index 0000000..2232073
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result;
+
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEFF;
+    result = 0xFE;
+
+    __asm
+        ("cmpgu.eq.ob %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != result) {
+        printf("cmpgu.eq.ob error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c b/tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c
new file mode 100644
index 0000000..b41c443
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c
@@ -0,0 +1,38 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x11777066;
+    rt     = 0x55AA70FF;
+    result = 0x02;
+    __asm
+        ("cmpgu.eq.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != result) {
+        printf("cmpgu.eq.ph wrong\n");
+
+        return -1;
+    }
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x0F;
+    __asm
+        ("cmpgu.eq.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("cmpgu.eq.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c b/tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c
new file mode 100644
index 0000000..f28dceb
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result;
+
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEFF;
+    result = 0xFF;
+
+    __asm
+        ("cmpgu.le.ob %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != result) {
+        printf("cmpgu.le.ob error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c b/tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c
new file mode 100644
index 0000000..dd2b091
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c
@@ -0,0 +1,37 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x11777066;
+    rt     = 0x55AA70FF;
+    result = 0x0F;
+    __asm
+        ("cmpgu.le.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("cmpgu.le.qb wrong\n");
+
+        return -1;
+    }
+
+    rs     = 0x11777066;
+    rt     = 0x11766066;
+    result = 0x09;
+    __asm
+        ("cmpgu.le.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("cmpgu.le.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c b/tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c
new file mode 100644
index 0000000..aa335ac
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result;
+
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEFF;
+    result = 0x01;
+
+    __asm
+        ("cmpgu.lt.ob %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != result) {
+        printf("cmpgu.lt.ob error\n");
+
+        return -1;
+    }
+
+   return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c b/tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c
new file mode 100644
index 0000000..a467cb7
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c
@@ -0,0 +1,38 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x11777066;
+    rt     = 0x55AA70FF;
+    result = 0x0D;
+    __asm
+        ("cmpgu.lt.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != result) {
+        printf("cmpgu.lt.qb wrong\n");
+
+        return -1;
+    }
+
+    rs     = 0x11777066;
+    rt     = 0x11766066;
+    result = 0x00;
+    __asm
+        ("cmpgu.lt.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("cmpgu.lt.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c b/tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c
new file mode 100644
index 0000000..a2b5681
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dspreg, dspresult;
+
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEFF;
+    dspresult = 0xFE;
+
+    __asm
+        ("cmpu.eq.ob %1, %2\n\t"
+         "rddsp %0"
+         : "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = ((dspreg >> 24) & 0xFF);
+
+    if (dspreg != dspresult) {
+        printf("cmpu.eq.ob error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c b/tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c
new file mode 100644
index 0000000..28f3bec
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c
@@ -0,0 +1,42 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long dsp;
+    long long result;
+
+    rs         = 0x11777066;
+    rt         = 0x55AA70FF;
+    result     = 0x02;
+    __asm
+        ("cmpu.eq.qb %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    if (dsp != result) {
+        printf("cmpu.eq.qb wrong\n");
+
+        return -1;
+    }
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x0F;
+    __asm
+        ("cmpu.eq.qb %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    if (dsp != result) {
+        printf("cmpu.eq.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmpu_le_ob.c b/tests/tcg/mips/mips64-dsp/cmpu_le_ob.c
new file mode 100644
index 0000000..71845bc
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmpu_le_ob.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, dspreg, dspresult;
+
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEFF;
+    dspresult = 0xFF;
+
+    __asm
+        ("cmpu.le.ob %1, %2\n\t"
+         "rddsp %0"
+         : "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = dspreg >> 24;
+    if (dspreg != dspresult) {
+        printf("cmpu.le.ob error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmpu_le_qb.c b/tests/tcg/mips/mips64-dsp/cmpu_le_qb.c
new file mode 100644
index 0000000..8a17a08
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmpu_le_qb.c
@@ -0,0 +1,41 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long dsp;
+    long long result;
+
+    rs         = 0x11777066;
+    rt         = 0x55AA70FF;
+    result     = 0x0F;
+    __asm
+        ("cmpu.le.qb %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    if (dsp != result) {
+        printf("cmpu.le.qb wrong\n");
+
+        return -1;
+    }
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x0F;
+    __asm
+        ("cmpu.le.qb %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    if (dsp != result) {
+        printf("cmpu.le.qb wrong\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c b/tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c
new file mode 100644
index 0000000..832f6d3
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, dspreg, dspresult;
+
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEFF;
+    dspresult = 0x01;
+
+    __asm
+        ("cmpu.lt.ob %1, %2\n\t"
+         "rddsp %0"
+         : "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+
+    dspreg = dspreg >> 24;
+    if (dspreg != dspresult) {
+        printf("cmpu.lt.ob error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c b/tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c
new file mode 100644
index 0000000..adb75ee
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c
@@ -0,0 +1,42 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long dsp;
+    long long result;
+
+    rs         = 0x11777066;
+    rt         = 0x55AA70FF;
+    result     = 0x0D;
+    __asm
+        ("cmpu.lt.qb %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    if (dsp != result) {
+        printf("cmpu.lt.qb wrong\n");
+
+        return -1;
+    }
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x00;
+    __asm
+        ("cmpu.lt.qb %1, %2\n\t"
+         "rddsp %0\n\t"
+         : "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    if (dsp != result) {
+        printf("cmpu.lt.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dappend.c b/tests/tcg/mips/mips64-dsp/dappend.c
new file mode 100644
index 0000000..ba8e121
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dappend.c
@@ -0,0 +1,37 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long res;
+    rt = 0x1234567887654321;
+    rs = 0xabcd1234abcd8765;
+
+    res = 0x1234567887654321;
+    __asm
+        ("dappend %0, %1, 0x0\n\t"
+         : "=r"(rt)
+         : "r"(rs)
+        );
+
+    if (rt != res) {
+        printf("dappend error\n");
+        return -1;
+    }
+
+    rt = 0x1234567887654321;
+    rs = 0xabcd1234abcd8765;
+
+    res = 0x2345678876543215;
+    __asm
+        ("dappend %0, %1, 0x4\n\t"
+         : "=r"(rt)
+         : "r"(rs)
+        );
+
+    if (rt != res) {
+        printf("dappend error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextp.c b/tests/tcg/mips/mips64-dsp/dextp.c
new file mode 100644
index 0000000..794ad48
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextp.c
@@ -0,0 +1,33 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, dsp;
+    long long achi, acli;
+    long long res, resdsp;
+    int rs;
+    rs = 0xabcd1234;
+
+    achi = 0x12345678;
+    acli = 0x87654321;
+    res = 0xff;
+    resdsp = 0x0;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "wrdsp %4, 0x1\n\t"
+         "wrdsp %4\n\t"
+         "dextp %0, $ac1, 0x7\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs)
+        );
+    dsp = (dsp >> 14) & 0x1;
+    if ((dsp != resdsp) || (rt != res)) {
+        printf("dextp error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextpdp.c b/tests/tcg/mips/mips64-dsp/dextpdp.c
new file mode 100644
index 0000000..a0cb069
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextpdp.c
@@ -0,0 +1,37 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, dsp;
+    long long achi, acli;
+    long long res, resdsp, resdsppos;
+    int rs;
+    int tmp1, tmp2;
+    rs = 0xabcd1234;
+
+    achi = 0x12345678;
+    acli = 0x87654321;
+    res = 0xff;
+    resdsp = 0x0;
+    resdsppos = 0x2c;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "wrdsp %4, 0x1\n\t"
+         "wrdsp %4\n\t"
+         "dextpdp %0, $ac1, 0x7\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs)
+        );
+    tmp1 = (dsp >> 14) & 0x1;
+    tmp2 = dsp & 0x3f;
+
+    if ((tmp1 != resdsp) || (rt != res) || (tmp2 != resdsppos)) {
+        printf("dextpdp error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextpdpv.c b/tests/tcg/mips/mips64-dsp/dextpdpv.c
new file mode 100644
index 0000000..70b3ed8
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextpdpv.c
@@ -0,0 +1,38 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long res, resdsp, resdsppos;
+    int rsdsp;
+    int tmp1, tmp2;
+    rsdsp = 0xabcd1234;
+    rs = 0x7;
+    achi = 0x12345678;
+    acli = 0x87654321;
+    res = 0xff;
+    resdsp = 0x0;
+    resdsppos = 0x2c;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "wrdsp %4, 0x1\n\t"
+         "wrdsp %4\n\t"
+         "dextpdpv %0, $ac1, %5\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rsdsp), "r"(rs)
+        );
+
+    tmp1 = (dsp >> 14) & 0x1;
+    tmp2 = dsp & 0x3f;
+
+    if ((tmp1 != resdsp) || (rt != res) || (tmp2 != resdsppos)) {
+        printf("dextpdpv error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextpv.c b/tests/tcg/mips/mips64-dsp/dextpv.c
new file mode 100644
index 0000000..78b6aec
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextpv.c
@@ -0,0 +1,34 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long res, resdsp;
+    int rsdsp;
+    rsdsp = 0xabcd1234;
+    rs = 0x7;
+
+    achi = 0x12345678;
+    acli = 0x87654321;
+    res = 0xff;
+    resdsp = 0x0;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "wrdsp %4, 0x1\n\t"
+         "wrdsp %4\n\t"
+         "dextpv %0, $ac1, %5\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rsdsp), "r"(rs)
+        );
+    dsp = (dsp >> 14) & 0x1;
+    if ((dsp != resdsp) || (rt != res)) {
+        printf("dextpv error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextr_l.c b/tests/tcg/mips/mips64-dsp/dextr_l.c
new file mode 100644
index 0000000..f5590a1
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextr_l.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt;
+    long long achi, acli;
+    long long res;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+
+    res = 0x9080000000091a2b;
+
+    __asm
+        ("mthi %1, $ac1\n\t"
+         "mtlo %2, $ac1\n\t"
+         "dextr.l %0, $ac1, 0x8\n\t"
+         : "=r"(rt)
+         : "r"(achi), "r"(acli)
+        );
+    if (rt != res) {
+        printf("dextr.l error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextr_r_l.c b/tests/tcg/mips/mips64-dsp/dextr_r_l.c
new file mode 100644
index 0000000..2b59393
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextr_r_l.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, dsp;
+    long long achi, acli;
+    long long res, resdsp;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+
+    res = 0x9080000000091a2b;
+    resdsp = 0x01;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "dextr_r.l %0, $ac1, 0x8\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli)
+        );
+
+    dsp = (dsp >> 23) & 0x1;
+
+    if ((dsp != resdsp) || (rt != res)) {
+        printf("dextr_r.l error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextr_r_w.c b/tests/tcg/mips/mips64-dsp/dextr_r_w.c
new file mode 100644
index 0000000..125bd0b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextr_r_w.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, dsp;
+    long long achi, acli;
+    long long res, resdsp;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+
+    res = 0x091A2B;
+    resdsp = 0x01;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "dextr_r.w %0, $ac1, 0x8\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli)
+        );
+
+    dsp = (dsp >> 23) & 0x1;
+
+    if ((dsp != resdsp) || (rt != res)) {
+        printf("dextr_r.w error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextr_rs_l.c b/tests/tcg/mips/mips64-dsp/dextr_rs_l.c
new file mode 100644
index 0000000..fbe021d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextr_rs_l.c
@@ -0,0 +1,31 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, dsp;
+    long long achi, acli;
+    long long res, resdsp;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+
+    res = 0x8000000000000000;
+    resdsp = 0x1;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "dextr_rs.l %0, $ac1, 0x8\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli)
+        );
+    dsp = (dsp >> 23) & 0x1;
+
+    if ((dsp != resdsp) || (rt != res)) {
+        printf("dextr_rs.l error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextr_rs_w.c b/tests/tcg/mips/mips64-dsp/dextr_rs_w.c
new file mode 100644
index 0000000..c97e2e5
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextr_rs_w.c
@@ -0,0 +1,31 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, dsp;
+    long long achi, acli;
+    long long res, resdsp;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+
+    res = 0xffffffff80000000;
+    resdsp = 0x1;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "dextr_rs.w %0, $ac1, 0x8\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli)
+        );
+    dsp = (dsp >> 23) & 0x1;
+
+    if ((dsp != resdsp) || (rt != res)) {
+        printf("dextr_rs.w error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextr_s_h.c b/tests/tcg/mips/mips64-dsp/dextr_s_h.c
new file mode 100644
index 0000000..a664b73
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextr_s_h.c
@@ -0,0 +1,31 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, dsp;
+    long long achi, acli;
+    long long res, resdsp;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+
+    res = 0xffffffffffff8000;
+    resdsp = 0x1;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "dextr_s.h %0, $ac1, 0x8\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli)
+        );
+    dsp = (dsp >> 23) & 0x1;
+
+    if ((dsp != resdsp) || (rt != res)) {
+        printf("dextr_s.h error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextr_w.c b/tests/tcg/mips/mips64-dsp/dextr_w.c
new file mode 100644
index 0000000..7bd7d11
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextr_w.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt;
+    long long achi, acli;
+    long long res;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+
+    res = 0x091A2B;
+
+    __asm
+        ("mthi %1, $ac1\n\t"
+         "mtlo %2, $ac1\n\t"
+         "dextr.w %0, $ac1, 0x8\n\t"
+         : "=r"(rt)
+         : "r"(achi), "r"(acli)
+        );
+    if (rt != res) {
+        printf("dextr.w error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextrv_l.c b/tests/tcg/mips/mips64-dsp/dextrv_l.c
new file mode 100644
index 0000000..70b21a0
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextrv_l.c
@@ -0,0 +1,28 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long res;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+    rs = 0x8;
+
+    res = 0x9080000000091a2b;
+
+    __asm
+        ("mthi %1, $ac1\n\t"
+         "mtlo %2, $ac1\n\t"
+         "dextrv.l %0, $ac1, %3\n\t"
+         : "=r"(rt)
+         : "r"(achi), "r"(acli), "r"(rs)
+        );
+    if (rt != res) {
+        printf("dextrv.l error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextrv_r_l.c b/tests/tcg/mips/mips64-dsp/dextrv_r_l.c
new file mode 100644
index 0000000..a9b07fe
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextrv_r_l.c
@@ -0,0 +1,33 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, dsp, rs;
+    long long achi, acli;
+    long long res, resdsp;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+    rs = 0x8;
+
+    res = 0x9080000000091a2b;
+    resdsp = 0x01;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "dextrv_r.l %0, $ac1, %4\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs)
+        );
+
+    dsp = (dsp >> 23) & 0x1;
+
+    if ((dsp != resdsp) || (rt != res)) {
+        printf("dextrv_r.l error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextrv_r_w.c b/tests/tcg/mips/mips64-dsp/dextrv_r_w.c
new file mode 100644
index 0000000..ec3837f
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextrv_r_w.c
@@ -0,0 +1,33 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long res, resdsp;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+    rs = 0x8;
+
+    res = 0x091A2B;
+    resdsp = 0x01;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "dextrv_r.w %0, $ac1, %4\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs)
+        );
+
+    dsp = (dsp >> 23) & 0x1;
+
+    if ((dsp != resdsp) || (rt != res)) {
+        printf("dextrv_r.w error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextrv_rs_l.c b/tests/tcg/mips/mips64-dsp/dextrv_rs_l.c
new file mode 100644
index 0000000..6a2594f
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextrv_rs_l.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long res, resdsp;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+    rs = 0x8;
+
+    res = 0x8000000000000000;
+    resdsp = 0x1;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "dextrv_rs.l %0, $ac1, %4\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs)
+        );
+    dsp = (dsp >> 23) & 0x1;
+
+    if ((dsp != resdsp) || (rt != res)) {
+        printf("dextrv_rs.l error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextrv_rs_w.c b/tests/tcg/mips/mips64-dsp/dextrv_rs_w.c
new file mode 100644
index 0000000..9f8a9b3
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextrv_rs_w.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long res, resdsp;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+    rs = 0x8;
+
+    res = 0xffffffff80000000;
+    resdsp = 0x1;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "dextrv_rs.w %0, $ac1, %4\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs)
+        );
+    dsp = (dsp >> 23) & 0x1;
+
+    if ((dsp != resdsp) || (rt != res)) {
+        printf("dextrv_rs.w error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextrv_s_h.c b/tests/tcg/mips/mips64-dsp/dextrv_s_h.c
new file mode 100644
index 0000000..87d3aee
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextrv_s_h.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long res, resdsp;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+    rs = 0x8;
+
+    res = 0xffffffffffff8000;
+    resdsp = 0x1;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "dextrv_s.h %0, $ac1, %4\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs)
+        );
+    dsp = (dsp >> 23) & 0x1;
+
+    if ((dsp != resdsp) || (rt != res)) {
+        printf("dextrv_s.h error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dextrv_w.c b/tests/tcg/mips/mips64-dsp/dextrv_w.c
new file mode 100644
index 0000000..4db6ebd
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dextrv_w.c
@@ -0,0 +1,28 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long res;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+    rs = 0x8;
+
+    res = 0x091A2B;
+
+    __asm
+        ("mthi %1, $ac1\n\t"
+         "mtlo %2, $ac1\n\t"
+         "dextrv.w %0, $ac1, %3\n\t"
+         : "=r"(rt)
+         : "r"(achi), "r"(acli), "r"(rs)
+        );
+    if (rt != res) {
+        printf("dextrv.w error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dinsv.c b/tests/tcg/mips/mips64-dsp/dinsv.c
new file mode 100644
index 0000000..25152c0
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dinsv.c
@@ -0,0 +1,25 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, dsp;
+    long long res;
+
+    rs = 0x1234567887654321;
+    rt = 0x1234567812345678;
+    dsp = 0x2222;
+    res = 0x1234567812345678;
+    __asm
+        ("wrdsp  %1, 0x3\n\t"
+         "wrdsp %1\n\t"
+         "dinsv %0, %2\n\t"
+         : "+r"(rt)
+         : "r"(dsp), "r"(rs)
+        );
+
+    if (rt != res) {
+        printf("dinsv error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dmadd.c b/tests/tcg/mips/mips64-dsp/dmadd.c
new file mode 100644
index 0000000..fb22614
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dmadd.c
@@ -0,0 +1,57 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resh, resl;
+
+    achi = 0x1;
+    acli = 0x1;
+
+    rs = 0x0000000100000001;
+    rt = 0x0000000200000002;
+
+    resh = 0x1;
+    resl = 0x5;
+    __asm
+       ("mthi %2, $ac1 \t\n"
+        "mtlo %3, $ac1 \t\n"
+        "dmadd $ac1, %4, %5\t\n"
+        "mfhi %0, $ac1 \t\n"
+        "mflo %1, $ac1 \t\n"
+        : "=r"(acho), "=r"(aclo)
+        : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+      );
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 dmadd error\n");
+
+        return -1;
+    }
+
+    achi = 0x1;
+    acli = 0x1;
+
+    rs = 0xaaaabbbbccccdddd;
+    rt = 0xaaaabbbbccccdddd;
+
+    resh = 0x0000000000000000;
+    resl = 0xffffffffca860b63;
+
+    __asm
+       ("mthi %2, $ac1 \t\n"
+        "mtlo %3, $ac1 \t\n"
+        "dmadd $ac1, %4, %5\t\n"
+        "mfhi %0, $ac1 \t\n"
+        "mflo %1, $ac1 \t\n"
+        : "=r"(acho), "=r"(aclo)
+        : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+      );
+    if ((acho != resh) || (aclo != resl)) {
+        printf("2 dmadd error\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dmaddu.c b/tests/tcg/mips/mips64-dsp/dmaddu.c
new file mode 100644
index 0000000..39ab0c1
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dmaddu.c
@@ -0,0 +1,56 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resh, resl;
+    achi = 0x1;
+    acli = 0x2;
+
+    rs = 0x0000000200000002;
+    rt = 0x0000000200000002;
+    resh = 0x1;
+    resl = 0xa;
+    __asm
+        ("mthi %2, $ac1 \t\n"
+         "mtlo %3, $ac1 \t\n"
+         "dmaddu $ac1, %4, %5\t\n"
+         "mfhi %0, $ac1 \t\n"
+         "mflo %1, $ac1 \t\n"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 dmaddu error\n");
+
+        return -1;
+    }
+
+    achi = 0x1;
+    acli = 0x1;
+
+    rs = 0xaaaabbbbccccdddd;
+    rt = 0xaaaabbbbccccdddd;
+
+    resh = 0x0000000000000002;
+    resl = 0xffffffffca860b63;
+
+    __asm
+        ("mthi %2, $ac1 \t\n"
+         "mtlo %3, $ac1 \t\n"
+         "dmaddu $ac1, %4, %5\t\n"
+         "mfhi %0, $ac1 \t\n"
+         "mflo %1, $ac1 \t\n"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((acho != resh) || (aclo != resl)) {
+        printf("2 dmaddu error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dmsub.c b/tests/tcg/mips/mips64-dsp/dmsub.c
new file mode 100644
index 0000000..16be617
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dmsub.c
@@ -0,0 +1,59 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resh, resl;
+    achi = 0x1;
+    acli = 0x8;
+
+    rs = 0x0000000100000001;
+    rt = 0x0000000200000002;
+
+    resh = 0x1;
+    resl = 0x4;
+
+    __asm
+        ("mthi %2, $ac1 \t\n"
+         "mtlo %3, $ac1 \t\n"
+         "dmsub $ac1, %4, %5\t\n"
+         "mfhi %0, $ac1 \t\n"
+         "mflo %1, $ac1 \t\n"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 dmsub error\n");
+
+        return -1;
+    }
+
+    achi = 0xfffffffF;
+    acli = 0xfffffffF;
+
+    rs = 0x8888999977776666;
+    rt = 0x9999888877776666;
+
+    resh = 0xffffffffffffffff;
+    resl = 0x789aae13;
+
+    __asm
+        ("mthi %2, $ac1 \t\n"
+         "mtlo %3, $ac1 \t\n"
+         "dmsub $ac1, %4, %5\t\n"
+         "mfhi %0, $ac1 \t\n"
+         "mflo %1, $ac1 \t\n"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((acho != resh) || (aclo != resl)) {
+        printf("2 dmsub error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dmsubu.c b/tests/tcg/mips/mips64-dsp/dmsubu.c
new file mode 100644
index 0000000..cc4838a
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dmsubu.c
@@ -0,0 +1,59 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resh, resl;
+    achi = 0x1;
+    acli = 0x8;
+
+    rs = 0x0000000100000001;
+    rt = 0x0000000200000002;
+
+    resh = 0x1;
+    resl = 0x4;
+
+    __asm
+        ("mthi %2, $ac1 \t\n"
+         "mtlo %3, $ac1 \t\n"
+         "dmsubu $ac1, %4, %5\t\n"
+         "mfhi %0, $ac1 \t\n"
+         "mflo %1, $ac1 \t\n"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 dmsubu error\n");
+
+        return -1;
+    }
+
+    achi = 0xfffffffF;
+    acli = 0xfffffffF;
+
+    rs = 0x8888999977776666;
+    rt = 0x9999888877776666;
+
+    resh = 0xffffffffffffffff;
+    resl = 0x789aae13;
+
+    __asm
+        ("mthi %2, $ac1 \t\n"
+         "mtlo %3, $ac1 \t\n"
+         "dmsubu $ac1, %4, %5\t\n"
+         "mfhi %0, $ac1 \t\n"
+         "mflo %1, $ac1 \t\n"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((acho != resh) || (aclo != resl)) {
+        printf("2 dmsubu error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dmthlip.c b/tests/tcg/mips/mips64-dsp/dmthlip.c
new file mode 100644
index 0000000..4a001f2
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dmthlip.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, dsp;
+    long long achi, acli;
+    long long res, rsdsp;
+
+
+    rs = 0xaaaabbbbccccdddd;
+    achi = 0x87654321;
+    acli = 0x12345678;
+    dsp = 0x22;
+
+    res = 0x62;
+
+    __asm
+        ("mthi %1, $ac1\n\t"
+         "mtlo %2, $ac1\n\t"
+         "wrdsp %3\n\t"
+         "dmthlip %4, $ac1\n\t"
+         "rddsp %0\n\t"
+         : "=r"(rsdsp)
+         : "r"(achi), "r"(acli), "r"(dsp), "r"(rs)
+        );
+    if (rsdsp != res) {
+        printf("dmthlip error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c b/tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c
new file mode 100644
index 0000000..1bca935
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, dsp;
+    long long ach = 0, acl = 0;
+    long long resulth, resultl, resultdsp;
+
+    rs        = 0x800000FF;
+    rt        = 0x80000002;
+    resulth   = 0x00;
+    resultl   = 0xFFFFFFFF800003FB;
+    resultdsp = 0x01;
+    __asm
+        ("mthi        %0, $ac1\n\t"
+         "mtlo        %1, $ac1\n\t"
+         "dpaq_s.w.ph $ac1, %3, %4\n\t"
+         "mfhi        %0,   $ac1\n\t"
+         "mflo        %1,   $ac1\n\t"
+         "rddsp       %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = dsp >> 17 & 0x01;
+    if ((dsp != resultdsp) || (ach != resulth) || (acl != resultl)) {
+        printf("dpaq_w.w.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c b/tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c
new file mode 100644
index 0000000..94fc8c1
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c
@@ -0,0 +1,57 @@
+#include"io.h"
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resh, resl;
+
+    achi = 0x1;
+    acli = 0x1;
+    rs = 0x0001000100010001;
+    rt = 0x0002000200020002;
+    resh = 0x1;
+    resl = 0x11;
+
+    __asm
+        ("mthi %2, $ac1\t\n"
+         "mtlo %3, $ac1\t\n"
+         "dpaq_s.w.qh $ac1, %4, %5\t\n"
+         "mfhi %0, $ac1\t\n"
+         "mflo %1, $ac1\t\n"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 dpaq_s.w.qh error\n");
+
+        return -1;
+    }
+
+    achi = 0xffffffff;
+    acli = 0xaaaaaaaa;
+
+    rs = 0x1111222233334444;
+    rt = 0xffffeeeeddddcccc;
+
+    resh = 0xffffffffffffffff;
+    resl = 0xffffffffd27ad82e;
+
+    __asm
+        ("mthi %2, $ac1\t\n"
+         "mtlo %3, $ac1\t\n"
+         "dpaq_s.w.qh $ac1, %4, %5\t\n"
+         "mfhi %0, $ac1\t\n"
+         "mflo %1, $ac1\t\n"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((acho != resh) || (aclo != resl)) {
+        printf("2 dpaq_s.w.qh error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c b/tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c
new file mode 100644
index 0000000..3ee4c92
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c
@@ -0,0 +1,62 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long achi, acli;
+    long long acho, aclo;
+    long long dsp;
+    long long resh, resl;
+    long long resdsp;
+
+    rs = 0x0000000100000001;
+    rt = 0x0000000200000002;
+    achi = 0x1;
+    acli = 0x1;
+    resh = 0xFFFFFFFFFFFFFFFF;
+    resl = 0x00;
+    resdsp = 0x01;
+
+    __asm
+        ("mthi        %3, $ac1\n\t"
+         "mtlo        %4, $ac1\n\t"
+         "dpaq_sa.l.pw $ac1, %5, %6\n\t"
+         "mfhi        %0,   $ac1\n\t"
+         "mflo        %1,   $ac1\n\t"
+         "rddsp       %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((acho != resh) || (aclo != resl) || ((dsp >> (16 + 1)) != resdsp)) {
+        printf("1 dpaq_sa_l_pw error\n");
+
+        return -1;
+    }
+
+    rs = 0xaaaabbbbccccdddd;
+    rt = 0x3333444455556666;
+    achi = 0x88888888;
+    acli = 0x66666666;
+
+    resh = 0xffffffff88888887;
+    resl = 0xffffffff9e2661da;
+
+    __asm
+        ("mthi        %2, $ac1\n\t"
+         "mtlo        %3, $ac1\n\t"
+         "dpaq_sa.l.pw $ac1, %4, %5\n\t"
+         "mfhi        %0,   $ac1\n\t"
+         "mflo        %1,   $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 dpaq_sa_l_pw error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c b/tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c
new file mode 100644
index 0000000..54490f2
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, dsp;
+    long long ach = 0, acl = 0;
+    long long resulth, resultl, resultdsp;
+
+    rs        = 0x800000FF;
+    rt        = 0x80000002;
+    resulth   = 0x7FFFFFFF;
+    resultl   = 0xFFFFFFFFFFFFFFFF;
+    resultdsp = 0x01;
+    __asm
+        ("mthi        %0, $ac1\n\t"
+         "mtlo        %0, $ac1\n\t"
+         "dpaq_sa.l.w $ac1, %3, %4\n\t"
+         "mfhi        %0,   $ac1\n\t"
+         "mflo        %1,   $ac1\n\t"
+         "rddsp       %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x01;
+    if ((dsp != resultdsp) || (ach != resulth) || (acl != resultl)) {
+        printf("dpaq_sa.l.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpau_h_obl.c b/tests/tcg/mips/mips64-dsp/dpau_h_obl.c
new file mode 100644
index 0000000..54905e8
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpau_h_obl.c
@@ -0,0 +1,59 @@
+
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resh, resl;
+
+    rs = 0x0000000100000001;
+    rt = 0x0000000200000002;
+    achi = 0x1;
+    acli = 0x1;
+    resh = 0x1;
+    resl = 0x3;
+
+    __asm
+        ("mthi        %2, $ac1\n\t"
+         "mtlo        %3, $ac1\n\t"
+         "dpau.h.obl $ac1, %4, %5\n\t"
+         "mfhi        %0,   $ac1\n\t"
+         "mflo        %1,   $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 dpau.h.obl error\n");
+
+        return -1;
+    }
+
+    rs = 0xaaaabbbbccccdddd;
+    rt = 0x3333444455556666;
+    achi = 0x88888888;
+    acli = 0x66666666;
+
+    resh = 0xffffffff88888888;
+    resl = 0x66670d7a;
+
+    __asm
+        ("mthi        %2, $ac1\n\t"
+         "mtlo        %3, $ac1\n\t"
+         "dpau.h.obl $ac1, %4, %5\n\t"
+         "mfhi        %0,   $ac1\n\t"
+         "mflo        %1,   $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 dpau.h.obl error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpau_h_obr.c b/tests/tcg/mips/mips64-dsp/dpau_h_obr.c
new file mode 100644
index 0000000..d7aa60b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpau_h_obr.c
@@ -0,0 +1,59 @@
+
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resh, resl;
+
+    rs = 0x0000000100000001;
+    rt = 0x0000000200000002;
+    achi = 0x1;
+    acli = 0x1;
+    resh = 0x1;
+    resl = 0x3;
+
+    __asm
+        ("mthi        %2, $ac1\n\t"
+         "mtlo        %3, $ac1\n\t"
+         "dpau.h.obr $ac1, %4, %5\n\t"
+         "mfhi        %0,   $ac1\n\t"
+         "mflo        %1,   $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 dpau.h.obr error\n");
+
+        return -1;
+    }
+
+    rs = 0xccccddddaaaabbbb;
+    rt = 0x5555666633334444;
+    achi = 0x88888888;
+    acli = 0x66666666;
+
+    resh = 0xffffffff88888888;
+    resl = 0x66670d7a;
+
+    __asm
+        ("mthi        %2, $ac1\n\t"
+         "mtlo        %3, $ac1\n\t"
+         "dpau.h.obr $ac1, %4, %5\n\t"
+         "mfhi        %0,   $ac1\n\t"
+         "mflo        %1,   $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 dpau.h.obr error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpau_h_qbl.c b/tests/tcg/mips/mips64-dsp/dpau_h_qbl.c
new file mode 100644
index 0000000..fcfd764
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpau_h_qbl.c
@@ -0,0 +1,29 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long ach = 5, acl = 3;
+    long long resulth, resultl;
+
+    rs        = 0x800000FF;
+    rt        = 0x80000002;
+    resulth   = 0x05;
+    resultl   = 0x4003;
+    __asm
+        ("mthi       %0, $ac1\n\t"
+         "mtlo       %1, $ac1\n\t"
+         "dpau.h.qbl $ac1, %2, %3\n\t"
+         "mfhi       %0,   $ac1\n\t"
+         "mflo       %1,   $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    if ((ach != resulth) || (acl != resultl)) {
+        printf("dpau.h.qbl wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpau_h_qbr.c b/tests/tcg/mips/mips64-dsp/dpau_h_qbr.c
new file mode 100644
index 0000000..3282461
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpau_h_qbr.c
@@ -0,0 +1,29 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long ach = 5, acl = 3;
+    long long resulth, resultl;
+
+    rs        = 0x800000FF;
+    rt        = 0x80000002;
+    resulth   = 0x05;
+    resultl   = 0x0201;
+    __asm
+        ("mthi       %0, $ac1\n\t"
+         "mtlo       %1, $ac1\n\t"
+         "dpau.h.qbr $ac1, %2, %3\n\t"
+         "mfhi       %0,   $ac1\n\t"
+         "mflo       %1,   $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    if ((ach != resulth) || (acl != resultl)) {
+        printf("dpau.h.qbr wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c b/tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c
new file mode 100644
index 0000000..c8a414b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c
@@ -0,0 +1,29 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long ach = 5, acl = 5;
+    long long resulth, resultl;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x04;
+    resultl = 0xFFFFFFFFEE9794A3;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsq_s.w.ph $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    if ((ach != resulth) || (acl != resultl)) {
+        printf("dpsq_s.w.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c b/tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c
new file mode 100644
index 0000000..8fd5e25
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c
@@ -0,0 +1,33 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resh, resl;
+
+    rs      = 0xffffeeeeddddcccc;
+    rt      = 0x9999888877776666;
+    achi = 0x67576;
+    acli = 0x98878;
+
+    resh = 0x67576;
+    resl = 0x5b1682c4;
+    __asm
+        ("mthi  %2, $ac1\n\t"
+         "mtlo  %3, $ac1\n\t"
+         "dpsq_s.w.qh $ac1, %4, %5\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((acho != resh) || (aclo != resl)) {
+        printf("dpsq_s.w.qh wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c b/tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c
new file mode 100644
index 0000000..42ce901
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c
@@ -0,0 +1,39 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, dsp;
+    long long achi, acli;
+    long long resh, resl, resdsp;
+
+    rs      = 0x89789BC0123AD;
+    rt      = 0x5467591643721;
+
+    achi = 0x98765437;
+    acli = 0x65489709;
+
+    resh = 0xffffffff98765438;
+    resl = 0xFFFFFFFFf06d9f35;
+
+    resdsp = 0x00;
+
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsq_sa.l.pw $ac1, %3, %4\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "+r"(achi), "+r"(acli), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x01;
+    if ((dsp != resdsp) || (achi != resh) || (acli != resl)) {
+        printf("dpsq_sa.l.pw wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c b/tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c
new file mode 100644
index 0000000..9a5b090
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, dsp;
+    long long ach = 5, acl = 5;
+    long long resulth, resultl, resultdsp;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x7FFFFFFF;
+    resultl = 0xFFFFFFFFFFFFFFFF;
+    resultdsp = 0x01;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsq_sa.l.w $ac1, %3, %4\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x01;
+    if ((dsp != resultdsp) || (ach != resulth) || (acl != resultl)) {
+        printf("dpsq_sa.l.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpsu_h_obl.c b/tests/tcg/mips/mips64-dsp/dpsu_h_obl.c
new file mode 100644
index 0000000..c0a8f4d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpsu_h_obl.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long ach = 5, acl = 5;
+    long long resulth, resultl;
+
+    rs      = 0x88886666BC0123AD;
+    rt      = 0x9999888801643721;
+
+    resulth = 0x04;
+    resultl = 0xFFFFFFFFFFFEF115;
+
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsu.h.obl $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+
+    if ((ach != resulth) || (acl != resultl)) {
+        printf("dpsu.h.obl wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpsu_h_obr.c b/tests/tcg/mips/mips64-dsp/dpsu_h_obr.c
new file mode 100644
index 0000000..aa0d47a
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpsu_h_obr.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long ach = 5, acl = 5;
+    long long resulth, resultl;
+
+    rs      = 0x7878878888886666;
+    rt      = 0x9865454399998888;
+
+    resulth = 0x04;
+    resultl = 0xFFFFFFFFFFFeF115;
+
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsu.h.obr $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+
+    if ((ach != resulth) || (acl != resultl)) {
+        printf("dpsu.h.qbr wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c b/tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c
new file mode 100644
index 0000000..da6dbb6
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c
@@ -0,0 +1,29 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long ach = 5, acl = 5;
+    long long resulth, resultl;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x04;
+    resultl = 0xFFFFFFFFFFFFFEE5;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsu.h.qbl $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    if ((ach != resulth) || (acl != resultl)) {
+        printf("dpsu.h.qbl wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c b/tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c
new file mode 100644
index 0000000..bf00b70
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c
@@ -0,0 +1,29 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long ach = 5, acl = 5;
+    long long resulth, resultl;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x04;
+    resultl = 0xFFFFFFFFFFFFE233;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsu.h.qbr $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    if ((ach != resulth) || (acl != resultl)) {
+        printf("dpsu.h.qbr wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dshilo.c b/tests/tcg/mips/mips64-dsp/dshilo.c
new file mode 100644
index 0000000..2784f58
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dshilo.c
@@ -0,0 +1,31 @@
+#include "io.h"
+
+int main(void)
+{
+    long long achi, acli;
+    long long acho, aclo;
+    long long reshi, reslo;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+
+    reshi = 0xfffffffff8765432;
+    reslo = 0x1234567;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "dshilo $ac1, 0x4\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli)
+        );
+
+    if ((acho != reshi) || (aclo != reslo)) {
+        printf("dshilo error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/dshilov.c b/tests/tcg/mips/mips64-dsp/dshilov.c
new file mode 100644
index 0000000..dd5fa94
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/dshilov.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long achi, acli, rs;
+    long long acho, aclo;
+    long long reshi, reslo;
+
+    achi = 0x87654321;
+    acli = 0x12345678;
+    rs = 0x4;
+
+    reshi = 0xfffffffff8765432;
+    reslo = 0x1234567;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "dshilov $ac1, %4\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs)
+        );
+
+    if ((acho != reshi) || (aclo != reslo)) {
+        printf("dshilov error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/extp.c b/tests/tcg/mips/mips64-dsp/extp.c
new file mode 100644
index 0000000..c72f54b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/extp.c
@@ -0,0 +1,50 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, ach, acl, dsp;
+    long long result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    result = 0x000C;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extp %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 14) & 0x01;
+    if ((dsp != 0) || (result != rt)) {
+        printf("extp wrong\n");
+
+        return -1;
+    }
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x01;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extp %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 14) & 0x01;
+    if (dsp != 1) {
+        printf("extp wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/extpdp.c b/tests/tcg/mips/mips64-dsp/extpdp.c
new file mode 100644
index 0000000..f430193
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/extpdp.c
@@ -0,0 +1,51 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, ach, acl, dsp, pos, efi;
+    long long result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    result = 0x000C;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extpdp %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    pos =  dsp & 0x3F;
+    efi = (dsp >> 14) & 0x01;
+    if ((pos != 3) || (efi != 0) || (result != rt)) {
+        printf("extpdp wrong\n");
+
+        return -1;
+    }
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x01;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extpdp %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    efi = (dsp >> 14) & 0x01;
+    if (efi != 1) {
+        printf("extpdp wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/extpdpv.c b/tests/tcg/mips/mips64-dsp/extpdpv.c
new file mode 100644
index 0000000..ba57426
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/extpdpv.c
@@ -0,0 +1,52 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, ach, acl, dsp, pos, efi;
+    long long result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    rs  = 0x03;
+    result = 0x000C;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extpdpv %0, $ac1, %4\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl), "r"(rs)
+        );
+    pos =  dsp & 0x3F;
+    efi = (dsp >> 14) & 0x01;
+    if ((pos != 3) || (efi != 0) || (result != rt)) {
+        printf("extpdpv wrong\n");
+
+        return -1;
+    }
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x01;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extpdpv %0, $ac1, %4\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl), "r"(rs)
+        );
+    efi = (dsp >> 14) & 0x01;
+    if (efi != 1) {
+        printf("extpdpv wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/extpv.c b/tests/tcg/mips/mips64-dsp/extpv.c
new file mode 100644
index 0000000..158472b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/extpv.c
@@ -0,0 +1,51 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, ac, ach, acl, dsp;
+    long long result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    ac  = 0x03;
+    result = 0x000C;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extpv %0, $ac1, %4\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl), "r"(ac)
+        );
+    dsp = (dsp >> 14) & 0x01;
+    if ((dsp != 0) || (result != rt)) {
+        printf("extpv wrong\n");
+
+        return -1;
+    }
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x01;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extpv %0, $ac1, %4\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(ach), "r"(acl), "r"(ac)
+        );
+    dsp = (dsp >> 14) & 0x01;
+    if (dsp != 1) {
+        printf("extpv wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/extr_r_w.c b/tests/tcg/mips/mips64-dsp/extr_r_w.c
new file mode 100644
index 0000000..097b5e5
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/extr_r_w.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, ach, acl, dsp;
+    long long result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    result = 0xFFFFFFFFA0001699;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extr_r.w %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    if ((dsp != 1) || (result != rt)) {
+        printf("extr_r.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/extr_rs_w.c b/tests/tcg/mips/mips64-dsp/extr_rs_w.c
new file mode 100644
index 0000000..b9798a3
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/extr_rs_w.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, ach, acl, dsp;
+    long long result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    result = 0x7FFFFFFF;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extr_rs.w %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    if ((dsp != 1) || (result != rt)) {
+        printf("extr_rs.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/extr_s_h.c b/tests/tcg/mips/mips64-dsp/extr_s_h.c
new file mode 100644
index 0000000..2c2328f
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/extr_s_h.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, ach, acl, dsp;
+    long long result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    result = 0x00007FFF;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extr_s.h %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    if ((dsp != 1) || (result != rt)) {
+        printf("extr_s.h wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/extr_w.c b/tests/tcg/mips/mips64-dsp/extr_w.c
new file mode 100644
index 0000000..a5142d9
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/extr_w.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, ach, acl, dsp;
+    long long result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    result = 0xFFFFFFFFA0001699;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extr.w %0, $ac1, 0x03\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    if ((dsp != 1) || (result != rt)) {
+        printf("extr.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/extrv_r_w.c b/tests/tcg/mips/mips64-dsp/extrv_r_w.c
new file mode 100644
index 0000000..ebe0700
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/extrv_r_w.c
@@ -0,0 +1,31 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, ach, acl, dsp;
+    long long result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    rs  = 0x03;
+    result = 0xFFFFFFFFA0001699;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "extrv_r.w %0, $ac1, %2\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(rs), "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    if ((dsp != 1) || (result != rt)) {
+        printf("extrv_r.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/extrv_rs_w.c b/tests/tcg/mips/mips64-dsp/extrv_rs_w.c
new file mode 100644
index 0000000..b551f51
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/extrv_rs_w.c
@@ -0,0 +1,31 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, ach, acl, dsp;
+    long long result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    rs  = 0x03;
+    result = 0x7FFFFFFF;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "extrv_rs.w %0, $ac1, %2\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(rs), "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    if ((dsp != 1) || (result != rt)) {
+        printf("extrv_rs.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/extrv_s_h.c b/tests/tcg/mips/mips64-dsp/extrv_s_h.c
new file mode 100644
index 0000000..a8b3860
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/extrv_s_h.c
@@ -0,0 +1,31 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, ach, acl, dsp;
+    long long result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    rs  = 0x03;
+    result = 0x00007FFF;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "extrv_s.h %0, $ac1, %2\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(rs), "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    if ((dsp != 1) || (result != rt)) {
+        printf("extrv_s.h wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/extrv_w.c b/tests/tcg/mips/mips64-dsp/extrv_w.c
new file mode 100644
index 0000000..a553f6b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/extrv_w.c
@@ -0,0 +1,31 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, ach, acl, dsp;
+    long long result;
+
+    ach = 0x05;
+    acl = 0xB4CB;
+    dsp = 0x07;
+    rs  = 0x03;
+    result = 0xFFFFFFFFA0001699;
+
+    __asm
+        ("wrdsp %1, 0x01\n\t"
+         "mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "extrv.w %0, $ac1, %2\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "+r"(dsp)
+         : "r"(rs), "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    if ((dsp != 1) || (result != rt)) {
+        printf("extrv.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/head.S b/tests/tcg/mips/mips64-dsp/head.S
new file mode 100644
index 0000000..e97da50
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/head.S
@@ -0,0 +1,10 @@
+/*
+ *  Startup Code for MIPS64 CPU-core
+ *
+ */
+.text
+.globl _start
+.align 4
+_start:
+    jal    main
+
diff --git a/tests/tcg/mips/mips64-dsp/insv.c b/tests/tcg/mips/mips64-dsp/insv.c
new file mode 100644
index 0000000..fc5696f
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/insv.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long result;
+
+    /* msb = 10, lsb = 5 */
+    dsp    = 0x305;
+    rt     = 0x12345678;
+    rs     = 0xffffffff87654321;
+    result = 0x12345338;
+    __asm
+        ("wrdsp %2, 0x03\n\t"
+         "insv  %0, %1\n\t"
+         : "+r"(rt)
+         : "r"(rs), "r"(dsp)
+        );
+    if (rt != result) {
+        printf("insv wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/io.h b/tests/tcg/mips/mips64-dsp/io.h
new file mode 100644
index 0000000..b7db61d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/io.h
@@ -0,0 +1,22 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+extern int printf(const char *fmt, ...);
+extern unsigned long get_ticks(void);
+
+#define _read(source)                \
+({ unsigned long __res;                \
+    __asm__ __volatile__(            \
+        "mfc0\t%0, " #source "\n\t"    \
+        : "=r" (__res));        \
+    __res;                    \
+})
+
+#define __read(source)                \
+({ unsigned long __res;                \
+    __asm__ __volatile__(            \
+        "move\t%0, " #source "\n\t"    \
+        : "=r" (__res));        \
+    __res;                    \
+})
+
+#endif
diff --git a/tests/tcg/mips/mips64-dsp/lbux.c b/tests/tcg/mips/mips64-dsp/lbux.c
new file mode 100644
index 0000000..dbdc87b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/lbux.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long value, rd;
+    long long *p;
+    unsigned long long addr, index;
+    long long result;
+
+    value  = 0xBCDEF389;
+    p = &value;
+    addr = (unsigned long long)p;
+    index  = 0;
+    result = value & 0xFF;
+    __asm
+        ("lbux %0, %1(%2)\n\t"
+         : "=r"(rd)
+         : "r"(index), "r"(addr)
+        );
+    if (rd != result) {
+        printf("lbux wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/ldx.c b/tests/tcg/mips/mips64-dsp/ldx.c
new file mode 100644
index 0000000..787d9f0
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/ldx.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long value, rd;
+    long long *p;
+    unsigned long long addr, index;
+    long long result;
+
+    value  = 0xBCDEF389;
+    p = &value;
+    addr = (unsigned long long)p;
+    index  = 0;
+    result = 0xBCDEF389;
+    __asm
+        ("ldx %0, %1(%2)\n\t"
+         : "=r"(rd)
+         : "r"(index), "r"(addr)
+        );
+    if (rd != result) {
+        printf("lwx wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/lhx.c b/tests/tcg/mips/mips64-dsp/lhx.c
new file mode 100644
index 0000000..2020e56
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/lhx.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long value, rd;
+    long long *p;
+    unsigned long long addr, index;
+    long long result;
+
+    value  = 0xBCDEF389;
+    p = &value;
+    addr = (unsigned long long)p;
+    index  = 0;
+    result = 0xFFFFFFFFFFFFF389;
+    __asm
+        ("lhx %0, %1(%2)\n\t"
+         : "=r"(rd)
+         : "r"(index), "r"(addr)
+        );
+    if (rd != result) {
+        printf("lhx wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/lwx.c b/tests/tcg/mips/mips64-dsp/lwx.c
new file mode 100644
index 0000000..6a81414
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/lwx.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long value, rd;
+    long long *p;
+    unsigned long long addr, index;
+    long long result;
+
+    value  = 0xBCDEF389;
+    p = &value;
+    addr = (unsigned long long)p;
+    index  = 0;
+    result = 0xFFFFFFFFBCDEF389;
+    __asm
+        ("lwx %0, %1(%2)\n\t"
+         : "=r"(rd)
+         : "r"(index), "r"(addr)
+        );
+    if (rd != result) {
+        printf("lwx wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/madd.c b/tests/tcg/mips/mips64-dsp/madd.c
new file mode 100644
index 0000000..de6e44f
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/madd.c
@@ -0,0 +1,33 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0x01;
+    rt  = 0x01;
+    resulth = 0x05;
+    resultl = 0xB4CC;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "madd $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((resulth != acho) || (resultl != aclo)) {
+        printf("madd wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maddu.c b/tests/tcg/mips/mips64-dsp/maddu.c
new file mode 100644
index 0000000..e9f426a
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maddu.c
@@ -0,0 +1,33 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0x01;
+    rt  = 0x01;
+    resulth = 0x05;
+    resultl = 0xB4CC;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "madd $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((resulth != acho) || (resultl != aclo)) {
+        printf("maddu wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c b/tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c
new file mode 100644
index 0000000..c196b43
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c
@@ -0,0 +1,56 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0x98765432FF060000;
+    rt  = 0xfdeca987CB000000;
+    resulth = 0x05;
+    resultl = 0x18278587;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_s.l.pwl $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((resulth != acho) || (resultl != aclo)) {
+        printf("maq_s_l.w.pwl wrong 1\n");
+
+        return -1;
+    }
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0x80000000FF060000;
+    rt  = 0x80000000CB000000;
+    resulth = 0x05;
+    resultl = 0xb4ca;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_s.l.pwl $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) {
+        printf("maq_s_l.w.pwl wrong 2\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c b/tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c
new file mode 100644
index 0000000..e2af69f
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c
@@ -0,0 +1,56 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0x87898765432;
+    rt  = 0x7878fdeca987;
+    resulth = 0x05;
+    resultl = 0x18278587;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_s.l.pwr $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((resulth != acho) || (resultl != aclo)) {
+        printf("maq_s.w.pwr wrong\n");
+
+        return -1;
+    }
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0x89899980000000;
+    rt  = 0x88780000000;
+    resulth = 0x05;
+    resultl = 0xb4ca;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_s.l.pwr $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) {
+        printf("maq_s.w.pwr wrong\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_s_w_phl.c b/tests/tcg/mips/mips64-dsp/maq_s_w_phl.c
new file mode 100644
index 0000000..2f511d9
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_s_w_phl.c
@@ -0,0 +1,33 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0xFF060000;
+    rt  = 0xCB000000;
+    resulth = 0x04;
+    resultl = 0xFFFFFFFF947438CB;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_s.w.phl $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((resulth != acho) || (resultl != aclo)) {
+        printf("maq_s.w.phl wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_s_w_phr.c b/tests/tcg/mips/mips64-dsp/maq_s_w_phr.c
new file mode 100644
index 0000000..4c8f899
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_s_w_phr.c
@@ -0,0 +1,33 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0xFF06;
+    rt  = 0xCB00;
+    resulth = 0x04;
+    resultl = 0xFFFFFFFF947438CB;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_s.w.phr $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((resulth != acho) || (resultl != aclo)) {
+        printf("maq_s.w.phr wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c b/tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c
new file mode 100644
index 0000000..234a0af
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c
@@ -0,0 +1,62 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0x05;
+
+    rs  = 0x1234888899990000;
+    rt  = 0x9876888899990000;
+
+    resulth = 0x05;
+    resultl = 0x15ae87f5;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_s.w.qhll $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((resulth != acho) || (resultl != aclo)) {
+        printf("maq_s.w.qhll wrong\n");
+
+        return -1;
+    }
+
+
+    achi = 0x04;
+    acli = 0x06;
+    rs  = 0x8000888899990000;
+    rt  = 0x8000888899990000;
+
+    resulth = 0x04;
+    resultl = 0xffffffff80000005;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_s.w.qhll $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) {
+        printf("maq_s.w.qhll wrong\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c b/tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c
new file mode 100644
index 0000000..8768cba
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c
@@ -0,0 +1,62 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0x05;
+
+    rs  = 0x1234123412340000;
+    rt  = 0x9876987698760000;
+
+    resulth = 0x05;
+    resultl = 0x15ae87f5;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_s.w.qhlr $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((resulth != acho) || (resultl != aclo)) {
+        printf("1 maq_s.w.qhlr wrong\n");
+
+        return -1;
+    }
+
+
+    achi = 0x04;
+    acli = 0x06;
+    rs  = 0x8000800080000000;
+    rt  = 0x8000800080000000;
+
+    resulth = 0x04;
+    resultl = 0xffffffff80000005;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_s.w.qhlr $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) {
+        printf("2 maq_s.w.qhlr wrong\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c b/tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c
new file mode 100644
index 0000000..5006e2b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c
@@ -0,0 +1,63 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0x05;
+
+    rs  = 0x1234888812340000;
+    rt  = 0x9876888898760000;
+
+    resulth = 0x05;
+    resultl = 0x15ae87f5;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_s.w.qhrl $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((resulth != acho) || (resultl != aclo)) {
+        printf("1 maq_s.w.qhrl wrong\n");
+
+        return -1;
+    }
+
+
+    achi = 0x04;
+    acli = 0x06;
+    rs  = 0x8888999980000000;
+    rt  = 0x8888999980000000;
+
+    resulth = 0x04;
+    resultl = 0xffffffff80000005;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_s.w.qhrl $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) {
+        printf("2 maq_s.w.qhrl wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c b/tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c
new file mode 100644
index 0000000..1d213a5
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c
@@ -0,0 +1,63 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0x05;
+
+    rs  = 0x1234888812341234;
+    rt  = 0x9876888898769876;
+
+    resulth = 0x05;
+    resultl = 0x15ae87f5;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_s.w.qhrr $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((resulth != acho) || (resultl != aclo)) {
+        printf("1 maq_s.w.qhrr wrong\n");
+
+        return -1;
+    }
+
+
+    achi = 0x04;
+    acli = 0x06;
+    rs  = 0x8000888899998000;
+    rt  = 0x8000888899998000;
+
+    resulth = 0x04;
+    resultl = 0xffffffff80000005;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_s.w.qhrr $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) {
+        printf("2 maq_s.w.qhrr wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c b/tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c
new file mode 100644
index 0000000..b8101f7
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c
@@ -0,0 +1,33 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0xFF060000;
+    rt  = 0xCB000000;
+    resulth = 0xFFFFFFFFFFFFFFFF;
+    resultl = 0xFFFFFFFF947438cb;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_sa.w.phl $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((resulth != acho) || (resultl != aclo)) {
+        printf("maq_sa.w.phl wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c b/tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c
new file mode 100644
index 0000000..7da8cf6
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c
@@ -0,0 +1,33 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0xB4CB;
+    rs  = 0xFF06;
+    rt  = 0xCB00;
+    resulth = 0xFFFFFFFFFFFFFFFF;
+    resultl = 0xFFFFFFFF947438cb;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_sa.w.phr $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((resulth != acho) || (resultl != aclo)) {
+        printf("maq_sa.w.phr wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c
new file mode 100644
index 0000000..8816c7c
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c
@@ -0,0 +1,64 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0x05;
+
+    rs  = 0x1234888899990000;
+    rt  = 0x9876888899990000;
+
+    resulth = 0x0;
+    resultl = 0x15ae87f5;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_sa.w.qhll $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x0) || (resulth != acho) || (resultl != aclo)) {
+        printf("1 maq_sa.w.qhll wrong\n");
+
+        return -1;
+    }
+
+
+    achi = 0x04;
+    acli = 0x06;
+    rs  = 0x8000888899990000;
+    rt  = 0x8000888899990000;
+
+    resulth = 0xffffffffffffffff;
+    resultl = 0xffffffff80000000;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_sa.w.qhll $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) {
+        printf("2 maq_sa.w.qhll wrong\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c
new file mode 100644
index 0000000..40eefca
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c
@@ -0,0 +1,64 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0x05;
+
+    rs  = 0x1234123412340000;
+    rt  = 0x9876987699990000;
+
+    resulth = 0x0;
+    resultl = 0x15ae87f5;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_sa.w.qhlr $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x0) || (resulth != acho) || (resultl != aclo)) {
+        printf("maq_sa.w.qhlr wrong\n");
+
+        return -1;
+    }
+
+
+    achi = 0x04;
+    acli = 0x06;
+    rs  = 0x8000800099990000;
+    rt  = 0x8000800099990000;
+
+    resulth = 0xffffffffffffffff;
+    resultl = 0xffffffff80000000;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_sa.w.qhlr $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) {
+        printf("maq_sa.w.qhlr wrong\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c
new file mode 100644
index 0000000..0f970fc
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c
@@ -0,0 +1,64 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0x05;
+
+    rs  = 0x1234123412340000;
+    rt  = 0x9876987698760000;
+
+    resulth = 0x0;
+    resultl = 0x15ae87f5;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_sa.w.qhrl $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x0) || (resulth != acho) || (resultl != aclo)) {
+        printf("1 maq_sa.w.qhrl wrong\n");
+
+        return -1;
+    }
+
+
+    achi = 0x04;
+    acli = 0x06;
+    rs  = 0x8000800080000000;
+    rt  = 0x8000800080000000;
+
+    resulth = 0xffffffffffffffff;
+    resultl = 0xffffffff80000000;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_sa.w.qhrl $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) {
+        printf("2 maq_sa.w.qhrl wrong\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c
new file mode 100644
index 0000000..1f75665
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c
@@ -0,0 +1,64 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs, dsp;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    achi = 0x05;
+    acli = 0x05;
+
+    rs  = 0x1234123412341234;
+    rt  = 0x9876987698769876;
+
+    resulth = 0x0;
+    resultl = 0x15ae87f5;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_sa.w.qhrr $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x0) || (resulth != acho) || (resultl != aclo)) {
+        printf("1 maq_sa.w.qhrr wrong\n");
+
+        return -1;
+    }
+
+
+    achi = 0x04;
+    acli = 0x06;
+    rs  = 0x8000800080008000;
+    rt  = 0x8000800080008000;
+
+    resulth = 0xffffffffffffffff;
+    resultl = 0xffffffff80000000;
+
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "maq_sa.w.qhrr $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x1) || (resulth != acho) || (resultl != aclo)) {
+        printf("2 maq_sa.w.qhrr wrong\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/mfhi.c b/tests/tcg/mips/mips64-dsp/mfhi.c
new file mode 100644
index 0000000..ee915f7
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/mfhi.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long achi, acho;
+    long long result;
+
+    achi   = 0x004433;
+    result = 0x004433;
+
+    __asm
+        ("mthi %1, $ac1\n\t"
+         "mfhi %0, $ac1\n\t"
+         : "=r"(acho)
+         : "r"(achi)
+        );
+    if (result != acho) {
+        printf("mfhi wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/mflo.c b/tests/tcg/mips/mips64-dsp/mflo.c
new file mode 100644
index 0000000..cdc646b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/mflo.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long acli, aclo;
+    long long result;
+
+    acli   = 0x004433;
+    result = 0x004433;
+
+    __asm
+        ("mtlo %1, $ac1\n\t"
+         "mflo %0, $ac1\n\t"
+         : "=r"(aclo)
+         : "r"(acli)
+        );
+    if (result != aclo) {
+        printf("mflo wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/mips_boot.lds b/tests/tcg/mips/mips64-dsp/mips_boot.lds
new file mode 100644
index 0000000..bd7c0c0
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/mips_boot.lds
@@ -0,0 +1,31 @@
+OUTPUT_ARCH(mips)
+SECTIONS
+{
+    . = 0xffffffff80100000;
+    . = ALIGN((1 << 13));
+    .text :
+    {
+        *(.text)
+        *(.rodata)
+        *(.rodata.*)
+    }
+
+    __init_begin = .;
+    . = ALIGN((1 << 12));
+    .init.text : AT(ADDR(.init.text) - 0)
+    {
+        *(.init.text)
+    }
+    .init.data : AT(ADDR(.init.data) - 0)
+    {
+        *(.init.data)
+    }
+    . = ALIGN((1 << 12));
+    __init_end = .;
+
+    . = ALIGN((1 << 13));
+    .data :
+    {
+        *(.data)
+    }
+}
diff --git a/tests/tcg/mips/mips64-dsp/modsub.c b/tests/tcg/mips/mips64-dsp/modsub.c
new file mode 100644
index 0000000..2c91cb4
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/modsub.c
@@ -0,0 +1,37 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0xFFFFFFFF;
+    rt     = 0x000000FF;
+    result = 0xFFFFFF00;
+    __asm
+        ("modsub %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (result != rd) {
+        printf("modsub wrong\n");
+
+        return -1;
+    }
+
+    rs     = 0x00000000;
+    rt     = 0x00CD1FFF;
+    result = 0x0000CD1F;
+    __asm
+        ("modsub %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (result != rd) {
+        printf("modsub wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/msub.c b/tests/tcg/mips/mips64-dsp/msub.c
new file mode 100644
index 0000000..75066b5
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/msub.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long achi, acli, rs, rt;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    rs      = 0x00BBAACC;
+    rt      = 0x0B1C3D2F;
+    achi    = 0x00004433;
+    acli    = 0xFFCC0011;
+    resulth = 0xFFFFFFFFFFF81F29;
+    resultl = 0xFFFFFFFFB355089D;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "msub $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((acho != resulth) || (aclo != resultl)) {
+        printf("msub wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/msubu.c b/tests/tcg/mips/mips64-dsp/msubu.c
new file mode 100644
index 0000000..55f8ae0
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/msubu.c
@@ -0,0 +1,32 @@
+#include "io.h"
+
+int main(void)
+{
+    long long achi, acli, rs, rt;
+    long long acho, aclo;
+    long long resulth, resultl;
+
+    rs      = 0x00BBAACC;
+    rt      = 0x0B1C3D2F;
+    achi    = 0x00004433;
+    acli    = 0xFFCC0011;
+    resulth = 0xFFFFFFFFFFF81F29;
+    resultl = 0xFFFFFFFFB355089D;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "msubu $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    if ((acho != resulth) || (aclo != resultl)) {
+        printf("msubu wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/mthi.c b/tests/tcg/mips/mips64-dsp/mthi.c
new file mode 100644
index 0000000..8570051
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/mthi.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long achi, acho;
+    long long result;
+
+    achi   = 0x004433;
+    result = 0x004433;
+
+    __asm
+        ("mthi %1, $ac1\n\t"
+         "mfhi %0, $ac1\n\t"
+         : "=r"(acho)
+         : "r"(achi)
+        );
+    if (result != acho) {
+        printf("mthi wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/mthlip.c b/tests/tcg/mips/mips64-dsp/mthlip.c
new file mode 100644
index 0000000..5373bd4
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/mthlip.c
@@ -0,0 +1,35 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, ach, acl, dsp;
+    long long result, resulth, resultl;
+
+    dsp = 0x07;
+    ach = 0x05;
+    acl = 0xB4CB;
+    rs  = 0x00FFBBAA;
+    resulth = 0xB4CB;
+    resultl = 0x00FFBBAA;
+    result  = 0x27;
+
+    __asm
+        ("wrdsp %0, 0x01\n\t"
+         "mthi %1, $ac1\n\t"
+         "mtlo %2, $ac1\n\t"
+         "mthlip %3, $ac1\n\t"
+         "mfhi %1, $ac1\n\t"
+         "mflo %2, $ac1\n\t"
+         "rddsp %0\n\t"
+         : "+r"(dsp), "+r"(ach), "+r"(acl)
+         : "r"(rs)
+        );
+    dsp = dsp & 0x3F;
+    if ((dsp != result) || (ach != resulth) || (acl != resultl)) {
+        printf("mthlip wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/mtlo.c b/tests/tcg/mips/mips64-dsp/mtlo.c
new file mode 100644
index 0000000..304fffb
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/mtlo.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main(void)
+{
+    long long acli, aclo;
+    long long result;
+
+    acli   = 0x004433;
+    result = 0x004433;
+
+    __asm
+        ("mthi %1, $ac1\n\t"
+         "mfhi %0, $ac1\n\t"
+         : "=r"(aclo)
+         : "r"(acli)
+        );
+    if (result != aclo) {
+        printf("mtlo wrong\n");
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c b/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c
new file mode 100644
index 0000000..be38570
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c
@@ -0,0 +1,55 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result;
+    rd = 0;
+    rs = 0x45BCFFFF12345678;
+    rt = 0x98529AD287654321;
+    result = 0x52fbec7035a2ca5c;
+
+    __asm
+        ("muleq_s.pw.qhl %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("muleq_s.pw.qhl error\n");
+
+        return -1;
+    }
+
+    rd = 0;
+    rs = 0x45BC800012345678;
+    rt = 0x9852800087654321;
+    result = 0x52fbec707FFFFFFF;
+
+    __asm
+        ("muleq_s.pw.qhl %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("muleq_s.pw.qhl dspcontrol overflown flag error\n");
+
+        return -1;
+    }
+
+    rd = 0;
+    __asm
+        ("rddsp %0\n\t"
+         : "=r"(rd)
+        );
+    rd = rd >> 21;
+    rd = rd & 0x1;
+
+    if (rd != 1) {
+        printf("muleq_s.pw.qhl dspcontrol bit not set error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c b/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c
new file mode 100644
index 0000000..d0a84d4
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result;
+    rd = 0;
+    rs = 0x1234567845BCFFFF;
+    rt = 0x8765432198529AD2;
+    result = 0x52fbec7035a2ca5c;
+
+    __asm
+        ("muleq_s.pw.qhr %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("muleq_s.pw.qhr error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c b/tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c
new file mode 100644
index 0000000..0e59479
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c
@@ -0,0 +1,45 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x8000;
+    rt = 0x8000;
+    result = 0x7FFFFFFF;
+    resultdsp = 1;
+
+    __asm
+        ("muleq_s.w.phr %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    if ((rd  != result) || (dsp != resultdsp)) {
+        printf("muleq_s.w.phr wrong\n");
+
+        return -1;
+    }
+
+    rs = 0x1234;
+    rt = 0x4321;
+    result = 0x98be968;
+    resultdsp = 1;
+
+    __asm
+        ("muleq_s.w.phr %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    if ((rd  != result) || (dsp != resultdsp)) {
+        printf("muleq_s.w.phr wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c b/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c
new file mode 100644
index 0000000..2f444c9
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x80001234;
+    rt = 0x80004321;
+    result = 0xFFFFFFFFFFFF0000;
+    resultdsp = 1;
+
+    __asm
+        ("muleu_s.ph.qbl %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    if ((rd  != result) || (dsp != resultdsp)) {
+        printf("muleu_s.ph.qbl wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c b/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c
new file mode 100644
index 0000000..8bd0e99
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x8000;
+    rt = 0x80004321;
+    result = 0xFFFFFFFFFFFF0000;
+    resultdsp = 1;
+
+    __asm
+        ("muleu_s.ph.qbr %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    if ((rd  != result) || (dsp != resultdsp)) {
+        printf("muleu_s.ph.qbr wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c b/tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c
new file mode 100644
index 0000000..63b3ad5
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c
@@ -0,0 +1,25 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result;
+
+    rd = 0;
+    rs = 0x1234567802020202;
+    rt = 0x0034432112344321;
+    result = 0x03A8FFFFFFFFFFFF;
+
+    __asm
+        ("muleu_s.qh.obl %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != result) {
+        printf("muleu_s.qh.obl error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c b/tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c
new file mode 100644
index 0000000..f6289ee
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c
@@ -0,0 +1,25 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result;
+
+    rd = 0;
+    rs = 0x1234567802020204;
+    rt = 0x0034432112344321;
+    result = 0x006886422468FFFF;
+
+    __asm
+        ("muleu_s.qh.obr %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != result) {
+        printf("muleu_s.qh.obr error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/mulq_rs_ph.c b/tests/tcg/mips/mips64-dsp/mulq_rs_ph.c
new file mode 100644
index 0000000..fd6233d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/mulq_rs_ph.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x80001234;
+    rt = 0x80004321;
+    result = 0x7FFF098C;
+    resultdsp = 1;
+
+    __asm
+        ("mulq_rs.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    if ((rd  != result) || (dsp != resultdsp)) {
+        printf("mulq_rs.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/mulq_rs_qh.c b/tests/tcg/mips/mips64-dsp/mulq_rs_qh.c
new file mode 100644
index 0000000..7863c05
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/mulq_rs_qh.c
@@ -0,0 +1,33 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dsp, dspresult;
+    rt = 0x80003698CE8F9201;
+    rs = 0x800034634BCDE321;
+    result = 0x7fff16587a530313;
+
+    dspresult = 0x01;
+
+    __asm
+        ("mulq_rs.qh %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+
+    if (rd != result) {
+        printf("mulq_rs.qh error\n");
+
+        return -1;
+    }
+
+    dsp = (dsp >> 21) & 0x01;
+    if (dsp != dspresult) {
+        printf("mulq_rs.qh DSPControl Reg ouflag error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c b/tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c
new file mode 100644
index 0000000..02548f8
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c
@@ -0,0 +1,59 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, dsp;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resl, resh;
+
+    achi = 0x4;
+    acli = 0x4;
+
+    rs = 0x1234567887654321;
+    rt = 0x8765432112345678;
+
+    resh = 0x4;
+    resl = 0x4;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "mulsaq_s.l.pw $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 mulsaq_s.l.pw wrong\n");
+
+        return -1;
+    }
+
+    achi = 0x4;
+    acli = 0x4;
+
+    rs = 0x8000000087654321;
+    rt = 0x8000000012345678;
+
+    resh = 0x4;
+    resl = 0x1e8ee513;
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "mulsaq_s.l.pw $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x1) || (acho != resh) || (aclo != resl)) {
+        printf("2 mulsaq_s.l.pw wrong\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c b/tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c
new file mode 100644
index 0000000..92d7a0b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c
@@ -0,0 +1,57 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, dsp;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resl, resh;
+
+    achi = 0x4;
+    acli = 0x4;
+
+    rs = 0x5678123443218765;
+    rt = 0x4321876556781234;
+
+    resh = 0x4;
+    resl = 0x342fcbd4;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "mulsaq_s.w.qh $ac1, %4, %5\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 mulsaq_s.w.qh wrong\n");
+        return -1;
+    }
+
+    achi = 0x4;
+    acli = 0x4;
+
+    rs = 0x8000800087654321;
+    rt = 0x8000800012345678;
+
+    resh = 0x3;
+    resl = 0xffffffffe5e81a1c;
+    __asm
+        ("mthi %3, $ac1\n\t"
+         "mtlo %4, $ac1\n\t"
+         "mulsaq_s.w.qh $ac1, %5, %6\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "=r"(acho), "=r"(aclo), "=r"(dsp)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x1;
+    if ((dsp != 0x1) || (acho != resh) || (aclo != resl)) {
+        printf("2 mulsaq_s.w.qh wrong\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/mult.c b/tests/tcg/mips/mips64-dsp/mult.c
new file mode 100644
index 0000000..4a294d1
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/mult.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, ach, acl;
+    long long result, resulth, resultl;
+
+    rs  = 0x00FFBBAA;
+    rt  = 0x4B231000;
+    resulth = 0x4b0f01;
+    resultl = 0x71f8a000;
+    __asm
+        ("mult $ac1, %2, %3\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(ach), "=r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    if ((ach != resulth) || (acl != resultl)) {
+        printf("mult wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/multu.c b/tests/tcg/mips/mips64-dsp/multu.c
new file mode 100644
index 0000000..ea51cfa
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/multu.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt, ach, acl;
+    long long result, resulth, resultl;
+
+    rs  = 0x00FFBBAA;
+    rt  = 0x4B231000;
+    resulth = 0x4b0f01;
+    resultl = 0x71f8a000;
+    __asm
+        ("mult $ac1, %2, %3\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "=r"(ach), "=r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    if ((ach != resulth) || (acl != resultl)) {
+        printf("multu wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/out b/tests/tcg/mips/mips64-dsp/out
new file mode 100644
index 0000000..37723eb
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/out
@@ -0,0 +1,231 @@
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./absq_s_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./absq_s_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./absq_s_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./absq_s_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./addq_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./addq_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./addq_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./addq_s_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./addq_s_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./addq_s_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./addsc.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./addu_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./addu_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./addu_s_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./addu_s_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./addwc.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./bitrev.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./bposge32.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./bposge64.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmp_eq_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmp_eq_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmp_eq_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmpgu_eq_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmpgu_eq_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmpgu_le_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmpgu_le_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmpgu_lt_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmpgu_lt_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmp_le_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmp_le_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmp_le_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmp_lt_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmp_lt_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmp_lt_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmpu_eq_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmpu_eq_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmpu_le_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmpu_le_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmpu_lt_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./cmpu_lt_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextp.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextpdp.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextpdpv.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextpv.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextr_l.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextr_r_l.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextr_rs_l.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextr_rs_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextr_r_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextr_s_h.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextrv_l.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextrv_r_l.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextrv_rs_l.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextrv_rs_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextrv_r_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextrv_s_h.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextrv_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dextr_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dinsv.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dmadd.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dmaddu.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dmsub.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dmsubu.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dmthlip.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpaq_sa_l_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpaq_sa_l_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpaq_s_w_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpaq_s_w_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpau_h_obl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpau_h_obr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpau_h_qbl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpau_h_qbr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpsq_sa_l_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpsq_sa_l_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpsq_s_w_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpsq_s_w_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpsu_h_obl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpsu_h_obr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpsu_h_qbl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dpsu_h_qbr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dshilo.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./dshilov.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./extp.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./extpdp.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./extpdpv.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./extpv.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./extr_rs_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./extr_r_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./extr_s_h.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./extrv_rs_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./extrv_r_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./extrv_s_h.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./extrv_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./extr_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./insv.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./lbux.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./lhx.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./lwx.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./ldx.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./madd.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maddu.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_sa_w_phl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_sa_w_phr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_sa_w_qhll.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_sa_w_qhlr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_sa_w_qhrl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_sa_w_qhrr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_s_l_pwl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_s_l_pwr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_s_w_phl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_s_w_phr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_s_w_qhll.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_s_w_qhlr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_s_w_qhrl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./maq_s_w_qhrr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./mfhi.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./mflo.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./modsub.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./msub.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./msubu.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./mthi.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./mthlip.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./mtlo.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./muleq_s_pw_qhl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./muleq_s_pw_qhr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./muleq_s_w_phr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./muleu_s_ph_qbl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./muleu_s_ph_qbr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./muleu_s_qh_obl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./muleu_s_qh_obr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./mulq_rs_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./mulq_rs_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./mulsaq_s_l_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./mulsaq_s_w_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./mult.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./multu.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./packrl_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./packrl_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./pick_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./pick_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./pick_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./pick_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./pick_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceq_pw_qhla.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceq_pw_qhl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceq_pw_qhra.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceq_pw_qhr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./precequ_ph_qbla.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./precequ_ph_qbl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./precequ_ph_qbra.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./precequ_ph_qbr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceq_w_phl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceq_w_phr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceu_ph_qbla.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceu_ph_qbl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceu_ph_qbra.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceu_ph_qbr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceu_qh_obla.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceu_qh_obl.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceu_qh_obra.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./preceu_qh_obr.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./precrq_ob_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./precrq_ph_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./precrq_pw_l.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./precrq_qb_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./precrq_qh_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./precrq_rs_ph_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./precrq_rs_qh_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./precrqu_s_ob_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./precrqu_s_qb_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./raddu_w_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./rddsp.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./repl_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./repl_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./repl_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./repl_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./repl_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./replv_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./replv_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./replv_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./replv_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shilo.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shilov.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shll_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shll_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shll_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shll_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shll_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shll_s_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shll_s_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shll_s_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shll_s_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shllv_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shllv_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shllv_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shllv_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shllv_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shllv_s_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shllv_s_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shllv_s_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shllv_s_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shra_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shra_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shra_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shra_r_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shra_r_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shra_r_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shra_r_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shrav_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shrav_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shrav_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shrav_r_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shrav_r_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shrav_r_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shrav_r_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shrl_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shrl_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shrlv_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./shrlv_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./subq_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./subq_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./subq_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./subq_s_ph.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./subq_s_pw.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./subq_s_qh.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./subq_s_w.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./subu_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./subu_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./subu_s_ob.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./subu_s_qb.tst
+qemu-system-mips64el -nographic -cpu mips64dspr2 -kernel ./wrdsp.tst
diff --git a/tests/tcg/mips/mips64-dsp/packrl_ph.c b/tests/tcg/mips/mips64-dsp/packrl_ph.c
new file mode 100644
index 0000000..3722b0a
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/packrl_ph.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x56788765;
+
+    __asm
+        ("packrl.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (result != rd) {
+        printf("packrl.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/packrl_pw.c b/tests/tcg/mips/mips64-dsp/packrl_pw.c
new file mode 100644
index 0000000..7807418
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/packrl_pw.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long res;
+
+    rs = 0x1234567887654321;
+    rt = 0xabcdef9812345678;
+
+    res = 0x87654321abcdef98;
+
+    __asm
+        ("packrl.pw %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != res) {
+        printf("packrl.pw error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/pick_ob.c b/tests/tcg/mips/mips64-dsp/pick_ob.c
new file mode 100644
index 0000000..93bcc85
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/pick_ob.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long res;
+    dsp = 0xff000000;
+
+    rs = 0x1234567812345678;
+    rt = 0x8765432187654321;
+
+    res = 0x1234567812345678;
+
+    __asm
+        ("wrdsp %1, 0x10\n\t"
+         "pick.ob %0, %2, %3\n\t"
+         : "=r"(rd)
+         : "r"(dsp), "r"(rs), "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("pick.ob error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/pick_ph.c b/tests/tcg/mips/mips64-dsp/pick_ph.c
new file mode 100644
index 0000000..f7bde08
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/pick_ph.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    dsp = 0x0A000000;
+    result = 0x12344321;
+
+    __asm
+        ("wrdsp %3, 0x10\n\t"
+         "pick.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt), "r"(dsp)
+        );
+    if (rd != result) {
+        printf("pick.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/pick_pw.c b/tests/tcg/mips/mips64-dsp/pick_pw.c
new file mode 100644
index 0000000..277606b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/pick_pw.c
@@ -0,0 +1,28 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long res;
+    dsp = 0xff000000;
+
+    rs = 0x1234567812345678;
+    rt = 0x8765432187654321;
+
+    res = 0x1234567812345678;
+
+    __asm
+        ("wrdsp %1, 0x10\n\t"
+         "wrdsp %1\n\t"
+         "pick.pw %0, %2, %3\n\t"
+         : "=r"(rd), "+r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("pick.pw error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/pick_qb.c b/tests/tcg/mips/mips64-dsp/pick_qb.c
new file mode 100644
index 0000000..b0c4a17
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/pick_qb.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    dsp = 0x0A000000;
+    result = 0x12655621;
+
+    __asm
+        ("wrdsp %3, 0x10\n\t"
+         "pick.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt), "r"(dsp)
+        );
+    if (rd != result) {
+        printf("pick.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/pick_qh.c b/tests/tcg/mips/mips64-dsp/pick_qh.c
new file mode 100644
index 0000000..11391b5
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/pick_qh.c
@@ -0,0 +1,28 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long res;
+    dsp = 0xff000000;
+
+    rs = 0x1234567812345678;
+    rt = 0x8765432187654321;
+
+    res = 0x1234567812345678;
+
+    __asm
+        ("wrdsp %1, 0x10\n\t"
+         "wrdsp %1\n\t"
+         "pick.qh %0, %2, %3\n\t"
+         : "=r"(rd), "+r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("pick.qh error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/preceq_l_pwl.c b/tests/tcg/mips/mips64-dsp/preceq_l_pwl.c
new file mode 100644
index 0000000..6455100
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceq_l_pwl.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+    rt = 0xFFFFFFFF11111111;
+    result = 0xFFFFFFFF00000000;
+
+    __asm
+        ("preceq.l.pwl %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("preceq.l.pwl wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/tests/tcg/mips/mips64-dsp/preceq_l_pwr.c b/tests/tcg/mips/mips64-dsp/preceq_l_pwr.c
new file mode 100644
index 0000000..1e05339
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceq_l_pwr.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+    rt = 0xFFFFFFFF11111111;
+    result = 0x1111111100000000;
+
+    __asm
+        ("preceq.l.pwl %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("preceq.l.pwr wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c b/tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c
new file mode 100644
index 0000000..f44b940
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c
@@ -0,0 +1,21 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+    rt = 0x0123456789ABCDEF;
+    result = 0x0123000045670000;
+
+    __asm
+        ("preceq.pw.qhl %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("preceq.pw.qhl error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c b/tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c
new file mode 100644
index 0000000..f0f78f4
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+
+    rt = 0x123456789ABCDEF0;
+    result = 0x123400009ABC0000;
+
+    __asm
+        ("preceq.pw.qhla %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("preceq.pw.qhla error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c b/tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c
new file mode 100644
index 0000000..709d4f9
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c
@@ -0,0 +1,21 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+    rt = 0x0123456789ABCDEF;
+    result = 0x89AB0000CDEF0000;
+
+    __asm
+        ("preceq.pw.qhr %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("preceq.pw.qhr error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c b/tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c
new file mode 100644
index 0000000..4d071ec
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+
+    rt = 0x123456789ABCDEF0;
+    result = 0x56780000DEF00000;
+
+    __asm
+        ("preceq.pw.qhra %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("preceq.pw.qhra error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/preceq_w_phl.c b/tests/tcg/mips/mips64-dsp/preceq_w_phl.c
new file mode 100644
index 0000000..4ed3fc0
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceq_w_phl.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt = 0x87654321;
+    result = 0xFFFFFFFF87650000;
+
+    __asm
+        ("preceq.w.phl %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("preceq.w.phl wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/preceq_w_phr.c b/tests/tcg/mips/mips64-dsp/preceq_w_phr.c
new file mode 100644
index 0000000..e2ea093
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceq_w_phr.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt = 0x87654321;
+    result = 0x43210000;
+
+    __asm
+        ("preceq.w.phr %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("preceq.w.phr wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c b/tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c
new file mode 100644
index 0000000..17b7331
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt = 0x87654321;
+    result = 0x43803280;
+
+    __asm
+        ("precequ.ph.qbl %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("precequ.ph.qbl wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c b/tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c
new file mode 100644
index 0000000..15e9494
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt = 0x87654321;
+    result = 0x43802180;
+
+    __asm
+        ("precequ.ph.qbla %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("precequ.ph.qbla wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c b/tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c
new file mode 100644
index 0000000..495368c
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt = 0x87654321;
+    result = 0x21801080;
+
+    __asm
+        ("precequ.ph.qbr %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("precequ.ph.qbr wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c b/tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c
new file mode 100644
index 0000000..7c66369
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt = 0x87654321;
+    result = 0x32801080;
+
+    __asm
+        ("precequ.ph.qbra %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("precequ.ph.qbra wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precequ_qh_obl.c b/tests/tcg/mips/mips64-dsp/precequ_qh_obl.c
new file mode 100644
index 0000000..176d236
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precequ_qh_obl.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+    rt = 0x123456789ABCDEF0;
+    result = 0x09001A002B003C00;
+
+    __asm
+        ("precequ.qh.obla %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("precequ.qh.obla error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precequ_qh_obla.c b/tests/tcg/mips/mips64-dsp/precequ_qh_obla.c
new file mode 100644
index 0000000..93a36a4
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precequ_qh_obla.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+    rt = 0x123456789ABCDEF0;
+    result = 0x09002B004D006F00;
+
+    __asm
+        ("precequ.qh.obla %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("precequ.qh.obla error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precequ_qh_obr.c b/tests/tcg/mips/mips64-dsp/precequ_qh_obr.c
new file mode 100644
index 0000000..1214730
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precequ_qh_obr.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+
+    rt = 0x123456789ABCDEF0;
+    result = 0x4D005E006F007000;
+
+    __asm
+        ("precequ.qh.obr %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("precequ.qh.obr error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/tests/tcg/mips/mips64-dsp/precequ_qh_obra.c b/tests/tcg/mips/mips64-dsp/precequ_qh_obra.c
new file mode 100644
index 0000000..3aa0e09
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precequ_qh_obra.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+
+    rt = 0x123456789ABCDEF0;
+    result = 0x1A003C005D007000;
+
+    __asm
+        ("precequ.qh.obra %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("precequ.qh.obra error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c b/tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c
new file mode 100644
index 0000000..81f7917
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt = 0x87654321;
+    result = 0x00870065;
+
+    __asm
+        ("preceu.ph.qbl %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("preceu.ph.qbl wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c b/tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c
new file mode 100644
index 0000000..38cf6a6
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt = 0x87654321;
+    result = 0x00870043;
+
+    __asm
+        ("preceu.ph.qbla %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("preceu.ph.qbla wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c b/tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c
new file mode 100644
index 0000000..70c32b6
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt = 0x87654321;
+    result = 0x00430021;
+
+    __asm
+        ("preceu.ph.qbr %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("preceu.ph.qbr wrong");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c b/tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c
new file mode 100644
index 0000000..c6638aa
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt = 0x87654321;
+    result = 0x00650021;
+
+    __asm
+        ("preceu.ph.qbra %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (result != rd) {
+        printf("preceu.ph.qbra wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/preceu_qh_obl.c b/tests/tcg/mips/mips64-dsp/preceu_qh_obl.c
new file mode 100644
index 0000000..63f9373
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceu_qh_obl.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+    rt = 0x123456789ABCDEF0;
+    result = 0x0012003400560078;
+
+    __asm
+        ("preceu.qh.obl %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("preceu.qh.obl error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/preceu_qh_obla.c b/tests/tcg/mips/mips64-dsp/preceu_qh_obla.c
new file mode 100644
index 0000000..5fb65e4
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceu_qh_obla.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+    rt = 0x123456789ABCDEF0;
+    result = 0x00120056009A00DE;
+
+    __asm
+        ("preceu.qh.obla %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("preceu.qh.obla error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/preceu_qh_obr.c b/tests/tcg/mips/mips64-dsp/preceu_qh_obr.c
new file mode 100644
index 0000000..9af3b63
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceu_qh_obr.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+
+    rt = 0x123456789ABCDEF0;
+    result = 0x009A00BC00DE00F0;
+
+    __asm
+        ("preceu.qh.obr %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("preceu.qh.obr error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/preceu_qh_obra.c b/tests/tcg/mips/mips64-dsp/preceu_qh_obra.c
new file mode 100644
index 0000000..fd04083
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/preceu_qh_obra.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+
+    rt = 0x123456789ABCDEF0;
+    result = 0x0034007800BC00F0;
+
+    __asm
+        ("preceu.qh.obra %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("preceu.qh.obra error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precr_ob_qh.c b/tests/tcg/mips/mips64-dsp/precr_ob_qh.c
new file mode 100644
index 0000000..ce2da79
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precr_ob_qh.c
@@ -0,0 +1,25 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long res;
+
+    rs = 0x1234567812345678;
+    rt = 0x8765432187654321;
+
+    res = 0x3478347865216521;
+
+    __asm
+        ("precr.ob.qh %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("precr.ob.qh error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c b/tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c
new file mode 100644
index 0000000..8bb16de
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c
@@ -0,0 +1,40 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long res;
+
+    rt = 0x8765432187654321;
+    rs = 0x1234567812345678;
+
+    res = 0x4321432156785678;
+
+    __asm
+        ("precr_sra.qh.pw %0, %1, 0x0\n\t"
+         : "=r"(rt)
+         : "r"(rs)
+        );
+
+    if (rt != res) {
+        printf("precr_sra.qh.pw error\n");
+        return -1;
+    }
+
+    rt = 0x8765432187654321;
+    rs = 0x1234567812345678;
+
+    res = 0x5432543245674567;
+
+    __asm
+        ("precr_sra.qh.pw %0, %1, 0x4\n\t"
+         : "=r"(rt)
+         : "r"(rs)
+        );
+
+    if (rt != res) {
+        printf("precr_sra.qh.pw error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c b/tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c
new file mode 100644
index 0000000..734ac32
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c
@@ -0,0 +1,40 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long res;
+
+    rt = 0x8765432187654321;
+    rs = 0x1234567812345678;
+
+    res = 0x4321432156785678;
+
+    __asm
+        ("precr_sra_r.qh.pw %0, %1, 0x0\n\t"
+         : "=r"(rt)
+         : "r"(rs)
+        );
+
+    if (rt != res) {
+        printf("precr_sra_r.qh.pw error\n");
+        return -1;
+    }
+
+    rt = 0x8765432187654321;
+    rs = 0x1234567812345678;
+
+    res = 0x5432543245684568;
+
+    __asm
+        ("precr_sra_r.qh.pw %0, %1, 0x4\n\t"
+         : "=r"(rt)
+         : "r"(rs)
+        );
+
+    if (rt != res) {
+        printf("precr_sra_r.qh.pw error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precrq_ob_qh.c b/tests/tcg/mips/mips64-dsp/precrq_ob_qh.c
new file mode 100644
index 0000000..4f61b17
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precrq_ob_qh.c
@@ -0,0 +1,25 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long res;
+
+    rs = 0x1234567812345678;
+    rt = 0x8765432187654321;
+
+    res = 0x1256125687438743;
+
+    __asm
+        ("precrq.ob.qh %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("precrq.ob.qh error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precrq_ph_w.c b/tests/tcg/mips/mips64-dsp/precrq_ph_w.c
new file mode 100644
index 0000000..f0946ab
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precrq_ph_w.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x12348765;
+
+    __asm
+        ("precrq.ph.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (result != rd) {
+        printf("precrq.ph.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precrq_pw_l.c b/tests/tcg/mips/mips64-dsp/precrq_pw_l.c
new file mode 100644
index 0000000..da957c0
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precrq_pw_l.c
@@ -0,0 +1,25 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long res;
+
+    rs = 0x1234567812345678;
+    rt = 0x8765432187654321;
+
+    res = 0x1234567887654321;
+
+    __asm
+        ("precrq.pw.l %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("precrq.pw.l error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precrq_qb_ph.c b/tests/tcg/mips/mips64-dsp/precrq_qb_ph.c
new file mode 100644
index 0000000..f417c9f
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precrq_qb_ph.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x12568743;
+
+    __asm
+        ("precrq.qb.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (result != rd) {
+        printf("precrq.qb.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precrq_qh_pw.c b/tests/tcg/mips/mips64-dsp/precrq_qh_pw.c
new file mode 100644
index 0000000..4a4ffef
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precrq_qh_pw.c
@@ -0,0 +1,25 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long res;
+
+    rs = 0x1234567812345678;
+    rt = 0x8765432187654321;
+
+    res = 0x1234123487658765;
+
+    __asm
+        ("precrq.qh.pw %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("precrq.qh.pw error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c b/tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c
new file mode 100644
index 0000000..42e674b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x12348765;
+
+    __asm
+        ("precrq_rs.ph.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (result != rd) {
+        printf("precrq_rs.ph.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c b/tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c
new file mode 100644
index 0000000..9826510
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c
@@ -0,0 +1,25 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long res;
+
+    rs = 0x1234567812345678;
+    rt = 0x8765432187654321;
+
+    res = 0x1234123487658765;
+
+    __asm
+        ("precrq_rs.qh.pw %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("precrq_rs.qh.pw error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c b/tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c
new file mode 100644
index 0000000..dc8a643
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long res, resdsp;
+
+    rs = 0x1234567812345678;
+    rt = 0x8765432187654321;
+
+    res = 0x24ac24ac00860086;
+    resdsp = 0x1;
+
+    __asm
+        ("precrqu_s.ob.qh %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x1;
+    if ((rd != res) || (dsp != resdsp)) {
+        printf("precrq_s.ob.qh error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c b/tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c
new file mode 100644
index 0000000..a3ab898
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x24AC0086;
+
+    __asm
+        ("precrqu_s.qb.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (result != rd) {
+        printf("precrqu_s.qb.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/prependd.c b/tests/tcg/mips/mips64-dsp/prependd.c
new file mode 100644
index 0000000..b4208c2
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/prependd.c
@@ -0,0 +1,37 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long res;
+    rt = 0x1234567887654321;
+    rs = 0xabcd1234abcd8765;
+
+    res = 0x1234567887654321;
+    __asm
+        ("prependd %0, %1, 0x0\n\t"
+         : "=r"(rt)
+         : "r"(rs)
+        );
+
+    if (rt != res) {
+        printf("prependd error\n");
+        return -1;
+    }
+
+    rt = 0x1234567887654321;
+    rs = 0xabcd1234abcd8765;
+
+    res = 0xd876512345678876;
+    __asm
+        ("prependd %0, %1, 0x4\n\t"
+         : "=r"(rt)
+         : "r"(rs)
+        );
+
+    if (rt != res) {
+        printf("prependd error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/prependw.c b/tests/tcg/mips/mips64-dsp/prependw.c
new file mode 100644
index 0000000..d91bd20
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/prependw.c
@@ -0,0 +1,37 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long res;
+    rt = 0x1234567887654321;
+    rs = 0xabcd1234abcd8765;
+
+    res = 0x1234567887654321;
+    __asm
+        ("prependw %0, %1, 0x0\n\t"
+         : "=r"(rt)
+         : "r"(rs)
+        );
+
+    if (rt != res) {
+        printf("prependw error\n");
+        return -1;
+    }
+
+    rt = 0x1234567887654321;
+    rs = 0xabcd1234abcd8765;
+
+    res = 0x5123456788765432;
+    __asm
+        ("prependw %0, %1, 0x4\n\t"
+         : "=r"(rt)
+         : "r"(rs)
+        );
+
+    if (rt != res) {
+        printf("prependw error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/printf.c b/tests/tcg/mips/mips64-dsp/printf.c
new file mode 100644
index 0000000..cf8676d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/printf.c
@@ -0,0 +1,266 @@
+
+typedef unsigned long va_list;
+
+#define ACC    4
+#define __read(source)                    \
+({ va_list __res;                    \
+    __asm__ __volatile__(                \
+        "move\t%0, " #source "\n\t"        \
+        : "=r" (__res));            \
+    __res;                        \
+})
+
+enum format_type {
+    FORMAT_TYPE_NONE,
+    FORMAT_TYPE_HEX,
+    FORMAT_TYPE_ULONG,
+    FORMAT_TYPE_FLOAT
+};
+
+struct printf_spec {
+    char    type;
+};
+
+static int format_decode(char *fmt, struct printf_spec *spec)
+{
+    char *start = fmt;
+
+    for (; *fmt ; ++fmt) {
+        if (*fmt == '%') {
+            break;
+        }
+    }
+
+    switch (*++fmt) {
+    case 'x':
+        spec->type = FORMAT_TYPE_HEX;
+        break;
+
+    case 'd':
+        spec->type = FORMAT_TYPE_ULONG;
+        break;
+
+    case 'f':
+        spec->type = FORMAT_TYPE_FLOAT;
+        break;
+
+    default:
+        spec->type = FORMAT_TYPE_NONE;
+    }
+
+    return ++fmt - start;
+}
+
+void *memcpy(void *dest, void *src, int n)
+{
+    int i;
+    char *s = src;
+    char *d = dest;
+
+    for (i = 0; i < n; i++) {
+        d[i] = s[i];
+    }
+    return dest;
+}
+
+char *number(char *buf, va_list num)
+{
+    int i;
+    char *str = buf;
+    static char digits[16] = "0123456789abcdef";
+    str = str + sizeof(num) * 2;
+
+    for (i = 0; i < sizeof(num) * 2; i++) {
+        *--str = digits[num & 15];
+        num >>= 4;
+    }
+
+    return buf + sizeof(num) * 2;
+}
+
+char *__number(char *buf, va_list num)
+{
+    int i;
+    va_list mm = num;
+    char *str = buf;
+
+    if (!num) {
+        *str++ = '0';
+        return str;
+    }
+
+    for (i = 0; mm; mm = mm/10, i++) {
+        /* Do nothing. */
+    }
+
+    str = str + i;
+
+    while (num) {
+        *--str = num % 10 + 48;
+        num = num / 10;
+    }
+
+    return str + i;
+}
+
+va_list modf(va_list args, va_list *integer, va_list *num)
+{
+    int i;
+    double dot_v = 0;
+    va_list E, DOT, DOT_V;
+
+    if (!args) {
+        return 0;
+    }
+
+    for (i = 0, args = args << 1 >> 1; i < 52; i++) {
+        if ((args >> i) & 0x1) {
+            break;
+        }
+    }
+
+    *integer = 0;
+
+    if ((args >> 56 != 0x3f) || (args >> 52 == 0x3ff)) {
+        E = (args >> 52) - 1023;
+        DOT = 52 - E - i;
+        DOT_V = args << (12 + E) >> (12 + E) >> i;
+        *integer = ((args << 12 >> 12) >> (i + DOT)) | (1 << E);
+    } else {
+        E = ~((args >> 52) - 1023) + 1;
+        DOT_V = args << 12 >> 12;
+
+        dot_v += 1.0 / (1 << E);
+
+        for (i = 1; i <= 16; i++) {
+            if ((DOT_V >> (52 - i)) & 0x1) {
+                dot_v += 1.0 / (1 << E + i);
+            }
+        }
+
+        for (i = 1, E = 0; i <= ACC; i++) {
+            dot_v *= 10;
+            if (!(va_list)dot_v) {
+                E++;
+            }
+    }
+
+    *num = E;
+
+    return dot_v;
+    }
+
+    if (args & 0xf) {
+        for (i = 1; i <= 16; i++) {
+            if ((DOT_V >> (DOT - i)) & 0x1) {
+                dot_v += 1.0 / (1 << i);
+            }
+        }
+
+        for (i = 1, E = 0; i <= ACC; i++) {
+            dot_v *= 10;
+            if (!(va_list)dot_v) {
+                E++;
+            }
+        }
+
+        *num = E;
+
+        return dot_v;
+    } else if (DOT) {
+        for (i = 1; i <= DOT; i++) {
+            if ((DOT_V >> (DOT - i)) & 0x1) {
+                dot_v += 1.0 / (1 << i);
+            }
+        }
+
+        for (i = 1; i <= ACC; i++) {
+            dot_v = dot_v * 10;
+        }
+
+    return dot_v;
+    }
+
+    return 0;
+}
+
+int vsnprintf(char *buf, int size, char *fmt, va_list args)
+{
+    char *str, *mm;
+    struct printf_spec spec = {0};
+
+    str = mm = buf;
+
+    while (*fmt) {
+        char *old_fmt = fmt;
+        int read = format_decode(fmt, &spec);
+
+        fmt += read;
+
+        switch (spec.type) {
+        case FORMAT_TYPE_NONE: {
+            memcpy(str, old_fmt, read);
+            str += read;
+            break;
+        }
+        case FORMAT_TYPE_HEX: {
+            memcpy(str, old_fmt, read);
+            str = number(str + read, args);
+            for (; *mm ; ++mm) {
+                if (*mm == '%') {
+                    *mm = '0';
+                break;
+                }
+            }
+        break;
+        }
+        case FORMAT_TYPE_ULONG: {
+            memcpy(str, old_fmt, read - 2);
+            str = __number(str + read - 2, args);
+            break;
+        }
+        case FORMAT_TYPE_FLOAT: {
+            va_list integer, dot_v, num;
+            dot_v = modf(args, &integer, &num);
+            memcpy(str, old_fmt, read - 2);
+            str += read - 2;
+            if ((args >> 63 & 0x1)) {
+                *str++ = '-';
+            }
+            str = __number(str, integer);
+            if (dot_v) {
+                *str++ = '.';
+                while (num--) {
+                    *str++ = '0';
+                }
+                str = __number(str, dot_v);
+            }
+            break;
+        }
+        }
+    }
+    *str = '\0';
+
+    return str - buf;
+}
+
+static void serial_out(char *str)
+{
+    while (*str) {
+        *(char *)0xffffffffb80003f8 = *str++;
+    }
+}
+
+int vprintf(char *fmt, va_list args)
+{
+    int printed_len = 0;
+    static char printf_buf[512];
+    printed_len = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args);
+    serial_out(printf_buf);
+    return printed_len;
+}
+
+int printf(char *fmt, ...)
+{
+    return vprintf(fmt, __read($5));
+}
diff --git a/tests/tcg/mips/mips64-dsp/raddu_l_ob.c b/tests/tcg/mips/mips64-dsp/raddu_l_ob.c
new file mode 100644
index 0000000..76ddf25
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/raddu_l_ob.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, result;
+    rs = 0x12345678ABCDEF0;
+    result = 0x000000000001E258;
+
+    __asm
+        ("raddu.l.ob %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs)
+        );
+
+    if (rd != result) {
+        printf("raddu.l.ob error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/raddu_w_qb.c b/tests/tcg/mips/mips64-dsp/raddu_w_qb.c
new file mode 100644
index 0000000..c9d6535
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/raddu_w_qb.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs;
+    long long result;
+
+    rs = 0x12345678;
+    result = 0x114;
+
+    __asm
+        ("raddu.w.qb %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rs)
+        );
+    if (rd != result) {
+        printf("raddu.w.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/rddsp.c b/tests/tcg/mips/mips64-dsp/rddsp.c
new file mode 100644
index 0000000..7165572
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/rddsp.c
@@ -0,0 +1,53 @@
+#include "io.h"
+
+int main(void)
+{
+    long long dsp_i, dsp_o;
+    long long ccond_i, outflag_i, efi_i, c_i, scount_i, pos_i;
+    long long ccond_o, outflag_o, efi_o, c_o, scount_o, pos_o;
+    long long ccond_r, outflag_r, efi_r, c_r, scount_r, pos_r;
+
+    ccond_i   = 0x000000BC;/* 4 */
+    outflag_i = 0x0000001B;/* 3 */
+    efi_i     = 0x00000001;/* 5 */
+    c_i       = 0x00000001;/* 2 */
+    scount_i  = 0x0000000F;/* 1 */
+    pos_i     = 0x0000000C;/* 0 */
+
+    dsp_i = (ccond_i   << 24) | \
+            (outflag_i << 16) | \
+            (efi_i     << 14) | \
+            (c_i       << 13) | \
+            (scount_i  <<  7) | \
+            pos_i;
+
+    ccond_r   = ccond_i;
+    outflag_r = outflag_i;
+    efi_r     = efi_i;
+    c_r       = c_i;
+    scount_r  = scount_i;
+    pos_r     = pos_i;
+
+    __asm
+        ("wrdsp %1, 0x3F\n\t"
+         "rddsp %0, 0x3F\n\t"
+         : "=r"(dsp_o)
+         : "r"(dsp_i)
+        );
+
+    ccond_o   = (dsp_o >> 24) & 0xFF;
+    outflag_o = (dsp_o >> 16) & 0xFF;
+    efi_o     = (dsp_o >> 14) & 0x01;
+    c_o       = (dsp_o >> 14) & 0x01;
+    scount_o  = (dsp_o >>  7) & 0x3F;
+    pos_o     =  dsp_o & 0x1F;
+
+    if ((ccond_o != ccond_r) || (outflag_o != outflag_r) || (efi_o != efi_r) \
+            || (c_o != c_r) || (scount_o != scount_r) || (pos_o != pos_r)) {
+        printf("rddsp wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/repl_ob.c b/tests/tcg/mips/mips64-dsp/repl_ob.c
new file mode 100644
index 0000000..20cb780
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/repl_ob.c
@@ -0,0 +1,21 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, result;
+    rd = 0;
+    result = 0xFFFFFFFFFFFFFFFF;
+
+    __asm
+        ("repl.ob %0, 0xFF\n\t"
+         : "=r"(rd)
+        );
+
+    if (result != rd) {
+        printf("repl.ob error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/repl_ph.c b/tests/tcg/mips/mips64-dsp/repl_ph.c
new file mode 100644
index 0000000..11d29bd
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/repl_ph.c
@@ -0,0 +1,30 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, result;
+
+    result = 0x01BF01BF;
+    __asm
+        ("repl.ph %0, 0x1BF\n\t"
+         : "=r"(rd)
+        );
+    if (rd != result) {
+        printf("repl.ph wrong\n");
+
+        return -1;
+    }
+
+    result = 0x01FF01FF;
+    __asm
+        ("repl.ph %0, 0x01FF\n\t"
+         : "=r"(rd)
+        );
+    if (rd != result) {
+        printf("repl.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/repl_pw.c b/tests/tcg/mips/mips64-dsp/repl_pw.c
new file mode 100644
index 0000000..dee514c
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/repl_pw.c
@@ -0,0 +1,34 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, result;
+    rd = 0;
+    result = 0x000001FF000001FF;
+
+    __asm
+        ("repl.pw %0, 0x1FF\n\t"
+         : "=r"(rd)
+        );
+
+    if (result != rd) {
+        printf("repl.pw error\n");
+
+        return -1;
+    }
+
+    rd = 0;
+    result = 0xFFFFFE00FFFFFE00;
+    __asm
+        ("repl.pw %0, 0xFFFFFFFFFFFFFE00\n\t"
+         : "=r"(rd)
+        );
+
+    if (result != rd) {
+        printf("repl.pw error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/repl_qb.c b/tests/tcg/mips/mips64-dsp/repl_qb.c
new file mode 100644
index 0000000..592feae
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/repl_qb.c
@@ -0,0 +1,19 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, result;
+
+    result = 0xFFFFFFFFBFBFBFBF;
+    __asm
+        ("repl.qb %0, 0xBF\n\t"
+         : "=r"(rd)
+        );
+    if (rd != result) {
+        printf("repl.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/repl_qh.c b/tests/tcg/mips/mips64-dsp/repl_qh.c
new file mode 100644
index 0000000..82afc37
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/repl_qh.c
@@ -0,0 +1,34 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, result;
+    rd = 0;
+    result = 0x01FF01FF01FF01FF;
+
+    __asm
+        ("repl.qh %0, 0x1FF\n\t"
+         : "=r"(rd)
+        );
+
+    if (result != rd) {
+        printf("repl.qh error 1\n");
+
+        return -1;
+    }
+
+    rd = 0;
+    result = 0xFE00FE00FE00FE00;
+    __asm
+        ("repl.qh %0, 0xFFFFFFFFFFFFFE00\n\t"
+         : "=r"(rd)
+        );
+
+    if (result != rd) {
+        printf("repl.qh error 2\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/replv_ob.c b/tests/tcg/mips/mips64-dsp/replv_ob.c
new file mode 100644
index 0000000..31ff318
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/replv_ob.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+
+    rt = 0xFF;
+    result = 0xFFFFFFFFFFFFFFFF;
+
+    __asm
+        ("replv.ob %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("replv.ob error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/replv_ph.c b/tests/tcg/mips/mips64-dsp/replv_ph.c
new file mode 100644
index 0000000..0af7a36
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/replv_ph.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt = 0x12345678;
+    result = 0x56785678;
+    __asm
+        ("replv.ph %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("replv.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/replv_pw.c b/tests/tcg/mips/mips64-dsp/replv_pw.c
new file mode 100644
index 0000000..e1789af
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/replv_pw.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, result;
+    rd = 0;
+    rt = 0xFFFFFFFF;
+    result = 0xFFFFFFFFFFFFFFFF;
+
+    __asm
+        ("replv.pw %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (result != rd) {
+        printf("replv.pw error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/replv_qb.c b/tests/tcg/mips/mips64-dsp/replv_qb.c
new file mode 100644
index 0000000..d99298c
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/replv_qb.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt     = 0x12345678;
+    result = 0x78787878;
+    __asm
+        ("replv.qb %0, %1\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("replv.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shilo.c b/tests/tcg/mips/mips64-dsp/shilo.c
new file mode 100644
index 0000000..5f454f6
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shilo.c
@@ -0,0 +1,29 @@
+#include "io.h"
+
+int main(void)
+{
+    long long ach, acl;
+    long long resulth, resultl;
+
+    ach = 0xBBAACCFF;
+    acl = 0x1C3B001D;
+
+    resulth = 0x17755;
+    resultl = 0xFFFFFFFF99fe3876;
+
+    __asm
+        ("mthi %0, $ac1\n\t"
+         "mtlo %1, $ac1\n\t"
+         "shilo $ac1, 0x0F\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+        );
+    if ((ach != resulth) || (acl != resultl)) {
+        printf("shilo wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shilov.c b/tests/tcg/mips/mips64-dsp/shilov.c
new file mode 100644
index 0000000..e82615a
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shilov.c
@@ -0,0 +1,31 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, ach, acl;
+    long long resulth, resultl;
+
+    rs  = 0x0F;
+    ach = 0xBBAACCFF;
+    acl = 0x1C3B001D;
+
+    resulth = 0x17755;
+    resultl = 0xFFFFFFFF99fe3876;
+
+    __asm
+        ("mthi %0, $ac1\n\t"
+         "mtlo %1, $ac1\n\t"
+         "shilov $ac1, %2\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs)
+        );
+    if ((ach != resulth) || (acl != resultl)) {
+        printf("shilov wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shll_ob.c b/tests/tcg/mips/mips64-dsp/shll_ob.c
new file mode 100644
index 0000000..de9e6d0
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shll_ob.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, dsp;
+    long long res, resdsp;
+
+    rt = 0x9ba8765433456789;
+    res = 0xd840b0a098283848;
+    resdsp = 0x1;
+    __asm
+        ("shll.ob %0, %2, 0x3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+
+    dsp = (dsp >> 22) & 0x1;
+
+    if ((dsp != resdsp) || (rd != res)) {
+        printf("shll.ob error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shll_ph.c b/tests/tcg/mips/mips64-dsp/shll_ph.c
new file mode 100644
index 0000000..2a30c1a
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shll_ph.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, dsp;
+    long long result, resultdsp;
+
+    rt        = 0x12345678;
+    result    = 0xFFFFFFFFA000C000;
+    resultdsp = 1;
+
+    __asm
+        ("shll.ph %0, %2, 0x0B\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("shll.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shll_pw.c b/tests/tcg/mips/mips64-dsp/shll_pw.c
new file mode 100644
index 0000000..63dbae5
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shll_pw.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, dsp;
+    long long result, resultdsp;
+
+    rt        = 0x8765432112345678;
+    result    = 0x6543210034567800;
+    resultdsp = 1;
+
+    __asm
+        ("shll.pw %0, %2, 0x8\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+
+    dsp = (dsp >> 22) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("shll.pw wrong\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shll_qb.c b/tests/tcg/mips/mips64-dsp/shll_qb.c
new file mode 100644
index 0000000..c21ab66
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shll_qb.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, dsp;
+    long long result, resultdsp;
+
+    rt     = 0x87654321;
+    result = 0x38281808;
+    resultdsp = 0x01;
+
+    __asm
+        ("shll.qb %0, %2, 0x03\n\t"
+         "rddsp   %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    if (rd != result) {
+        printf("shll.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shll_qh.c b/tests/tcg/mips/mips64-dsp/shll_qh.c
new file mode 100644
index 0000000..067a6e5
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shll_qh.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, dsp;
+    long long res, resdsp;
+
+    rt = 0x9ba8765433456789;
+    res = 0xdd40b2a09a283c48;
+    resdsp = 0x1;
+    __asm
+        ("shll.qh %0, %2, 0x3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+
+    dsp = (dsp >> 22) & 0x1;
+
+    if ((dsp != resdsp) || (rd != res)) {
+        printf("shll.qh error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shll_s_ph.c b/tests/tcg/mips/mips64-dsp/shll_s_ph.c
new file mode 100644
index 0000000..3d96f6e
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shll_s_ph.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, dsp;
+    long long result, resultdsp;
+
+    rt        = 0x12345678;
+    result    = 0x7FFF7FFF;
+    resultdsp = 0x01;
+
+    __asm
+        ("shll_s.ph %0, %2, 0x0B\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("shll_s.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shll_s_pw.c b/tests/tcg/mips/mips64-dsp/shll_s_pw.c
new file mode 100644
index 0000000..e5190ed
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shll_s_pw.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, dsp;
+    long long result, resultdsp;
+
+    rt        = 0x8765432112345678;
+    result    = 0x800000007fffffff;
+    resultdsp = 1;
+
+    __asm
+        ("shll_s.pw %0, %2, 0x8\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+
+    dsp = (dsp >> 22) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("shll_s.pw wrong\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shll_s_qh.c b/tests/tcg/mips/mips64-dsp/shll_s_qh.c
new file mode 100644
index 0000000..eae0fd9
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shll_s_qh.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, dsp;
+    long long res, resdsp;
+
+    rt = 0x9ba8765433456789;
+    res = 0x80007fff7fff7fff;
+    resdsp = 0x1;
+    __asm
+        ("shll_s.qh %0, %2, 0x3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+
+    dsp = (dsp >> 22) & 0x1;
+
+    if ((dsp != resdsp) || (rd != res)) {
+        printf("shll_s.qh error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shll_s_w.c b/tests/tcg/mips/mips64-dsp/shll_s_w.c
new file mode 100644
index 0000000..5780061
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shll_s_w.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, dsp;
+    long long result, resultdsp;
+
+    rt        = 0x12345678;
+    result    = 0x7FFFFFFF;
+    resultdsp = 0x01;
+
+    __asm
+        ("shll_s.w %0, %2, 0x0B\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("shll_s.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shllv_ob.c b/tests/tcg/mips/mips64-dsp/shllv_ob.c
new file mode 100644
index 0000000..fe9bd4e
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shllv_ob.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, rs, dsp;
+    long long result, resultdsp;
+
+    rt        = 0x8765432112345678;
+    rs = 0x4;
+    result    = 0x7050301020406080;
+    resultdsp = 1;
+
+    __asm
+        ("shllv.ob %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+
+    dsp = (dsp >> 22) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("shllv.ob wrong\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shllv_ph.c b/tests/tcg/mips/mips64-dsp/shllv_ph.c
new file mode 100644
index 0000000..532291f
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shllv_ph.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs        = 0x0B;
+    rt        = 0x12345678;
+    result    = 0xFFFFFFFFA000C000;
+    resultdsp = 1;
+
+    __asm
+        ("shllv.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("shllv.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shllv_pw.c b/tests/tcg/mips/mips64-dsp/shllv_pw.c
new file mode 100644
index 0000000..59bf607
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shllv_pw.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, rs, dsp;
+    long long result, resultdsp;
+
+    rt        = 0x8765432112345678;
+    rs = 0x8;
+    result    = 0x6543210034567800;
+    resultdsp = 1;
+
+    __asm
+        ("shllv.pw %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+
+    dsp = (dsp >> 22) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("shllv.pw wrong\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shllv_qb.c b/tests/tcg/mips/mips64-dsp/shllv_qb.c
new file mode 100644
index 0000000..e49356b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shllv_qb.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs     = 0x03;
+    rt     = 0x87654321;
+    result = 0x38281808;
+    resultdsp = 0x01;
+
+    __asm
+        ("shllv.qb %0, %2, %3\n\t"
+         "rddsp   %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    if (rd != result) {
+        printf("shllv.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shllv_qh.c b/tests/tcg/mips/mips64-dsp/shllv_qh.c
new file mode 100644
index 0000000..2ba3ef1
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shllv_qh.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, rs, dsp;
+    long long result, resultdsp;
+
+    rt        = 0x8765432112345678;
+    rs = 0x4;
+    result    = 0x7650321023406780;
+    resultdsp = 1;
+
+    __asm
+        ("shllv.qh %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+
+    dsp = (dsp >> 22) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("shllv.qh wrong\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shllv_s_ph.c b/tests/tcg/mips/mips64-dsp/shllv_s_ph.c
new file mode 100644
index 0000000..7e69f94
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shllv_s_ph.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs        = 0x0B;
+    rt        = 0x12345678;
+    result    = 0x7FFF7FFF;
+    resultdsp = 0x01;
+
+    __asm
+        ("shllv_s.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("shllv_s.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shllv_s_pw.c b/tests/tcg/mips/mips64-dsp/shllv_s_pw.c
new file mode 100644
index 0000000..215fc80
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shllv_s_pw.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, rs, dsp;
+    long long result, resultdsp;
+
+    rt        = 0x8765432112345678;
+    rs = 0x8;
+    result    = 0x800000007fffffff;
+    resultdsp = 1;
+
+    __asm
+        ("shllv_s.pw %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+
+    dsp = (dsp >> 22) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("shllv_s.pw wrong\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shllv_s_qh.c b/tests/tcg/mips/mips64-dsp/shllv_s_qh.c
new file mode 100644
index 0000000..ff2c868
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shllv_s_qh.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, rs, dsp;
+    long long result, resultdsp;
+
+    rt        = 0x8765432112345678;
+    rs = 0x4;
+    result    = 0x80007fff7fff7fff;
+    resultdsp = 1;
+
+    __asm
+        ("shllv_s.qh %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+
+    dsp = (dsp >> 22) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("shllv_s.qh wrong\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shllv_s_w.c b/tests/tcg/mips/mips64-dsp/shllv_s_w.c
new file mode 100644
index 0000000..5f6af8b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shllv_s_w.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs        = 0x0B;
+    rt        = 0x12345678;
+    result    = 0x7FFFFFFF;
+    resultdsp = 0x01;
+
+    __asm
+        ("shllv_s.w %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt), "r"(rs)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("shllv_s.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shra_ob.c b/tests/tcg/mips/mips64-dsp/shra_ob.c
new file mode 100644
index 0000000..95f0724
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shra_ob.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main()
+{
+    long long rd, rt;
+    long long res;
+
+    rt = 0xbc98756abc654389;
+    res = 0xfbf9f7f6fb0604f8;
+
+    __asm
+        ("shra.ob %0, %1, 0x4\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("shra.ob error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shra_ph.c b/tests/tcg/mips/mips64-dsp/shra_ph.c
new file mode 100644
index 0000000..a2dc014
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shra_ph.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt     = 0x87654321;
+    result = 0xFFFFFFFFF0EC0864;
+
+    __asm
+        ("shra.ph %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("shra.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shra_pw.c b/tests/tcg/mips/mips64-dsp/shra_pw.c
new file mode 100644
index 0000000..693b7d5
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shra_pw.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long res;
+
+    rt = 0x1234567887654321;
+    res = 0x01234567f8765432;
+
+    __asm
+        ("shra.pw %0, %1, 0x4"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("shra.pw error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shra_qh.c b/tests/tcg/mips/mips64-dsp/shra_qh.c
new file mode 100644
index 0000000..89dd370
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shra_qh.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long res;
+
+    rt = 0x8512345654323454;
+
+    res = 0xf851034505430345;
+
+    __asm
+        ("shra.qh %0, %1, 0x4\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("shra.qh error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shra_r_ob.c b/tests/tcg/mips/mips64-dsp/shra_r_ob.c
new file mode 100644
index 0000000..1847094
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shra_r_ob.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main()
+{
+    long long rd, rt;
+    long long res;
+
+    rt = 0xbc98756abc654389;
+    res = 0xfcfaf8f7fc0705f9;
+
+    __asm
+        ("shra_r.ob %0, %1, 0x4\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("shra_r.ob error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shra_r_ph.c b/tests/tcg/mips/mips64-dsp/shra_r_ph.c
new file mode 100644
index 0000000..e0943ad
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shra_r_ph.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt     = 0x87654321;
+    result = 0xFFFFFFFFF0ED0864;
+
+    __asm
+        ("shra_r.ph %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("shra_r.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shra_r_pw.c b/tests/tcg/mips/mips64-dsp/shra_r_pw.c
new file mode 100644
index 0000000..e87a1d3
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shra_r_pw.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long res;
+
+    rt = 0x1234567887654321;
+    res = 0x01234568f8765432;
+
+    __asm
+        ("shra_r.pw %0, %1, 0x4"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("shra_r.pw error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shra_r_qh.c b/tests/tcg/mips/mips64-dsp/shra_r_qh.c
new file mode 100644
index 0000000..cc11dca
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shra_r_qh.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long res;
+
+    rt = 0x8512345654323454;
+    res = 0xf0a2068b0a86068b;
+
+    __asm
+        ("shra_r.qh %0, %1, 0x3\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("shra_r.qh error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shra_r_w.c b/tests/tcg/mips/mips64-dsp/shra_r_w.c
new file mode 100644
index 0000000..36d2c9c
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shra_r_w.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt     = 0x87654321;
+    result = 0xFFFFFFFFF0ECA864;
+
+    __asm
+        ("shra_r.w %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("shra_r.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shrav_ph.c b/tests/tcg/mips/mips64-dsp/shrav_ph.c
new file mode 100644
index 0000000..1b4e983
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shrav_ph.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x03;
+    rt     = 0x87654321;
+    result = 0xFFFFFFFFF0EC0864;
+
+    __asm
+        ("shrav.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    if (rd != result) {
+        printf("shrav.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shrav_pw.c b/tests/tcg/mips/mips64-dsp/shrav_pw.c
new file mode 100644
index 0000000..acec0bc
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shrav_pw.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, rs;
+    long long res;
+
+    rt = 0x1234567887654321;
+    rs = 0x4;
+    res = 0x01234567f8765432;
+
+    __asm
+        ("shrav.pw %0, %1, %2"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+
+    if (rd != res) {
+        printf("shrav.pw error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shrav_qh.c b/tests/tcg/mips/mips64-dsp/shrav_qh.c
new file mode 100644
index 0000000..110891c
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shrav_qh.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, rs;
+    long long res;
+
+    rt = 0x8512345654323454;
+    rs = 0x4;
+    res = 0xf851034505430345;
+
+    __asm
+        ("shrav.qh %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+
+    if (rd != res) {
+        printf("shrav.qh error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shrav_r_ph.c b/tests/tcg/mips/mips64-dsp/shrav_r_ph.c
new file mode 100644
index 0000000..350d529
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shrav_r_ph.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x03;
+    rt     = 0x87654321;
+    result = 0xFFFFFFFFF0ED0864;
+
+    __asm
+        ("shrav_r.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    if (rd != result) {
+        printf("shrav_r.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shrav_r_pw.c b/tests/tcg/mips/mips64-dsp/shrav_r_pw.c
new file mode 100644
index 0000000..1dc3e36
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shrav_r_pw.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, rs;
+    long long res;
+
+    rt = 0x1234567887654321;
+    rs = 0x4;
+    res = 0x01234568f8765432;
+
+    __asm
+        ("shrav_r.pw %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+
+    if (rd != res) {
+        printf("shrav_r.pw error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shrav_r_qh.c b/tests/tcg/mips/mips64-dsp/shrav_r_qh.c
new file mode 100644
index 0000000..65930ea
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shrav_r_qh.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, rs;
+    long long res;
+
+    rt = 0x8512345654323454;
+    rs = 0x3;
+    res = 0xf0a2068b0a86068b;
+
+    __asm
+        ("shrav_r.qh %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+
+    if (rd != res) {
+        printf("shrav_r.qh error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shrav_r_w.c b/tests/tcg/mips/mips64-dsp/shrav_r_w.c
new file mode 100644
index 0000000..3766c72
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shrav_r_w.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x03;
+    rt     = 0x87654321;
+    result = 0xFFFFFFFFF0ECA864;
+
+    __asm
+        ("shrav_r.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    if (rd != result) {
+        printf("shrav_r.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shrl_ob.c b/tests/tcg/mips/mips64-dsp/shrl_ob.c
new file mode 100644
index 0000000..4771a31
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shrl_ob.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long res;
+
+    rt = 0xab76543212345678;
+    res = 0x150e0a0602060a0f;
+
+    __asm
+        ("shrl.ob %0, %1, 0x3\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("shrl.ob error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shrl_qb.c b/tests/tcg/mips/mips64-dsp/shrl_qb.c
new file mode 100644
index 0000000..c0e36db
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shrl_qb.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt     = 0x12345678;
+    result = 0x00010203;
+
+    __asm
+        ("shrl.qb %0, %1, 0x05\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("shrl.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shrl_qh.c b/tests/tcg/mips/mips64-dsp/shrl_qh.c
new file mode 100644
index 0000000..c156246
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shrl_qh.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long res;
+
+    rt = 0x8765679abc543786;
+    res = 0x087606790bc50378;
+
+    __asm
+        ("shrl.qh %0, %1, 0x4\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+
+    if (rd != res) {
+        printf("shrl.qh error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shrlv_ob.c b/tests/tcg/mips/mips64-dsp/shrlv_ob.c
new file mode 100644
index 0000000..5e7e468
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shrlv_ob.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, rs;
+    long long res;
+
+    rt = 0xab76543212345678;
+    rs = 0x3;
+    res = 0x150e0a0602060a0f;
+
+    __asm
+        ("shrlv.ob %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+
+    if (rd != res) {
+        printf("shrlv.ob error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shrlv_qb.c b/tests/tcg/mips/mips64-dsp/shrlv_qb.c
new file mode 100644
index 0000000..5616aa9
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shrlv_qb.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x05;
+    rt     = 0x12345678;
+    result = 0x00010203;
+
+    __asm
+        ("shrlv.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    if (rd != result) {
+        printf("shrlv.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/shrlv_qh.c b/tests/tcg/mips/mips64-dsp/shrlv_qh.c
new file mode 100644
index 0000000..05de2fd
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/shrlv_qh.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, rs;
+    long long res;
+
+    rt = 0x8765679abc543786;
+    rs = 0x4;
+    res = 0x087606790bc50378;
+
+    __asm
+        ("shrlv.qh %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+
+    if (rd != res) {
+        printf("shrlv.qh error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/subq_ph.c b/tests/tcg/mips/mips64-dsp/subq_ph.c
new file mode 100644
index 0000000..6a1b186
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/subq_ph.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0xFFFFFFFF8ACF1357;
+    resultdsp = 0x01;
+
+    __asm
+        ("subq.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("subq.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/subq_pw.c b/tests/tcg/mips/mips64-dsp/subq_pw.c
new file mode 100644
index 0000000..32f96ba
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/subq_pw.c
@@ -0,0 +1,44 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+    rt = 0x123456789ABCDEF0;
+    rs = 0x123456789ABCDEF0;
+    result = 0x0;
+    dspresult = 0x0;
+
+    __asm
+        ("subq.pw %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+         );
+    dspreg = (dspreg >> 20) & 0x1;
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("subq.pw error1\n\t");
+
+        return -1;
+    }
+
+    rt = 0x123456789ABCDEF1;
+    rs = 0x123456789ABCDEF2;
+    result =  0x0000000000000001;
+    dspresult = 0x0;
+
+    __asm
+        ("subq.pw %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+    dspreg = (dspreg >> 20) & 0x1;
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("subq.pw error2\n");
+
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/tests/tcg/mips/mips64-dsp/subq_qh.c b/tests/tcg/mips/mips64-dsp/subq_qh.c
new file mode 100644
index 0000000..76d5f0a
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/subq_qh.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+    rt = 0x123456789ABCDEF0;
+    rs = 0x123456789ABCDEF0;
+    result = 0x0;
+    dspresult = 0x0;
+
+    __asm
+        ("subq.qh %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+    dspreg = (dspreg >> 20) & 0x1;
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("subq.qh error\n\t");
+
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/tests/tcg/mips/mips64-dsp/subq_s_ph.c b/tests/tcg/mips/mips64-dsp/subq_s_ph.c
new file mode 100644
index 0000000..0b162f0
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/subq_s_ph.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0x7FFF1357;
+    resultdsp = 0x01;
+
+    __asm
+        ("subq_s.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("subq_s.ph wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/subq_s_pw.c b/tests/tcg/mips/mips64-dsp/subq_s_pw.c
new file mode 100644
index 0000000..944d63f
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/subq_s_pw.c
@@ -0,0 +1,45 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+    rt = 0x9FFFFFFD9FFFFFFD;
+    rs = 0x4000000080000000;
+    result = 0x7fffffffe0000003;
+    dspresult = 0x1;
+
+    __asm
+        ("subq_s.pw %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+    dspreg = (dspreg >> 20) & 0x1;
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("subq_s.pw error1\n");
+
+        return -1;
+    }
+
+    rt = 0x123456789ABCDEF1;
+    rs = 0x123456789ABCDEF2;
+    result =  0x0000000000000001;
+    /* This time we do not set dspctrl, but it setted in pre-action. */
+    dspresult = 0x1;
+
+    __asm
+        ("subq_s.pw %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+    dspreg = (dspreg >> 20) & 0x1;
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("subq_s.pw error2\n");
+
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/tests/tcg/mips/mips64-dsp/subq_s_qh.c b/tests/tcg/mips/mips64-dsp/subq_s_qh.c
new file mode 100644
index 0000000..d02a459
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/subq_s_qh.c
@@ -0,0 +1,44 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEF0;
+    result = 0x0;
+    dspresult = 0x0;
+
+    __asm
+        ("subq_s.qh %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+    dspreg = (dspreg >> 20) & 0x1;
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("subq_s.qh error1\n");
+
+        return -1;
+    }
+
+    rs = 0x4000000080000000;
+    rt = 0x9FFD00009FFC0000;
+    result =  0x7FFF0000E0040000;
+    dspresult = 0x1;
+
+    __asm
+        ("subq_s.qh %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+        );
+    dspreg = (dspreg >> 20) & 0x1;
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("subq_s.qh error2\n");
+
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/tests/tcg/mips/mips64-dsp/subq_s_w.c b/tests/tcg/mips/mips64-dsp/subq_s_w.c
new file mode 100644
index 0000000..91d32da
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/subq_s_w.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0x7FFFFFFF;
+    resultdsp = 0x01;
+
+    __asm
+        ("subq_s.w %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("subq_s.w wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/subu_ob.c b/tests/tcg/mips/mips64-dsp/subu_ob.c
new file mode 100644
index 0000000..f670967
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/subu_ob.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+    rs = 0x6F6F6F6F6F6F6F6F;
+    rt = 0x5E5E5E5E5E5E5E5E;
+    result = 0x1111111111111111;
+    dspresult = 0x0;
+
+    __asm
+        ("subu.ob %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+         );
+
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("subu.ob error\n");
+
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/tests/tcg/mips/mips64-dsp/subu_qb.c b/tests/tcg/mips/mips64-dsp/subu_qb.c
new file mode 100644
index 0000000..9eb80df
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/subu_qb.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0xFFFFFFFF8BCF1357;
+    resultdsp = 0x01;
+
+    __asm
+        ("subu.qb %0, %2, %3\n\t"
+         "rddsp   %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("subu.qb wrong\n");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/subu_s_ob.c b/tests/tcg/mips/mips64-dsp/subu_s_ob.c
new file mode 100644
index 0000000..5df64e5
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/subu_s_ob.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dspreg, result, dspresult;
+    rs = 0x12345678ABCDEF0;
+    rt = 0x12345678ABCDEF1;
+    result = 0x00000000000;
+    dspresult = 0x01;
+
+    __asm
+        ("subu_s.ob %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dspreg)
+         : "r"(rs), "r"(rt)
+         );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("subu_s.ob error\n\t");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/subu_s_qb.c b/tests/tcg/mips/mips64-dsp/subu_s_qb.c
new file mode 100644
index 0000000..9de76f4
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/subu_s_qb.c
@@ -0,0 +1,27 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0x00001357;
+    resultdsp = 0x01;
+
+    __asm
+        ("subu_s.qb %0, %2, %3\n\t"
+         "rddsp   %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    if ((dsp != resultdsp) || (rd  != result)) {
+        printf("subu_s_qb wrong");
+
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dsp/wrdsp.c b/tests/tcg/mips/mips64-dsp/wrdsp.c
new file mode 100644
index 0000000..3033fd8
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/wrdsp.c
@@ -0,0 +1,48 @@
+#include "io.h"
+
+int main(void)
+{
+    long long dsp_i, dsp_o;
+    long long ccond_i, outflag_i, efi_i, c_i, scount_i, pos_i;
+    long long ccond_o, outflag_o, efi_o, c_o, scount_o, pos_o;
+    long long ccond_r, outflag_r, efi_r, c_r, scount_r, pos_r;
+
+    ccond_i = 0x000000BC;/* 4 */
+    outflag_i = 0x0000001B;/* 3 */
+    efi_i = 0x00000001;/* 5 */
+    c_i = 0x00000001;/* 2 */
+    scount_i = 0x0000000F;/* 1 */
+    pos_i = 0x0000000C;/* 0 */
+
+    dsp_i = (ccond_i << 24) | (outflag_i << 16) | (efi_i << 14) | (c_i << 13)
+            | (scount_i << 7) | pos_i;
+
+    ccond_r = ccond_i;
+    outflag_r = outflag_i;
+    efi_r = efi_i;
+    c_r = c_i;
+    scount_r = scount_i;
+    pos_r = pos_i;
+
+    __asm
+        ("wrdsp %1, 0x3F\n\t"
+         "rddsp %0, 0x3F\n\t"
+         : "=r"(dsp_o)
+         : "r"(dsp_i)
+        );
+
+    ccond_o = (dsp_o >> 24) & 0xFF;
+    outflag_o = (dsp_o >> 16) & 0xFF;
+    efi_o = (dsp_o >> 14) & 0x01;
+    c_o = (dsp_o >> 14) & 0x01;
+    scount_o = (dsp_o >> 7) & 0x3F;
+    pos_o = dsp_o & 0x1F;
+
+    if ((ccond_o != ccond_r) || (outflag_o != outflag_r) || (efi_o != efi_r) \
+            || (c_o != c_r) || (scount_o != scount_r) || (pos_o != pos_r)) {
+        printf("wrddsp wrong\n");
+
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/.directory b/tests/tcg/mips/mips64-dspr2/.directory
new file mode 100644
index 0000000..c75a914
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/.directory
@@ -0,0 +1,2 @@
+[Dolphin]
+Timestamp=2012,8,3,16,41,52
diff --git a/tests/tcg/mips/mips64-dspr2/Makefile b/tests/tcg/mips/mips64-dspr2/Makefile
new file mode 100644
index 0000000..69f92be
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/Makefile
@@ -0,0 +1,117 @@
+CROSS_COMPILE	?= mips64el-unknown-linux-gnu-
+
+SIM = qemu-system-mips64el
+SIMFLAGS = -nographic -cpu mips64dspr2 -kernel
+
+AS      = $(CROSS_COMPILE)as
+LD      = $(CROSS_COMPILE)ld
+CC      = $(CROSS_COMPILE)gcc
+AR      = $(CROSS_COMPILE)ar
+NM      = $(CROSS_COMPILE)nm
+STRIP       = $(CROSS_COMPILE)strip
+RANLIB      = $(CROSS_COMPILE)ranlib
+OBJCOPY     = $(CROSS_COMPILE)objcopy
+OBJDUMP     = $(CROSS_COMPILE)objdump
+
+VECTORS_OBJ ?= ./head.o ./printf.o
+
+HEAD_FLAGS ?= -nostdinc -mabi=64 -G 0 -mno-abicalls -fno-pic -pipe \
+              -msoft-float -march=mips64 -Wa,-mips64 -Wa,--trap \
+              -msym32 -DKBUILD_64BIT_SYM32 -I./
+
+CFLAGS ?= -nostdinc -mabi=64 -G 0 -mno-abicalls -fno-pic -fno-builtin  \
+          -pipe -march=mips64r2 -mgp64 -mdspr2 -static -Wa,--trap -msym32 \
+          -DKBUILD_64BIT_SYM32 -I./
+
+LDFLAGS = -T./mips_boot.lds -L./
+FLAGS = -nostdlib -mabi=64 -march=mips64r2 -mgp64 -mdspr2
+
+TESTCASES = absq_s_qb.tst
+TESTCASES += addqh_ph.tst
+TESTCASES += addqh_r_ph.tst
+TESTCASES += addqh_r_w.tst
+TESTCASES += addqh_w.tst
+#TESTCASES += adduh_ob.tst
+TESTCASES += adduh_qb.tst
+#TESTCASES += adduh_r_ob.tst
+TESTCASES += adduh_r_qb.tst
+TESTCASES += addu_ph.tst
+#TESTCASES += addu_qh.tst
+TESTCASES += addu_s_ph.tst
+#TESTCASES += addu_s_qh.tst
+TESTCASES += append.tst
+TESTCASES += balign.tst
+#TESTCASES += cmpgdu_eq_ob.tst
+TESTCASES += cmpgdu_eq_qb.tst
+#TESTCASES += cmpgdu_le_ob.tst
+TESTCASES += cmpgdu_le_qb.tst
+#TESTCASES += cmpgdu_lt_ob.tst
+TESTCASES += cmpgdu_lt_qb.tst
+#TESTCASES += dbalign.tst
+TESTCASES += dpaqx_sa_w_ph.tst
+TESTCASES += dpaqx_s_w_ph.tst
+TESTCASES += dpa_w_ph.tst
+#TESTCASES += dpa_w_qh.tst
+TESTCASES += dpax_w_ph.tst
+TESTCASES += dpsqx_sa_w_ph.tst
+TESTCASES += dpsqx_s_w_ph.tst
+TESTCASES += dps_w_ph.tst
+#TESTCASES += dps_w_qh.tst
+TESTCASES += dpsx_w_ph.tst
+TESTCASES += muleq_s_w_phl.tst
+TESTCASES += mul_ph.tst
+TESTCASES += mulq_rs_w.tst
+TESTCASES += mulq_s_ph.tst
+TESTCASES += mulq_s_w.tst
+TESTCASES += mulsaq_s_w_ph.tst
+TESTCASES += mulsa_w_ph.tst
+TESTCASES += mul_s_ph.tst
+TESTCASES += precr_qb_ph.tst
+TESTCASES += precr_sra_ph_w.tst
+TESTCASES += precr_sra_r_ph_w.tst
+TESTCASES += prepend.tst
+TESTCASES += shra_qb.tst
+TESTCASES += shra_r_qb.tst
+#TESTCASES += shrav_ob.tst
+TESTCASES += shrav_qb.tst
+#TESTCASES += shrav_r_ob.tst
+TESTCASES += shrav_r_qb.tst
+TESTCASES += shrl_ph.tst
+TESTCASES += shrlv_ph.tst
+TESTCASES += subqh_ph.tst
+TESTCASES += subqh_r_ph.tst
+TESTCASES += subqh_r_w.tst
+TESTCASES += subqh_w.tst
+#TESTCASES += subuh_ob.tst
+TESTCASES += subuh_qb.tst
+#TESTCASES += subuh_r_ob.tst
+TESTCASES += subuh_r_qb.tst
+TESTCASES += subu_ph.tst
+#TESTCASES += subu_qh.tst
+TESTCASES += subu_s_ph.tst
+#TESTCASES += subu_s_qh.tst
+
+all: build
+
+head.o : head.S
+	$(Q)$(CC) $(HEAD_FLAGS) -D"STACK_TOP=0xffffffff80200000" -c $< -o $@
+
+%.o  : %.S
+	$(CC) $(CFLAGS) -c $< -o $@
+
+%.o  : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
+%.tst: %.o $(VECTORS_OBJ)
+	$(CC) $(VECTORS_OBJ) $(FLAGS) $(LDFLAGS) $< -o $@
+
+build: $(VECTORS_OBJ) $(MIPSSOC_LIB) $(TESTCASES)
+
+check:  $(VECTORS_OBJ) $(MIPSSOC_LIB) $(TESTCASES)
+	@for case in $(TESTCASES); do \
+		echo $(SIM) $(SIMFLAGS) ./$$case; \
+		$(SIM) $(SIMFLAGS) ./$$case & (sleep 1; killall $(SIM)); \
+	done
+
+clean:
+	$(Q)rm -f *.o *.tst *.a
diff --git a/tests/tcg/mips/mips64-dspr2/absq_s_qb.c b/tests/tcg/mips/mips64-dspr2/absq_s_qb.c
new file mode 100644
index 0000000..f7aec3e
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/absq_s_qb.c
@@ -0,0 +1,42 @@
+#include "io.h"
+int main()
+{
+    long long input, result, dsp;
+    long long hope;
+
+    input = 0x701BA35E;
+    hope  = 0x701B5D5E;
+
+    __asm
+        ("absq_s.qb %0, %1\n\t"
+         : "=r"(result)
+         : "r"(input)
+        );
+    if (result != hope) {
+        printf("absq_s.qb error\n");
+        return -1;
+    }
+
+    input = 0x801BA35E;
+    hope  = 0x7F1B5D5E;
+
+    __asm
+        ("absq_s.qb %0, %2\n\t"
+         "rddsp %1\n\t"
+         : "=r"(result), "=r"(dsp)
+         : "r"(input)
+        );
+    dsp = dsp >> 20;
+    dsp &= 0x01;
+    if (result != hope) {
+        printf("absq_s.qb error\n");
+        return -1;
+    }
+
+    if (dsp != 1) {
+        printf("absq_s.qb error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/addqh_ph.c b/tests/tcg/mips/mips64-dspr2/addqh_ph.c
new file mode 100644
index 0000000..01d5333
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/addqh_ph.c
@@ -0,0 +1,35 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x706A13FE;
+    rt     = 0x13065174;
+    result = 0x41B832B9;
+    __asm
+        ("addqh.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (result != rd) {
+        printf("addqh.ph error!\n");
+        return -1;
+    }
+
+    rs     = 0x01000100;
+    rt     = 0x02000100;
+    result = 0x01800100;
+    __asm
+        ("addqh.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (result != rd) {
+        printf("addqh.ph error!\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/addqh_r_ph.c b/tests/tcg/mips/mips64-dspr2/addqh_r_ph.c
new file mode 100644
index 0000000..08112c3
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/addqh_r_ph.c
@@ -0,0 +1,35 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x706A13FE;
+    rt     = 0x13065174;
+    result = 0x41B832B9;
+    __asm
+        ("addqh_r.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addqh_r.ph error\n");
+        return -1;
+    }
+
+    rs     = 0x01000100;
+    rt     = 0x02000100;
+    result = 0x01800100;
+    __asm
+        ("addqh_r.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addqh_r.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/addqh_r_w.c b/tests/tcg/mips/mips64-dspr2/addqh_r_w.c
new file mode 100644
index 0000000..d324dec
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/addqh_r_w.c
@@ -0,0 +1,38 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x00000010;
+    rt     = 0x00000001;
+    result = 0x00000009;
+
+    __asm
+        ("addqh_r.w  %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != result) {
+        printf("addqh_r.w error!\n");
+        return -1;
+    }
+    rs     = 0xFFFFFFFE;
+    rt     = 0x00000001;
+    result = 0x00000000;
+
+    __asm
+        ("addqh_r.w  %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != result) {
+        printf("addqh_r.w error!\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/addqh_w.c b/tests/tcg/mips/mips64-dspr2/addqh_w.c
new file mode 100644
index 0000000..78559e6
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/addqh_w.c
@@ -0,0 +1,39 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x00000010;
+    rt     = 0x00000001;
+    result = 0x00000008;
+
+    __asm
+        ("addqh.w  %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != result) {
+        printf("addqh.w wrong\n");
+        return -1;
+    }
+
+    rs     = 0xFFFFFFFE;
+    rt     = 0x00000001;
+    result = 0xFFFFFFFFFFFFFFFF;
+
+    __asm
+        ("addqh.w  %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+
+    if (rd != result) {
+        printf("addqh.w wrong\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/addu_ph.c b/tests/tcg/mips/mips64-dspr2/addu_ph.c
new file mode 100644
index 0000000..c269178
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/addu_ph.c
@@ -0,0 +1,35 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x00FF00FF;
+    rt     = 0x00010001;
+    result = 0x01000100;
+    __asm
+        ("addu.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addu.ph error\n");
+        return -1;
+    }
+
+    rs     = 0xFFFF1111;
+    rt     = 0x00020001;
+    result = 0x00011112;
+    __asm
+        ("addu.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addu.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/addu_qh.c b/tests/tcg/mips/mips64-dspr2/addu_qh.c
new file mode 100644
index 0000000..858e314
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/addu_qh.c
@@ -0,0 +1,41 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+    rs = 0x123456787FFF0000;
+    rt = 0x1111111180000000;
+    result = 0x23456789FFFF0000;
+    dspresult = 0x0;
+
+    __asm("addu.qh %0, %2, %3\n\t"
+          "rddsp %1\n\t"
+          : "=r"(rd), "=r"(dspreg)
+          : "r"(rs), "r"(rt)
+         );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("addu.qh error\n");
+        return -1;
+    }
+
+    rs = 0x123456787FFF0000;
+    rt = 0x1111111180020000;
+    result = 0x23456789FFFF0000;
+    dspresult = 0x01;
+
+    __asm("addu.qh %0, %2, %3\n\t"
+          "rddsp %1\n\t"
+          : "=r"(rd), "=r"(dspreg)
+          : "r"(rs), "r"(rt)
+         );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("addu.qh overflow error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/addu_s_ph.c b/tests/tcg/mips/mips64-dspr2/addu_s_ph.c
new file mode 100644
index 0000000..d91d8aa
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/addu_s_ph.c
@@ -0,0 +1,35 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x00FE00FE;
+    rt     = 0x00020001;
+    result = 0x010000FF;
+    __asm
+        ("addu_s.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addu_s.ph error\n");
+        return -1;
+    }
+
+    rs     = 0xFFFF1111;
+    rt     = 0x00020001;
+    result = 0xFFFFFFFFFFFF1112;
+    __asm
+        ("addu_s.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("addu_s.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/addu_s_qh.c b/tests/tcg/mips/mips64-dspr2/addu_s_qh.c
new file mode 100644
index 0000000..2999900
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/addu_s_qh.c
@@ -0,0 +1,41 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+    rs = 0x123456787FFF0000;
+    rt = 0x1111111180000000;
+    result = 0x23456789FFFF0000;
+    dspresult = 0x0;
+
+    __asm("addu_s.qh %0, %2, %3\n\t"
+          "rddsp %1\n\t"
+          : "=r"(rd), "=r"(dspreg)
+          : "r"(rs), "r"(rt)
+         );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("addu_s.qh error\n");
+        return -1;
+    }
+
+    rs = 0x12345678FFFF0000;
+    rt = 0x11111111000F0000;
+    result = 0x23456789FFFF0000;
+    dspresult = 0x01;
+
+    __asm("addu_s.qh %0, %2, %3\n\t"
+          "rddsp %1\n\t"
+          : "=r"(rd), "=r"(dspreg)
+          : "r"(rs), "r"(rt)
+         );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("addu_s.qh error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/adduh_ob.c b/tests/tcg/mips/mips64-dspr2/adduh_ob.c
new file mode 100644
index 0000000..a8d5a6d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/adduh_ob.c
@@ -0,0 +1,21 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result;
+    rs = 0xFF987CDEBCEF2356;
+    rt = 0xFF987CDEBCEF2354;
+    result = 0xFF987CDEBCEF2355;
+
+    __asm("adduh.ob %0, %1, %2\n\t"
+          : "=r"(rd)
+          : "r"(rs), "r"(rt)
+         );
+
+    if (rd != result) {
+        printf("adduh.ob error\n\t");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/adduh_qb.c b/tests/tcg/mips/mips64-dspr2/adduh_qb.c
new file mode 100644
index 0000000..796b409
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/adduh_qb.c
@@ -0,0 +1,35 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0xFF0055AA;
+    rt     = 0x0113421B;
+    result = 0xffffffff80094B62;
+    __asm
+        ("adduh.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("adduh.qb error\n");
+        return -1;
+    }
+    rs     = 0xFFFF0FFF;
+    rt     = 0x00010111;
+    result = 0x7F800888;
+
+    __asm
+        ("adduh.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("adduh.qb error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/adduh_r_ob.c b/tests/tcg/mips/mips64-dspr2/adduh_r_ob.c
new file mode 100644
index 0000000..57a9874
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/adduh_r_ob.c
@@ -0,0 +1,21 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result;
+    rs = 0xFF987CDEBCEF2356;
+    rt = 0xFF987CDEBCEF2355;
+    result = 0xFF987CDEBCEF2356;
+
+    __asm("adduh_r.ob %0, %1, %2\n\t"
+          : "=r"(rd)
+          : "r"(rs), "r"(rt)
+         );
+
+    if (rd != result) {
+        printf("adduh_r.ob error\n\t");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/adduh_r_qb.c b/tests/tcg/mips/mips64-dspr2/adduh_r_qb.c
new file mode 100644
index 0000000..ae65fa5
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/adduh_r_qb.c
@@ -0,0 +1,35 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0xFF0055AA;
+    rt     = 0x01112211;
+    result = 0xffffffff80093C5E;
+    __asm
+        ("adduh_r.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("adduh_r.qb error\n");
+        return -1;
+    }
+
+    rs     = 0xFFFF0FFF;
+    rt     = 0x00010111;
+    result = 0xffffffff80800888;
+    __asm
+        ("adduh_r.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("adduh_r.qb error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/append.c b/tests/tcg/mips/mips64-dspr2/append.c
new file mode 100644
index 0000000..68a7cec
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/append.c
@@ -0,0 +1,35 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long result;
+
+    rs     = 0xFF0055AA;
+    rt     = 0x0113421B;
+    result = 0x02268436;
+    __asm
+        ("append %0, %1, 0x01\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    if (rt != result) {
+        printf("append error\n");
+        return -1;
+    }
+
+    rs     = 0xFFFF0FFF;
+    rt     = 0x00010111;
+    result = 0x0010111F;
+    __asm
+        ("append %0, %1, 0x04\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    if (rt != result) {
+        printf("append error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/balign.c b/tests/tcg/mips/mips64-dspr2/balign.c
new file mode 100644
index 0000000..7fbe815
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/balign.c
@@ -0,0 +1,35 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long result;
+
+    rs     = 0xFF0055AA;
+    rt     = 0x0113421B;
+    result = 0x13421BFF;
+    __asm
+        ("balign %0, %1, 0x01\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    if (rt != result) {
+        printf("balign error\n");
+        return -1;
+    }
+
+    rs     = 0xFFFF0FFF;
+    rt     = 0x00010111;
+    result = 0x11FFFF0F;
+    __asm
+        ("balign %0, %1, 0x03\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    if (rt != result) {
+        printf("balign error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c b/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c
new file mode 100644
index 0000000..135328a
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEFF;
+    result = 0xFE;
+    dspresult = 0xFE;
+
+    __asm("cmpgdu.eq.ob %0, %2, %3\n\t"
+          "rddsp %1"
+          : "=r"(rd), "=r"(dspreg)
+          : "r"(rs), "r"(rt)
+         );
+
+    dspreg = ((dspreg >> 24) & 0xFF);
+
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("cmpgdu.eq.ob error\n");
+        return -1;
+    }
+
+   return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c b/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c
new file mode 100644
index 0000000..c63f648
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c
@@ -0,0 +1,41 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long dsp;
+    long long result;
+
+    rs         = 0x11777066;
+    rt         = 0x55AA70FF;
+    result     = 0x02;
+    __asm
+        ("cmpgdu.eq.qb %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    if ((rd != result) || (dsp != result)) {
+        printf("cmpgdu.eq.qb error\n");
+        return -1;
+    }
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x0F;
+    __asm
+        ("cmpgdu.eq.qb %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+
+    if ((rd != result) || (dsp != result)) {
+        printf("cmpgdu.eq.qb error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c b/tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c
new file mode 100644
index 0000000..c1440b1
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEFF;
+    dspresult = 0xFF;
+    result = 0xFF;
+
+    __asm("cmpgdu.le.ob %0, %2, %3\n\t"
+          "rddsp %1"
+          : "=r"(rd), "=r"(dspreg)
+          : "r"(rs), "r"(rt)
+         );
+
+    dspreg = ((dspreg >> 24) & 0xFF);
+
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("cmpgdu.le.ob error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c b/tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c
new file mode 100644
index 0000000..f0a60ea
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c
@@ -0,0 +1,48 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long dsp;
+    long long result;
+
+    rs         = 0x11777066;
+    rt         = 0x55AA70FF;
+    result     = 0x0F;
+    __asm
+        ("cmpgdu.le.qb %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    if (rd  != result) {
+        printf("cmpgdu.le.qb error\n");
+        return -1;
+    }
+    if (dsp != result) {
+        printf("cmpgdu.le.qb error\n");
+        return -1;
+    }
+
+    rs     = 0x11777066;
+    rt     = 0x11707066;
+    result = 0x0B;
+    __asm
+        ("cmpgdu.le.qb %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    if (rd  != result) {
+        printf("cmpgdu.le.qb error\n");
+        return -1;
+    }
+    if (dsp != result) {
+        printf("cmpgdu.le.qb error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c b/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c
new file mode 100644
index 0000000..87e7028
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result, dspreg, dspresult;
+
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEFF;
+    dspresult = 0x01;
+    result = 0x01;
+
+    __asm("cmpgdu.lt.ob %0, %2, %3\n\t"
+          "rddsp %1"
+          : "=r"(rd), "=r"(dspreg)
+          : "r"(rs), "r"(rt)
+         );
+
+    dspreg = ((dspreg >> 24) & 0xFF);
+
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("cmpgdu.lt.ob error\n");
+        return -1;
+    }
+
+   return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c b/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c
new file mode 100644
index 0000000..a71e4e3
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c
@@ -0,0 +1,48 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long dsp;
+    long long result;
+
+    rs         = 0x11777066;
+    rt         = 0x55AA70FF;
+    result     = 0x0D;
+    __asm
+        ("cmpgdu.lt.qb %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    if (rd  != result) {
+        printf("cmpgdu.lt.qb error\n");
+        return -1;
+    }
+    if (dsp != result) {
+        printf("cmpgdu.lt.qb error\n");
+        return -1;
+    }
+
+    rs     = 0x11777066;
+    rt     = 0x11777066;
+    result = 0x00;
+    __asm
+        ("cmpgdu.lt.qb %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 24) & 0x0F;
+    if (rd  != result) {
+        printf("cmpgdu.lt.qb error\n");
+        return -1;
+    }
+    if (dsp != result) {
+        printf("cmpgdu.lt.qb error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/dbalign.c b/tests/tcg/mips/mips64-dspr2/dbalign.c
new file mode 100644
index 0000000..dbc40d5
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/dbalign.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rt, rs;
+    long long res;
+    rt = 0x1234567887654321;
+    rs = 0xabcd1234abcd1234;
+
+    res = 0x34567887654321ab;
+
+    asm ("dbalign %0, %1, 0x1\n"
+         : "=r"(rt)
+         : "r"(rs)
+        );
+
+    if (rt != res) {
+        printf("dbalign error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/dpa_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpa_w_ph.c
new file mode 100644
index 0000000..a634d10
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/dpa_w_ph.c
@@ -0,0 +1,32 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long ach = 5, acl = 5;
+    long long resulth, resultl;
+
+    rs     = 0x00FF00FF;
+    rt     = 0x00010002;
+    resulth = 0x05;
+    resultl = 0x0302;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpa.w.ph $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    if (ach != resulth) {
+        printf("dpa.w.ph error\n");
+        return -1;
+    }
+    if (acl != resultl) {
+        printf("dpa.w.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/dpa_w_qh.c b/tests/tcg/mips/mips64-dspr2/dpa_w_qh.c
new file mode 100644
index 0000000..1411e44
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/dpa_w_qh.c
@@ -0,0 +1,56 @@
+#include"io.h"
+int main(void)
+{
+    long long rt, rs;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resh, resl;
+
+    achi = 0x1;
+    acli = 0x1;
+
+    rs = 0x0001000100010001;
+    rt = 0x0002000200020002;
+
+    resh = 0x1;
+    resl = 0x9;
+
+    asm("mthi %2, $ac1\t\n"
+        "mtlo %3, $ac1\t\n"
+        "dpa.w.qh $ac1, %4, %5\t\n"
+        "mfhi %0, $ac1\t\n"
+        "mflo %1, $ac1\t\n"
+        : "=r"(acho), "=r"(aclo)
+        : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+       );
+
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 dpa.w.qh error\n");
+        return -1;
+    }
+
+
+    achi = 0xffffffff;
+    acli = 0xaaaaaaaa;
+
+    rs = 0xaaaabbbbccccdddd;
+    rt = 0x7777888899996666;
+
+    resh = 0xffffffffffffffff;
+    resl = 0x320cdf02;
+
+    asm("mthi %2, $ac1\t\n"
+        "mtlo %3, $ac1\t\n"
+        "dpa.w.qh $ac1, %4, %5\t\n"
+        "mfhi %0, $ac1\t\n"
+        "mflo %1, $ac1\t\n"
+        : "=r"(acho), "=r"(aclo)
+        : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+       );
+    if ((acho != resh) || (aclo != resl)) {
+        printf("2 dpa.w.qh error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c
new file mode 100644
index 0000000..5ed9988
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c
@@ -0,0 +1,74 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rs, rt, dsp;
+    long long ach = 5, acl = 5;
+    long long resulth, resultl, resultdsp;
+
+    rs     = 0x800000FF;
+    rt     = 0x00018000;
+    resulth = 0x05;
+    resultl = 0xFFFFFFFF80000202;
+    resultdsp = 0x01;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpaqx_s.w.ph $ac1, %3, %4\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x01;
+    if (dsp != resultdsp) {
+        printf("dpaqx_s.w.ph error\n");
+        return -1;
+    }
+    if (ach != resulth) {
+        printf("dpaqx_s.w.ph error\n");
+        return -1;
+    }
+    if (acl != resultl) {
+        printf("dpaqx_s.w.ph error\n");
+        return -1;
+    }
+
+    ach    = 5;
+    acl    = 5;
+    rs     = 0x00FF00FF;
+    rt     = 0x00010002;
+    resulth = 0x05;
+    resultl = 0x05FF;
+    /***********************************************************
+     * Because of we set outflag at last time, although this
+     * time we set nothing, but it is stay the last time value.
+     **********************************************************/
+    resultdsp = 0x01;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpaqx_s.w.ph $ac1, %3, %4\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x01;
+    if (dsp != resultdsp) {
+        printf("dpaqx_s.w.ph error\n");
+        return -1;
+    }
+    if (ach != resulth) {
+        printf("dpaqx_s.w.ph error\n");
+        return -1;
+    }
+    if (acl != resultl) {
+        printf("dpaqx_s.w.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c
new file mode 100644
index 0000000..881ee91
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c
@@ -0,0 +1,42 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rs, rt, dsp;
+    long long ach = 5, acl = 5;
+    long long resulth, resultl, resultdsp;
+
+    rs     = 0x00FF00FF;
+    rt     = 0x00010002;
+    resulth = 0x00;
+    resultl = 0x7fffffff;
+    resultdsp = 0x01;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpaqx_sa.w.ph $ac1, %3, %4\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+
+    dsp = (dsp >> 17) & 0x01;
+    if (dsp != resultdsp) {
+        printf("dpaqx_sa.w.ph error\n");
+        return -1;
+    }
+
+    if (ach != resulth) {
+        printf("dpaqx_sa.w.ph error\n");
+        return -1;
+    }
+
+    if (acl != resultl) {
+        printf("dpaqx_sa.w.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/dpax_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpax_w_ph.c
new file mode 100644
index 0000000..9d595fc
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/dpax_w_ph.c
@@ -0,0 +1,32 @@
+#include"io.h"
+
+int main(void)
+{
+    long rs, rt;
+    long ach = 5, acl = 5;
+    long resulth, resultl;
+
+    rs     = 0x00FF00FF;
+    rt     = 0x00010002;
+    resulth = 0x05;
+    resultl = 0x0302;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpax.w.ph $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    if (ach != resulth) {
+        printf("dpax.w.ph error\n");
+        return -1;
+    }
+    if (acl != resultl) {
+        printf("dpax.w.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/dps_w_ph.c b/tests/tcg/mips/mips64-dspr2/dps_w_ph.c
new file mode 100644
index 0000000..99f292e
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/dps_w_ph.c
@@ -0,0 +1,28 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long ach = 5, acl = 5;
+    long long resulth, resultl;
+
+    rs     = 0x00FF00FF;
+    rt     = 0x00010002;
+    resulth = 0x04;
+    resultl = 0xFFFFFFFFFFFFFFD08;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dps.w.ph $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    if (ach != resulth || acl != resultl) {
+        printf("dps.w.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/dps_w_qh.c b/tests/tcg/mips/mips64-dspr2/dps_w_qh.c
new file mode 100644
index 0000000..61277eb
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/dps_w_qh.c
@@ -0,0 +1,55 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long achi, acli;
+    long long acho, aclo;
+    long long resh, resl;
+
+    rs = 0x0000000100000001;
+    rt = 0x0000000200000002;
+    achi = 0x1;
+    acli = 0x8;
+
+    resh = 0x1;
+    resl = 0x4;
+
+    asm ("mthi %2, $ac1\t\n"
+         "mtlo %3, $ac1\t\n"
+         "dps.w.qh $ac1, %4, %5\t\n"
+         "mfhi %0, $ac1\t\n"
+         "mflo %1, $ac1\t\n"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 dps.w.qh error\n");
+        return -1;
+    }
+
+    rs = 0xaaaabbbbccccdddd;
+    rt = 0xaaaabbbbccccdddd;
+
+    achi = 0x88888888;
+    achi = 0x55555555;
+
+    resh = 0xfffffffff7777777;
+    resl = 0x0a38b181;
+
+    asm ("mthi %2, $ac1\t\n"
+         "mtlo %3, $ac1\t\n"
+         "dps.w.qh $ac1, %4, %5\t\n"
+         "mfhi %0, $ac1\t\n"
+         "mflo %1, $ac1\t\n"
+         : "=r"(acho), "=r"(aclo)
+         : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+        );
+
+    if ((acho != resh) || (aclo != resl)) {
+        printf("1 dps.w.qh error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c
new file mode 100644
index 0000000..44be535
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c
@@ -0,0 +1,31 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rs, rt, dsp;
+    long long ach = 5, acl = 5;
+    long long resulth, resultl, resultdsp;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x04;
+    resultl = 0xFFFFFFFFAEA3E09B;
+    resultdsp = 0x00;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsqx_s.w.ph $ac1, %3, %4\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x01;
+    if (dsp != resultdsp || ach != resulth || acl != resultl) {
+        printf("dpsqx_s.w.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c
new file mode 100644
index 0000000..6b2e6d1
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c
@@ -0,0 +1,30 @@
+#include"io.h"
+int main()
+{
+    long long rs, rt, dsp;
+    long long ach = 5, acl = 5;
+    long long resulth, resultl, resultdsp;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x00;
+    resultl = 0x7FFFFFFF;
+    resultdsp = 0x01;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsqx_sa.w.ph $ac1, %3, %4\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         "rddsp %2\n\t"
+         : "+r"(ach), "+r"(acl), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 17) & 0x01;
+    if (dsp != resultdsp || ach != resulth || acl != resultl) {
+        printf("dpsqx_sa.w.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c b/tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c
new file mode 100644
index 0000000..b6291b5
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c
@@ -0,0 +1,28 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long ach = 5, acl = 5;
+    long long resulth, resultl;
+
+    rs      = 0xBC0123AD;
+    rt      = 0x01643721;
+    resulth = 0x04;
+    resultl = 0xFFFFFFFFD751F050;
+    __asm
+        ("mthi  %0, $ac1\n\t"
+         "mtlo  %1, $ac1\n\t"
+         "dpsx.w.ph $ac1, %2, %3\n\t"
+         "mfhi  %0, $ac1\n\t"
+         "mflo  %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    if (ach != resulth || acl != resultl) {
+        printf("dpsx.w.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/head.S b/tests/tcg/mips/mips64-dspr2/head.S
new file mode 100644
index 0000000..e97da50
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/head.S
@@ -0,0 +1,10 @@
+/*
+ *  Startup Code for MIPS64 CPU-core
+ *
+ */
+.text
+.globl _start
+.align 4
+_start:
+    jal    main
+
diff --git a/tests/tcg/mips/mips64-dspr2/io.h b/tests/tcg/mips/mips64-dspr2/io.h
new file mode 100644
index 0000000..b7db61d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/io.h
@@ -0,0 +1,22 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+extern int printf(const char *fmt, ...);
+extern unsigned long get_ticks(void);
+
+#define _read(source)                \
+({ unsigned long __res;                \
+    __asm__ __volatile__(            \
+        "mfc0\t%0, " #source "\n\t"    \
+        : "=r" (__res));        \
+    __res;                    \
+})
+
+#define __read(source)                \
+({ unsigned long __res;                \
+    __asm__ __volatile__(            \
+        "move\t%0, " #source "\n\t"    \
+        : "=r" (__res));        \
+    __res;                    \
+})
+
+#endif
diff --git a/tests/tcg/mips/mips64-dspr2/mips_boot.lds b/tests/tcg/mips/mips64-dspr2/mips_boot.lds
new file mode 100644
index 0000000..bd7c0c0
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/mips_boot.lds
@@ -0,0 +1,31 @@
+OUTPUT_ARCH(mips)
+SECTIONS
+{
+    . = 0xffffffff80100000;
+    . = ALIGN((1 << 13));
+    .text :
+    {
+        *(.text)
+        *(.rodata)
+        *(.rodata.*)
+    }
+
+    __init_begin = .;
+    . = ALIGN((1 << 12));
+    .init.text : AT(ADDR(.init.text) - 0)
+    {
+        *(.init.text)
+    }
+    .init.data : AT(ADDR(.init.data) - 0)
+    {
+        *(.init.data)
+    }
+    . = ALIGN((1 << 12));
+    __init_end = .;
+
+    . = ALIGN((1 << 13));
+    .data :
+    {
+        *(.data)
+    }
+}
diff --git a/tests/tcg/mips/mips64-dspr2/mul_ph.c b/tests/tcg/mips/mips64-dspr2/mul_ph.c
new file mode 100644
index 0000000..9b8e80f
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/mul_ph.c
@@ -0,0 +1,26 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x03FB1234;
+    rt = 0x0BCC4321;
+    result = 0xF504F4B4;
+    resultdsp = 1;
+
+    __asm
+        ("mul.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    if (rd  != result || dsp != resultdsp) {
+        printf("mul.ph wrong\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/mul_s_ph.c b/tests/tcg/mips/mips64-dspr2/mul_s_ph.c
new file mode 100644
index 0000000..233c484
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/mul_s_ph.c
@@ -0,0 +1,26 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x03FB1234;
+    rt = 0x0BCC4321;
+    result = 0x7fff7FFF;
+    resultdsp = 1;
+
+    __asm
+        ("mul_s.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    if (rd != result || dsp != resultdsp) {
+        printf("mul_s.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/muleq_s_w_phl.c b/tests/tcg/mips/mips64-dspr2/muleq_s_w_phl.c
new file mode 100644
index 0000000..9623683
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/muleq_s_w_phl.c
@@ -0,0 +1,42 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x80001234;
+    rt = 0x80004321;
+    result = 0x7FFFFFFF;
+    resultdsp = 1;
+
+    __asm
+        ("muleq_s.w.phl %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    if (rd  != result || dsp != resultdsp) {
+        printf("muleq_s.w.phl error\n");
+        return -1;
+    }
+    rs = 0x12340000;
+    rt = 0x43210000;
+    result = 0x98be968;
+    resultdsp = 1;
+
+    __asm
+        ("muleq_s.w.phl %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    if (rd  != result || dsp != resultdsp) {
+        printf("muleq_s.w.phl error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/mulq_rs_w.c b/tests/tcg/mips/mips64-dspr2/mulq_rs_w.c
new file mode 100644
index 0000000..ffdc66d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/mulq_rs_w.c
@@ -0,0 +1,40 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x80001234;
+    rt = 0x80004321;
+    result = 0xFFFFFFFF80005555;
+
+    __asm
+        ("mulq_rs.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("mulq_rs.w error!\n");
+        return -1;
+    }
+
+    rs = 0x80000000;
+    rt = 0x80000000;
+    result = 0x7FFFFFFF;
+    resultdsp = 1;
+
+    __asm
+        ("mulq_rs.w %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    if (rd != result || dsp != resultdsp) {
+        printf("mulq_rs.w error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/mulq_s_ph.c b/tests/tcg/mips/mips64-dspr2/mulq_s_ph.c
new file mode 100644
index 0000000..b8c20c6
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/mulq_s_ph.c
@@ -0,0 +1,26 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x80001234;
+    rt = 0x80004321;
+    result = 0x7FFF098B;
+    resultdsp = 1;
+
+    __asm
+        ("mulq_s.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    if (rd  != result || dsp != resultdsp) {
+        printf("mulq_s.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/mulq_s_w.c b/tests/tcg/mips/mips64-dspr2/mulq_s_w.c
new file mode 100644
index 0000000..db74b71
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/mulq_s_w.c
@@ -0,0 +1,40 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x80001234;
+    rt = 0x80004321;
+    result = 0xFFFFFFFF80005555;
+
+    __asm
+        ("mulq_s.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("mulq_s.w error\n");
+        return -1;
+    }
+
+    rs = 0x80000000;
+    rt = 0x80000000;
+    result = 0x7FFFFFFF;
+    resultdsp = 1;
+
+    __asm
+        ("mulq_s.w %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 21) & 0x01;
+    if (rd != result || dsp != resultdsp) {
+        printf("mulq_s.w error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c b/tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c
new file mode 100644
index 0000000..5b22a60
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c
@@ -0,0 +1,30 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rs, rt, ach, acl;
+    long long resulth, resultl;
+
+    ach = 0x05;
+    acl = 0x00BBDDCC;
+    rs = 0x80001234;
+    rt = 0x80004321;
+    resulth = 0x05;
+    resultl = 0x3BF5E918;
+
+    __asm
+        ("mthi %0, $ac1\n\t"
+         "mtlo %1, $ac1\n\t"
+         "mulsa.w.ph $ac1, %2, %3\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    if (ach != resulth || acl != resultl) {
+        printf("mulsa.w.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c b/tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c
new file mode 100644
index 0000000..835a73d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c
@@ -0,0 +1,30 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rs, rt, ach, acl;
+    long long resulth, resultl;
+
+    ach = 0x05;
+    acl = 0x00BBDDCC;
+    rs = 0x80001234;
+    rt = 0x80004321;
+    resulth = 0x05;
+    resultl = 0x772ff463;
+
+    __asm
+        ("mthi %0, $ac1\n\t"
+         "mtlo %1, $ac1\n\t"
+         "mulsaq_s.w.ph $ac1, %2, %3\n\t"
+         "mfhi %0, $ac1\n\t"
+         "mflo %1, $ac1\n\t"
+         : "+r"(ach), "+r"(acl)
+         : "r"(rs), "r"(rt)
+        );
+    if (ach != resulth || acl != resultl) {
+        printf("mulsaq_s.w.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/precr_qb_ph.c b/tests/tcg/mips/mips64-dspr2/precr_qb_ph.c
new file mode 100644
index 0000000..80d5e8d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/precr_qb_ph.c
@@ -0,0 +1,23 @@
+#include"io.h"
+
+int main()
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x34786521;
+
+    __asm
+        ("precr.qb.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (result != rd) {
+        printf("precr.qb.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c b/tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c
new file mode 100644
index 0000000..b1d7bcd
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c
@@ -0,0 +1,37 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x43215678;
+
+    __asm
+        ("precr_sra.ph.w %0, %1, 0x00\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    if (result != rt) {
+        printf("precr_sra.ph.w error\n");
+        return -1;
+    }
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0xFFFFFFFFFFFF0000;
+
+    __asm
+        ("precr_sra.ph.w %0, %1, 0x1F\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    if (result != rt) {
+        printf("precr_sra.ph.w error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c b/tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c
new file mode 100644
index 0000000..62d220d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c
@@ -0,0 +1,37 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x43215678;
+
+    __asm
+        ("precr_sra_r.ph.w %0, %1, 0x00\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    if (result != rt) {
+        printf("precr_sra_r.ph.w error\n");
+        return -1;
+    }
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0xFFFFFFFFFFFF0000;
+
+    __asm
+        ("precr_sra_r.ph.w %0, %1, 0x1F\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    if (result != rt) {
+        printf("precr_sra_r.ph.w error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/prepend.c b/tests/tcg/mips/mips64-dspr2/prepend.c
new file mode 100644
index 0000000..4ab083e
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/prepend.c
@@ -0,0 +1,35 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0xFFFFFFFF87654321;
+    __asm
+        ("prepend %0, %1, 0x00\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    if (rt != result) {
+        printf("prepend error\n");
+        return -1;
+    }
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0xFFFFFFFFACF10ECA;
+    __asm
+        ("prepend %0, %1, 0x0F\n\t"
+         : "+r"(rt)
+         : "r"(rs)
+        );
+    if (rt != result) {
+        printf("prepend error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/printf.c b/tests/tcg/mips/mips64-dspr2/printf.c
new file mode 100644
index 0000000..cf8676d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/printf.c
@@ -0,0 +1,266 @@
+
+typedef unsigned long va_list;
+
+#define ACC    4
+#define __read(source)                    \
+({ va_list __res;                    \
+    __asm__ __volatile__(                \
+        "move\t%0, " #source "\n\t"        \
+        : "=r" (__res));            \
+    __res;                        \
+})
+
+enum format_type {
+    FORMAT_TYPE_NONE,
+    FORMAT_TYPE_HEX,
+    FORMAT_TYPE_ULONG,
+    FORMAT_TYPE_FLOAT
+};
+
+struct printf_spec {
+    char    type;
+};
+
+static int format_decode(char *fmt, struct printf_spec *spec)
+{
+    char *start = fmt;
+
+    for (; *fmt ; ++fmt) {
+        if (*fmt == '%') {
+            break;
+        }
+    }
+
+    switch (*++fmt) {
+    case 'x':
+        spec->type = FORMAT_TYPE_HEX;
+        break;
+
+    case 'd':
+        spec->type = FORMAT_TYPE_ULONG;
+        break;
+
+    case 'f':
+        spec->type = FORMAT_TYPE_FLOAT;
+        break;
+
+    default:
+        spec->type = FORMAT_TYPE_NONE;
+    }
+
+    return ++fmt - start;
+}
+
+void *memcpy(void *dest, void *src, int n)
+{
+    int i;
+    char *s = src;
+    char *d = dest;
+
+    for (i = 0; i < n; i++) {
+        d[i] = s[i];
+    }
+    return dest;
+}
+
+char *number(char *buf, va_list num)
+{
+    int i;
+    char *str = buf;
+    static char digits[16] = "0123456789abcdef";
+    str = str + sizeof(num) * 2;
+
+    for (i = 0; i < sizeof(num) * 2; i++) {
+        *--str = digits[num & 15];
+        num >>= 4;
+    }
+
+    return buf + sizeof(num) * 2;
+}
+
+char *__number(char *buf, va_list num)
+{
+    int i;
+    va_list mm = num;
+    char *str = buf;
+
+    if (!num) {
+        *str++ = '0';
+        return str;
+    }
+
+    for (i = 0; mm; mm = mm/10, i++) {
+        /* Do nothing. */
+    }
+
+    str = str + i;
+
+    while (num) {
+        *--str = num % 10 + 48;
+        num = num / 10;
+    }
+
+    return str + i;
+}
+
+va_list modf(va_list args, va_list *integer, va_list *num)
+{
+    int i;
+    double dot_v = 0;
+    va_list E, DOT, DOT_V;
+
+    if (!args) {
+        return 0;
+    }
+
+    for (i = 0, args = args << 1 >> 1; i < 52; i++) {
+        if ((args >> i) & 0x1) {
+            break;
+        }
+    }
+
+    *integer = 0;
+
+    if ((args >> 56 != 0x3f) || (args >> 52 == 0x3ff)) {
+        E = (args >> 52) - 1023;
+        DOT = 52 - E - i;
+        DOT_V = args << (12 + E) >> (12 + E) >> i;
+        *integer = ((args << 12 >> 12) >> (i + DOT)) | (1 << E);
+    } else {
+        E = ~((args >> 52) - 1023) + 1;
+        DOT_V = args << 12 >> 12;
+
+        dot_v += 1.0 / (1 << E);
+
+        for (i = 1; i <= 16; i++) {
+            if ((DOT_V >> (52 - i)) & 0x1) {
+                dot_v += 1.0 / (1 << E + i);
+            }
+        }
+
+        for (i = 1, E = 0; i <= ACC; i++) {
+            dot_v *= 10;
+            if (!(va_list)dot_v) {
+                E++;
+            }
+    }
+
+    *num = E;
+
+    return dot_v;
+    }
+
+    if (args & 0xf) {
+        for (i = 1; i <= 16; i++) {
+            if ((DOT_V >> (DOT - i)) & 0x1) {
+                dot_v += 1.0 / (1 << i);
+            }
+        }
+
+        for (i = 1, E = 0; i <= ACC; i++) {
+            dot_v *= 10;
+            if (!(va_list)dot_v) {
+                E++;
+            }
+        }
+
+        *num = E;
+
+        return dot_v;
+    } else if (DOT) {
+        for (i = 1; i <= DOT; i++) {
+            if ((DOT_V >> (DOT - i)) & 0x1) {
+                dot_v += 1.0 / (1 << i);
+            }
+        }
+
+        for (i = 1; i <= ACC; i++) {
+            dot_v = dot_v * 10;
+        }
+
+    return dot_v;
+    }
+
+    return 0;
+}
+
+int vsnprintf(char *buf, int size, char *fmt, va_list args)
+{
+    char *str, *mm;
+    struct printf_spec spec = {0};
+
+    str = mm = buf;
+
+    while (*fmt) {
+        char *old_fmt = fmt;
+        int read = format_decode(fmt, &spec);
+
+        fmt += read;
+
+        switch (spec.type) {
+        case FORMAT_TYPE_NONE: {
+            memcpy(str, old_fmt, read);
+            str += read;
+            break;
+        }
+        case FORMAT_TYPE_HEX: {
+            memcpy(str, old_fmt, read);
+            str = number(str + read, args);
+            for (; *mm ; ++mm) {
+                if (*mm == '%') {
+                    *mm = '0';
+                break;
+                }
+            }
+        break;
+        }
+        case FORMAT_TYPE_ULONG: {
+            memcpy(str, old_fmt, read - 2);
+            str = __number(str + read - 2, args);
+            break;
+        }
+        case FORMAT_TYPE_FLOAT: {
+            va_list integer, dot_v, num;
+            dot_v = modf(args, &integer, &num);
+            memcpy(str, old_fmt, read - 2);
+            str += read - 2;
+            if ((args >> 63 & 0x1)) {
+                *str++ = '-';
+            }
+            str = __number(str, integer);
+            if (dot_v) {
+                *str++ = '.';
+                while (num--) {
+                    *str++ = '0';
+                }
+                str = __number(str, dot_v);
+            }
+            break;
+        }
+        }
+    }
+    *str = '\0';
+
+    return str - buf;
+}
+
+static void serial_out(char *str)
+{
+    while (*str) {
+        *(char *)0xffffffffb80003f8 = *str++;
+    }
+}
+
+int vprintf(char *fmt, va_list args)
+{
+    int printed_len = 0;
+    static char printf_buf[512];
+    printed_len = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args);
+    serial_out(printf_buf);
+    return printed_len;
+}
+
+int printf(char *fmt, ...)
+{
+    return vprintf(fmt, __read($5));
+}
diff --git a/tests/tcg/mips/mips64-dspr2/shra_qb.c b/tests/tcg/mips/mips64-dspr2/shra_qb.c
new file mode 100644
index 0000000..cac3102
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/shra_qb.c
@@ -0,0 +1,35 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt = 0x12345678;
+    result = 0x02060A0F;
+
+    __asm
+        ("shra.qb %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("shra.qb error\n");
+        return -1;
+    }
+
+    rt = 0x87654321;
+    result = 0xFFFFFFFFF00C0804;
+
+    __asm
+        ("shra.qb %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("shra.qb error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/shra_r_qb.c b/tests/tcg/mips/mips64-dspr2/shra_r_qb.c
new file mode 100644
index 0000000..9c64f75
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/shra_r_qb.c
@@ -0,0 +1,35 @@
+#include "io.h"
+
+int main()
+{
+    int rd, rt;
+    int result;
+
+    rt = 0x12345678;
+    result = 0x02070B0F;
+
+    __asm
+        ("shra_r.qb %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("shra_r.qb wrong\n");
+        return -1;
+    }
+
+    rt = 0x87654321;
+    result = 0xF10D0804;
+
+    __asm
+        ("shra_r.qb %0, %1, 0x03\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("shra_r.qb wrong\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/shrav_ob.c b/tests/tcg/mips/mips64-dspr2/shrav_ob.c
new file mode 100644
index 0000000..fbdfbab
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/shrav_ob.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, rs;
+    long long res;
+
+    rt = 0x1234567887654321;
+    rs = 0x4;
+    res = 0xf1f3f5f7f8060402;
+
+    asm ("shrav.ob %0, %1, %2"
+        : "=r"(rd)
+        : "r"(rt), "r"(rs)
+        );
+
+    if (rd != res) {
+        printf("shra.ob error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/shrav_qb.c b/tests/tcg/mips/mips64-dspr2/shrav_qb.c
new file mode 100644
index 0000000..a716203
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/shrav_qb.c
@@ -0,0 +1,37 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x03;
+    rt = 0x12345678;
+    result = 0x02060A0F;
+
+    __asm
+        ("shrav.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    if (rd != result) {
+        printf("shrav.qb error\n");
+        return -1;
+    }
+
+    rs = 0x03;
+    rt = 0x87654321;
+    result = 0xFFFFFFFFF00C0804;
+
+    __asm
+        ("shrav.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    if (rd != result) {
+        printf("shrav.qb error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/shrav_r_ob.c b/tests/tcg/mips/mips64-dspr2/shrav_r_ob.c
new file mode 100644
index 0000000..b80100a
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/shrav_r_ob.c
@@ -0,0 +1,22 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rt, rs;
+    long long res;
+
+    rt = 0x1234567887654321;
+    rs = 0x4;
+    res = 0xe3e7ebf0f1ede9e5;
+
+    asm ("shrav_r.ob %0, %1, %2"
+        : "=r"(rd)
+        : "r"(rt), "r"(rs)
+        );
+
+    if (rd != res) {
+        printf("shra_r.ob error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/shrav_r_qb.c b/tests/tcg/mips/mips64-dspr2/shrav_r_qb.c
new file mode 100644
index 0000000..009080b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/shrav_r_qb.c
@@ -0,0 +1,37 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x03;
+    rt = 0x12345678;
+    result = 0x02070B0F;
+
+    __asm
+        ("shrav_r.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    if (rd != result) {
+        printf("shrav_r.qb error\n");
+        return -1;
+    }
+
+    rs = 0x03;
+    rt = 0x87654321;
+    result = 0xFFFFFFFFF10D0804;
+
+    __asm
+        ("shrav_r.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    if (rd != result) {
+        printf("shrav_r.qb error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/shrl_ph.c b/tests/tcg/mips/mips64-dspr2/shrl_ph.c
new file mode 100644
index 0000000..e32d976
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/shrl_ph.c
@@ -0,0 +1,22 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rt;
+    long long result;
+
+    rt     = 0x12345678;
+    result = 0x009102B3;
+
+    __asm
+        ("shrl.ph %0, %1, 0x05\n\t"
+         : "=r"(rd)
+         : "r"(rt)
+        );
+    if (rd != result) {
+        printf("shrl.ph error!\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/shrlv_ph.c b/tests/tcg/mips/mips64-dspr2/shrlv_ph.c
new file mode 100644
index 0000000..58c5488
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/shrlv_ph.c
@@ -0,0 +1,23 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs     = 0x05;
+    rt     = 0x12345678;
+    result = 0x009102B3;
+
+    __asm
+        ("shrlv.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rt), "r"(rs)
+        );
+    if (rd != result) {
+        printf("shrlv.ph error!\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/subqh_ph.c b/tests/tcg/mips/mips64-dspr2/subqh_ph.c
new file mode 100644
index 0000000..9037401
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/subqh_ph.c
@@ -0,0 +1,23 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x456709AB;
+
+    __asm
+        ("subqh.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("subqh.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/subqh_r_ph.c b/tests/tcg/mips/mips64-dspr2/subqh_r_ph.c
new file mode 100644
index 0000000..b8f9d2f
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/subqh_r_ph.c
@@ -0,0 +1,23 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x456809AC;
+
+    __asm
+        ("subqh_r.ph %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("subqh_r.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/subqh_r_w.c b/tests/tcg/mips/mips64-dspr2/subqh_r_w.c
new file mode 100644
index 0000000..b025e40
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/subqh_r_w.c
@@ -0,0 +1,23 @@
+#include"io.h"
+
+int main()
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x456789AC;
+
+    __asm
+        ("subqh_r.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("subqh_r.w error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/subqh_w.c b/tests/tcg/mips/mips64-dspr2/subqh_w.c
new file mode 100644
index 0000000..65f1760
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/subqh_w.c
@@ -0,0 +1,23 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0x456789AB;
+
+    __asm
+        ("subqh.w %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("subqh.w error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/subu_ph.c b/tests/tcg/mips/mips64-dspr2/subu_ph.c
new file mode 100644
index 0000000..d057b74
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/subu_ph.c
@@ -0,0 +1,26 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0x7531ECA9;
+    resultdsp = 0x01;
+
+    __asm
+        ("subu.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    if (dsp != resultdsp || rd  != result) {
+        printf("subu.ph error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/subu_qh.c b/tests/tcg/mips/mips64-dspr2/subu_qh.c
new file mode 100644
index 0000000..911cb34
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/subu_qh.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dspreg, result, dspresult;
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEF1;
+    result = 0x000000000000000F;
+    dspresult = 0x01;
+
+    __asm("subu.qh %0, %2, %3\n\t"
+          "rddsp %1\n\t"
+          : "=r"(rd), "=r"(dspreg)
+          : "r"(rs), "r"(rt)
+         );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("subu.qh error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/subu_s_ph.c b/tests/tcg/mips/mips64-dspr2/subu_s_ph.c
new file mode 100644
index 0000000..08b2428
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/subu_s_ph.c
@@ -0,0 +1,25 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result    = 0x75310000;
+    resultdsp = 0x01;
+
+    __asm
+        ("subu_s.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    if (dsp != resultdsp || rd  != result) {
+        printf("subu_s.ph error\n");
+        return -1;
+    }
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/subu_s_qh.c b/tests/tcg/mips/mips64-dspr2/subu_s_qh.c
new file mode 100644
index 0000000..78be739
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/subu_s_qh.c
@@ -0,0 +1,24 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dspreg, result, dspresult;
+    rs = 0x123456789ABCDEF0;
+    rt = 0x123456789ABCDEF1;
+    result = 0x0000000000000000;
+    dspresult = 0x01;
+
+    __asm("subu_s.qh %0, %2, %3\n\t"
+          "rddsp %1\n\t"
+          : "=r"(rd), "=r"(dspreg)
+          : "r"(rs), "r"(rt)
+         );
+
+    dspreg = ((dspreg >> 20) & 0x01);
+    if ((rd != result) || (dspreg != dspresult)) {
+        printf("subu_s.qh error\n\t");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/subuh_ob.c b/tests/tcg/mips/mips64-dspr2/subuh_ob.c
new file mode 100644
index 0000000..f74e8ef
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/subuh_ob.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result;
+
+    rd = 0x0;
+    rs = 0x246856789ABCDEF0;
+    rt = 0x123456789ABCDEF0;
+    result = 0x091A000000000000;
+
+    __asm("subuh.ob %0, %1, %2\n\t"
+          : "=r"(rd)
+          : "r"(rs), "r"(rt)
+         );
+
+    if (rd != result) {
+        printf("subuh.ob error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/subuh_qb.c b/tests/tcg/mips/mips64-dspr2/subuh_qb.c
new file mode 100644
index 0000000..aac7a83
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/subuh_qb.c
@@ -0,0 +1,23 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0xC5E7092B;
+
+    __asm
+        ("subuh.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("subuh.qb wrong\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/subuh_r_ob.c b/tests/tcg/mips/mips64-dspr2/subuh_r_ob.c
new file mode 100644
index 0000000..fc20ffd
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/subuh_r_ob.c
@@ -0,0 +1,23 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, result;
+
+    rd = 0x0;
+    rs = 0x246956789ABCDEF0;
+    rt = 0x123456789ABCDEF0;
+    result = 0x091B000000000000;
+
+    __asm("subuh.ob %0, %1, %2\n\t"
+          : "=r"(rd)
+          : "r"(rs), "r"(rt)
+         );
+
+    if (rd != result) {
+        printf("subuh.ob error\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/mips/mips64-dspr2/subuh_r_qb.c b/tests/tcg/mips/mips64-dspr2/subuh_r_qb.c
new file mode 100644
index 0000000..149d1aa
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/subuh_r_qb.c
@@ -0,0 +1,23 @@
+#include"io.h"
+
+int main(void)
+{
+    long long rd, rs, rt;
+    long long result;
+
+    rs = 0x12345678;
+    rt = 0x87654321;
+    result = 0xC6E80A2C;
+
+    __asm
+        ("subuh_r.qb %0, %1, %2\n\t"
+         : "=r"(rd)
+         : "r"(rs), "r"(rt)
+        );
+    if (rd != result) {
+        printf("subuh_r.qb wrong\n");
+        return -1;
+    }
+
+    return 0;
+}
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v6 13/13] target-mips-ase-dsp: Change TODO
  2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
                   ` (11 preceding siblings ...)
  2012-08-21  9:32 ` [Qemu-devel] [PATCH v6 12/13] target-mips-ase-dsp: Add testcases Jia Liu
@ 2012-08-21  9:34 ` Jia Liu
  12 siblings, 0 replies; 20+ messages in thread
From: Jia Liu @ 2012-08-21  9:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Delete DSP r1 & DSP r2 from TODO.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-mips/TODO |    2 --
 1 file changed, 2 deletions(-)

diff --git a/target-mips/TODO b/target-mips/TODO
index 2a3546f..15d67cd 100644
--- a/target-mips/TODO
+++ b/target-mips/TODO
@@ -6,8 +6,6 @@ General
 - Unimplemented ASEs:
   - MDMX
   - SmartMIPS
-  - DSP r1
-  - DSP r2
 - MT ASE only partially implemented and not functional
 - Shadow register support only partially implemented,
   lacks set switching on interrupt/exception.
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v6 01/13] target-mips-ase-dsp: Add internal functions
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 01/13] target-mips-ase-dsp: Add internal functions Jia Liu
@ 2012-08-23 13:31   ` Aurelien Jarno
  0 siblings, 0 replies; 20+ messages in thread
From: Aurelien Jarno @ 2012-08-23 13:31 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Tue, Aug 21, 2012 at 02:53:07PM +0800, Jia Liu wrote:
> Add internal functions using by MIPS ASE DSP instructions.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/Makefile.objs |    2 +-
>  target-mips/dsp_helper.c  | 1277 +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 1278 insertions(+), 1 deletion(-)
>  create mode 100644 target-mips/dsp_helper.c

Looks fine to me.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

> diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs
> index 2e0e093..55b252d 100644
> --- a/target-mips/Makefile.objs
> +++ b/target-mips/Makefile.objs
> @@ -1,4 +1,4 @@
> -obj-y += translate.o op_helper.o helper.o cpu.o
> +obj-y += translate.o dsp_helper.o op_helper.o helper.o cpu.o
>  obj-$(CONFIG_SOFTMMU) += machine.o
>  
>  $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
> diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
> new file mode 100644
> index 0000000..a7d6c7e
> --- /dev/null
> +++ b/target-mips/dsp_helper.c
> @@ -0,0 +1,1277 @@
> +/*
> + * MIPS ASE DSP Instruction emulation helpers for QEMU.
> + *
> + * Copyright (c) 2012  Jia Liu <proljc@gmail.com>
> + *                     Dongxue Zhang <elat.era@gmail.com>
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "cpu.h"
> +#include "helper.h"
> +
> +/*** MIPS DSP internal functions begin ***/
> +static inline int not_word_value(target_long value)
> +{
> +    target_ulong temp;
> +
> +    temp = (target_long)(int32_t)(value & 0xFFFFFFFF);
> +    if (value == temp) {
> +        return 0;
> +    } else {
> +        return 1;
> +    }
> +}
> +
> +static inline void set_DSPControl_overflow_flag(CPUMIPSState *env,
> +                                                uint32_t flag, int position)
> +{
> +    env->active_tc.DSPControl |= (target_ulong)flag << position;
> +}
> +
> +static inline void set_DSPControl_carryflag(CPUMIPSState *env, uint32_t flag)
> +{
> +    env->active_tc.DSPControl |= (target_ulong)flag << 13;
> +}
> +
> +static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
> +{
> +    uint32_t flag;
> +
> +    flag = (env->active_tc.DSPControl >> 13) & 0x01;
> +
> +    return flag;
> +}
> +
> +static inline void set_DSPControl_24(CPUMIPSState *env, uint32_t flag, int len)
> +{
> +  uint32_t filter;
> +
> +  filter = ((0x01 << len) - 1) << 24;
> +  filter = ~filter;
> +
> +  env->active_tc.DSPControl &= filter;
> +  env->active_tc.DSPControl |= (target_ulong)flag << 24;
> +}
> +
> +static inline uint32_t get_DSPControl_24(CPUMIPSState *env, int len)
> +{
> +  uint32_t cond;
> +  uint32_t filter;
> +
> +  filter = (0x01 << len) - 1;
> +
> +  cond = (env->active_tc.DSPControl >> 24) & filter;
> +
> +  return cond;
> +}
> +
> +static inline void set_DSPControl_pos(CPUMIPSState *env, uint32_t pos)
> +{
> +    target_ulong dspc;
> +
> +    dspc = env->active_tc.DSPControl;
> +#ifndef TARGET_MIPS64
> +    dspc = dspc & 0xFFFFFFC0;
> +    dspc |= pos;
> +#else
> +    dspc = dspc & 0xFFFFFF80;
> +    dspc |= pos;
> +#endif
> +    env->active_tc.DSPControl = dspc;
> +}
> +
> +static inline uint32_t get_DSPControl_pos(CPUMIPSState *env)
> +{
> +    target_ulong dspc;
> +    uint32_t pos;
> +
> +    dspc = env->active_tc.DSPControl;
> +
> +#ifndef TARGET_MIPS64
> +    pos = dspc & 0x3F;
> +#else
> +    pos = dspc & 0x7F;
> +#endif
> +
> +    return pos;
> +}
> +
> +static inline void set_DSPControl_efi(CPUMIPSState *env, uint32_t flag)
> +{
> +    env->active_tc.DSPControl &= 0xFFFFBFFF;
> +    env->active_tc.DSPControl |= (target_ulong)flag << 14;
> +}
> +
> +/* get abs value */
> +static inline int8_t mipsdsp_sat_abs_u8(CPUMIPSState *env, uint8_t a)
> +{
> +    int8_t temp;
> +    temp = a;
> +
> +    if (a == 0x80) {
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +        temp = 0x7f;
> +    } else {
> +        if ((a & 0x80) == 0x80) {
> +            temp = -temp;
> +        }
> +    }
> +
> +    return temp;
> +}
> +
> +static inline int16_t mipsdsp_sat_abs_u16(CPUMIPSState *env, uint16_t a)
> +{
> +    int16_t temp;
> +    temp = a;
> +
> +    if (a == 0x8000) {
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +        temp = 0x7fff;
> +    } else {
> +        if ((a & 0x8000) == 0x8000) {
> +            temp = -temp;
> +        }
> +    }
> +
> +    return temp;
> +}
> +
> +static inline int32_t mipsdsp_sat_abs_u32(CPUMIPSState *env, uint32_t a)
> +{
> +    int32_t temp;
> +    temp = a;
> +
> +    if (a == 0x80000000) {
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +        temp = 0x7FFFFFFF;
> +    } else {
> +        if ((a & 0x80000000) == 0x80000000) {
> +            temp = -temp;
> +        }
> +    }
> +
> +    return temp;
> +}
> +
> +/* get sum value */
> +static inline int16_t mipsdsp_add_i16(CPUMIPSState *env, int16_t a, int16_t b)
> +{
> +    int16_t tempS;
> +    int32_t tempI, temp15, temp16;
> +
> +    tempS = a + b;
> +    tempI = a + b;
> +    temp15 = (tempI & 0x8000) >> 15;
> +    temp16 = (tempI & 0x10000) >> 16;
> +
> +    if (temp15 != temp16) {
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +
> +    return tempS;
> +}
> +
> +static inline int16_t mipsdsp_sat_add_i16(CPUMIPSState *env,
> +                                          int16_t a, int16_t b)
> +{
> +    int16_t tempS;
> +    int32_t tempI, temp15, temp16;
> +
> +    tempS = a + b;
> +    tempI = (int32_t)a + (int32_t)b;
> +    temp15 = (tempI & 0x8000) >> 15;
> +    temp16 = (tempI & 0x10000) >> 16;
> +
> +    if (temp15 != temp16) {
> +        if (temp16 == 0) {
> +            tempS = 0x7FFF;
> +        } else {
> +            tempS = 0x8000;
> +        }
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +
> +    return tempS;
> +}
> +
> +static inline int32_t mipsdsp_sat_add_i32(CPUMIPSState *env,
> +                                          int32_t a, int32_t b)
> +{
> +    int32_t tempI;
> +    int64_t tempL, temp31, temp32;
> +
> +    tempI = a + b;
> +    tempL = (int64_t)a + (int64_t)b;
> +    temp31 = (tempL & 0x80000000) >> 31;
> +    temp32 = (tempL & 0x100000000ull) >> 32;
> +
> +    if (temp31 != temp32) {
> +        if (temp32 == 0) {
> +            tempI = 0x7FFFFFFF;
> +        } else {
> +            tempI = 0x80000000;
> +        }
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +
> +    return tempI;
> +}
> +
> +static inline uint8_t mipsdsp_add_u8(CPUMIPSState *env, uint8_t a, uint8_t b)
> +{
> +    uint8_t  result;
> +    uint16_t tempA, tempB, temp;
> +
> +    tempA = a;
> +    tempB = b;
> +    temp = tempA + tempB;
> +    result = temp & 0xFF;
> +
> +    if ((temp & 0x0100) == 0x0100) {
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +
> +    return result;
> +}
> +
> +static inline uint16_t mipsdsp_add_u16(CPUMIPSState *env,
> +                                       uint16_t a, uint16_t b)
> +{
> +    uint16_t result;
> +    uint32_t tempA, tempB, temp;
> +
> +    tempA = a;
> +    tempB = b;
> +    temp = tempA + tempB;
> +    result = temp & 0xFFFF;
> +
> +    if ((temp & 0x00010000) == 0x00010000) {
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +
> +    return result;
> +}
> +
> +static inline uint8_t mipsdsp_sat_add_u8(CPUMIPSState *env,
> +                                         uint8_t a, uint8_t b)
> +{
> +    uint8_t  result;
> +    uint16_t tempA, tempB, temp;
> +
> +    tempA = a;
> +    tempB = b;
> +    temp = tempA + tempB;
> +    result = temp & 0xFF;
> +
> +    if ((0x0100 & temp) == 0x0100) {
> +        result = 0xFF;
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +
> +    return result;
> +}
> +
> +static inline uint16_t mipsdsp_sat_add_u16(CPUMIPSState *env,
> +                                           uint16_t a, uint16_t b)
> +{
> +    uint16_t result;
> +    uint32_t tempA, tempB, temp;
> +
> +    tempA = a;
> +    tempB = b;
> +    temp = tempA + tempB;
> +    result = temp & 0xFFFF;
> +
> +    if ((0x00010000 & temp) == 0x00010000) {
> +        result = 0xFFFF;
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +
> +    return result;
> +}
> +
> +static inline int32_t mipsdsp_sat32_acc_q31(CPUMIPSState *env,
> +                                            int32_t acc, int32_t a)
> +{
> +    int64_t tempA, temp;
> +    int32_t temp32, temp31, result;
> +    int64_t temp_sum;
> +
> +#ifndef TARGET_MIPS64
> +    temp = ((uint64_t)env->active_tc.HI[acc] << 32) |
> +           (uint64_t)env->active_tc.LO[acc];
> +#else
> +    temp = (uint64_t)env->active_tc.LO[acc];
> +#endif
> +    tempA = (int64_t)a;
> +
> +    temp_sum = tempA + temp;
> +
> +    temp32 = (temp_sum >> 32) & 0x01;
> +    temp31 = (temp_sum >> 31) & 0x01;
> +    result = temp_sum & 0xFFFFFFFF;
> +
> +    if (temp32 != temp31) {
> +        if (temp32 == 0) {
> +            result = 0x80000000;
> +        } else {
> +            result = 0x7FFFFFFF;
> +        }
> +        set_DSPControl_overflow_flag(env, 1, 16 + acc);
> +    }
> +
> +    return result;
> +}
> +
> +/* a[0] is LO, a[1] is HI. */
> +static inline void mipsdsp_sat64_acc_add_q63(CPUMIPSState *env,
> +                                             int64_t *ret,
> +                                             int32_t ac,
> +                                             int64_t *a)
> +{
> +    uint32_t temp64, temp63;
> +    int64_t temp[3];
> +    int64_t acc[3];
> +    int64_t temp_sum;
> +
> +    temp[0] = a[0];
> +    temp[1] = a[1];
> +    if (((temp[1] >> 63) & 0x01) == 0) {
> +        temp[2] = 0x00;
> +    } else {
> +        temp[2] = 0xFFFFFFFFFFFFFFFFull;
> +    }
> +
> +    acc[0] = env->active_tc.LO[ac];
> +    acc[1] = env->active_tc.HI[ac];
> +    if (((acc[1] >> 63) & 0x01) == 0) {
> +        acc[2] = 0x00;
> +    } else {
> +        acc[2] = 0xFFFFFFFFFFFFFFFFull;
> +    }
> +
> +    temp_sum = temp[0] + acc[0];
> +    if (((uint64_t)temp_sum < (uint64_t)temp[0]) &&
> +       ((uint64_t)temp_sum < (uint64_t)acc[0])) {
> +        temp[1] += 1;
> +        if (temp[1] == 0) {
> +            temp[2] += 1;
> +        }
> +    }
> +    temp[0] = temp_sum;
> +
> +    temp_sum = temp[1] + acc[1];
> +    if (((uint64_t)temp_sum < (uint64_t)temp[1]) &&
> +       ((uint64_t)temp_sum < (uint64_t)acc[1])) {
> +        temp[2] += 1;
> +    }
> +
> +    temp[1] = temp_sum;
> +    temp[2] += acc[2];
> +    temp64 = temp[1] & 0x01;
> +    temp63 = (temp[0] >> 63) & 0x01;
> +
> +    if (temp64 != temp63) {
> +        if (temp64 == 1) {
> +            ret[0] = 0x8000000000000000ull;
> +            ret[1] = 0xFFFFFFFFFFFFFFFFull;
> +        } else {
> +            ret[0] = 0x0;
> +            ret[1] = 0x7FFFFFFFFFFFFFFFull;
> +        }
> +        set_DSPControl_overflow_flag(env, 1, 16 + ac);
> +    } else {
> +        ret[0] = temp[0];
> +        ret[1] = temp[1];
> +    }
> +}
> +
> +/* a[0] is LO, a[1] is HI. */
> +static inline void mipsdsp_sat64_acc_sub_q63(CPUMIPSState *env,
> +                                             int64_t *ret,
> +                                             int32_t ac,
> +                                             int64_t *a)
> +{
> +    uint32_t temp64, temp63;
> +    int64_t temp[3];
> +    int64_t acc[3];
> +    int64_t temp_sum;
> +
> +    temp[0] = a[0];
> +    temp[1] = a[1];
> +    if (((temp[1] >> 63) & 0x01) == 0) {
> +        temp[2] = 0x00;
> +    } else {
> +        temp[2] = 0xFFFFFFFFFFFFFFFFull;
> +    }
> +
> +    acc[0] = env->active_tc.LO[ac];
> +    acc[1] = env->active_tc.HI[ac];
> +    if (((acc[1] >> 63) & 0x01) == 0) {
> +        acc[2] = 0x00;
> +    } else {
> +        acc[2] = 0xFFFFFFFFFFFFFFFFull;
> +    }
> +
> +    temp_sum = acc[0] - temp[0];
> +    if ((uint64_t)temp_sum > (uint64_t)acc[0]) {
> +        acc[1] -= 1;
> +        if (acc[1] == 0xFFFFFFFFFFFFFFFFull) {
> +            acc[2] -= 1;
> +        }
> +    }
> +    acc[0] = temp_sum;
> +
> +    temp_sum = acc[1] - temp[1];
> +    if ((uint64_t)temp_sum > (uint64_t)acc[1]) {
> +        acc[2] -= 1;
> +    }
> +    acc[1] = temp_sum;
> +    acc[2] -= temp[2];
> +
> +    temp64 = acc[1] & 0x01;
> +    temp63 = (acc[0] >> 63) & 0x01;
> +
> +    if (temp64 != temp63) {
> +        if (temp64 == 1) {
> +            ret[0] = 0x8000000000000000ull;
> +            ret[1] = 0xFFFFFFFFFFFFFFFFull;
> +        } else {
> +            ret[0] = 0x0;
> +            ret[1] = 0x7FFFFFFFFFFFFFFFull;
> +        }
> +        set_DSPControl_overflow_flag(env, 1, 16 + ac);
> +    } else {
> +        ret[0] = acc[0];
> +        ret[1] = acc[1];
> +    }
> +}
> +
> +static inline int32_t mipsdsp_mul_i16_i16(CPUMIPSState *env,
> +                                          int16_t a, int16_t b)
> +{
> +    int32_t temp, tempA, tempB;
> +
> +    tempA = a;
> +    tempB = b;
> +    temp = tempA * tempB;
> +
> +    if ((temp > 0x7FFF) || (temp < 0xFFFF8000)) {
> +        set_DSPControl_overflow_flag(env, 1, 21);
> +    }
> +    temp &= 0x0000FFFF;
> +
> +    return temp;
> +}
> +
> +static inline int32_t mipsdsp_sat16_mul_i16_i16(CPUMIPSState *env,
> +                                                int16_t a, int16_t b)
> +{
> +    int32_t temp, tempA, tempB;
> +
> +    tempA = a;
> +    tempB = b;
> +    temp = tempA * tempB;
> +
> +    if (temp > 0x7FFF) {
> +        temp = 0x00007FFF;
> +        set_DSPControl_overflow_flag(env, 1, 21);
> +    } else if (temp < 0x00007FFF) {
> +        temp = 0xFFFF8000;
> +        set_DSPControl_overflow_flag(env, 1, 21);
> +    }
> +    temp &= 0x0000FFFF;
> +
> +    return temp;
> +}
> +
> +static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(CPUMIPSState *env,
> +                                                         uint16_t a, uint16_t b)
> +{
> +    int16_t tempA, tempB;
> +    int32_t temp;
> +
> +    tempA = a;
> +    tempB = b;
> +
> +    if ((a == 0x8000) && (b == 0x8000)) {
> +        temp = 0x7FFFFFFF;
> +        set_DSPControl_overflow_flag(env, 1, 21);
> +    } else {
> +        temp = ((int32_t)tempA * (int32_t)tempB) << 1;
> +    }
> +
> +    return temp;
> +}
> +
> +/* right shift */
> +static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
> +{
> +    int32_t temp, tempA, tempB;
> +    int16_t result;
> +
> +    tempA = a;
> +    tempB = b;
> +    temp = tempA + tempB;
> +    result = (temp >> 1) & 0xFFFF;
> +
> +    return result;
> +}
> +
> +/* round right shift */
> +static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b)
> +{
> +    int32_t temp, tempA, tempB;
> +    int16_t result;
> +
> +    tempA = a;
> +    tempB = b;
> +    temp = tempA + tempB;
> +    temp += 1;
> +    result = (temp >> 1) & 0xFFFF;
> +
> +    return result;
> +}
> +
> +static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b)
> +{
> +    int64_t temp, tempA, tempB;
> +    int32_t result;
> +
> +    tempA = a;
> +    tempB = b;
> +    temp = tempA + tempB;
> +    result = (temp >> 1) & 0xFFFFFFFF;
> +
> +    return result;
> +}
> +
> +static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b)
> +{
> +    int64_t temp, tempA, tempB;
> +    int32_t result;
> +    tempA = a;
> +    tempB = b;
> +
> +    temp = tempA + tempB;
> +    temp += 1;
> +    result = (temp >> 1) & 0xFFFFFFFF;
> +
> +    return result;
> +}
> +
> +static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b)
> +{
> +    uint16_t tempA, tempB, temp;
> +    uint8_t  result;
> +
> +    tempA = a;
> +    tempB = b;
> +    temp = tempA + tempB;
> +    result = (temp >> 1) & 0x00FF;
> +
> +    return result;
> +}
> +
> +static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b)
> +{
> +    uint16_t tempA, tempB, temp;
> +    uint8_t  result;
> +
> +    tempA = a;
> +    tempB = b;
> +    temp = tempA + tempB + 1;
> +    result = (temp >> 1) & 0x00FF;
> +
> +    return result;
> +}
> +
> +static inline int64_t mipsdsp_rashift_short_acc(CPUMIPSState *env,
> +                                                int32_t ac,
> +                                                int32_t shift)
> +{
> +    int32_t sign, temp31;
> +    int64_t temp, acc;
> +
> +    sign = (env->active_tc.HI[ac] >> 31) & 0x01;
> +    acc = ((int64_t)env->active_tc.HI[ac] << 32) |
> +          ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
> +    if (shift == 0) {
> +        temp = acc;
> +    } else {
> +        if (sign == 0) {
> +            temp = (((int64_t)0x01 << (32 - shift + 1)) - 1) & (acc >> shift);
> +        } else {
> +            temp = ((((int64_t)0x01 << (shift + 1)) - 1) << (32 - shift)) |
> +                   (acc >> shift);
> +        }
> +    }
> +
> +    temp31 = (temp >> 31) & 0x01;
> +    if (sign != temp31) {
> +        set_DSPControl_overflow_flag(env, 1, 23);
> +    }
> +
> +    return temp;
> +}
> +
> +/*  128 bits long. p[0] is LO, p[1] is HI. */
> +static inline void mipsdsp__rashift_short_acc(CPUMIPSState *env,
> +                                              int64_t *p,
> +                                              int32_t ac,
> +                                              int32_t shift)
> +{
> +    int64_t acc;
> +
> +    acc = ((int64_t)env->active_tc.HI[ac] << 32) |
> +          ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
> +    if (shift == 0) {
> +        p[0] = acc << 1;
> +        p[1] = (acc >> 63) & 0x01;
> +    } else {
> +        p[0] = acc >> (shift - 1);
> +        p[1] = 0;
> +    }
> +}
> +
> +/* 128 bits long. p[0] is LO, p[1] is HI */
> +static inline void mipsdsp_rashift_acc(CPUMIPSState *env,
> +                                       uint64_t *p,
> +                                       uint32_t ac,
> +                                       uint32_t shift)
> +{
> +    uint64_t tempB, tempA;
> +
> +    tempB = env->active_tc.HI[ac];
> +    tempA = env->active_tc.LO[ac];
> +    shift = shift & 0x1F;
> +
> +    if (shift == 0) {
> +        p[1] = tempB;
> +        p[0] = tempA;
> +    } else {
> +        p[0] = (tempB << (64 - shift)) | (tempA >> shift);
> +        p[1] = (int64_t)tempB >> shift;
> +    }
> +}
> +
> +/* FIXME
> + * if ( shift5..0 = 0 ) then
> + *   temp128..0 ← ( HI[ac]0 || LO[ac]63..0 || 0 )
> + * else
> + *   sign ← HI[ac]63
> + *   temp128..0 ←
> + *           signshift || (( HI[ac]63..0 || LO[ac]63..0 ) >> shift5..0) ||
> + *   LO[ac]shift-1
> + * endif
> + * return temp128..0
> + * endfunction _shiftAccRightArithmetic
> + */
> +/* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/
> +static inline void mipsdsp__rashift_acc(CPUMIPSState *env,
> +                                       uint64_t *p,
> +                                       uint32_t ac,
> +                                       uint32_t shift)
> +{
> +    uint64_t tempB, tempA;
> +
> +    tempB = env->active_tc.HI[ac];
> +    tempA = env->active_tc.LO[ac];
> +    shift = shift & 0x3F;
> +
> +    if (shift == 0) {
> +        p[2] = tempB >> 63;
> +        p[1] = (tempB << 1) | (tempA >> 63);
> +        p[0] = tempA << 1;
> +    } else {
> +        p[0] = (tempB << (64 - shift)) | (tempA >> shift);
> +        p[1] = (int64_t)tempB >> shift;
> +        if (((tempB >> 63) & 0x01) == 1) {
> +            p[2] = 0xFfffFfffFfffFfffull;
> +        } else {
> +            p[2] = 0x0;
> +        }
> +    }
> +}
> +
> +static inline int32_t mipsdsp_mul_q15_q15(CPUMIPSState *env,
> +                                          int32_t ac, uint16_t a, uint16_t b)
> +{
> +    uint16_t tempA, tempB;
> +    int32_t temp;
> +
> +    tempA = a;
> +    tempB = b;
> +
> +    if ((a == 0x8000) && (b == 0x8000)) {
> +        temp = 0x7FFFFFFF;
> +        set_DSPControl_overflow_flag(env, 1, 16 + ac);
> +    } else {
> +        temp = ((uint32_t)tempA * (uint32_t)tempB) << 1;
> +    }
> +
> +    return temp;
> +}
> +
> +static inline int64_t mipsdsp_mul_q31_q31(CPUMIPSState *env,
> +                                          int32_t ac, uint32_t a, uint32_t b)
> +{
> +    uint32_t tempA, tempB;
> +    uint64_t temp;
> +
> +    tempA = a;
> +    tempB = b;
> +
> +    if ((a == 0x80000000) && (b == 0x80000000)) {
> +        temp = 0x7FFFFFFFFFFFFFFFull;
> +        set_DSPControl_overflow_flag(env, 1, 16 + ac);
> +    } else {
> +        temp = ((uint64_t)tempA * (uint64_t)tempB) << 1;
> +    }
> +
> +    return temp;
> +}
> +
> +static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b)
> +{
> +    uint16_t temp;
> +    temp = (uint16_t)a * (uint16_t)b;
> +
> +    return temp;
> +}
> +
> +static inline uint16_t mipsdsp_mul_u8_u16(CPUMIPSState *env,
> +                                          uint8_t a, uint16_t b)
> +{
> +    uint16_t tempS;
> +    uint32_t tempI, tempA, tempB;
> +
> +    tempA = a;
> +    tempB = b;
> +    tempI = tempA * tempB;
> +    if (tempI > 0x0000FFFF) {
> +        tempI = 0x0000FFFF;
> +        set_DSPControl_overflow_flag(env, 1, 21);
> +    }
> +    tempS = tempI & 0x0000FFFF;
> +
> +    return tempS;
> +}
> +
> +static inline uint64_t mipsdsp_mul_u32_u32(CPUMIPSState *env,
> +                                           uint32_t a, uint32_t b)
> +{
> +  uint64_t temp;
> +
> +  temp = (uint64_t)a * (uint64_t)b;
> +
> +  return temp;
> +}
> +
> +static inline int16_t mipsdsp_rndq15_mul_q15_q15(CPUMIPSState *env,
> +                                                 uint16_t a, uint16_t b)
> +{
> +    uint16_t result;
> +    uint32_t temp;
> +
> +    if ((a == 0x8000) && (b == 0x8000)) {
> +        temp = 0x7FFF0000;
> +        set_DSPControl_overflow_flag(env, 1, 21);
> +    } else {
> +        temp = (a * b) << 1;
> +        temp = temp + 0x00008000;
> +    }
> +    result = (temp & 0xFFFF0000) >> 16;
> +
> +    return result;
> +}
> +
> +static inline int32_t mipsdsp_sat16_mul_q15_q15(CPUMIPSState *env,
> +                                                uint16_t a, uint16_t b)
> +{
> +    int16_t tempA, tempB;
> +    int32_t temp;
> +
> +    tempA = a;
> +    tempB = b;
> +
> +    if ((a == 0x8000) && (b == 0x8000)) {
> +        temp = 0x7FFF0000;
> +        set_DSPControl_overflow_flag(env, 1, 21);
> +    } else {
> +        temp = ((uint32_t)tempA * (uint32_t)tempB);
> +        temp = temp << 1;
> +    }
> +    temp = (temp >> 16) & 0x0000FFFF;
> +
> +    return temp;
> +}
> +
> +static inline uint16_t mipsdsp_trunc16_sat16_round(CPUMIPSState *env,
> +                                                   uint32_t a)
> +{
> +    uint16_t result;
> +    uint32_t temp32, temp31;
> +    int64_t temp;
> +
> +    temp = (int32_t)a + 0x00008000;
> +    temp32 = (temp >> 32) & 0x01;
> +    temp31 = (temp >> 31) & 0x01;
> +
> +    if (temp32 != temp31) {
> +        temp = 0x7FFFFFFF;
> +        set_DSPControl_overflow_flag(env, 1, 22);
> +    }
> +    result = (temp >> 16) & 0xFFFF;
> +
> +    return result;
> +}
> +
> +static inline uint8_t mipsdsp_sat8_reduce_precision(CPUMIPSState *env,
> +                                                    uint16_t a)
> +{
> +    uint8_t  result;
> +    uint16_t mag;
> +    uint32_t sign;
> +
> +    sign = (a >> 15) & 0x01;
> +    mag = a & 0x7FFF;
> +
> +    if (sign == 0) {
> +        if (mag > 0x7F80) {
> +            result = 0xFF;
> +            set_DSPControl_overflow_flag(env, 1, 22);
> +        } else {
> +            result = (mag >> 7) & 0xFFFF;
> +        }
> +    } else {
> +        result = 0x00;
> +        set_DSPControl_overflow_flag(env, 1, 22);
> +    }
> +
> +    return result;
> +}
> +
> +static inline uint8_t mipsdsp_lshift8(CPUMIPSState *env, uint8_t a, uint8_t s)
> +{
> +    uint8_t sign;
> +    uint8_t temp, discard;
> +
> +    if (s == 0) {
> +        temp = a;
> +    } else {
> +        sign = (a >> 7) & 0x01;
> +        temp = a << s;
> +        if (sign != 0) {
> +            discard = (((0x01 << (8 - s)) - 1) << s) |
> +                      ((a >> (6 - (s - 1))) & ((0x01 << s) - 1));
> +        } else {
> +            discard = a >> (6 - (s - 1));
> +        }
> +
> +        if (discard != 0x00) {
> +            set_DSPControl_overflow_flag(env, 1, 22);
> +        }
> +    }
> +
> +    return temp;
> +}
> +
> +static inline uint8_t mipsdsp_rshift8(uint8_t a, uint8_t s)
> +{
> +    uint8_t temp;
> +    if (s == 0) {
> +        temp = a;
> +    } else {
> +        temp = a >> s;
> +    }
> +    return temp;
> +}
> +
> +static inline uint16_t mipsdsp_lshift16(CPUMIPSState *env,
> +                                        uint16_t a, uint8_t s)
> +{
> +    uint8_t  sign;
> +    uint16_t temp, discard;
> +
> +    if (s == 0) {
> +        temp = a;
> +    } else {
> +        sign = (a >> 15) & 0x01;
> +        temp = a << s;
> +        if (sign != 0) {
> +            discard = (((0x01 << (16 - s)) - 1) << s) |
> +                      ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
> +        } else {
> +            discard = a >> (14 - (s - 1));
> +        }
> +
> +        if ((discard != 0x0000) && (discard != 0xFFFF)) {
> +            set_DSPControl_overflow_flag(env, 1, 22);
> +        }
> +    }
> +
> +    return temp;
> +}
> +
> +
> +static inline uint32_t mipsdsp_lshift32(CPUMIPSState *env,
> +                                        uint32_t a, uint8_t s)
> +{
> +    uint32_t temp, discard;
> +
> +    if (s == 0) {
> +        temp = a;
> +    } else {
> +        temp = a << s;
> +        discard = (int32_t)a >> (31 - (s - 1));
> +
> +        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
> +            set_DSPControl_overflow_flag(env, 1, 22);
> +        }
> +    }
> +
> +    return temp;
> +}
> +
> +static inline uint16_t mipsdsp_sat16_lshift(CPUMIPSState *env,
> +                                            uint16_t a, uint8_t s)
> +{
> +    uint8_t  sign;
> +    uint16_t temp, discard;
> +
> +    if (s == 0) {
> +        temp = a;
> +    } else {
> +        sign = (a >> 15) & 0x01;
> +        temp = a << s;
> +        if (sign != 0) {
> +            discard = (((0x01 << (16 - s)) - 1) << s) |
> +                      ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
> +        } else {
> +            discard = a >> (14 - (s - 1));
> +        }
> +
> +        if ((discard != 0x0000) && (discard != 0xFFFF)) {
> +            temp = (sign == 0) ? 0x7FFF : 0x8000;
> +            set_DSPControl_overflow_flag(env, 1, 22);
> +        }
> +    }
> +
> +    return temp;
> +}
> +
> +static inline uint32_t mipsdsp_sat32_lshift(CPUMIPSState *env,
> +                                            uint32_t a, uint8_t s)
> +{
> +    uint8_t  sign;
> +    uint32_t temp, discard;
> +
> +    if (s == 0) {
> +        temp = a;
> +    } else {
> +        sign = (a >> 31) & 0x01;
> +        temp = a << s;
> +        if (sign != 0) {
> +            discard = (((0x01 << (32 - s)) - 1) << s) |
> +                      ((a >> (30 - (s - 1))) & ((0x01 << s) - 1));
> +        } else {
> +            discard = a >> (30 - (s - 1));
> +        }
> +
> +        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
> +            temp = (sign == 0) ? 0x7FFFFFFF : 0x80000000;
> +            set_DSPControl_overflow_flag(env, 1, 22);
> +        }
> +    }
> +
> +    return temp;
> +}
> +
> +static inline uint16_t mipsdsp_rashift16(uint16_t a, uint8_t s)
> +{
> +    int16_t i, temp;
> +
> +    i = a;
> +    if (s == 0) {
> +        temp = a;
> +    } else {
> +        temp = i >> s;
> +    }
> +
> +    return temp;
> +}
> +
> +static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s)
> +{
> +    int16_t  i, result;
> +    uint32_t temp;
> +
> +    i = a;
> +    if (s == 0) {
> +        temp = (uint32_t)a << 1;
> +    } else {
> +        temp = (int32_t)i >> (s - 1);
> +    }
> +    temp   = temp + 1;
> +    result = temp >> 1;
> +
> +    return result;
> +}
> +
> +static inline uint32_t mipsdsp_rashift32(uint32_t a, uint8_t s)
> +{
> +    int32_t i, temp;
> +
> +    i = a;
> +    if (s == 0) {
> +        temp = a;
> +    } else {
> +        temp = i >> s;
> +    }
> +
> +    return temp;
> +}
> +
> +static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s)
> +{
> +    int32_t i;
> +    int64_t temp;
> +    uint32_t result;
> +
> +    i = a;
> +    if (s == 0) {
> +        temp = a << 1;
> +    } else {
> +        temp = (int64_t)i >> (s - 1);
> +    }
> +    temp += 1;
> +    result = (temp >> 1) & 0x00000000FFFFFFFFull;
> +
> +    return result;
> +}
> +
> +static inline uint16_t mipsdsp_sub_i16(CPUMIPSState *env, int16_t a, int16_t b)
> +{
> +    uint8_t  temp16, temp15;
> +    uint16_t result;
> +    int32_t  temp;
> +
> +    temp = (int32_t)a - (int32_t)b;
> +    temp16 = (temp >> 16) & 0x01;
> +    temp15 = (temp >> 15) & 0x01;
> +    if (temp16 != temp15) {
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +    result = temp & 0x0000FFFF;
> +
> +    return result;
> +}
> +
> +static inline uint16_t mipsdsp_sat16_sub(CPUMIPSState *env,
> +                                         int16_t a, int16_t b)
> +{
> +    uint8_t  temp16, temp15;
> +    uint16_t result;
> +    int32_t  temp;
> +
> +    temp = (int32_t)a - (int32_t)b;
> +    temp16 = (temp >> 16) & 0x01;
> +    temp15 = (temp >> 15) & 0x01;
> +    if (temp16 != temp15) {
> +        if (temp16 == 0) {
> +            temp = 0x7FFF;
> +        } else {
> +            temp = 0x8000;
> +        }
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +    result = temp & 0x0000FFFF;
> +
> +    return result;
> +}
> +
> +static inline uint32_t mipsdsp_sat32_sub(CPUMIPSState *env,
> +                                         int32_t a, int32_t b)
> +{
> +    uint8_t  temp32, temp31;
> +    uint32_t result;
> +    int64_t  temp;
> +
> +    temp = (int64_t)a - (int64_t)b;
> +    temp32 = (temp >> 32) & 0x01;
> +    temp31 = (temp >> 31) & 0x01;
> +    if (temp32 != temp31) {
> +        if (temp32 == 0) {
> +            temp = 0x7FFFFFFF;
> +        } else {
> +            temp = 0x80000000;
> +        }
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +    result = temp & 0x00000000FFFFFFFFull;
> +
> +    return result;
> +}
> +
> +static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b)
> +{
> +    int32_t  temp;
> +    uint16_t result;
> +
> +    temp = (int32_t)a - (int32_t)b;
> +    result = (temp >> 1) & 0x0000FFFF;
> +
> +    return result;
> +}
> +
> +static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b)
> +{
> +    int32_t  temp;
> +    uint16_t result;
> +
> +    temp = (int32_t)a - (int32_t)b;
> +    temp += 1;
> +    result = (temp >> 1) & 0x0000FFFF;
> +
> +    return result;
> +}
> +
> +static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b)
> +{
> +    int64_t  temp;
> +    uint32_t result;
> +
> +    temp   = (int64_t)a - (int64_t)b;
> +    result = (temp >> 1) & 0x00000000FFFFFFFFull;
> +
> +    return result;
> +}
> +
> +static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b)
> +{
> +    int64_t  temp;
> +    uint32_t result;
> +
> +    temp = (int64_t)a - (int64_t)b;
> +    temp += 1;
> +    result = (temp >> 1) & 0x00000000FFFFFFFFull;
> +
> +    return result;
> +}
> +
> +static inline uint16_t mipsdsp_sub_u16_u16(CPUMIPSState *env,
> +                                           uint16_t a, uint16_t b)
> +{
> +    uint8_t  temp16;
> +    uint16_t result;
> +    uint32_t temp;
> +
> +    temp = (uint32_t)a - (uint32_t)b;
> +    temp16 = (temp >> 16) & 0x01;
> +    if (temp16 == 1) {
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +    result = temp & 0x0000FFFF;
> +    return result;
> +}
> +
> +static inline uint16_t mipsdsp_satu16_sub_u16_u16(CPUMIPSState *env,
> +                                                  uint16_t a, uint16_t b)
> +{
> +    uint8_t  temp16;
> +    uint16_t result;
> +    uint32_t temp;
> +
> +    temp   = (uint32_t)a - (uint32_t)b;
> +    temp16 = (temp >> 16) & 0x01;
> +
> +    if (temp16 == 1) {
> +        temp = 0x0000;
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +    result = temp & 0x0000FFFF;
> +
> +    return result;
> +}
> +
> +static inline uint8_t mipsdsp_sub_u8(CPUMIPSState *env, uint8_t a, uint8_t b)
> +{
> +    uint8_t  result, temp8;
> +    uint16_t temp;
> +
> +    temp = (uint16_t)a - (uint16_t)b;
> +    temp8 = (temp >> 8) & 0x01;
> +    if (temp8 == 1) {
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +    result = temp & 0x00FF;
> +
> +    return result;
> +}
> +
> +static inline uint8_t mipsdsp_satu8_sub(CPUMIPSState *env, uint8_t a, uint8_t b)
> +{
> +    uint8_t  result, temp8;
> +    uint16_t temp;
> +
> +    temp = (uint16_t)a - (uint16_t)b;
> +    temp8 = (temp >> 8) & 0x01;
> +    if (temp8 == 1) {
> +        temp = 0x00;
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +    result = temp & 0x00FF;
> +
> +    return result;
> +}
> +
> +static inline uint32_t mipsdsp_sub32(CPUMIPSState *env, int32_t a, int32_t b)
> +{
> +    uint32_t result, temp32, temp31;
> +    int64_t temp;
> +
> +    temp = (int64_t)a - (int64_t)b;
> +    temp32 = (temp >> 32) & 0x01;
> +    temp31 = (temp >> 31) & 0x01;
> +    if (temp32 != temp31) {
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +    result = temp & 0xFFFFFFFF;
> +
> +    return result;
> +}
> +
> +static inline int32_t mipsdsp_add_i32(CPUMIPSState *env, int32_t a, int32_t b)
> +{
> +    int32_t result;
> +    int32_t temp32, temp31;
> +    int64_t aL, bL;
> +    int64_t temp;
> +
> +    aL = (int64_t)a;
> +    bL = (int64_t)b;
> +    temp = aL + bL;
> +
> +    temp32 = (temp >> 32) & 0x01;
> +    temp31 = (temp >> 31) & 0x01;
> +    if (temp32 != temp31) {
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +    result = temp & 0xFFFFFFFF;
> +
> +    return result;
> +}
> +/*** MIPS DSP internal functions end ***/
> -- 
> 1.7.9.5
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v6 02/13] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 02/13] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Jia Liu
@ 2012-08-23 13:33   ` Aurelien Jarno
  0 siblings, 0 replies; 20+ messages in thread
From: Aurelien Jarno @ 2012-08-23 13:33 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Tue, Aug 21, 2012 at 02:53:08PM +0800, Jia Liu wrote:
> Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/translate.c |  107 +++++++++++++++++++++++++++++++++++------------
>  1 file changed, 81 insertions(+), 26 deletions(-)

This code assume that the DSP ASE is always available and enabled, while
when it is not the case, it should trigger an exception.

> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index 47daf85..0793153 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -5,6 +5,7 @@
>   *  Copyright (c) 2006 Marius Groeger (FPU operations)
>   *  Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
>   *  Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
> + *  Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
>   *
>   * This library is free software; you can redistribute it and/or
>   * modify it under the terms of the GNU Lesser General Public
> @@ -1972,6 +1973,7 @@ static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
>  static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
>  {
>      const char *opn = "hilo";
> +    unsigned int acc;
>  
>      if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
>          /* Treat as NOP. */
> @@ -1980,25 +1982,71 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
>      }
>      switch (opc) {
>      case OPC_MFHI:
> -        tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
> +        acc = ((ctx->opcode) >> 21) & 0x03;
> +#if defined(TARGET_MIPS64)
> +        if (acc == 0) {
> +            tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
> +        } else {
> +            tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
> +        }
> +#else
> +        tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
> +#endif
>          opn = "mfhi";
>          break;
>      case OPC_MFLO:
> -        tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
> +        acc = ((ctx->opcode) >> 21) & 0x03;
> +#if defined(TARGET_MIPS64)
> +        if (acc == 0) {
> +            tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
> +        } else {
> +            tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
> +        }
> +#else
> +        tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
> +#endif
>          opn = "mflo";
>          break;
>      case OPC_MTHI:
> -        if (reg != 0)
> -            tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
> -        else
> -            tcg_gen_movi_tl(cpu_HI[0], 0);
> +        acc = ((ctx->opcode) >> 11) & 0x03;
> +#if defined(TARGET_MIPS64)
> +        if (reg != 0) {
> +            if (acc == 0) {
> +                tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
> +            } else {
> +                tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
> +            }
> +        } else {
> +            tcg_gen_movi_tl(cpu_HI[acc], 0);
> +        }
> +#else
> +        if (reg != 0) {
> +            tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
> +        } else {
> +            tcg_gen_movi_tl(cpu_HI[acc], 0);
> +        }
> +#endif
>          opn = "mthi";
>          break;
>      case OPC_MTLO:
> -        if (reg != 0)
> -            tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
> -        else
> -            tcg_gen_movi_tl(cpu_LO[0], 0);
> +        acc = ((ctx->opcode) >> 11) & 0x03;
> +#if defined(TARGET_MIPS64)
> +        if (reg != 0) {
> +            if (acc == 0) {
> +                tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
> +            } else {
> +                tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
> +            }
> +        } else {
> +            tcg_gen_movi_tl(cpu_LO[acc], 0);
> +        }
> +#else
> +        if (reg != 0) {
> +            tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
> +        } else {
> +            tcg_gen_movi_tl(cpu_LO[acc], 0);
> +        }
> +#endif
>          opn = "mtlo";
>          break;
>      }
> @@ -2011,6 +2059,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
>  {
>      const char *opn = "mul/div";
>      TCGv t0, t1;
> +    unsigned int acc;
>  
>      switch (opc) {
>      case OPC_DIV:
> @@ -2073,6 +2122,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
>          {
>              TCGv_i64 t2 = tcg_temp_new_i64();
>              TCGv_i64 t3 = tcg_temp_new_i64();
> +            acc = ((ctx->opcode) >> 11) & 0x03;
>  
>              tcg_gen_ext_tl_i64(t2, t0);
>              tcg_gen_ext_tl_i64(t3, t1);
> @@ -2082,8 +2132,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
>              tcg_gen_shri_i64(t2, t2, 32);
>              tcg_gen_trunc_i64_tl(t1, t2);
>              tcg_temp_free_i64(t2);
> -            tcg_gen_ext32s_tl(cpu_LO[0], t0);
> -            tcg_gen_ext32s_tl(cpu_HI[0], t1);
> +            tcg_gen_ext32s_tl(cpu_LO[acc], t0);
> +            tcg_gen_ext32s_tl(cpu_HI[acc], t1);
>          }
>          opn = "mult";
>          break;
> @@ -2091,6 +2141,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
>          {
>              TCGv_i64 t2 = tcg_temp_new_i64();
>              TCGv_i64 t3 = tcg_temp_new_i64();
> +            acc = ((ctx->opcode) >> 11) & 0x03;
>  
>              tcg_gen_ext32u_tl(t0, t0);
>              tcg_gen_ext32u_tl(t1, t1);
> @@ -2102,8 +2153,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
>              tcg_gen_shri_i64(t2, t2, 32);
>              tcg_gen_trunc_i64_tl(t1, t2);
>              tcg_temp_free_i64(t2);
> -            tcg_gen_ext32s_tl(cpu_LO[0], t0);
> -            tcg_gen_ext32s_tl(cpu_HI[0], t1);
> +            tcg_gen_ext32s_tl(cpu_LO[acc], t0);
> +            tcg_gen_ext32s_tl(cpu_HI[acc], t1);
>          }
>          opn = "multu";
>          break;
> @@ -2150,19 +2201,20 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
>          {
>              TCGv_i64 t2 = tcg_temp_new_i64();
>              TCGv_i64 t3 = tcg_temp_new_i64();
> +            acc = ((ctx->opcode) >> 11) & 0x03;
>  
>              tcg_gen_ext_tl_i64(t2, t0);
>              tcg_gen_ext_tl_i64(t3, t1);
>              tcg_gen_mul_i64(t2, t2, t3);
> -            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
> +            tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
>              tcg_gen_add_i64(t2, t2, t3);
>              tcg_temp_free_i64(t3);
>              tcg_gen_trunc_i64_tl(t0, t2);
>              tcg_gen_shri_i64(t2, t2, 32);
>              tcg_gen_trunc_i64_tl(t1, t2);
>              tcg_temp_free_i64(t2);
> -            tcg_gen_ext32s_tl(cpu_LO[0], t0);
> -            tcg_gen_ext32s_tl(cpu_HI[0], t1);
> +            tcg_gen_ext32s_tl(cpu_LO[acc], t0);
> +            tcg_gen_ext32s_tl(cpu_HI[acc], t1);
>          }
>          opn = "madd";
>          break;
> @@ -2170,21 +2222,22 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
>         {
>              TCGv_i64 t2 = tcg_temp_new_i64();
>              TCGv_i64 t3 = tcg_temp_new_i64();
> +            acc = ((ctx->opcode) >> 11) & 0x03;
>  
>              tcg_gen_ext32u_tl(t0, t0);
>              tcg_gen_ext32u_tl(t1, t1);
>              tcg_gen_extu_tl_i64(t2, t0);
>              tcg_gen_extu_tl_i64(t3, t1);
>              tcg_gen_mul_i64(t2, t2, t3);
> -            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
> +            tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
>              tcg_gen_add_i64(t2, t2, t3);
>              tcg_temp_free_i64(t3);
>              tcg_gen_trunc_i64_tl(t0, t2);
>              tcg_gen_shri_i64(t2, t2, 32);
>              tcg_gen_trunc_i64_tl(t1, t2);
>              tcg_temp_free_i64(t2);
> -            tcg_gen_ext32s_tl(cpu_LO[0], t0);
> -            tcg_gen_ext32s_tl(cpu_HI[0], t1);
> +            tcg_gen_ext32s_tl(cpu_LO[acc], t0);
> +            tcg_gen_ext32s_tl(cpu_HI[acc], t1);
>          }
>          opn = "maddu";
>          break;
> @@ -2192,19 +2245,20 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
>          {
>              TCGv_i64 t2 = tcg_temp_new_i64();
>              TCGv_i64 t3 = tcg_temp_new_i64();
> +            acc = ((ctx->opcode) >> 11) & 0x03;
>  
>              tcg_gen_ext_tl_i64(t2, t0);
>              tcg_gen_ext_tl_i64(t3, t1);
>              tcg_gen_mul_i64(t2, t2, t3);
> -            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
> +            tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
>              tcg_gen_sub_i64(t2, t3, t2);
>              tcg_temp_free_i64(t3);
>              tcg_gen_trunc_i64_tl(t0, t2);
>              tcg_gen_shri_i64(t2, t2, 32);
>              tcg_gen_trunc_i64_tl(t1, t2);
>              tcg_temp_free_i64(t2);
> -            tcg_gen_ext32s_tl(cpu_LO[0], t0);
> -            tcg_gen_ext32s_tl(cpu_HI[0], t1);
> +            tcg_gen_ext32s_tl(cpu_LO[acc], t0);
> +            tcg_gen_ext32s_tl(cpu_HI[acc], t1);
>          }
>          opn = "msub";
>          break;
> @@ -2212,21 +2266,22 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
>          {
>              TCGv_i64 t2 = tcg_temp_new_i64();
>              TCGv_i64 t3 = tcg_temp_new_i64();
> +            acc = ((ctx->opcode) >> 11) & 0x03;
>  
>              tcg_gen_ext32u_tl(t0, t0);
>              tcg_gen_ext32u_tl(t1, t1);
>              tcg_gen_extu_tl_i64(t2, t0);
>              tcg_gen_extu_tl_i64(t3, t1);
>              tcg_gen_mul_i64(t2, t2, t3);
> -            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
> +            tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
>              tcg_gen_sub_i64(t2, t3, t2);
>              tcg_temp_free_i64(t3);
>              tcg_gen_trunc_i64_tl(t0, t2);
>              tcg_gen_shri_i64(t2, t2, 32);
>              tcg_gen_trunc_i64_tl(t1, t2);
>              tcg_temp_free_i64(t2);
> -            tcg_gen_ext32s_tl(cpu_LO[0], t0);
> -            tcg_gen_ext32s_tl(cpu_HI[0], t1);
> +            tcg_gen_ext32s_tl(cpu_LO[acc], t0);
> +            tcg_gen_ext32s_tl(cpu_HI[acc], t1);
>          }
>          opn = "msubu";
>          break;
> -- 
> 1.7.9.5
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v6 03/13] target-mips-ase-dsp: Add branch instructions
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 03/13] target-mips-ase-dsp: Add branch instructions Jia Liu
@ 2012-08-23 14:18   ` Aurelien Jarno
  0 siblings, 0 replies; 20+ messages in thread
From: Aurelien Jarno @ 2012-08-23 14:18 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Tue, Aug 21, 2012 at 02:53:09PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP Branch instructions.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/translate.c |   52 +++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 48 insertions(+), 4 deletions(-)
> 
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index 0793153..b049238 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -332,6 +332,14 @@ enum {
>      OPC_DSHD     = (0x05 << 6) | OPC_DBSHFL,
>  };
>  
> +/* MIPS DSP REGIMM opcodes */
> +enum {
> +    OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
> +#if defined(TARGET_MIPS64)
> +    OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
> +#endif
> +};
> +
>  /* Coprocessor 0 (rs field) */
>  #define MASK_CP0(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
>  
> @@ -2798,6 +2806,24 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
>          }
>          btgt = ctx->pc + insn_bytes + offset;
>          break;
> +    case OPC_BPOSGE32:
> +        tcg_gen_mov_tl(t0, cpu_dspctrl);
> +#if defined(TARGET_MIPS64)
> +        tcg_gen_andi_tl(t0, t0, 0x7F);
> +#else
> +        tcg_gen_andi_tl(t0, t0, 0x3F);
> +#endif

You can directly use cpu_dspctrl as the second argument of andi_tl. I
know this is optimized later by TCG, but it will still be faster if you
use less instructions.

> +        bcond_compute = 1;
> +        btgt = ctx->pc + insn_bytes + offset;
> +        break;
> +#if defined(TARGET_MIPS64)
> +    case OPC_BPOSGE64:
> +        tcg_gen_mov_tl(t0, cpu_dspctrl);
> +        tcg_gen_andi_tl(t0, t0, 0x7F);

Same here.

> +        bcond_compute = 1;
> +        btgt = ctx->pc + insn_bytes + offset;
> +        break;
> +#endif
>      case OPC_J:
>      case OPC_JAL:
>      case OPC_JALX:
> @@ -2986,6 +3012,16 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
>              tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
>              MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
>              goto likely;
> +        case OPC_BPOSGE32:
> +            tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
> +            MIPS_DEBUG("bposge32 %s, " TARGET_FMT_lx, t0, btgt);
> +            goto not_likely;
> +#if defined(TARGET_MIPS64)
> +        case OPC_BPOSGE64:
> +            tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
> +            MIPS_DEBUG("bposge64 %s, " TARGET_FMT_lx, t0, btgt);
> +            goto not_likely;
> +#endif
>          case OPC_BLTZALS:
>          case OPC_BLTZAL:
>              ctx->hflags |= (opc == OPC_BLTZALS
> @@ -11222,10 +11258,6 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
>                                  (ctx->opcode >> 18) & 0x7, imm << 1);
>              *is_branch = 1;
>              break;
> -        case BPOSGE64:
> -        case BPOSGE32:
> -            /* MIPS DSP: not implemented */
> -            /* Fall through */
>          default:
>              MIPS_INVAL("pool32i");
>              generate_exception(ctx, EXCP_RI);
> @@ -12134,6 +12166,18 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>              check_insn(env, ctx, ISA_MIPS32R2);
>              /* Treat as NOP. */
>              break;
> +        case OPC_BPOSGE32:    /* MIPS DSP branch */
> +            check_insn(env, ctx, ASE_DSP);

check_insn() is not enough there. It only checks if the CPU support the
instruction set, while the DSP ASE manual says that the DSPEn bit should
be set to allow execution of DSP instructions, otherwise a State
Disabled Exception should be generated. It's something important so that
the OS can do lazy context switching.

Please look for example at the check_cop1x() instruction to see how to
do that.

> +            gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
> +            *is_branch = 1;
> +            break;
> +#if defined(TARGET_MIPS64)
> +        case OPC_BPOSGE64:
> +            check_insn(env, ctx, ASE_DSP);
> +            gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
> +            *is_branch = 1;
> +            break;
> +#endif
>          default:            /* Invalid */
>              MIPS_INVAL("regimm");
>              generate_exception(ctx, EXCP_RI);
> -- 
> 1.7.9.5
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v6 04/13] target-mips-ase-dsp: Add load instructions
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 04/13] target-mips-ase-dsp: Add load instructions Jia Liu
@ 2012-08-23 14:23   ` Aurelien Jarno
  0 siblings, 0 replies; 20+ messages in thread
From: Aurelien Jarno @ 2012-08-23 14:23 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Tue, Aug 21, 2012 at 02:53:10PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP Load instructions.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/translate.c |   69 +++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 69 insertions(+)
> 
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index b049238..f154f09 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -313,6 +313,9 @@ enum {
>      OPC_MODU_G_2E   = 0x23 | OPC_SPECIAL3,
>      OPC_DMOD_G_2E   = 0x26 | OPC_SPECIAL3,
>      OPC_DMODU_G_2E  = 0x27 | OPC_SPECIAL3,
> +
> +    /* MIPS DSP Load */
> +    OPC_LX_DSP         = 0x0A | OPC_SPECIAL3,
>  };
>  
>  /* BSHFL opcodes */
> @@ -340,6 +343,17 @@ enum {
>  #endif
>  };
>  
> +#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
> +/* MIPS DSP Load */
> +enum {
> +    OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
> +    OPC_LHX  = (0x04 << 6) | OPC_LX_DSP,
> +    OPC_LWX  = (0x00 << 6) | OPC_LX_DSP,
> +#if defined(TARGET_MIPS64)
> +    OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
> +#endif
> +};
> +
>  /* Coprocessor 0 (rs field) */
>  #define MASK_CP0(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
>  
> @@ -12124,6 +12138,61 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>              check_insn(env, ctx, INSN_LOONGSON2E);
>              gen_loongson_integer(ctx, op1, rd, rs, rt);
>              break;
> +        case OPC_LX_DSP:
> +            op2 = MASK_LX(ctx->opcode);
> +            switch (op2) {
> +            case OPC_LBUX:
> +                check_insn(env, ctx, ASE_DSP);

How about factorizing the check_insn() code one level above?

> +                {
> +                    TCGv addr = tcg_temp_new();
> +
> +                    save_cpu_state(ctx, 1);

I don't think you need to save pc here, they are normal load
instructions.

> +                    gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]);
> +                    op_ld_lbu(cpu_gpr[rd], addr, ctx);
> +                    tcg_temp_free(addr);
> +                    break;
> +                }
> +            case OPC_LHX:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    TCGv addr = tcg_temp_new();
> +
> +                    save_cpu_state(ctx, 1);
> +                    gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]);
> +                    op_ld_lh(cpu_gpr[rd], addr, ctx);
> +                    tcg_temp_free(addr);
> +                    break;
> +                }
> +            case OPC_LWX:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    TCGv addr = tcg_temp_new();
> +
> +                    save_cpu_state(ctx, 1);
> +                    gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]);
> +                    op_ld_lw(cpu_gpr[rd], addr, ctx);
> +                    tcg_temp_free(addr);
> +                    break;
> +                }
> +#if defined(TARGET_MIPS64)
> +            case OPC_LDX:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    TCGv addr = tcg_temp_new();
> +
> +                    save_cpu_state(ctx, 1);
> +                    gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]);
> +                    op_ld_ld(cpu_gpr[rd], addr, ctx);
> +                    tcg_temp_free(addr);
> +                    break;
> +                }
> +#endif
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK LX");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
>  #if defined(TARGET_MIPS64)
>          case OPC_DEXTM ... OPC_DEXT:
>          case OPC_DINSM ... OPC_DINS:
> -- 
> 1.7.9.5
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v6 05/13] target-mips-ase-dsp: Add arithmetic instructions
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 05/13] target-mips-ase-dsp: Add arithmetic instructions Jia Liu
@ 2012-08-23 14:28   ` Aurelien Jarno
  0 siblings, 0 replies; 20+ messages in thread
From: Aurelien Jarno @ 2012-08-23 14:28 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Tue, Aug 21, 2012 at 02:53:11PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP Arithmetic instructions.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/dsp_helper.c | 1929 ++++++++++++++++++++++++++++++++++++++++++++++
>  target-mips/helper.h     |  132 ++++
>  target-mips/translate.c  |  675 ++++++++++++++++
>  3 files changed, 2736 insertions(+)
> 
> diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
> index a7d6c7e..486b22f 100644
> --- a/target-mips/dsp_helper.c
> +++ b/target-mips/dsp_helper.c
> @@ -1275,3 +1275,1932 @@ static inline int32_t mipsdsp_add_i32(CPUMIPSState *env, int32_t a, int32_t b)
>      return result;
>  }
>  /*** MIPS DSP internal functions end ***/
> +
> +#define MIPSDSP_LHI 0xFFFFFFFF00000000ull
> +#define MIPSDSP_LLO 0x00000000FFFFFFFFull
> +#define MIPSDSP_HI  0xFFFF0000
> +#define MIPSDSP_LO  0x0000FFFF
> +#define MIPSDSP_Q3  0xFF000000
> +#define MIPSDSP_Q2  0x00FF0000
> +#define MIPSDSP_Q1  0x0000FF00
> +#define MIPSDSP_Q0  0x000000FF
> +
> +/** DSP Arithmetic Sub-class insns **/
> +target_ulong helper_addq_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    int16_t  rsh, rsl, rth, rtl, temph, templ;
> +    uint32_t rd;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +
> +    temph = mipsdsp_add_i16(env, rsh, rth);
> +    templ = mipsdsp_add_i16(env, rsl, rtl);
> +    rd = ((unsigned int)temph << 16) | ((unsigned int)templ & 0xFFFF);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_addq_s_ph(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    int16_t rsh, rsl, rth, rtl, temph, templ;
> +    uint32_t rd;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +
> +    temph = mipsdsp_sat_add_i16(env, rsh, rth);
> +    templ = mipsdsp_sat_add_i16(env, rsl, rtl);
> +    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & 0xFFFF);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_addq_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rs3, rs2, rs1, rs0;
> +    uint16_t rt3, rt2, rt1, rt0;
> +    uint16_t tempD, tempC, tempB, tempA;
> +    uint64_t temp;
> +
> +    rs3 = (rs >> 48) & MIPSDSP_LO;
> +    rs2 = (rs >> 32) & MIPSDSP_LO;
> +    rs1 = (rs >> 16) & MIPSDSP_LO;
> +    rs0 = rs & MIPSDSP_LO;
> +    rt3 = (rt >> 48) & MIPSDSP_LO;
> +    rt2 = (rt >> 32) & MIPSDSP_LO;
> +    rt1 = (rt >> 16) & MIPSDSP_LO;
> +    rt0 = rt & MIPSDSP_LO;
> +
> +    tempD = mipsdsp_add_i16(env, rs3, rt3);
> +    tempC = mipsdsp_add_i16(env, rs2, rt2);
> +    tempB = mipsdsp_add_i16(env, rs1, rt1);
> +    tempA = mipsdsp_add_i16(env, rs0, rt0);
> +
> +    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
> +      ((uint64_t)tempB << 16) | (uint64_t)tempA;
> +
> +    return temp;
> +}
> +
> +target_ulong helper_addq_s_qh(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rs3, rs2, rs1, rs0;
> +    uint16_t rt3, rt2, rt1, rt0;
> +    uint16_t tempD, tempC, tempB, tempA;
> +    uint64_t temp;
> +
> +    rs3 = (rs >> 48) & MIPSDSP_LO;
> +    rs2 = (rs >> 32) & MIPSDSP_LO;
> +    rs1 = (rs >> 16) & MIPSDSP_LO;
> +    rs0 = rs & MIPSDSP_LO;
> +    rt3 = (rt >> 48) & MIPSDSP_LO;
> +    rt2 = (rt >> 32) & MIPSDSP_LO;
> +    rt1 = (rt >> 16) & MIPSDSP_LO;
> +    rt0 = rt & MIPSDSP_LO;
> +
> +    tempD = mipsdsp_sat_add_i16(env, rs3, rt3);
> +    tempC = mipsdsp_sat_add_i16(env, rs2, rt2);
> +    tempB = mipsdsp_sat_add_i16(env, rs1, rt1);
> +    tempA = mipsdsp_sat_add_i16(env, rs0, rt0);
> +
> +    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
> +      ((uint64_t)tempB << 16) | (uint64_t)tempA;
> +
> +    return temp;
> +}
> +#endif
> +
> +target_ulong helper_addq_s_w(CPUMIPSState *env,
> +                             target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +    rd = mipsdsp_sat_add_i32(env, rs, rt);
> +    return (target_long)(int32_t)rd;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_addq_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rs1, rs0;
> +    uint32_t rt1, rt0;
> +    uint32_t tempB, tempA;
> +    uint64_t temp;
> +
> +    rs1 = (rs >> 32) & MIPSDSP_LLO;
> +    rs0 = rs & MIPSDSP_LLO;
> +    rt1 = (rt >> 32) & MIPSDSP_LLO;
> +    rt0 = rt & MIPSDSP_LLO;
> +
> +    tempB = mipsdsp_add_i32(env, rs1, rt1);
> +    tempA = mipsdsp_add_i32(env, rs0, rt0);
> +
> +    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
> +
> +    return temp;
> +}
> +
> +target_ulong helper_addq_s_pw(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rs1, rs0;
> +    uint32_t rt1, rt0;
> +    uint32_t tempB, tempA;
> +    uint64_t temp;
> +
> +    rs1 = (rs >> 32) & MIPSDSP_LLO;
> +    rs0 = rs & MIPSDSP_LLO;
> +    rt1 = (rt >> 32) & MIPSDSP_LLO;
> +    rt0 = rt & MIPSDSP_LLO;
> +
> +    tempB = mipsdsp_sat_add_i32(env, rs1, rt1);
> +    tempA = mipsdsp_sat_add_i32(env, rs0, rt0);
> +
> +    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
> +
> +    return temp;
> +}
> +#endif
> +
> +target_ulong helper_addu_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +    uint8_t  rs0, rs1, rs2, rs3;
> +    uint8_t  rt0, rt1, rt2, rt3;
> +    uint8_t  temp0, temp1, temp2, temp3;
> +
> +    rs0 =  rs & MIPSDSP_Q0;
> +    rs1 = (rs & MIPSDSP_Q1) >>  8;
> +    rs2 = (rs & MIPSDSP_Q2) >> 16;
> +    rs3 = (rs & MIPSDSP_Q3) >> 24;
> +
> +    rt0 =  rt & MIPSDSP_Q0;
> +    rt1 = (rt & MIPSDSP_Q1) >>  8;
> +    rt2 = (rt & MIPSDSP_Q2) >> 16;
> +    rt3 = (rt & MIPSDSP_Q3) >> 24;
> +
> +    temp0 = mipsdsp_add_u8(env, rs0, rt0);
> +    temp1 = mipsdsp_add_u8(env, rs1, rt1);
> +    temp2 = mipsdsp_add_u8(env, rs2, rt2);
> +    temp3 = mipsdsp_add_u8(env, rs3, rt3);
> +
> +    rd = (((uint32_t)temp3 << 24) & MIPSDSP_Q3) |
> +         (((uint32_t)temp2 << 16) & MIPSDSP_Q2) |
> +         (((uint32_t)temp1 <<  8) & MIPSDSP_Q1) |
> +         ((uint32_t)temp0         & MIPSDSP_Q0);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_addu_s_qb(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +    uint8_t rs0, rs1, rs2, rs3;
> +    uint8_t rt0, rt1, rt2, rt3;
> +    uint8_t temp0, temp1, temp2, temp3;
> +
> +    rs0 =  rs & MIPSDSP_Q0;
> +    rs1 = (rs & MIPSDSP_Q1) >>  8;
> +    rs2 = (rs & MIPSDSP_Q2) >> 16;
> +    rs3 = (rs & MIPSDSP_Q3) >> 24;
> +
> +    rt0 =  rt & MIPSDSP_Q0;
> +    rt1 = (rt & MIPSDSP_Q1) >>  8;
> +    rt2 = (rt & MIPSDSP_Q2) >> 16;
> +    rt3 = (rt & MIPSDSP_Q3) >> 24;
> +
> +    temp0 = mipsdsp_sat_add_u8(env, rs0, rt0);
> +    temp1 = mipsdsp_sat_add_u8(env, rs1, rt1);
> +    temp2 = mipsdsp_sat_add_u8(env, rs2, rt2);
> +    temp3 = mipsdsp_sat_add_u8(env, rs3, rt3);
> +
> +    rd = (((uint8_t)temp3 << 24) & MIPSDSP_Q3) |
> +         (((uint8_t)temp2 << 16) & MIPSDSP_Q2) |
> +         (((uint8_t)temp1 <<  8) & MIPSDSP_Q1) |
> +         ((uint8_t)temp0         & MIPSDSP_Q0);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_adduh_qb(target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +    uint8_t  rs0, rs1, rs2, rs3;
> +    uint8_t  rt0, rt1, rt2, rt3;
> +    uint8_t  temp0, temp1, temp2, temp3;
> +
> +    rs0 =  rs & MIPSDSP_Q0;
> +    rs1 = (rs & MIPSDSP_Q1) >>  8;
> +    rs2 = (rs & MIPSDSP_Q2) >> 16;
> +    rs3 = (rs & MIPSDSP_Q3) >> 24;
> +
> +    rt0 =  rt & MIPSDSP_Q0;
> +    rt1 = (rt & MIPSDSP_Q1) >>  8;
> +    rt2 = (rt & MIPSDSP_Q2) >> 16;
> +    rt3 = (rt & MIPSDSP_Q3) >> 24;
> +
> +    temp0 = mipsdsp_rshift1_add_u8(rs0, rt0);
> +    temp1 = mipsdsp_rshift1_add_u8(rs1, rt1);
> +    temp2 = mipsdsp_rshift1_add_u8(rs2, rt2);
> +    temp3 = mipsdsp_rshift1_add_u8(rs3, rt3);
> +
> +    rd = (((uint32_t)temp3 << 24) & MIPSDSP_Q3) |
> +         (((uint32_t)temp2 << 16) & MIPSDSP_Q2) |
> +         (((uint32_t)temp1 <<  8) & MIPSDSP_Q1) |
> +         ((uint32_t)temp0         & MIPSDSP_Q0);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_adduh_r_qb(target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +    uint8_t  rs0, rs1, rs2, rs3;
> +    uint8_t  rt0, rt1, rt2, rt3;
> +    uint8_t  temp0, temp1, temp2, temp3;
> +
> +    rs0 =  rs & MIPSDSP_Q0;
> +    rs1 = (rs & MIPSDSP_Q1) >>  8;
> +    rs2 = (rs & MIPSDSP_Q2) >> 16;
> +    rs3 = (rs & MIPSDSP_Q3) >> 24;
> +
> +    rt0 =  rt & MIPSDSP_Q0;
> +    rt1 = (rt & MIPSDSP_Q1) >>  8;
> +    rt2 = (rt & MIPSDSP_Q2) >> 16;
> +    rt3 = (rt & MIPSDSP_Q3) >> 24;
> +
> +    temp0 = mipsdsp_rrshift1_add_u8(rs0, rt0);
> +    temp1 = mipsdsp_rrshift1_add_u8(rs1, rt1);
> +    temp2 = mipsdsp_rrshift1_add_u8(rs2, rt2);
> +    temp3 = mipsdsp_rrshift1_add_u8(rs3, rt3);
> +
> +    rd = (((uint32_t)temp3 << 24) & MIPSDSP_Q3) |
> +         (((uint32_t)temp2 << 16) & MIPSDSP_Q2) |
> +         (((uint32_t)temp1 <<  8) & MIPSDSP_Q1) |
> +         ((uint32_t)temp0         & MIPSDSP_Q0);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_addu_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rsh, rsl, rth, rtl, temph, templ;
> +    uint32_t rd;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +    temph = mipsdsp_add_u16(env, rsh, rth);
> +    templ = mipsdsp_add_u16(env, rsl, rtl);
> +    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_addu_s_ph(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rsh, rsl, rth, rtl, temph, templ;
> +    uint32_t rd;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +    temph = mipsdsp_sat_add_u16(env, rsh, rth);
> +    templ = mipsdsp_sat_add_u16(env, rsl, rtl);
> +    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_addqh_ph(target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +    int16_t rsh, rsl, rth, rtl, temph, templ;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +
> +    temph = mipsdsp_rshift1_add_q16(rsh, rth);
> +    templ = mipsdsp_rshift1_add_q16(rsl, rtl);
> +    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_addqh_r_ph(target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +    int16_t rsh, rsl, rth, rtl, temph, templ;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +
> +    temph = mipsdsp_rrshift1_add_q16(rsh, rth);
> +    templ = mipsdsp_rrshift1_add_q16(rsl, rtl);
> +    rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_addqh_w(target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +
> +    rd = mipsdsp_rshift1_add_q32(rs, rt);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_addqh_r_w(target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +
> +    rd = mipsdsp_rrshift1_add_q32(rs, rt);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_addu_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    int i;
> +    uint8_t rs_t[8], rt_t[8];
> +    uint8_t temp[8];
> +    uint64_t result;
> +
> +    result = 0;
> +
> +    for (i = 0; i < 8; i++) {
> +        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
> +        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
> +        temp[i] = mipsdsp_add_u8(env, rs_t[i], rt_t[i]);
> +    }
> +
> +    for (i = 0; i < 8; i++) {
> +        result |= (uint64_t)temp[i] << (8 * i);
> +    }
> +
> +    return result;
> +}
> +
> +target_ulong helper_addu_s_ob(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    int i;
> +    uint8_t rs_t[8], rt_t[8];
> +    uint8_t temp[8];
> +    uint64_t result;
> +
> +    result = 0;
> +
> +    for (i = 0; i < 8; i++) {
> +        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
> +        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
> +        temp[i] = mipsdsp_sat_add_u8(env, rs_t[i], rt_t[i]);
> +    }
> +
> +    for (i = 0; i < 8; i++) {
> +        result |= (uint64_t)temp[i] << (8 * i);
> +    }
> +
> +    return result;
> +}
> +
> +target_ulong helper_adduh_ob(target_ulong rs, target_ulong rt)
> +{
> +    int i;
> +    uint8_t rs_t[8], rt_t[8];
> +    uint8_t temp[8];
> +    uint64_t result;
> +
> +    result = 0;
> +
> +    for (i = 0; i < 8; i++) {
> +        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
> +        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
> +        temp[i] = mipsdsp_rshift1_add_u8(rs_t[i], rt_t[i]);
> +    }
> +
> +    for (i = 0; i < 8; i++) {
> +        result |= (uint64_t)temp[i] << (8 * i);
> +    }
> +
> +    return result;
> +}
> +
> +target_ulong helper_adduh_r_ob(target_ulong rs, target_ulong rt)
> +{
> +    int i;
> +    uint8_t rs_t[8], rt_t[8];
> +    uint8_t temp[8];
> +    uint64_t result;
> +
> +    result = 0;
> +
> +    for (i = 0; i < 8; i++) {
> +        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
> +        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
> +        temp[i] = mipsdsp_rrshift1_add_u8(rs_t[i], rt_t[i]);
> +    }
> +
> +    for (i = 0; i < 8; i++) {
> +        result |= (uint64_t)temp[i] << (8 * i);
> +    }
> +
> +    return result;
> +}
> +
> +target_ulong helper_addu_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rs3, rs2, rs1, rs0;
> +    uint16_t rt3, rt2, rt1, rt0;
> +    uint16_t tempD, tempC, tempB, tempA;
> +    uint64_t temp;
> +
> +    rs3 = (rs >> 48) & MIPSDSP_LO;
> +    rs2 = (rs >> 32) & MIPSDSP_LO;
> +    rs1 = (rs >> 16) & MIPSDSP_LO;
> +    rs0 = rs & MIPSDSP_LO;
> +    rt3 = (rt >> 48) & MIPSDSP_LO;
> +    rt2 = (rt >> 32) & MIPSDSP_LO;
> +    rt1 = (rt >> 16) & MIPSDSP_LO;
> +    rt0 = rt & MIPSDSP_LO;
> +
> +    tempD = mipsdsp_add_u16(env, rs3, rt3);
> +    tempC = mipsdsp_add_u16(env, rs2, rt2);
> +    tempB = mipsdsp_add_u16(env, rs1, rt1);
> +    tempA = mipsdsp_add_u16(env, rs0, rt0);
> +
> +    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
> +           ((uint64_t)tempB << 16) | (uint64_t)tempA;
> +
> +    return temp;
> +}
> +
> +target_ulong helper_addu_s_qh(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rs3, rs2, rs1, rs0;
> +    uint16_t rt3, rt2, rt1, rt0;
> +    uint16_t tempD, tempC, tempB, tempA;
> +    uint64_t temp;
> +
> +    rs3 = (rs >> 48) & MIPSDSP_LO;
> +    rs2 = (rs >> 32) & MIPSDSP_LO;
> +    rs1 = (rs >> 16) & MIPSDSP_LO;
> +    rs0 = rs & MIPSDSP_LO;
> +    rt3 = (rt >> 48) & MIPSDSP_LO;
> +    rt2 = (rt >> 32) & MIPSDSP_LO;
> +    rt1 = (rt >> 16) & MIPSDSP_LO;
> +    rt0 = rt & MIPSDSP_LO;
> +
> +    tempD = mipsdsp_sat_add_u16(env, rs3, rt3);
> +    tempC = mipsdsp_sat_add_u16(env, rs2, rt2);
> +    tempB = mipsdsp_sat_add_u16(env, rs1, rt1);
> +    tempA = mipsdsp_sat_add_u16(env, rs0, rt0);
> +
> +    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
> +           ((uint64_t)tempB << 16) | (uint64_t)tempA;
> +
> +    return temp;
> +}
> +#endif
> +
> +target_ulong helper_subq_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rsh, rsl;
> +    uint16_t rth, rtl;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +
> +    tempB = mipsdsp_sub_i16(env, rsh, rth);
> +    tempA = mipsdsp_sub_i16(env, rsl, rtl);
> +    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_subq_s_ph(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rsh, rsl;
> +    uint16_t rth, rtl;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +
> +    tempB = mipsdsp_sat16_sub(env, rsh, rth);
> +    tempA = mipsdsp_sat16_sub(env, rsl, rtl);
> +    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_subq_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rs3, rs2, rs1, rs0;
> +    uint16_t rt3, rt2, rt1, rt0;
> +    uint16_t tempD, tempC, tempB, tempA;
> +    uint64_t temp;
> +
> +    rs3 = (rs >> 48) & MIPSDSP_LO;
> +    rs2 = (rs >> 32) & MIPSDSP_LO;
> +    rs1 = (rs >> 16) & MIPSDSP_LO;
> +    rs0 = rs & MIPSDSP_LO;
> +    rt3 = (rt >> 48) & MIPSDSP_LO;
> +    rt2 = (rt >> 32) & MIPSDSP_LO;
> +    rt1 = (rt >> 16) & MIPSDSP_LO;
> +    rt0 = rt & MIPSDSP_LO;
> +
> +    tempD = mipsdsp_sub_i16(env, rs3, rt3);
> +    tempC = mipsdsp_sub_i16(env, rs2, rt2);
> +    tempB = mipsdsp_sub_i16(env, rs1, rt1);
> +    tempA = mipsdsp_sub_i16(env, rs0, rt0);
> +
> +    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
> +      ((uint64_t)tempB << 16) | (uint64_t)tempA;
> +    return temp;
> +}
> +
> +target_ulong helper_subq_s_qh(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rs3, rs2, rs1, rs0;
> +    uint16_t rt3, rt2, rt1, rt0;
> +    uint16_t tempD, tempC, tempB, tempA;
> +    uint64_t temp;
> +    rs3 = (rs >> 48) & MIPSDSP_LO;
> +    rs2 = (rs >> 32) & MIPSDSP_LO;
> +    rs1 = (rs >> 16) & MIPSDSP_LO;
> +    rs0 = rs & MIPSDSP_LO;
> +    rt3 = (rt >> 48) & MIPSDSP_LO;
> +    rt2 = (rt >> 32) & MIPSDSP_LO;
> +    rt1 = (rt >> 16) & MIPSDSP_LO;
> +    rt0 = rt & MIPSDSP_LO;
> +
> +    tempD = mipsdsp_sat16_sub(env, rs3, rt3);
> +    tempC = mipsdsp_sat16_sub(env, rs2, rt2);
> +    tempB = mipsdsp_sat16_sub(env, rs1, rt1);
> +    tempA = mipsdsp_sat16_sub(env, rs0, rt0);
> +
> +    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
> +           ((uint64_t)tempB << 16) | (uint64_t)tempA;
> +    return temp;
> +}
> +#endif
> +
> +target_ulong helper_subq_s_w(CPUMIPSState *env,
> +                             target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +
> +    rd = mipsdsp_sat32_sub(env, rs, rt);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_subq_pw(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rs1, rs0;
> +    uint32_t rt1, rt0;
> +    uint32_t tempB, tempA;
> +    uint64_t temp;
> +
> +    rs1 = (rs >> 32) & MIPSDSP_LLO;
> +    rs0 = rs & MIPSDSP_LLO;
> +    rt1 = (rt >> 32) & MIPSDSP_LLO;
> +    rt0 = rt & MIPSDSP_LLO;
> +
> +    tempB = mipsdsp_sub32(env, rs1, rt1);
> +    tempA = mipsdsp_sub32(env, rs0, rt0);
> +
> +    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
> +    return temp;
> +}
> +
> +target_ulong helper_subq_s_pw(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rs1, rs0;
> +    uint32_t rt1, rt0;
> +    uint32_t tempB, tempA;
> +    uint64_t temp;
> +
> +    rs1 = (rs >> 32) & MIPSDSP_LLO;
> +    rs0 = rs & MIPSDSP_LLO;
> +    rt1 = (rt >> 32) & MIPSDSP_LLO;
> +    rt0 = rt & MIPSDSP_LLO;
> +
> +    tempB = mipsdsp_sat32_sub(env, rs1, rt1);
> +    tempA = mipsdsp_sat32_sub(env, rs0, rt0);
> +
> +    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
> +    return temp;
> +}
> +#endif
> +
> +target_ulong helper_subu_qb(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint8_t rs3, rs2, rs1, rs0;
> +    uint8_t rt3, rt2, rt1, rt0;
> +    uint8_t tempD, tempC, tempB, tempA;
> +    uint32_t rd;
> +
> +    rs3 = (rs & MIPSDSP_Q3) >> 24;
> +    rs2 = (rs & MIPSDSP_Q2) >> 16;
> +    rs1 = (rs & MIPSDSP_Q1) >>  8;
> +    rs0 =  rs & MIPSDSP_Q0;
> +
> +    rt3 = (rt & MIPSDSP_Q3) >> 24;
> +    rt2 = (rt & MIPSDSP_Q2) >> 16;
> +    rt1 = (rt & MIPSDSP_Q1) >>  8;
> +    rt0 =  rt & MIPSDSP_Q0;
> +
> +    tempD = mipsdsp_sub_u8(env, rs3, rt3);
> +    tempC = mipsdsp_sub_u8(env, rs2, rt2);
> +    tempB = mipsdsp_sub_u8(env, rs1, rt1);
> +    tempA = mipsdsp_sub_u8(env, rs0, rt0);
> +
> +    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
> +         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_subu_s_qb(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    uint8_t rs3, rs2, rs1, rs0;
> +    uint8_t rt3, rt2, rt1, rt0;
> +    uint8_t tempD, tempC, tempB, tempA;
> +    uint32_t rd;
> +
> +    rs3 = (rs & MIPSDSP_Q3) >> 24;
> +    rs2 = (rs & MIPSDSP_Q2) >> 16;
> +    rs1 = (rs & MIPSDSP_Q1) >>  8;
> +    rs0 =  rs & MIPSDSP_Q0;
> +
> +    rt3 = (rt & MIPSDSP_Q3) >> 24;
> +    rt2 = (rt & MIPSDSP_Q2) >> 16;
> +    rt1 = (rt & MIPSDSP_Q1) >>  8;
> +    rt0 =  rt & MIPSDSP_Q0;
> +
> +    tempD = mipsdsp_satu8_sub(env, rs3, rt3);
> +    tempC = mipsdsp_satu8_sub(env, rs2, rt2);
> +    tempB = mipsdsp_satu8_sub(env, rs1, rt1);
> +    tempA = mipsdsp_satu8_sub(env, rs0, rt0);
> +
> +    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
> +         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_subuh_qb(target_ulong rs, target_ulong rt)
> +{
> +    uint8_t rs3, rs2, rs1, rs0;
> +    uint8_t rt3, rt2, rt1, rt0;
> +    uint8_t tempD, tempC, tempB, tempA;
> +    uint32_t rd;
> +
> +    rs3 = (rs & MIPSDSP_Q3) >> 24;
> +    rs2 = (rs & MIPSDSP_Q2) >> 16;
> +    rs1 = (rs & MIPSDSP_Q1) >>  8;
> +    rs0 =  rs & MIPSDSP_Q0;
> +
> +    rt3 = (rt & MIPSDSP_Q3) >> 24;
> +    rt2 = (rt & MIPSDSP_Q2) >> 16;
> +    rt1 = (rt & MIPSDSP_Q1) >>  8;
> +    rt0 =  rt & MIPSDSP_Q0;
> +
> +    tempD = ((uint16_t)rs3 - (uint16_t)rt3) >> 1;
> +    tempC = ((uint16_t)rs2 - (uint16_t)rt2) >> 1;
> +    tempB = ((uint16_t)rs1 - (uint16_t)rt1) >> 1;
> +    tempA = ((uint16_t)rs0 - (uint16_t)rt0) >> 1;
> +
> +    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
> +         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
> +
> +    return (target_ulong)rd;
> +}
> +
> +target_ulong helper_subuh_r_qb(target_ulong rs, target_ulong rt)
> +{
> +    uint8_t rs3, rs2, rs1, rs0;
> +    uint8_t rt3, rt2, rt1, rt0;
> +    uint8_t tempD, tempC, tempB, tempA;
> +    uint32_t rd;
> +
> +    rs3 = (rs & MIPSDSP_Q3) >> 24;
> +    rs2 = (rs & MIPSDSP_Q2) >> 16;
> +    rs1 = (rs & MIPSDSP_Q1) >>  8;
> +    rs0 =  rs & MIPSDSP_Q0;
> +
> +    rt3 = (rt & MIPSDSP_Q3) >> 24;
> +    rt2 = (rt & MIPSDSP_Q2) >> 16;
> +    rt1 = (rt & MIPSDSP_Q1) >>  8;
> +    rt0 =  rt & MIPSDSP_Q0;
> +
> +    tempD = ((uint16_t)rs3 - (uint16_t)rt3 + 1) >> 1;
> +    tempC = ((uint16_t)rs2 - (uint16_t)rt2 + 1) >> 1;
> +    tempB = ((uint16_t)rs1 - (uint16_t)rt1 + 1) >> 1;
> +    tempA = ((uint16_t)rs0 - (uint16_t)rt0 + 1) >> 1;
> +
> +    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
> +         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
> +
> +    return (target_ulong)rd;
> +}
> +
> +target_ulong helper_subu_ph(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rsh, rsl, rth, rtl;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +
> +    tempB = mipsdsp_sub_u16_u16(env, rth, rsh);
> +    tempA = mipsdsp_sub_u16_u16(env, rtl, rsl);
> +    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_subu_s_ph(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rsh, rsl, rth, rtl;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +
> +    tempB = mipsdsp_satu16_sub_u16_u16(env, rth, rsh);
> +    tempA = mipsdsp_satu16_sub_u16_u16(env, rtl, rsl);
> +    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_subqh_ph(target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rsh, rsl;
> +    uint16_t rth, rtl;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +    tempB = mipsdsp_rshift1_sub_q16(rsh, rth);
> +    tempA = mipsdsp_rshift1_sub_q16(rsl, rtl);
> +    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_subqh_r_ph(target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rsh, rsl;
> +    uint16_t rth, rtl;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +    tempB = mipsdsp_rrshift1_sub_q16(rsh, rth);
> +    tempA = mipsdsp_rrshift1_sub_q16(rsl, rtl);
> +    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_subqh_w(target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +
> +    rd = mipsdsp_rshift1_sub_q32(rs, rt);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_subqh_r_w(target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +
> +    rd = mipsdsp_rrshift1_sub_q32(rs, rt);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_subu_ob(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    int i;
> +    uint8_t rs_t[8], rt_t[8];
> +    uint8_t temp[8];
> +    uint64_t result;
> +
> +    result = 0;
> +
> +    for (i = 0; i < 8; i++) {
> +        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
> +        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
> +        temp[i] = mipsdsp_sub_u8(env, rs_t[i], rt_t[i]);
> +    }
> +
> +    for (i = 0; i < 8; i++) {
> +        result += (uint64_t)temp[i] << (i * 8);
> +    }
> +
> +    return result;
> +}
> +
> +target_ulong helper_subu_s_ob(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    int i;
> +    uint8_t rs_t[8], rt_t[8];
> +    uint8_t temp[8];
> +    uint64_t result;
> +
> +    result = 0;
> +
> +    for (i = 0; i < 8; i++) {
> +        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
> +        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
> +        temp[i] = mipsdsp_satu8_sub(env, rs_t[i], rt_t[i]);
> +    }
> +
> +    for (i = 0; i < 8; i++) {
> +        result += (uint64_t)temp[i] << (i * 8);
> +    }
> +
> +    return result;
> +}
> +
> +target_ulong helper_subuh_ob(target_ulong rs, target_ulong rt)
> +{
> +    int i;
> +    uint8_t rs_t[8], rt_t[8];
> +    uint8_t temp[8];
> +    uint64_t result;
> +
> +    result = 0;
> +
> +    for (i = 0; i < 8; i++) {
> +        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
> +        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
> +        temp[i] = ((uint16_t)rs_t[i] - (uint16_t)rt_t[i]) >> 1;
> +      }
> +
> +    for (i = 0; i < 8; i++) {
> +        result |= (uint64_t)temp[i] << (8 * i);
> +    }
> +
> +    return result;
> +}
> +
> +target_ulong helper_subuh_r_ob(target_ulong rs, target_ulong rt)
> +{
> +    int i;
> +    uint8_t rs_t[8], rt_t[8];
> +    uint8_t temp[8];
> +    uint64_t result;
> +
> +    result = 0;
> +
> +    for (i = 0; i < 8; i++) {
> +        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
> +        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
> +        temp[i] = ((uint16_t)rs_t[i] - (uint16_t)rt_t[i] + 1) >> 1;
> +    }
> +
> +    for (i = 0; i < 8; i++) {
> +        result |= (uint64_t)temp[i] << (8 * i);
> +    }
> +
> +    return result;
> +}
> +
> +target_ulong helper_subu_qh(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rs3, rs2, rs1, rs0;
> +    uint16_t rt3, rt2, rt1, rt0;
> +    uint16_t tempD, tempC, tempB, tempA;
> +    uint64_t temp;
> +
> +    rs3 = (rs >> 48) & MIPSDSP_LO;
> +    rs2 = (rs >> 32) & MIPSDSP_LO;
> +    rs1 = (rs >> 16) & MIPSDSP_LO;
> +    rs0 = rs & MIPSDSP_LO;
> +    rt3 = (rt >> 48) & MIPSDSP_LO;
> +    rt2 = (rt >> 32) & MIPSDSP_LO;
> +    rt1 = (rt >> 16) & MIPSDSP_LO;
> +    rt0 = rt & MIPSDSP_LO;
> +
> +    tempD = mipsdsp_sub_u16_u16(env, rs3, rt3);
> +    tempC = mipsdsp_sub_u16_u16(env, rs2, rt2);
> +    tempB = mipsdsp_sub_u16_u16(env, rs1, rt1);
> +    tempA = mipsdsp_sub_u16_u16(env, rs0, rt0);
> +
> +    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
> +      ((uint64_t)tempB << 16) | (uint64_t)tempA;
> +    return temp;
> +}
> +
> +
> +target_ulong helper_subu_s_qh(CPUMIPSState *env,
> +                              target_ulong rs, target_ulong rt)
> +{
> +    uint16_t rs3, rs2, rs1, rs0;
> +    uint16_t rt3, rt2, rt1, rt0;
> +    uint16_t tempD, tempC, tempB, tempA;
> +    uint64_t temp;
> +
> +    rs3 = (rs >> 48) & MIPSDSP_LO;
> +    rs2 = (rs >> 32) & MIPSDSP_LO;
> +    rs1 = (rs >> 16) & MIPSDSP_LO;
> +    rs0 = rs & MIPSDSP_LO;
> +    rt3 = (rt >> 48) & MIPSDSP_LO;
> +    rt2 = (rt >> 32) & MIPSDSP_LO;
> +    rt1 = (rt >> 16) & MIPSDSP_LO;
> +    rt0 = rt & MIPSDSP_LO;
> +
> +    tempD = mipsdsp_satu16_sub_u16_u16(env, rs3, rt3);
> +    tempC = mipsdsp_satu16_sub_u16_u16(env, rs2, rt2);
> +    tempB = mipsdsp_satu16_sub_u16_u16(env, rs1, rt1);
> +    tempA = mipsdsp_satu16_sub_u16_u16(env, rs0, rt0);
> +
> +    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
> +           ((uint64_t)tempB << 16) | (uint64_t)tempA;
> +    return temp;
> +}
> +#endif
> +
> +target_ulong helper_addsc(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +    uint64_t temp, tempRs, tempRt;
> +    int32_t flag;
> +
> +    tempRs = (uint64_t)rs & MIPSDSP_LLO;
> +    tempRt = (uint64_t)rt & MIPSDSP_LLO;
> +
> +    temp = tempRs + tempRt;
> +    flag = (temp & 0x0100000000ull) >> 32;
> +    set_DSPControl_carryflag(env, flag);
> +    rd = temp & MIPSDSP_LLO;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_addwc(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rd;
> +    int32_t temp32, temp31;
> +    int64_t rsL, rtL, tempL;
> +
> +    rsL = (int32_t)rs;
> +    rtL = (int32_t)rt;
> +    tempL = rsL + rtL + get_DSPControl_carryflag(env);
> +    temp31 = (tempL >> 31) & 0x01;
> +    temp32 = (tempL >> 32) & 0x01;
> +
> +    if (temp31 != temp32) {
> +        set_DSPControl_overflow_flag(env, 1, 20);
> +    }
> +
> +    rd = tempL & MIPSDSP_LLO;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_modsub(target_ulong rs, target_ulong rt)
> +{
> +    int32_t decr;
> +    uint16_t lastindex;
> +    target_ulong rd;
> +
> +    decr = rt & MIPSDSP_Q0;
> +    lastindex = (rt >> 8) & MIPSDSP_LO;
> +
> +    if ((rs & MIPSDSP_LLO) == 0x00000000) {
> +        rd = (target_ulong)lastindex;
> +    } else {
> +        rd = rs - decr;
> +    }
> +
> +    return rd;
> +}
> +
> +target_ulong helper_raddu_w_qb(target_ulong rs)
> +{
> +    uint8_t  rs3, rs2, rs1, rs0;
> +    uint16_t temp;
> +    uint32_t rd;
> +
> +    rs3 = (rs & MIPSDSP_Q3) >> 24;
> +    rs2 = (rs & MIPSDSP_Q2) >> 16;
> +    rs1 = (rs & MIPSDSP_Q1) >>  8;
> +    rs0 =  rs & MIPSDSP_Q0;
> +
> +    temp = (uint16_t)rs3 + (uint16_t)rs2 + (uint16_t)rs1 + (uint16_t)rs0;
> +    rd = temp;
> +
> +    return (target_ulong)rd;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_raddu_l_ob(target_ulong rs)
> +{
> +    int i;
> +    uint16_t rs_t[8];
> +    uint64_t temp;
> +
> +    temp = 0;
> +
> +    for (i = 0; i < 8; i++) {
> +        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
> +        temp += (uint64_t)rs_t[i];
> +    }
> +
> +    return temp;
> +}
> +#endif
> +
> +target_ulong helper_absq_s_qb(CPUMIPSState *env, target_ulong rt)
> +{
> +    uint32_t rd;
> +    int8_t tempD, tempC, tempB, tempA;
> +
> +    tempD = (rt & MIPSDSP_Q3) >> 24;
> +    tempC = (rt & MIPSDSP_Q2) >> 16;
> +    tempB = (rt & MIPSDSP_Q1) >>  8;
> +    tempA =  rt & MIPSDSP_Q0;
> +
> +    rd = (((uint32_t)mipsdsp_sat_abs_u8 (env, tempD) << 24) & MIPSDSP_Q3) |
> +         (((uint32_t)mipsdsp_sat_abs_u8 (env, tempC) << 16) & MIPSDSP_Q2) |
> +         (((uint32_t)mipsdsp_sat_abs_u8 (env, tempB) <<  8) & MIPSDSP_Q1) |
> +         ((uint32_t)mipsdsp_sat_abs_u8 (env, tempA) & MIPSDSP_Q0);
> +
> +    return (target_ulong)rd;
> +}
> +
> +target_ulong helper_absq_s_ph(CPUMIPSState *env, target_ulong rt)
> +{
> +    uint32_t rd;
> +    int16_t tempA, tempB;
> +
> +    tempA = (rt & MIPSDSP_HI) >> 16;
> +    tempB =  rt & MIPSDSP_LO;
> +
> +    rd = ((uint32_t)mipsdsp_sat_abs_u16 (env, tempA) << 16) |
> +         ((uint32_t)(mipsdsp_sat_abs_u16 (env, tempB)) & 0xFFFF);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_absq_s_w(CPUMIPSState *env, target_ulong rt)
> +{
> +    uint32_t rd;
> +    int32_t temp;
> +
> +    temp = rt;
> +    rd = mipsdsp_sat_abs_u32(env, temp);
> +
> +    return (target_ulong)rd;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_absq_s_ob(CPUMIPSState *env, target_ulong rt)
> +{
> +    uint8_t tempH, tempG, tempF, tempE;
> +    uint8_t tempD, tempC, tempB, tempA;
> +    uint64_t temp;
> +
> +    tempH = (rt >> 56) & MIPSDSP_Q0;
> +    tempG = (rt >> 48) & MIPSDSP_Q0;
> +    tempF = (rt >> 40) & MIPSDSP_Q0;
> +    tempE = (rt >> 32) & MIPSDSP_Q0;
> +    tempD = (rt >> 24) & MIPSDSP_Q0;
> +    tempC = (rt >> 16) & MIPSDSP_Q0;
> +    tempB = (rt >> 8) & MIPSDSP_Q0;
> +    tempA = rt & MIPSDSP_Q0;
> +
> +    tempH = mipsdsp_sat_abs_u8(env, tempH);
> +    tempG = mipsdsp_sat_abs_u8(env, tempG);
> +    tempF = mipsdsp_sat_abs_u8(env, tempF);
> +    tempE = mipsdsp_sat_abs_u8(env, tempE);
> +    tempD = mipsdsp_sat_abs_u8(env, tempD);
> +    tempC = mipsdsp_sat_abs_u8(env, tempC);
> +    tempB = mipsdsp_sat_abs_u8(env, tempB);
> +    tempA = mipsdsp_sat_abs_u8(env, tempA);
> +
> +    temp = ((uint64_t)tempH << 56) | ((uint64_t)tempG << 48) |
> +           ((uint64_t)tempF << 40) | ((uint64_t)tempE << 32) |
> +           ((uint64_t)tempD << 24) | ((uint64_t)tempC << 16) |
> +           ((uint64_t)tempB << 8) | (uint64_t)tempA;
> +
> +    return temp;
> +}
> +
> +target_ulong helper_absq_s_qh(CPUMIPSState *env, target_ulong rt)
> +{
> +    uint16_t tempD, tempC, tempB, tempA;
> +    uint64_t temp;
> +
> +    tempD = (rt >> 48) & MIPSDSP_LO;
> +    tempC = (rt >> 32) & MIPSDSP_LO;
> +    tempB = (rt >> 16) & MIPSDSP_LO;
> +    tempA = rt & MIPSDSP_LO;
> +
> +    tempD = mipsdsp_sat_abs_u16(env, tempD);
> +    tempC = mipsdsp_sat_abs_u16(env, tempC);
> +    tempB = mipsdsp_sat_abs_u16(env, tempB);
> +    tempA = mipsdsp_sat_abs_u16(env, tempA);
> +
> +    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
> +           ((uint64_t)tempB << 16) | (uint64_t)tempA;
> +
> +    return temp;
> +}
> +
> +target_ulong helper_absq_s_pw(CPUMIPSState *env, target_ulong rt)
> +{
> +    uint32_t tempB, tempA;
> +    uint64_t temp;
> +
> +    tempB = (rt >> 32) & MIPSDSP_LLO;
> +    tempA = rt & MIPSDSP_LLO;
> +
> +    tempB = mipsdsp_sat_abs_u32(env, tempB);
> +    tempA = mipsdsp_sat_abs_u32(env, tempA);
> +
> +    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
> +
> +    return temp;
> +}
> +#endif
> +
> +target_ulong helper_precr_qb_ph(target_ulong rs, target_ulong rt)
> +{
> +    uint8_t  rs2, rs0, rt2, rt0;
> +    uint32_t rd;
> +
> +    rs2 = (rs & MIPSDSP_Q2) >> 16;
> +    rs0 =  rs & MIPSDSP_Q0;
> +    rt2 = (rt & MIPSDSP_Q2) >> 16;
> +    rt0 =  rt & MIPSDSP_Q0;
> +    rd = ((uint32_t)rs2 << 24) | ((uint32_t)rs0 << 16) |
> +         ((uint32_t)rt2 <<  8) | (uint32_t)rt0;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_precrq_qb_ph(target_ulong rs, target_ulong rt)
> +{
> +    uint8_t tempD, tempC, tempB, tempA;
> +    uint32_t rd;
> +
> +    tempD = (rs & MIPSDSP_Q3) >> 24;
> +    tempC = (rs & MIPSDSP_Q1) >>  8;
> +    tempB = (rt & MIPSDSP_Q3) >> 24;
> +    tempA = (rt & MIPSDSP_Q1) >>  8;
> +
> +    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
> +         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs,
> +                                   target_ulong rt)
> +{
> +    uint16_t tempB, tempA;
> +
> +    if (sa == 0) {
> +        tempB = rt & MIPSDSP_LO;
> +        tempA = rs & MIPSDSP_LO;
> +    } else {
> +        tempB = ((int32_t)rt >> sa) & MIPSDSP_LO;
> +        tempA = ((int32_t)rs >> sa) & MIPSDSP_LO;
> +    }
> +    rt = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
> +
> +    return (target_long)(int32_t)rt;
> +}
> +
> +target_ulong helper_precr_sra_r_ph_w(uint32_t sa,
> +                                     target_ulong rs, target_ulong rt)
> +{
> +    uint64_t tempB, tempA;
> +
> +    if (sa == 0) {
> +        tempB = (rt & MIPSDSP_LO) << 1;
> +        tempA = (rs & MIPSDSP_LO) << 1;
> +    } else {
> +        tempB = ((int32_t)rt >> (sa - 1)) + 1;
> +        tempA = ((int32_t)rs >> (sa - 1)) + 1;
> +    }
> +    rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO);
> +
> +    return (target_long)(int32_t)rt;
> +}
> +
> +target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt)
> +{
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    tempB = (rs & MIPSDSP_HI) >> 16;
> +    tempA = (rt & MIPSDSP_HI) >> 16;
> +    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_precrq_rs_ph_w(CPUMIPSState *env,
> +                                   target_ulong rs, target_ulong rt)
> +{
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    tempB = mipsdsp_trunc16_sat16_round(env, rs);
> +    tempA = mipsdsp_trunc16_sat16_round(env, rt);
> +    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt)
> +{
> +    uint8_t rs6, rs4, rs2, rs0;
> +    uint8_t rt6, rt4, rt2, rt0;
> +    uint64_t temp;
> +
> +    rs6 = (rs >> 48) & MIPSDSP_Q0;
> +    rs4 = (rs >> 32) & MIPSDSP_Q0;
> +    rs2 = (rs >> 16) & MIPSDSP_Q0;
> +    rs0 = rs & MIPSDSP_Q0;
> +    rt6 = (rt >> 48) & MIPSDSP_Q0;
> +    rt4 = (rt >> 32) & MIPSDSP_Q0;
> +    rt2 = (rt >> 16) & MIPSDSP_Q0;
> +    rt0 = rt & MIPSDSP_Q0;
> +
> +    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
> +           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
> +           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
> +           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
> +
> +    return temp;
> +}
> +
> +target_ulong helper_precr_sra_qh_pw(target_ulong rs, target_ulong rt,
> +                                    uint32_t sa)
> +{
> +    uint16_t rs3, rs2, rs1, rs0;
> +    uint16_t rt3, rt2, rt1, rt0;
> +    uint16_t tempD, tempC, tempB, tempA;
> +    uint64_t result;
> +
> +    rs3 = (rs >> 48) & MIPSDSP_LO;
> +    rs2 = (rs >> 32) & MIPSDSP_LO;
> +    rs1 = (rs >> 16) & MIPSDSP_LO;
> +    rs0 = rs & MIPSDSP_LO;
> +    rt3 = (rt >> 48) & MIPSDSP_LO;
> +    rt2 = (rt >> 32) & MIPSDSP_LO;
> +    rt1 = (rt >> 16) & MIPSDSP_LO;
> +    rt0 = rt & MIPSDSP_LO;
> +
> +    if (sa == 0) {
> +        tempD = rt2;
> +        tempC = rt0;
> +        tempB = rs2;
> +        tempA = rs0;
> +    } else {
> +        tempD = (int16_t)rt3 >> sa;
> +        tempC = (int16_t)rt1 >> sa;
> +        tempB = (int16_t)rs3 >> sa;
> +        tempA = (int16_t)rs1 >> sa;
> +    }
> +
> +    result = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
> +             ((uint64_t)tempB << 16) | (uint64_t)tempA;
> +
> +    return result;
> +}
> +
> +
> +target_ulong helper_precr_sra_r_qh_pw(target_ulong rs, target_ulong rt,
> +                                      uint32_t sa)
> +{
> +    uint16_t rs3, rs2, rs1, rs0;
> +    uint16_t rt3, rt2, rt1, rt0;
> +    uint16_t tempD, tempC, tempB, tempA;
> +    uint64_t result;
> +
> +    rs3 = (rs >> 48) & MIPSDSP_LO;
> +    rs2 = (rs >> 32) & MIPSDSP_LO;
> +    rs1 = (rs >> 16) & MIPSDSP_LO;
> +    rs0 = rs & MIPSDSP_LO;
> +    rt3 = (rt >> 48) & MIPSDSP_LO;
> +    rt2 = (rt >> 32) & MIPSDSP_LO;
> +    rt1 = (rt >> 16) & MIPSDSP_LO;
> +    rt0 = rt & MIPSDSP_LO;
> +
> +    if (sa == 0) {
> +        tempD = rt2 << 1;
> +        tempC = rt0 << 1;
> +        tempB = rs2 << 1;
> +        tempA = rs0 << 1;
> +    } else {
> +        tempD = (((int16_t)rt3 >> sa) + 1) >> 1;
> +        tempC = (((int16_t)rt1 >> sa) + 1) >> 1;
> +        tempB = (((int16_t)rs3 >> sa) + 1) >> 1;
> +        tempA = (((int16_t)rs1 >> sa) + 1) >> 1;
> +    }
> +
> +    result = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
> +             ((uint64_t)tempB << 16) | (uint64_t)tempA;
> +
> +    return result;
> +}
> +
> +target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt)
> +{
> +    uint8_t rs6, rs4, rs2, rs0;
> +    uint8_t rt6, rt4, rt2, rt0;
> +    uint64_t temp;
> +
> +    rs6 = (rs >> 56) & MIPSDSP_Q0;
> +    rs4 = (rs >> 40) & MIPSDSP_Q0;
> +    rs2 = (rs >> 24) & MIPSDSP_Q0;
> +    rs0 = (rs >> 8) & MIPSDSP_Q0;
> +    rt6 = (rt >> 56) & MIPSDSP_Q0;
> +    rt4 = (rt >> 40) & MIPSDSP_Q0;
> +    rt2 = (rt >> 24) & MIPSDSP_Q0;
> +    rt0 = (rt >> 8) & MIPSDSP_Q0;
> +
> +    temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
> +           ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
> +           ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
> +           ((uint64_t)rt2 << 8) | (uint64_t)rt0;
> +
> +    return temp;
> +}
> +
> +target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt)
> +{
> +    uint16_t tempD, tempC, tempB, tempA;
> +    uint64_t temp;
> +
> +    tempD = (rs >> 48) & MIPSDSP_LO;
> +    tempC = (rs >> 16) & MIPSDSP_LO;
> +    tempB = (rt >> 48) & MIPSDSP_LO;
> +    tempA = (rt >> 16) & MIPSDSP_LO;
> +
> +    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
> +           ((uint64_t)tempB << 16) | (uint64_t)tempA;
> +
> +    return temp;
> +}
> +
> +target_ulong helper_precrq_rs_qh_pw(CPUMIPSState *env,
> +                                    target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rs2, rs0;
> +    uint32_t rt2, rt0;
> +    uint16_t tempD, tempC, tempB, tempA;
> +    uint64_t temp;
> +
> +    rs2 = (rs >> 32) & MIPSDSP_LLO;
> +    rs0 = rs & MIPSDSP_LLO;
> +    rt2 = (rt >> 32) & MIPSDSP_LLO;
> +    rt0 = rt & MIPSDSP_LLO;
> +
> +    tempD = mipsdsp_trunc16_sat16_round(env, rs2);
> +    tempC = mipsdsp_trunc16_sat16_round(env, rs0);
> +    tempB = mipsdsp_trunc16_sat16_round(env, rt2);
> +    tempA = mipsdsp_trunc16_sat16_round(env, rt0);
> +
> +    temp = ((uint64_t)tempD << 48) | ((uint64_t)tempC << 32) |
> +           ((uint64_t)tempB << 16) | (uint64_t)tempA;
> +
> +    return temp;
> +}
> +
> +target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt)
> +{
> +    uint32_t tempB, tempA;
> +    uint64_t temp;
> +
> +    tempB = (rs >> 32) & MIPSDSP_LLO;
> +    tempA = (rt >> 32) & MIPSDSP_LLO;
> +
> +    temp = ((uint64_t)tempB << 32) | (uint64_t)tempA;
> +
> +    return temp;
> +}
> +#endif
> +
> +target_ulong helper_precrqu_s_qb_ph(CPUMIPSState *env,
> +                                    target_ulong rs, target_ulong rt)
> +{
> +    uint8_t  tempD, tempC, tempB, tempA;
> +    uint16_t rsh, rsl, rth, rtl;
> +    uint32_t rd;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +
> +    tempD = mipsdsp_sat8_reduce_precision(env, rsh);
> +    tempC = mipsdsp_sat8_reduce_precision(env, rsl);
> +    tempB = mipsdsp_sat8_reduce_precision(env, rth);
> +    tempA = mipsdsp_sat8_reduce_precision(env, rtl);
> +
> +    rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |
> +         ((uint32_t)tempB <<  8) | (uint32_t)tempA;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_precrqu_s_ob_qh(CPUMIPSState *env,
> +                                    target_ulong rs, target_ulong rt)
> +{
> +    int i;
> +    uint16_t rs3, rs2, rs1, rs0;
> +    uint16_t rt3, rt2, rt1, rt0;
> +    uint8_t temp[8];
> +    uint64_t result;
> +
> +    result = 0;
> +
> +    rs3 = (rs >> 48) & MIPSDSP_LO;
> +    rs2 = (rs >> 32) & MIPSDSP_LO;
> +    rs1 = (rs >> 16) & MIPSDSP_LO;
> +    rs0 = rs & MIPSDSP_LO;
> +    rt3 = (rt >> 48) & MIPSDSP_LO;
> +    rt2 = (rt >> 32) & MIPSDSP_LO;
> +    rt1 = (rt >> 16) & MIPSDSP_LO;
> +    rt0 = rt & MIPSDSP_LO;
> +
> +    temp[7] = mipsdsp_sat8_reduce_precision(env, rs3);
> +    temp[6] = mipsdsp_sat8_reduce_precision(env, rs2);
> +    temp[5] = mipsdsp_sat8_reduce_precision(env, rs1);
> +    temp[4] = mipsdsp_sat8_reduce_precision(env, rs0);
> +    temp[3] = mipsdsp_sat8_reduce_precision(env, rt3);
> +    temp[2] = mipsdsp_sat8_reduce_precision(env, rt2);
> +    temp[1] = mipsdsp_sat8_reduce_precision(env, rt1);
> +    temp[0] = mipsdsp_sat8_reduce_precision(env, rt0);
> +
> +    for (i = 0; i < 8; i++) {
> +        result |= (uint64_t)temp[i] << (8 * i);
> +    }
> +
> +    return result;
> +}
> +#endif
> +
> +target_ulong helper_preceq_w_phl(target_ulong rt)
> +{
> +    uint32_t rd;
> +
> +    rd = rt & MIPSDSP_HI;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_preceq_w_phr(target_ulong rt)
> +{
> +    uint16_t rtl;
> +    uint32_t rd;
> +
> +    rtl = rt & MIPSDSP_LO;
> +    rd  = rtl << 16;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_preceq_pw_qhl(target_ulong rt)
> +{
> +    uint16_t tempB, tempA;
> +    uint32_t tempBI, tempAI;
> +    uint64_t temp;
> +
> +    tempB = (rt >> 48) & MIPSDSP_LO;
> +    tempA = (rt >> 32) & MIPSDSP_LO;
> +
> +    tempBI = (uint32_t)tempB << 16;
> +    tempAI = (uint32_t)tempA << 16;
> +
> +    temp = ((uint64_t)tempBI << 32) | ((uint64_t)tempAI);
> +
> +    return temp;
> +}
> +
> +target_ulong helper_preceq_pw_qhr(target_ulong rt)
> +{
> +    uint16_t tempB, tempA;
> +    uint32_t tempBI, tempAI;
> +    uint64_t temp;
> +
> +    tempB = (rt >> 16) & MIPSDSP_LO;
> +    tempA = rt & MIPSDSP_LO;
> +
> +    tempBI = (uint32_t)tempB << 16;
> +    tempAI = (uint32_t)tempA << 16;
> +
> +    temp = ((uint64_t)tempBI << 32) | ((uint64_t)tempAI);
> +
> +    return temp;
> +}
> +
> +target_ulong helper_preceq_pw_qhla(target_ulong rt)
> +{
> +    uint16_t tempB, tempA;
> +    uint32_t tempBI, tempAI;
> +    uint64_t temp;
> +
> +    tempB = (rt >> 48) & MIPSDSP_LO;
> +    tempA = (rt >> 16) & MIPSDSP_LO;
> +
> +    tempBI = (uint32_t)tempB << 16;
> +    tempAI = (uint32_t)tempA << 16;
> +
> +    temp = ((uint64_t)tempBI << 32) | ((uint64_t)tempAI);
> +
> +    return temp;
> +}
> +
> +target_ulong helper_preceq_pw_qhra(target_ulong rt)
> +{
> +    uint16_t tempB, tempA;
> +    uint32_t tempBI, tempAI;
> +    uint64_t temp;
> +
> +    tempB = (rt >> 32) & MIPSDSP_LO;
> +    tempA = rt & MIPSDSP_LO;
> +
> +    tempBI = (uint32_t)tempB << 16;
> +    tempAI = (uint32_t)tempA << 16;
> +
> +    temp = ((uint64_t)tempBI << 32) | ((uint64_t)tempAI);
> +
> +    return temp;
> +}
> +
> +target_ulong helper_preceq_l_pwl(target_ulong rt)
> +{
> +    uint64_t temp;
> +    temp = rt & MIPSDSP_LHI;
> +    return temp;
> +}
> +
> +target_ulong helper_preceq_l_pwr(target_ulong rt)
> +{
> +    uint64_t temp;
> +    temp = rt << 32;
> +    return temp;
> +}
> +#endif
> +
> +target_ulong helper_precequ_ph_qbl(target_ulong rt)
> +{
> +    uint8_t  rt3, rt2;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rt3 = (rt & MIPSDSP_Q3) >> 24;
> +    rt2 = (rt & MIPSDSP_Q2) >> 16;
> +
> +    tempB = (uint16_t)rt3 << 7;
> +    tempA = (uint16_t)rt2 << 7;
> +    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_precequ_ph_qbr(target_ulong rt)
> +{
> +    uint8_t  rt1, rt0;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rt1 = (rt & MIPSDSP_Q1) >> 8;
> +    rt0 =  rt & MIPSDSP_Q0;
> +    tempB = (uint16_t)rt1 << 7;
> +    tempA = (uint16_t)rt0 << 7;
> +    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_precequ_ph_qbla(target_ulong rt)
> +{
> +    uint8_t  rt3, rt1;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rt3 = (rt & MIPSDSP_Q3) >> 24;
> +    rt1 = (rt & MIPSDSP_Q1) >>  8;
> +
> +    tempB = (uint16_t)rt3 << 7;
> +    tempA = (uint16_t)rt1 << 7;
> +    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_precequ_ph_qbra(target_ulong rt)
> +{
> +    uint8_t  rt2, rt0;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rt2 = (rt & MIPSDSP_Q2) >> 16;
> +    rt0 =  rt & MIPSDSP_Q0;
> +    tempB = (uint16_t)rt2 << 7;
> +    tempA = (uint16_t)rt0 << 7;
> +    rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_precequ_qh_obl(target_ulong rt)
> +{
> +    uint8_t tempDC, tempCC, tempBC, tempAC;
> +    uint16_t tempDS, tempCS, tempBS, tempAS;
> +    uint64_t temp;
> +
> +    tempDC = (rt >> 56) & MIPSDSP_Q0;
> +    tempCC = (rt >> 48) & MIPSDSP_Q0;
> +    tempBC = (rt >> 40) & MIPSDSP_Q0;
> +    tempAC = (rt >> 32) & MIPSDSP_Q0;
> +
> +    tempDS = (uint16_t)tempDC << 7;
> +    tempCS = (uint16_t)tempCC << 7;
> +    tempBS = (uint16_t)tempBC << 7;
> +    tempAS = (uint16_t)tempAC << 7;
> +
> +    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
> +           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
> +    return temp;
> +}
> +
> +target_ulong helper_precequ_qh_obr(target_ulong rt)
> +{
> +    uint8_t tempDC, tempCC, tempBC, tempAC;
> +    uint16_t tempDS, tempCS, tempBS, tempAS;
> +    uint64_t temp;
> +
> +    tempDC = (rt >> 24) & MIPSDSP_Q0;
> +    tempCC = (rt >> 16) & MIPSDSP_Q0;
> +    tempBC = (rt >> 8) & MIPSDSP_Q0;
> +    tempAC = rt & MIPSDSP_Q0;
> +
> +    tempDS = (uint16_t)tempDC << 7;
> +    tempCS = (uint16_t)tempCC << 7;
> +    tempBS = (uint16_t)tempBC << 7;
> +    tempAS = (uint16_t)tempAC << 7;
> +
> +    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
> +           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
> +    return temp;
> +}
> +
> +target_ulong helper_precequ_qh_obla(target_ulong rt)
> +{
> +    uint8_t tempDC, tempCC, tempBC, tempAC;
> +    uint16_t tempDS, tempCS, tempBS, tempAS;
> +    uint64_t temp;
> +
> +    tempDC = (rt >> 56) & MIPSDSP_Q0;
> +    tempCC = (rt >> 40) & MIPSDSP_Q0;
> +    tempBC = (rt >> 24) & MIPSDSP_Q0;
> +    tempAC = (rt >> 8) & MIPSDSP_Q0;
> +
> +    tempDS = (uint16_t)tempDC << 7;
> +    tempCS = (uint16_t)tempCC << 7;
> +    tempBS = (uint16_t)tempBC << 7;
> +    tempAS = (uint16_t)tempAC << 7;
> +
> +    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
> +           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
> +    return temp;
> +}
> +
> +target_ulong helper_precequ_qh_obra(target_ulong rt)
> +{
> +    uint8_t tempDC, tempCC, tempBC, tempAC;
> +    uint16_t tempDS, tempCS, tempBS, tempAS;
> +    uint64_t temp;
> +
> +    tempDC = (rt >> 48) & MIPSDSP_Q0;
> +    tempCC = (rt >> 32) & MIPSDSP_Q0;
> +    tempBC = (rt >> 16) & MIPSDSP_Q0;
> +    tempAC = rt & MIPSDSP_Q0;
> +
> +    tempDS = (uint16_t)tempDC << 7;
> +    tempCS = (uint16_t)tempCC << 7;
> +    tempBS = (uint16_t)tempBC << 7;
> +    tempAS = (uint16_t)tempAC << 7;
> +
> +    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
> +           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
> +    return temp;
> +}
> +#endif
> +
> +target_ulong helper_preceu_ph_qbl(target_ulong rt)
> +{
> +    uint8_t  rt3, rt2;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rt3 = (rt & MIPSDSP_Q3) >> 24;
> +    rt2 = (rt & MIPSDSP_Q2) >> 16;
> +    tempB = (uint16_t) rt3;
> +    tempA = (uint16_t) rt2;
> +    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_preceu_ph_qbr(target_ulong rt)
> +{
> +    uint8_t  rt1, rt0;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rt1 = (rt & MIPSDSP_Q1) >> 8;
> +    rt0 =  rt & MIPSDSP_Q0;
> +    tempB = (uint16_t) rt1;
> +    tempA = (uint16_t) rt0;
> +    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_preceu_ph_qbla(target_ulong rt)
> +{
> +    uint8_t  rt3, rt1;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rt3 = (rt & MIPSDSP_Q3) >> 24;
> +    rt1 = (rt & MIPSDSP_Q1) >>  8;
> +    tempB = (uint16_t) rt3;
> +    tempA = (uint16_t) rt1;
> +    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
> +
> +    return (target_long)(int32_t)rd;
> +}
> +
> +target_ulong helper_preceu_ph_qbra(target_ulong rt)
> +{
> +    uint8_t  rt2, rt0;
> +    uint16_t tempB, tempA;
> +    uint32_t rd;
> +
> +    rt2 = (rt & MIPSDSP_Q2) >> 16;
> +    rt0 =  rt & MIPSDSP_Q0;
> +    tempB = (uint16_t)rt2;
> +    tempA = (uint16_t)rt0;
> +    rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
> +    return (target_long)(int32_t)rd;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_preceu_qh_obl(target_ulong rt)
> +{
> +    uint8_t tempDC, tempCC, tempBC, tempAC;
> +    uint16_t tempDS, tempCS, tempBS, tempAS;
> +    uint64_t temp;
> +
> +    tempDC = (rt >> 56) & MIPSDSP_Q0;
> +    tempCC = (rt >> 48) & MIPSDSP_Q0;
> +    tempBC = (rt >> 40) & MIPSDSP_Q0;
> +    tempAC = (rt >> 32) & MIPSDSP_Q0;
> +
> +    tempDS = (uint16_t)tempDC;
> +    tempCS = (uint16_t)tempCC;
> +    tempBS = (uint16_t)tempBC;
> +    tempAS = (uint16_t)tempAC;
> +
> +    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
> +           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
> +    return temp;
> +}
> +
> +target_ulong helper_preceu_qh_obr(target_ulong rt)
> +{
> +    uint8_t tempDC, tempCC, tempBC, tempAC;
> +    uint16_t tempDS, tempCS, tempBS, tempAS;
> +    uint64_t temp;
> +
> +    tempDC = (rt >> 24) & MIPSDSP_Q0;
> +    tempCC = (rt >> 16) & MIPSDSP_Q0;
> +    tempBC = (rt >> 8) & MIPSDSP_Q0;
> +    tempAC = rt & MIPSDSP_Q0;
> +
> +    tempDS = (uint16_t)tempDC;
> +    tempCS = (uint16_t)tempCC;
> +    tempBS = (uint16_t)tempBC;
> +    tempAS = (uint16_t)tempAC;
> +
> +    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
> +           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
> +    return temp;
> +}
> +
> +target_ulong helper_preceu_qh_obla(target_ulong rt)
> +{
> +    uint8_t tempDC, tempCC, tempBC, tempAC;
> +    uint16_t tempDS, tempCS, tempBS, tempAS;
> +    uint64_t temp;
> +
> +    tempDC = (rt >> 56) & MIPSDSP_Q0;
> +    tempCC = (rt >> 40) & MIPSDSP_Q0;
> +    tempBC = (rt >> 24) & MIPSDSP_Q0;
> +    tempAC = (rt >> 8) & MIPSDSP_Q0;
> +
> +    tempDS = (uint16_t)tempDC;
> +    tempCS = (uint16_t)tempCC;
> +    tempBS = (uint16_t)tempBC;
> +    tempAS = (uint16_t)tempAC;
> +
> +    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
> +           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
> +    return temp;
> +}
> +
> +target_ulong helper_preceu_qh_obra(target_ulong rt)
> +{
> +    uint8_t tempDC, tempCC, tempBC, tempAC;
> +    uint16_t tempDS, tempCS, tempBS, tempAS;
> +    uint64_t temp;
> +
> +    tempDC = (rt >> 48) & MIPSDSP_Q0;
> +    tempCC = (rt >> 32) & MIPSDSP_Q0;
> +    tempBC = (rt >> 16) & MIPSDSP_Q0;
> +    tempAC = rt & MIPSDSP_Q0;
> +
> +    tempDS = (uint16_t)tempDC;
> +    tempCS = (uint16_t)tempCC;
> +    tempBS = (uint16_t)tempBC;
> +    tempAS = (uint16_t)tempAC;
> +
> +    temp = ((uint64_t)tempDS << 48) | ((uint64_t)tempCS << 32) |
> +           ((uint64_t)tempBS << 16) | (uint64_t)tempAS;
> +    return temp;
> +}
> +#endif
> +
> +#undef MIPSDSP_LHI
> +#undef MIPSDSP_LLO
> +#undef MIPSDSP_HI
> +#undef MIPSDSP_LO
> +#undef MIPSDSP_Q3
> +#undef MIPSDSP_Q2
> +#undef MIPSDSP_Q1
> +#undef MIPSDSP_Q0
> diff --git a/target-mips/helper.h b/target-mips/helper.h
> index 76fb451..0607105 100644
> --- a/target-mips/helper.h
> +++ b/target-mips/helper.h
> @@ -297,4 +297,136 @@ DEF_HELPER_0(rdhwr_ccres, tl)
>  DEF_HELPER_1(pmon, void, int)
>  DEF_HELPER_0(wait, void)
>  
> +/*** MIPS DSP ***/
> +/* DSP Arithmetic Sub-class insns */
> +DEF_HELPER_FLAGS_3(addq_ph, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(addq_s_ph, 0, tl, env, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(addq_qh, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(addq_s_qh, 0, tl, env, tl, tl)
> +#endif
> +DEF_HELPER_FLAGS_3(addq_s_w, 0, tl, env, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(addq_pw, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(addq_s_pw, 0, tl, env, tl, tl)
> +#endif
> +DEF_HELPER_FLAGS_3(addu_qb, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(addu_s_qb, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_2(adduh_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(adduh_r_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_3(addu_ph, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(addu_s_ph, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_2(addqh_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(addqh_r_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(addqh_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(addqh_r_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(addu_ob, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(addu_s_ob, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_2(adduh_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(adduh_r_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_3(addu_qh, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(addu_s_qh, 0, tl, env, tl, tl)
> +#endif
> +DEF_HELPER_FLAGS_3(subq_ph, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(subq_s_ph, 0, tl, env, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(subq_qh, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(subq_s_qh, 0, tl, env, tl, tl)
> +#endif
> +DEF_HELPER_FLAGS_3(subq_s_w, 0, tl, env, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(subq_pw, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(subq_s_pw, 0, tl, env, tl, tl)
> +#endif
> +DEF_HELPER_FLAGS_3(subu_qb, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(subu_s_qb, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_2(subuh_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(subuh_r_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_3(subu_ph, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(subu_s_ph, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_2(subqh_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(subqh_r_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(subqh_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(subqh_r_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(subu_ob, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(subu_s_ob, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_2(subuh_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(subuh_r_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_3(subu_qh, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(subu_s_qh, 0, tl, env, tl, tl)
> +#endif
> +DEF_HELPER_FLAGS_3(addsc, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_3(addwc, 0, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_2(modsub, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_1(raddu_w_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_1(raddu_l_ob, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +#endif
> +DEF_HELPER_FLAGS_2(absq_s_qb, 0, tl, env, tl)
> +DEF_HELPER_FLAGS_2(absq_s_ph, 0, tl, env, tl)
> +DEF_HELPER_FLAGS_2(absq_s_w, 0, tl, env, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_2(absq_s_ob, 0, tl, env, tl)
> +DEF_HELPER_FLAGS_2(absq_s_qh, 0, tl, env, tl)
> +DEF_HELPER_FLAGS_2(absq_s_pw, 0, tl, env, tl)
> +#endif
> +DEF_HELPER_FLAGS_2(precr_qb_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(precrq_qb_ph, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_3(precr_sra_ph_w, TCG_CALL_CONST | TCG_CALL_PURE,
> +                   tl, i32, tl, tl)
> +DEF_HELPER_FLAGS_3(precr_sra_r_ph_w, TCG_CALL_CONST | TCG_CALL_PURE,
> +                   tl, i32, tl, tl)
> +DEF_HELPER_FLAGS_2(precrq_ph_w, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_3(precrq_rs_ph_w, 0, tl, env, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_2(precr_ob_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_3(precr_sra_qh_pw,
> +                   TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
> +DEF_HELPER_FLAGS_3(precr_sra_r_qh_pw,
> +                   TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, i32)
> +DEF_HELPER_FLAGS_2(precrq_ob_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(precrq_qh_pw, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_3(precrq_rs_qh_pw,
> +                   TCG_CALL_CONST | TCG_CALL_PURE, tl, env, tl, tl)
> +DEF_HELPER_FLAGS_2(precrq_pw_l, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +#endif
> +DEF_HELPER_FLAGS_3(precrqu_s_qb_ph, 0, tl, env, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(precrqu_s_ob_qh,
> +                   TCG_CALL_CONST | TCG_CALL_PURE, tl, env, tl, tl)
> +
> +#endif
> +DEF_HELPER_FLAGS_1(preceq_w_phl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(preceq_w_phr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_1(preceq_pw_qhl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(preceq_pw_qhr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(preceq_pw_qhla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(preceq_pw_qhra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(preceq_l_pwl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(preceq_l_pwr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +#endif
> +DEF_HELPER_FLAGS_1(precequ_ph_qbl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(precequ_ph_qbr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(precequ_ph_qbla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(precequ_ph_qbra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_1(precequ_qh_obl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(precequ_qh_obr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(precequ_qh_obla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(precequ_qh_obra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +#endif
> +DEF_HELPER_FLAGS_1(preceu_ph_qbl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(preceu_ph_qbr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(preceu_ph_qbla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(preceu_ph_qbra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_1(preceu_qh_obl, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(preceu_qh_obr, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(preceu_qh_obla, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_1(preceu_qh_obra, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +#endif
> +
>  #include "def-helper.h"
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index f154f09..0ea9131 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -316,6 +316,21 @@ enum {
>  
>      /* MIPS DSP Load */
>      OPC_LX_DSP         = 0x0A | OPC_SPECIAL3,
> +    /* MIPS DSP Arithmetic */
> +    OPC_ADDU_QB_DSP    = 0x10 | OPC_SPECIAL3,
> +#if defined(TARGET_MIPS64)
> +    OPC_ADDU_OB_DSP    = 0x14 | OPC_SPECIAL3,
> +#endif
> +    OPC_ABSQ_S_PH_DSP  = 0x12 | OPC_SPECIAL3,
> +#if defined(TARGET_MIPS64)
> +    OPC_ABSQ_S_QH_DSP  = 0x16 | OPC_SPECIAL3,
> +#endif
> +    /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E.  */
> +    /* OPC_ADDUH_QB_DSP   = 0x18 | OPC_SPECIAL3,  */
> +    OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
> +#if defined(TARGET_MIPS64)
> +    OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
> +#endif
>  };
>  
>  /* BSHFL opcodes */
> @@ -354,6 +369,144 @@ enum {
>  #endif
>  };
>  
> +#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
> +enum {
> +    /* MIPS DSP Arithmetic Sub-class */
> +    OPC_ADDQ_PH        = (0x0A << 6) | OPC_ADDU_QB_DSP,
> +    OPC_ADDQ_S_PH      = (0x0E << 6) | OPC_ADDU_QB_DSP,
> +    OPC_ADDQ_S_W       = (0x16 << 6) | OPC_ADDU_QB_DSP,
> +    OPC_ADDU_QB        = (0x00 << 6) | OPC_ADDU_QB_DSP,
> +    OPC_ADDU_S_QB      = (0x04 << 6) | OPC_ADDU_QB_DSP,
> +    OPC_ADDU_PH        = (0x08 << 6) | OPC_ADDU_QB_DSP,
> +    OPC_ADDU_S_PH      = (0x0C << 6) | OPC_ADDU_QB_DSP,
> +    OPC_SUBQ_PH        = (0x0B << 6) | OPC_ADDU_QB_DSP,
> +    OPC_SUBQ_S_PH      = (0x0F << 6) | OPC_ADDU_QB_DSP,
> +    OPC_SUBQ_S_W       = (0x17 << 6) | OPC_ADDU_QB_DSP,
> +    OPC_SUBU_QB        = (0x01 << 6) | OPC_ADDU_QB_DSP,
> +    OPC_SUBU_S_QB      = (0x05 << 6) | OPC_ADDU_QB_DSP,
> +    OPC_SUBU_PH        = (0x09 << 6) | OPC_ADDU_QB_DSP,
> +    OPC_SUBU_S_PH      = (0x0D << 6) | OPC_ADDU_QB_DSP,
> +    OPC_ADDSC          = (0x10 << 6) | OPC_ADDU_QB_DSP,
> +    OPC_ADDWC          = (0x11 << 6) | OPC_ADDU_QB_DSP,
> +    OPC_MODSUB         = (0x12 << 6) | OPC_ADDU_QB_DSP,
> +    OPC_RADDU_W_QB     = (0x14 << 6) | OPC_ADDU_QB_DSP,
> +};
> +
> +#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
> +#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
> +enum {
> +    /* MIPS DSP Arithmetic Sub-class */
> +    OPC_ADDUH_QB   = (0x00 << 6) | OPC_ADDUH_QB_DSP,
> +    OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
> +    OPC_ADDQH_PH   = (0x08 << 6) | OPC_ADDUH_QB_DSP,
> +    OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
> +    OPC_ADDQH_W    = (0x10 << 6) | OPC_ADDUH_QB_DSP,
> +    OPC_ADDQH_R_W  = (0x12 << 6) | OPC_ADDUH_QB_DSP,
> +    OPC_SUBUH_QB   = (0x01 << 6) | OPC_ADDUH_QB_DSP,
> +    OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
> +    OPC_SUBQH_PH   = (0x09 << 6) | OPC_ADDUH_QB_DSP,
> +    OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
> +    OPC_SUBQH_W    = (0x11 << 6) | OPC_ADDUH_QB_DSP,
> +    OPC_SUBQH_R_W  = (0x13 << 6) | OPC_ADDUH_QB_DSP,
> +};
> +
> +#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
> +enum {
> +    /* MIPS DSP Arithmetic Sub-class */
> +    OPC_ABSQ_S_QB       = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_ABSQ_S_PH       = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_ABSQ_S_W        = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_PRECEQ_W_PHL    = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_PRECEQ_W_PHR    = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_PRECEQU_PH_QBL  = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_PRECEQU_PH_QBR  = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_PRECEU_PH_QBL   = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_PRECEU_PH_QBR   = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_PRECEU_PH_QBLA  = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_PRECEU_PH_QBRA  = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
> +};
> +
> +#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
> +enum {
> +    /* MIPS DSP Arithmetic Sub-class */
> +    OPC_PRECR_QB_PH      = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
> +    OPC_PRECRQ_QB_PH     = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
> +    OPC_PRECR_SRA_PH_W   = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
> +    OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
> +    OPC_PRECRQ_PH_W      = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
> +    OPC_PRECRQ_RS_PH_W   = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
> +    OPC_PRECRQU_S_QB_PH  = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
> +};
> +
> +#if defined(TARGET_MIPS64)
> +#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
> +enum {
> +    /* MIPS DSP Arithmetic Sub-class */
> +    OPC_PRECEQ_L_PWL    = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_PRECEQ_L_PWR    = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_PRECEQ_PW_QHL   = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_PRECEQ_PW_QHR   = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_PRECEQ_PW_QHLA  = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_PRECEQ_PW_QHRA  = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_PRECEQU_QH_OBL  = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_PRECEQU_QH_OBR  = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_PRECEU_QH_OBL   = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_PRECEU_QH_OBR   = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_PRECEU_QH_OBLA  = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_PRECEU_QH_OBRA  = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_ABSQ_S_OB       = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_ABSQ_S_PW       = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_ABSQ_S_QH       = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
> +};
> +#endif
> +
> +#if defined(TARGET_MIPS64)
> +#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
> +enum {
> +    /* MIPS DSP Arithmetic Sub-class */
> +    OPC_RADDU_L_OB     = (0x14 << 6) | OPC_ADDU_OB_DSP,
> +    OPC_SUBQ_PW        = (0x13 << 6) | OPC_ADDU_OB_DSP,
> +    OPC_SUBQ_S_PW      = (0x17 << 6) | OPC_ADDU_OB_DSP,
> +    OPC_SUBQ_QH        = (0x0B << 6) | OPC_ADDU_OB_DSP,
> +    OPC_SUBQ_S_QH      = (0x0F << 6) | OPC_ADDU_OB_DSP,
> +    OPC_SUBU_OB        = (0x01 << 6) | OPC_ADDU_OB_DSP,
> +    OPC_SUBU_S_OB      = (0x05 << 6) | OPC_ADDU_OB_DSP,
> +    OPC_SUBU_QH        = (0x09 << 6) | OPC_ADDU_OB_DSP,
> +    OPC_SUBU_S_QH      = (0x0D << 6) | OPC_ADDU_OB_DSP,
> +    OPC_SUBUH_OB       = (0x19 << 6) | OPC_ADDU_OB_DSP,
> +    OPC_SUBUH_R_OB     = (0x1B << 6) | OPC_ADDU_OB_DSP,
> +    OPC_ADDQ_PW        = (0x12 << 6) | OPC_ADDU_OB_DSP,
> +    OPC_ADDQ_S_PW      = (0x16 << 6) | OPC_ADDU_OB_DSP,
> +    OPC_ADDQ_QH        = (0x0A << 6) | OPC_ADDU_OB_DSP,
> +    OPC_ADDQ_S_QH      = (0x0E << 6) | OPC_ADDU_OB_DSP,
> +    OPC_ADDU_OB        = (0x00 << 6) | OPC_ADDU_OB_DSP,
> +    OPC_ADDU_S_OB      = (0x04 << 6) | OPC_ADDU_OB_DSP,
> +    OPC_ADDU_QH        = (0x08 << 6) | OPC_ADDU_OB_DSP,
> +    OPC_ADDU_S_QH      = (0x0C << 6) | OPC_ADDU_OB_DSP,
> +    OPC_ADDUH_OB       = (0x18 << 6) | OPC_ADDU_OB_DSP,
> +    OPC_ADDUH_R_OB     = (0x1A << 6) | OPC_ADDU_OB_DSP,
> +};
> +#endif
> +
> +#if defined(TARGET_MIPS64)
> +#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
> +enum {
> +    /* MIPS DSP Arithmetic Sub-class */
> +    OPC_PRECR_OB_QH       = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
> +    OPC_PRECR_SRA_QH_PW   = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
> +    OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
> +    OPC_PRECRQ_OB_QH      = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
> +    OPC_PRECRQ_PW_L       = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
> +    OPC_PRECRQ_QH_PW      = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
> +    OPC_PRECRQ_RS_QH_PW   = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
> +    OPC_PRECRQU_S_OB_QH   = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
> +};
> +#endif
> +
>  /* Coprocessor 0 (rs field) */
>  #define MASK_CP0(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
>  
> @@ -12134,6 +12287,72 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>              break;
>          case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
>          case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
> +        /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
> +         * the same mask and op1. */
> +            if (op1 == OPC_MULT_G_2E) {
> +                int is_mult_g_2e = 0;
> +                op2 = MASK_ADDUH_QB(ctx->opcode);
> +                switch (op2) {
> +                case  OPC_ADDUH_QB:
> +                    check_insn(env, ctx, ASE_DSPR2);
> +                    gen_helper_adduh_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                    break;
> +                case  OPC_ADDUH_R_QB:
> +                    check_insn(env, ctx, ASE_DSPR2);
> +                    gen_helper_adduh_r_qb(cpu_gpr[rd],
> +                                          cpu_gpr[rs], cpu_gpr[rt]);
> +                    break;
> +                case  OPC_ADDQH_PH:
> +                    check_insn(env, ctx, ASE_DSPR2);
> +                    gen_helper_addqh_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                    break;
> +                case  OPC_ADDQH_R_PH:
> +                    check_insn(env, ctx, ASE_DSPR2);
> +                    gen_helper_addqh_r_ph(cpu_gpr[rd], cpu_gpr[rs],
> +                                          cpu_gpr[rt]);
> +                    break;
> +                case  OPC_ADDQH_W:
> +                    check_insn(env, ctx, ASE_DSPR2);
> +                    gen_helper_addqh_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                    break;
> +                case  OPC_ADDQH_R_W:
> +                    check_insn(env, ctx, ASE_DSPR2);
> +                    gen_helper_addqh_r_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                    break;
> +                case  OPC_SUBUH_QB:
> +                    check_insn(env, ctx, ASE_DSPR2);
> +                    gen_helper_subuh_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                    break;
> +                case  OPC_SUBUH_R_QB:
> +                    check_insn(env, ctx, ASE_DSPR2);
> +                    gen_helper_subuh_r_qb(cpu_gpr[rd],
> +                                          cpu_gpr[rs], cpu_gpr[rt]);
> +                    break;
> +                case  OPC_SUBQH_PH:
> +                    check_insn(env, ctx, ASE_DSPR2);
> +                    gen_helper_subqh_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                    break;
> +                case  OPC_SUBQH_R_PH:
> +                    check_insn(env, ctx, ASE_DSPR2);
> +                    gen_helper_subqh_r_ph(cpu_gpr[rd],
> +                                          cpu_gpr[rs], cpu_gpr[rt]);
> +                    break;
> +                case  OPC_SUBQH_W:
> +                    check_insn(env, ctx, ASE_DSPR2);
> +                    gen_helper_subqh_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                    break;
> +                case  OPC_SUBQH_R_W:
> +                    check_insn(env, ctx, ASE_DSPR2);
> +                    gen_helper_subqh_r_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                    break;
> +                default:
> +                    is_mult_g_2e = 1;
> +                    break;
> +                }



Due to instruction conflicts, you can't have Loongson 2E and MIPS DSP
instructions at the same time. You should at INSN_LOONGSON2E and
ASE_DSPR2 to look which instruction to execute instead of using this
is_mult_g_2e thingy.


> +                if (is_mult_g_2e == 0) {
> +                    break;
> +                }
> +            }
>          case OPC_MOD_G_2E ... OPC_MODU_G_2E:
>              check_insn(env, ctx, INSN_LOONGSON2E);
>              gen_loongson_integer(ctx, op1, rd, rs, rt);
> @@ -12193,6 +12412,213 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>                  break;
>              }
>              break;
> +        case OPC_ABSQ_S_PH_DSP:
> +            op2 = MASK_ABSQ_S_PH(ctx->opcode);
> +            switch (op2) {
> +            case OPC_ABSQ_S_QB:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_absq_s_qb(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
> +                break;
> +            case OPC_ABSQ_S_PH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_absq_s_ph(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
> +                break;

ASE_DSPR2 implies ASE_DSP. You can probably evaluate the check of
ASE_DSP one level above to avoid repeating the same pattern at each
line.

> +            case OPC_ABSQ_S_W:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_absq_s_w(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQ_W_PHL:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceq_w_phl(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQ_W_PHR:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceq_w_phr(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQU_PH_QBL:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precequ_ph_qbl(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQU_PH_QBR:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precequ_ph_qbr(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQU_PH_QBLA:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precequ_ph_qbla(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQU_PH_QBRA:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precequ_ph_qbra(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEU_PH_QBL:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceu_ph_qbl(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEU_PH_QBR:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceu_ph_qbr(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEU_PH_QBLA:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceu_ph_qbla(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEU_PH_QBRA:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceu_ph_qbra(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK ABSQ_S.PH");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
> +        case OPC_ADDU_QB_DSP:
> +            op2 = MASK_ADDU_QB(ctx->opcode);
> +            switch (op2) {
> +            case OPC_ADDQ_PH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_addq_ph(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDQ_S_PH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_addq_s_ph(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDQ_S_W:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_addq_s_w(cpu_gpr[rd], cpu_env,
> +                                    cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDU_QB:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_addu_qb(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDU_S_QB:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_addu_s_qb(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDU_PH:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_addu_ph(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDU_S_PH:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_addu_s_ph(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBQ_PH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_subq_ph(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBQ_S_PH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_subq_s_ph(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBQ_S_W:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_subq_s_w(cpu_gpr[rd], cpu_env,
> +                                    cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBU_QB:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_subu_qb(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBU_S_QB:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_subu_s_qb(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBU_PH:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_subu_ph(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBU_S_PH:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_subu_s_ph(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDSC:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_addsc(cpu_gpr[rd], cpu_env,
> +                                 cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDWC:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_addwc(cpu_gpr[rd], cpu_env,
> +                                 cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_MODSUB:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_modsub(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_RADDU_W_QB:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_raddu_w_qb(cpu_gpr[rd], cpu_gpr[rs]);
> +                break;
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK ADDU.QB");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
> +        case OPC_CMPU_EQ_QB_DSP:
> +            op2 = MASK_CMPU_EQ_QB(ctx->opcode);
> +            switch (op2) {
> +            case OPC_PRECR_QB_PH:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_precr_qb_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECRQ_QB_PH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precrq_qb_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECR_SRA_PH_W:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                {
> +                    TCGv_i32 temp_rd = tcg_const_i32(rd);
> +                    gen_helper_precr_sra_ph_w(cpu_gpr[rt], temp_rd,
> +                                           cpu_gpr[rs], cpu_gpr[rt]);
> +                    tcg_temp_free_i32(temp_rd);
> +                    break;
> +                }
> +            case OPC_PRECR_SRA_R_PH_W:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                {
> +                    TCGv_i32 temp_rd = tcg_const_i32(rd);
> +                    gen_helper_precr_sra_r_ph_w(cpu_gpr[rt], temp_rd,
> +                                            cpu_gpr[rs], cpu_gpr[rt]);
> +                    tcg_temp_free_i32(temp_rd);
> +                    break;
> +                }
> +            case OPC_PRECRQ_PH_W:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precrq_ph_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECRQ_RS_PH_W:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precrq_rs_ph_w(cpu_gpr[rd], cpu_env,
> +                                          cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECRQU_S_QB_PH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precrqu_s_qb_ph(cpu_gpr[rd], cpu_env,
> +                                           cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK CMPU.EQ.QB");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
>  #if defined(TARGET_MIPS64)
>          case OPC_DEXTM ... OPC_DEXT:
>          case OPC_DINSM ... OPC_DINS:
> @@ -12213,6 +12639,255 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>              gen_loongson_integer(ctx, op1, rd, rs, rt);
>              break;
>  #endif
> +#if defined(TARGET_MIPS64)
> +        case OPC_ABSQ_S_QH_DSP:
> +            op2 = MASK_ABSQ_S_QH(ctx->opcode);
> +            switch (op2) {
> +            case OPC_PRECEQ_L_PWL:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceq_l_pwl(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQ_L_PWR:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceq_l_pwr(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQ_PW_QHL:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceq_pw_qhl(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQ_PW_QHR:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceq_pw_qhr(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQ_PW_QHLA:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceq_pw_qhla(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQ_PW_QHRA:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceq_pw_qhra(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQU_QH_OBL:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precequ_qh_obl(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQU_QH_OBR:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precequ_qh_obr(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQU_QH_OBLA:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precequ_qh_obla(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEQU_QH_OBRA:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precequ_qh_obra(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEU_QH_OBL:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceu_qh_obl(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEU_QH_OBR:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceu_qh_obr(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEU_QH_OBLA:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceu_qh_obla(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECEU_QH_OBRA:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_preceu_qh_obra(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_ABSQ_S_OB:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_absq_s_ob(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
> +                break;
> +            case OPC_ABSQ_S_PW:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_absq_s_pw(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
> +                break;
> +            case OPC_ABSQ_S_QH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_absq_s_qh(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
> +                break;
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK ABSQ_S.QH");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
> +#endif
> +#if defined(TARGET_MIPS64)
> +        case OPC_ADDU_OB_DSP:
> +            op2 = MASK_ADDU_OB(ctx->opcode);
> +            switch (op2) {
> +            case OPC_RADDU_L_OB:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_raddu_l_ob(cpu_gpr[rd], cpu_gpr[rs]);
> +                break;
> +            case OPC_SUBQ_PW:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_subq_pw(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBQ_S_PW:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_subq_s_pw(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBQ_QH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_subq_qh(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBQ_S_QH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_subq_s_qh(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBU_OB:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_subu_ob(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBU_S_OB:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_subu_s_ob(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBU_QH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_subu_qh(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBU_S_QH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_subu_s_qh(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBUH_OB:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_subuh_ob(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_SUBUH_R_OB:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_subuh_r_ob(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDQ_PW:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_addq_pw(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDQ_S_PW:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_addq_s_pw(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDQ_QH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_addq_qh(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDQ_S_QH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_addq_s_qh(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDU_OB:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_addu_ob(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDU_S_OB:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_addu_s_ob(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDU_QH:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_addu_qh(cpu_gpr[rd], cpu_env,
> +                                   cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDU_S_QH:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_addu_s_qh(cpu_gpr[rd], cpu_env,
> +                                     cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDUH_OB:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_adduh_ob(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_ADDUH_R_OB:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_adduh_r_ob(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK ADDU.OB");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
> +#endif
> +#if defined(TARGET_MIPS64)
> +        case OPC_CMPU_EQ_OB_DSP:
> +            op2 = MASK_CMPU_EQ_OB(ctx->opcode);
> +            switch (op2) {
> +            case OPC_PRECR_OB_QH:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                gen_helper_precr_ob_qh(cpu_gpr[rd], cpu_gpr[rs],
> +                                       cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECR_SRA_QH_PW:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                {
> +                    TCGv_i32 sa_v = tcg_const_i32(rd);
> +                    gen_helper_precr_sra_qh_pw(cpu_gpr[rt], cpu_gpr[rs],
> +                                               cpu_gpr[rt], sa_v);
> +                    tcg_temp_free_i32(sa_v);
> +                    break;
> +                }
> +            case OPC_PRECR_SRA_R_QH_PW:
> +                check_insn(env, ctx, ASE_DSPR2);
> +                {
> +                    TCGv_i32 sa_v = tcg_const_i32(rd);
> +                    gen_helper_precr_sra_r_qh_pw(cpu_gpr[rt], cpu_gpr[rs],
> +                                                 cpu_gpr[rt], sa_v);
> +                    tcg_temp_free_i32(sa_v);
> +                    break;
> +                }
> +            case OPC_PRECRQ_OB_QH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precrq_ob_qh(cpu_gpr[rd], cpu_gpr[rs],
> +                                        cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECRQ_PW_L:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precrq_pw_l(cpu_gpr[rd], cpu_gpr[rs],
> +                                       cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECRQ_QH_PW:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precrq_qh_pw(cpu_gpr[rd], cpu_gpr[rs],
> +                                        cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECRQ_RS_QH_PW:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precrq_rs_qh_pw(cpu_gpr[rd], cpu_env,
> +                                           cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            case OPC_PRECRQU_S_OB_QH:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_precrqu_s_ob_qh(cpu_gpr[rd], cpu_env,
> +                                           cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK CMPU.EQ.OB");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
> +#endif
>          default:            /* Invalid */
>              MIPS_INVAL("special3");
>              generate_exception(ctx, EXCP_RI);
> -- 
> 1.7.9.5
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v6 08/13] target-mips-ase-dsp: Add bit/manipulation instructions
  2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 08/13] target-mips-ase-dsp: Add bit/manipulation instructions Jia Liu
@ 2012-08-23 14:48   ` Aurelien Jarno
  0 siblings, 0 replies; 20+ messages in thread
From: Aurelien Jarno @ 2012-08-23 14:48 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Tue, Aug 21, 2012 at 02:53:14PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP Bit/Manipulation instructions.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/dsp_helper.c |   79 +++++++++++++
>  target-mips/helper.h     |    7 ++
>  target-mips/translate.c  |  289 +++++++++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 374 insertions(+), 1 deletion(-)
> 
> diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
> index ff51d2f..4564d9c 100644
> --- a/target-mips/dsp_helper.c
> +++ b/target-mips/dsp_helper.c
> @@ -6211,6 +6211,85 @@ void helper_dmsubu(CPUMIPSState *env,
>  }
>  #endif
>  
> +/** DSP Bit/Manipulation Sub-class insns **/
> +target_ulong helper_bitrev(target_ulong rt)
> +{
> +    int32_t temp;
> +    uint32_t rd;
> +    int i, last;
> +
> +    temp = rt & MIPSDSP_LO;
> +    rd = 0;
> +    for (i = 0; i < 16; i++) {
> +        last = temp % 2;
> +        temp = temp >> 1;
> +        rd = rd | (last << (15 - i));
> +    }
> +
> +    return (target_ulong)rd;
> +}
> +
> +target_ulong helper_insv(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    uint32_t pos, size, msb, lsb, rs_f, rt_f;
> +    uint32_t temp, temprs, temprt;
> +    uint32_t rs_notword, rt_notword;
> +    target_ulong dspc;
> +
> +    dspc = env->active_tc.DSPControl;
> +    pos  = dspc & 0x1F;
> +    size = (dspc >> 7) & 0x1F;
> +    msb  = pos + size - 1;
> +    lsb  = pos;
> +
> +    rs_notword = not_word_value(rs);
> +    rt_notword = not_word_value(rt);
> +
> +    if ((lsb > msb) || (rs_notword == 1) || (rt_notword == 1)) {
> +        return rt;
> +    }
> +
> +    rs_f = (((int32_t)0x01 << (msb - lsb + 1 + 1)) - 1) << lsb;
> +    rt_f = rs_f ^ 0xFFFFFFFF;
> +    temprs = rs & rs_f;
> +    temprt = rt & rt_f;
> +    temp = temprs | temprt;
> +
> +    return (target_long)(int32_t)temp;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_dinsv(CPUMIPSState *env, target_ulong rs, target_ulong rt)
> +{
> +    target_ulong dspctrl;
> +    target_ulong filter;
> +    uint8_t pos, size;
> +    uint8_t msb, lsb;
> +    uint64_t temp;
> +
> +    temp = rt;
> +    dspctrl = env->active_tc.DSPControl;
> +    pos = dspctrl & 0x7F;
> +    size = (dspctrl >> 7) & 0x3F;
> +
> +    msb = pos + size - 1;
> +    lsb = pos;
> +
> +    if ((lsb > msb) || (msb > 63)) {
> +        return temp;
> +    }
> +
> +    temp = 0;
> +    filter = ((target_ulong)0x01 << size) - 1;
> +    filter = filter << pos;
> +
> +    temp |= rs & filter;
> +    temp |= rt & (~filter);
> +
> +    return temp;
> +}
> +#endif
> +
>  #undef MIPSDSP_LHI
>  #undef MIPSDSP_LLO
>  #undef MIPSDSP_HI
> diff --git a/target-mips/helper.h b/target-mips/helper.h
> index 69bcb6c..df86ef9 100644
> --- a/target-mips/helper.h
> +++ b/target-mips/helper.h
> @@ -582,4 +582,11 @@ DEF_HELPER_FLAGS_4(dmsub, 0, void, env, tl, tl, i32)
>  DEF_HELPER_FLAGS_4(dmsubu, 0, void, env, tl, tl, i32)
>  #endif
>  
> +/* DSP Bit/Manipulation Sub-class insns */
> +DEF_HELPER_FLAGS_1(bitrev, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl)
> +DEF_HELPER_FLAGS_3(insv, 0, tl, env, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(dinsv, 0, tl, env, tl, tl);
> +#endif
> +
>  #include "def-helper.h"
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index d8f83e0..1a9df0f 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -343,6 +343,11 @@ enum {
>  #if defined(TARGET_MIPS64)
>      OPC_DPAQ_W_QH_DSP  = 0x34 | OPC_SPECIAL3,
>  #endif
> +    /* DSP Bit/Manipulation Sub-class */
> +    OPC_INSV_DSP       = 0x0C | OPC_SPECIAL3,
> +#if defined(TARGET_MIPS64)
> +    OPC_DINSV_DSP      = 0x0D | OPC_SPECIAL3,
> +#endif
>  };
>  
>  /* BSHFL opcodes */
> @@ -450,6 +455,12 @@ enum {
>      OPC_PRECEU_PH_QBR   = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
>      OPC_PRECEU_PH_QBLA  = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
>      OPC_PRECEU_PH_QBRA  = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
> +    /* DSP Bit/Manipulation Sub-class */
> +    OPC_BITREV          = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_REPL_QB         = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_REPLV_QB        = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_REPL_PH         = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
> +    OPC_REPLV_PH        = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
>  };
>  
>  #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
> @@ -518,6 +529,12 @@ enum {
>      OPC_MULSA_W_PH    = (0x02 << 6) | OPC_DPA_W_PH_DSP,
>  };
>  
> +#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
> +enum {
> +    /* DSP Bit/Manipulation Sub-class */
> +    OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
> +};
> +
>  #if defined(TARGET_MIPS64)
>  #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
>  enum {
> @@ -539,6 +556,13 @@ enum {
>      OPC_ABSQ_S_OB       = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
>      OPC_ABSQ_S_PW       = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
>      OPC_ABSQ_S_QH       = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
> +    /* DSP Bit/Manipulation Sub-class */
> +    OPC_REPL_OB         = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_REPL_PW         = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_REPL_QH         = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_REPLV_OB        = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_REPLV_PW        = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
> +    OPC_REPLV_QH        = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
>  };
>  #endif
>  
> @@ -592,6 +616,14 @@ enum {
>  #endif
>  
>  #if defined(TARGET_MIPS64)
> +#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
> +enum {
> +    /* DSP Bit/Manipulation Sub-class */
> +    OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
> +};
> +#endif
> +
> +#if defined(TARGET_MIPS64)
>  #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
>  enum {
>      /* MIPS DSP Multiply Sub-class insns */
> @@ -12633,6 +12665,116 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>                  check_insn(env, ctx, ASE_DSP);
>                  gen_helper_preceu_ph_qbra(cpu_gpr[rd], cpu_gpr[rt]);
>                  break;
> +            case OPC_BITREV:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_bitrev(cpu_gpr[rd], cpu_gpr[rt]);
> +                break;
> +            case OPC_REPL_QB:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    TCGv imm3, imm2, imm1, imm0, temp_rd;
> +                    temp_rd = tcg_const_tl(0);
> +
> +                    imm = (ctx->opcode >> 16) & 0xFF;
> +                    imm3 = tcg_const_tl(imm);
> +                    imm2 = tcg_const_tl(imm);
> +                    imm1 = tcg_const_tl(imm);
> +                    imm0 = tcg_const_tl(imm);
> +                    tcg_gen_shli_tl(imm3, imm3, 24);
> +                    tcg_gen_shli_tl(imm2, imm2, 16);
> +                    tcg_gen_shli_tl(imm1, imm1, 8);
> +                    tcg_gen_or_tl(temp_rd, temp_rd, imm3);
> +                    tcg_gen_or_tl(temp_rd, temp_rd, imm2);
> +                    tcg_gen_or_tl(temp_rd, temp_rd, imm1);
> +                    tcg_gen_or_tl(temp_rd, temp_rd, imm0);

What's the point of loading 4 times the same value in a TCG register,
and do the shifts in TCG code? Either load it once, and shift it after
each or TCG instruction, or directly load the shifted value. In both
case you can just use a single TCG variable.

> +#if defined(TARGET_MIPS64)
> +                    tcg_gen_ext32s_i64(temp_rd, temp_rd);
> +#endif
> +                    gen_store_gpr(temp_rd, rd);
> +                    tcg_temp_free(temp_rd);
> +                    tcg_temp_free(imm3);
> +                    tcg_temp_free(imm2);
> +                    tcg_temp_free(imm1);
> +                    tcg_temp_free(imm0);
> +                    break;
> +                }
> +            case OPC_REPLV_QB:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    TCGv rt3, rt2, rt1, rt0, temp_rd;
> +                    temp_rd = tcg_const_tl(0);
> +
> +                    rt3 = tcg_const_tl(0);
> +                    rt2 = tcg_const_tl(0);
> +                    rt1 = tcg_const_tl(0);
> +                    rt0 = tcg_const_tl(0);

Why loading 0 here...

> +                    tcg_gen_andi_tl(rt3, cpu_gpr[rt], 0xFF);
> +                    tcg_gen_andi_tl(rt2, cpu_gpr[rt], 0xFF);
> +                    tcg_gen_andi_tl(rt1, cpu_gpr[rt], 0xFF);
> +                    tcg_gen_andi_tl(rt0, cpu_gpr[rt], 0xFF);

... and override the value just below?

> +                    tcg_gen_shli_tl(rt3, rt3, 24);
> +                    tcg_gen_shli_tl(rt2, rt2, 16);
> +                    tcg_gen_shli_tl(rt1, rt1, 8);
> +
> +                    tcg_gen_or_tl(temp_rd, temp_rd, rt3);
> +                    tcg_gen_or_tl(temp_rd, temp_rd, rt2);
> +                    tcg_gen_or_tl(temp_rd, temp_rd, rt1);
> +                    tcg_gen_or_tl(temp_rd, temp_rd, rt0);

All of that seems quite complicated. It would be easier to do something like that:
    t = tcg_temp_new_tl();
    tcg_gen_ext8u(temp_rd, cpu_gpr[rt]);
    tcg_gen_shli(t, temp_rd, 8);
    tcg_gen_or(temp_rd, temp_rd, t);
    tcg_gen_shli(t, temp_rd, 16);
    tcg_gen_or(temp_rd, temp_rd, t);
    tcg_temp_free(t);

> +#if defined(TARGET_MIPS64)
> +                    tcg_gen_ext32s_i64(temp_rd, temp_rd);
> +#endif
> +                    gen_store_gpr(temp_rd, rd);
> +
> +                    tcg_temp_free(temp_rd);
> +                    tcg_temp_free(rt3);
> +                    tcg_temp_free(rt2);
> +                    tcg_temp_free(rt1);
> +                    tcg_temp_free(rt0);
> +                     break;
> +                }
> +            case OPC_REPL_PH:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    TCGv immhi, immlo, temp_rd;
> +                    temp_rd = tcg_const_tl(0);
> +
> +                    imm = (ctx->opcode >> 16) & 0x03FF;
> +                    immhi = tcg_const_tl(imm);
> +                    immlo = tcg_const_tl(imm);
> +                    tcg_gen_shli_tl(immhi, immhi, 16);

Again, don't load immhi for overriding just after.

> +                    tcg_gen_or_tl(temp_rd, immhi, immlo);

What about:

tcg_gen_mov_tl(temp_rd, imm << 16 | imm);

> +#if defined(TARGET_MIPS64)
> +                    tcg_gen_ext32s_i64(temp_rd, temp_rd);
> +#endif

With the proper cast you can even fold that in the mov_tl.

> +                    gen_store_gpr(temp_rd, rd);
> +                    tcg_temp_free(temp_rd);
> +                    tcg_temp_free(immhi);
> +                    tcg_temp_free(immlo);
> +                    break;
> +                }
> +            case OPC_REPLV_PH:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    TCGv rt0, rt1, temp_rd;
> +                    temp_rd = tcg_const_tl(0);
> +
> +                    rt0 = tcg_const_tl(0);
> +                    rt1 = tcg_const_tl(0);
> +                    tcg_gen_andi_tl(rt0, cpu_gpr[rt], 0xFFFF);
> +                    tcg_gen_andi_tl(rt1, cpu_gpr[rt], 0xFFFF);
> +                    tcg_gen_shli_tl(rt1, rt1, 16);
> +                    tcg_gen_or_tl(temp_rd, rt1, rt0);
> +#if defined(TARGET_MIPS64)
> +                    tcg_gen_ext32s_i64(temp_rd, temp_rd);
> +#endif

Same kind of issues as above.

> +                    gen_store_gpr(temp_rd, rd);
> +                    tcg_temp_free(temp_rd);
> +                    tcg_temp_free(rt0);
> +                    tcg_temp_free(rt1);
> +                    break;
> +                }
>              default:            /* Invalid */
>                  MIPS_INVAL("MASK ABSQ_S.PH");
>                  generate_exception(ctx, EXCP_RI);
> @@ -13133,6 +13275,22 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>                  break;
>              }
>              break;
> +        case OPC_INSV_DSP:
> +            op2 = MASK_INSV(ctx->opcode);
> +            switch (op2) {
> +            case OPC_INSV:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    gen_helper_insv(cpu_gpr[rt], cpu_env,
> +                                    cpu_gpr[rs], cpu_gpr[rt]);
> +                    break;
> +                }
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK INSV");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
>  #if defined(TARGET_MIPS64)
>          case OPC_DEXTM ... OPC_DEXT:
>          case OPC_DINSM ... OPC_DINS:
> @@ -13213,6 +13371,119 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>                  check_insn(env, ctx, ASE_DSP);
>                  gen_helper_preceu_qh_obra(cpu_gpr[rd], cpu_gpr[rt]);
>                  break;
> +            case OPC_REPL_OB:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    int i;
> +                    TCGv_i64 immv, temp_rd;
> +                    temp_rd = tcg_const_i64(0);
> +
> +                    imm = (ctx->opcode >> 16) & 0xFF;
> +                    immv = tcg_const_i64(imm);
> +
> +                    tcg_gen_or_i64(temp_rd, temp_rd, immv);
> +                    for (i = 0; i < 7; i++) {
> +                        tcg_gen_shli_i64(temp_rd, temp_rd, 8);
> +                        tcg_gen_or_i64(temp_rd, temp_rd, immv);
> +                    }
> +                    gen_store_gpr(temp_rd, rd);
> +                    break;
> +                }
> +            case OPC_REPL_PW:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    TCGv_i64 temp = tcg_temp_new_i64();
> +
> +                    imm = (ctx->opcode >> 16) & 0x03FF;
> +                    imm = (int16_t)(imm << 6) >> 6;
> +
> +                    tcg_gen_movi_i64(temp,
> +                                     (uint64_t)(uint32_t)(int32_t)imm);
> +                    tcg_gen_shli_i64(temp, temp, 32);
> +                    tcg_gen_ori_i64(temp, temp,
> +                                    (uint64_t)(uint32_t)(int32_t)imm);
> +
> +                    gen_store_gpr(temp, rd);
> +
> +                    tcg_temp_free_i64(temp);
> +                    break;
> +                }
> +            case OPC_REPL_QH:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    TCGv_i64 temp = tcg_temp_new_i64();
> +
> +                    imm = (ctx->opcode >> 16) & 0x03FF;
> +                    imm = (int16_t)(imm << 6) >> 6;
> +
> +                    tcg_gen_movi_i64(temp, (uint64_t)(uint16_t)imm);
> +                    tcg_gen_shli_i64(temp, temp, 16);
> +                    tcg_gen_ori_i64(temp, temp, (uint64_t)(uint16_t)imm);
> +                    tcg_gen_shli_i64(temp, temp, 16);
> +                    tcg_gen_ori_i64(temp, temp, (uint64_t)(uint16_t)imm);
> +                    tcg_gen_shli_i64(temp, temp, 16);
> +                    tcg_gen_ori_i64(temp, temp, (uint64_t)(uint16_t)imm);
> +
> +                    gen_store_gpr(temp, rd);
> +
> +                    tcg_temp_free_i64(temp);
> +                    break;
> +                }
> +            case OPC_REPLV_OB:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    int i;
> +                    TCGv_i64 immv, temp_rd;
> +                    immv = tcg_const_i64(0);
> +                    temp_rd = tcg_const_i64(0);
> +
> +                    tcg_gen_ori_i64(immv, cpu_gpr[rt], 0xFF);
> +                    tcg_gen_or_i64(temp_rd, temp_rd, immv);
> +                    for (i = 0; i < 7; i++) {
> +                        tcg_gen_shli_i64(temp_rd, temp_rd, 8);
> +                        tcg_gen_or_i64(temp_rd, temp_rd, immv);
> +                    }
> +                    gen_store_gpr(temp_rd, rd);
> +                    tcg_temp_free_i64(immv);
> +                    tcg_temp_free_i64(temp_rd);
> +                    break;
> +                }
> +            case OPC_REPLV_PW:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    TCGv_i64 imm_v;
> +                    imm_v = tcg_const_i64(0);
> +
> +                    tcg_gen_ori_i64(imm_v, cpu_gpr[rt], 0xFFFFFFFF);
> +                    tcg_gen_ext32s_i64(cpu_gpr[rd], imm_v);
> +
> +                    tcg_temp_free_i64(imm_v);
> +                    break;
> +                }
> +            case OPC_REPLV_QH:
> +                check_insn(env, ctx, ASE_DSP);
> +                {
> +                    TCGv_i64 imm_v;
> +                    TCGv_i64 temp_rd;
> +
> +                    imm_v = tcg_const_i64(0);
> +                    temp_rd = tcg_const_i64(0);
> +                    tcg_gen_ori_i64(imm_v, cpu_gpr[rt], 0xffff);
> +
> +                    tcg_gen_or_i64(temp_rd, temp_rd, imm_v);
> +                    tcg_gen_shli_i64(temp_rd, temp_rd, 16);
> +                    tcg_gen_or_i64(temp_rd, temp_rd, imm_v);
> +                    tcg_gen_shli_i64(temp_rd, temp_rd, 16);
> +                    tcg_gen_or_i64(temp_rd, temp_rd, imm_v);
> +                    tcg_gen_shli_i64(temp_rd, temp_rd, 16);
> +                    tcg_gen_or_i64(temp_rd, temp_rd, imm_v);
> +
> +                    gen_store_gpr(temp_rd, rd);
> +
> +                    tcg_temp_free_i64(imm_v);
> +                    tcg_temp_free_i64(temp_rd);
> +                    break;
> +                }
>              case OPC_ABSQ_S_OB:
>                  check_insn(env, ctx, ASE_DSPR2);
>                  gen_helper_absq_s_ob(cpu_gpr[rd], cpu_env, cpu_gpr[rt]);
> @@ -13574,6 +13845,22 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>              }
>  #endif
>  #if defined(TARGET_MIPS64)
> +        case OPC_DINSV_DSP:
> +            op2 = MASK_INSV(ctx->opcode);
> +            switch (op2) {
> +            case OPC_DINSV:
> +                check_insn(env, ctx, ASE_DSP);
> +                gen_helper_dinsv(cpu_gpr[rt], cpu_env,
> +                                 cpu_gpr[rs], cpu_gpr[rt]);
> +                break;
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK DINSV");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
> +#endif
> +#if defined(TARGET_MIPS64)
>          case OPC_SHLL_OB_DSP:
>              op2 = MASK_SHLL_OB(ctx->opcode);
>              switch (op2) {
> @@ -13748,7 +14035,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>                  generate_exception(ctx, EXCP_RI);
>                  break;
>              }
> -          break;
> +            break;
>  #endif
>          default:            /* Invalid */
>              MIPS_INVAL("special3");
> -- 
> 1.7.9.5
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2012-08-23 14:48 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-21  6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 01/13] target-mips-ase-dsp: Add internal functions Jia Liu
2012-08-23 13:31   ` Aurelien Jarno
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 02/13] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Jia Liu
2012-08-23 13:33   ` Aurelien Jarno
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 03/13] target-mips-ase-dsp: Add branch instructions Jia Liu
2012-08-23 14:18   ` Aurelien Jarno
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 04/13] target-mips-ase-dsp: Add load instructions Jia Liu
2012-08-23 14:23   ` Aurelien Jarno
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 05/13] target-mips-ase-dsp: Add arithmetic instructions Jia Liu
2012-08-23 14:28   ` Aurelien Jarno
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 06/13] target-mips-ase-dsp: Add GPR Based shift instructions Jia Liu
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 07/13] target-mips-ase-dsp: Add multiply instructions Jia Liu
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 08/13] target-mips-ase-dsp: Add bit/manipulation instructions Jia Liu
2012-08-23 14:48   ` Aurelien Jarno
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 09/13] target-mips-ase-dsp: Add compare pick instructions Jia Liu
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 10/13] target-mips-ase-dsp: Add MIPS ASE DSP Accumulator and DSPControl Access instructions Jia Liu
2012-08-21  6:53 ` [Qemu-devel] [PATCH v6 11/13] target-mips-ase-dsp: Add MIPS[32|64] ASE DSP[R1|R2] generic cpu model Jia Liu
2012-08-21  9:32 ` [Qemu-devel] [PATCH v6 12/13] target-mips-ase-dsp: Add testcases Jia Liu
2012-08-21  9:34 ` [Qemu-devel] [PATCH v6 13/13] target-mips-ase-dsp: Change TODO Jia Liu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.