All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support
@ 2012-09-27 13:24 Jia Liu
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 01/14] target-mips-ase-dsp: Add internal funtions Jia Liu
                   ` (14 more replies)
  0 siblings, 15 replies; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 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:
v9:
Addressed Aurelien's review comments:
- group translate actions by opcode
- group helpers using macro
- remove unused function not_word_value
- add absolute macro, overflow check macro, split/combine number macro
- undo delete bposge32/64 from micromips
- add return register 0 check

v8:
Addressed Aurelien's review comments:
- fix HFLAGS check, I hope it is right this time
- make a lot of code more clean
- fix branch instructions
- fix load instructions, I hope it is right this time
- fix bit instructions
- use a macro to deal CMP
- use 74kf instead of mips32dspr2

v7:
Addressed Aurelien's review comments:
- make hflags check for dsp, use check_dsp[r2]() instead of check_insn
- directly use cpu_dspctrl as the second argument in branch instructions
- factorizing some check_dsp() code one level
- remove unnecessary save_cpu_state() from load instructions
- resolve conflicts between MIPS DSP and loongson2e better
- make repl* more clean

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 (14):
  target-mips-ase-dsp: Add internal funtions
  target-mips-ase-dsp: Add dsp resources access check
  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 DSP accumulator instructions
  target-mips-ase-dsp: Add MIPS DSP processors
  target-mips-ase-dsp: Add testcases
  target-mips-ase-dsp: Change TODO file

 linux-user/main.c                              |    6 +
 target-mips/Makefile.objs                      |    2 +-
 target-mips/TODO                               |    2 -
 target-mips/cpu.h                              |   27 +-
 target-mips/dsp_helper.c                       | 4109 ++++++++++++++++++++++++
 target-mips/helper.c                           |    3 +
 target-mips/helper.h                           |  349 ++
 target-mips/translate.c                        | 3074 +++++++++++++++++-
 target-mips/translate_init.c                   |   52 +
 tests/tcg/mips/mips32-dsp/Makefile             |  135 +
 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_phl.c      |   41 +
 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/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             |  305 ++
 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               |   16 +
 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      |   62 +
 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_phl.c      |   46 +
 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/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             |   16 +
 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 +
 496 files changed, 23383 insertions(+), 111 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_phl.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/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_phl.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/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.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 01/14] target-mips-ase-dsp: Add internal funtions
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:51   ` Aurelien Jarno
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 02/14] target-mips-ase-dsp: Add dsp resources access check Jia Liu
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 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  | 1121 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1122 insertions(+), 1 deletion(-)
 create mode 100644 target-mips/dsp_helper.c

diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs
index 3eeeeac..119c816 100644
--- a/target-mips/Makefile.objs
+++ b/target-mips/Makefile.objs
@@ -1,2 +1,2 @@
-obj-y += translate.o op_helper.o lmi_helper.o helper.o cpu.o
+obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o
 obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
new file mode 100644
index 0000000..b04b489
--- /dev/null
+++ b/target-mips/dsp_helper.c
@@ -0,0 +1,1121 @@
+/*
+ * 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 ***/
+#define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x)
+#define MIPSDSP_OVERFLOW(a, b, c, d) (!(!((a ^ b ^ -1) & (a ^ c) & d)))
+
+static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
+                                                CPUMIPSState *env)
+{
+    env->active_tc.DSPControl |= (target_ulong)flag << position;
+}
+
+static inline void set_DSPControl_carryflag(uint32_t flag, CPUMIPSState *env)
+{
+    env->active_tc.DSPControl |= (target_ulong)flag << 13;
+}
+
+static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
+{
+    return (env->active_tc.DSPControl >> 13) & 0x01;
+}
+
+static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env)
+{
+  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(int len, CPUMIPSState *env)
+{
+  uint32_t filter;
+
+  filter = (0x01 << len) - 1;
+
+  return (env->active_tc.DSPControl >> 24) & filter;
+}
+
+static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env)
+{
+    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(uint32_t flag, CPUMIPSState *env)
+{
+    env->active_tc.DSPControl &= 0xFFFFBFFF;
+    env->active_tc.DSPControl |= (target_ulong)flag << 14;
+}
+
+/* get abs value */
+static inline int8_t mipsdsp_sat_abs_u8(int8_t a, CPUMIPSState *env)
+{
+    if (a == INT8_MIN) {
+        set_DSPControl_overflow_flag(1, 20, env);
+        return 0x7f;
+    } else {
+        return MIPSDSP_ABS(a);
+    }
+
+    return a;
+}
+
+static inline int16_t mipsdsp_sat_abs_u16(int16_t a, CPUMIPSState *env)
+{
+    if (a == INT16_MIN) {
+        set_DSPControl_overflow_flag(1, 20, env);
+        return 0x7fff;
+    } else {
+        return MIPSDSP_ABS(a);
+    }
+
+    return a;
+}
+
+static inline int32_t mipsdsp_sat_abs_u32(int32_t a, CPUMIPSState *env)
+{
+    if (a == INT32_MIN) {
+        set_DSPControl_overflow_flag(1, 20, env);
+        return 0x7FFFFFFF;
+    } else {
+        return MIPSDSP_ABS(a);
+    }
+
+    return a;
+}
+
+/* get sum value */
+static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env)
+{
+    int16_t tempI;
+
+    tempI = a + b;
+
+    if (MIPSDSP_OVERFLOW(a, b, tempI, 0x8000)) {
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return tempI;
+}
+
+static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b,
+                                          CPUMIPSState *env)
+{
+    int16_t tempS;
+
+    tempS = a + b;
+
+    if (MIPSDSP_OVERFLOW(a, b, tempS, 0x8000)) {
+        if (a > 0) {
+            tempS = 0x7FFF;
+        } else {
+            tempS = 0x8000;
+        }
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return tempS;
+}
+
+static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b,
+                                          CPUMIPSState *env)
+{
+    int32_t tempI;
+
+    tempI = a + b;
+
+    if (MIPSDSP_OVERFLOW(a, b, tempI, 0x80000000)) {
+        if (a > 0) {
+            tempI = 0x7FFFFFFF;
+        } else {
+            tempI = 0x80000000;
+        }
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return tempI;
+}
+
+static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
+{
+    uint16_t temp;
+
+    temp = (uint16_t)a + (uint16_t)b;
+
+    if (temp & 0x0100) {
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return temp & 0xFF;
+}
+
+static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b,
+                                       CPUMIPSState *env)
+{
+    uint32_t temp;
+
+    temp = (uint32_t)a + (uint32_t)b;
+
+    if (temp & 0x00010000) {
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return temp & 0xFFFF;
+}
+
+static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b,
+                                         CPUMIPSState *env)
+{
+    uint8_t  result;
+    uint16_t temp;
+
+    temp = (uint16_t)a + (uint16_t)b;
+    result = temp & 0xFF;
+
+    if (0x0100 & temp) {
+        result = 0xFF;
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return result;
+}
+
+static inline uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b,
+                                           CPUMIPSState *env)
+{
+    uint16_t result;
+    uint32_t temp;
+
+    temp = (uint32_t)a + (uint32_t)b;
+    result = temp & 0xFFFF;
+
+    if (0x00010000 & temp) {
+        result = 0xFFFF;
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return result;
+}
+
+static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a,
+                                            CPUMIPSState *env)
+{
+    int64_t 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
+
+    temp_sum = (int64_t)a + temp;
+
+    temp32 = (temp_sum >> 32) & 0x01;
+    temp31 = (temp_sum >> 31) & 0x01;
+    result = temp_sum & 0xFFFFFFFF;
+
+    if (temp32 != temp31) {
+        if (temp32 == 0) {
+            result = 0x7FFFFFFF;
+        } else {
+            result = 0x80000000;
+        }
+        set_DSPControl_overflow_flag(1, 16 + acc, env);
+    }
+
+    return result;
+}
+
+/* a[0] is LO, a[1] is HI. */
+static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret,
+                                             int32_t ac,
+                                             int64_t *a,
+                                             CPUMIPSState *env)
+{
+    int64_t temp[3];
+    int64_t acc[3];
+    int64_t temp_sum;
+
+    temp[0] = a[0];
+    temp[1] = a[1];
+    if (temp[1] >= 0) {
+        temp[2] = 0x00;
+    } else {
+        temp[2] = ~0ull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+    if (acc[1] >= 0) {
+        acc[2] = 0x00;
+    } else {
+        acc[2] = ~0ull;
+    }
+
+    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;
+    }
+
+    if (MIPSDSP_OVERFLOW(temp[1], acc[1], temp_sum, INT64_MIN)) {
+        if (temp[1] > 0) {
+            ret[0] = 0x0;
+            ret[1] = 0x7FFFFFFFFFFFFFFFull;
+        } else {
+            ret[0] = 0x8000000000000000ull;
+            ret[1] = ~0ull;
+        }
+        set_DSPControl_overflow_flag(1, 16 + ac, env);
+    } else {
+        ret[0] = temp[0];
+        ret[1] = temp_sum;
+    }
+}
+
+/* a[0] is LO, a[1] is HI. */
+static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
+                                             int32_t ac,
+                                             int64_t *a,
+                                             CPUMIPSState *env)
+{
+    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] >= 0) {
+        temp[2] = 0x00;
+    } else {
+        temp[2] = ~0ull;
+    }
+
+    acc[0] = env->active_tc.LO[ac];
+    acc[1] = env->active_tc.HI[ac];
+    if (acc[1] >= 0) {
+        acc[2] = 0x00;
+    } else {
+        acc[2] = ~0ull;
+    }
+
+    temp_sum = acc[0] - temp[0];
+    if ((uint64_t)temp_sum > (uint64_t)acc[0]) {
+        acc[1] -= 1;
+        if (acc[1] == ~0ull) {
+            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] = ~0ull;
+        } else {
+            ret[0] = 0x0;
+            ret[1] = 0x7FFFFFFFFFFFFFFFull;
+        }
+        set_DSPControl_overflow_flag(1, 16 + ac, env);
+    } else {
+        ret[0] = acc[0];
+        ret[1] = acc[1];
+    }
+}
+
+static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b,
+                                          CPUMIPSState *env)
+{
+    int32_t temp;
+
+    temp = (int32_t)a * (int32_t)b;
+
+    if ((temp > 0x7FFF) || (temp < 0xFFFF8000)) {
+        set_DSPControl_overflow_flag(1, 21, env);
+    }
+    temp &= 0x0000FFFF;
+
+    return temp;
+}
+
+static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b)
+{
+    return a * b;
+}
+
+static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b)
+{
+    return a * b;
+}
+
+static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b,
+                                                CPUMIPSState *env)
+{
+    int32_t temp;
+
+    temp = (int32_t)a * (int32_t)b;
+
+    if (temp > 0x7FFF) {
+        temp = 0x00007FFF;
+        set_DSPControl_overflow_flag(1, 21, env);
+    } else if (temp < 0x00007FFF) {
+        temp = 0xFFFF8000;
+        set_DSPControl_overflow_flag(1, 21, env);
+    }
+    temp &= 0x0000FFFF;
+
+    return temp;
+}
+
+static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b,
+                                                         CPUMIPSState *env)
+{
+    int32_t temp;
+
+    if ((a == 0x8000) && (b == 0x8000)) {
+        temp = 0x7FFFFFFF;
+        set_DSPControl_overflow_flag(1, 21, env);
+    } else {
+        temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1;
+    }
+
+    return temp;
+}
+
+/* right shift */
+static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov)
+{
+    return a >> mov;
+}
+
+static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov)
+{
+    return a >> mov;
+}
+
+static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov)
+{
+    return a >> mov;
+}
+
+static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov)
+{
+    return a >> mov;
+}
+
+static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov)
+{
+    return a >> mov;
+}
+
+static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
+{
+    int32_t temp;
+
+    temp = (int32_t)a + (int32_t)b;
+
+    return (temp >> 1) & 0xFFFF;
+}
+
+/* round right shift */
+static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b)
+{
+    int32_t temp;
+
+    temp = (int32_t)a + (int32_t)b;
+    temp += 1;
+
+    return (temp >> 1) & 0xFFFF;
+}
+
+static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b)
+{
+    int64_t temp;
+
+    temp = (int64_t)a + (int64_t)b;
+
+    return (temp >> 1) & 0xFFFFFFFF;
+}
+
+static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b)
+{
+    int64_t temp;
+
+    temp = (int64_t)a + (int64_t)b;
+    temp += 1;
+
+    return (temp >> 1) & 0xFFFFFFFF;
+}
+
+static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b)
+{
+    uint16_t temp;
+
+    temp = (uint16_t)a + (uint16_t)b;
+
+    return (temp >> 1) & 0x00FF;
+}
+
+static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b)
+{
+    uint16_t temp;
+
+    temp = (uint16_t)a + (uint16_t)b + 1;
+
+    return (temp >> 1) & 0x00FF;
+}
+
+static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b)
+{
+    uint16_t temp;
+
+    temp = (uint16_t)a - (uint16_t)b;
+
+    return (temp >> 1) & 0x00FF;
+}
+
+static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b)
+{
+    uint16_t temp;
+
+    temp = (uint16_t)a - (uint16_t)b + 1;
+
+    return (temp >> 1) & 0x00FF;
+}
+
+static inline int64_t mipsdsp_rashift_short_acc(int32_t ac,
+                                                int32_t shift,
+                                                CPUMIPSState *env)
+{
+    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(1, 23, env);
+    }
+
+    return temp;
+}
+
+/*  128 bits long. p[0] is LO, p[1] is HI. */
+static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
+                                                int32_t ac,
+                                                int32_t shift,
+                                                CPUMIPSState *env)
+{
+    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(uint64_t *p,
+                                       uint32_t ac,
+                                       uint32_t shift,
+                                       CPUMIPSState *env)
+{
+    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;
+    }
+}
+
+/* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/
+static inline void mipsdsp_rndrashift_acc(uint64_t *p,
+                                          uint32_t ac,
+                                          uint32_t shift,
+                                          CPUMIPSState *env)
+{
+    int64_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 << (65 - shift)) | (tempA >> (shift - 1));
+        p[1] = (int64_t)tempB >> (shift - 1);
+        if (tempB >= 0) {
+            p[2] = 0x0;
+        } else {
+            p[2] = ~0ull;
+        }
+    }
+}
+
+static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b,
+                                          CPUMIPSState *env)
+{
+    int32_t temp;
+
+    if ((a == 0x8000) && (b == 0x8000)) {
+        temp = 0x7FFFFFFF;
+        set_DSPControl_overflow_flag(1, 16 + ac, env);
+    } else {
+        temp = ((uint32_t)a * (uint32_t)b) << 1;
+    }
+
+    return temp;
+}
+
+static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b,
+                                          CPUMIPSState *env)
+{
+    uint64_t temp;
+
+    if ((a == 0x80000000) && (b == 0x80000000)) {
+        temp = 0x7FFFFFFFFFFFFFFFull;
+        set_DSPControl_overflow_flag(1, 16 + ac, env);
+    } else {
+        temp = ((uint64_t)a * (uint64_t)b) << 1;
+    }
+
+    return temp;
+}
+
+static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b)
+{
+    return (uint16_t)a * (uint16_t)b;
+}
+
+static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b,
+                                          CPUMIPSState *env)
+{
+    uint32_t tempI;
+
+    tempI = (uint32_t)a * (uint32_t)b;
+    if (tempI > 0x0000FFFF) {
+        tempI = 0x0000FFFF;
+        set_DSPControl_overflow_flag(1, 21, env);
+    }
+
+    return tempI & 0x0000FFFF;
+}
+
+static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b)
+{
+    return (uint64_t)a * (uint64_t)b;
+}
+
+static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b,
+                                                 CPUMIPSState *env)
+{
+    uint32_t temp;
+
+    if ((a == 0x8000) && (b == 0x8000)) {
+        temp = 0x7FFF0000;
+        set_DSPControl_overflow_flag(1, 21, env);
+    } else {
+        temp = (a * b) << 1;
+        temp = temp + 0x00008000;
+    }
+
+    return (temp & 0xFFFF0000) >> 16;
+}
+
+static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b,
+                                                CPUMIPSState *env)
+{
+    int32_t temp;
+
+    if ((a == 0x8000) && (b == 0x8000)) {
+        temp = 0x7FFF0000;
+        set_DSPControl_overflow_flag(1, 21, env);
+    } else {
+        temp = ((uint32_t)a * (uint32_t)b);
+        temp = temp << 1;
+    }
+
+    return (temp >> 16) & 0x0000FFFF;
+}
+
+static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a,
+                                                   CPUMIPSState *env)
+{
+    int64_t temp;
+
+    temp = (int32_t)a + 0x00008000;
+
+    if (a > 0x7fff8000) {
+        temp = 0x7FFFFFFF;
+        set_DSPControl_overflow_flag(1, 22, env);
+    }
+
+    return (temp >> 16) & 0xFFFF;
+}
+
+static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
+                                                    CPUMIPSState *env)
+{
+    uint16_t mag;
+    uint32_t sign;
+
+    sign = (a >> 15) & 0x01;
+    mag = a & 0x7FFF;
+
+    if (sign == 0) {
+        if (mag > 0x7F80) {
+            set_DSPControl_overflow_flag(1, 22, env);
+            return 0xFF;
+        } else {
+            return (mag >> 7) & 0xFFFF;
+        }
+    } else {
+        set_DSPControl_overflow_flag(1, 22, env);
+        return 0x00;
+    }
+}
+
+static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env)
+{
+    uint8_t sign;
+    uint8_t discard;
+
+    if (s == 0) {
+        return a;
+    } else {
+        sign = (a >> 7) & 0x01;
+        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(1, 22, env);
+        }
+        return a << s;
+    }
+}
+
+static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
+                                        CPUMIPSState *env)
+{
+    uint8_t  sign;
+    uint16_t discard;
+
+    if (s == 0) {
+        return a;
+    } else {
+        sign = (a >> 15) & 0x01;
+        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(1, 22, env);
+        }
+        return a << s;
+    }
+}
+
+
+static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s,
+                                        CPUMIPSState *env)
+{
+    uint32_t discard;
+
+    if (s == 0) {
+        return a;
+    } else {
+        discard = (int32_t)a >> (31 - (s - 1));
+
+        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
+            set_DSPControl_overflow_flag(1, 22, env);
+        }
+        return a << s;
+    }
+}
+
+static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s,
+                                            CPUMIPSState *env)
+{
+    uint8_t  sign;
+    uint16_t discard;
+
+    if (s == 0) {
+        return a;
+    } else {
+        sign = (a >> 15) & 0x01;
+        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(1, 22, env);
+            return (sign == 0) ? 0x7FFF : 0x8000;
+        } else {
+            return a << s;
+        }
+    }
+}
+
+static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s,
+                                            CPUMIPSState *env)
+{
+    uint8_t  sign;
+    uint32_t discard;
+
+    if (s == 0) {
+        return a;
+    } else {
+        sign = (a >> 31) & 0x01;
+        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)) {
+            set_DSPControl_overflow_flag(1, 22, env);
+            return (sign == 0) ? 0x7FFFFFFF : 0x80000000;
+        } else {
+            return a << s;
+        }
+    }
+}
+
+static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a, uint8_t s)
+{
+    uint32_t temp;
+
+    if (s == 0) {
+        temp = (uint32_t)a << 1;
+    } else {
+        temp = (int32_t)(int8_t)a >> (s - 1);
+    }
+
+    return (temp + 1) >> 1;
+}
+
+static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s)
+{
+    uint32_t temp;
+
+    if (s == 0) {
+        temp = (uint32_t)a << 1;
+    } else {
+        temp = (int32_t)(int16_t)a >> (s - 1);
+    }
+
+    return (temp + 1) >> 1;
+}
+
+static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s)
+{
+    int64_t temp;
+
+    if (s == 0) {
+        temp = a << 1;
+    } else {
+        temp = (int64_t)(int32_t)a >> (s - 1);
+    }
+    temp += 1;
+
+    return (temp >> 1) & 0x00000000FFFFFFFFull;
+}
+
+static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env)
+{
+    int16_t  temp;
+
+    temp = a - b;
+    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return temp;
+}
+
+static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b,
+                                         CPUMIPSState *env)
+{
+    int16_t  temp;
+
+    temp = a - b;
+    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
+        if (a > 0) {
+            temp = 0x7FFF;
+        } else {
+            temp = 0x8000;
+        }
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return temp;
+}
+
+static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b,
+                                         CPUMIPSState *env)
+{
+    int32_t  temp;
+
+    temp = a - b;
+    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
+        if (a > 0) {
+            temp = 0x7FFFFFFF;
+        } else {
+            temp = 0x80000000;
+        }
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return temp & 0x00000000FFFFFFFFull;
+}
+
+static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b)
+{
+    int32_t  temp;
+
+    temp = (int32_t)a - (int32_t)b;
+
+    return (temp >> 1) & 0x0000FFFF;
+}
+
+static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b)
+{
+    int32_t  temp;
+
+    temp = (int32_t)a - (int32_t)b;
+    temp += 1;
+
+    return (temp >> 1) & 0x0000FFFF;
+}
+
+static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b)
+{
+    int64_t  temp;
+
+    temp = (int64_t)a - (int64_t)b;
+
+    return (temp >> 1) & 0x00000000FFFFFFFFull;
+}
+
+static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b)
+{
+    int64_t  temp;
+
+    temp = (int64_t)a - (int64_t)b;
+    temp += 1;
+
+    return (temp >> 1) & 0x00000000FFFFFFFFull;
+}
+
+static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b,
+                                           CPUMIPSState *env)
+{
+    uint8_t  temp16;
+    uint32_t temp;
+
+    temp = (uint32_t)a - (uint32_t)b;
+    temp16 = (temp >> 16) & 0x01;
+    if (temp16 == 1) {
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+    return temp & 0x0000FFFF;
+}
+
+static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b,
+                                                  CPUMIPSState *env)
+{
+    uint8_t  temp16;
+    uint32_t temp;
+
+    temp   = (uint32_t)a - (uint32_t)b;
+    temp16 = (temp >> 16) & 0x01;
+
+    if (temp16 == 1) {
+        temp = 0x0000;
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return temp & 0x0000FFFF;
+}
+
+static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
+{
+    uint8_t  temp8;
+    uint16_t temp;
+
+    temp = (uint16_t)a - (uint16_t)b;
+    temp8 = (temp >> 8) & 0x01;
+    if (temp8 == 1) {
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return temp & 0x00FF;
+}
+
+static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env)
+{
+    uint8_t  temp8;
+    uint16_t temp;
+
+    temp = (uint16_t)a - (uint16_t)b;
+    temp8 = (temp >> 8) & 0x01;
+    if (temp8 == 1) {
+        temp = 0x00;
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return temp & 0x00FF;
+}
+
+static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
+{
+    int32_t temp;
+
+    temp = a - b;
+    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return temp;
+}
+
+static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env)
+{
+    int32_t temp;
+
+    temp = a + b;
+
+    if (MIPSDSP_OVERFLOW(a, b, temp, 0x80000000)) {
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    return temp;
+}
+
+static inline int32_t mipsdsp_cmp_eq(uint32_t a, uint32_t b)
+{
+    return a == b;
+}
+
+static inline int32_t mipsdsp_cmp_le(uint32_t a, uint32_t b)
+{
+    return a <= b;
+}
+
+static inline int32_t mipsdsp_cmp_lt(uint32_t a, uint32_t b)
+{
+    return a < b;
+}
+/*** MIPS DSP internal functions end ***/
-- 
1.7.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 02/14] target-mips-ase-dsp: Add dsp resources access check
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 01/14] target-mips-ase-dsp: Add internal funtions Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:51   ` Aurelien Jarno
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 03/14] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Jia Liu
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Add MIPS ASE DSP resources access check.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 linux-user/main.c       |    6 ++++++
 target-mips/cpu.h       |   27 +++++++++++++++++++++++++--
 target-mips/helper.c    |    3 +++
 target-mips/translate.c |   23 +++++++++++++++++++++++
 4 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 9f3476b..cd6523b 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2281,6 +2281,12 @@ done_syscall:
                 queue_signal(env, info.si_signo, &info);
             }
             break;
+        case EXCP_DSPDIS:
+            info.si_signo = TARGET_SIGILL;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_ILLOPC;
+            queue_signal(env, info.si_signo, &info);
+            break;
         default:
             //        error:
             fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index b7a5112..7d46603 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -415,7 +415,7 @@ struct CPUMIPSState {
     int error_code;
     uint32_t hflags;    /* CPU State */
     /* TMASK defines different execution modes */
-#define MIPS_HFLAG_TMASK  0x007FF
+#define MIPS_HFLAG_TMASK  0xC07FF
 #define MIPS_HFLAG_MODE   0x00007 /* execution modes                    */
     /* The KSU flags must be the lowest bits in hflags. The flag order
        must be the same as defined for CP0 Status. This allows to use
@@ -453,6 +453,9 @@ struct CPUMIPSState {
 #define MIPS_HFLAG_BDS32  0x10000 /* branch requires 32-bit delay slot  */
 #define MIPS_HFLAG_BX     0x20000 /* branch exchanges execution mode    */
 #define MIPS_HFLAG_BMASK  (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT)
+    /* MIPS DSP resources access. */
+#define MIPS_HFLAG_DSP   0x40000  /* Enable access to MIPS DSP resources. */
+#define MIPS_HFLAG_DSPR2 0x80000  /* Enable access to MIPS DSPR2 resources. */
     target_ulong btarget;        /* Jump / branch target               */
     target_ulong bcond;          /* Branch condition (if needed)       */
 
@@ -610,8 +613,9 @@ enum {
     EXCP_MDMX,
     EXCP_C2E,
     EXCP_CACHE, /* 32 */
+    EXCP_DSPDIS,
 
-    EXCP_LAST = EXCP_CACHE,
+    EXCP_LAST = EXCP_DSPDIS,
 };
 /* Dummy exception for conditional stores.  */
 #define EXCP_SC 0x100
@@ -772,6 +776,25 @@ static inline void compute_hflags(CPUMIPSState *env)
     if (env->CP0_Status & (1 << CP0St_FR)) {
         env->hflags |= MIPS_HFLAG_F64;
     }
+    if (env->insn_flags & ASE_DSPR2) {
+        /* Enables access MIPS DSP resources
+           on processors implementing one of these ASEs. If the MIPS DSP ASE is
+           not implemented, this bit must be ignored on write and read as
+           zero. */
+        if (env->CP0_Status & (1 << CP0St_MX)) {
+            env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2;
+        }
+
+    } else if (env->insn_flags & ASE_DSP) {
+        /* Enables access MIPS DSP resources
+           on processors implementing one of these ASEs. If the MIPS DSP ASE is
+           not implemented, this bit must be ignored on write and read as
+           zero. */
+        if (env->CP0_Status & (1 << CP0St_MX)) {
+            env->hflags |= MIPS_HFLAG_DSP;
+        }
+
+    }
     if (env->insn_flags & ISA_MIPS32R2) {
         if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
             env->hflags |= MIPS_HFLAG_COP1X;
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 4208bb2..edbe2b0 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -592,6 +592,9 @@ void do_interrupt (CPUMIPSState *env)
     case EXCP_THREAD:
         cause = 25;
         goto set_EPC;
+    case EXCP_DSPDIS:
+        cause = 26;
+        goto set_EPC;
     case EXCP_CACHE:
         cause = 30;
         if (env->CP0_Status & (1 << CP0St_BEV)) {
diff --git a/target-mips/translate.c b/target-mips/translate.c
index fa79d49..b724d24 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -942,6 +942,24 @@ static inline void check_cp1_registers(DisasContext *ctx, int regs)
         generate_exception(ctx, EXCP_RI);
 }
 
+/* Verify that the processor is running with DSP instructions enabled.
+   This is enabled by CP0 Status register MX(24) bit.
+ */
+
+static inline void check_dsp(DisasContext *ctx)
+{
+    if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
+        generate_exception(ctx, EXCP_DSPDIS);
+    }
+}
+
+static inline void check_dspr2(DisasContext *ctx)
+{
+    if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
+        generate_exception(ctx, EXCP_DSPDIS);
+    }
+}
+
 /* This code generates a "reserved instruction" exception if the
    CPU does not support the instruction set corresponding to flags. */
 static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
@@ -13196,6 +13214,11 @@ void cpu_state_reset(CPUMIPSState *env)
     if (env->CP0_Config1 & (1 << CP0C1_FP)) {
         env->CP0_Status |= (1 << CP0St_CU1);
     }
+    if (env->cpu_model->insn_flags & ASE_DSPR2) {
+        env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2;
+    } else if (env->cpu_model->insn_flags & ASE_DSP) {
+        env->hflags |= MIPS_HFLAG_DSP;
+    }
 #else
     if (env->hflags & MIPS_HFLAG_BMASK) {
         /* If the exception was raised from a delay slot,
-- 
1.7.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 03/14] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 01/14] target-mips-ase-dsp: Add internal funtions Jia Liu
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 02/14] target-mips-ase-dsp: Add dsp resources access check Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:51   ` Aurelien Jarno
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 04/14] target-mips-ase-dsp: Add branch instructions Jia Liu
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 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 |  122 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 95 insertions(+), 27 deletions(-)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index b724d24..1927781 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
@@ -2113,33 +2114,75 @@ 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. */
         MIPS_DEBUG("NOP");
         return;
     }
+
+    if (opc == OPC_MFHI || opc == OPC_MFLO) {
+        acc = ((ctx->opcode) >> 21) & 0x03;
+    } else {
+        acc = ((ctx->opcode) >> 11) & 0x03;
+    }
+
+    if (acc != 0) {
+        check_dsp(ctx);
+    }
+
     switch (opc) {
     case OPC_MFHI:
-        tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
+#if defined(TARGET_MIPS64)
+        if (acc != 0) {
+            tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
+        } else
+#endif
+        {
+            tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
+        }
         opn = "mfhi";
         break;
     case OPC_MFLO:
-        tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
+#if defined(TARGET_MIPS64)
+        if (acc != 0) {
+            tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
+        } else
+#endif
+        {
+            tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
+        }
         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);
+        if (reg != 0) {
+#if defined(TARGET_MIPS64)
+            if (acc != 0) {
+                tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
+            } else
+#endif
+            {
+                tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
+            }
+        } else {
+            tcg_gen_movi_tl(cpu_HI[acc], 0);
+        }
         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);
+        if (reg != 0) {
+#if defined(TARGET_MIPS64)
+            if (acc != 0) {
+                tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
+            } else
+#endif
+            {
+                tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
+            }
+        } else {
+            tcg_gen_movi_tl(cpu_LO[acc], 0);
+        }
         opn = "mtlo";
         break;
     }
@@ -2152,6 +2195,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:
@@ -2214,6 +2258,10 @@ 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;
+            if (acc != 0) {
+                check_dsp(ctx);
+            }
 
             tcg_gen_ext_tl_i64(t2, t0);
             tcg_gen_ext_tl_i64(t3, t1);
@@ -2223,8 +2271,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;
@@ -2232,6 +2280,10 @@ 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;
+            if (acc != 0) {
+                check_dsp(ctx);
+            }
 
             tcg_gen_ext32u_tl(t0, t0);
             tcg_gen_ext32u_tl(t1, t1);
@@ -2243,8 +2295,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;
@@ -2291,41 +2343,49 @@ 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;
+            if (acc != 0) {
+                check_dsp(ctx);
+            }
 
             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;
     case OPC_MADDU:
-       {
+        {
             TCGv_i64 t2 = tcg_temp_new_i64();
             TCGv_i64 t3 = tcg_temp_new_i64();
+            acc = ((ctx->opcode) >> 11) & 0x03;
+            if (acc != 0) {
+                check_dsp(ctx);
+            }
 
             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;
@@ -2333,19 +2393,23 @@ 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;
+            if (acc != 0) {
+                check_dsp(ctx);
+            }
 
             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;
@@ -2353,21 +2417,25 @@ 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;
+            if (acc != 0) {
+                check_dsp(ctx);
+            }
 
             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.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 04/14] target-mips-ase-dsp: Add branch instructions
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
                   ` (2 preceding siblings ...)
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 03/14] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:51   ` Aurelien Jarno
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 05/14] target-mips-ase-dsp: Add load instructions Jia Liu
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 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 |   36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 1927781..4103f24 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))
 
@@ -3224,6 +3232,16 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
         }
         btgt = ctx->pc + insn_bytes + offset;
         break;
+    case OPC_BPOSGE32:
+#if defined(TARGET_MIPS64)
+    case OPC_BPOSGE64:
+        tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
+#else
+        tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
+#endif
+        bcond_compute = 1;
+        btgt = ctx->pc + insn_bytes + offset;
+        break;
     case OPC_J:
     case OPC_JAL:
     case OPC_JALX:
@@ -3412,6 +3430,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 " TARGET_FMT_lx, btgt);
+            goto not_likely;
+#if defined(TARGET_MIPS64)
+        case OPC_BPOSGE64:
+            tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
+            MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
+            goto not_likely;
+#endif
         case OPC_BLTZALS:
         case OPC_BLTZAL:
             ctx->hflags |= (opc == OPC_BLTZALS
@@ -12582,6 +12610,14 @@ 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 */
+#if defined(TARGET_MIPS64)
+        case OPC_BPOSGE64:
+#endif
+            check_dsp(ctx);
+            gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
+            *is_branch = 1;
+            break;
         default:            /* Invalid */
             MIPS_INVAL("regimm");
             generate_exception(ctx, EXCP_RI);
-- 
1.7.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 05/14] target-mips-ase-dsp: Add load instructions
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
                   ` (3 preceding siblings ...)
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 04/14] target-mips-ase-dsp: Add branch instructions Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:51   ` Aurelien Jarno
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 06/14] target-mips-ase-dsp: Add arithmetic instructions Jia Liu
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 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 |   84 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 4103f24..6d5c475 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))
 
@@ -12213,6 +12227,58 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b
 
 #endif
 
+/* MIPSDSP functions. */
+static void gen_mipsdsp_ld(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+                           int rd, int base, int offset)
+{
+    const char *opn = "ldx";
+    TCGv t0;
+
+    if (rd == 0 && env->insn_flags & (ASE_DSP | ASE_DSPR2)) {
+        /* Loongson CPU uses a load to zero register for prefetch.
+           We emulate it as a NOP. On other CPU we must perform the
+           actual memory access. */
+        MIPS_DEBUG("NOP");
+        return;
+    }
+
+    t0 = tcg_temp_new();
+    gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
+    save_cpu_state(ctx, 0);
+
+    switch (opc) {
+    case OPC_LBUX:
+        op_ld_lbu(t0, t0, ctx);
+        gen_store_gpr(t0, rd);
+        opn = "lbux";
+        break;
+    case OPC_LHX:
+        op_ld_lh(t0, t0, ctx);
+        gen_store_gpr(t0, rd);
+        opn = "lhx";
+        break;
+    case OPC_LWX:
+        op_ld_lw(t0, t0, ctx);
+        gen_store_gpr(t0, rd);
+        opn = "lwx";
+        break;
+#if defined(TARGET_MIPS64)
+    case OPC_LDX:
+        op_ld_ld(t0, t0, ctx);
+        gen_store_gpr(t0, rd);
+        opn = "ldx";
+        break;
+#endif
+    }
+    (void)opn; /* avoid a compiler warning */
+    MIPS_DEBUG("%s %s, %s(%s)", opn,
+               regnames[rd], regnames[offset], regnames[base]);
+    tcg_temp_free(t0);
+}
+
+
+/* End MIPSDSP functions. */
+
 static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
 {
     int32_t offset;
@@ -12568,6 +12634,24 @@ 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:
+            check_dsp(ctx);
+            op2 = MASK_LX(ctx->opcode);
+            switch (op2) {
+#if defined(TARGET_MIPS64)
+            case OPC_LDX:
+#endif
+            case OPC_LBUX:
+            case OPC_LHX:
+            case OPC_LWX:
+                gen_mipsdsp_ld(env, ctx, op2, rd, rs, rt);
+                break;
+            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.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 06/14] target-mips-ase-dsp: Add arithmetic instructions
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
                   ` (4 preceding siblings ...)
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 05/14] target-mips-ase-dsp: Add load instructions Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:51   ` Aurelien Jarno
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 07/14] target-mips-ase-dsp: Add GPR-based shift instructions Jia Liu
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 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 |  895 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/helper.h     |  126 +++++++
 target-mips/translate.c  |  830 +++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 1848 insertions(+), 3 deletions(-)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index b04b489..555a5ed 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -1119,3 +1119,898 @@ static inline int32_t mipsdsp_cmp_lt(uint32_t a, uint32_t b)
     return a < b;
 }
 /*** 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
+
+#define MIPSDSP_SPLIT32_8(num, a, b, c, d)  \
+    do {                                    \
+        a = (num >> 24) & MIPSDSP_Q0;       \
+        b = (num >> 16) & MIPSDSP_Q0;       \
+        c = (num >> 8) & MIPSDSP_Q0;        \
+        d = num & MIPSDSP_Q0;               \
+    } while (0)
+
+#define MIPSDSP_SPLIT32_16(num, a, b)       \
+    do {                                    \
+        a = (num >> 16) & MIPSDSP_LO;       \
+        b = num & MIPSDSP_LO;               \
+    } while (0)
+
+#define MIPSDSP_RETURN32(a)             ((target_long)(int32_t)a)
+#define MIPSDSP_RETURN32_8(a, b, c, d)  ((target_long)(int32_t) \
+                                         (((uint32_t)a << 24) | \
+                                         (((uint32_t)b << 16) | \
+                                         (((uint32_t)c << 8) |  \
+                                          ((uint32_t)d & 0xFF)))))
+#define MIPSDSP_RETURN32_16(a, b)       ((target_long)(int32_t) \
+                                         (((uint32_t)a << 16) | \
+                                          ((uint32_t)b & 0xFFFF)))
+
+#ifdef TARGET_MIPS64
+#define MIPSDSP_SPLIT64_16(num, a, b, c, d)  \
+    do {                                     \
+        a = (num >> 48) & MIPSDSP_LO;        \
+        b = (num >> 32) & MIPSDSP_LO;        \
+        c = (num >> 16) & MIPSDSP_LO;        \
+        d = num & MIPSDSP_LO;                \
+    } while (0)
+
+#define MIPSDSP_SPLIT64_32(num, a, b)       \
+    do {                                    \
+        a = (num >> 32) & MIPSDSP_LLO;      \
+        b = num & MIPSDSP_LLO;              \
+    } while (0)
+
+#define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)a << 48) | \
+                                         ((uint64_t)b << 32) | \
+                                         ((uint64_t)c << 16) | \
+                                         (uint64_t)d)
+#define MIPSDSP_RETURN64_32(a, b)       (((uint64_t)a << 32) | (uint64_t)b)
+#endif
+
+/** DSP Arithmetic Sub-class insns **/
+#define ARITH_PH(name, func)                                      \
+target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt) \
+{                                                                 \
+    uint16_t  rsh, rsl, rth, rtl, temph, templ;                   \
+                                                                  \
+    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                             \
+    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
+                                                                  \
+    temph = mipsdsp_##func(rsh, rth);                             \
+    templ = mipsdsp_##func(rsl, rtl);                             \
+                                                                  \
+    return MIPSDSP_RETURN32_16(temph, templ);                     \
+}
+
+#define ARITH_PH_ENV(name, func)                                  \
+target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt, \
+                                CPUMIPSState *env)                \
+{                                                                 \
+    uint16_t  rsh, rsl, rth, rtl, temph, templ;                   \
+                                                                  \
+    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                             \
+    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
+                                                                  \
+    temph = mipsdsp_##func(rsh, rth, env);                        \
+    templ = mipsdsp_##func(rsl, rtl, env);                        \
+                                                                  \
+    return MIPSDSP_RETURN32_16(temph, templ);                     \
+}
+
+
+ARITH_PH_ENV(addq, add_i16);
+ARITH_PH_ENV(addq_s, sat_add_i16);
+ARITH_PH_ENV(addu, add_u16);
+ARITH_PH_ENV(addu_s, sat_add_u16);
+
+ARITH_PH(addqh, rshift1_add_q16);
+ARITH_PH(addqh_r, rrshift1_add_q16);
+
+ARITH_PH_ENV(subq, sub_i16);
+ARITH_PH_ENV(subq_s, sat16_sub);
+ARITH_PH_ENV(subu, sub_u16_u16);
+ARITH_PH_ENV(subu_s, satu16_sub_u16_u16);
+
+ARITH_PH(subqh, rshift1_sub_q16);
+ARITH_PH(subqh_r, rrshift1_sub_q16);
+
+#undef ARITH_PH
+#undef ARITH_PH_ENV
+
+#ifdef TARGET_MIPS64
+#define ARITH_QH_ENV(name, func) \
+target_ulong helper_##name##_qh(target_ulong rs, target_ulong rt, \
+                                CPUMIPSState *env)           \
+{                                                            \
+    uint16_t rs3, rs2, rs1, rs0;                             \
+    uint16_t rt3, rt2, rt1, rt0;                             \
+    uint16_t tempD, tempC, tempB, tempA;                     \
+                                                             \
+    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);              \
+    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);              \
+                                                             \
+    tempD = mipsdsp_##func(rs3, rt3, env);                   \
+    tempC = mipsdsp_##func(rs2, rt2, env);                   \
+    tempB = mipsdsp_##func(rs1, rt1, env);                   \
+    tempA = mipsdsp_##func(rs0, rt0, env);                   \
+                                                             \
+    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
+}
+
+ARITH_QH_ENV(addq, add_i16);
+ARITH_QH_ENV(addq_s, sat_add_i16);
+ARITH_QH_ENV(addu, add_u16);
+ARITH_QH_ENV(addu_s, sat_add_u16);
+
+ARITH_QH_ENV(subq, sub_i16);
+ARITH_QH_ENV(subq_s, sat16_sub);
+ARITH_QH_ENV(subu, sub_u16_u16);
+ARITH_QH_ENV(subu_s, satu16_sub_u16_u16);
+
+#undef ARITH_QH_ENV
+
+#endif
+
+#define ARITH_W(name, func) \
+target_ulong helper_##name##_w(target_ulong rs, target_ulong rt) \
+{                                                                \
+    uint32_t rd;                                                 \
+    rd = mipsdsp_##func(rs, rt);                                 \
+    return MIPSDSP_RETURN32(rd);                                 \
+}
+
+#define ARITH_W_ENV(name, func) \
+target_ulong helper_##name##_w(target_ulong rs, target_ulong rt, \
+                               CPUMIPSState *env)                \
+{                                                                \
+    uint32_t rd;                                                 \
+    rd = mipsdsp_##func(rs, rt, env);                            \
+    return MIPSDSP_RETURN32(rd);                                 \
+}
+
+ARITH_W_ENV(addq_s, sat_add_i32);
+
+ARITH_W(addqh, rshift1_add_q32);
+ARITH_W(addqh_r, rrshift1_add_q32);
+
+ARITH_W_ENV(subq_s, sat32_sub);
+
+ARITH_W(subqh, rshift1_sub_q32);
+ARITH_W(subqh_r, rrshift1_sub_q32);
+
+#undef ARITH_W
+#undef ARITH_W_ENV
+
+target_ulong helper_absq_s_w(target_ulong rt, CPUMIPSState *env)
+{
+    uint32_t rd;
+
+    rd = mipsdsp_sat_abs_u32(rt, env);
+
+    return (target_ulong)rd;
+}
+
+
+#if defined(TARGET_MIPS64)
+
+#define ARITH_PW_ENV(name, func) \
+target_ulong helper_##name##_pw(target_ulong rs, target_ulong rt, \
+                                CPUMIPSState *env)                \
+{                                                                 \
+    uint32_t rs1, rs0;                                            \
+    uint32_t rt1, rt0;                                            \
+    uint32_t tempB, tempA;                                        \
+                                                                  \
+    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                             \
+    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
+                                                                  \
+    tempB = mipsdsp_##func(rs1, rt1, env);                        \
+    tempA = mipsdsp_##func(rs0, rt0, env);                        \
+                                                                  \
+    return MIPSDSP_RETURN64_32(tempB, tempA);                     \
+}
+
+ARITH_PW_ENV(addq, add_i32);
+ARITH_PW_ENV(addq_s, sat_add_i32);
+ARITH_PW_ENV(subq, sub32);
+ARITH_PW_ENV(subq_s, sat32_sub);
+
+#undef ARITH_PW_ENV
+
+#endif
+
+#define ARITH_QB(name, func) \
+target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \
+{                                                                 \
+    uint8_t  rs0, rs1, rs2, rs3;                                  \
+    uint8_t  rt0, rt1, rt2, rt3;                                  \
+    uint8_t  temp0, temp1, temp2, temp3;                          \
+                                                                  \
+    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                    \
+    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                    \
+                                                                  \
+    temp0 = mipsdsp_##func(rs0, rt0);                             \
+    temp1 = mipsdsp_##func(rs1, rt1);                             \
+    temp2 = mipsdsp_##func(rs2, rt2);                             \
+    temp3 = mipsdsp_##func(rs3, rt3);                             \
+                                                                  \
+    return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0);        \
+}
+
+#define ARITH_QB_ENV(name, func) \
+target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt, \
+                                CPUMIPSState *env)          \
+{                                                           \
+    uint8_t  rs0, rs1, rs2, rs3;                            \
+    uint8_t  rt0, rt1, rt2, rt3;                            \
+    uint8_t  temp0, temp1, temp2, temp3;                    \
+                                                            \
+    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);              \
+    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);              \
+                                                            \
+    temp0 = mipsdsp_##func(rs0, rt0, env);                  \
+    temp1 = mipsdsp_##func(rs1, rt1, env);                  \
+    temp2 = mipsdsp_##func(rs2, rt2, env);                  \
+    temp3 = mipsdsp_##func(rs3, rt3, env);                  \
+                                                            \
+    return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0);  \
+}
+
+ARITH_QB(adduh, rshift1_add_u8);
+ARITH_QB(adduh_r, rrshift1_add_u8);
+
+ARITH_QB_ENV(addu, add_u8);
+ARITH_QB_ENV(addu_s, sat_add_u8);
+
+#undef ADDU_QB
+#undef ADDU_QB_ENV
+
+#if defined(TARGET_MIPS64)
+#define ARITH_OB(name, func) \
+target_ulong helper_##name##_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_##func(rs_t[i], rt_t[i]);               \
+        result |= (uint64_t)temp[i] << (8 * i);                   \
+    }                                                             \
+                                                                  \
+    return result;                                                \
+}
+
+#define ARITH_OB_ENV(name, func) \
+target_ulong helper_##name##_ob(target_ulong rs, target_ulong rt, \
+                                CPUMIPSState *env)                \
+{                                                                 \
+    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_##func(rs_t[i], rt_t[i], env);          \
+        result |= (uint64_t)temp[i] << (8 * i);                   \
+    }                                                             \
+                                                                  \
+    return result;                                                \
+}
+
+ARITH_OB_ENV(addu, add_u8);
+ARITH_OB_ENV(addu_s, sat_add_u8);
+
+ARITH_OB(adduh, rshift1_add_u8);
+ARITH_OB(adduh_r, rrshift1_add_u8);
+
+ARITH_OB_ENV(subu, sub_u8);
+ARITH_OB_ENV(subu_s, satu8_sub);
+
+ARITH_OB(subuh, rshift1_sub_u8);
+ARITH_OB(subuh_r, rrshift1_sub_u8);
+
+#undef ARITH_OB
+#undef ARITH_OB_ENV
+
+#endif
+
+#define SUBU_QB(name, func) \
+target_ulong helper_##name##_qb(target_ulong rs,               \
+                                target_ulong rt,               \
+                                CPUMIPSState *env)             \
+{                                                              \
+    uint8_t rs3, rs2, rs1, rs0;                                \
+    uint8_t rt3, rt2, rt1, rt0;                                \
+    uint8_t tempD, tempC, tempB, tempA;                        \
+                                                               \
+    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                 \
+    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                 \
+                                                               \
+    tempD = mipsdsp_##func(rs3, rt3, env);                     \
+    tempC = mipsdsp_##func(rs2, rt2, env);                     \
+    tempB = mipsdsp_##func(rs1, rt1, env);                     \
+    tempA = mipsdsp_##func(rs0, rt0, env);                     \
+                                                               \
+    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);     \
+}
+
+SUBU_QB(subu, sub_u8);
+SUBU_QB(subu_s, satu8_sub);
+
+#undef SUBU_QB
+
+#define SUBUH_QB(name, var) \
+target_ulong helper_##name##_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;                           \
+                                                                  \
+    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                    \
+    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                    \
+                                                                  \
+    tempD = ((uint16_t)rs3 - (uint16_t)rt3 + var) >> 1;           \
+    tempC = ((uint16_t)rs2 - (uint16_t)rt2 + var) >> 1;           \
+    tempB = ((uint16_t)rs1 - (uint16_t)rt1 + var) >> 1;           \
+    tempA = ((uint16_t)rs0 - (uint16_t)rt0 + var) >> 1;           \
+                                                                  \
+    return ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |    \
+           ((uint32_t)tempB << 8) | (uint32_t)tempA;              \
+}
+
+SUBUH_QB(subuh, 0);
+SUBUH_QB(subuh_r, 1);
+
+#undef SUBUH_QB
+
+target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
+{
+    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(flag, env);
+
+    return (target_long)(int32_t)(temp & MIPSDSP_LLO);
+}
+
+target_ulong helper_addwc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
+{
+    uint32_t rd;
+    int32_t temp32, temp31;
+    int64_t tempL;
+
+    tempL = (int32_t)rs + (int32_t)rt + get_DSPControl_carryflag(env);
+    temp31 = (tempL >> 31) & 0x01;
+    temp32 = (tempL >> 32) & 0x01;
+
+    if (temp31 != temp32) {
+        set_DSPControl_overflow_flag(1, 20, env);
+    }
+
+    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;
+
+    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);
+
+    temp = (uint16_t)rs3 + (uint16_t)rs2 + (uint16_t)rs1 + (uint16_t)rs0;
+
+    return (target_ulong)temp;
+}
+
+#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(target_ulong rt, CPUMIPSState *env)
+{
+    uint32_t rd;
+    int8_t tempD, tempC, tempB, tempA;
+
+    MIPSDSP_SPLIT32_8(rt, tempD, tempC, tempB, tempA);
+
+    rd = (((uint32_t)mipsdsp_sat_abs_u8 (tempD, env) << 24) & MIPSDSP_Q3) |
+         (((uint32_t)mipsdsp_sat_abs_u8 (tempC, env) << 16) & MIPSDSP_Q2) |
+         (((uint32_t)mipsdsp_sat_abs_u8 (tempB, env) <<  8) & MIPSDSP_Q1) |
+         ((uint32_t)mipsdsp_sat_abs_u8 (tempA, env) & MIPSDSP_Q0);
+
+    return (target_ulong)rd;
+}
+
+target_ulong helper_absq_s_ph(target_ulong rt, CPUMIPSState *env)
+{
+    uint32_t rd;
+    int16_t tempB, tempA;
+
+    MIPSDSP_SPLIT32_16(rt, tempB, tempA);
+
+    rd = ((uint32_t)(uint16_t)mipsdsp_sat_abs_u16 (tempB, env) << 16) |
+        ((uint32_t)((uint16_t)mipsdsp_sat_abs_u16 (tempA, env)) & 0xFFFF);
+
+    return (target_long)(int32_t)rd;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_absq_s_ob(target_ulong rt, CPUMIPSState *env)
+{
+    int i;
+    int8_t temp[8];
+    uint64_t result;
+
+    for (i = 0; i < 8; i++) {
+        temp[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
+        temp[i] = mipsdsp_sat_abs_u8(temp[i], env);
+    }
+
+    for (i = 0; i < 8; i++) {
+        result = (uint64_t)(uint8_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+target_ulong helper_absq_s_qh(target_ulong rt, CPUMIPSState *env)
+{
+    int16_t tempD, tempC, tempB, tempA;
+
+    MIPSDSP_SPLIT64_16(rt, tempD, tempC, tempB, tempA);
+
+    tempD = mipsdsp_sat_abs_u16(tempD, env);
+    tempC = mipsdsp_sat_abs_u16(tempC, env);
+    tempB = mipsdsp_sat_abs_u16(tempB, env);
+    tempA = mipsdsp_sat_abs_u16(tempA, env);
+
+    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
+}
+
+target_ulong helper_absq_s_pw(target_ulong rt, CPUMIPSState *env)
+{
+    int32_t tempB, tempA;
+
+    MIPSDSP_SPLIT64_32(rt, tempB, tempA);
+
+    tempB = mipsdsp_sat_abs_u32(tempB, env);
+    tempA = mipsdsp_sat_abs_u32(tempA, env);
+
+    return MIPSDSP_RETURN64_32(tempB, tempA);
+}
+#endif
+
+#define PRECR_QB_PH(name, a, b)\
+target_ulong helper_##name##_qb_ph(target_ulong rs, target_ulong rt) \
+{                                                                    \
+    uint8_t tempD, tempC, tempB, tempA;                              \
+                                                                     \
+    tempD = (rs >> a) & MIPSDSP_Q0;                                  \
+    tempC = (rs >> b) & MIPSDSP_Q0;                                  \
+    tempB = (rt >> a) & MIPSDSP_Q0;                                  \
+    tempA = (rt >> b) & MIPSDSP_Q0;                                  \
+                                                                     \
+    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);           \
+}
+
+PRECR_QB_PH(precr, 16, 0);
+PRECR_QB_PH(precrq, 24, 8);
+
+#undef PRECR_QB_OH
+
+target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs,
+                                   target_ulong rt)
+{
+    uint16_t tempB, tempA;
+
+    tempB = ((int32_t)rt >> sa) & MIPSDSP_LO;
+    tempA = ((int32_t)rs >> sa) & MIPSDSP_LO;
+
+    return MIPSDSP_RETURN32_16(tempB, tempA);
+}
+
+target_ulong helper_precr_sra_r_ph_w(uint32_t sa,
+                                     target_ulong rs, target_ulong rt)
+{
+    uint64_t tempB, tempA;
+
+    /* If sa = 0, then (sa - 1) = -1 will case shift error, so we need else. */
+    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;
+
+    tempB = (rs & MIPSDSP_HI) >> 16;
+    tempA = (rt & MIPSDSP_HI) >> 16;
+
+    return MIPSDSP_RETURN32_16(tempB, tempA);
+}
+
+target_ulong helper_precrq_rs_ph_w(target_ulong rs, target_ulong rt,
+                                   CPUMIPSState *env)
+{
+    uint16_t tempB, tempA;
+
+    tempB = mipsdsp_trunc16_sat16_round(rs, env);
+    tempA = mipsdsp_trunc16_sat16_round(rt, env);
+
+    return MIPSDSP_RETURN32_16(tempB, tempA);
+}
+
+#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;
+}
+
+#define PRECR_QH_PW(name, var) \
+target_ulong helper_precr_##name##_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;                              \
+                                                                      \
+    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);                       \
+    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                       \
+                                                                      \
+    /* When sa = 0, we use rt2, rt0, rs2, rs0;                        \
+     * when sa != 0, we use rt3, rt1, rs3, rs1. */                    \
+    if (sa == 0) {                                                    \
+        tempD = rt2 << var;                                           \
+        tempC = rt0 << var;                                           \
+        tempB = rs2 << var;                                           \
+        tempA = rs0 << var;                                           \
+    } else {                                                          \
+        tempD = (((int16_t)rt3 >> sa) + var) >> var;                  \
+        tempC = (((int16_t)rt1 >> sa) + var) >> var;                  \
+        tempB = (((int16_t)rs3 >> sa) + var) >> var;                  \
+        tempA = (((int16_t)rs1 >> sa) + var) >> var;                  \
+    }                                                                 \
+                                                                      \
+    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);           \
+}
+
+PRECR_QH_PW(sra, 0);
+PRECR_QH_PW(sra_r, 1);
+
+#undef PRECR_QH_PW
+
+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;
+
+    tempD = (rs >> 48) & MIPSDSP_LO;
+    tempC = (rs >> 16) & MIPSDSP_LO;
+    tempB = (rt >> 48) & MIPSDSP_LO;
+    tempA = (rt >> 16) & MIPSDSP_LO;
+
+    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
+}
+
+target_ulong helper_precrq_rs_qh_pw(target_ulong rs, target_ulong rt,
+                                    CPUMIPSState *env)
+{
+    uint32_t rs2, rs0;
+    uint32_t rt2, rt0;
+    uint16_t tempD, tempC, tempB, tempA;
+
+    rs2 = (rs >> 32) & MIPSDSP_LLO;
+    rs0 = rs & MIPSDSP_LLO;
+    rt2 = (rt >> 32) & MIPSDSP_LLO;
+    rt0 = rt & MIPSDSP_LLO;
+
+    tempD = mipsdsp_trunc16_sat16_round(rs2, env);
+    tempC = mipsdsp_trunc16_sat16_round(rs0, env);
+    tempB = mipsdsp_trunc16_sat16_round(rt2, env);
+    tempA = mipsdsp_trunc16_sat16_round(rt0, env);
+
+    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
+}
+
+target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt)
+{
+    uint32_t tempB, tempA;
+
+    tempB = (rs >> 32) & MIPSDSP_LLO;
+    tempA = (rt >> 32) & MIPSDSP_LLO;
+
+    return MIPSDSP_RETURN64_32(tempB, tempA);
+}
+#endif
+
+target_ulong helper_precrqu_s_qb_ph(target_ulong rs, target_ulong rt,
+                                    CPUMIPSState *env)
+{
+    uint8_t  tempD, tempC, tempB, tempA;
+    uint16_t rsh, rsl, rth, rtl;
+
+    rsh = (rs & MIPSDSP_HI) >> 16;
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+    rtl =  rt & MIPSDSP_LO;
+
+    tempD = mipsdsp_sat8_reduce_precision(rsh, env);
+    tempC = mipsdsp_sat8_reduce_precision(rsl, env);
+    tempB = mipsdsp_sat8_reduce_precision(rth, env);
+    tempA = mipsdsp_sat8_reduce_precision(rtl, env);
+
+    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_precrqu_s_ob_qh(target_ulong rs, target_ulong rt,
+                                    CPUMIPSState *env)
+{
+    int i;
+    uint16_t rs3, rs2, rs1, rs0;
+    uint16_t rt3, rt2, rt1, rt0;
+    uint8_t temp[8];
+    uint64_t result;
+
+    result = 0;
+
+    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
+    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
+
+    temp[7] = mipsdsp_sat8_reduce_precision(rs3, env);
+    temp[6] = mipsdsp_sat8_reduce_precision(rs2, env);
+    temp[5] = mipsdsp_sat8_reduce_precision(rs1, env);
+    temp[4] = mipsdsp_sat8_reduce_precision(rs0, env);
+    temp[3] = mipsdsp_sat8_reduce_precision(rt3, env);
+    temp[2] = mipsdsp_sat8_reduce_precision(rt2, env);
+    temp[1] = mipsdsp_sat8_reduce_precision(rt1, env);
+    temp[0] = mipsdsp_sat8_reduce_precision(rt0, env);
+
+    for (i = 0; i < 8; i++) {
+        result |= (uint64_t)temp[i] << (8 * i);
+    }
+
+    return result;
+}
+
+#define PRECEQ_PW(name, a, b) \
+target_ulong helper_preceq_pw_##name(target_ulong rt) \
+{                                                       \
+    uint16_t tempB, tempA;                              \
+    uint32_t tempBI, tempAI;                            \
+                                                        \
+    tempB = (rt >> a) & MIPSDSP_LO;                     \
+    tempA = (rt >> b) & MIPSDSP_LO;                     \
+                                                        \
+    tempBI = (uint32_t)tempB << 16;                     \
+    tempAI = (uint32_t)tempA << 16;                     \
+                                                        \
+    return MIPSDSP_RETURN64_32(tempBI, tempAI);         \
+}
+
+PRECEQ_PW(qhl, 48, 32);
+PRECEQ_PW(qhr, 16, 0);
+PRECEQ_PW(qhla, 48, 16);
+PRECEQ_PW(qhra, 32, 0);
+
+#undef PRECEQ_PW
+
+#endif
+
+#define PRECEQU_PH(name, a, b) \
+target_ulong helper_precequ_ph_##name(target_ulong rt) \
+{                                                        \
+    uint16_t tempB, tempA;                               \
+                                                         \
+    tempB = (rt >> a) & MIPSDSP_Q0;                      \
+    tempA = (rt >> b) & MIPSDSP_Q0;                      \
+                                                         \
+    tempB = tempB << 7;                                  \
+    tempA = tempA << 7;                                  \
+                                                         \
+    return MIPSDSP_RETURN32_16(tempB, tempA);            \
+}
+
+PRECEQU_PH(qbl, 24, 16);
+PRECEQU_PH(qbr, 8, 0);
+PRECEQU_PH(qbla, 24, 8);
+PRECEQU_PH(qbra, 16, 0);
+
+#undef PRECEQU_PH
+
+#if defined(TARGET_MIPS64)
+#define PRECEQU_QH(name, a, b, c, d) \
+target_ulong helper_precequ_qh_##name(target_ulong rt)       \
+{                                                            \
+    uint16_t tempD, tempC, tempB, tempA;                     \
+                                                             \
+    tempD = (rt >> a) & MIPSDSP_Q0;                          \
+    tempC = (rt >> b) & MIPSDSP_Q0;                          \
+    tempB = (rt >> c) & MIPSDSP_Q0;                          \
+    tempA = (rt >> d) & MIPSDSP_Q0;                          \
+                                                             \
+    tempD = tempD << 7;                                      \
+    tempC = tempC << 7;                                      \
+    tempB = tempB << 7;                                      \
+    tempA = tempA << 7;                                      \
+                                                             \
+    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
+}
+
+PRECEQU_QH(obl, 56, 48, 40, 32);
+PRECEQU_QH(obr, 24, 16, 8, 0);
+PRECEQU_QH(obla, 56, 40, 24, 8);
+PRECEQU_QH(obra, 48, 32, 16, 0);
+
+#undef PRECEQU_QH
+
+#endif
+
+#define PRECEU_PH(name, a, b) \
+target_ulong helper_preceu_ph_##name(target_ulong rt) \
+{                                                     \
+    uint16_t tempB, tempA;                            \
+                                                      \
+    tempB = (rt >> a) & MIPSDSP_Q0;                   \
+    tempA = (rt >> b) & MIPSDSP_Q0;                   \
+                                                      \
+    return MIPSDSP_RETURN32_16(tempB, tempA);         \
+}
+
+PRECEU_PH(qbl, 24, 16);
+PRECEU_PH(qbr, 8, 0);
+PRECEU_PH(qbla, 24, 8);
+PRECEU_PH(qbra, 16, 0);
+
+#undef PRECEU_PH
+
+#if defined(TARGET_MIPS64)
+#define PRECEU_QH(name, a, b, c, d) \
+target_ulong helper_preceu_qh_##name(target_ulong rt)        \
+{                                                            \
+    uint16_t tempD, tempC, tempB, tempA;                     \
+                                                             \
+    tempD = (rt >> a) & MIPSDSP_Q0;                          \
+    tempC = (rt >> b) & MIPSDSP_Q0;                          \
+    tempB = (rt >> c) & MIPSDSP_Q0;                          \
+    tempA = (rt >> d) & MIPSDSP_Q0;                          \
+                                                             \
+    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
+}
+
+PRECEU_QH(obl, 56, 48, 40, 32);
+PRECEU_QH(obr, 24, 16, 8, 0);
+PRECEU_QH(obla, 56, 40, 24, 8);
+PRECEU_QH(obra, 48, 32, 16, 0);
+
+#undef PRECEU_QH
+
+#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
+
+#undef MIPSDSP_SPLIT32_8
+#undef MIPSDSP_SPLIT32_16
+
+#undef MIPSDSP_RETURN32
+#undef MIPSDSP_RETURN32_8
+#undef MIPSDSP_RETURN32_16
+
+#ifdef TARGET_MIPS64
+#undef MIPSDSP_SPLIT64_16
+#undef MIPSDSP_SPLIT64_32
+#undef MIPSDSP_RETURN64_16
+#undef MIPSDSP_RETURN64_32
+#endif
diff --git a/target-mips/helper.h b/target-mips/helper.h
index f35ed78..9201aae 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -362,4 +362,130 @@ DEF_HELPER_FLAGS_2(pasubub, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
 DEF_HELPER_FLAGS_1(biadd, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
 DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
 
+/*** MIPS DSP ***/
+/* DSP Arithmetic Sub-class insns */
+DEF_HELPER_FLAGS_3(addq_ph, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(addq_s_ph, 0, tl, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(addq_qh, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(addq_s_qh, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(addq_s_w, 0, tl, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(addq_pw, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(addq_s_pw, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(addu_qb, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(addu_s_qb, 0, tl, tl, tl, env)
+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, tl, tl, env)
+DEF_HELPER_FLAGS_3(addu_s_ph, 0, tl, tl, tl, env)
+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, tl, tl, env)
+DEF_HELPER_FLAGS_3(addu_s_ob, 0, tl, tl, tl, env)
+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, tl, tl, env)
+DEF_HELPER_FLAGS_3(addu_s_qh, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(subq_ph, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(subq_s_ph, 0, tl, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(subq_qh, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(subq_s_qh, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(subq_s_w, 0, tl, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(subq_pw, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(subq_s_pw, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(subu_qb, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(subu_s_qb, 0, tl, tl, tl, env)
+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, tl, tl, env)
+DEF_HELPER_FLAGS_3(subu_s_ph, 0, tl, tl, tl, env)
+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, tl, tl, env)
+DEF_HELPER_FLAGS_3(subu_s_ob, 0, tl, tl, tl, env)
+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, tl, tl, env)
+DEF_HELPER_FLAGS_3(subu_s_qh, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(addsc, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(addwc, 0, tl, tl, tl, env)
+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, tl, env)
+DEF_HELPER_FLAGS_2(absq_s_ph, 0, tl, tl, env)
+DEF_HELPER_FLAGS_2(absq_s_w, 0, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_2(absq_s_ob, 0, tl, tl, env)
+DEF_HELPER_FLAGS_2(absq_s_qh, 0, tl, tl, env)
+DEF_HELPER_FLAGS_2(absq_s_pw, 0, tl, tl, env)
+#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, tl, tl, env)
+#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, tl, tl, env)
+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, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(precrqu_s_ob_qh,
+                   TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, env)
+
+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)
+#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 6d5c475..d057b30 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))
 
@@ -12276,6 +12429,494 @@ static void gen_mipsdsp_ld(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
     tcg_temp_free(t0);
 }
 
+static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
+                              int ret, int v1, int v2)
+{
+    const char *opn = "mipsdsp arith";
+
+    if (ret == 0) {
+        /* Treat as NOP. */
+        MIPS_DEBUG("NOP");
+        return;
+    }
+
+    switch (op1) {
+    /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
+    case OPC_MULT_G_2E:
+        check_dspr2(ctx);
+        switch (op2) {
+        case OPC_ADDUH_QB:
+            gen_helper_adduh_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_ADDUH_R_QB:
+            gen_helper_adduh_r_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_ADDQH_PH:
+            gen_helper_addqh_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_ADDQH_R_PH:
+            gen_helper_addqh_r_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_ADDQH_W:
+            gen_helper_addqh_w(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_ADDQH_R_W:
+            gen_helper_addqh_r_w(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_SUBUH_QB:
+            gen_helper_subuh_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_SUBUH_R_QB:
+            gen_helper_subuh_r_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_SUBQH_PH:
+            gen_helper_subqh_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_SUBQH_R_PH:
+            gen_helper_subqh_r_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_SUBQH_W:
+            gen_helper_subqh_w(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_SUBQH_R_W:
+            gen_helper_subqh_r_w(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        }
+        break;
+    case OPC_ABSQ_S_PH_DSP:
+        switch (op2) {
+        case OPC_ABSQ_S_QB:
+            check_dspr2(ctx);
+            gen_helper_absq_s_qb(cpu_gpr[ret], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ABSQ_S_PH:
+            check_dsp(ctx);
+            gen_helper_absq_s_ph(cpu_gpr[ret], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ABSQ_S_W:
+            check_dsp(ctx);
+            gen_helper_absq_s_w(cpu_gpr[ret], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_PRECEQ_W_PHL:
+            {
+                TCGv temp = tcg_temp_new();;
+                check_dsp(ctx);
+                tcg_gen_andi_tl(temp, cpu_gpr[v2], 0xFFFF0000);
+                tcg_gen_ext32s_tl(cpu_gpr[ret], temp);
+                tcg_temp_free(temp);
+                break;
+            }
+        case OPC_PRECEQ_W_PHR:
+            {
+                TCGv temp = tcg_temp_new();;
+                check_dsp(ctx);
+                tcg_gen_andi_tl(temp, cpu_gpr[v2], 0x0000FFFF);
+                tcg_gen_shli_tl(temp, temp, 16);
+                tcg_gen_ext32s_tl(cpu_gpr[ret], temp);
+                tcg_temp_free(temp);
+                break;
+            }
+        case OPC_PRECEQU_PH_QBL:
+            check_dsp(ctx);
+            gen_helper_precequ_ph_qbl(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEQU_PH_QBR:
+            check_dsp(ctx);
+            gen_helper_precequ_ph_qbr(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEQU_PH_QBLA:
+            check_dsp(ctx);
+            gen_helper_precequ_ph_qbla(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEQU_PH_QBRA:
+            check_dsp(ctx);
+            gen_helper_precequ_ph_qbra(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEU_PH_QBL:
+            check_dsp(ctx);
+            gen_helper_preceu_ph_qbl(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEU_PH_QBR:
+            check_dsp(ctx);
+            gen_helper_preceu_ph_qbr(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEU_PH_QBLA:
+            check_dsp(ctx);
+            gen_helper_preceu_ph_qbla(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEU_PH_QBRA:
+            check_dsp(ctx);
+            gen_helper_preceu_ph_qbra(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        }
+        break;
+    case OPC_ADDU_QB_DSP:
+        switch (op2) {
+        case OPC_ADDQ_PH:
+            check_dsp(ctx);
+            gen_helper_addq_ph(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDQ_S_PH:
+            check_dsp(ctx);
+            gen_helper_addq_s_ph(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDQ_S_W:
+            check_dsp(ctx);
+            gen_helper_addq_s_w(cpu_gpr[ret], cpu_gpr[v1],
+                                cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDU_QB:
+            check_dsp(ctx);
+            gen_helper_addu_qb(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDU_S_QB:
+            check_dsp(ctx);
+            gen_helper_addu_s_qb(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDU_PH:
+            check_dspr2(ctx);
+            gen_helper_addu_ph(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDU_S_PH:
+            check_dspr2(ctx);
+            gen_helper_addu_s_ph(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBQ_PH:
+            check_dsp(ctx);
+            gen_helper_subq_ph(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBQ_S_PH:
+            check_dsp(ctx);
+            gen_helper_subq_s_ph(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBQ_S_W:
+            check_dsp(ctx);
+            gen_helper_subq_s_w(cpu_gpr[ret], cpu_gpr[v1],
+                                cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBU_QB:
+            check_dsp(ctx);
+            gen_helper_subu_qb(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBU_S_QB:
+            check_dsp(ctx);
+            gen_helper_subu_s_qb(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBU_PH:
+            check_dspr2(ctx);
+            gen_helper_subu_ph(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBU_S_PH:
+            check_dspr2(ctx);
+            gen_helper_subu_s_ph(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDSC:
+            check_dsp(ctx);
+            gen_helper_addsc(cpu_gpr[ret], cpu_gpr[v1],
+                             cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDWC:
+            check_dsp(ctx);
+            gen_helper_addwc(cpu_gpr[ret], cpu_gpr[v1],
+                             cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_MODSUB:
+            check_dsp(ctx);
+            gen_helper_modsub(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_RADDU_W_QB:
+            check_dsp(ctx);
+            gen_helper_raddu_w_qb(cpu_gpr[ret], cpu_gpr[v1]);
+            break;
+        }
+        break;
+    case OPC_CMPU_EQ_QB_DSP:
+        switch (op2) {
+        case OPC_PRECR_QB_PH:
+            check_dspr2(ctx);
+            gen_helper_precr_qb_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_PRECRQ_QB_PH:
+            check_dsp(ctx);
+            gen_helper_precrq_qb_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_PRECR_SRA_PH_W:
+            check_dspr2(ctx);
+            {
+                TCGv_i32 sa_t = tcg_const_i32(v2);
+                gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t,
+                                       cpu_gpr[v1], cpu_gpr[ret]);
+                tcg_temp_free_i32(sa_t);
+                break;
+            }
+        case OPC_PRECR_SRA_R_PH_W:
+            check_dspr2(ctx);
+            {
+                TCGv_i32 sa_t = tcg_const_i32(v2);
+                gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t,
+                                        cpu_gpr[v1], cpu_gpr[ret]);
+                tcg_temp_free_i32(sa_t);
+                break;
+            }
+        case OPC_PRECRQ_PH_W:
+            check_dsp(ctx);
+            gen_helper_precrq_ph_w(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_PRECRQ_RS_PH_W:
+            check_dsp(ctx);
+            gen_helper_precrq_rs_ph_w(cpu_gpr[ret], cpu_gpr[v1],
+                                      cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_PRECRQU_S_QB_PH:
+            check_dsp(ctx);
+            gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], cpu_gpr[v1],
+                                       cpu_gpr[v2], cpu_env);
+            break;
+        }
+        break;
+#ifdef TARGET_MIPS64
+    case OPC_ABSQ_S_QH_DSP:
+        switch (op2) {
+        case OPC_PRECEQ_L_PWL:
+            check_dsp(ctx);
+            tcg_gen_andi_tl(cpu_gpr[ret], cpu_gpr[v2], 0xFFFFFFFF00000000ull);
+            break;
+        case OPC_PRECEQ_L_PWR:
+            check_dsp(ctx);
+            tcg_gen_andi_tl(cpu_gpr[ret], cpu_gpr[v2], 0xFFFFFFFFull);
+            break;
+        case OPC_PRECEQ_PW_QHL:
+            check_dsp(ctx);
+            gen_helper_preceq_pw_qhl(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEQ_PW_QHR:
+            check_dsp(ctx);
+            gen_helper_preceq_pw_qhr(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEQ_PW_QHLA:
+            check_dsp(ctx);
+            gen_helper_preceq_pw_qhla(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEQ_PW_QHRA:
+            check_dsp(ctx);
+            gen_helper_preceq_pw_qhra(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEQU_QH_OBL:
+            check_dsp(ctx);
+            gen_helper_precequ_qh_obl(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEQU_QH_OBR:
+            check_dsp(ctx);
+            gen_helper_precequ_qh_obr(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEQU_QH_OBLA:
+            check_dsp(ctx);
+            gen_helper_precequ_qh_obla(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEQU_QH_OBRA:
+            check_dsp(ctx);
+            gen_helper_precequ_qh_obra(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEU_QH_OBL:
+            check_dsp(ctx);
+            gen_helper_preceu_qh_obl(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEU_QH_OBR:
+            check_dsp(ctx);
+            gen_helper_preceu_qh_obr(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEU_QH_OBLA:
+            check_dsp(ctx);
+            gen_helper_preceu_qh_obla(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_PRECEU_QH_OBRA:
+            check_dsp(ctx);
+            gen_helper_preceu_qh_obra(cpu_gpr[ret], cpu_gpr[v2]);
+            break;
+        case OPC_ABSQ_S_OB:
+            check_dspr2(ctx);
+            gen_helper_absq_s_ob(cpu_gpr[ret], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ABSQ_S_PW:
+            check_dsp(ctx);
+            gen_helper_absq_s_pw(cpu_gpr[ret], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ABSQ_S_QH:
+            check_dsp(ctx);
+            gen_helper_absq_s_qh(cpu_gpr[ret], cpu_gpr[v2], cpu_env);
+            break;
+        }
+        break;
+    case OPC_ADDU_OB_DSP:
+        switch (op2) {
+        case OPC_RADDU_L_OB:
+            check_dsp(ctx);
+            gen_helper_raddu_l_ob(cpu_gpr[ret], cpu_gpr[v1]);
+            break;
+        case OPC_SUBQ_PW:
+            check_dsp(ctx);
+            gen_helper_subq_pw(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBQ_S_PW:
+            check_dsp(ctx);
+            gen_helper_subq_s_pw(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBQ_QH:
+            check_dsp(ctx);
+            gen_helper_subq_qh(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBQ_S_QH:
+            check_dsp(ctx);
+            gen_helper_subq_s_qh(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBU_OB:
+            check_dsp(ctx);
+            gen_helper_subu_ob(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBU_S_OB:
+            check_dsp(ctx);
+            gen_helper_subu_s_ob(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBU_QH:
+            check_dspr2(ctx);
+            gen_helper_subu_qh(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBU_S_QH:
+            check_dspr2(ctx);
+            gen_helper_subu_s_qh(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_SUBUH_OB:
+            check_dspr2(ctx);
+            gen_helper_subuh_ob(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_SUBUH_R_OB:
+            check_dspr2(ctx);
+            gen_helper_subuh_r_ob(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_ADDQ_PW:
+            check_dsp(ctx);
+            gen_helper_addq_pw(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDQ_S_PW:
+            check_dsp(ctx);
+            gen_helper_addq_s_pw(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDQ_QH:
+            check_dsp(ctx);
+            gen_helper_addq_qh(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDQ_S_QH:
+            check_dsp(ctx);
+            gen_helper_addq_s_qh(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDU_OB:
+            check_dsp(ctx);
+            gen_helper_addu_ob(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDU_S_OB:
+            check_dsp(ctx);
+            gen_helper_addu_s_ob(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDU_QH:
+            check_dspr2(ctx);
+            gen_helper_addu_qh(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDU_S_QH:
+            check_dspr2(ctx);
+            gen_helper_addu_s_qh(cpu_gpr[ret], cpu_gpr[v1],
+                                 cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_ADDUH_OB:
+            check_dspr2(ctx);
+            gen_helper_adduh_ob(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_ADDUH_R_OB:
+            check_dspr2(ctx);
+            gen_helper_adduh_r_ob(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        }
+        break;
+    case OPC_CMPU_EQ_OB_DSP:
+        switch (op2) {
+        case OPC_PRECR_OB_QH:
+            check_dspr2(ctx);
+            gen_helper_precr_ob_qh(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_PRECR_SRA_QH_PW:
+            check_dspr2(ctx);
+            {
+                TCGv_i32 ret_t = tcg_const_i32(ret);
+                gen_helper_precr_sra_qh_pw(cpu_gpr[v2], cpu_gpr[v1],
+                                           cpu_gpr[v2], ret_t);
+                tcg_temp_free_i32(ret_t);
+                break;
+            }
+        case OPC_PRECR_SRA_R_QH_PW:
+            check_dspr2(ctx);
+            {
+                TCGv_i32 sa_v = tcg_const_i32(ret);
+                gen_helper_precr_sra_r_qh_pw(cpu_gpr[v2], cpu_gpr[v1],
+                                             cpu_gpr[v2], sa_v);
+                tcg_temp_free_i32(sa_v);
+                break;
+            }
+        case OPC_PRECRQ_OB_QH:
+            check_dsp(ctx);
+            gen_helper_precrq_ob_qh(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_PRECRQ_PW_L:
+            check_dsp(ctx);
+            gen_helper_precrq_pw_l(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_PRECRQ_QH_PW:
+            check_dsp(ctx);
+            gen_helper_precrq_qh_pw(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_PRECRQ_RS_QH_PW:
+            check_dsp(ctx);
+            gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], cpu_gpr[v1],
+                                       cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_PRECRQU_S_OB_QH:
+            check_dsp(ctx);
+            gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], cpu_gpr[v1],
+                                       cpu_gpr[v2], cpu_env);
+            break;
+        }
+        break;
+#endif
+    }
+
+    (void)opn; /* avoid a compiler warning */
+    MIPS_DEBUG("%s", opn);
+}
 
 /* End MIPSDSP functions. */
 
@@ -12629,10 +13270,37 @@ 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:
         case OPC_MOD_G_2E ... OPC_MODU_G_2E:
-            check_insn(env, ctx, INSN_LOONGSON2E);
-            gen_loongson_integer(ctx, op1, rd, rs, rt);
+        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 ((env->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
+                op2 = MASK_ADDUH_QB(ctx->opcode);
+                switch (op2) {
+                case OPC_ADDUH_QB:
+                case OPC_ADDUH_R_QB:
+                case OPC_ADDQH_PH:
+                case OPC_ADDQH_R_PH:
+                case OPC_ADDQH_W:
+                case OPC_ADDQH_R_W:
+                case OPC_SUBUH_QB:
+                case OPC_SUBUH_R_QB:
+                case OPC_SUBQH_PH:
+                case OPC_SUBQH_R_PH:
+                case OPC_SUBQH_W:
+                case OPC_SUBQH_R_W:
+                    gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
+                    break;
+                default:
+                    MIPS_INVAL("MASK ADDUH.QB");
+                    generate_exception(ctx, EXCP_RI);
+                    break;
+                }
+            } else if (env->insn_flags & INSN_LOONGSON2E) {
+                gen_loongson_integer(ctx, op1, rd, rs, rt);
+            } else {
+                generate_exception(ctx, EXCP_RI);
+            }
             break;
         case OPC_LX_DSP:
             check_dsp(ctx);
@@ -12652,6 +13320,80 @@ 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:
+            case OPC_ABSQ_S_PH:
+            case OPC_ABSQ_S_W:
+            case OPC_PRECEQ_W_PHL:
+            case OPC_PRECEQ_W_PHR:
+            case OPC_PRECEQU_PH_QBL:
+            case OPC_PRECEQU_PH_QBR:
+            case OPC_PRECEQU_PH_QBLA:
+            case OPC_PRECEQU_PH_QBRA:
+            case OPC_PRECEU_PH_QBL:
+            case OPC_PRECEU_PH_QBR:
+            case OPC_PRECEU_PH_QBLA:
+            case OPC_PRECEU_PH_QBRA:
+                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
+                break;
+            default:
+                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:
+            case OPC_ADDQ_S_PH:
+            case OPC_ADDQ_S_W:
+            case OPC_ADDU_QB:
+            case OPC_ADDU_S_QB:
+            case OPC_ADDU_PH:
+            case OPC_ADDU_S_PH:
+            case OPC_SUBQ_PH:
+            case OPC_SUBQ_S_PH:
+            case OPC_SUBQ_S_W:
+            case OPC_SUBU_QB:
+            case OPC_SUBU_S_QB:
+            case OPC_SUBU_PH:
+            case OPC_SUBU_S_PH:
+            case OPC_ADDSC:
+            case OPC_ADDWC:
+            case OPC_MODSUB:
+            case OPC_RADDU_W_QB:
+                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
+                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_SRA_PH_W:
+            case OPC_PRECR_SRA_R_PH_W:
+                gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
+                break;
+            case OPC_PRECR_QB_PH:
+            case OPC_PRECRQ_QB_PH:
+            case OPC_PRECRQ_PH_W:
+            case OPC_PRECRQ_RS_PH_W:
+            case OPC_PRECRQU_S_QB_PH:
+                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, 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:
@@ -12671,6 +13413,88 @@ 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_ABSQ_S_QH_DSP:
+            op2 = MASK_ABSQ_S_QH(ctx->opcode);
+            switch (op2) {
+            case OPC_PRECEQ_L_PWL:
+            case OPC_PRECEQ_L_PWR:
+            case OPC_PRECEQ_PW_QHL:
+            case OPC_PRECEQ_PW_QHR:
+            case OPC_PRECEQ_PW_QHLA:
+            case OPC_PRECEQ_PW_QHRA:
+            case OPC_PRECEQU_QH_OBL:
+            case OPC_PRECEQU_QH_OBR:
+            case OPC_PRECEQU_QH_OBLA:
+            case OPC_PRECEQU_QH_OBRA:
+            case OPC_PRECEU_QH_OBL:
+            case OPC_PRECEU_QH_OBR:
+            case OPC_PRECEU_QH_OBLA:
+            case OPC_PRECEU_QH_OBRA:
+            case OPC_ABSQ_S_OB:
+            case OPC_ABSQ_S_PW:
+            case OPC_ABSQ_S_QH:
+                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK ABSQ_S.QH");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+        case OPC_ADDU_OB_DSP:
+            op2 = MASK_ADDU_OB(ctx->opcode);
+            switch (op2) {
+            case OPC_RADDU_L_OB:
+            case OPC_SUBQ_PW:
+            case OPC_SUBQ_S_PW:
+            case OPC_SUBQ_QH:
+            case OPC_SUBQ_S_QH:
+            case OPC_SUBU_OB:
+            case OPC_SUBU_S_OB:
+            case OPC_SUBU_QH:
+            case OPC_SUBU_S_QH:
+            case OPC_SUBUH_OB:
+            case OPC_SUBUH_R_OB:
+            case OPC_ADDQ_PW:
+            case OPC_ADDQ_S_PW:
+            case OPC_ADDQ_QH:
+            case OPC_ADDQ_S_QH:
+            case OPC_ADDU_OB:
+            case OPC_ADDU_S_OB:
+            case OPC_ADDU_QH:
+            case OPC_ADDU_S_QH:
+            case OPC_ADDUH_OB:
+            case OPC_ADDUH_R_OB:
+                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK ADDU.OB");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+        case OPC_CMPU_EQ_OB_DSP:
+            op2 = MASK_CMPU_EQ_OB(ctx->opcode);
+            switch (op2) {
+            case OPC_PRECR_SRA_QH_PW:
+            case OPC_PRECR_SRA_R_QH_PW:
+                /* Return value is rt. */
+                gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
+                break;
+            case OPC_PRECR_OB_QH:
+            case OPC_PRECRQ_OB_QH:
+            case OPC_PRECRQ_PW_L:
+            case OPC_PRECRQ_QH_PW:
+            case OPC_PRECRQ_RS_QH_PW:
+            case OPC_PRECRQU_S_OB_QH:
+                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK CMPU_EQ.OB");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
 #endif
         default:            /* Invalid */
             MIPS_INVAL("special3");
-- 
1.7.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 07/14] target-mips-ase-dsp: Add GPR-based shift instructions
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
                   ` (5 preceding siblings ...)
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 06/14] target-mips-ase-dsp: Add arithmetic instructions Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:51   ` Aurelien Jarno
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 08/14] target-mips-ase-dsp: Add multiply instructions Jia Liu
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 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 |  256 +++++++++++++++++++++++++++++++++++
 target-mips/helper.h     |   38 ++++++
 target-mips/translate.c  |  332 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 626 insertions(+)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 555a5ed..476f4e5 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -1992,6 +1992,262 @@ PRECEU_QH(obra, 48, 32, 16, 0);
 
 #endif
 
+/** DSP GPR-Based Shift Sub-class insns **/
+#define SHIFT_QB(name, func) \
+target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt) \
+{                                                                    \
+    uint8_t rt3, rt2, rt1, rt0;                                      \
+                                                                     \
+    sa = sa & 0x07;                                                  \
+                                                                     \
+    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                       \
+                                                                     \
+    rt3 = mipsdsp_##func(rt3, sa);                                   \
+    rt2 = mipsdsp_##func(rt2, sa);                                   \
+    rt1 = mipsdsp_##func(rt1, sa);                                   \
+    rt0 = mipsdsp_##func(rt0, sa);                                   \
+                                                                     \
+    return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0);                   \
+}
+
+#define SHIFT_QB_ENV(name, func) \
+target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt,\
+                                CPUMIPSState *env) \
+{                                                                    \
+    uint8_t rt3, rt2, rt1, rt0;                                      \
+                                                                     \
+    sa = sa & 0x07;                                                  \
+                                                                     \
+    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                       \
+                                                                     \
+    rt3 = mipsdsp_##func(rt3, sa, env);                              \
+    rt2 = mipsdsp_##func(rt2, sa, env);                              \
+    rt1 = mipsdsp_##func(rt1, sa, env);                              \
+    rt0 = mipsdsp_##func(rt0, sa, env);                              \
+                                                                     \
+    return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0);                   \
+}
+
+SHIFT_QB_ENV(shll, lshift8);
+SHIFT_QB(shrl, rshift_u8);
+
+SHIFT_QB(shra, rashift8);
+SHIFT_QB(shra_r, rnd8_rashift);
+
+#undef SHIFT_QB
+#undef SHIFT_QB_ENV
+
+#if defined(TARGET_MIPS64)
+#define SHIFT_OB(name, func) \
+target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \
+{                                                                        \
+    int i;                                                               \
+    uint8_t rt_t[8];                                                     \
+    uint64_t temp;                                                       \
+                                                                         \
+    sa = sa & 0x07;                                                      \
+    temp = 0;                                                            \
+                                                                         \
+    for (i = 0; i < 8; i++) {                                            \
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                          \
+        rt_t[i] = mipsdsp_##func(rt_t[i], sa);                           \
+        temp |= (uint64_t)rt_t[i] << (8 * i);                            \
+    }                                                                    \
+                                                                         \
+    return temp;                                                         \
+}
+
+#define SHIFT_OB_ENV(name, func) \
+target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \
+                                CPUMIPSState *env)                       \
+{                                                                        \
+    int i;                                                               \
+    uint8_t rt_t[8];                                                     \
+    uint64_t temp;                                                       \
+                                                                         \
+    sa = sa & 0x07;                                                      \
+    temp = 0;                                                            \
+                                                                         \
+    for (i = 0; i < 8; i++) {                                            \
+        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                          \
+        rt_t[i] = mipsdsp_##func(rt_t[i], sa, env);                      \
+        temp |= (uint64_t)rt_t[i] << (8 * i);                            \
+    }                                                                    \
+                                                                         \
+    return temp;                                                         \
+}
+
+SHIFT_OB_ENV(shll, lshift8);
+SHIFT_OB(shrl, rshift_u8);
+
+SHIFT_OB(shra, rashift8);
+SHIFT_OB(shra_r, rnd8_rashift);
+
+#undef SHIFT_OB
+#undef SHIFT_OB_ENV
+
+#endif
+
+#define SHIFT_PH(name, func) \
+target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt, \
+                                CPUMIPSState *env)                \
+{                                                                 \
+    uint16_t rth, rtl;                                            \
+                                                                  \
+    sa = sa & 0x0F;                                               \
+                                                                  \
+    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
+                                                                  \
+    rth = mipsdsp_##func(rth, sa, env);                           \
+    rtl = mipsdsp_##func(rtl, sa, env);                           \
+                                                                  \
+    return MIPSDSP_RETURN32_16(rth, rtl);                         \
+}
+
+SHIFT_PH(shll, lshift16);
+SHIFT_PH(shll_s, sat16_lshift);
+
+#undef SHIFT_PH
+
+#if defined(TARGET_MIPS64)
+#define SHIFT_QH(name, func) \
+target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa) \
+{                                                                 \
+    uint16_t rt3, rt2, rt1, rt0;                                  \
+                                                                  \
+    sa = sa & 0x0F;                                               \
+                                                                  \
+    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                   \
+                                                                  \
+    rt3 = mipsdsp_##func(rt3, sa);                                \
+    rt2 = mipsdsp_##func(rt2, sa);                                \
+    rt1 = mipsdsp_##func(rt1, sa);                                \
+    rt0 = mipsdsp_##func(rt0, sa);                                \
+                                                                  \
+    return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0);               \
+}
+
+#define SHIFT_QH_ENV(name, func) \
+target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa, \
+                                CPUMIPSState *env)                \
+{                                                                 \
+    uint16_t rt3, rt2, rt1, rt0;                                  \
+                                                                  \
+    sa = sa & 0x0F;                                               \
+                                                                  \
+    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                   \
+                                                                  \
+    rt3 = mipsdsp_##func(rt3, sa, env);                           \
+    rt2 = mipsdsp_##func(rt2, sa, env);                           \
+    rt1 = mipsdsp_##func(rt1, sa, env);                           \
+    rt0 = mipsdsp_##func(rt0, sa, env);                           \
+                                                                  \
+    return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0);               \
+}
+
+SHIFT_QH_ENV(shll, lshift16);
+SHIFT_QH_ENV(shll_s, sat16_lshift);
+
+SHIFT_QH(shrl, rshift_u16);
+SHIFT_QH(shra, rashift16);
+SHIFT_QH(shra_r, rnd16_rashift);
+
+#undef SHIFT_QH
+#undef SHIFT_QH_ENV
+
+#endif
+
+#define SHIFT_W(name, func) \
+target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \
+{                                                                       \
+    uint32_t temp;                                                      \
+                                                                        \
+    sa = sa & 0x1F;                                                     \
+    temp = mipsdsp_##func(rt, sa);                                      \
+                                                                        \
+    return (target_long)(int32_t)temp;                                  \
+}
+
+#define SHIFT_W_ENV(name, func) \
+target_ulong helper_##name##_w(target_ulong sa, target_ulong rt, \
+                               CPUMIPSState *env) \
+{                                                                       \
+    uint32_t temp;                                                      \
+                                                                        \
+    sa = sa & 0x1F;                                                     \
+    temp = mipsdsp_##func(rt, sa, env);                                 \
+                                                                        \
+    return (target_long)(int32_t)temp;                                  \
+}
+
+SHIFT_W_ENV(shll_s, sat32_lshift);
+SHIFT_W(shra_r, rnd32_rashift);
+
+#undef SHIFT_W
+#undef SHIFT_W_ENV
+
+#if defined(TARGET_MIPS64)
+#define SHIFT_PW(name, func) \
+target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa) \
+{                                                                 \
+    uint32_t rt1, rt0;                                            \
+                                                                  \
+    sa = sa & 0x1F;                                               \
+    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
+                                                                  \
+    rt1 = mipsdsp_##func(rt1, sa);                                \
+    rt0 = mipsdsp_##func(rt0, sa);                                \
+                                                                  \
+    return MIPSDSP_RETURN64_32(rt1, rt0);                         \
+}
+
+#define SHIFT_PW_ENV(name, func) \
+target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa, \
+                                CPUMIPSState *env)                \
+{                                                                 \
+    uint32_t rt1, rt0;                                            \
+                                                                  \
+    sa = sa & 0x1F;                                               \
+    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
+                                                                  \
+    rt1 = mipsdsp_##func(rt1, sa, env);                           \
+    rt0 = mipsdsp_##func(rt0, sa, env);                           \
+                                                                  \
+    return MIPSDSP_RETURN64_32(rt1, rt0);                         \
+}
+
+SHIFT_PW_ENV(shll, lshift32);
+SHIFT_PW_ENV(shll_s, sat32_lshift);
+
+SHIFT_PW(shra, rashift32);
+SHIFT_PW(shra_r, rnd32_rashift);
+
+#undef SHIFT_PW
+#undef SHIFT_PW_ENV
+
+#endif
+
+#define SHIFT_PH(name, func) \
+target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \
+{                                                                    \
+    uint16_t rth, rtl;                                               \
+                                                                     \
+    sa = sa & 0x0F;                                                  \
+                                                                     \
+    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                \
+                                                                     \
+    rth = mipsdsp_##func(rth, sa);                                   \
+    rtl = mipsdsp_##func(rtl, sa);                                   \
+                                                                     \
+    return MIPSDSP_RETURN32_16(rth, rtl);                            \
+}
+
+SHIFT_PH(shrl, rshift_u16);
+SHIFT_PH(shra, rashift16);
+SHIFT_PH(shra_r, rnd16_rashift);
+
+#undef SHIFT_PH
+
 #undef MIPSDSP_LHI
 #undef MIPSDSP_LLO
 #undef MIPSDSP_HI
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 9201aae..5258ef6 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -488,4 +488,42 @@ 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, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(shll_ob, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(shll_ph, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(shll_s_ph, 0, tl, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(shll_qh, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(shll_s_qh, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(shll_s_w, 0, tl, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(shll_pw, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(shll_s_pw, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_2(shrl_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(shrl_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, tl)
+DEF_HELPER_FLAGS_2(shrl_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+#endif
+DEF_HELPER_FLAGS_2(shra_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(shra_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, tl)
+DEF_HELPER_FLAGS_2(shra_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, tl, tl)
+DEF_HELPER_FLAGS_2(shra_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, tl, tl)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_2(shra_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, tl)
+DEF_HELPER_FLAGS_2(shra_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, tl)
+#endif
+
 #include "def-helper.h"
diff --git a/target-mips/translate.c b/target-mips/translate.c
index d057b30..72e2703 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))
 
@@ -12918,6 +12989,261 @@ static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
     MIPS_DEBUG("%s", opn);
 }
 
+static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
+                              int ret, int v1, int v2)
+{
+    uint32_t op2;
+    const char *opn = "mipsdsp shift";
+    TCGv t0 = tcg_const_tl(v1);
+
+    if (ret == 0) {
+        /* Treat as NOP. */
+        MIPS_DEBUG("NOP");
+        return;
+    }
+
+    switch (opc) {
+    case OPC_SHLL_QB_DSP:
+        {
+            op2 = MASK_SHLL_QB(ctx->opcode);
+            switch (op2) {
+            case OPC_SHLL_QB:
+                check_dsp(ctx);
+                gen_helper_shll_qb(cpu_gpr[ret], t0,
+                                   cpu_gpr[v2], cpu_env);
+                break;
+            case OPC_SHLLV_QB:
+                check_dsp(ctx);
+                gen_helper_shll_qb(cpu_gpr[ret], cpu_gpr[v1],
+                                    cpu_gpr[v2], cpu_env);
+                break;
+            case OPC_SHLL_PH:
+                check_dsp(ctx);
+                gen_helper_shll_ph(cpu_gpr[ret], t0,
+                                   cpu_gpr[v2], cpu_env);
+                break;
+            case OPC_SHLLV_PH:
+                check_dsp(ctx);
+                gen_helper_shll_ph(cpu_gpr[ret], cpu_gpr[v1],
+                                    cpu_gpr[v2], cpu_env);
+                break;
+            case OPC_SHLL_S_PH:
+                check_dsp(ctx);
+                gen_helper_shll_s_ph(cpu_gpr[ret], t0,
+                                     cpu_gpr[v2], cpu_env);
+                break;
+            case OPC_SHLLV_S_PH:
+                check_dsp(ctx);
+                gen_helper_shll_s_ph(cpu_gpr[ret], cpu_gpr[v1],
+                                      cpu_gpr[v2], cpu_env);
+                break;
+            case OPC_SHLL_S_W:
+                check_dsp(ctx);
+                gen_helper_shll_s_w(cpu_gpr[ret], t0,
+                                    cpu_gpr[v2], cpu_env);
+                break;
+            case OPC_SHLLV_S_W:
+                check_dsp(ctx);
+                gen_helper_shll_s_w(cpu_gpr[ret], cpu_gpr[v1],
+                                     cpu_gpr[v2], cpu_env);
+                break;
+            case OPC_SHRL_QB:
+                check_dsp(ctx);
+                gen_helper_shrl_qb(cpu_gpr[ret], t0, cpu_gpr[v2]);
+                break;
+            case OPC_SHRLV_QB:
+                check_dsp(ctx);
+                gen_helper_shrl_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+                break;
+            case OPC_SHRL_PH:
+                check_dspr2(ctx);
+                gen_helper_shrl_ph(cpu_gpr[ret], t0, cpu_gpr[v2]);
+                break;
+            case OPC_SHRLV_PH:
+                check_dspr2(ctx);
+                gen_helper_shrl_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+                break;
+            case OPC_SHRA_QB:
+                check_dspr2(ctx);
+                gen_helper_shra_qb(cpu_gpr[ret], t0, cpu_gpr[v2]);
+                break;
+            case OPC_SHRA_R_QB:
+                check_dspr2(ctx);
+                gen_helper_shra_r_qb(cpu_gpr[ret], t0, cpu_gpr[v2]);
+                break;
+            case OPC_SHRAV_QB:
+                check_dspr2(ctx);
+                gen_helper_shra_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+                break;
+            case OPC_SHRAV_R_QB:
+                check_dspr2(ctx);
+                gen_helper_shra_r_qb(cpu_gpr[ret], cpu_gpr[v1],
+                                      cpu_gpr[v2]);
+                break;
+            case OPC_SHRA_PH:
+                check_dsp(ctx);
+                gen_helper_shra_ph(cpu_gpr[ret], t0, cpu_gpr[v2]);
+                break;
+            case OPC_SHRA_R_PH:
+                check_dsp(ctx);
+                gen_helper_shra_r_ph(cpu_gpr[ret], t0, cpu_gpr[v2]);
+                break;
+            case OPC_SHRAV_PH:
+                check_dsp(ctx);
+                gen_helper_shra_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+                break;
+            case OPC_SHRAV_R_PH:
+                check_dsp(ctx);
+                gen_helper_shra_r_ph(cpu_gpr[ret], cpu_gpr[v1],
+                                      cpu_gpr[v2]);
+                break;
+            case OPC_SHRA_R_W:
+                check_dsp(ctx);
+                gen_helper_shra_r_w(cpu_gpr[ret], t0, cpu_gpr[v2]);
+                break;
+            case OPC_SHRAV_R_W:
+                check_dsp(ctx);
+                gen_helper_shra_r_w(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK SHLL.QB");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
+        }
+#ifdef TARGET_MIPS64
+    case OPC_SHLL_OB_DSP:
+        op2 = MASK_SHLL_OB(ctx->opcode);
+        switch (op2) {
+        case OPC_SHLL_PW:
+            check_dsp(ctx);
+            gen_helper_shll_pw(cpu_gpr[ret], cpu_gpr[v2],
+                               t0, cpu_env);
+            break;
+        case OPC_SHLLV_PW:
+            check_dsp(ctx);
+            gen_helper_shll_pw(cpu_gpr[ret], cpu_gpr[v2],
+                                cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_SHLL_S_PW:
+            check_dsp(ctx);
+            gen_helper_shll_s_pw(cpu_gpr[ret], cpu_gpr[v2],
+                                 t0, cpu_env);
+            break;
+        case OPC_SHLLV_S_PW:
+            check_dsp(ctx);
+            gen_helper_shll_s_pw(cpu_gpr[ret], cpu_gpr[v2],
+                                  cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_SHLL_OB:
+            check_dsp(ctx);
+            gen_helper_shll_ob(cpu_gpr[ret], cpu_gpr[v2],
+                               t0, cpu_env);
+            break;
+        case OPC_SHLLV_OB:
+            check_dsp(ctx);
+            gen_helper_shll_ob(cpu_gpr[ret], cpu_gpr[v2],
+                                cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_SHLL_QH:
+            check_dsp(ctx);
+            gen_helper_shll_qh(cpu_gpr[ret], cpu_gpr[v2],
+                               t0, cpu_env);
+            break;
+        case OPC_SHLLV_QH:
+            check_dsp(ctx);
+            gen_helper_shll_qh(cpu_gpr[ret], cpu_gpr[v2],
+                                cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_SHLL_S_QH:
+            check_dsp(ctx);
+            gen_helper_shll_s_qh(cpu_gpr[ret], cpu_gpr[v2],
+                                 t0, cpu_env);
+            break;
+        case OPC_SHLLV_S_QH:
+            check_dsp(ctx);
+            gen_helper_shll_s_qh(cpu_gpr[ret], cpu_gpr[v2],
+                                  cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_SHRA_OB:
+            check_dspr2(ctx);
+            gen_helper_shra_ob(cpu_gpr[ret], cpu_gpr[v2], t0);
+            break;
+        case OPC_SHRAV_OB:
+            check_dspr2(ctx);
+            gen_helper_shra_ob(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
+            break;
+        case OPC_SHRA_R_OB:
+            check_dspr2(ctx);
+            gen_helper_shra_r_ob(cpu_gpr[ret], cpu_gpr[v2], t0);
+            break;
+        case OPC_SHRAV_R_OB:
+            check_dspr2(ctx);
+            gen_helper_shra_r_ob(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
+            break;
+        case OPC_SHRA_PW:
+            check_dsp(ctx);
+            gen_helper_shra_pw(cpu_gpr[ret], cpu_gpr[v2], t0);
+            break;
+        case OPC_SHRAV_PW:
+            check_dsp(ctx);
+            gen_helper_shra_pw(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
+            break;
+        case OPC_SHRA_R_PW:
+            check_dsp(ctx);
+            gen_helper_shra_r_pw(cpu_gpr[ret], cpu_gpr[v2], t0);
+            break;
+        case OPC_SHRAV_R_PW:
+            check_dsp(ctx);
+            gen_helper_shra_r_pw(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
+            break;
+        case OPC_SHRA_QH:
+            check_dsp(ctx);
+            gen_helper_shra_qh(cpu_gpr[ret], cpu_gpr[v2], t0);
+            break;
+        case OPC_SHRAV_QH:
+            check_dsp(ctx);
+            gen_helper_shra_qh(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
+            break;
+        case OPC_SHRA_R_QH:
+            check_dsp(ctx);
+            gen_helper_shra_r_qh(cpu_gpr[ret], cpu_gpr[v2], t0);
+            break;
+        case OPC_SHRAV_R_QH:
+            check_dsp(ctx);
+            gen_helper_shra_r_qh(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
+            break;
+        case OPC_SHRL_OB:
+            check_dsp(ctx);
+            gen_helper_shrl_ob(cpu_gpr[ret], cpu_gpr[v2], t0);
+            break;
+        case OPC_SHRLV_OB:
+            check_dsp(ctx);
+            gen_helper_shrl_ob(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
+            break;
+        case OPC_SHRL_QH:
+            check_dspr2(ctx);
+            gen_helper_shrl_qh(cpu_gpr[ret], cpu_gpr[v2], t0);
+            break;
+        case OPC_SHRLV_QH:
+            check_dspr2(ctx);
+            gen_helper_shrl_qh(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
+            break;
+        default:            /* Invalid */
+            MIPS_INVAL("MASK SHLL.OB");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
+        break;
+#endif
+    }
+
+    tcg_temp_free(t0);
+    (void)opn; /* avoid a compiler warning */
+    MIPS_DEBUG("%s", opn);
+}
+
 /* End MIPSDSP functions. */
 
 static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
@@ -13394,6 +13720,9 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 break;
             }
             break;
+        case OPC_SHLL_QB_DSP:
+            gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
@@ -13495,6 +13824,9 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 break;
             }
             break;
+        case OPC_SHLL_OB_DSP:
+            gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
+            break;
 #endif
         default:            /* Invalid */
             MIPS_INVAL("special3");
-- 
1.7.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 08/14] target-mips-ase-dsp: Add multiply instructions
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
                   ` (6 preceding siblings ...)
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 07/14] target-mips-ase-dsp: Add GPR-based shift instructions Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:51   ` Aurelien Jarno
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 09/14] target-mips-ase-dsp: Add bit/manipulation instructions Jia Liu
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 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 |  938 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/helper.h     |   91 +++++
 target-mips/translate.c  |  531 ++++++++++++++++++++++++++
 3 files changed, 1560 insertions(+)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 476f4e5..b98be0d 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -2248,6 +2248,944 @@ SHIFT_PH(shra_r, rnd16_rashift);
 
 #undef SHIFT_PH
 
+/** DSP Multiply Sub-class insns **/
+/* Return value made up by two 16bits value.
+ * FIXME give the macro a better name.
+ */
+#define MUL_RETURN32_16_PH(name, func, \
+                           rsmov1, rsmov2, rsfilter, \
+                           rtmov1, rtmov2, rtfilter) \
+target_ulong helper_##name(target_ulong rs, target_ulong rt, \
+                           CPUMIPSState *env)                \
+{                                                            \
+    uint16_t rsB, rsA, rtB, rtA;                             \
+                                                             \
+    rsB = (rs >> rsmov1) & rsfilter;                         \
+    rsA = (rs >> rsmov2) & rsfilter;                         \
+    rtB = (rt >> rtmov1) & rtfilter;                         \
+    rtA = (rt >> rtmov2) & rtfilter;                         \
+                                                             \
+    rsB = mipsdsp_##func(rsB, rtB, env);                     \
+    rsA = mipsdsp_##func(rsA, rtA, env);                     \
+                                                             \
+    return MIPSDSP_RETURN32_16(rsB, rsA);                    \
+}
+
+MUL_RETURN32_16_PH(muleu_s_ph_qbl, mul_u8_u16, \
+                      24, 16, MIPSDSP_Q0, \
+                      16, 0, MIPSDSP_LO);
+MUL_RETURN32_16_PH(muleu_s_ph_qbr, mul_u8_u16, \
+                      8, 0, MIPSDSP_Q0, \
+                      16, 0, MIPSDSP_LO);
+MUL_RETURN32_16_PH(mulq_rs_ph, rndq15_mul_q15_q15, \
+                      16, 0, MIPSDSP_LO, \
+                      16, 0, MIPSDSP_LO);
+MUL_RETURN32_16_PH(mul_ph, mul_i16_i16, \
+                      16, 0, MIPSDSP_LO, \
+                      16, 0, MIPSDSP_LO);
+MUL_RETURN32_16_PH(mul_s_ph, sat16_mul_i16_i16, \
+                      16, 0, MIPSDSP_LO, \
+                      16, 0, MIPSDSP_LO);
+MUL_RETURN32_16_PH(mulq_s_ph, sat16_mul_q15_q15, \
+                      16, 0, MIPSDSP_LO, \
+                      16, 0, MIPSDSP_LO);
+
+#undef MUL_RETURN32_16_PH
+
+#define MUL_RETURN32_32_ph(name, func, movbits) \
+target_ulong helper_##name(target_ulong rs, target_ulong rt, \
+                                  CPUMIPSState *env)         \
+{                                                            \
+    int16_t rsh, rth;                                        \
+    int32_t temp;                                            \
+                                                             \
+    rsh = (rs >> movbits) & MIPSDSP_LO;                      \
+    rth = (rt >> movbits) & MIPSDSP_LO;                      \
+    temp = mipsdsp_##func(rsh, rth, env);                    \
+                                                             \
+    return (target_long)(int32_t)temp;                       \
+}
+
+MUL_RETURN32_32_ph(muleq_s_w_phl, mul_q15_q15_overflowflag21, 16);
+MUL_RETURN32_32_ph(muleq_s_w_phr, mul_q15_q15_overflowflag21, 0);
+
+#undef MUL_RETURN32_32_ph
+
+#define MUL_VOID_PH(name, use_ac_env) \
+void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
+                          CPUMIPSState *env)                             \
+{                                                                        \
+    int16_t rsh, rsl, rth, rtl;                                          \
+    int32_t tempB, tempA;                                                \
+    int64_t acc, dotp;                                                   \
+                                                                         \
+    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                                    \
+    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                    \
+                                                                         \
+    if (use_ac_env == 1) {                                               \
+        tempB = mipsdsp_mul_q15_q15(ac, rsh, rth, env);                  \
+        tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl, env);                  \
+    } else {                                                             \
+        tempB = mipsdsp_mul_u16_u16(rsh, rth);                           \
+        tempA = mipsdsp_mul_u16_u16(rsl, rtl);                           \
+    }                                                                    \
+                                                                         \
+    dotp = (int64_t)tempB - (int64_t)tempA;                              \
+    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);  \
+}
+
+MUL_VOID_PH(mulsaq_s_w_ph, 1);
+MUL_VOID_PH(mulsa_w_ph, 0);
+
+#undef MUL_VOID_PH
+
+#if defined(TARGET_MIPS64)
+#define MUL_RETURN64_16_QH(name, func, \
+                           rsmov1, rsmov2, rsmov3, rsmov4, rsfilter, \
+                           rtmov1, rtmov2, rtmov3, rtmov4, rtfilter) \
+target_ulong helper_##name(target_ulong rs, target_ulong rt,         \
+                           CPUMIPSState *env)                        \
+{                                                                    \
+    uint16_t rs3, rs2, rs1, rs0;                                     \
+    uint16_t rt3, rt2, rt1, rt0;                                     \
+    uint16_t tempD, tempC, tempB, tempA;                             \
+                                                                     \
+    rs3 = (rs >> rsmov1) & rsfilter;                                 \
+    rs2 = (rs >> rsmov2) & rsfilter;                                 \
+    rs1 = (rs >> rsmov3) & rsfilter;                                 \
+    rs0 = (rs >> rsmov4) & rsfilter;                                 \
+    rt3 = (rt >> rtmov1) & rtfilter;                                 \
+    rt2 = (rt >> rtmov2) & rtfilter;                                 \
+    rt1 = (rt >> rtmov3) & rtfilter;                                 \
+    rt0 = (rt >> rtmov4) & rtfilter;                                 \
+                                                                     \
+    tempD = mipsdsp_##func(rs3, rt3, env);                           \
+    tempC = mipsdsp_##func(rs2, rt2, env);                           \
+    tempB = mipsdsp_##func(rs1, rt1, env);                           \
+    tempA = mipsdsp_##func(rs0, rt0, env);                           \
+                                                                     \
+    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);          \
+}
+
+MUL_RETURN64_16_QH(muleu_s_qh_obl, mul_u8_u16, \
+                   56, 48, 40, 32, MIPSDSP_Q0, \
+                   48, 32, 16, 0, MIPSDSP_LO);
+MUL_RETURN64_16_QH(muleu_s_qh_obr, mul_u8_u16, \
+                   24, 16, 8, 0, MIPSDSP_Q0, \
+                   48, 32, 16, 0, MIPSDSP_LO);
+MUL_RETURN64_16_QH(mulq_rs_qh, rndq15_mul_q15_q15, \
+                   48, 32, 16, 0, MIPSDSP_LO, \
+                   48, 32, 16, 0, MIPSDSP_LO);
+
+#undef MUL_RETURN64_16_QH
+
+#define MUL_RETURN64_32_QH(name, \
+                           rsmov1, rsmov2, \
+                           rtmov1, rtmov2) \
+target_ulong helper_##name(target_ulong rs, target_ulong rt, \
+                           CPUMIPSState *env)                \
+{                                                            \
+    uint16_t rsB, rsA;                                       \
+    uint16_t rtB, rtA;                                       \
+    uint32_t tempB, tempA;                                   \
+                                                             \
+    rsB = (rs >> rsmov1) & MIPSDSP_LO;                       \
+    rsA = (rs >> rsmov2) & MIPSDSP_LO;                       \
+    rtB = (rt >> rtmov1) & MIPSDSP_LO;                       \
+    rtA = (rt >> rtmov2) & MIPSDSP_LO;                       \
+                                                             \
+    tempB = mipsdsp_mul_q15_q15(5, rsB, rtB, env);           \
+    tempA = mipsdsp_mul_q15_q15(5, rsA, rtA, env);           \
+                                                             \
+    return ((uint64_t)tempB << 32) | (uint64_t)tempA;        \
+}
+
+MUL_RETURN64_32_QH(muleq_s_pw_qhl, 48, 32, 48, 32);
+MUL_RETURN64_32_QH(muleq_s_pw_qhr, 16, 0, 16, 0);
+
+#undef MUL_RETURN64_32_QH
+
+void helper_mulsaq_s_w_qh(target_ulong rs, target_ulong rt, uint32_t ac,
+                          CPUMIPSState *env)
+{
+    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;
+
+    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
+    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
+
+    tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env);
+    tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env);
+    tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env);
+    tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env);
+
+    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] = ~0ull;
+    }
+
+    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
+
+#define DP_QB(name, func, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
+void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
+                   CPUMIPSState *env)                                    \
+{                                                                        \
+    uint8_t rs3, rs2;                                                    \
+    uint8_t rt3, rt2;                                                    \
+    uint16_t tempB, tempA;                                               \
+    uint64_t tempC, dotp;                                                \
+                                                                         \
+    rs3 = (rs >> rsmov1) & MIPSDSP_Q0;                                   \
+    rs2 = (rs >> rsmov2) & MIPSDSP_Q0;                                   \
+    rt3 = (rt >> rtmov1) & MIPSDSP_Q0;                                   \
+    rt2 = (rt >> rtmov2) & MIPSDSP_Q0;                                   \
+    tempB = mipsdsp_##func(rs3, rt3);                                    \
+    tempA = mipsdsp_##func(rs2, rt2);                                    \
+    dotp = (int64_t)tempB + (int64_t)tempA;                              \
+    if (is_add) {                                                        \
+        tempC = (((uint64_t)env->active_tc.HI[ac] << 32) |               \
+                 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO))        \
+            + dotp;                                                      \
+    } else {                                                             \
+        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); \
+}
+
+DP_QB(dpau_h_qbl, mul_u8_u8, 1, 24, 16, 24, 16);
+DP_QB(dpau_h_qbr, mul_u8_u8, 1, 8, 0, 8, 0);
+DP_QB(dpsu_h_qbl, mul_u8_u8, 0, 24, 16, 24, 16);
+DP_QB(dpsu_h_qbr, mul_u8_u8, 0, 8, 0, 8, 0);
+
+#undef DP_QB
+
+#if defined(TARGET_MIPS64)
+#define DP_OB(name, add_sub, \
+              rsmov1, rsmov2, rsmov3, rsmov4, \
+              rtmov1, rtmov2, rtmov3, rtmov4) \
+void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,       \
+                       CPUMIPSState *env)                               \
+{                                                                       \
+    uint8_t rsD, rsC, rsB, rsA;                                         \
+    uint8_t rtD, rtC, rtB, rtA;                                         \
+    uint16_t tempD, tempC, tempB, tempA;                                \
+    uint64_t temp[2];                                                   \
+    uint64_t acc[2];                                                    \
+    uint64_t temp_sum;                                                  \
+                                                                        \
+    temp[0] = 0;                                                        \
+    temp[1] = 0;                                                        \
+                                                                        \
+    rsD = (rs >> rsmov1) & MIPSDSP_Q0;                                  \
+    rsC = (rs >> rsmov2) & MIPSDSP_Q0;                                  \
+    rsB = (rs >> rsmov3) & MIPSDSP_Q0;                                  \
+    rsA = (rs >> rsmov4) & MIPSDSP_Q0;                                  \
+    rtD = (rt >> rtmov1) & MIPSDSP_Q0;                                  \
+    rtC = (rt >> rtmov2) & MIPSDSP_Q0;                                  \
+    rtB = (rt >> rtmov3) & MIPSDSP_Q0;                                  \
+    rtA = (rt >> rtmov4) & MIPSDSP_Q0;                                  \
+                                                                        \
+    tempD = mipsdsp_mul_u8_u8(rsD, rtD);                                \
+    tempC = mipsdsp_mul_u8_u8(rsC, rtC);                                \
+    tempB = mipsdsp_mul_u8_u8(rsB, rtB);                                \
+    tempA = mipsdsp_mul_u8_u8(rsA, rtA);                                \
+                                                                        \
+    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];                                     \
+                                                                        \
+    if (add_sub) {                                                      \
+        temp_sum = acc[0] + temp[0];                                    \
+        acc[1] = acc[1] + MIPSDSP_OVERFLOW(acc[0], temp[0], temp_sum,   \
+                                             0x8000000000000000ull);    \
+        temp[0] = temp_sum;                                             \
+        temp[1] = acc[1] + temp[1];                                     \
+    } else {                                                            \
+        temp_sum = acc[0] - temp[0];                                    \
+        acc[1] = acc[1] + MIPSDSP_OVERFLOW(acc[0], -temp[0], temp_sum,  \
+                                             0x8000000000000000ull);    \
+        temp[0] = temp_sum;                                             \
+        temp[1] = acc[1] - temp[1];                                     \
+    }                                                                   \
+                                                                        \
+    env->active_tc.HI[ac] = temp[1];                                    \
+    env->active_tc.LO[ac] = temp[0];                                    \
+}
+
+DP_OB(dpau_h_obl, 1, 56, 48, 40, 32, 56, 48, 40, 32);
+DP_OB(dpau_h_obr, 1, 24, 16, 8, 0, 24, 16, 8, 0);
+DP_OB(dpsu_h_obl, 0, 56, 48, 40, 32, 56, 48, 40, 32);
+DP_OB(dpsu_h_obr, 0, 24, 16, 8, 0, 24, 16, 8, 0);
+
+#undef DP_OB
+#endif
+
+#define DP_NOFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2)             \
+void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,              \
+                   CPUMIPSState *env)                                          \
+{                                                                              \
+    uint16_t rsB, rsA, rtB, rtA;                                               \
+    int32_t  tempA, tempB;                                                     \
+    int64_t  acc;                                                              \
+                                                                               \
+    rsB = (rs >> rsmov1) & MIPSDSP_LO;                                         \
+    rsA = (rs >> rsmov2) & MIPSDSP_LO;                                         \
+    rtB = (rt >> rtmov1) & MIPSDSP_LO;                                         \
+    rtA = (rt >> rtmov2) & MIPSDSP_LO;                                         \
+                                                                               \
+    tempB = (int32_t)rsB * (int32_t)rtB;                                       \
+    tempA = (int32_t)rsA * (int32_t)rtA;                                       \
+                                                                               \
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                            \
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);                     \
+                                                                               \
+    if (is_add) {                                                              \
+        acc = acc + ((int64_t)tempB + (int64_t)tempA);                         \
+    } else {                                                                   \
+        acc = acc - ((int64_t)tempB + (int64_t)tempA);                         \
+    }                                                                          \
+                                                                               \
+    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);         \
+}
+
+DP_NOFUNC_PH(dpa_w_ph, 1, 16, 0, 16, 0);
+DP_NOFUNC_PH(dpax_w_ph, 1, 16, 0, 0, 16);
+DP_NOFUNC_PH(dps_w_ph, 0, 16, 0, 16, 0);
+DP_NOFUNC_PH(dpsx_w_ph, 0, 16, 0, 0, 16);
+#undef DP_NOFUNC_PH
+
+#define DP_HASFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
+void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,   \
+                   CPUMIPSState *env)                      \
+{                                                          \
+    int16_t rsB, rsA, rtB, rtA;                            \
+    int32_t tempB, tempA;                                  \
+    int64_t acc, dotp;                                     \
+                                                           \
+    rsB = (rs >> rsmov1) & MIPSDSP_LO;                     \
+    rsA = (rs >> rsmov2) & MIPSDSP_LO;                     \
+    rtB = (rt >> rtmov1) & MIPSDSP_LO;                     \
+    rtA = (rt >> rtmov2) & MIPSDSP_LO;                     \
+                                                           \
+    tempB = mipsdsp_mul_q15_q15(ac, rsB, rtB, env);        \
+    tempA = mipsdsp_mul_q15_q15(ac, rsA, rtA, env);        \
+                                                           \
+    dotp = (int64_t)tempB + (int64_t)tempA;                \
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |        \
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
+                                                           \
+    if (is_add) {                                          \
+        acc = acc + dotp;                                  \
+    } else {                                               \
+        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);                               \
+}
+
+DP_HASFUNC_PH(dpaq_s_w_ph, 1, 16, 0, 16, 0);
+DP_HASFUNC_PH(dpaqx_s_w_ph, 1, 16, 0, 0, 16);
+DP_HASFUNC_PH(dpsq_s_w_ph, 0, 16, 0, 16, 0);
+DP_HASFUNC_PH(dpsqx_s_w_ph, 0, 16, 0, 0, 16);
+
+#undef DP_HASFUNC_PH
+
+#define DP_128OPERATION_PH(name, is_add) \
+void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
+                          CPUMIPSState *env)                             \
+{                                                                        \
+    int16_t rsh, rsl, rth, rtl;                                          \
+    int32_t tempB, tempA, tempC62_31, tempC63;                           \
+    int64_t acc, dotp, tempC;                                            \
+                                                                         \
+    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                                    \
+    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                    \
+                                                                         \
+    tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl, env);                      \
+    tempA = mipsdsp_mul_q15_q15(ac, rsl, rth, env);                      \
+                                                                         \
+    dotp = (int64_t)tempB + (int64_t)tempA;                              \
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                      \
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);               \
+    if (is_add) {                                                        \
+        tempC = acc + dotp;                                              \
+    } else {                                                             \
+        tempC = acc - dotp;                                              \
+    }                                                                    \
+    tempC63 = (tempC >> 63) & 0x01;                                      \
+    tempC62_31 = (tempC >> 31) & 0xFFFFFFFF;                             \
+                                                                         \
+    if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) {                  \
+        tempC = 0x7FFFFFFF;                                              \
+        set_DSPControl_overflow_flag(1, 16 + ac, env);                   \
+    }                                                                    \
+                                                                         \
+    if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) {                  \
+        tempC = 0xFFFFFFFF80000000ull;                                   \
+        set_DSPControl_overflow_flag(1, 16 + ac, env);                   \
+    }                                                                    \
+                                                                         \
+    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);                                           \
+}
+
+DP_128OPERATION_PH(dpaqx_sa_w_ph, 1);
+DP_128OPERATION_PH(dpsqx_sa_w_ph, 0);
+
+#undef DP_128OPERATION_HP
+
+#if defined(TARGET_MIPS64)
+#define DP_QH(name, is_add, use_ac_env) \
+void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,    \
+                   CPUMIPSState *env)                                \
+{                                                                    \
+    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;                                                \
+                                                                     \
+    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);                      \
+    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                      \
+                                                                     \
+    if (use_ac_env) {                                                \
+        tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env);              \
+        tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env);              \
+        tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env);              \
+        tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env);              \
+    } else {                                                         \
+        tempD = mipsdsp_mul_u16_u16(rs3, rt3);                       \
+        tempC = mipsdsp_mul_u16_u16(rs2, rt2);                       \
+        tempB = mipsdsp_mul_u16_u16(rs1, rt1);                       \
+        tempA = mipsdsp_mul_u16_u16(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] >= 0) {                                              \
+        temp[1] = 0;                                                 \
+    } else {                                                         \
+        temp[1] = ~0ull;                                             \
+    }                                                                \
+                                                                     \
+    acc[1] = env->active_tc.HI[ac];                                  \
+    acc[0] = env->active_tc.LO[ac];                                  \
+                                                                     \
+    if (is_add) {                                                    \
+        temp_sum = acc[0] + temp[0];                                 \
+        if (MIPSDSP_OVERFLOW(acc[0], temp[0], temp_sum,              \
+                               0x8000000000000000ull)) {             \
+            acc[1] = acc[1] + 1;                                     \
+        }                                                            \
+        temp[0] = temp_sum;                                          \
+        temp[1] = acc[1] + temp[1];                                  \
+    } else {                                                         \
+        temp_sum = acc[0] - temp[0];                                 \
+        if (MIPSDSP_OVERFLOW(acc[0], -temp[0], temp_sum,             \
+                               0x8000000000000000ull)) {             \
+            acc[1] = acc[1] - 1;                                     \
+        }                                                            \
+        temp[0] = temp_sum;                                          \
+        temp[1] = acc[1] - temp[1];                                  \
+    }                                                                \
+                                                                     \
+    env->active_tc.HI[ac] = temp[1];                                 \
+    env->active_tc.LO[ac] = temp[0];                                 \
+}
+
+DP_QH(dpa_w_qh, 1, 0);
+DP_QH(dpaq_s_w_qh, 1, 1);
+DP_QH(dps_w_qh, 0, 0);
+DP_QH(dpsq_s_w_qh, 0, 1);
+
+#undef DP_QH
+
+#endif
+
+#define DP_L_W(name, is_add) \
+void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,     \
+                   CPUMIPSState *env)                                 \
+{                                                                     \
+    int32_t temp64, temp63, tempacc63, tempdotp63, tempDL63;          \
+    int64_t dotp, acc;                                                \
+    int64_t tempDL[2];                                                \
+    uint64_t temp;                                                    \
+                                                                      \
+    dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env);                      \
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                   \
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);            \
+    if (is_add) {                                                     \
+        tempDL[0] = acc + dotp;                                       \
+    } else {                                                          \
+        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(1, 16 + ac, env);                \
+    }                                                                 \
+                                                                      \
+    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);                                         \
+}
+
+DP_L_W(dpaq_sa_l_w, 1);
+DP_L_W(dpsq_sa_l_w, 0);
+
+#undef DP_L_W
+
+#if defined(TARGET_MIPS64)
+#define DP_L_PW(name, func) \
+void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
+                   CPUMIPSState *env)                             \
+{                                                                 \
+    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;                                                  \
+                                                                  \
+    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                             \
+    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
+                                                                  \
+    tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env);            \
+    tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);            \
+                                                                  \
+    if (tempB[0] >= 0) {                                          \
+        tempB[1] = 0x00;                                          \
+    } else {                                                      \
+        tempB[1] = ~0ull;                                         \
+    }                                                             \
+                                                                  \
+    if (tempA[0] >= 0) {                                          \
+        tempA[1] = 0x00;                                          \
+    } else {                                                      \
+        tempA[1] = ~0ull;                                         \
+    }                                                             \
+                                                                  \
+    temp_sum = tempB[0] + tempA[0];                               \
+    if (MIPSDSP_OVERFLOW(tempB[0], tempA[0], temp_sum,            \
+                           0x8000000000000000ull)) {              \
+        temp[1] += 1;                                             \
+    }                                                             \
+    temp[0] = temp_sum;                                           \
+    temp[1] += tempB[1] + tempA[1];                               \
+                                                                  \
+    mipsdsp_##func(acc, ac, temp, env);                           \
+                                                                  \
+    env->active_tc.HI[ac] = acc[1];                               \
+    env->active_tc.LO[ac] = acc[0];                               \
+}
+
+DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63);
+DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63);
+
+#undef DP_L_PW
+
+void helper_mulsaq_s_l_pw(target_ulong rs, target_ulong rt, uint32_t ac,
+                          CPUMIPSState *env)
+{
+    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(ac, rs1, rt1, env);
+    tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);
+
+    if (tempB[0] >= 0) {
+        tempB[1] = 0x00;
+    } else {
+        tempB[1] = ~0ull;
+    }
+
+    if (tempA[0] >= 0) {
+        tempA[1] = 0x00;
+    } else {
+        tempA[1] = ~0ull;
+    }
+
+    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] = ~0ull;
+    }
+
+    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
+
+#define MAQ_S_W(name, mov) \
+void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
+                   CPUMIPSState *env)                             \
+{                                                                 \
+    int16_t rsh, rth;                                             \
+    int32_t tempA;                                                \
+    int64_t tempL, acc;                                           \
+                                                                  \
+    rsh = (rs >> mov) & MIPSDSP_LO;                               \
+    rth = (rt >> mov) & MIPSDSP_LO;                               \
+    tempA  = mipsdsp_mul_q15_q15(ac, rsh, rth, env);              \
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |               \
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);        \
+    tempL  = (int64_t)tempA + 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);                                    \
+}
+
+MAQ_S_W(maq_s_w_phl, 16);
+MAQ_S_W(maq_s_w_phr, 0);
+
+#undef MAQ_S_W
+
+#define MAQ_SA_W(name, mov) \
+void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
+                   CPUMIPSState *env)                                    \
+{                                                                        \
+    int16_t rsh, rth;                                                    \
+    int32_t tempA;                                                       \
+                                                                         \
+    rsh = (rs >> mov) & MIPSDSP_LO;                                      \
+    rth = (rt >> mov) & MIPSDSP_LO;                                      \
+    tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env);                      \
+    tempA = mipsdsp_sat32_acc_q31(ac, tempA, env);                       \
+                                                                         \
+    env->active_tc.HI[ac] = (target_long)(int32_t)(((int64_t)tempA &     \
+                                                    MIPSDSP_LHI) >> 32); \
+    env->active_tc.LO[ac] = (target_long)(int32_t)((int64_t)tempA &      \
+                                                   MIPSDSP_LLO);         \
+}
+
+MAQ_SA_W(maq_sa_w_phl, 16);
+MAQ_SA_W(maq_sa_w_phr, 0);
+
+#undef MAQ_SA_W
+
+#define MULQ_W(name, addvar) \
+target_ulong helper_##name(target_ulong rs, target_ulong rt,   \
+                           CPUMIPSState *env)                  \
+{                                                              \
+    uint32_t rs_t, rt_t;                                       \
+    int32_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(1, 21, env);              \
+    } else {                                                   \
+        tempL  = ((int64_t)rs_t * (int64_t)rt_t) << 1;         \
+        tempL += addvar;                                       \
+    }                                                          \
+    tempI = (tempL & MIPSDSP_LHI) >> 32;                       \
+                                                               \
+    return (target_long)(int32_t)tempI;                        \
+}
+
+MULQ_W(mulq_s_w, 0);
+MULQ_W(mulq_rs_w, 0x80000000ull);
+
+#undef MULQ_W
+
+#if defined(TARGET_MIPS64)
+
+#define MAQ_S_W_QH(name, mov) \
+void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
+                   CPUMIPSState *env)                             \
+{                                                                 \
+    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 >> mov) & MIPSDSP_LO;                              \
+    rt_t = (rt >> mov) & MIPSDSP_LO;                              \
+    temp_mul = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env);          \
+                                                                  \
+    temp[0] = (int64_t)temp_mul;                                  \
+    if (temp[0] >= 0) {                                           \
+        temp[1] = 0x00;                                           \
+    } else {                                                      \
+        temp[1] = ~0ull;                                          \
+    }                                                             \
+                                                                  \
+    acc[0] = env->active_tc.LO[ac];                               \
+    acc[1] = env->active_tc.HI[ac];                               \
+                                                                  \
+    temp_sum = acc[0] + temp[0];                                  \
+    if (MIPSDSP_OVERFLOW(acc[0], temp[0], temp_sum,               \
+                           0x8000000000000000ull)) {              \
+        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];                               \
+}
+
+MAQ_S_W_QH(maq_s_w_qhll, 48);
+MAQ_S_W_QH(maq_s_w_qhlr, 32);
+MAQ_S_W_QH(maq_s_w_qhrl, 16);
+MAQ_S_W_QH(maq_s_w_qhrr, 0);
+
+#undef MAQ_S_W_QH
+
+#define MAQ_SA_W(name, mov) \
+void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
+                   CPUMIPSState *env)                             \
+{                                                                 \
+    int16_t rs_t, rt_t;                                           \
+    int32_t temp;                                                 \
+    int64_t acc[2];                                               \
+                                                                  \
+    rs_t = (rs >> mov) & MIPSDSP_LO;                              \
+    rt_t = (rt >> mov) & MIPSDSP_LO;                              \
+    temp = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env);              \
+    temp = mipsdsp_sat32_acc_q31(ac, temp, env);                  \
+                                                                  \
+    acc[0] = (int64_t)(int32_t)temp;                              \
+    if (acc[0] >= 0) {                                            \
+        acc[1] = 0x00;                                            \
+    } else {                                                      \
+        acc[1] = ~0ull;                                           \
+    }                                                             \
+                                                                  \
+    env->active_tc.HI[ac] = acc[1];                               \
+    env->active_tc.LO[ac] = acc[0];                               \
+}
+
+MAQ_SA_W(maq_sa_w_qhll, 48);
+MAQ_SA_W(maq_sa_w_qhlr, 32);
+MAQ_SA_W(maq_sa_w_qhrl, 16);
+MAQ_SA_W(maq_sa_w_qhrr, 0);
+
+#undef MAQ_SA_W
+
+#define MAQ_S_L_PW(name, mov) \
+void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
+                   CPUMIPSState *env)                             \
+{                                                                 \
+    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 >> mov) & MIPSDSP_LLO;                             \
+    rt_t = (rt >> mov) & MIPSDSP_LLO;                             \
+                                                                  \
+    temp[0] = mipsdsp_mul_q31_q31(ac, rs_t, rt_t, env);           \
+    if (temp[0] >= 0) {                                           \
+        temp[1] = 0x00;                                           \
+    } else {                                                      \
+        temp[1] = ~0ull;                                          \
+    }                                                             \
+                                                                  \
+    acc[0] = env->active_tc.LO[ac];                               \
+    acc[1] = env->active_tc.HI[ac];                               \
+                                                                  \
+    temp_sum = acc[0] + temp[0];                                  \
+    if (MIPSDSP_OVERFLOW(acc[0], temp[0], temp_sum,               \
+                         0x8000000000000000ull)) {                \
+        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];                               \
+}
+
+MAQ_S_L_PW(maq_s_l_pwl, 32);
+MAQ_S_L_PW(maq_s_l_pwr, 0);
+
+#undef MAQ_S_L_PW
+
+#define DM_OPERATE(name, func, is_add, sigext) \
+void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,    \
+                  CPUMIPSState *env)                                 \
+{                                                                    \
+    int32_t rs1, rs0;                                                \
+    int32_t rt1, rt0;                                                \
+    int64_t tempBL[2], tempAL[2];                                    \
+    int64_t acc[2];                                                  \
+    int64_t temp[2];                                                 \
+    int64_t temp_sum;                                                \
+                                                                     \
+    temp[0] = 0x00;                                                  \
+    temp[1] = 0x00;                                                  \
+                                                                     \
+    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                                \
+    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                                \
+                                                                     \
+    if (sigext) {                                                    \
+        tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1);               \
+        tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0);               \
+                                                                     \
+        if (tempBL[0] >= 0) {                                        \
+            tempBL[1] = 0x0;                                         \
+        } else {                                                     \
+            tempBL[1] = ~0ull;                                       \
+        }                                                            \
+                                                                     \
+        if (tempAL[0] >= 0) {                                        \
+            tempAL[1] = 0x0;                                         \
+        } else {                                                     \
+            tempAL[1] = ~0ull;                                       \
+        }                                                            \
+    } else {                                                         \
+        tempBL[0] = mipsdsp_##func(rs1, rt1);                        \
+        tempAL[0] = mipsdsp_##func(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 (MIPSDSP_OVERFLOW(tempBL[0], tempAL[0], temp_sum,             \
+                         0x8000000000000000ull)) {                   \
+        temp[1] += 1;                                                \
+    }                                                                \
+    temp[0] = temp_sum;                                              \
+    temp[1] += tempBL[1] + tempAL[1];                                \
+                                                                     \
+    if (is_add) {                                                    \
+        temp_sum = acc[0] + temp[0];                                 \
+        if (MIPSDSP_OVERFLOW(acc[0], temp[0], temp_sum,              \
+                             0x8000000000000000ull)) {               \
+            acc[1] = acc[1] + 1;                                     \
+        }                                                            \
+        temp[0] = temp_sum;                                          \
+        temp[1] = acc[1] + temp[1];                                  \
+    } else {                                                         \
+        temp_sum = acc[0] - temp[0];                                 \
+        if (MIPSDSP_OVERFLOW(acc[0], -temp[0], temp_sum,             \
+                             0x8000000000000000ull)) {               \
+            acc[1] = acc[1] - 1;                                     \
+        }                                                            \
+        temp[0] = temp_sum;                                          \
+        temp[1] = acc[1] - temp[1];                                  \
+    }                                                                \
+                                                                     \
+    env->active_tc.HI[ac] = temp[1];                                 \
+    env->active_tc.LO[ac] = temp[0];                                 \
+}
+
+DM_OPERATE(dmadd, mul_i32_i32, 1, 1);
+DM_OPERATE(dmaddu, mul_u32_u32, 1, 0);
+DM_OPERATE(dmsub, mul_i32_i32, 0, 1);
+DM_OPERATE(dmsubu, mul_u32_u32, 0, 0);
+#undef DM_OPERATE
+#endif
+
 #undef MIPSDSP_LHI
 #undef MIPSDSP_LLO
 #undef MIPSDSP_HI
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 5258ef6..6a6ca99 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -526,4 +526,95 @@ DEF_HELPER_FLAGS_2(shra_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, tl)
 #endif
 
+/* DSP Multiply Sub-class insns */
+DEF_HELPER_FLAGS_3(muleu_s_ph_qbl, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(muleu_s_ph_qbr, 0, tl, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(muleu_s_qh_obl, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(muleu_s_qh_obr, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(mulq_rs_ph, 0, tl, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(mulq_rs_qh, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(muleq_s_w_phl, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(muleq_s_w_phr, 0, tl, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(muleq_s_pw_qhl, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(muleq_s_pw_qhr, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_4(dpau_h_qbl, 0, void, i32, tl, tl, env)
+DEF_HELPER_FLAGS_4(dpau_h_qbr, 0, void, i32, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpau_h_obl, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(dpau_h_obr, 0, void, tl, tl, i32, env)
+#endif
+DEF_HELPER_FLAGS_4(dpsu_h_qbl, 0, void, i32, tl, tl, env)
+DEF_HELPER_FLAGS_4(dpsu_h_qbr, 0, void, i32, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpsu_h_obl, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(dpsu_h_obr, 0, void, tl, tl, i32, env)
+#endif
+DEF_HELPER_FLAGS_4(dpa_w_ph, 0, void, i32, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpa_w_qh, 0, void, tl, tl, i32, env)
+#endif
+DEF_HELPER_FLAGS_4(dpax_w_ph, 0, void, i32, tl, tl, env)
+DEF_HELPER_FLAGS_4(dpaq_s_w_ph, 0, void, i32, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpaq_s_w_qh, 0, void, tl, tl, i32, env)
+#endif
+DEF_HELPER_FLAGS_4(dpaqx_s_w_ph, 0, void, i32, tl, tl, env)
+DEF_HELPER_FLAGS_4(dpaqx_sa_w_ph, 0, void, i32, tl, tl, env)
+DEF_HELPER_FLAGS_4(dps_w_ph, 0, void, i32, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dps_w_qh, 0, void, tl, tl, i32, env)
+#endif
+DEF_HELPER_FLAGS_4(dpsx_w_ph, 0, void, i32, tl, tl, env)
+DEF_HELPER_FLAGS_4(dpsq_s_w_ph, 0, void, i32, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpsq_s_w_qh, 0, void, tl, tl, i32, env)
+#endif
+DEF_HELPER_FLAGS_4(dpsqx_s_w_ph, 0, void, i32, tl, tl, env)
+DEF_HELPER_FLAGS_4(dpsqx_sa_w_ph, 0, void, i32, tl, tl, env)
+DEF_HELPER_FLAGS_4(mulsaq_s_w_ph, 0, void, i32, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(mulsaq_s_w_qh, 0, void, tl, tl, i32, env)
+#endif
+DEF_HELPER_FLAGS_4(dpaq_sa_l_w, 0, void, i32, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpaq_sa_l_pw, 0, void, tl, tl, i32, env)
+#endif
+DEF_HELPER_FLAGS_4(dpsq_sa_l_w, 0, void, i32, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(dpsq_sa_l_pw, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(mulsaq_s_l_pw, 0, void, tl, tl, i32, env)
+#endif
+DEF_HELPER_FLAGS_4(maq_s_w_phl, 0, void, i32, tl, tl, env)
+DEF_HELPER_FLAGS_4(maq_s_w_phr, 0, void, i32, tl, tl, env)
+DEF_HELPER_FLAGS_4(maq_sa_w_phl, 0, void, i32, tl, tl, env)
+DEF_HELPER_FLAGS_4(maq_sa_w_phr, 0, void, i32, tl, tl, env)
+DEF_HELPER_FLAGS_3(mul_ph, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(mul_s_ph, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(mulq_s_ph, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(mulq_s_w, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(mulq_rs_w, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_4(mulsa_w_ph, 0, void, i32, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_4(maq_s_w_qhll, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(maq_s_w_qhlr, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(maq_s_w_qhrl, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(maq_s_w_qhrr, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(maq_sa_w_qhll, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(maq_sa_w_qhlr, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(maq_sa_w_qhrl, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(maq_sa_w_qhrr, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(maq_s_l_pwl, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(maq_s_l_pwr, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(dmadd, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(dmaddu, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(dmsub, 0, void, tl, tl, i32, env)
+DEF_HELPER_FLAGS_4(dmsubu, 0, void, tl, tl, i32, env)
+#endif
+
 #include "def-helper.h"
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 72e2703..1ec6edc 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 */
@@ -13244,6 +13323,365 @@ static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
     MIPS_DEBUG("%s", opn);
 }
 
+static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
+                                 int ret, int rs, int rt, int check_ret)
+{
+    const char *opn = "mipsdsp multiply";
+    TCGv_i32 t0 = tcg_const_i32(ret);
+
+    if ((ret == 0) && (check_ret == 1)) {
+        /* Treat as NOP. */
+        MIPS_DEBUG("NOP");
+        return;
+    }
+
+    switch (op1) {
+    /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
+     * the same mask and op1. */
+    case OPC_MULT_G_2E:
+        switch (op2) {
+        case  OPC_MUL_PH:
+            gen_helper_mul_ph(cpu_gpr[ret], cpu_gpr[rs],
+                              cpu_gpr[rt], cpu_env);
+            break;
+        case  OPC_MUL_S_PH:
+            gen_helper_mul_s_ph(cpu_gpr[ret], cpu_gpr[rs],
+                                cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MULQ_S_W:
+            gen_helper_mulq_s_w(cpu_gpr[ret], cpu_gpr[rs],
+                                cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MULQ_RS_W:
+            gen_helper_mulq_rs_w(cpu_gpr[ret], cpu_gpr[rs],
+                                 cpu_gpr[rt], cpu_env);
+            break;
+        }
+        break;
+    case OPC_DPA_W_PH_DSP:
+        switch (op2) {
+        case OPC_DPAU_H_QBL:
+            check_dsp(ctx);
+            gen_helper_dpau_h_qbl(t0, cpu_gpr[rs],
+                                  cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPAU_H_QBR:
+            check_dsp(ctx);
+            gen_helper_dpau_h_qbr(t0, cpu_gpr[rs],
+                                  cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPSU_H_QBL:
+            check_dsp(ctx);
+            gen_helper_dpsu_h_qbl(t0, cpu_gpr[rs],
+                                  cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPSU_H_QBR:
+            check_dsp(ctx);
+            gen_helper_dpsu_h_qbr(t0, cpu_gpr[rs],
+                                  cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPA_W_PH:
+            check_dspr2(ctx);
+            gen_helper_dpa_w_ph(t0, cpu_gpr[rs],
+                                cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPAX_W_PH:
+            check_dspr2(ctx);
+            gen_helper_dpax_w_ph(t0, cpu_gpr[rs],
+                                 cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPAQ_S_W_PH:
+            check_dsp(ctx);
+            gen_helper_dpaq_s_w_ph(t0, cpu_gpr[rs],
+                                   cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPAQX_S_W_PH:
+            check_dspr2(ctx);
+            gen_helper_dpaqx_s_w_ph(t0, cpu_gpr[rs],
+                                    cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPAQX_SA_W_PH:
+            check_dspr2(ctx);
+            gen_helper_dpaqx_sa_w_ph(t0, cpu_gpr[rs],
+                                     cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPS_W_PH:
+            check_dspr2(ctx);
+            gen_helper_dps_w_ph(t0, cpu_gpr[rs],
+                                cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPSX_W_PH:
+            check_dspr2(ctx);
+            gen_helper_dpsx_w_ph(t0, cpu_gpr[rs],
+                                 cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPSQ_S_W_PH:
+            check_dsp(ctx);
+            gen_helper_dpsq_s_w_ph(t0, cpu_gpr[rs],
+                                   cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPSQX_S_W_PH:
+            check_dspr2(ctx);
+            gen_helper_dpsqx_s_w_ph(t0, cpu_gpr[rs],
+                                    cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPSQX_SA_W_PH:
+            check_dspr2(ctx);
+            {
+                gen_helper_dpsqx_sa_w_ph(t0, cpu_gpr[rs],
+                                         cpu_gpr[rt], cpu_env);
+                break;
+            }
+        case OPC_MULSAQ_S_W_PH:
+            check_dsp(ctx);
+            gen_helper_mulsaq_s_w_ph(t0, cpu_gpr[rs],
+                                     cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPAQ_SA_L_W:
+            check_dsp(ctx);
+            gen_helper_dpaq_sa_l_w(t0, cpu_gpr[rs],
+                                   cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_DPSQ_SA_L_W:
+            check_dsp(ctx);
+            gen_helper_dpsq_sa_l_w(t0, cpu_gpr[rs],
+                                   cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MAQ_S_W_PHL:
+            check_dsp(ctx);
+            gen_helper_maq_s_w_phl(t0, cpu_gpr[rs],
+                                   cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MAQ_S_W_PHR:
+            check_dsp(ctx);
+            gen_helper_maq_s_w_phr(t0, cpu_gpr[rs],
+                                   cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MAQ_SA_W_PHL:
+            check_dsp(ctx);
+            gen_helper_maq_sa_w_phl(t0, cpu_gpr[rs],
+                                    cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MAQ_SA_W_PHR:
+            check_dsp(ctx);
+            gen_helper_maq_sa_w_phr(t0, cpu_gpr[rs],
+                                    cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MULSA_W_PH:
+            check_dspr2(ctx);
+            gen_helper_mulsa_w_ph(t0, cpu_gpr[rs],
+                                  cpu_gpr[rt], cpu_env);
+            break;
+        }
+#ifdef TARGET_MIPS64
+    case OPC_DPAQ_W_QH_DSP:
+        {
+            int ac = ret & 0x03;
+            tcg_gen_movi_i32(t0, ac);
+
+            switch (op2) {
+            case OPC_DMADD:
+                check_dsp(ctx);
+                gen_helper_dmadd(cpu_gpr[rs], cpu_gpr[rt], t0, cpu_env);
+                break;
+            case OPC_DMADDU:
+                check_dsp(ctx);
+                gen_helper_dmaddu(cpu_gpr[rs], cpu_gpr[rt], t0, cpu_env);
+                break;
+            case OPC_DMSUB:
+                check_dsp(ctx);
+                gen_helper_dmsub(cpu_gpr[rs], cpu_gpr[rt], t0, cpu_env);
+                break;
+            case OPC_DMSUBU:
+                check_dsp(ctx);
+                gen_helper_dmsubu(cpu_gpr[rs], cpu_gpr[rt], t0, cpu_env);
+                break;
+            case OPC_DPA_W_QH:
+                check_dspr2(ctx);
+                gen_helper_dpa_w_qh(cpu_gpr[rs], cpu_gpr[rt],
+                                    t0, cpu_env);
+                break;
+            case OPC_DPAQ_S_W_QH:
+                check_dsp(ctx);
+                gen_helper_dpaq_s_w_qh(cpu_gpr[rs], cpu_gpr[rt],
+                                       t0, cpu_env);
+                break;
+            case OPC_DPAQ_SA_L_PW:
+                check_dsp(ctx);
+                gen_helper_dpaq_sa_l_pw(cpu_gpr[rs], cpu_gpr[rt],
+                                        t0, cpu_env);
+                break;
+            case OPC_DPAU_H_OBL:
+                check_dsp(ctx);
+                gen_helper_dpau_h_obl(cpu_gpr[rs], cpu_gpr[rt],
+                                      t0, cpu_env);
+                break;
+            case OPC_DPAU_H_OBR:
+                check_dsp(ctx);
+                gen_helper_dpau_h_obr(cpu_gpr[rs], cpu_gpr[rt],
+                                      t0, cpu_env);
+                break;
+            case OPC_DPS_W_QH:
+                check_dspr2(ctx);
+                gen_helper_dps_w_qh(cpu_gpr[rs], cpu_gpr[rt],
+                                    t0, cpu_env);
+                break;
+            case OPC_DPSQ_S_W_QH:
+                check_dsp(ctx);
+                gen_helper_dpsq_s_w_qh(cpu_gpr[rs], cpu_gpr[rt],
+                                       t0, cpu_env);
+                break;
+            case OPC_DPSQ_SA_L_PW:
+                check_dsp(ctx);
+                gen_helper_dpsq_sa_l_pw(cpu_gpr[rs], cpu_gpr[rt],
+                                        t0, cpu_env);
+                break;
+            case OPC_DPSU_H_OBL:
+                check_dsp(ctx);
+                gen_helper_dpsu_h_obl(cpu_gpr[rs], cpu_gpr[rt],
+                                      t0, cpu_env);
+                break;
+            case OPC_DPSU_H_OBR:
+                check_dsp(ctx);
+                gen_helper_dpsu_h_obr(cpu_gpr[rs], cpu_gpr[rt],
+                                      t0, cpu_env);
+                break;
+            case OPC_MAQ_S_L_PWL:
+                check_dsp(ctx);
+                gen_helper_maq_s_l_pwl(cpu_gpr[rs], cpu_gpr[rt],
+                                       t0, cpu_env);
+                break;
+            case OPC_MAQ_S_L_PWR:
+                check_dsp(ctx);
+                gen_helper_maq_s_l_pwr(cpu_gpr[rs], cpu_gpr[rt],
+                                       t0, cpu_env);
+                break;
+            case OPC_MAQ_S_W_QHLL:
+                check_dsp(ctx);
+                gen_helper_maq_s_w_qhll(cpu_gpr[rs], cpu_gpr[rt],
+                                        t0, cpu_env);
+                break;
+            case OPC_MAQ_SA_W_QHLL:
+                check_dsp(ctx);
+                gen_helper_maq_sa_w_qhll(cpu_gpr[rs], cpu_gpr[rt],
+                                         t0, cpu_env);
+                break;
+            case OPC_MAQ_S_W_QHLR:
+                check_dsp(ctx);
+                gen_helper_maq_s_w_qhlr(cpu_gpr[rs], cpu_gpr[rt],
+                                        t0, cpu_env);
+                break;
+            case OPC_MAQ_SA_W_QHLR:
+                check_dsp(ctx);
+                gen_helper_maq_sa_w_qhlr(cpu_gpr[rs], cpu_gpr[rt],
+                                         t0, cpu_env);
+                break;
+            case OPC_MAQ_S_W_QHRL:
+                check_dsp(ctx);
+                gen_helper_maq_s_w_qhrl(cpu_gpr[rs], cpu_gpr[rt],
+                                        t0, cpu_env);
+                break;
+            case OPC_MAQ_SA_W_QHRL:
+                check_dsp(ctx);
+                gen_helper_maq_sa_w_qhrl(cpu_gpr[rs], cpu_gpr[rt],
+                                         t0, cpu_env);
+                break;
+            case OPC_MAQ_S_W_QHRR:
+                check_dsp(ctx);
+                gen_helper_maq_s_w_qhrr(cpu_gpr[rs], cpu_gpr[rt],
+                                        t0, cpu_env);
+                break;
+            case OPC_MAQ_SA_W_QHRR:
+                check_dsp(ctx);
+                gen_helper_maq_sa_w_qhrr(cpu_gpr[rs], cpu_gpr[rt],
+                                         t0, cpu_env);
+                break;
+            case OPC_MULSAQ_S_L_PW:
+                check_dsp(ctx);
+                gen_helper_mulsaq_s_l_pw(cpu_gpr[rs], cpu_gpr[rt],
+                                         t0, cpu_env);
+                break;
+            case OPC_MULSAQ_S_W_QH:
+                check_dsp(ctx);
+                gen_helper_mulsaq_s_w_qh(cpu_gpr[rs], cpu_gpr[rt],
+                                         t0, cpu_env);
+                break;
+            }
+        }
+        break;
+#endif
+    case OPC_ADDU_QB_DSP:
+        switch (op2) {
+        case OPC_MULEU_S_PH_QBL:
+            check_dsp(ctx);
+            gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], cpu_gpr[rs],
+                                      cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MULEU_S_PH_QBR:
+            check_dsp(ctx);
+            gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], cpu_gpr[rs],
+                                      cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MULQ_RS_PH:
+            check_dsp(ctx);
+            gen_helper_mulq_rs_ph(cpu_gpr[ret], cpu_gpr[rs],
+                                  cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MULEQ_S_W_PHL:
+            check_dsp(ctx);
+            gen_helper_muleq_s_w_phl(cpu_gpr[ret], cpu_gpr[rs],
+                                     cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MULEQ_S_W_PHR:
+            check_dsp(ctx);
+            gen_helper_muleq_s_w_phr(cpu_gpr[ret], cpu_gpr[rs],
+                                     cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MULQ_S_PH:
+            check_dspr2(ctx);
+            gen_helper_mulq_s_ph(cpu_gpr[ret], cpu_gpr[rs],
+                                 cpu_gpr[rt], cpu_env);
+            break;
+        }
+#ifdef TARGET_MIPS64
+    case OPC_ADDU_OB_DSP:
+        switch (op2) {
+        case OPC_MULEQ_S_PW_QHL:
+            check_dsp(ctx);
+            gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], cpu_gpr[rs],
+                                      cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MULEQ_S_PW_QHR:
+            check_dsp(ctx);
+            gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], cpu_gpr[rs],
+                                      cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MULEU_S_QH_OBL:
+            check_dsp(ctx);
+            gen_helper_muleu_s_qh_obl(cpu_gpr[ret], cpu_gpr[rs],
+                                      cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MULEU_S_QH_OBR:
+            check_dsp(ctx);
+            gen_helper_muleu_s_qh_obr(cpu_gpr[ret], cpu_gpr[rs],
+                                      cpu_gpr[rt], cpu_env);
+            break;
+        case OPC_MULQ_RS_QH:
+            check_dsp(ctx);
+            gen_helper_mulq_rs_qh(cpu_gpr[ret], cpu_gpr[rs],
+                                  cpu_gpr[rt], cpu_env);
+            break;
+        }
+#endif
+        break;
+    }
+    tcg_temp_free_i32(t0);
+
+    (void)opn; /* avoid a compiler warning */
+    MIPS_DEBUG("%s", opn);
+
+}
+
 /* End MIPSDSP functions. */
 
 static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
@@ -13617,6 +14055,12 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 case OPC_SUBQH_R_W:
                     gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
                     break;
+                case OPC_MUL_PH:
+                case OPC_MUL_S_PH:
+                case OPC_MULQ_S_W:
+                case OPC_MULQ_RS_W:
+                    gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
+                    break;
                 default:
                     MIPS_INVAL("MASK ADDUH.QB");
                     generate_exception(ctx, EXCP_RI);
@@ -13693,6 +14137,14 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             case OPC_RADDU_W_QB:
                 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
                 break;
+            case OPC_MULEU_S_PH_QBL:
+            case OPC_MULEU_S_PH_QBR:
+            case OPC_MULQ_RS_PH:
+            case OPC_MULEQ_S_W_PHL:
+            case OPC_MULEQ_S_W_PHR:
+            case OPC_MULQ_S_PH:
+                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
+                break;
             default:            /* Invalid */
                 MIPS_INVAL("MASK ADDU.QB");
                 generate_exception(ctx, EXCP_RI);
@@ -13723,6 +14175,39 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_SHLL_QB_DSP:
             gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
             break;
+        case OPC_DPA_W_PH_DSP:
+            op2 = MASK_DPA_W_PH(ctx->opcode);
+            switch (op2) {
+            case OPC_DPAU_H_QBL:
+            case OPC_DPAU_H_QBR:
+            case OPC_DPSU_H_QBL:
+            case OPC_DPSU_H_QBR:
+            case OPC_DPA_W_PH:
+            case OPC_DPAX_W_PH:
+            case OPC_DPAQ_S_W_PH:
+            case OPC_DPAQX_S_W_PH:
+            case OPC_DPAQX_SA_W_PH:
+            case OPC_DPS_W_PH:
+            case OPC_DPSX_W_PH:
+            case OPC_DPSQ_S_W_PH:
+            case OPC_DPSQX_S_W_PH:
+            case OPC_DPSQX_SA_W_PH:
+            case OPC_MULSAQ_S_W_PH:
+            case OPC_DPAQ_SA_L_W:
+            case OPC_DPSQ_SA_L_W:
+            case OPC_MAQ_S_W_PHL:
+            case OPC_MAQ_S_W_PHR:
+            case OPC_MAQ_SA_W_PHL:
+            case OPC_MAQ_SA_W_PHR:
+            case OPC_MULSA_W_PH:
+                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
+                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:
@@ -13796,6 +14281,13 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             case OPC_ADDUH_R_OB:
                 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
                 break;
+            case OPC_MULEQ_S_PW_QHL:
+            case OPC_MULEQ_S_PW_QHR:
+            case OPC_MULEU_S_QH_OBL:
+            case OPC_MULEU_S_QH_OBR:
+            case OPC_MULQ_RS_QH:
+                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
+                break;
             default:            /* Invalid */
                 MIPS_INVAL("MASK ADDU.OB");
                 generate_exception(ctx, EXCP_RI);
@@ -13824,6 +14316,45 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 break;
             }
             break;
+        case OPC_DPAQ_W_QH_DSP:
+            op2 = MASK_DPAQ_W_QH(ctx->opcode);
+            switch (op2) {
+            case OPC_DPAU_H_OBL:
+            case OPC_DPAU_H_OBR:
+            case OPC_DPSU_H_OBL:
+            case OPC_DPSU_H_OBR:
+            case OPC_DPA_W_QH:
+            case OPC_DPAQ_S_W_QH:
+            case OPC_DPS_W_QH:
+            case OPC_DPSQ_S_W_QH:
+            case OPC_MULSAQ_S_W_QH:
+            case OPC_DPAQ_SA_L_PW:
+            case OPC_DPSQ_SA_L_PW:
+            case OPC_MULSAQ_S_L_PW:
+                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
+                break;
+            case OPC_MAQ_S_W_QHLL:
+            case OPC_MAQ_S_W_QHLR:
+            case OPC_MAQ_S_W_QHRL:
+            case OPC_MAQ_S_W_QHRR:
+            case OPC_MAQ_SA_W_QHLL:
+            case OPC_MAQ_SA_W_QHLR:
+            case OPC_MAQ_SA_W_QHRL:
+            case OPC_MAQ_SA_W_QHRR:
+            case OPC_MAQ_S_L_PWL:
+            case OPC_MAQ_S_L_PWR:
+            case OPC_DMADD:
+            case OPC_DMADDU:
+            case OPC_DMSUB:
+            case OPC_DMSUBU:
+                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK DPAQ.W.QH");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
         case OPC_SHLL_OB_DSP:
             gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
             break;
-- 
1.7.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 09/14] target-mips-ase-dsp: Add bit/manipulation instructions
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
                   ` (7 preceding siblings ...)
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 08/14] target-mips-ase-dsp: Add multiply instructions Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:51   ` Aurelien Jarno
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 10/14] target-mips-ase-dsp: Add compare-pick instructions Jia Liu
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 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 |   55 ++++++++++
 target-mips/helper.h     |    7 ++
 target-mips/translate.c  |  268 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 330 insertions(+)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index b98be0d..7516242 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -3186,6 +3186,61 @@ DM_OPERATE(dmsubu, mul_u32_u32, 0, 0);
 #undef DM_OPERATE
 #endif
 
+/** DSP Bit/Manipulation Sub-class insns **/
+target_ulong helper_bitrev(target_ulong rt)
+{
+    int32_t temp;
+    uint32_t rd;
+    int i;
+
+    temp = rt & MIPSDSP_LO;
+    rd = 0;
+    for (i = 0; i < 16; i++) {
+        rd = (rd << 1) | (temp & 1);
+        temp = temp >> 1;
+    }
+
+    return (target_ulong)rd;
+}
+
+#define BIT_INSV(name, posfilter, sizefilter, ret_type)         \
+target_ulong helper_##name(CPUMIPSState *env, target_ulong rs,  \
+                           target_ulong rt)                     \
+{                                                               \
+    uint32_t pos, size, msb, lsb;                               \
+    target_ulong filter;                                        \
+    target_ulong temp, temprs, temprt;                          \
+    target_ulong dspc;                                          \
+                                                                \
+    dspc = env->active_tc.DSPControl;                           \
+                                                                \
+    pos  = dspc & posfilter;                                    \
+    size = (dspc >> 7) & sizefilter;                            \
+                                                                \
+    msb  = pos + size - 1;                                      \
+    lsb  = pos;                                                 \
+                                                                \
+    if (lsb > msb || (msb > TARGET_LONG_BITS)) {                \
+        return rt;                                              \
+    }                                                           \
+                                                                \
+    filter = ((int32_t)0x01 << size) - 1;                       \
+    filter = filter << pos;                                     \
+    temprs = rs & filter;                                       \
+    temprt = rt & ~filter;                                      \
+    temp = temprs | temprt;                                     \
+                                                                \
+    return (target_long)(ret_type)temp;                         \
+}
+
+BIT_INSV(insv, 0x1F, 0x1F, int32_t);
+#ifdef TARGET_MIPS64
+BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
+#endif
+
+#undef BIT_INSV
+
+
 #undef MIPSDSP_LHI
 #undef MIPSDSP_LLO
 #undef MIPSDSP_HI
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 6a6ca99..31475a2 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -617,4 +617,11 @@ DEF_HELPER_FLAGS_4(dmsub, 0, void, tl, tl, i32, env)
 DEF_HELPER_FLAGS_4(dmsubu, 0, void, tl, tl, i32, env)
 #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 1ec6edc..d5c2419 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 */
@@ -13682,6 +13714,189 @@ static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
 
 }
 
+static void gen_mipsdsp_bitinsn(CPUMIPSState *env, DisasContext *ctx,
+                                uint32_t op1, uint32_t op2,
+                                int ret, int val)
+{
+    const char *opn = "mipsdsp Bit/ Manipulation";
+    TCGv t0 = tcg_temp_new();
+    int16_t imm;
+
+    if (ret == 0) {
+        /* Treat as NOP. */
+        MIPS_DEBUG("NOP");
+        return;
+    }
+
+    switch (op1) {
+    case OPC_ABSQ_S_PH_DSP:
+        switch (op2) {
+        case OPC_BITREV:
+            check_dsp(ctx);
+            gen_helper_bitrev(cpu_gpr[ret], cpu_gpr[val]);
+            break;
+        case OPC_REPL_QB:
+            check_dsp(ctx);
+            {
+                target_long result;
+                imm = (ctx->opcode >> 16) & 0xFF;
+                result = (uint32_t)imm << 24 | \
+                         (uint32_t)imm << 16 | \
+                         (uint32_t)imm << 8  | \
+                         (uint32_t)imm;
+#ifdef TARGET_MIPS64
+                result = (target_long)(result << 32) >> 32;
+#endif
+                tcg_gen_movi_tl(cpu_gpr[ret], result);
+            }
+            break;
+        case OPC_REPLV_QB:
+            check_dsp(ctx);
+            {
+                TCGv temp_rd;
+
+                temp_rd = tcg_temp_new();
+
+                /* we need t0 to save gpr[val] 7..0 bits. */
+                tcg_gen_ext8u_tl(t0, cpu_gpr[val]);
+                tcg_gen_mov_tl(temp_rd, t0);
+                tcg_gen_shli_tl(t0, t0, 8);
+                tcg_gen_or_tl(temp_rd, temp_rd, t0);
+                tcg_gen_mov_tl(t0, temp_rd);
+                tcg_gen_shli_tl(t0, t0, 16);
+                tcg_gen_or_tl(temp_rd, temp_rd, t0);
+#if defined(TARGET_MIPS64)
+                tcg_gen_ext32s_i64(temp_rd, temp_rd);
+#endif
+                tcg_gen_mov_tl(cpu_gpr[ret], temp_rd);
+
+                tcg_temp_free(temp_rd);
+            }
+            break;
+        case OPC_REPL_PH:
+            check_dsp(ctx);
+            {
+                imm = (ctx->opcode >> 16) & 0x03FF;
+                tcg_gen_movi_tl(cpu_gpr[ret], \
+                                (target_long)((int32_t)imm << 16 | \
+                                (uint32_t)(uint16_t)imm));
+            }
+            break;
+        case OPC_REPLV_PH:
+            check_dsp(ctx);
+            {
+                TCGv temp_rd;
+
+                temp_rd = tcg_temp_new();
+
+                tcg_gen_ext16u_tl(t0, cpu_gpr[val]);
+                tcg_gen_ext16s_tl(temp_rd, cpu_gpr[val]);
+                tcg_gen_shli_tl(temp_rd, temp_rd, 16);
+                tcg_gen_or_tl(temp_rd, temp_rd, t0);
+                tcg_gen_mov_tl(cpu_gpr[ret], temp_rd);
+
+                tcg_temp_free(temp_rd);
+            }
+            break;
+        }
+        break;
+#ifdef TARGET_MIPS64
+    case OPC_ABSQ_S_QH_DSP:
+        switch (op2) {
+        case OPC_REPL_OB:
+            check_dsp(ctx);
+            {
+                target_long temp;
+
+                imm = (ctx->opcode >> 16) & 0xFF;
+                temp = imm;
+                temp = (temp << 8) | temp;
+                temp = (temp << 16) | temp;
+                temp = (temp << 32) | temp;
+                tcg_gen_movi_tl(cpu_gpr[ret], temp);
+                break;
+            }
+        case OPC_REPL_PW:
+            check_dsp(ctx);
+            {
+                target_long temp;
+
+                imm = (ctx->opcode >> 16) & 0x03FF;
+                imm = (int16_t)(imm << 6) >> 6;
+                temp = ((target_long)imm << 32) \
+                       | ((target_long)imm & 0xFFFFFFFF);
+                tcg_gen_movi_tl(cpu_gpr[ret], temp);
+                break;
+            }
+        case OPC_REPL_QH:
+            check_dsp(ctx);
+            {
+                target_long temp;
+
+                imm = (ctx->opcode >> 16) & 0x03FF;
+                imm = (int16_t)(imm << 6) >> 6;
+
+                temp = ((uint64_t)(uint16_t)imm << 48) | \
+                       ((uint64_t)(uint16_t)imm << 32) | \
+                       ((uint64_t)(uint16_t)imm << 16) | \
+                       (uint64_t)(uint16_t)imm;
+                tcg_gen_movi_tl(cpu_gpr[ret], temp);
+                break;
+            }
+        case OPC_REPLV_OB:
+            check_dsp(ctx);
+            {
+                TCGv temp_rd;
+
+                temp_rd = tcg_temp_new();
+
+                tcg_gen_ext8u_tl(t0, cpu_gpr[val]);
+                tcg_gen_mov_tl(temp_rd, t0);
+                tcg_gen_shli_tl(temp_rd, temp_rd, 8);
+                tcg_gen_or_tl(temp_rd, temp_rd, t0);
+                tcg_gen_mov_tl(t0, temp_rd);
+                tcg_gen_shli_tl(temp_rd, temp_rd, 16);
+                tcg_gen_or_tl(temp_rd, temp_rd, t0);
+                tcg_gen_concat_tl_i64(temp_rd, temp_rd, temp_rd);
+
+                gen_store_gpr(temp_rd, ret);
+
+                tcg_temp_free(temp_rd);
+                break;
+            }
+        case OPC_REPLV_PW:
+            check_dsp(ctx);
+            {
+                tcg_gen_ext32u_i64(t0, cpu_gpr[val]);
+                tcg_gen_concat_tl_i64(cpu_gpr[ret], t0, t0);
+                break;
+            }
+        case OPC_REPLV_QH:
+            check_dsp(ctx);
+            {
+                TCGv temp_rd;
+
+                temp_rd = tcg_temp_new();
+
+                tcg_gen_ext16u_tl(t0, cpu_gpr[val]);
+                tcg_gen_mov_tl(temp_rd, t0);
+                tcg_gen_shli_tl(temp_rd, temp_rd, 16);
+                tcg_gen_or_tl(temp_rd, temp_rd, t0);
+                tcg_gen_concat_tl_i64(cpu_gpr[ret], temp_rd, temp_rd);
+
+                tcg_temp_free(temp_rd);
+                break;
+            }
+        }
+        break;
+#endif
+    }
+    tcg_temp_free(t0);
+
+    (void)opn; /* avoid a compiler warning */
+    MIPS_DEBUG("%s", opn);
+}
+
 /* End MIPSDSP functions. */
 
 static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
@@ -14108,6 +14323,13 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             case OPC_PRECEU_PH_QBRA:
                 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
                 break;
+            case OPC_BITREV:
+            case OPC_REPL_QB:
+            case OPC_REPLV_QB:
+            case OPC_REPL_PH:
+            case OPC_REPLV_PH:
+                gen_mipsdsp_bitinsn(env, ctx, op1, op2, rd, rt);
+                break;
             default:
                 MIPS_INVAL("MASK ABSQ_S.PH");
                 generate_exception(ctx, EXCP_RI);
@@ -14208,6 +14430,26 @@ 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_dsp(ctx);
+                {
+                    if (rt == 0) {
+                        MIPS_DEBUG("NOP");
+                        break;
+                    }
+                    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:
@@ -14249,6 +14491,14 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             case OPC_ABSQ_S_QH:
                 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
                 break;
+            case OPC_REPL_OB:
+            case OPC_REPL_PW:
+            case OPC_REPL_QH:
+            case OPC_REPLV_OB:
+            case OPC_REPLV_PW:
+            case OPC_REPLV_QH:
+                gen_mipsdsp_bitinsn(env, ctx, op1, op2, rd, rt);
+                break;
             default:            /* Invalid */
                 MIPS_INVAL("MASK ABSQ_S.QH");
                 generate_exception(ctx, EXCP_RI);
@@ -14355,6 +14605,24 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 break;
             }
             break;
+        case OPC_DINSV_DSP:
+            op2 = MASK_INSV(ctx->opcode);
+            switch (op2) {
+            case OPC_DINSV:
+                check_dsp(ctx);
+                if (rt == 0) {
+                    MIPS_DEBUG("NOP");
+                    break;
+                }
+                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;
         case OPC_SHLL_OB_DSP:
             gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
             break;
-- 
1.7.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 10/14] target-mips-ase-dsp: Add compare-pick instructions
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
                   ` (8 preceding siblings ...)
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 09/14] target-mips-ase-dsp: Add bit/manipulation instructions Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:51   ` Aurelien Jarno
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 11/14] target-mips-ase-dsp: Add DSP accumulator instructions Jia Liu
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 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 |  235 ++++++++++++++++++++++++++++++
 target-mips/helper.h     |   52 +++++++
 target-mips/translate.c  |  356 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 643 insertions(+)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 7516242..dabece4 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -3241,6 +3241,241 @@ BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
 #undef BIT_INSV
 
 
+/** DSP Compare-Pick Sub-class insns **/
+#define CMP_HAS_RET(name, func, split_num, filter, bit_size) \
+target_ulong helper_##name(target_ulong rs, target_ulong rt) \
+{                                                       \
+    uint32_t rs_t[split_num];                            \
+    uint32_t rt_t[split_num];                            \
+    uint8_t cc[split_num];                              \
+    uint32_t temp = 0;                                  \
+    int i;                                              \
+                                                        \
+    for (i = 0; i < split_num; i++) {                   \
+        rs_t[i] = (rs >> (bit_size * i)) & filter;      \
+        rt_t[i] = (rt >> (bit_size * i)) & filter;      \
+        cc[i] = mipsdsp_##func(rs_t[i], rt_t[i]);       \
+        temp |= cc[i] << i;                             \
+    }                                                   \
+                                                         \
+    return (target_ulong)temp;                          \
+}
+
+CMP_HAS_RET(cmpgu_eq_qb, cmp_eq, 4, MIPSDSP_Q0, 8);
+CMP_HAS_RET(cmpgu_lt_qb, cmp_lt, 4, MIPSDSP_Q0, 8);
+CMP_HAS_RET(cmpgu_le_qb, cmp_le, 4, MIPSDSP_Q0, 8);
+
+#ifdef TARGET_MIPS64
+CMP_HAS_RET(cmpgu_eq_ob, cmp_eq, 8, MIPSDSP_Q0, 8);
+CMP_HAS_RET(cmpgu_lt_ob, cmp_lt, 8, MIPSDSP_Q0, 8);
+CMP_HAS_RET(cmpgu_le_ob, cmp_le, 8, MIPSDSP_Q0, 8);
+#endif
+
+#undef CMP_HAS_RET
+
+
+#define CMP_NO_RET(name, func, split_num, filter, bit_size)   \
+void helper_##name(target_ulong rs, target_ulong rt,      \
+                            CPUMIPSState *env)            \
+{                                                         \
+    int32_t rs_t[split_num], rt_t[split_num];             \
+    int32_t flag = 0;                                     \
+    int32_t cc[split_num];                                \
+    int i;                                                \
+                                                          \
+    for (i = 0; i < split_num; i++) {                     \
+        rs_t[i] = (rs >> (bit_size * i)) & filter;        \
+        rt_t[i] = (rt >> (bit_size * i)) & filter;        \
+                                                          \
+        cc[i] = mipsdsp_##func(rs_t[i], rt_t[i]);         \
+        flag |= cc[i] << i;                               \
+    }                                                     \
+                                                          \
+    set_DSPControl_24(flag, split_num, env);              \
+}
+
+CMP_NO_RET(cmpu_eq_qb, cmp_eq, 4, MIPSDSP_Q0, 8);
+CMP_NO_RET(cmpu_lt_qb, cmp_lt, 4, MIPSDSP_Q0, 8);
+CMP_NO_RET(cmpu_le_qb, cmp_le, 4, MIPSDSP_Q0, 8);
+
+CMP_NO_RET(cmp_eq_ph, cmp_eq, 2, MIPSDSP_LO, 16);
+CMP_NO_RET(cmp_lt_ph, cmp_lt, 2, MIPSDSP_LO, 16);
+CMP_NO_RET(cmp_le_ph, cmp_le, 2, MIPSDSP_LO, 16);
+
+#ifdef TARGET_MIPS64
+CMP_NO_RET(cmpu_eq_ob, cmp_eq, 8, MIPSDSP_Q0, 8);
+CMP_NO_RET(cmpu_lt_ob, cmp_lt, 8, MIPSDSP_Q0, 8);
+CMP_NO_RET(cmpu_le_ob, cmp_le, 8, MIPSDSP_Q0, 8);
+
+CMP_NO_RET(cmp_eq_qh, cmp_eq, 4, MIPSDSP_LO, 16);
+CMP_NO_RET(cmp_lt_qh, cmp_lt, 4, MIPSDSP_LO, 16);
+CMP_NO_RET(cmp_le_qh, cmp_le, 4, MIPSDSP_LO, 16);
+
+CMP_NO_RET(cmp_eq_pw, cmp_eq, 2, MIPSDSP_LLO, 32);
+CMP_NO_RET(cmp_lt_pw, cmp_lt, 2, MIPSDSP_LLO, 32);
+CMP_NO_RET(cmp_le_pw, cmp_le, 2, MIPSDSP_LLO, 32);
+#endif
+#undef CMP_NO_RET
+
+#if defined(TARGET_MIPS64)
+
+#define CMPGDU_OB(name) \
+target_ulong helper_cmpgdu_##name##_ob(target_ulong rs, target_ulong rt, \
+                                       CPUMIPSState *env)  \
+{                                                     \
+    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 (mipsdsp_cmp_##name(rs_t[i], rt_t[i])) {   \
+            cond |= 0x01 << i;                        \
+        }                                             \
+    }                                                 \
+                                                      \
+    set_DSPControl_24(cond, 8, env);                  \
+                                                      \
+    return (uint64_t)cond;                            \
+}
+
+CMPGDU_OB(eq)
+CMPGDU_OB(lt)
+CMPGDU_OB(le)
+#undef CMPGDU_OB
+#endif
+
+#define PICK_INSN(name, split_num, filter, bit_size, ret32bit) \
+target_ulong helper_##name(target_ulong rs, target_ulong rt,   \
+                            CPUMIPSState *env)                 \
+{                                                              \
+    uint32_t rs_t[split_num];                                  \
+    uint32_t rt_t[split_num];                                  \
+    uint32_t cc[split_num];                                    \
+    target_ulong dsp;                                          \
+    int i;                                                     \
+    target_ulong result = 0;                                   \
+                                                               \
+    dsp = env->active_tc.DSPControl;                           \
+    for (i = 0; i < split_num; i++) {                          \
+        rs_t[i] = (rs >> (bit_size * i)) & filter;             \
+        rt_t[i] = (rt >> (bit_size * i)) & filter;             \
+        cc[i] = (dsp >> (24 + i)) & 0x01;                      \
+        cc[i] = cc[i] == 1 ? rs_t[i] : rt_t[i];                \
+                                                               \
+        result |= (target_ulong)cc[i] << (bit_size * i);       \
+    }                                                          \
+                                                               \
+    if (ret32bit) {                                            \
+        result = (target_long)(int32_t)(result & MIPSDSP_LLO); \
+    }                                                          \
+                                                               \
+    return result;                                             \
+}
+
+PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1);
+PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1);
+
+#ifdef TARGET_MIPS64
+PICK_INSN(pick_ob, 8, MIPSDSP_Q0, 8, 0);
+PICK_INSN(pick_qh, 4, MIPSDSP_LO, 16, 0);
+PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0);
+#endif
+#undef PICK_INSN
+
+#define APPEND_INSN(name, ret_32) \
+target_ulong helper_##name(target_ulong rt, target_ulong rs, uint32_t sa) \
+{                                                                         \
+    target_ulong temp;                                                    \
+                                                                          \
+    if (ret_32) {                                                         \
+        temp = ((rt & MIPSDSP_LLO) << sa) |                               \
+               ((rs & MIPSDSP_LLO) & ((0x01 << sa) - 1));                 \
+        temp = (target_long)(int32_t)(temp & MIPSDSP_LLO);                \
+    } else {                                                              \
+        temp = (rt << sa) | (rs & ((0x01 << sa) - 1));                    \
+    }                                                                     \
+                                                                          \
+    return temp;                                                          \
+}
+
+APPEND_INSN(append, 1);
+#ifdef TARGET_MIPS64
+APPEND_INSN(dappend, 0);
+#endif
+#undef APPEND_INSN
+
+#define PREPEND_INSN(name, or_val, ret_32)                    \
+target_ulong helper_##name(target_ulong rs, target_ulong rt,  \
+                           uint32_t sa)                       \
+{                                                             \
+    sa |= or_val;                                             \
+                                                              \
+    if (1) {                                                  \
+        return (target_long)(int32_t)(uint32_t)               \
+            (((rs & MIPSDSP_LLO) << (32 - sa)) |              \
+             ((rt & MIPSDSP_LLO) >> sa));                     \
+    } else {                                                  \
+        return (rs << (64 - sa)) | (rt >> sa);                \
+    }                                                         \
+}
+
+PREPEND_INSN(prepend, 0, 1);
+#ifdef TARGET_MIPS64
+PREPEND_INSN(prependw, 0, 0);
+PREPEND_INSN(prependd, 0x20, 0);
+#endif
+#undef PREPEND_INSN
+
+#define BALIGN_INSN(name, filter, ret32) \
+target_ulong helper_##name(target_ulong rs, target_ulong rt, uint32_t bp) \
+{                                                                         \
+    bp = bp & 0x03;                                                       \
+                                                                          \
+    if ((bp & 1) == 0) {                                                  \
+        return rt;                                                        \
+    } else {                                                              \
+        if (ret32) {                                                      \
+            return (target_long)(int32_t)((rt << (8 * bp)) |              \
+                                          (rs >> (8 * (4 - bp))));        \
+        } else {                                                          \
+            return (rt << (8 * bp)) | (rs >> (8 * (8 - bp)));             \
+        }                                                                 \
+    }                                                                     \
+}
+
+BALIGN_INSN(balign, 0x03, 1);
+#if defined(TARGET_MIPS64)
+BALIGN_INSN(dbalign, 0x07, 0);
+#endif
+#undef BALIGN_INSN
+
+target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt)
+{
+    uint32_t rsl, rth;
+
+    rsl =  rs & MIPSDSP_LO;
+    rth = (rt & MIPSDSP_HI) >> 16;
+
+    return (target_long)(int32_t)((rsl << 16) | rth);
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt)
+{
+    uint32_t rs0, rt1;
+
+    rs0 = rs & MIPSDSP_LLO;
+    rt1 = (rt >> 32) & MIPSDSP_LLO;
+
+    return ((uint64_t)rs0 << 32) | (uint64_t)rt1;
+}
+#endif
+
 #undef MIPSDSP_LHI
 #undef MIPSDSP_LLO
 #undef MIPSDSP_HI
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 31475a2..3d3c596 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -624,4 +624,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, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmpu_lt_qb, 0, void, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmpu_le_qb, 0, void, tl, tl, env)
+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, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmp_lt_ph, 0, void, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmp_le_ph, 0, void, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(cmpu_eq_ob, 0, void, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmpu_lt_ob, 0, void, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmpu_le_ob, 0, void, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmpgdu_eq_ob, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmpgdu_lt_ob, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmpgdu_le_ob, 0, tl, tl, tl, env)
+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, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmp_lt_qh, 0, void, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmp_le_qh, 0, void, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmp_eq_pw, 0, void, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmp_lt_pw, 0, void, tl, tl, env)
+DEF_HELPER_FLAGS_3(cmp_le_pw, 0, void, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(pick_qb, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(pick_ph, 0, tl, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(pick_ob, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(pick_qh, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(pick_pw, 0, tl, tl, tl, env)
+#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, tl, tl, i32)
+#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, tl, tl, i32)
+#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 d5c2419..7102074 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 */
@@ -13897,6 +13957,250 @@ static void gen_mipsdsp_bitinsn(CPUMIPSState *env, DisasContext *ctx,
     MIPS_DEBUG("%s", opn);
 }
 
+static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
+                                     uint32_t op1, uint32_t op2,
+                                     int ret, int v1, int v2, int check_ret)
+{
+    const char *opn = "mipsdsp add compare pick";
+    TCGv_i32 t0 = tcg_temp_new_i32();
+    TCGv t1 = tcg_temp_new();
+
+    if ((ret == 0) && (check_ret == 1)) {
+        /* Treat as NOP. */
+        MIPS_DEBUG("NOP");
+        return;
+    }
+
+    switch (op1) {
+    case OPC_APPEND_DSP:
+        switch (op2) {
+        case OPC_APPEND:
+            tcg_gen_movi_i32(t0, v2);
+            gen_helper_append(cpu_gpr[ret], cpu_gpr[ret],
+                              cpu_gpr[v1], t0);
+            break;
+        case OPC_PREPEND:
+            tcg_gen_movi_i32(t0, v2);
+            gen_helper_prepend(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[ret], t0);
+            break;
+        case OPC_BALIGN:
+            tcg_gen_movi_i32(t0, v2);
+                gen_helper_balign(cpu_gpr[ret], cpu_gpr[v1],
+                                  cpu_gpr[ret], t0);
+                break;
+        default:            /* Invid */
+            MIPS_INVAL("MASK APPEND");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
+        break;
+    case OPC_CMPU_EQ_QB_DSP:
+        switch (op2) {
+        case OPC_CMPU_EQ_QB:
+            check_dsp(ctx);
+            gen_helper_cmpu_eq_qb(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMPU_LT_QB:
+            check_dsp(ctx);
+            gen_helper_cmpu_lt_qb(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMPU_LE_QB:
+            check_dsp(ctx);
+            gen_helper_cmpu_le_qb(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMPGU_EQ_QB:
+            check_dsp(ctx);
+            gen_helper_cmpgu_eq_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_CMPGU_LT_QB:
+            check_dsp(ctx);
+            gen_helper_cmpgu_lt_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_CMPGU_LE_QB:
+            check_dsp(ctx);
+            gen_helper_cmpgu_le_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_CMPGDU_EQ_QB:
+            check_dspr2(ctx);
+            gen_helper_cmpgu_eq_qb(t1, cpu_gpr[v1], cpu_gpr[v2]);
+            tcg_gen_mov_tl(cpu_gpr[ret], t1);
+            tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
+            tcg_gen_shli_tl(t1, t1, 24);
+            tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
+            break;
+        case OPC_CMPGDU_LT_QB:
+            check_dspr2(ctx);
+            gen_helper_cmpgu_lt_qb(t1, cpu_gpr[v1], cpu_gpr[v2]);
+            tcg_gen_mov_tl(cpu_gpr[ret], t1);
+            tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
+            tcg_gen_shli_tl(t1, t1, 24);
+            tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
+            break;
+        case OPC_CMPGDU_LE_QB:
+            check_dspr2(ctx);
+            gen_helper_cmpgu_le_qb(t1, cpu_gpr[v1], cpu_gpr[v2]);
+            tcg_gen_mov_tl(cpu_gpr[ret], t1);
+            tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
+            tcg_gen_shli_tl(t1, t1, 24);
+            tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
+            break;
+        case OPC_CMP_EQ_PH:
+            check_dsp(ctx);
+            gen_helper_cmp_eq_ph(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMP_LT_PH:
+            check_dsp(ctx);
+            gen_helper_cmp_lt_ph(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMP_LE_PH:
+            check_dsp(ctx);
+            gen_helper_cmp_le_ph(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_PICK_QB:
+            check_dsp(ctx);
+            gen_helper_pick_qb(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_PICK_PH:
+            check_dsp(ctx);
+            gen_helper_pick_ph(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_PACKRL_PH:
+            check_dsp(ctx);
+            gen_helper_packrl_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        }
+        break;
+#ifdef TARGET_MIPS64
+    case OPC_CMPU_EQ_OB_DSP:
+        switch (op2) {
+        case OPC_CMP_EQ_PW:
+            check_dsp(ctx);
+            gen_helper_cmp_eq_pw(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMP_LT_PW:
+            check_dsp(ctx);
+            gen_helper_cmp_lt_pw(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMP_LE_PW:
+            check_dsp(ctx);
+            gen_helper_cmp_le_pw(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMP_EQ_QH:
+            check_dsp(ctx);
+            gen_helper_cmp_eq_qh(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMP_LT_QH:
+            check_dsp(ctx);
+            gen_helper_cmp_lt_qh(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMP_LE_QH:
+            check_dsp(ctx);
+            gen_helper_cmp_le_qh(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMPGDU_EQ_OB:
+            check_dspr2(ctx);
+            gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], cpu_gpr[v1],
+                                    cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMPGDU_LT_OB:
+            check_dspr2(ctx);
+            gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], cpu_gpr[v1],
+                                    cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMPGDU_LE_OB:
+            check_dspr2(ctx);
+            gen_helper_cmpgdu_le_ob(cpu_gpr[ret], cpu_gpr[v1],
+                                    cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMPGU_EQ_OB:
+            check_dsp(ctx);
+            gen_helper_cmpgu_eq_ob(cpu_gpr[ret], cpu_gpr[v1],
+                                   cpu_gpr[v2]);
+            break;
+        case OPC_CMPGU_LT_OB:
+            check_dsp(ctx);
+            gen_helper_cmpgu_lt_ob(cpu_gpr[ret], cpu_gpr[v1],
+                                   cpu_gpr[v2]);
+            break;
+        case OPC_CMPGU_LE_OB:
+            check_dsp(ctx);
+            gen_helper_cmpgu_le_ob(cpu_gpr[ret], cpu_gpr[v1],
+                                   cpu_gpr[v2]);
+            break;
+        case OPC_CMPU_EQ_OB:
+            check_dsp(ctx);
+            gen_helper_cmpu_eq_ob(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMPU_LT_OB:
+            check_dsp(ctx);
+            gen_helper_cmpu_lt_ob(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_CMPU_LE_OB:
+            check_dsp(ctx);
+            gen_helper_cmpu_le_ob(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_PACKRL_PW:
+            check_dsp(ctx);
+            gen_helper_packrl_pw(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
+            break;
+        case OPC_PICK_OB:
+            check_dsp(ctx);
+            gen_helper_pick_ob(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_PICK_PW:
+            check_dsp(ctx);
+            gen_helper_pick_pw(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        case OPC_PICK_QH:
+            check_dsp(ctx);
+            gen_helper_pick_qh(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[v2], cpu_env);
+            break;
+        }
+        break;
+    case OPC_DAPPEND_DSP:
+        switch (op2) {
+        case OPC_DAPPEND:
+            tcg_gen_movi_i32(t0, v2);
+            gen_helper_dappend(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[ret], t0);
+            break;
+        case OPC_PREPENDD:
+            tcg_gen_movi_i32(t0, v2);
+            gen_helper_prependd(cpu_gpr[ret], cpu_gpr[v1],
+                                cpu_gpr[ret], t0);
+            break;
+        case OPC_PREPENDW:
+            tcg_gen_movi_i32(t0, v2);
+            gen_helper_prependw(cpu_gpr[ret], cpu_gpr[v1],
+                                cpu_gpr[ret], t0);
+            break;
+        case OPC_DBALIGN:
+            tcg_gen_movi_i32(t0, v2);
+            gen_helper_dbalign(cpu_gpr[ret], cpu_gpr[v1],
+                               cpu_gpr[ret], t0);
+            break;
+        default:            /* Invalid */
+            MIPS_INVAL("MASK DAPPEND");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
+        break;
+#endif
+    }
+
+    tcg_temp_free_i32(t0);
+    tcg_temp_free(t1);
+
+    (void)opn; /* avoid a compiler warning */
+    MIPS_DEBUG("%s", opn);
+}
+
 /* End MIPSDSP functions. */
 
 static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
@@ -14388,6 +14692,25 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             case OPC_PRECRQU_S_QB_PH:
                 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
                 break;
+            case OPC_CMPU_EQ_QB:
+            case OPC_CMPU_LT_QB:
+            case OPC_CMPU_LE_QB:
+            case OPC_CMP_EQ_PH:
+            case OPC_CMP_LT_PH:
+            case OPC_CMP_LE_PH:
+                gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
+                break;
+            case OPC_CMPGU_EQ_QB:
+            case OPC_CMPGU_LT_QB:
+            case OPC_CMPGU_LE_QB:
+            case OPC_CMPGDU_EQ_QB:
+            case OPC_CMPGDU_LT_QB:
+            case OPC_CMPGDU_LE_QB:
+            case OPC_PICK_QB:
+            case OPC_PICK_PH:
+            case OPC_PACKRL_PH:
+                gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
+                break;
             default:            /* Invalid */
                 MIPS_INVAL("MASK CMPU.EQ.QB");
                 generate_exception(ctx, EXCP_RI);
@@ -14450,6 +14773,11 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 break;
             }
             break;
+        case OPC_APPEND_DSP:
+            check_dspr2(ctx);
+            op2 = MASK_APPEND(ctx->opcode);
+            gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
+            break;
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
@@ -14560,12 +14888,40 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             case OPC_PRECRQU_S_OB_QH:
                 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
                 break;
+            case OPC_CMPU_EQ_OB:
+            case OPC_CMPU_LT_OB:
+            case OPC_CMPU_LE_OB:
+            case OPC_CMP_EQ_QH:
+            case OPC_CMP_LT_QH:
+            case OPC_CMP_LE_QH:
+            case OPC_CMP_EQ_PW:
+            case OPC_CMP_LT_PW:
+            case OPC_CMP_LE_PW:
+                gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
+                break;
+            case OPC_CMPGDU_EQ_OB:
+            case OPC_CMPGDU_LT_OB:
+            case OPC_CMPGDU_LE_OB:
+            case OPC_CMPGU_EQ_OB:
+            case OPC_CMPGU_LT_OB:
+            case OPC_CMPGU_LE_OB:
+            case OPC_PACKRL_PW:
+            case OPC_PICK_OB:
+            case OPC_PICK_PW:
+            case OPC_PICK_QH:
+                gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
+                break;
             default:            /* Invalid */
                 MIPS_INVAL("MASK CMPU_EQ.OB");
                 generate_exception(ctx, EXCP_RI);
                 break;
             }
             break;
+        case OPC_DAPPEND_DSP:
+            check_dspr2(ctx);
+            op2 = MASK_DAPPEND(ctx->opcode);
+            gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
+            break;
         case OPC_DPAQ_W_QH_DSP:
             op2 = MASK_DPAQ_W_QH(ctx->opcode);
             switch (op2) {
-- 
1.7.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 11/14] target-mips-ase-dsp: Add DSP accumulator instructions
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
                   ` (9 preceding siblings ...)
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 10/14] target-mips-ase-dsp: Add compare-pick instructions Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:51   ` Aurelien Jarno
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 12/14] target-mips-ase-dsp: Add MIPS DSP processors Jia Liu
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 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 |  609 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/helper.h     |   35 +++
 target-mips/translate.c  |  340 ++++++++++++++++++++++++++
 3 files changed, 984 insertions(+)

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index dabece4..6ff063b 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -3476,6 +3476,615 @@ 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(target_ulong ac, target_ulong shift,
+                           CPUMIPSState *env)
+{
+    int32_t tempI;
+    int64_t tempDL[2];
+
+    shift = shift & 0x0F;
+
+    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(1, 23, env);
+    }
+
+    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(1, 23, env);
+    }
+
+    return (target_long)tempI;
+}
+
+target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
+                             CPUMIPSState *env)
+{
+    int64_t tempDL[2];
+
+    shift = shift & 0x0F;
+
+    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(1, 23, env);
+    }
+
+    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(1, 23, env);
+    }
+
+    return (target_long)(int32_t)(tempDL[0] >> 1);
+}
+
+target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
+                              CPUMIPSState *env)
+{
+    int32_t tempI, temp64;
+    int64_t tempDL[2];
+
+    shift = shift & 0x0F;
+
+    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
+    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        set_DSPControl_overflow_flag(1, 23, env);
+    }
+    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(1, 23, env);
+    }
+
+    return (target_long)tempI;
+}
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dextr_w(target_ulong ac, target_ulong shift,
+                            CPUMIPSState *env)
+{
+    uint64_t temp[3];
+
+    shift = shift & 0x3F;
+
+    mipsdsp_rndrashift_acc(temp, ac, shift, env);
+
+    return (int64_t)(int32_t)(temp[0] >> 1);
+}
+
+target_ulong helper_dextr_r_w(target_ulong ac, target_ulong shift,
+                              CPUMIPSState *env)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+
+    shift = shift & 0x3F;
+    mipsdsp_rndrashift_acc(temp, ac, shift, env);
+
+    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] != ~0ull)) {
+        set_DSPControl_overflow_flag(1, 23, env);
+    }
+
+    return (int64_t)(int32_t)(temp[0] >> 1);
+}
+
+target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift,
+                               CPUMIPSState *env)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+
+    shift = shift & 0x3F;
+    mipsdsp_rndrashift_acc(temp, ac, shift, env);
+
+    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] != ~0ull)) {
+        if (temp128 == 0) {
+            temp[0] = 0x0FFFFFFFF;
+        } else {
+            temp[0] = 0x0100000000;
+        }
+        set_DSPControl_overflow_flag(1, 23, env);
+    }
+
+    return (int64_t)(int32_t)(temp[0] >> 1);
+}
+
+target_ulong helper_dextr_l(target_ulong ac, target_ulong shift,
+                            CPUMIPSState *env)
+{
+    uint64_t temp[3];
+    target_ulong result;
+
+    shift = shift & 0x3F;
+
+    mipsdsp_rndrashift_acc(temp, ac, shift, env);
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift,
+                              CPUMIPSState *env)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    target_ulong result;
+
+    shift = shift & 0x3F;
+    mipsdsp_rndrashift_acc(temp, ac, shift, env);
+
+    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] != ~0ull)) {
+        set_DSPControl_overflow_flag(1, 23, env);
+    }
+
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+
+target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift,
+                               CPUMIPSState *env)
+{
+    uint64_t temp[3];
+    uint32_t temp128;
+    target_ulong result;
+
+    shift = shift & 0x3F;
+    mipsdsp_rndrashift_acc(temp, ac, shift, env);
+
+    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] != ~0ull)) {
+        if (temp128 == 0) {
+            temp[1] &= 0xFFFFFFFFFFFFFFFEull;
+            temp[0] |= 0xFFFFFFFFFFFFFFFEull;
+        } else {
+            temp[1] |= 0x01;
+            temp[0] &= 0x01;
+        }
+        set_DSPControl_overflow_flag(1, 23, env);
+    }
+    result = (temp[1] << 63) | (temp[0] >> 1);
+
+    return result;
+}
+#endif
+
+target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift,
+                             CPUMIPSState *env)
+{
+    int64_t temp;
+
+    shift = shift & 0x0F;
+
+    temp = mipsdsp_rashift_short_acc(ac, shift, env);
+    if (temp > 0x0000000000007FFFull) {
+        temp = 0x00007FFF;
+        set_DSPControl_overflow_flag(1, 23, env);
+    } else if (temp < 0xFFFFFFFFFFFF8000ull) {
+        temp = 0xFFFF8000;
+        set_DSPControl_overflow_flag(1, 23, env);
+    }
+
+    return (target_long)(int32_t)(temp & 0xFFFFFFFF);
+}
+
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dextr_s_h(target_ulong ac, target_ulong shift,
+                              CPUMIPSState *env)
+{
+    int64_t temp[2];
+    uint32_t temp127;
+
+    shift = shift & 0x1F;
+
+    mipsdsp_rashift_acc((uint64_t *)temp, ac, shift, env);
+
+    temp127 = (temp[1] >> 63) & 0x01;
+
+    if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) {
+        temp[0] &= 0xFFFF0000;
+        temp[0] |= 0x00007FFF;
+        set_DSPControl_overflow_flag(1, 23, env);
+    } else if ((temp127 == 1) &&
+            (temp[1] < 0xFFFFFFFFFFFFFFFFll
+             || temp[0] < 0xFFFFFFFFFFFF1000ll)) {
+        temp[0] &= 0xFFFF0000;
+        temp[0] |= 0x00008000;
+        set_DSPControl_overflow_flag(1, 23, env);
+    }
+
+    return (int64_t)(int16_t)(temp[0] & MIPSDSP_LO);
+}
+
+#endif
+
+target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState *env)
+{
+    int32_t start_pos;
+    int sub;
+    uint32_t temp;
+    uint64_t acc;
+
+    size = size & 0x1F;
+
+    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(0, env);
+    } else {
+        set_DSPControl_efi(1, env);
+    }
+
+    return (target_ulong)temp;
+}
+
+target_ulong helper_extpdp(target_ulong ac, target_ulong size,
+                           CPUMIPSState *env)
+{
+    int32_t start_pos;
+    int sub;
+    uint32_t temp;
+    uint64_t acc;
+
+    size = size & 0x1F;
+    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(start_pos - (size + 1), env);
+        set_DSPControl_efi(0, env);
+    } else {
+        set_DSPControl_efi(1, env);
+    }
+
+    return (target_ulong)temp;
+}
+
+
+#if defined(TARGET_MIPS64)
+target_ulong helper_dextp(target_ulong ac, target_ulong size, CPUMIPSState *env)
+{
+    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(0, env);
+    } else {
+        set_DSPControl_efi(1, env);
+    }
+
+    return temp;
+}
+
+target_ulong helper_dextpdp(target_ulong ac, target_ulong size,
+                            CPUMIPSState *env)
+{
+    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_pos(sub, env);
+        set_DSPControl_efi(0, env);
+    } else {
+        set_DSPControl_efi(1, env);
+    }
+
+    return temp;
+}
+
+#endif
+
+void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env)
+{
+    int8_t  rs5_0;
+    uint64_t temp, acc;
+
+    rs5_0 = rs & 0x3F;
+    rs5_0 = (int8_t)(rs5_0 << 2) >> 2;
+    rs5_0 = MIPSDSP_ABS(rs5_0);
+    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 (rs5_0 > 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(target_ulong shift, target_ulong ac, CPUMIPSState *env)
+{
+    int8_t shift_t;
+    uint64_t tempB, tempA;
+
+    shift_t = (uint8_t)(shift << 1) >> 1;
+    shift_t = MIPSDSP_ABS(shift_t);
+
+    tempB = env->active_tc.HI[ac];
+    tempA = env->active_tc.LO[ac];
+
+    if (shift_t != 0) {
+        if (shift_t >= 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(target_ulong ac, target_ulong rs, CPUMIPSState *env)
+{
+    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(pos + 32, env);
+    }
+}
+
+#if defined(TARGET_MIPS64)
+void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env)
+{
+    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(pos, env);
+    }
+}
+#endif
+
+void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
+{
+    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(target_ulong masknum, CPUMIPSState *env)
+{
+    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 3d3c596..45af62f 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -676,4 +676,39 @@ 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, tl, tl, env)
+DEF_HELPER_FLAGS_3(extr_r_w, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(extr_rs_w, 0, tl, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dextr_w, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(dextr_r_w, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(dextr_rs_w, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(dextr_l, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(dextr_r_l, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(dextr_rs_l, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(extr_s_h, 0, tl, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dextr_s_h, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(extp, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(extpdp, 0, tl, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dextp, 0, tl, tl, tl, env)
+DEF_HELPER_FLAGS_3(dextpdp, 0, tl, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(shilo, 0, void, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dshilo, 0, void, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(mthlip, 0, void, tl, tl, env)
+#if defined(TARGET_MIPS64)
+DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env)
+#endif
+DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env)
+DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env)
+
+
+
 #include "def-helper.h"
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 7102074..fc034b8 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,30 @@ 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 +705,32 @@ 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,
+};
+
 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
     /* DSP Bit/Manipulation Sub-class */
@@ -14201,6 +14256,225 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
     MIPS_DEBUG("%s", opn);
 }
 
+static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
+                                int ret, int v1, int v2, int check_ret)
+
+{
+    const char *opn = "mipsdsp accumulator";
+    TCGv t0 = tcg_temp_new();
+    TCGv t1 = tcg_temp_new();
+    int16_t imm;
+
+    if ((ret == 0) && (check_ret == 1)) {
+        /* Treat as NOP. */
+        MIPS_DEBUG("NOP");
+        return;
+    }
+
+    switch (op1) {
+    case OPC_EXTR_W_DSP:
+        check_dsp(ctx);
+        switch (op2) {
+        case OPC_EXTR_W:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_EXTR_R_W:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_EXTR_RS_W:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_EXTR_S_H:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_EXTRV_S_H:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_extr_s_h(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_EXTRV_W:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_extr_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_EXTRV_R_W:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_extr_r_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_EXTRV_RS_W:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_extr_rs_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_EXTP:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_EXTPV:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_extp(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_EXTPDP:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_EXTPDPV:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_extpdp(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_SHILO:
+            imm = (ctx->opcode >> 20) & 0x3F;
+            tcg_gen_movi_tl(t0, ret);
+            tcg_gen_movi_tl(t1, imm);
+            gen_helper_shilo(t0, t1, cpu_env);
+            break;
+        case OPC_SHILOV:
+            tcg_gen_movi_tl(t0, ret);
+            gen_helper_shilo(t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_MTHLIP:
+            tcg_gen_movi_tl(t0, ret);
+            gen_helper_mthlip(t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_WRDSP:
+            imm = (ctx->opcode >> 11) & 0x3FF;
+            tcg_gen_movi_tl(t0, imm);
+            gen_helper_wrdsp(cpu_gpr[v1], t0, cpu_env);
+            break;
+        case OPC_RDDSP:
+            imm = (ctx->opcode >> 16) & 0x03FF;
+            tcg_gen_movi_tl(t0, imm);
+            gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
+            break;
+        }
+        break;
+#ifdef TARGET_MIPS64
+    case OPC_DEXTR_W_DSP:
+        check_dsp(ctx);
+        switch (op2) {
+        case OPC_DMTHLIP:
+            tcg_gen_movi_tl(t0, ret);
+            gen_helper_dmthlip(cpu_gpr[v1], t0, cpu_env);
+            break;
+        case OPC_DSHILO:
+            {
+                int shift = (ctx->opcode >> 19) & 0x7F;
+                int ac = (ctx->opcode >> 11) & 0x03;
+                tcg_gen_movi_tl(t0, shift);
+                tcg_gen_movi_tl(t1, ac);
+                gen_helper_dshilo(t0, t1, cpu_env);
+                break;
+            }
+        case OPC_DSHILOV:
+            {
+                int ac = (ctx->opcode >> 11) & 0x03;
+                tcg_gen_movi_tl(t0, ac);
+                gen_helper_dshilo(cpu_gpr[v1], t0, cpu_env);
+                break;
+            }
+        case OPC_DEXTP:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+
+            gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_DEXTPV:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_dextp(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_DEXTPDP:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_DEXTPDPV:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_dextpdp(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_DEXTR_L:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_DEXTR_R_L:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_DEXTR_RS_L:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_DEXTR_W:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_DEXTR_R_W:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_DEXTR_RS_W:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_DEXTR_S_H:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_DEXTRV_S_H:
+            tcg_gen_movi_tl(t0, v2);
+            tcg_gen_movi_tl(t1, v1);
+            gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
+            break;
+        case OPC_DEXTRV_L:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_dextr_l(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_DEXTRV_R_L:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_dextr_r_l(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_DEXTRV_RS_L:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_dextr_rs_l(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_DEXTRV_W:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_dextr_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_DEXTRV_R_W:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_dextr_r_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        case OPC_DEXTRV_RS_W:
+            tcg_gen_movi_tl(t0, v2);
+            gen_helper_dextr_rs_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
+            break;
+        }
+        break;
+#endif
+    }
+
+
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+
+    (void)opn; /* avoid a compiler warning */
+    MIPS_DEBUG("%s", opn);
+}
+
 /* End MIPSDSP functions. */
 
 static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
@@ -14778,6 +15052,38 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             op2 = MASK_APPEND(ctx->opcode);
             gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
             break;
+        case OPC_EXTR_W_DSP:
+            op2 = MASK_EXTR_W(ctx->opcode);
+            switch (op2) {
+            case OPC_EXTR_W:
+            case OPC_EXTR_R_W:
+            case OPC_EXTR_RS_W:
+            case OPC_EXTR_S_H:
+            case OPC_EXTRV_S_H:
+            case OPC_EXTRV_W:
+            case OPC_EXTRV_R_W:
+            case OPC_EXTRV_RS_W:
+            case OPC_EXTP:
+            case OPC_EXTPV:
+            case OPC_EXTPDP:
+            case OPC_EXTPDPV:
+                gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
+                break;
+            case OPC_RDDSP:
+                gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
+                break;
+            case OPC_SHILO:
+            case OPC_SHILOV:
+            case OPC_MTHLIP:
+            case OPC_WRDSP:
+                gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
+                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:
@@ -14922,6 +15228,40 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             op2 = MASK_DAPPEND(ctx->opcode);
             gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
             break;
+        case OPC_DEXTR_W_DSP:
+            op2 = MASK_DEXTR_W(ctx->opcode);
+            switch (op2) {
+            case OPC_DEXTP:
+            case OPC_DEXTPDP:
+            case OPC_DEXTPDPV:
+            case OPC_DEXTPV:
+            case OPC_DEXTR_L:
+            case OPC_DEXTR_R_L:
+            case OPC_DEXTR_RS_L:
+            case OPC_DEXTR_W:
+            case OPC_DEXTR_R_W:
+            case OPC_DEXTR_RS_W:
+            case OPC_DEXTR_S_H:
+            case OPC_DEXTRV_L:
+            case OPC_DEXTRV_R_L:
+            case OPC_DEXTRV_RS_L:
+            case OPC_DEXTRV_S_H:
+            case OPC_DEXTRV_W:
+            case OPC_DEXTRV_R_W:
+            case OPC_DEXTRV_RS_W:
+                gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
+                break;
+            case OPC_DMTHLIP:
+            case OPC_DSHILO:
+            case OPC_DSHILOV:
+                gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
+                break;
+            default:            /* Invalid */
+                MIPS_INVAL("MASK EXTR.W");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            break;
         case OPC_DPAQ_W_QH_DSP:
             op2 = MASK_DPAQ_W_QH(ctx->opcode);
             switch (op2) {
-- 
1.7.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 12/14] target-mips-ase-dsp: Add MIPS DSP processors
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
                   ` (10 preceding siblings ...)
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 11/14] target-mips-ase-dsp: Add DSP accumulator instructions Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:51   ` Aurelien Jarno
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 13/14] target-mips-ase-dsp: Add testcases Jia Liu
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Add 74kf and mips64dspr2-generic-cpu model for test.

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

diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index c39138f..73a14a9 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -311,6 +311,29 @@ static const mips_def_t mips_defs[] =
         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT,
         .mmu_type = MMU_TYPE_R4000,
     },
+    {
+        .name = "74Kf",
+        .CP0_PRid = 0x97,
+        .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) | (1 << CP0C3_DSPP),
+        .CP0_LLAddr_rw_bitmask = 0,
+        .CP0_LLAddr_shift = 4,
+        .SYNCI_Step = 32,
+        .CCRes = 2,
+        .CP0_Status_rw_bitmask = 0x3778FF1F,
+        .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 +507,35 @@ static const mips_def_t mips_defs[] =
       .insn_flags = CPU_LOONGSON2F,
       .mmu_type = MMU_TYPE_R4000,
     },
+    {
+        /* A generic CPU providing MIPS64 ASE DSP 2 features.
+           FIXME: Eventually this should be replaced by a real CPU model. */
+        .name = "mips64dspr2",
+        .CP0_PRid = 0x00010000,
+        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
+                       (MMU_TYPE_R4000 << CP0C0_MT),
+        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << 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 | (1 << CP0C3_LPA),
+        .CP0_LLAddr_rw_bitmask = 0,
+        .CP0_LLAddr_shift = 0,
+        .SYNCI_Step = 32,
+        .CCRes = 2,
+        .CP0_Status_rw_bitmask = 0x36FBFFFF,
+        .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) |
+                    (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
+                    (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .SEGBITS = 42,
+        /* The architectural limit is 59, but we have hardcoded 36 bit
+           in some places...
+        .PABITS = 59, */ /* the architectural limit */
+        .PABITS = 36,
+        .insn_flags = CPU_MIPS64R2 | ASE_DSP | ASE_DSPR2,
+        .mmu_type = MMU_TYPE_R4000,
+    },
 
 #endif
 };
-- 
1.7.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 13/14] target-mips-ase-dsp: Add testcases
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
                   ` (11 preceding siblings ...)
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 12/14] target-mips-ase-dsp: Add MIPS DSP processors Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:51   ` Aurelien Jarno
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 14/14] target-mips-ase-dsp: Change TODO file Jia Liu
  2012-10-06  2:33 ` [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 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             |  135 +++++++++++
 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_phl.c      |   41 ++++
 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/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             |  305 ++++++++++++++++++++++++
 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               |   16 ++
 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      |   62 +++++
 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_phl.c      |   46 ++++
 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/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             |   16 ++
 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, 15870 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_phl.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/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_phl.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/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..232527b
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/Makefile
@@ -0,0 +1,135 @@
+-include ../../config-host.mak
+
+CROSS=mips64el-unknown-linux-gnu-
+
+SIM=qemu-mipsel
+SIM_FLAGS=-cpu 74Kf
+
+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_phl.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..2337abe
--- /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 addr, index;
+    int result;
+
+    value  = 0xBCDEF389;
+    p = &value;
+    addr = (unsigned 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..10be3b3
--- /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 addr, index;
+    int result;
+
+    value  = 0xBCDEF389;
+    p = &value;
+    addr = (unsigned 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..e6543c9
--- /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 addr, index;
+    int result;
+
+    value  = 0xBCDEF389;
+    p = &value;
+    addr = (unsigned 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..6111d8d
--- /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 = 0x00;
+    resultl = 0x7FFFFFFF;
+
+    __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..96b4915
--- /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 = 0x00;
+    resultl = 0x7FFFFFFF;
+
+    __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_phl.c b/tests/tcg/mips/mips32-dsp/muleq_s_w_phl.c
new file mode 100644
index 0000000..b3a5370
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/muleq_s_w_phl.c
@@ -0,0 +1,41 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+    int rd, rs, rt, dsp;
+    int result, resultdsp;
+
+    rs = 0x80001234;
+    rt = 0x80001234;
+    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 = 0x12349988;
+    rt = 0x43219988;
+    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-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/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..5a07a72
--- /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 74Kf
+
+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..244ecea
--- /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 = 0x87654321;
+    rt = 0x12345678;
+    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..8e4da4f
--- /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 = 0x87654321;
+    rt = 0x12345678;
+    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..b6e358d
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/Makefile
@@ -0,0 +1,305 @@
+
+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_phl.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..dd0565f
--- /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 = 0x2100000000123456;
+
+    __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..ab3c351
--- /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 = 0x2100000000123456;
+    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..e4a2072
--- /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 = 0x123456;
+    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..654dfaf
--- /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 = 0x123456;
+
+    __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..44b0160
--- /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 = 0x2100000000123456;
+
+    __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..c5b3850
--- /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 = 0x2100000000123456;
+    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..7cefdab
--- /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 = 0x123456;
+    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..4028a7a
--- /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 = 0x123456;
+
+    __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..8789e84
--- /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 = 0x1;
+    resl = 0x9;
+    resdsp = 0x00;
+
+    __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..4bfb00b
--- /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 = 0xffffffffffffffff;
+    resl = 0x00;
+
+    resdsp = 0x01;
+
+    __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..9a099ae
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/head.S
@@ -0,0 +1,16 @@
+/*
+ *  Startup Code for MIPS64 CPU-core
+ *
+ */
+.text
+.globl _start
+.align 4
+_start:
+    ori    $2, $2, 0xffff
+    sll    $2, $2, 16
+    ori    $2, $2, 0xffff
+    mtc0   $2, $12, 0
+    jal    main
+
+end:
+    b end
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..e467aa2
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/maq_sa_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 = 0x00;
+    resultl = 0x15ae87f5;
+
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "maq_sa.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("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_phl.c b/tests/tcg/mips/mips64-dsp/muleq_s_w_phl.c
new file mode 100644
index 0000000..76c615b
--- /dev/null
+++ b/tests/tcg/mips/mips64-dsp/muleq_s_w_phl.c
@@ -0,0 +1,46 @@
+#include "io.h"
+
+int main(void)
+{
+    long long rd, rs, rt, dsp;
+    long long result, resultdsp;
+
+    rs = 0x80009988;
+    rt = 0x80009988;
+    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.phr wrong\n");
+
+        return -1;
+    }
+
+    rs = 0x12343322;
+    rt = 0x43213322;
+    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.phr wrong\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/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..d35376a
--- /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 error1\n");
+
+        return -1;
+    }
+
+    rd = 0;
+    result = 0xFFFFFE00FFFFFE00;
+    __asm
+        ("repl.pw %0, 0xFFFFFFFFFFFFFE00\n\t"
+         : "=r"(rd)
+        );
+
+    if (result != rd) {
+        printf("repl.pw error2\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..9a099ae
--- /dev/null
+++ b/tests/tcg/mips/mips64-dspr2/head.S
@@ -0,0 +1,16 @@
+/*
+ *  Startup Code for MIPS64 CPU-core
+ *
+ */
+.text
+.globl _start
+.align 4
+_start:
+    ori    $2, $2, 0xffff
+    sll    $2, $2, 16
+    ori    $2, $2, 0xffff
+    mtc0   $2, $12, 0
+    jal    main
+
+end:
+    b end
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..db609b2
--- /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 = 0xFFFFFFFFF504F4B4;
+    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..60a6b1b
--- /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 = 0x87654321;
+    rt = 0x12345678;
+    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..ae32cc0
--- /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 = 0x87654321;
+    rt = 0x12345678;
+    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.10.2 (Apple Git-33)

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

* [Qemu-devel] [PATCH v9 14/14] target-mips-ase-dsp: Change TODO file
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
                   ` (12 preceding siblings ...)
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 13/14] target-mips-ase-dsp: Add testcases Jia Liu
@ 2012-09-27 13:24 ` Jia Liu
  2012-10-06 14:52   ` Aurelien Jarno
  2012-10-06  2:33 ` [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
  14 siblings, 1 reply; 30+ messages in thread
From: Jia Liu @ 2012-09-27 13:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Delete DSP r1 & DSP r2 from TODO file.

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.10.2 (Apple Git-33)

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

* Re: [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support
  2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
                   ` (13 preceding siblings ...)
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 14/14] target-mips-ase-dsp: Change TODO file Jia Liu
@ 2012-10-06  2:33 ` Jia Liu
  14 siblings, 0 replies; 30+ messages in thread
From: Jia Liu @ 2012-10-06  2:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

hi Aurelien,

ping again ~~~

On Thu, Sep 27, 2012 at 9:24 PM, Jia Liu <proljc@gmail.com> wrote:
>
> 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:
> v9:
> Addressed Aurelien's review comments:
> - group translate actions by opcode
> - group helpers using macro
> - remove unused function not_word_value
> - add absolute macro, overflow check macro, split/combine number macro
> - undo delete bposge32/64 from micromips
> - add return register 0 check
>
> v8:
> Addressed Aurelien's review comments:
> - fix HFLAGS check, I hope it is right this time
> - make a lot of code more clean
> - fix branch instructions
> - fix load instructions, I hope it is right this time
> - fix bit instructions
> - use a macro to deal CMP
> - use 74kf instead of mips32dspr2
>
> v7:
> Addressed Aurelien's review comments:
> - make hflags check for dsp, use check_dsp[r2]() instead of check_insn
> - directly use cpu_dspctrl as the second argument in branch instructions
> - factorizing some check_dsp() code one level
> - remove unnecessary save_cpu_state() from load instructions
> - resolve conflicts between MIPS DSP and loongson2e better
> - make repl* more clean
>
> 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 (14):
>   target-mips-ase-dsp: Add internal funtions
>   target-mips-ase-dsp: Add dsp resources access check
>   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 DSP accumulator instructions
>   target-mips-ase-dsp: Add MIPS DSP processors
>   target-mips-ase-dsp: Add testcases
>   target-mips-ase-dsp: Change TODO file
>
>  linux-user/main.c                              |    6 +
>  target-mips/Makefile.objs                      |    2 +-
>  target-mips/TODO                               |    2 -
>  target-mips/cpu.h                              |   27 +-
>  target-mips/dsp_helper.c                       | 4109 ++++++++++++++++++++++++
>  target-mips/helper.c                           |    3 +
>  target-mips/helper.h                           |  349 ++
>  target-mips/translate.c                        | 3074 +++++++++++++++++-
>  target-mips/translate_init.c                   |   52 +
>  tests/tcg/mips/mips32-dsp/Makefile             |  135 +
>  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_phl.c      |   41 +
>  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/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             |  305 ++
>  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               |   16 +
>  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      |   62 +
>  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_phl.c      |   46 +
>  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/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             |   16 +
>  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 +
>  496 files changed, 23383 insertions(+), 111 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_phl.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/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_phl.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/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.10.2 (Apple Git-33)
>

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

* Re: [Qemu-devel] [PATCH v9 01/14] target-mips-ase-dsp: Add internal funtions
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 01/14] target-mips-ase-dsp: Add internal funtions Jia Liu
@ 2012-10-06 14:51   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:51 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:38PM +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  | 1121 +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 1122 insertions(+), 1 deletion(-)
>  create mode 100644 target-mips/dsp_helper.c
> 
> diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs
> index 3eeeeac..119c816 100644
> --- a/target-mips/Makefile.objs
> +++ b/target-mips/Makefile.objs
> @@ -1,2 +1,2 @@
> -obj-y += translate.o op_helper.o lmi_helper.o helper.o cpu.o
> +obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o
>  obj-$(CONFIG_SOFTMMU) += machine.o
> diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
> new file mode 100644
> index 0000000..b04b489
> --- /dev/null
> +++ b/target-mips/dsp_helper.c
> @@ -0,0 +1,1121 @@
> +/*
> + * 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 ***/
> +#define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x)
> +#define MIPSDSP_OVERFLOW(a, b, c, d) (!(!((a ^ b ^ -1) & (a ^ c) & d)))
> +
> +static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
> +                                                CPUMIPSState *env)
> +{
> +    env->active_tc.DSPControl |= (target_ulong)flag << position;
> +}
> +
> +static inline void set_DSPControl_carryflag(uint32_t flag, CPUMIPSState *env)
> +{
> +    env->active_tc.DSPControl |= (target_ulong)flag << 13;
> +}
> +
> +static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
> +{
> +    return (env->active_tc.DSPControl >> 13) & 0x01;
> +}
> +
> +static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env)
> +{
> +  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(int len, CPUMIPSState *env)
> +{
> +  uint32_t filter;
> +
> +  filter = (0x01 << len) - 1;
> +
> +  return (env->active_tc.DSPControl >> 24) & filter;
> +}
> +
> +static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env)
> +{
> +    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(uint32_t flag, CPUMIPSState *env)
> +{
> +    env->active_tc.DSPControl &= 0xFFFFBFFF;
> +    env->active_tc.DSPControl |= (target_ulong)flag << 14;
> +}
> +
> +/* get abs value */
> +static inline int8_t mipsdsp_sat_abs_u8(int8_t a, CPUMIPSState *env)
> +{
> +    if (a == INT8_MIN) {
> +        set_DSPControl_overflow_flag(1, 20, env);
> +        return 0x7f;
> +    } else {
> +        return MIPSDSP_ABS(a);
> +    }
> +
> +    return a;
> +}
> +
> +static inline int16_t mipsdsp_sat_abs_u16(int16_t a, CPUMIPSState *env)
> +{
> +    if (a == INT16_MIN) {
> +        set_DSPControl_overflow_flag(1, 20, env);
> +        return 0x7fff;
> +    } else {
> +        return MIPSDSP_ABS(a);
> +    }
> +
> +    return a;
> +}
> +
> +static inline int32_t mipsdsp_sat_abs_u32(int32_t a, CPUMIPSState *env)
> +{
> +    if (a == INT32_MIN) {
> +        set_DSPControl_overflow_flag(1, 20, env);
> +        return 0x7FFFFFFF;
> +    } else {
> +        return MIPSDSP_ABS(a);
> +    }
> +
> +    return a;
> +}

The "return a" is useless in the three functions above. Also I don't get
why this functions have a u8, u16 and u32 prefix, while they don't work
on unsigned number but rather signed number.

Also note that you could replace the 3 functions above by something like:

#define DO_MIPS_SAT_ABS(size)                                          \
static inline int##size##_t mipsdsp_sat_abs_u##size(int##size##a,      \
                                                    CPUMIPSState *env) \
{                                                                      \
    if (a == INT##size##_MIN) {                                        \
        set_DSPControl_overflow_flag(1, 20, env);                      \
	return INT##size##_MAX;                                        \
    } else {                                                           \
        return MIPSDSP_ABS(a);                                         \
    }                                                                  \
}
DO_MIPS_SAT_ABS(8)
DO_MIPS_SAT_ABS(16)
DO_MIPS_SAT_ABS(32)
#undef DO_MIPS_SAT_ABS

> +/* get sum value */
> +static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env)
> +{
> +    int16_t tempI;
> +
> +    tempI = a + b;
> +
> +    if (MIPSDSP_OVERFLOW(a, b, tempI, 0x8000)) {
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return tempI;
> +}
> +
> +static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b,
> +                                          CPUMIPSState *env)
> +{
> +    int16_t tempS;
> +
> +    tempS = a + b;
> +
> +    if (MIPSDSP_OVERFLOW(a, b, tempS, 0x8000)) {
> +        if (a > 0) {
> +            tempS = 0x7FFF;
> +        } else {
> +            tempS = 0x8000;
> +        }
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return tempS;
> +}
> +
> +static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b,
> +                                          CPUMIPSState *env)
> +{
> +    int32_t tempI;
> +
> +    tempI = a + b;
> +
> +    if (MIPSDSP_OVERFLOW(a, b, tempI, 0x80000000)) {
> +        if (a > 0) {
> +            tempI = 0x7FFFFFFF;
> +        } else {
> +            tempI = 0x80000000;
> +        }
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return tempI;
> +}
> +
> +static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
> +{
> +    uint16_t temp;
> +
> +    temp = (uint16_t)a + (uint16_t)b;
> +
> +    if (temp & 0x0100) {
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return temp & 0xFF;
> +}
> +
> +static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b,
> +                                       CPUMIPSState *env)
> +{
> +    uint32_t temp;
> +
> +    temp = (uint32_t)a + (uint32_t)b;
> +
> +    if (temp & 0x00010000) {
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return temp & 0xFFFF;
> +}
> +
> +static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b,
> +                                         CPUMIPSState *env)
> +{
> +    uint8_t  result;
> +    uint16_t temp;
> +
> +    temp = (uint16_t)a + (uint16_t)b;
> +    result = temp & 0xFF;
> +
> +    if (0x0100 & temp) {
> +        result = 0xFF;
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return result;
> +}
> +
> +static inline uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b,
> +                                           CPUMIPSState *env)
> +{
> +    uint16_t result;
> +    uint32_t temp;
> +
> +    temp = (uint32_t)a + (uint32_t)b;
> +    result = temp & 0xFFFF;
> +
> +    if (0x00010000 & temp) {
> +        result = 0xFFFF;
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }> +
> +    return result;
> +}
> +
> +static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a,
> +                                            CPUMIPSState *env)
> +{
> +    int64_t 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
> +
> +    temp_sum = (int64_t)a + temp;
> +
> +    temp32 = (temp_sum >> 32) & 0x01;
> +    temp31 = (temp_sum >> 31) & 0x01;
> +    result = temp_sum & 0xFFFFFFFF;
> +
> +    if (temp32 != temp31) {
> +        if (temp32 == 0) {
> +            result = 0x7FFFFFFF;
> +        } else {
> +            result = 0x80000000;
> +        }
> +        set_DSPControl_overflow_flag(1, 16 + acc, env);
> +    }
> +
> +    return result;
> +}
> +
> +/* a[0] is LO, a[1] is HI. */
> +static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret,
> +                                             int32_t ac,
> +                                             int64_t *a,
> +                                             CPUMIPSState *env)
> +{
> +    int64_t temp[3];
> +    int64_t acc[3];
> +    int64_t temp_sum;
> +
> +    temp[0] = a[0];
> +    temp[1] = a[1];
> +    if (temp[1] >= 0) {
> +        temp[2] = 0x00;
> +    } else {
> +        temp[2] = ~0ull;
> +    }
> +
> +    acc[0] = env->active_tc.LO[ac];
> +    acc[1] = env->active_tc.HI[ac];
> +    if (acc[1] >= 0) {
> +        acc[2] = 0x00;
> +    } else {
> +        acc[2] = ~0ull;
> +    }
> +
> +    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;
> +    }
> +
> +    if (MIPSDSP_OVERFLOW(temp[1], acc[1], temp_sum, INT64_MIN)) {
> +        if (temp[1] > 0) {
> +            ret[0] = 0x0;
> +            ret[1] = 0x7FFFFFFFFFFFFFFFull;
> +        } else {
> +            ret[0] = 0x8000000000000000ull;
> +            ret[1] = ~0ull;
> +        }
> +        set_DSPControl_overflow_flag(1, 16 + ac, env);
> +    } else {
> +        ret[0] = temp[0];
> +        ret[1] = temp_sum;
> +    }
> +}
> +
> +/* a[0] is LO, a[1] is HI. */
> +static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
> +                                             int32_t ac,
> +                                             int64_t *a,
> +                                             CPUMIPSState *env)
> +{
> +    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] >= 0) {
> +        temp[2] = 0x00;
> +    } else {
> +        temp[2] = ~0ull;
> +    }
> +
> +    acc[0] = env->active_tc.LO[ac];
> +    acc[1] = env->active_tc.HI[ac];
> +    if (acc[1] >= 0) {
> +        acc[2] = 0x00;
> +    } else {
> +        acc[2] = ~0ull;
> +    }
> +
> +    temp_sum = acc[0] - temp[0];
> +    if ((uint64_t)temp_sum > (uint64_t)acc[0]) {
> +        acc[1] -= 1;
> +        if (acc[1] == ~0ull) {
> +            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] = ~0ull;
> +        } else {
> +            ret[0] = 0x0;
> +            ret[1] = 0x7FFFFFFFFFFFFFFFull;
> +        }
> +        set_DSPControl_overflow_flag(1, 16 + ac, env);

The overflow there can probably be checked the same way as for 64-bit
numbers, using MIPSDSP_OVERFLOW instead of doing 192 bit arithmetic only
for one bit.

> +    } else {
> +        ret[0] = acc[0];
> +        ret[1] = acc[1];
> +    }
> +}
> +
> +static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b,
> +                                          CPUMIPSState *env)
> +{
> +    int32_t temp;
> +
> +    temp = (int32_t)a * (int32_t)b;
> +
> +    if ((temp > 0x7FFF) || (temp < 0xFFFF8000)) {
> +        set_DSPControl_overflow_flag(1, 21, env);
> +    }
> +    temp &= 0x0000FFFF;
> +
> +    return temp;
> +}
> +
> +static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b)
> +{
> +    return a * b;
> +}
> +
> +static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b)
> +{
> +    return a * b;
> +}
> +
> +static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b,
> +                                                CPUMIPSState *env)
> +{
> +    int32_t temp;
> +
> +    temp = (int32_t)a * (int32_t)b;
> +
> +    if (temp > 0x7FFF) {
> +        temp = 0x00007FFF;
> +        set_DSPControl_overflow_flag(1, 21, env);
> +    } else if (temp < 0x00007FFF) {
> +        temp = 0xFFFF8000;
> +        set_DSPControl_overflow_flag(1, 21, env);
> +    }
> +    temp &= 0x0000FFFF;
> +
> +    return temp;
> +}
> +
> +static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b,
> +                                                         CPUMIPSState *env)
> +{
> +    int32_t temp;
> +
> +    if ((a == 0x8000) && (b == 0x8000)) {
> +        temp = 0x7FFFFFFF;
> +        set_DSPControl_overflow_flag(1, 21, env);
> +    } else {
> +        temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1;
> +    }
> +
> +    return temp;
> +}
> +
> +/* right shift */
> +static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov)
> +{
> +    return a >> mov;
> +}
> +
> +static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov)
> +{
> +    return a >> mov;
> +}
> +
> +static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov)
> +{
> +    return a >> mov;
> +}
> +
> +static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov)
> +{
> +    return a >> mov;
> +}
> +
> +static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov)
> +{
> +    return a >> mov;
> +}
> +
> +static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
> +{
> +    int32_t temp;
> +
> +    temp = (int32_t)a + (int32_t)b;
> +
> +    return (temp >> 1) & 0xFFFF;
> +}
> +
> +/* round right shift */
> +static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b)
> +{
> +    int32_t temp;
> +
> +    temp = (int32_t)a + (int32_t)b;
> +    temp += 1;
> +
> +    return (temp >> 1) & 0xFFFF;
> +}
> +
> +static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b)
> +{
> +    int64_t temp;
> +
> +    temp = (int64_t)a + (int64_t)b;
> +
> +    return (temp >> 1) & 0xFFFFFFFF;
> +}
> +
> +static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b)
> +{
> +    int64_t temp;
> +
> +    temp = (int64_t)a + (int64_t)b;
> +    temp += 1;
> +
> +    return (temp >> 1) & 0xFFFFFFFF;
> +}
> +
> +static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b)
> +{
> +    uint16_t temp;
> +
> +    temp = (uint16_t)a + (uint16_t)b;
> +
> +    return (temp >> 1) & 0x00FF;
> +}
> +
> +static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b)
> +{
> +    uint16_t temp;
> +
> +    temp = (uint16_t)a + (uint16_t)b + 1;
> +
> +    return (temp >> 1) & 0x00FF;
> +}
> +
> +static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b)
> +{
> +    uint16_t temp;
> +
> +    temp = (uint16_t)a - (uint16_t)b;
> +
> +    return (temp >> 1) & 0x00FF;
> +}
> +
> +static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b)
> +{
> +    uint16_t temp;
> +
> +    temp = (uint16_t)a - (uint16_t)b + 1;
> +
> +    return (temp >> 1) & 0x00FF;
> +}
> +
> +static inline int64_t mipsdsp_rashift_short_acc(int32_t ac,
> +                                                int32_t shift,
> +                                                CPUMIPSState *env)
> +{
> +    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(1, 23, env);
> +    }
> +
> +    return temp;
> +}
> +
> +/*  128 bits long. p[0] is LO, p[1] is HI. */
> +static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
> +                                                int32_t ac,
> +                                                int32_t shift,
> +                                                CPUMIPSState *env)
> +{
> +    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(uint64_t *p,
> +                                       uint32_t ac,
> +                                       uint32_t shift,
> +                                       CPUMIPSState *env)
> +{
> +    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;
> +    }
> +}
> +
> +/* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/
> +static inline void mipsdsp_rndrashift_acc(uint64_t *p,
> +                                          uint32_t ac,
> +                                          uint32_t shift,
> +                                          CPUMIPSState *env)
> +{
> +    int64_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 << (65 - shift)) | (tempA >> (shift - 1));
> +        p[1] = (int64_t)tempB >> (shift - 1);
> +        if (tempB >= 0) {
> +            p[2] = 0x0;
> +        } else {
> +            p[2] = ~0ull;
> +        }
> +    }
> +}
> +
> +static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b,
> +                                          CPUMIPSState *env)
> +{
> +    int32_t temp;
> +
> +    if ((a == 0x8000) && (b == 0x8000)) {
> +        temp = 0x7FFFFFFF;
> +        set_DSPControl_overflow_flag(1, 16 + ac, env);
> +    } else {
> +        temp = ((uint32_t)a * (uint32_t)b) << 1;
> +    }
> +
> +    return temp;
> +}
> +
> +static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b,
> +                                          CPUMIPSState *env)
> +{
> +    uint64_t temp;
> +
> +    if ((a == 0x80000000) && (b == 0x80000000)) {
> +        temp = 0x7FFFFFFFFFFFFFFFull;
> +        set_DSPControl_overflow_flag(1, 16 + ac, env);
> +    } else {
> +        temp = ((uint64_t)a * (uint64_t)b) << 1;
> +    }
> +
> +    return temp;
> +}
> +
> +static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b)
> +{
> +    return (uint16_t)a * (uint16_t)b;
> +}
> +
> +static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b,
> +                                          CPUMIPSState *env)
> +{
> +    uint32_t tempI;
> +
> +    tempI = (uint32_t)a * (uint32_t)b;
> +    if (tempI > 0x0000FFFF) {
> +        tempI = 0x0000FFFF;
> +        set_DSPControl_overflow_flag(1, 21, env);
> +    }
> +
> +    return tempI & 0x0000FFFF;
> +}
> +
> +static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b)
> +{
> +    return (uint64_t)a * (uint64_t)b;
> +}
> +
> +static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b,
> +                                                 CPUMIPSState *env)
> +{
> +    uint32_t temp;
> +
> +    if ((a == 0x8000) && (b == 0x8000)) {
> +        temp = 0x7FFF0000;
> +        set_DSPControl_overflow_flag(1, 21, env);
> +    } else {
> +        temp = (a * b) << 1;
> +        temp = temp + 0x00008000;
> +    }
> +
> +    return (temp & 0xFFFF0000) >> 16;
> +}
> +
> +static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b,
> +                                                CPUMIPSState *env)
> +{
> +    int32_t temp;
> +
> +    if ((a == 0x8000) && (b == 0x8000)) {
> +        temp = 0x7FFF0000;
> +        set_DSPControl_overflow_flag(1, 21, env);
> +    } else {
> +        temp = ((uint32_t)a * (uint32_t)b);
> +        temp = temp << 1;
> +    }
> +
> +    return (temp >> 16) & 0x0000FFFF;
> +}
> +
> +static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a,
> +                                                   CPUMIPSState *env)
> +{
> +    int64_t temp;
> +
> +    temp = (int32_t)a + 0x00008000;
> +
> +    if (a > 0x7fff8000) {
> +        temp = 0x7FFFFFFF;
> +        set_DSPControl_overflow_flag(1, 22, env);
> +    }
> +
> +    return (temp >> 16) & 0xFFFF;
> +}
> +
> +static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
> +                                                    CPUMIPSState *env)
> +{
> +    uint16_t mag;
> +    uint32_t sign;
> +
> +    sign = (a >> 15) & 0x01;
> +    mag = a & 0x7FFF;
> +
> +    if (sign == 0) {
> +        if (mag > 0x7F80) {
> +            set_DSPControl_overflow_flag(1, 22, env);
> +            return 0xFF;
> +        } else {
> +            return (mag >> 7) & 0xFFFF;
> +        }
> +    } else {
> +        set_DSPControl_overflow_flag(1, 22, env);
> +        return 0x00;
> +    }
> +}
> +
> +static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env)
> +{
> +    uint8_t sign;
> +    uint8_t discard;
> +
> +    if (s == 0) {
> +        return a;
> +    } else {
> +        sign = (a >> 7) & 0x01;
> +        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(1, 22, env);
> +        }
> +        return a << s;
> +    }
> +}
> +
> +static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
> +                                        CPUMIPSState *env)
> +{
> +    uint8_t  sign;
> +    uint16_t discard;
> +
> +    if (s == 0) {
> +        return a;
> +    } else {
> +        sign = (a >> 15) & 0x01;
> +        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(1, 22, env);
> +        }
> +        return a << s;
> +    }
> +}
> +
> +
> +static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s,
> +                                        CPUMIPSState *env)
> +{
> +    uint32_t discard;
> +
> +    if (s == 0) {
> +        return a;
> +    } else {
> +        discard = (int32_t)a >> (31 - (s - 1));
> +
> +        if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
> +            set_DSPControl_overflow_flag(1, 22, env);
> +        }
> +        return a << s;
> +    }
> +}
> +
> +static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s,
> +                                            CPUMIPSState *env)
> +{
> +    uint8_t  sign;
> +    uint16_t discard;
> +
> +    if (s == 0) {
> +        return a;
> +    } else {
> +        sign = (a >> 15) & 0x01;
> +        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(1, 22, env);
> +            return (sign == 0) ? 0x7FFF : 0x8000;
> +        } else {
> +            return a << s;
> +        }
> +    }
> +}
> +
> +static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s,
> +                                            CPUMIPSState *env)
> +{
> +    uint8_t  sign;
> +    uint32_t discard;
> +
> +    if (s == 0) {
> +        return a;
> +    } else {
> +        sign = (a >> 31) & 0x01;
> +        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)) {
> +            set_DSPControl_overflow_flag(1, 22, env);
> +            return (sign == 0) ? 0x7FFFFFFF : 0x80000000;
> +        } else {
> +            return a << s;
> +        }
> +    }
> +}
> +
> +static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a, uint8_t s)
> +{
> +    uint32_t temp;
> +
> +    if (s == 0) {
> +        temp = (uint32_t)a << 1;
> +    } else {
> +        temp = (int32_t)(int8_t)a >> (s - 1);
> +    }
> +
> +    return (temp + 1) >> 1;
> +}
> +
> +static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s)
> +{
> +    uint32_t temp;
> +
> +    if (s == 0) {
> +        temp = (uint32_t)a << 1;
> +    } else {
> +        temp = (int32_t)(int16_t)a >> (s - 1);
> +    }
> +
> +    return (temp + 1) >> 1;
> +}
> +
> +static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s)
> +{
> +    int64_t temp;
> +
> +    if (s == 0) {
> +        temp = a << 1;
> +    } else {
> +        temp = (int64_t)(int32_t)a >> (s - 1);
> +    }
> +    temp += 1;
> +
> +    return (temp >> 1) & 0x00000000FFFFFFFFull;
> +}
> +
> +static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env)
> +{
> +    int16_t  temp;
> +
> +    temp = a - b;
> +    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return temp;
> +}
> +
> +static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b,
> +                                         CPUMIPSState *env)
> +{
> +    int16_t  temp;
> +
> +    temp = a - b;
> +    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
> +        if (a > 0) {
> +            temp = 0x7FFF;
> +        } else {
> +            temp = 0x8000;
> +        }
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return temp;
> +}
> +
> +static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b,
> +                                         CPUMIPSState *env)
> +{
> +    int32_t  temp;
> +
> +    temp = a - b;
> +    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
> +        if (a > 0) {
> +            temp = 0x7FFFFFFF;
> +        } else {
> +            temp = 0x80000000;
> +        }
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return temp & 0x00000000FFFFFFFFull;
> +}
> +
> +static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b)
> +{
> +    int32_t  temp;
> +
> +    temp = (int32_t)a - (int32_t)b;
> +
> +    return (temp >> 1) & 0x0000FFFF;
> +}
> +
> +static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b)
> +{
> +    int32_t  temp;
> +
> +    temp = (int32_t)a - (int32_t)b;
> +    temp += 1;
> +
> +    return (temp >> 1) & 0x0000FFFF;
> +}
> +
> +static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b)
> +{
> +    int64_t  temp;
> +
> +    temp = (int64_t)a - (int64_t)b;
> +
> +    return (temp >> 1) & 0x00000000FFFFFFFFull;
> +}
> +
> +static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b)
> +{
> +    int64_t  temp;
> +
> +    temp = (int64_t)a - (int64_t)b;
> +    temp += 1;
> +
> +    return (temp >> 1) & 0x00000000FFFFFFFFull;
> +}
> +
> +static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b,
> +                                           CPUMIPSState *env)
> +{
> +    uint8_t  temp16;
> +    uint32_t temp;
> +
> +    temp = (uint32_t)a - (uint32_t)b;
> +    temp16 = (temp >> 16) & 0x01;
> +    if (temp16 == 1) {
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +    return temp & 0x0000FFFF;
> +}
> +
> +static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b,
> +                                                  CPUMIPSState *env)
> +{
> +    uint8_t  temp16;
> +    uint32_t temp;
> +
> +    temp   = (uint32_t)a - (uint32_t)b;
> +    temp16 = (temp >> 16) & 0x01;
> +
> +    if (temp16 == 1) {
> +        temp = 0x0000;
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return temp & 0x0000FFFF;
> +}
> +
> +static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
> +{
> +    uint8_t  temp8;
> +    uint16_t temp;
> +
> +    temp = (uint16_t)a - (uint16_t)b;
> +    temp8 = (temp >> 8) & 0x01;
> +    if (temp8 == 1) {
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return temp & 0x00FF;
> +}
> +
> +static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env)
> +{
> +    uint8_t  temp8;
> +    uint16_t temp;
> +
> +    temp = (uint16_t)a - (uint16_t)b;
> +    temp8 = (temp >> 8) & 0x01;
> +    if (temp8 == 1) {
> +        temp = 0x00;
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return temp & 0x00FF;
> +}
> +
> +static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
> +{
> +    int32_t temp;
> +
> +    temp = a - b;
> +    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return temp;
> +}
> +
> +static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env)
> +{
> +    int32_t temp;
> +
> +    temp = a + b;
> +
> +    if (MIPSDSP_OVERFLOW(a, b, temp, 0x80000000)) {
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    return temp;
> +}
> +
> +static inline int32_t mipsdsp_cmp_eq(uint32_t a, uint32_t b)
> +{
> +    return a == b;
> +}
> +
> +static inline int32_t mipsdsp_cmp_le(uint32_t a, uint32_t b)
> +{
> +    return a <= b;
> +}
> +
> +static inline int32_t mipsdsp_cmp_lt(uint32_t a, uint32_t b)
> +{
> +    return a < b;
> +}
> +/*** MIPS DSP internal functions end ***/
> -- 
> 1.7.10.2 (Apple Git-33)
> 
> 

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

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

* Re: [Qemu-devel] [PATCH v9 02/14] target-mips-ase-dsp: Add dsp resources access check
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 02/14] target-mips-ase-dsp: Add dsp resources access check Jia Liu
@ 2012-10-06 14:51   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:51 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:39PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP resources access check.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  linux-user/main.c       |    6 ++++++
>  target-mips/cpu.h       |   27 +++++++++++++++++++++++++--
>  target-mips/helper.c    |    3 +++
>  target-mips/translate.c |   23 +++++++++++++++++++++++
>  4 files changed, 57 insertions(+), 2 deletions(-)
> 
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 9f3476b..cd6523b 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -2281,6 +2281,12 @@ done_syscall:
>                  queue_signal(env, info.si_signo, &info);
>              }
>              break;
> +        case EXCP_DSPDIS:
> +            info.si_signo = TARGET_SIGILL;
> +            info.si_errno = 0;
> +            info.si_code = TARGET_ILL_ILLOPC;
> +            queue_signal(env, info.si_signo, &info);
> +            break;
>          default:
>              //        error:
>              fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index b7a5112..7d46603 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -415,7 +415,7 @@ struct CPUMIPSState {
>      int error_code;
>      uint32_t hflags;    /* CPU State */
>      /* TMASK defines different execution modes */
> -#define MIPS_HFLAG_TMASK  0x007FF
> +#define MIPS_HFLAG_TMASK  0xC07FF
>  #define MIPS_HFLAG_MODE   0x00007 /* execution modes                    */
>      /* The KSU flags must be the lowest bits in hflags. The flag order
>         must be the same as defined for CP0 Status. This allows to use
> @@ -453,6 +453,9 @@ struct CPUMIPSState {
>  #define MIPS_HFLAG_BDS32  0x10000 /* branch requires 32-bit delay slot  */
>  #define MIPS_HFLAG_BX     0x20000 /* branch exchanges execution mode    */
>  #define MIPS_HFLAG_BMASK  (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT)
> +    /* MIPS DSP resources access. */
> +#define MIPS_HFLAG_DSP   0x40000  /* Enable access to MIPS DSP resources. */
> +#define MIPS_HFLAG_DSPR2 0x80000  /* Enable access to MIPS DSPR2 resources. */
>      target_ulong btarget;        /* Jump / branch target               */
>      target_ulong bcond;          /* Branch condition (if needed)       */
>  
> @@ -610,8 +613,9 @@ enum {
>      EXCP_MDMX,
>      EXCP_C2E,
>      EXCP_CACHE, /* 32 */
> +    EXCP_DSPDIS,
>  
> -    EXCP_LAST = EXCP_CACHE,
> +    EXCP_LAST = EXCP_DSPDIS,
>  };
>  /* Dummy exception for conditional stores.  */
>  #define EXCP_SC 0x100
> @@ -772,6 +776,25 @@ static inline void compute_hflags(CPUMIPSState *env)
>      if (env->CP0_Status & (1 << CP0St_FR)) {
>          env->hflags |= MIPS_HFLAG_F64;
>      }
> +    if (env->insn_flags & ASE_DSPR2) {
> +        /* Enables access MIPS DSP resources
> +           on processors implementing one of these ASEs. If the MIPS DSP ASE is
> +           not implemented, this bit must be ignored on write and read as
> +           zero. */
> +        if (env->CP0_Status & (1 << CP0St_MX)) {
> +            env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2;
> +        }
> +
> +    } else if (env->insn_flags & ASE_DSP) {
> +        /* Enables access MIPS DSP resources
> +           on processors implementing one of these ASEs. If the MIPS DSP ASE is
> +           not implemented, this bit must be ignored on write and read as
> +           zero. */
> +        if (env->CP0_Status & (1 << CP0St_MX)) {
> +            env->hflags |= MIPS_HFLAG_DSP;
> +        }
> +
> +    }
>      if (env->insn_flags & ISA_MIPS32R2) {
>          if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
>              env->hflags |= MIPS_HFLAG_COP1X;
> diff --git a/target-mips/helper.c b/target-mips/helper.c
> index 4208bb2..edbe2b0 100644
> --- a/target-mips/helper.c
> +++ b/target-mips/helper.c
> @@ -592,6 +592,9 @@ void do_interrupt (CPUMIPSState *env)
>      case EXCP_THREAD:
>          cause = 25;
>          goto set_EPC;
> +    case EXCP_DSPDIS:
> +        cause = 26;
> +        goto set_EPC;
>      case EXCP_CACHE:
>          cause = 30;
>          if (env->CP0_Status & (1 << CP0St_BEV)) {
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index fa79d49..b724d24 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -942,6 +942,24 @@ static inline void check_cp1_registers(DisasContext *ctx, int regs)
>          generate_exception(ctx, EXCP_RI);
>  }
>  
> +/* Verify that the processor is running with DSP instructions enabled.
> +   This is enabled by CP0 Status register MX(24) bit.
> + */
> +
> +static inline void check_dsp(DisasContext *ctx)
> +{
> +    if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
> +        generate_exception(ctx, EXCP_DSPDIS);
> +    }
> +}
> +
> +static inline void check_dspr2(DisasContext *ctx)
> +{
> +    if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
> +        generate_exception(ctx, EXCP_DSPDIS);
> +    }
> +}
> +
>  /* This code generates a "reserved instruction" exception if the
>     CPU does not support the instruction set corresponding to flags. */
>  static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
> @@ -13196,6 +13214,11 @@ void cpu_state_reset(CPUMIPSState *env)
>      if (env->CP0_Config1 & (1 << CP0C1_FP)) {
>          env->CP0_Status |= (1 << CP0St_CU1);
>      }
> +    if (env->cpu_model->insn_flags & ASE_DSPR2) {
> +        env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2;
> +    } else if (env->cpu_model->insn_flags & ASE_DSP) {
> +        env->hflags |= MIPS_HFLAG_DSP;
> +    }
>  #else
>      if (env->hflags & MIPS_HFLAG_BMASK) {
>          /* If the exception was raised from a delay slot,

Looks fine to me.

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

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

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

* Re: [Qemu-devel] [PATCH v9 03/14] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 03/14] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Jia Liu
@ 2012-10-06 14:51   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:51 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:40PM +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 |  122 ++++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 95 insertions(+), 27 deletions(-)
> 
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index b724d24..1927781 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
> @@ -2113,33 +2114,75 @@ 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. */
>          MIPS_DEBUG("NOP");
>          return;
>      }
> +
> +    if (opc == OPC_MFHI || opc == OPC_MFLO) {
> +        acc = ((ctx->opcode) >> 21) & 0x03;
> +    } else {
> +        acc = ((ctx->opcode) >> 11) & 0x03;
> +    }
> +
> +    if (acc != 0) {
> +        check_dsp(ctx);
> +    }
> +
>      switch (opc) {
>      case OPC_MFHI:
> -        tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
> +#if defined(TARGET_MIPS64)
> +        if (acc != 0) {
> +            tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
> +        } else
> +#endif
> +        {
> +            tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
> +        }
>          opn = "mfhi";
>          break;
>      case OPC_MFLO:
> -        tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
> +#if defined(TARGET_MIPS64)
> +        if (acc != 0) {
> +            tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
> +        } else
> +#endif
> +        {
> +            tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
> +        }
>          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);
> +        if (reg != 0) {
> +#if defined(TARGET_MIPS64)
> +            if (acc != 0) {
> +                tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
> +            } else
> +#endif
> +            {
> +                tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
> +            }
> +        } else {
> +            tcg_gen_movi_tl(cpu_HI[acc], 0);
> +        }
>          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);
> +        if (reg != 0) {
> +#if defined(TARGET_MIPS64)
> +            if (acc != 0) {
> +                tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
> +            } else
> +#endif
> +            {
> +                tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
> +            }
> +        } else {
> +            tcg_gen_movi_tl(cpu_LO[acc], 0);
> +        }
>          opn = "mtlo";
>          break;
>      }
> @@ -2152,6 +2195,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:
> @@ -2214,6 +2258,10 @@ 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;
> +            if (acc != 0) {
> +                check_dsp(ctx);
> +            }
>  
>              tcg_gen_ext_tl_i64(t2, t0);
>              tcg_gen_ext_tl_i64(t3, t1);
> @@ -2223,8 +2271,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;
> @@ -2232,6 +2280,10 @@ 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;
> +            if (acc != 0) {
> +                check_dsp(ctx);
> +            }
>  
>              tcg_gen_ext32u_tl(t0, t0);
>              tcg_gen_ext32u_tl(t1, t1);
> @@ -2243,8 +2295,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;
> @@ -2291,41 +2343,49 @@ 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;
> +            if (acc != 0) {
> +                check_dsp(ctx);
> +            }
>  
>              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;
>      case OPC_MADDU:
> -       {
> +        {
>              TCGv_i64 t2 = tcg_temp_new_i64();
>              TCGv_i64 t3 = tcg_temp_new_i64();
> +            acc = ((ctx->opcode) >> 11) & 0x03;
> +            if (acc != 0) {
> +                check_dsp(ctx);
> +            }
>  
>              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;
> @@ -2333,19 +2393,23 @@ 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;
> +            if (acc != 0) {
> +                check_dsp(ctx);
> +            }
>  
>              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;
> @@ -2353,21 +2417,25 @@ 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;
> +            if (acc != 0) {
> +                check_dsp(ctx);
> +            }
>  
>              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;

Looks fine to me.

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

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

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

* Re: [Qemu-devel] [PATCH v9 04/14] target-mips-ase-dsp: Add branch instructions
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 04/14] target-mips-ase-dsp: Add branch instructions Jia Liu
@ 2012-10-06 14:51   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:51 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:41PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP Branch instructions.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/translate.c |   36 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
> 
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index 1927781..4103f24 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))
>  
> @@ -3224,6 +3232,16 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
>          }
>          btgt = ctx->pc + insn_bytes + offset;
>          break;
> +    case OPC_BPOSGE32:
> +#if defined(TARGET_MIPS64)
> +    case OPC_BPOSGE64:
> +        tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
> +#else
> +        tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
> +#endif
> +        bcond_compute = 1;
> +        btgt = ctx->pc + insn_bytes + offset;
> +        break;
>      case OPC_J:
>      case OPC_JAL:
>      case OPC_JALX:
> @@ -3412,6 +3430,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 " TARGET_FMT_lx, btgt);
> +            goto not_likely;
> +#if defined(TARGET_MIPS64)
> +        case OPC_BPOSGE64:
> +            tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
> +            MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
> +            goto not_likely;
> +#endif
>          case OPC_BLTZALS:
>          case OPC_BLTZAL:
>              ctx->hflags |= (opc == OPC_BLTZALS
> @@ -12582,6 +12610,14 @@ 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 */
> +#if defined(TARGET_MIPS64)
> +        case OPC_BPOSGE64:
> +#endif
> +            check_dsp(ctx);
> +            gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
> +            *is_branch = 1;
> +            break;
>          default:            /* Invalid */
>              MIPS_INVAL("regimm");
>              generate_exception(ctx, EXCP_RI);

Looks fine to me.

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

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

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

* Re: [Qemu-devel] [PATCH v9 05/14] target-mips-ase-dsp: Add load instructions
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 05/14] target-mips-ase-dsp: Add load instructions Jia Liu
@ 2012-10-06 14:51   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:51 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:42PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP Load instructions.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/translate.c |   84 +++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 84 insertions(+)
> 
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index 4103f24..6d5c475 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))
>  
> @@ -12213,6 +12227,58 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b
>  
>  #endif
>  
> +/* MIPSDSP functions. */
> +static void gen_mipsdsp_ld(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
> +                           int rd, int base, int offset)
> +{
> +    const char *opn = "ldx";
> +    TCGv t0;
> +
> +    if (rd == 0 && env->insn_flags & (ASE_DSP | ASE_DSPR2)) {
> +        /* Loongson CPU uses a load to zero register for prefetch.
> +           We emulate it as a NOP. On other CPU we must perform the
> +           actual memory access. */
> +        MIPS_DEBUG("NOP");
> +        return;
> +    }

I don't really understand why Loongson is playing a role there. This
part should simply be dropped.

> +    t0 = tcg_temp_new();
> +    gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);

base or offset can be register 0, in that case it won't work.

> +    save_cpu_state(ctx, 0);
> +
> +    switch (opc) {
> +    case OPC_LBUX:
> +        op_ld_lbu(t0, t0, ctx);
> +        gen_store_gpr(t0, rd);
> +        opn = "lbux";
> +        break;
> +    case OPC_LHX:
> +        op_ld_lh(t0, t0, ctx);
> +        gen_store_gpr(t0, rd);
> +        opn = "lhx";
> +        break;
> +    case OPC_LWX:
> +        op_ld_lw(t0, t0, ctx);
> +        gen_store_gpr(t0, rd);
> +        opn = "lwx";
> +        break;
> +#if defined(TARGET_MIPS64)
> +    case OPC_LDX:
> +        op_ld_ld(t0, t0, ctx);
> +        gen_store_gpr(t0, rd);
> +        opn = "ldx";
> +        break;
> +#endif
> +    }
> +    (void)opn; /* avoid a compiler warning */
> +    MIPS_DEBUG("%s %s, %s(%s)", opn,
> +               regnames[rd], regnames[offset], regnames[base]);
> +    tcg_temp_free(t0);
> +}
> +
> +
> +/* End MIPSDSP functions. */
> +
>  static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>  {
>      int32_t offset;
> @@ -12568,6 +12634,24 @@ 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:
> +            check_dsp(ctx);

As ctx is passed to gen_mipsdsp_ld(), the check might be moved there.

> +            op2 = MASK_LX(ctx->opcode);
> +            switch (op2) {
> +#if defined(TARGET_MIPS64)
> +            case OPC_LDX:
> +#endif
> +            case OPC_LBUX:
> +            case OPC_LHX:
> +            case OPC_LWX:
> +                gen_mipsdsp_ld(env, ctx, op2, rd, rs, rt);
> +                break;
> +            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.10.2 (Apple Git-33)
> 
> 

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

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

* Re: [Qemu-devel] [PATCH v9 06/14] target-mips-ase-dsp: Add arithmetic instructions
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 06/14] target-mips-ase-dsp: Add arithmetic instructions Jia Liu
@ 2012-10-06 14:51   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:51 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:43PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP Arithmetic instructions.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/dsp_helper.c |  895 ++++++++++++++++++++++++++++++++++++++++++++++
>  target-mips/helper.h     |  126 +++++++
>  target-mips/translate.c  |  830 +++++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 1848 insertions(+), 3 deletions(-)
> 
> diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
> index b04b489..555a5ed 100644
> --- a/target-mips/dsp_helper.c
> +++ b/target-mips/dsp_helper.c
> @@ -1119,3 +1119,898 @@ static inline int32_t mipsdsp_cmp_lt(uint32_t a, uint32_t b)
>      return a < b;
>  }
>  /*** 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
> +
> +#define MIPSDSP_SPLIT32_8(num, a, b, c, d)  \
> +    do {                                    \
> +        a = (num >> 24) & MIPSDSP_Q0;       \
> +        b = (num >> 16) & MIPSDSP_Q0;       \
> +        c = (num >> 8) & MIPSDSP_Q0;        \
> +        d = num & MIPSDSP_Q0;               \
> +    } while (0)
> +
> +#define MIPSDSP_SPLIT32_16(num, a, b)       \
> +    do {                                    \
> +        a = (num >> 16) & MIPSDSP_LO;       \
> +        b = num & MIPSDSP_LO;               \
> +    } while (0)
> +
> +#define MIPSDSP_RETURN32(a)             ((target_long)(int32_t)a)
> +#define MIPSDSP_RETURN32_8(a, b, c, d)  ((target_long)(int32_t) \
> +                                         (((uint32_t)a << 24) | \
> +                                         (((uint32_t)b << 16) | \
> +                                         (((uint32_t)c << 8) |  \
> +                                          ((uint32_t)d & 0xFF)))))
> +#define MIPSDSP_RETURN32_16(a, b)       ((target_long)(int32_t) \
> +                                         (((uint32_t)a << 16) | \
> +                                          ((uint32_t)b & 0xFFFF)))
> +
> +#ifdef TARGET_MIPS64
> +#define MIPSDSP_SPLIT64_16(num, a, b, c, d)  \
> +    do {                                     \
> +        a = (num >> 48) & MIPSDSP_LO;        \
> +        b = (num >> 32) & MIPSDSP_LO;        \
> +        c = (num >> 16) & MIPSDSP_LO;        \
> +        d = num & MIPSDSP_LO;                \
> +    } while (0)
> +
> +#define MIPSDSP_SPLIT64_32(num, a, b)       \
> +    do {                                    \
> +        a = (num >> 32) & MIPSDSP_LLO;      \
> +        b = num & MIPSDSP_LLO;              \
> +    } while (0)
> +
> +#define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)a << 48) | \
> +                                         ((uint64_t)b << 32) | \
> +                                         ((uint64_t)c << 16) | \
> +                                         (uint64_t)d)
> +#define MIPSDSP_RETURN64_32(a, b)       (((uint64_t)a << 32) | (uint64_t)b)
> +#endif
> +
> +/** DSP Arithmetic Sub-class insns **/
> +#define ARITH_PH(name, func)                                      \
> +target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt) \
> +{                                                                 \
> +    uint16_t  rsh, rsl, rth, rtl, temph, templ;                   \
> +                                                                  \
> +    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                             \
> +    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
> +                                                                  \
> +    temph = mipsdsp_##func(rsh, rth);                             \
> +    templ = mipsdsp_##func(rsl, rtl);                             \
> +                                                                  \
> +    return MIPSDSP_RETURN32_16(temph, templ);                     \
> +}
> +
> +#define ARITH_PH_ENV(name, func)                                  \
> +target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt, \
> +                                CPUMIPSState *env)                \
> +{                                                                 \
> +    uint16_t  rsh, rsl, rth, rtl, temph, templ;                   \
> +                                                                  \
> +    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                             \
> +    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
> +                                                                  \
> +    temph = mipsdsp_##func(rsh, rth, env);                        \
> +    templ = mipsdsp_##func(rsl, rtl, env);                        \
> +                                                                  \
> +    return MIPSDSP_RETURN32_16(temph, templ);                     \
> +}
> +
> +
> +ARITH_PH_ENV(addq, add_i16);
> +ARITH_PH_ENV(addq_s, sat_add_i16);
> +ARITH_PH_ENV(addu, add_u16);
> +ARITH_PH_ENV(addu_s, sat_add_u16);
> +
> +ARITH_PH(addqh, rshift1_add_q16);
> +ARITH_PH(addqh_r, rrshift1_add_q16);
> +
> +ARITH_PH_ENV(subq, sub_i16);
> +ARITH_PH_ENV(subq_s, sat16_sub);
> +ARITH_PH_ENV(subu, sub_u16_u16);
> +ARITH_PH_ENV(subu_s, satu16_sub_u16_u16);
> +
> +ARITH_PH(subqh, rshift1_sub_q16);
> +ARITH_PH(subqh_r, rrshift1_sub_q16);
> +
> +#undef ARITH_PH
> +#undef ARITH_PH_ENV
> +
> +#ifdef TARGET_MIPS64
> +#define ARITH_QH_ENV(name, func) \
> +target_ulong helper_##name##_qh(target_ulong rs, target_ulong rt, \
> +                                CPUMIPSState *env)           \
> +{                                                            \
> +    uint16_t rs3, rs2, rs1, rs0;                             \
> +    uint16_t rt3, rt2, rt1, rt0;                             \
> +    uint16_t tempD, tempC, tempB, tempA;                     \
> +                                                             \
> +    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);              \
> +    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);              \
> +                                                             \
> +    tempD = mipsdsp_##func(rs3, rt3, env);                   \
> +    tempC = mipsdsp_##func(rs2, rt2, env);                   \
> +    tempB = mipsdsp_##func(rs1, rt1, env);                   \
> +    tempA = mipsdsp_##func(rs0, rt0, env);                   \
> +                                                             \
> +    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
> +}
> +
> +ARITH_QH_ENV(addq, add_i16);
> +ARITH_QH_ENV(addq_s, sat_add_i16);
> +ARITH_QH_ENV(addu, add_u16);
> +ARITH_QH_ENV(addu_s, sat_add_u16);
> +
> +ARITH_QH_ENV(subq, sub_i16);
> +ARITH_QH_ENV(subq_s, sat16_sub);
> +ARITH_QH_ENV(subu, sub_u16_u16);
> +ARITH_QH_ENV(subu_s, satu16_sub_u16_u16);
> +
> +#undef ARITH_QH_ENV
> +
> +#endif
> +
> +#define ARITH_W(name, func) \
> +target_ulong helper_##name##_w(target_ulong rs, target_ulong rt) \
> +{                                                                \
> +    uint32_t rd;                                                 \
> +    rd = mipsdsp_##func(rs, rt);                                 \
> +    return MIPSDSP_RETURN32(rd);                                 \
> +}
> +
> +#define ARITH_W_ENV(name, func) \
> +target_ulong helper_##name##_w(target_ulong rs, target_ulong rt, \
> +                               CPUMIPSState *env)                \
> +{                                                                \
> +    uint32_t rd;                                                 \
> +    rd = mipsdsp_##func(rs, rt, env);                            \
> +    return MIPSDSP_RETURN32(rd);                                 \
> +}
> +
> +ARITH_W_ENV(addq_s, sat_add_i32);
> +
> +ARITH_W(addqh, rshift1_add_q32);
> +ARITH_W(addqh_r, rrshift1_add_q32);
> +
> +ARITH_W_ENV(subq_s, sat32_sub);
> +
> +ARITH_W(subqh, rshift1_sub_q32);
> +ARITH_W(subqh_r, rrshift1_sub_q32);
> +
> +#undef ARITH_W
> +#undef ARITH_W_ENV
> +
> +target_ulong helper_absq_s_w(target_ulong rt, CPUMIPSState *env)
> +{
> +    uint32_t rd;
> +
> +    rd = mipsdsp_sat_abs_u32(rt, env);
> +
> +    return (target_ulong)rd;
> +}
> +
> +
> +#if defined(TARGET_MIPS64)
> +
> +#define ARITH_PW_ENV(name, func) \
> +target_ulong helper_##name##_pw(target_ulong rs, target_ulong rt, \
> +                                CPUMIPSState *env)                \
> +{                                                                 \
> +    uint32_t rs1, rs0;                                            \
> +    uint32_t rt1, rt0;                                            \
> +    uint32_t tempB, tempA;                                        \
> +                                                                  \
> +    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                             \
> +    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
> +                                                                  \
> +    tempB = mipsdsp_##func(rs1, rt1, env);                        \
> +    tempA = mipsdsp_##func(rs0, rt0, env);                        \
> +                                                                  \
> +    return MIPSDSP_RETURN64_32(tempB, tempA);                     \
> +}
> +
> +ARITH_PW_ENV(addq, add_i32);
> +ARITH_PW_ENV(addq_s, sat_add_i32);
> +ARITH_PW_ENV(subq, sub32);
> +ARITH_PW_ENV(subq_s, sat32_sub);
> +
> +#undef ARITH_PW_ENV
> +
> +#endif
> +
> +#define ARITH_QB(name, func) \
> +target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \
> +{                                                                 \
> +    uint8_t  rs0, rs1, rs2, rs3;                                  \
> +    uint8_t  rt0, rt1, rt2, rt3;                                  \
> +    uint8_t  temp0, temp1, temp2, temp3;                          \
> +                                                                  \
> +    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                    \
> +    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                    \
> +                                                                  \
> +    temp0 = mipsdsp_##func(rs0, rt0);                             \
> +    temp1 = mipsdsp_##func(rs1, rt1);                             \
> +    temp2 = mipsdsp_##func(rs2, rt2);                             \
> +    temp3 = mipsdsp_##func(rs3, rt3);                             \
> +                                                                  \
> +    return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0);        \
> +}
> +
> +#define ARITH_QB_ENV(name, func) \
> +target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt, \
> +                                CPUMIPSState *env)          \
> +{                                                           \
> +    uint8_t  rs0, rs1, rs2, rs3;                            \
> +    uint8_t  rt0, rt1, rt2, rt3;                            \
> +    uint8_t  temp0, temp1, temp2, temp3;                    \
> +                                                            \
> +    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);              \
> +    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);              \
> +                                                            \
> +    temp0 = mipsdsp_##func(rs0, rt0, env);                  \
> +    temp1 = mipsdsp_##func(rs1, rt1, env);                  \
> +    temp2 = mipsdsp_##func(rs2, rt2, env);                  \
> +    temp3 = mipsdsp_##func(rs3, rt3, env);                  \
> +                                                            \
> +    return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0);  \
> +}
> +
> +ARITH_QB(adduh, rshift1_add_u8);
> +ARITH_QB(adduh_r, rrshift1_add_u8);
> +
> +ARITH_QB_ENV(addu, add_u8);
> +ARITH_QB_ENV(addu_s, sat_add_u8);
> +
> +#undef ADDU_QB
> +#undef ADDU_QB_ENV
> +
> +#if defined(TARGET_MIPS64)
> +#define ARITH_OB(name, func) \
> +target_ulong helper_##name##_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_##func(rs_t[i], rt_t[i]);               \
> +        result |= (uint64_t)temp[i] << (8 * i);                   \
> +    }                                                             \
> +                                                                  \
> +    return result;                                                \
> +}
> +
> +#define ARITH_OB_ENV(name, func) \
> +target_ulong helper_##name##_ob(target_ulong rs, target_ulong rt, \
> +                                CPUMIPSState *env)                \
> +{                                                                 \
> +    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_##func(rs_t[i], rt_t[i], env);          \
> +        result |= (uint64_t)temp[i] << (8 * i);                   \
> +    }                                                             \
> +                                                                  \
> +    return result;                                                \
> +}
> +
> +ARITH_OB_ENV(addu, add_u8);
> +ARITH_OB_ENV(addu_s, sat_add_u8);
> +
> +ARITH_OB(adduh, rshift1_add_u8);
> +ARITH_OB(adduh_r, rrshift1_add_u8);
> +
> +ARITH_OB_ENV(subu, sub_u8);
> +ARITH_OB_ENV(subu_s, satu8_sub);
> +
> +ARITH_OB(subuh, rshift1_sub_u8);
> +ARITH_OB(subuh_r, rrshift1_sub_u8);
> +
> +#undef ARITH_OB
> +#undef ARITH_OB_ENV
> +
> +#endif
> +
> +#define SUBU_QB(name, func) \
> +target_ulong helper_##name##_qb(target_ulong rs,               \
> +                                target_ulong rt,               \
> +                                CPUMIPSState *env)             \
> +{                                                              \
> +    uint8_t rs3, rs2, rs1, rs0;                                \
> +    uint8_t rt3, rt2, rt1, rt0;                                \
> +    uint8_t tempD, tempC, tempB, tempA;                        \
> +                                                               \
> +    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                 \
> +    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                 \
> +                                                               \
> +    tempD = mipsdsp_##func(rs3, rt3, env);                     \
> +    tempC = mipsdsp_##func(rs2, rt2, env);                     \
> +    tempB = mipsdsp_##func(rs1, rt1, env);                     \
> +    tempA = mipsdsp_##func(rs0, rt0, env);                     \
> +                                                               \
> +    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);     \
> +}
> +
> +SUBU_QB(subu, sub_u8);
> +SUBU_QB(subu_s, satu8_sub);
> +
> +#undef SUBU_QB
> +
> +#define SUBUH_QB(name, var) \
> +target_ulong helper_##name##_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;                           \
> +                                                                  \
> +    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                    \
> +    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                    \
> +                                                                  \
> +    tempD = ((uint16_t)rs3 - (uint16_t)rt3 + var) >> 1;           \
> +    tempC = ((uint16_t)rs2 - (uint16_t)rt2 + var) >> 1;           \
> +    tempB = ((uint16_t)rs1 - (uint16_t)rt1 + var) >> 1;           \
> +    tempA = ((uint16_t)rs0 - (uint16_t)rt0 + var) >> 1;           \
> +                                                                  \
> +    return ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) |    \
> +           ((uint32_t)tempB << 8) | (uint32_t)tempA;              \
> +}
> +

Why not using (uint32_t)MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA)
here?

> +SUBUH_QB(subuh, 0);
> +SUBUH_QB(subuh_r, 1);
> +
> +#undef SUBUH_QB
> +
> +target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
> +{
> +    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(flag, env);
> +
> +    return (target_long)(int32_t)(temp & MIPSDSP_LLO);
> +}
> +
> +target_ulong helper_addwc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
> +{
> +    uint32_t rd;
> +    int32_t temp32, temp31;
> +    int64_t tempL;
> +
> +    tempL = (int32_t)rs + (int32_t)rt + get_DSPControl_carryflag(env);
> +    temp31 = (tempL >> 31) & 0x01;
> +    temp32 = (tempL >> 32) & 0x01;
> +
> +    if (temp31 != temp32) {
> +        set_DSPControl_overflow_flag(1, 20, env);
> +    }
> +
> +    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;
> +
> +    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);
> +
> +    temp = (uint16_t)rs3 + (uint16_t)rs2 + (uint16_t)rs1 + (uint16_t)rs0;
> +
> +    return (target_ulong)temp;
> +}
> +
> +#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(target_ulong rt, CPUMIPSState *env)
> +{
> +    uint32_t rd;
> +    int8_t tempD, tempC, tempB, tempA;
> +
> +    MIPSDSP_SPLIT32_8(rt, tempD, tempC, tempB, tempA);
> +
> +    rd = (((uint32_t)mipsdsp_sat_abs_u8 (tempD, env) << 24) & MIPSDSP_Q3) |
> +         (((uint32_t)mipsdsp_sat_abs_u8 (tempC, env) << 16) & MIPSDSP_Q2) |
> +         (((uint32_t)mipsdsp_sat_abs_u8 (tempB, env) <<  8) & MIPSDSP_Q1) |
> +         ((uint32_t)mipsdsp_sat_abs_u8 (tempA, env) & MIPSDSP_Q0);
> +
> +    return (target_ulong)rd;
> +}

The result is supposed to be signed extended, so you should use
MIPSDSP_RETURN32_8 instead.

> +
> +target_ulong helper_absq_s_ph(target_ulong rt, CPUMIPSState *env)
> +{
> +    uint32_t rd;
> +    int16_t tempB, tempA;
> +
> +    MIPSDSP_SPLIT32_16(rt, tempB, tempA);
> +
> +    rd = ((uint32_t)(uint16_t)mipsdsp_sat_abs_u16 (tempB, env) << 16) |
> +        ((uint32_t)((uint16_t)mipsdsp_sat_abs_u16 (tempA, env)) & 0xFFFF);
> +
> +    return (target_long)(int32_t)rd;
> +}

There you can use MIPSDSP_RETURN32_16.

> +#if defined(TARGET_MIPS64)
> +target_ulong helper_absq_s_ob(target_ulong rt, CPUMIPSState *env)
> +{
> +    int i;
> +    int8_t temp[8];
> +    uint64_t result;
> +
> +    for (i = 0; i < 8; i++) {
> +        temp[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
> +        temp[i] = mipsdsp_sat_abs_u8(temp[i], env);
> +    }
> +
> +    for (i = 0; i < 8; i++) {
> +        result = (uint64_t)(uint8_t)temp[i] << (8 * i);
> +    }
> +
> +    return result;
> +}
> +
> +target_ulong helper_absq_s_qh(target_ulong rt, CPUMIPSState *env)
> +{
> +    int16_t tempD, tempC, tempB, tempA;
> +
> +    MIPSDSP_SPLIT64_16(rt, tempD, tempC, tempB, tempA);
> +
> +    tempD = mipsdsp_sat_abs_u16(tempD, env);
> +    tempC = mipsdsp_sat_abs_u16(tempC, env);
> +    tempB = mipsdsp_sat_abs_u16(tempB, env);
> +    tempA = mipsdsp_sat_abs_u16(tempA, env);
> +
> +    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
> +}
> +
> +target_ulong helper_absq_s_pw(target_ulong rt, CPUMIPSState *env)
> +{
> +    int32_t tempB, tempA;
> +
> +    MIPSDSP_SPLIT64_32(rt, tempB, tempA);
> +
> +    tempB = mipsdsp_sat_abs_u32(tempB, env);
> +    tempA = mipsdsp_sat_abs_u32(tempA, env);
> +
> +    return MIPSDSP_RETURN64_32(tempB, tempA);
> +}
> +#endif
> +
> +#define PRECR_QB_PH(name, a, b)\
> +target_ulong helper_##name##_qb_ph(target_ulong rs, target_ulong rt) \
> +{                                                                    \
> +    uint8_t tempD, tempC, tempB, tempA;                              \
> +                                                                     \
> +    tempD = (rs >> a) & MIPSDSP_Q0;                                  \
> +    tempC = (rs >> b) & MIPSDSP_Q0;                                  \
> +    tempB = (rt >> a) & MIPSDSP_Q0;                                  \
> +    tempA = (rt >> b) & MIPSDSP_Q0;                                  \
> +                                                                     \
> +    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);           \
> +}
> +
> +PRECR_QB_PH(precr, 16, 0);
> +PRECR_QB_PH(precrq, 24, 8);
> +
> +#undef PRECR_QB_OH
> +
> +target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs,
> +                                   target_ulong rt)
> +{
> +    uint16_t tempB, tempA;
> +
> +    tempB = ((int32_t)rt >> sa) & MIPSDSP_LO;
> +    tempA = ((int32_t)rs >> sa) & MIPSDSP_LO;
> +
> +    return MIPSDSP_RETURN32_16(tempB, tempA);
> +}
> +
> +target_ulong helper_precr_sra_r_ph_w(uint32_t sa,
> +                                     target_ulong rs, target_ulong rt)
> +{
> +    uint64_t tempB, tempA;
> +
> +    /* If sa = 0, then (sa - 1) = -1 will case shift error, so we need else. */
> +    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;
> +
> +    tempB = (rs & MIPSDSP_HI) >> 16;
> +    tempA = (rt & MIPSDSP_HI) >> 16;
> +
> +    return MIPSDSP_RETURN32_16(tempB, tempA);
> +}
> +
> +target_ulong helper_precrq_rs_ph_w(target_ulong rs, target_ulong rt,
> +                                   CPUMIPSState *env)
> +{
> +    uint16_t tempB, tempA;
> +
> +    tempB = mipsdsp_trunc16_sat16_round(rs, env);
> +    tempA = mipsdsp_trunc16_sat16_round(rt, env);
> +
> +    return MIPSDSP_RETURN32_16(tempB, tempA);
> +}
> +
> +#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;
> +}
> +
> +#define PRECR_QH_PW(name, var) \
> +target_ulong helper_precr_##name##_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;                              \
> +                                                                      \
> +    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);                       \
> +    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                       \
> +                                                                      \
> +    /* When sa = 0, we use rt2, rt0, rs2, rs0;                        \
> +     * when sa != 0, we use rt3, rt1, rs3, rs1. */                    \
> +    if (sa == 0) {                                                    \
> +        tempD = rt2 << var;                                           \
> +        tempC = rt0 << var;                                           \
> +        tempB = rs2 << var;                                           \
> +        tempA = rs0 << var;                                           \
> +    } else {                                                          \
> +        tempD = (((int16_t)rt3 >> sa) + var) >> var;                  \
> +        tempC = (((int16_t)rt1 >> sa) + var) >> var;                  \
> +        tempB = (((int16_t)rs3 >> sa) + var) >> var;                  \
> +        tempA = (((int16_t)rs1 >> sa) + var) >> var;                  \
> +    }                                                                 \
> +                                                                      \
> +    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);           \
> +}
> +
> +PRECR_QH_PW(sra, 0);
> +PRECR_QH_PW(sra_r, 1);
> +
> +#undef PRECR_QH_PW
> +
> +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;
> +
> +    tempD = (rs >> 48) & MIPSDSP_LO;
> +    tempC = (rs >> 16) & MIPSDSP_LO;
> +    tempB = (rt >> 48) & MIPSDSP_LO;
> +    tempA = (rt >> 16) & MIPSDSP_LO;
> +
> +    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
> +}
> +
> +target_ulong helper_precrq_rs_qh_pw(target_ulong rs, target_ulong rt,
> +                                    CPUMIPSState *env)
> +{
> +    uint32_t rs2, rs0;
> +    uint32_t rt2, rt0;
> +    uint16_t tempD, tempC, tempB, tempA;
> +
> +    rs2 = (rs >> 32) & MIPSDSP_LLO;
> +    rs0 = rs & MIPSDSP_LLO;
> +    rt2 = (rt >> 32) & MIPSDSP_LLO;
> +    rt0 = rt & MIPSDSP_LLO;
> +
> +    tempD = mipsdsp_trunc16_sat16_round(rs2, env);
> +    tempC = mipsdsp_trunc16_sat16_round(rs0, env);
> +    tempB = mipsdsp_trunc16_sat16_round(rt2, env);
> +    tempA = mipsdsp_trunc16_sat16_round(rt0, env);
> +
> +    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
> +}
> +
> +target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt)
> +{
> +    uint32_t tempB, tempA;
> +
> +    tempB = (rs >> 32) & MIPSDSP_LLO;
> +    tempA = (rt >> 32) & MIPSDSP_LLO;
> +
> +    return MIPSDSP_RETURN64_32(tempB, tempA);
> +}
> +#endif
> +
> +target_ulong helper_precrqu_s_qb_ph(target_ulong rs, target_ulong rt,
> +                                    CPUMIPSState *env)
> +{
> +    uint8_t  tempD, tempC, tempB, tempA;
> +    uint16_t rsh, rsl, rth, rtl;
> +
> +    rsh = (rs & MIPSDSP_HI) >> 16;
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +    rtl =  rt & MIPSDSP_LO;
> +
> +    tempD = mipsdsp_sat8_reduce_precision(rsh, env);
> +    tempC = mipsdsp_sat8_reduce_precision(rsl, env);
> +    tempB = mipsdsp_sat8_reduce_precision(rth, env);
> +    tempA = mipsdsp_sat8_reduce_precision(rtl, env);
> +
> +    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_precrqu_s_ob_qh(target_ulong rs, target_ulong rt,
> +                                    CPUMIPSState *env)
> +{
> +    int i;
> +    uint16_t rs3, rs2, rs1, rs0;
> +    uint16_t rt3, rt2, rt1, rt0;
> +    uint8_t temp[8];
> +    uint64_t result;
> +
> +    result = 0;
> +
> +    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
> +    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
> +
> +    temp[7] = mipsdsp_sat8_reduce_precision(rs3, env);
> +    temp[6] = mipsdsp_sat8_reduce_precision(rs2, env);
> +    temp[5] = mipsdsp_sat8_reduce_precision(rs1, env);
> +    temp[4] = mipsdsp_sat8_reduce_precision(rs0, env);
> +    temp[3] = mipsdsp_sat8_reduce_precision(rt3, env);
> +    temp[2] = mipsdsp_sat8_reduce_precision(rt2, env);
> +    temp[1] = mipsdsp_sat8_reduce_precision(rt1, env);
> +    temp[0] = mipsdsp_sat8_reduce_precision(rt0, env);
> +
> +    for (i = 0; i < 8; i++) {
> +        result |= (uint64_t)temp[i] << (8 * i);
> +    }
> +
> +    return result;
> +}
> +
> +#define PRECEQ_PW(name, a, b) \
> +target_ulong helper_preceq_pw_##name(target_ulong rt) \
> +{                                                       \
> +    uint16_t tempB, tempA;                              \
> +    uint32_t tempBI, tempAI;                            \
> +                                                        \
> +    tempB = (rt >> a) & MIPSDSP_LO;                     \
> +    tempA = (rt >> b) & MIPSDSP_LO;                     \
> +                                                        \
> +    tempBI = (uint32_t)tempB << 16;                     \
> +    tempAI = (uint32_t)tempA << 16;                     \
> +                                                        \
> +    return MIPSDSP_RETURN64_32(tempBI, tempAI);         \
> +}
> +
> +PRECEQ_PW(qhl, 48, 32);
> +PRECEQ_PW(qhr, 16, 0);
> +PRECEQ_PW(qhla, 48, 16);
> +PRECEQ_PW(qhra, 32, 0);
> +
> +#undef PRECEQ_PW
> +
> +#endif
> +
> +#define PRECEQU_PH(name, a, b) \
> +target_ulong helper_precequ_ph_##name(target_ulong rt) \
> +{                                                        \
> +    uint16_t tempB, tempA;                               \
> +                                                         \
> +    tempB = (rt >> a) & MIPSDSP_Q0;                      \
> +    tempA = (rt >> b) & MIPSDSP_Q0;                      \
> +                                                         \
> +    tempB = tempB << 7;                                  \
> +    tempA = tempA << 7;                                  \
> +                                                         \
> +    return MIPSDSP_RETURN32_16(tempB, tempA);            \
> +}
> +
> +PRECEQU_PH(qbl, 24, 16);
> +PRECEQU_PH(qbr, 8, 0);
> +PRECEQU_PH(qbla, 24, 8);
> +PRECEQU_PH(qbra, 16, 0);
> +
> +#undef PRECEQU_PH
> +
> +#if defined(TARGET_MIPS64)
> +#define PRECEQU_QH(name, a, b, c, d) \
> +target_ulong helper_precequ_qh_##name(target_ulong rt)       \
> +{                                                            \
> +    uint16_t tempD, tempC, tempB, tempA;                     \
> +                                                             \
> +    tempD = (rt >> a) & MIPSDSP_Q0;                          \
> +    tempC = (rt >> b) & MIPSDSP_Q0;                          \
> +    tempB = (rt >> c) & MIPSDSP_Q0;                          \
> +    tempA = (rt >> d) & MIPSDSP_Q0;                          \
> +                                                             \
> +    tempD = tempD << 7;                                      \
> +    tempC = tempC << 7;                                      \
> +    tempB = tempB << 7;                                      \
> +    tempA = tempA << 7;                                      \
> +                                                             \
> +    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
> +}
> +
> +PRECEQU_QH(obl, 56, 48, 40, 32);
> +PRECEQU_QH(obr, 24, 16, 8, 0);
> +PRECEQU_QH(obla, 56, 40, 24, 8);
> +PRECEQU_QH(obra, 48, 32, 16, 0);
> +
> +#undef PRECEQU_QH
> +
> +#endif
> +
> +#define PRECEU_PH(name, a, b) \
> +target_ulong helper_preceu_ph_##name(target_ulong rt) \
> +{                                                     \
> +    uint16_t tempB, tempA;                            \
> +                                                      \
> +    tempB = (rt >> a) & MIPSDSP_Q0;                   \
> +    tempA = (rt >> b) & MIPSDSP_Q0;                   \
> +                                                      \
> +    return MIPSDSP_RETURN32_16(tempB, tempA);         \
> +}
> +
> +PRECEU_PH(qbl, 24, 16);
> +PRECEU_PH(qbr, 8, 0);
> +PRECEU_PH(qbla, 24, 8);
> +PRECEU_PH(qbra, 16, 0);
> +
> +#undef PRECEU_PH
> +
> +#if defined(TARGET_MIPS64)
> +#define PRECEU_QH(name, a, b, c, d) \
> +target_ulong helper_preceu_qh_##name(target_ulong rt)        \
> +{                                                            \
> +    uint16_t tempD, tempC, tempB, tempA;                     \
> +                                                             \
> +    tempD = (rt >> a) & MIPSDSP_Q0;                          \
> +    tempC = (rt >> b) & MIPSDSP_Q0;                          \
> +    tempB = (rt >> c) & MIPSDSP_Q0;                          \
> +    tempA = (rt >> d) & MIPSDSP_Q0;                          \
> +                                                             \
> +    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
> +}
> +
> +PRECEU_QH(obl, 56, 48, 40, 32);
> +PRECEU_QH(obr, 24, 16, 8, 0);
> +PRECEU_QH(obla, 56, 40, 24, 8);
> +PRECEU_QH(obra, 48, 32, 16, 0);
> +
> +#undef PRECEU_QH
> +
> +#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
> +
> +#undef MIPSDSP_SPLIT32_8
> +#undef MIPSDSP_SPLIT32_16
> +
> +#undef MIPSDSP_RETURN32
> +#undef MIPSDSP_RETURN32_8
> +#undef MIPSDSP_RETURN32_16
> +
> +#ifdef TARGET_MIPS64
> +#undef MIPSDSP_SPLIT64_16
> +#undef MIPSDSP_SPLIT64_32
> +#undef MIPSDSP_RETURN64_16
> +#undef MIPSDSP_RETURN64_32
> +#endif
> diff --git a/target-mips/helper.h b/target-mips/helper.h
> index f35ed78..9201aae 100644
> --- a/target-mips/helper.h
> +++ b/target-mips/helper.h
> @@ -362,4 +362,130 @@ DEF_HELPER_FLAGS_2(pasubub, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
>  DEF_HELPER_FLAGS_1(biadd, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
>  DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
>  
> +/*** MIPS DSP ***/
> +/* DSP Arithmetic Sub-class insns */
> +DEF_HELPER_FLAGS_3(addq_ph, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(addq_s_ph, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(addq_qh, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(addq_s_qh, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(addq_s_w, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(addq_pw, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(addq_s_pw, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(addu_qb, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(addu_s_qb, 0, tl, tl, tl, env)
> +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, tl, tl, env)
> +DEF_HELPER_FLAGS_3(addu_s_ph, 0, tl, tl, tl, env)
> +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, tl, tl, env)
> +DEF_HELPER_FLAGS_3(addu_s_ob, 0, tl, tl, tl, env)
> +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, tl, tl, env)
> +DEF_HELPER_FLAGS_3(addu_s_qh, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(subq_ph, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(subq_s_ph, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(subq_qh, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(subq_s_qh, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(subq_s_w, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(subq_pw, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(subq_s_pw, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(subu_qb, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(subu_s_qb, 0, tl, tl, tl, env)
> +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, tl, tl, env)
> +DEF_HELPER_FLAGS_3(subu_s_ph, 0, tl, tl, tl, env)
> +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, tl, tl, env)
> +DEF_HELPER_FLAGS_3(subu_s_ob, 0, tl, tl, tl, env)
> +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, tl, tl, env)
> +DEF_HELPER_FLAGS_3(subu_s_qh, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(addsc, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(addwc, 0, tl, tl, tl, env)
> +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, tl, env)
> +DEF_HELPER_FLAGS_2(absq_s_ph, 0, tl, tl, env)
> +DEF_HELPER_FLAGS_2(absq_s_w, 0, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_2(absq_s_ob, 0, tl, tl, env)
> +DEF_HELPER_FLAGS_2(absq_s_qh, 0, tl, tl, env)
> +DEF_HELPER_FLAGS_2(absq_s_pw, 0, tl, tl, env)
> +#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, tl, tl, env)
> +#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, tl, tl, env)
> +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, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(precrqu_s_ob_qh,
> +                   TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl, env)
> +
> +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)
> +#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 6d5c475..d057b30 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))
>  
> @@ -12276,6 +12429,494 @@ static void gen_mipsdsp_ld(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
>      tcg_temp_free(t0);
>  }
>  
> +static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
> +                              int ret, int v1, int v2)
> +{
> +    const char *opn = "mipsdsp arith";
> +
> +    if (ret == 0) {
> +        /* Treat as NOP. */
> +        MIPS_DEBUG("NOP");
> +        return;
> +    }
> +
> +    switch (op1) {
> +    /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
> +    case OPC_MULT_G_2E:
> +        check_dspr2(ctx);
> +        switch (op2) {
> +        case OPC_ADDUH_QB:
> +            gen_helper_adduh_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_ADDUH_R_QB:
> +            gen_helper_adduh_r_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_ADDQH_PH:
> +            gen_helper_addqh_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_ADDQH_R_PH:
> +            gen_helper_addqh_r_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_ADDQH_W:
> +            gen_helper_addqh_w(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_ADDQH_R_W:
> +            gen_helper_addqh_r_w(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_SUBUH_QB:
> +            gen_helper_subuh_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_SUBUH_R_QB:
> +            gen_helper_subuh_r_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_SUBQH_PH:
> +            gen_helper_subqh_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_SUBQH_R_PH:
> +            gen_helper_subqh_r_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_SUBQH_W:
> +            gen_helper_subqh_w(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_SUBQH_R_W:
> +            gen_helper_subqh_r_w(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        }
> +        break;
> +    case OPC_ABSQ_S_PH_DSP:
> +        switch (op2) {
> +        case OPC_ABSQ_S_QB:
> +            check_dspr2(ctx);
> +            gen_helper_absq_s_qb(cpu_gpr[ret], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ABSQ_S_PH:
> +            check_dsp(ctx);
> +            gen_helper_absq_s_ph(cpu_gpr[ret], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ABSQ_S_W:
> +            check_dsp(ctx);
> +            gen_helper_absq_s_w(cpu_gpr[ret], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_PRECEQ_W_PHL:
> +            {
> +                TCGv temp = tcg_temp_new();;
> +                check_dsp(ctx);
> +                tcg_gen_andi_tl(temp, cpu_gpr[v2], 0xFFFF0000);
> +                tcg_gen_ext32s_tl(cpu_gpr[ret], temp);
> +                tcg_temp_free(temp);
> +                break;
> +            }
> +        case OPC_PRECEQ_W_PHR:
> +            {
> +                TCGv temp = tcg_temp_new();;
> +                check_dsp(ctx);
> +                tcg_gen_andi_tl(temp, cpu_gpr[v2], 0x0000FFFF);
> +                tcg_gen_shli_tl(temp, temp, 16);
> +                tcg_gen_ext32s_tl(cpu_gpr[ret], temp);
> +                tcg_temp_free(temp);
> +                break;
> +            }
> +        case OPC_PRECEQU_PH_QBL:
> +            check_dsp(ctx);
> +            gen_helper_precequ_ph_qbl(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEQU_PH_QBR:
> +            check_dsp(ctx);
> +            gen_helper_precequ_ph_qbr(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEQU_PH_QBLA:
> +            check_dsp(ctx);
> +            gen_helper_precequ_ph_qbla(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEQU_PH_QBRA:
> +            check_dsp(ctx);
> +            gen_helper_precequ_ph_qbra(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEU_PH_QBL:
> +            check_dsp(ctx);
> +            gen_helper_preceu_ph_qbl(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEU_PH_QBR:
> +            check_dsp(ctx);
> +            gen_helper_preceu_ph_qbr(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEU_PH_QBLA:
> +            check_dsp(ctx);
> +            gen_helper_preceu_ph_qbla(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEU_PH_QBRA:
> +            check_dsp(ctx);
> +            gen_helper_preceu_ph_qbra(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        }
> +        break;
> +    case OPC_ADDU_QB_DSP:
> +        switch (op2) {
> +        case OPC_ADDQ_PH:
> +            check_dsp(ctx);
> +            gen_helper_addq_ph(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDQ_S_PH:
> +            check_dsp(ctx);
> +            gen_helper_addq_s_ph(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDQ_S_W:
> +            check_dsp(ctx);
> +            gen_helper_addq_s_w(cpu_gpr[ret], cpu_gpr[v1],
> +                                cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDU_QB:
> +            check_dsp(ctx);
> +            gen_helper_addu_qb(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDU_S_QB:
> +            check_dsp(ctx);
> +            gen_helper_addu_s_qb(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDU_PH:
> +            check_dspr2(ctx);
> +            gen_helper_addu_ph(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDU_S_PH:
> +            check_dspr2(ctx);
> +            gen_helper_addu_s_ph(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBQ_PH:
> +            check_dsp(ctx);
> +            gen_helper_subq_ph(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBQ_S_PH:
> +            check_dsp(ctx);
> +            gen_helper_subq_s_ph(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBQ_S_W:
> +            check_dsp(ctx);
> +            gen_helper_subq_s_w(cpu_gpr[ret], cpu_gpr[v1],
> +                                cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBU_QB:
> +            check_dsp(ctx);
> +            gen_helper_subu_qb(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBU_S_QB:
> +            check_dsp(ctx);
> +            gen_helper_subu_s_qb(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBU_PH:
> +            check_dspr2(ctx);
> +            gen_helper_subu_ph(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBU_S_PH:
> +            check_dspr2(ctx);
> +            gen_helper_subu_s_ph(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDSC:
> +            check_dsp(ctx);
> +            gen_helper_addsc(cpu_gpr[ret], cpu_gpr[v1],
> +                             cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDWC:
> +            check_dsp(ctx);
> +            gen_helper_addwc(cpu_gpr[ret], cpu_gpr[v1],
> +                             cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_MODSUB:
> +            check_dsp(ctx);
> +            gen_helper_modsub(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_RADDU_W_QB:
> +            check_dsp(ctx);
> +            gen_helper_raddu_w_qb(cpu_gpr[ret], cpu_gpr[v1]);
> +            break;
> +        }
> +        break;
> +    case OPC_CMPU_EQ_QB_DSP:
> +        switch (op2) {
> +        case OPC_PRECR_QB_PH:
> +            check_dspr2(ctx);
> +            gen_helper_precr_qb_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECRQ_QB_PH:
> +            check_dsp(ctx);
> +            gen_helper_precrq_qb_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECR_SRA_PH_W:
> +            check_dspr2(ctx);
> +            {
> +                TCGv_i32 sa_t = tcg_const_i32(v2);
> +                gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t,
> +                                       cpu_gpr[v1], cpu_gpr[ret]);
> +                tcg_temp_free_i32(sa_t);
> +                break;
> +            }
> +        case OPC_PRECR_SRA_R_PH_W:
> +            check_dspr2(ctx);
> +            {
> +                TCGv_i32 sa_t = tcg_const_i32(v2);
> +                gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t,
> +                                        cpu_gpr[v1], cpu_gpr[ret]);
> +                tcg_temp_free_i32(sa_t);
> +                break;
> +            }
> +        case OPC_PRECRQ_PH_W:
> +            check_dsp(ctx);
> +            gen_helper_precrq_ph_w(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECRQ_RS_PH_W:
> +            check_dsp(ctx);
> +            gen_helper_precrq_rs_ph_w(cpu_gpr[ret], cpu_gpr[v1],
> +                                      cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_PRECRQU_S_QB_PH:
> +            check_dsp(ctx);
> +            gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], cpu_gpr[v1],
> +                                       cpu_gpr[v2], cpu_env);
> +            break;
> +        }
> +        break;
> +#ifdef TARGET_MIPS64
> +    case OPC_ABSQ_S_QH_DSP:
> +        switch (op2) {
> +        case OPC_PRECEQ_L_PWL:
> +            check_dsp(ctx);
> +            tcg_gen_andi_tl(cpu_gpr[ret], cpu_gpr[v2], 0xFFFFFFFF00000000ull);
> +            break;
> +        case OPC_PRECEQ_L_PWR:
> +            check_dsp(ctx);
> +            tcg_gen_andi_tl(cpu_gpr[ret], cpu_gpr[v2], 0xFFFFFFFFull);
> +            break;
> +        case OPC_PRECEQ_PW_QHL:
> +            check_dsp(ctx);
> +            gen_helper_preceq_pw_qhl(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEQ_PW_QHR:
> +            check_dsp(ctx);
> +            gen_helper_preceq_pw_qhr(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEQ_PW_QHLA:
> +            check_dsp(ctx);
> +            gen_helper_preceq_pw_qhla(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEQ_PW_QHRA:
> +            check_dsp(ctx);
> +            gen_helper_preceq_pw_qhra(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEQU_QH_OBL:
> +            check_dsp(ctx);
> +            gen_helper_precequ_qh_obl(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEQU_QH_OBR:
> +            check_dsp(ctx);
> +            gen_helper_precequ_qh_obr(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEQU_QH_OBLA:
> +            check_dsp(ctx);
> +            gen_helper_precequ_qh_obla(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEQU_QH_OBRA:
> +            check_dsp(ctx);
> +            gen_helper_precequ_qh_obra(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEU_QH_OBL:
> +            check_dsp(ctx);
> +            gen_helper_preceu_qh_obl(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEU_QH_OBR:
> +            check_dsp(ctx);
> +            gen_helper_preceu_qh_obr(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEU_QH_OBLA:
> +            check_dsp(ctx);
> +            gen_helper_preceu_qh_obla(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECEU_QH_OBRA:
> +            check_dsp(ctx);
> +            gen_helper_preceu_qh_obra(cpu_gpr[ret], cpu_gpr[v2]);
> +            break;
> +        case OPC_ABSQ_S_OB:
> +            check_dspr2(ctx);
> +            gen_helper_absq_s_ob(cpu_gpr[ret], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ABSQ_S_PW:
> +            check_dsp(ctx);
> +            gen_helper_absq_s_pw(cpu_gpr[ret], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ABSQ_S_QH:
> +            check_dsp(ctx);
> +            gen_helper_absq_s_qh(cpu_gpr[ret], cpu_gpr[v2], cpu_env);
> +            break;
> +        }
> +        break;
> +    case OPC_ADDU_OB_DSP:
> +        switch (op2) {
> +        case OPC_RADDU_L_OB:
> +            check_dsp(ctx);
> +            gen_helper_raddu_l_ob(cpu_gpr[ret], cpu_gpr[v1]);
> +            break;
> +        case OPC_SUBQ_PW:
> +            check_dsp(ctx);
> +            gen_helper_subq_pw(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBQ_S_PW:
> +            check_dsp(ctx);
> +            gen_helper_subq_s_pw(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBQ_QH:
> +            check_dsp(ctx);
> +            gen_helper_subq_qh(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBQ_S_QH:
> +            check_dsp(ctx);
> +            gen_helper_subq_s_qh(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBU_OB:
> +            check_dsp(ctx);
> +            gen_helper_subu_ob(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBU_S_OB:
> +            check_dsp(ctx);
> +            gen_helper_subu_s_ob(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBU_QH:
> +            check_dspr2(ctx);
> +            gen_helper_subu_qh(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBU_S_QH:
> +            check_dspr2(ctx);
> +            gen_helper_subu_s_qh(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_SUBUH_OB:
> +            check_dspr2(ctx);
> +            gen_helper_subuh_ob(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_SUBUH_R_OB:
> +            check_dspr2(ctx);
> +            gen_helper_subuh_r_ob(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_ADDQ_PW:
> +            check_dsp(ctx);
> +            gen_helper_addq_pw(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDQ_S_PW:
> +            check_dsp(ctx);
> +            gen_helper_addq_s_pw(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDQ_QH:
> +            check_dsp(ctx);
> +            gen_helper_addq_qh(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDQ_S_QH:
> +            check_dsp(ctx);
> +            gen_helper_addq_s_qh(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDU_OB:
> +            check_dsp(ctx);
> +            gen_helper_addu_ob(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDU_S_OB:
> +            check_dsp(ctx);
> +            gen_helper_addu_s_ob(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDU_QH:
> +            check_dspr2(ctx);
> +            gen_helper_addu_qh(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDU_S_QH:
> +            check_dspr2(ctx);
> +            gen_helper_addu_s_qh(cpu_gpr[ret], cpu_gpr[v1],
> +                                 cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_ADDUH_OB:
> +            check_dspr2(ctx);
> +            gen_helper_adduh_ob(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_ADDUH_R_OB:
> +            check_dspr2(ctx);
> +            gen_helper_adduh_r_ob(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        }
> +        break;
> +    case OPC_CMPU_EQ_OB_DSP:
> +        switch (op2) {
> +        case OPC_PRECR_OB_QH:
> +            check_dspr2(ctx);
> +            gen_helper_precr_ob_qh(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECR_SRA_QH_PW:
> +            check_dspr2(ctx);
> +            {
> +                TCGv_i32 ret_t = tcg_const_i32(ret);
> +                gen_helper_precr_sra_qh_pw(cpu_gpr[v2], cpu_gpr[v1],
> +                                           cpu_gpr[v2], ret_t);
> +                tcg_temp_free_i32(ret_t);
> +                break;
> +            }
> +        case OPC_PRECR_SRA_R_QH_PW:
> +            check_dspr2(ctx);
> +            {
> +                TCGv_i32 sa_v = tcg_const_i32(ret);
> +                gen_helper_precr_sra_r_qh_pw(cpu_gpr[v2], cpu_gpr[v1],
> +                                             cpu_gpr[v2], sa_v);
> +                tcg_temp_free_i32(sa_v);
> +                break;
> +            }
> +        case OPC_PRECRQ_OB_QH:
> +            check_dsp(ctx);
> +            gen_helper_precrq_ob_qh(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECRQ_PW_L:
> +            check_dsp(ctx);
> +            gen_helper_precrq_pw_l(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECRQ_QH_PW:
> +            check_dsp(ctx);
> +            gen_helper_precrq_qh_pw(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_PRECRQ_RS_QH_PW:
> +            check_dsp(ctx);
> +            gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], cpu_gpr[v1],
> +                                       cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_PRECRQU_S_OB_QH:
> +            check_dsp(ctx);
> +            gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], cpu_gpr[v1],
> +                                       cpu_gpr[v2], cpu_env);
> +            break;
> +        }

All these functions should check for v1 and v2 being 0.

> +        break;
> +#endif
> +    }
> +
> +    (void)opn; /* avoid a compiler warning */
> +    MIPS_DEBUG("%s", opn);
> +}
>  
>  /* End MIPSDSP functions. */
>  
> @@ -12629,10 +13270,37 @@ 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:
>          case OPC_MOD_G_2E ... OPC_MODU_G_2E:
> -            check_insn(env, ctx, INSN_LOONGSON2E);
> -            gen_loongson_integer(ctx, op1, rd, rs, rt);
> +        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 ((env->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
> +                op2 = MASK_ADDUH_QB(ctx->opcode);
> +                switch (op2) {
> +                case OPC_ADDUH_QB:
> +                case OPC_ADDUH_R_QB:
> +                case OPC_ADDQH_PH:
> +                case OPC_ADDQH_R_PH:
> +                case OPC_ADDQH_W:
> +                case OPC_ADDQH_R_W:
> +                case OPC_SUBUH_QB:
> +                case OPC_SUBUH_R_QB:
> +                case OPC_SUBQH_PH:
> +                case OPC_SUBQH_R_PH:
> +                case OPC_SUBQH_W:
> +                case OPC_SUBQH_R_W:
> +                    gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
> +                    break;
> +                default:
> +                    MIPS_INVAL("MASK ADDUH.QB");
> +                    generate_exception(ctx, EXCP_RI);
> +                    break;
> +                }
> +            } else if (env->insn_flags & INSN_LOONGSON2E) {
> +                gen_loongson_integer(ctx, op1, rd, rs, rt);
> +            } else {
> +                generate_exception(ctx, EXCP_RI);
> +            }
>              break;
>          case OPC_LX_DSP:
>              check_dsp(ctx);
> @@ -12652,6 +13320,80 @@ 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:
> +            case OPC_ABSQ_S_PH:
> +            case OPC_ABSQ_S_W:
> +            case OPC_PRECEQ_W_PHL:
> +            case OPC_PRECEQ_W_PHR:
> +            case OPC_PRECEQU_PH_QBL:
> +            case OPC_PRECEQU_PH_QBR:
> +            case OPC_PRECEQU_PH_QBLA:
> +            case OPC_PRECEQU_PH_QBRA:
> +            case OPC_PRECEU_PH_QBL:
> +            case OPC_PRECEU_PH_QBR:
> +            case OPC_PRECEU_PH_QBLA:
> +            case OPC_PRECEU_PH_QBRA:
> +                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
> +                break;
> +            default:
> +                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:
> +            case OPC_ADDQ_S_PH:
> +            case OPC_ADDQ_S_W:
> +            case OPC_ADDU_QB:
> +            case OPC_ADDU_S_QB:
> +            case OPC_ADDU_PH:
> +            case OPC_ADDU_S_PH:
> +            case OPC_SUBQ_PH:
> +            case OPC_SUBQ_S_PH:
> +            case OPC_SUBQ_S_W:
> +            case OPC_SUBU_QB:
> +            case OPC_SUBU_S_QB:
> +            case OPC_SUBU_PH:
> +            case OPC_SUBU_S_PH:
> +            case OPC_ADDSC:
> +            case OPC_ADDWC:
> +            case OPC_MODSUB:
> +            case OPC_RADDU_W_QB:
> +                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
> +                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_SRA_PH_W:
> +            case OPC_PRECR_SRA_R_PH_W:
> +                gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
> +                break;
> +            case OPC_PRECR_QB_PH:
> +            case OPC_PRECRQ_QB_PH:
> +            case OPC_PRECRQ_PH_W:
> +            case OPC_PRECRQ_RS_PH_W:
> +            case OPC_PRECRQU_S_QB_PH:
> +                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, 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:
> @@ -12671,6 +13413,88 @@ 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_ABSQ_S_QH_DSP:
> +            op2 = MASK_ABSQ_S_QH(ctx->opcode);
> +            switch (op2) {
> +            case OPC_PRECEQ_L_PWL:
> +            case OPC_PRECEQ_L_PWR:
> +            case OPC_PRECEQ_PW_QHL:
> +            case OPC_PRECEQ_PW_QHR:
> +            case OPC_PRECEQ_PW_QHLA:
> +            case OPC_PRECEQ_PW_QHRA:
> +            case OPC_PRECEQU_QH_OBL:
> +            case OPC_PRECEQU_QH_OBR:
> +            case OPC_PRECEQU_QH_OBLA:
> +            case OPC_PRECEQU_QH_OBRA:
> +            case OPC_PRECEU_QH_OBL:
> +            case OPC_PRECEU_QH_OBR:
> +            case OPC_PRECEU_QH_OBLA:
> +            case OPC_PRECEU_QH_OBRA:
> +            case OPC_ABSQ_S_OB:
> +            case OPC_ABSQ_S_PW:
> +            case OPC_ABSQ_S_QH:
> +                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
> +                break;
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK ABSQ_S.QH");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
> +        case OPC_ADDU_OB_DSP:
> +            op2 = MASK_ADDU_OB(ctx->opcode);
> +            switch (op2) {
> +            case OPC_RADDU_L_OB:
> +            case OPC_SUBQ_PW:
> +            case OPC_SUBQ_S_PW:
> +            case OPC_SUBQ_QH:
> +            case OPC_SUBQ_S_QH:
> +            case OPC_SUBU_OB:
> +            case OPC_SUBU_S_OB:
> +            case OPC_SUBU_QH:
> +            case OPC_SUBU_S_QH:
> +            case OPC_SUBUH_OB:
> +            case OPC_SUBUH_R_OB:
> +            case OPC_ADDQ_PW:
> +            case OPC_ADDQ_S_PW:
> +            case OPC_ADDQ_QH:
> +            case OPC_ADDQ_S_QH:
> +            case OPC_ADDU_OB:
> +            case OPC_ADDU_S_OB:
> +            case OPC_ADDU_QH:
> +            case OPC_ADDU_S_QH:
> +            case OPC_ADDUH_OB:
> +            case OPC_ADDUH_R_OB:
> +                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
> +                break;
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK ADDU.OB");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
> +        case OPC_CMPU_EQ_OB_DSP:
> +            op2 = MASK_CMPU_EQ_OB(ctx->opcode);
> +            switch (op2) {
> +            case OPC_PRECR_SRA_QH_PW:
> +            case OPC_PRECR_SRA_R_QH_PW:
> +                /* Return value is rt. */
> +                gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
> +                break;
> +            case OPC_PRECR_OB_QH:
> +            case OPC_PRECRQ_OB_QH:
> +            case OPC_PRECRQ_PW_L:
> +            case OPC_PRECRQ_QH_PW:
> +            case OPC_PRECRQ_RS_QH_PW:
> +            case OPC_PRECRQU_S_OB_QH:
> +                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
> +                break;
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK CMPU_EQ.OB");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
>  #endif
>          default:            /* Invalid */
>              MIPS_INVAL("special3");
> -- 
> 1.7.10.2 (Apple Git-33)
> 
> 

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

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

* Re: [Qemu-devel] [PATCH v9 07/14] target-mips-ase-dsp: Add GPR-based shift instructions
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 07/14] target-mips-ase-dsp: Add GPR-based shift instructions Jia Liu
@ 2012-10-06 14:51   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:51 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:44PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP GPR-Based Shift instructions.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/dsp_helper.c |  256 +++++++++++++++++++++++++++++++++++
>  target-mips/helper.h     |   38 ++++++
>  target-mips/translate.c  |  332 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 626 insertions(+)
> 
> diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
> index 555a5ed..476f4e5 100644
> --- a/target-mips/dsp_helper.c
> +++ b/target-mips/dsp_helper.c
> @@ -1992,6 +1992,262 @@ PRECEU_QH(obra, 48, 32, 16, 0);
>  
>  #endif
>  
> +/** DSP GPR-Based Shift Sub-class insns **/
> +#define SHIFT_QB(name, func) \
> +target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt) \
> +{                                                                    \
> +    uint8_t rt3, rt2, rt1, rt0;                                      \
> +                                                                     \
> +    sa = sa & 0x07;                                                  \
> +                                                                     \
> +    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                       \
> +                                                                     \
> +    rt3 = mipsdsp_##func(rt3, sa);                                   \
> +    rt2 = mipsdsp_##func(rt2, sa);                                   \
> +    rt1 = mipsdsp_##func(rt1, sa);                                   \
> +    rt0 = mipsdsp_##func(rt0, sa);                                   \
> +                                                                     \
> +    return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0);                   \
> +}
> +
> +#define SHIFT_QB_ENV(name, func) \
> +target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt,\
> +                                CPUMIPSState *env) \
> +{                                                                    \
> +    uint8_t rt3, rt2, rt1, rt0;                                      \
> +                                                                     \
> +    sa = sa & 0x07;                                                  \
> +                                                                     \
> +    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                       \
> +                                                                     \
> +    rt3 = mipsdsp_##func(rt3, sa, env);                              \
> +    rt2 = mipsdsp_##func(rt2, sa, env);                              \
> +    rt1 = mipsdsp_##func(rt1, sa, env);                              \
> +    rt0 = mipsdsp_##func(rt0, sa, env);                              \
> +                                                                     \
> +    return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0);                   \
> +}
> +
> +SHIFT_QB_ENV(shll, lshift8);
> +SHIFT_QB(shrl, rshift_u8);
> +
> +SHIFT_QB(shra, rashift8);
> +SHIFT_QB(shra_r, rnd8_rashift);
> +
> +#undef SHIFT_QB
> +#undef SHIFT_QB_ENV
> +
> +#if defined(TARGET_MIPS64)
> +#define SHIFT_OB(name, func) \
> +target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \
> +{                                                                        \
> +    int i;                                                               \
> +    uint8_t rt_t[8];                                                     \
> +    uint64_t temp;                                                       \
> +                                                                         \
> +    sa = sa & 0x07;                                                      \
> +    temp = 0;                                                            \
> +                                                                         \
> +    for (i = 0; i < 8; i++) {                                            \
> +        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                          \
> +        rt_t[i] = mipsdsp_##func(rt_t[i], sa);                           \
> +        temp |= (uint64_t)rt_t[i] << (8 * i);                            \
> +    }                                                                    \
> +                                                                         \
> +    return temp;                                                         \
> +}
> +
> +#define SHIFT_OB_ENV(name, func) \
> +target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \
> +                                CPUMIPSState *env)                       \
> +{                                                                        \
> +    int i;                                                               \
> +    uint8_t rt_t[8];                                                     \
> +    uint64_t temp;                                                       \
> +                                                                         \
> +    sa = sa & 0x07;                                                      \
> +    temp = 0;                                                            \
> +                                                                         \
> +    for (i = 0; i < 8; i++) {                                            \
> +        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                          \
> +        rt_t[i] = mipsdsp_##func(rt_t[i], sa, env);                      \
> +        temp |= (uint64_t)rt_t[i] << (8 * i);                            \
> +    }                                                                    \
> +                                                                         \
> +    return temp;                                                         \
> +}
> +
> +SHIFT_OB_ENV(shll, lshift8);
> +SHIFT_OB(shrl, rshift_u8);
> +
> +SHIFT_OB(shra, rashift8);
> +SHIFT_OB(shra_r, rnd8_rashift);
> +
> +#undef SHIFT_OB
> +#undef SHIFT_OB_ENV
> +
> +#endif
> +
> +#define SHIFT_PH(name, func) \
> +target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt, \
> +                                CPUMIPSState *env)                \
> +{                                                                 \
> +    uint16_t rth, rtl;                                            \
> +                                                                  \
> +    sa = sa & 0x0F;                                               \
> +                                                                  \
> +    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
> +                                                                  \
> +    rth = mipsdsp_##func(rth, sa, env);                           \
> +    rtl = mipsdsp_##func(rtl, sa, env);                           \
> +                                                                  \
> +    return MIPSDSP_RETURN32_16(rth, rtl);                         \
> +}
> +
> +SHIFT_PH(shll, lshift16);
> +SHIFT_PH(shll_s, sat16_lshift);
> +
> +#undef SHIFT_PH
> +
> +#if defined(TARGET_MIPS64)
> +#define SHIFT_QH(name, func) \
> +target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa) \
> +{                                                                 \
> +    uint16_t rt3, rt2, rt1, rt0;                                  \
> +                                                                  \
> +    sa = sa & 0x0F;                                               \
> +                                                                  \
> +    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                   \
> +                                                                  \
> +    rt3 = mipsdsp_##func(rt3, sa);                                \
> +    rt2 = mipsdsp_##func(rt2, sa);                                \
> +    rt1 = mipsdsp_##func(rt1, sa);                                \
> +    rt0 = mipsdsp_##func(rt0, sa);                                \
> +                                                                  \
> +    return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0);               \
> +}
> +
> +#define SHIFT_QH_ENV(name, func) \
> +target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa, \
> +                                CPUMIPSState *env)                \
> +{                                                                 \
> +    uint16_t rt3, rt2, rt1, rt0;                                  \
> +                                                                  \
> +    sa = sa & 0x0F;                                               \
> +                                                                  \
> +    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                   \
> +                                                                  \
> +    rt3 = mipsdsp_##func(rt3, sa, env);                           \
> +    rt2 = mipsdsp_##func(rt2, sa, env);                           \
> +    rt1 = mipsdsp_##func(rt1, sa, env);                           \
> +    rt0 = mipsdsp_##func(rt0, sa, env);                           \
> +                                                                  \
> +    return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0);               \
> +}
> +
> +SHIFT_QH_ENV(shll, lshift16);
> +SHIFT_QH_ENV(shll_s, sat16_lshift);
> +
> +SHIFT_QH(shrl, rshift_u16);
> +SHIFT_QH(shra, rashift16);
> +SHIFT_QH(shra_r, rnd16_rashift);
> +
> +#undef SHIFT_QH
> +#undef SHIFT_QH_ENV
> +
> +#endif
> +
> +#define SHIFT_W(name, func) \
> +target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \
> +{                                                                       \
> +    uint32_t temp;                                                      \
> +                                                                        \
> +    sa = sa & 0x1F;                                                     \
> +    temp = mipsdsp_##func(rt, sa);                                      \
> +                                                                        \
> +    return (target_long)(int32_t)temp;                                  \
> +}
> +
> +#define SHIFT_W_ENV(name, func) \
> +target_ulong helper_##name##_w(target_ulong sa, target_ulong rt, \
> +                               CPUMIPSState *env) \
> +{                                                                       \
> +    uint32_t temp;                                                      \
> +                                                                        \
> +    sa = sa & 0x1F;                                                     \
> +    temp = mipsdsp_##func(rt, sa, env);                                 \
> +                                                                        \
> +    return (target_long)(int32_t)temp;                                  \
> +}
> +
> +SHIFT_W_ENV(shll_s, sat32_lshift);
> +SHIFT_W(shra_r, rnd32_rashift);
> +
> +#undef SHIFT_W
> +#undef SHIFT_W_ENV
> +
> +#if defined(TARGET_MIPS64)
> +#define SHIFT_PW(name, func) \
> +target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa) \
> +{                                                                 \
> +    uint32_t rt1, rt0;                                            \
> +                                                                  \
> +    sa = sa & 0x1F;                                               \
> +    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
> +                                                                  \
> +    rt1 = mipsdsp_##func(rt1, sa);                                \
> +    rt0 = mipsdsp_##func(rt0, sa);                                \
> +                                                                  \
> +    return MIPSDSP_RETURN64_32(rt1, rt0);                         \
> +}
> +
> +#define SHIFT_PW_ENV(name, func) \
> +target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa, \
> +                                CPUMIPSState *env)                \
> +{                                                                 \
> +    uint32_t rt1, rt0;                                            \
> +                                                                  \
> +    sa = sa & 0x1F;                                               \
> +    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
> +                                                                  \
> +    rt1 = mipsdsp_##func(rt1, sa, env);                           \
> +    rt0 = mipsdsp_##func(rt0, sa, env);                           \
> +                                                                  \
> +    return MIPSDSP_RETURN64_32(rt1, rt0);                         \
> +}
> +
> +SHIFT_PW_ENV(shll, lshift32);
> +SHIFT_PW_ENV(shll_s, sat32_lshift);
> +
> +SHIFT_PW(shra, rashift32);
> +SHIFT_PW(shra_r, rnd32_rashift);
> +
> +#undef SHIFT_PW
> +#undef SHIFT_PW_ENV
> +
> +#endif
> +
> +#define SHIFT_PH(name, func) \
> +target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \
> +{                                                                    \
> +    uint16_t rth, rtl;                                               \
> +                                                                     \
> +    sa = sa & 0x0F;                                                  \
> +                                                                     \
> +    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                \
> +                                                                     \
> +    rth = mipsdsp_##func(rth, sa);                                   \
> +    rtl = mipsdsp_##func(rtl, sa);                                   \
> +                                                                     \
> +    return MIPSDSP_RETURN32_16(rth, rtl);                            \
> +}
> +
> +SHIFT_PH(shrl, rshift_u16);
> +SHIFT_PH(shra, rashift16);
> +SHIFT_PH(shra_r, rnd16_rashift);
> +
> +#undef SHIFT_PH
> +
>  #undef MIPSDSP_LHI
>  #undef MIPSDSP_LLO
>  #undef MIPSDSP_HI
> diff --git a/target-mips/helper.h b/target-mips/helper.h
> index 9201aae..5258ef6 100644
> --- a/target-mips/helper.h
> +++ b/target-mips/helper.h
> @@ -488,4 +488,42 @@ 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, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(shll_ob, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(shll_ph, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(shll_s_ph, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(shll_qh, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(shll_s_qh, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(shll_s_w, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(shll_pw, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(shll_s_pw, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_2(shrl_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(shrl_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, tl)
> +DEF_HELPER_FLAGS_2(shrl_qh, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +#endif
> +DEF_HELPER_FLAGS_2(shra_qb, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(shra_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, tl)
> +DEF_HELPER_FLAGS_2(shra_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, tl, tl)
> +DEF_HELPER_FLAGS_2(shra_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, tl, tl)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_2(shra_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, tl)
> +DEF_HELPER_FLAGS_2(shra_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, tl)
> +#endif
> +
>  #include "def-helper.h"
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index d057b30..72e2703 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))
>  
> @@ -12918,6 +12989,261 @@ static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
>      MIPS_DEBUG("%s", opn);
>  }
>  
> +static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
> +                              int ret, int v1, int v2)
> +{
> +    uint32_t op2;
> +    const char *opn = "mipsdsp shift";
> +    TCGv t0 = tcg_const_tl(v1);
> +
> +    if (ret == 0) {
> +        /* Treat as NOP. */
> +        MIPS_DEBUG("NOP");
> +        return;
> +    }
> +
> +    switch (opc) {
> +    case OPC_SHLL_QB_DSP:
> +        {
> +            op2 = MASK_SHLL_QB(ctx->opcode);
> +            switch (op2) {
> +            case OPC_SHLL_QB:
> +                check_dsp(ctx);
> +                gen_helper_shll_qb(cpu_gpr[ret], t0,
> +                                   cpu_gpr[v2], cpu_env);
> +                break;
> +            case OPC_SHLLV_QB:
> +                check_dsp(ctx);
> +                gen_helper_shll_qb(cpu_gpr[ret], cpu_gpr[v1],
> +                                    cpu_gpr[v2], cpu_env);
> +                break;
> +            case OPC_SHLL_PH:
> +                check_dsp(ctx);
> +                gen_helper_shll_ph(cpu_gpr[ret], t0,
> +                                   cpu_gpr[v2], cpu_env);
> +                break;
> +            case OPC_SHLLV_PH:
> +                check_dsp(ctx);
> +                gen_helper_shll_ph(cpu_gpr[ret], cpu_gpr[v1],
> +                                    cpu_gpr[v2], cpu_env);
> +                break;
> +            case OPC_SHLL_S_PH:
> +                check_dsp(ctx);
> +                gen_helper_shll_s_ph(cpu_gpr[ret], t0,
> +                                     cpu_gpr[v2], cpu_env);
> +                break;
> +            case OPC_SHLLV_S_PH:
> +                check_dsp(ctx);
> +                gen_helper_shll_s_ph(cpu_gpr[ret], cpu_gpr[v1],
> +                                      cpu_gpr[v2], cpu_env);
> +                break;
> +            case OPC_SHLL_S_W:
> +                check_dsp(ctx);
> +                gen_helper_shll_s_w(cpu_gpr[ret], t0,
> +                                    cpu_gpr[v2], cpu_env);
> +                break;
> +            case OPC_SHLLV_S_W:
> +                check_dsp(ctx);
> +                gen_helper_shll_s_w(cpu_gpr[ret], cpu_gpr[v1],
> +                                     cpu_gpr[v2], cpu_env);
> +                break;
> +            case OPC_SHRL_QB:
> +                check_dsp(ctx);
> +                gen_helper_shrl_qb(cpu_gpr[ret], t0, cpu_gpr[v2]);
> +                break;
> +            case OPC_SHRLV_QB:
> +                check_dsp(ctx);
> +                gen_helper_shrl_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +                break;
> +            case OPC_SHRL_PH:
> +                check_dspr2(ctx);
> +                gen_helper_shrl_ph(cpu_gpr[ret], t0, cpu_gpr[v2]);
> +                break;
> +            case OPC_SHRLV_PH:
> +                check_dspr2(ctx);
> +                gen_helper_shrl_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +                break;
> +            case OPC_SHRA_QB:
> +                check_dspr2(ctx);
> +                gen_helper_shra_qb(cpu_gpr[ret], t0, cpu_gpr[v2]);
> +                break;
> +            case OPC_SHRA_R_QB:
> +                check_dspr2(ctx);
> +                gen_helper_shra_r_qb(cpu_gpr[ret], t0, cpu_gpr[v2]);
> +                break;
> +            case OPC_SHRAV_QB:
> +                check_dspr2(ctx);
> +                gen_helper_shra_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +                break;
> +            case OPC_SHRAV_R_QB:
> +                check_dspr2(ctx);
> +                gen_helper_shra_r_qb(cpu_gpr[ret], cpu_gpr[v1],
> +                                      cpu_gpr[v2]);
> +                break;
> +            case OPC_SHRA_PH:
> +                check_dsp(ctx);
> +                gen_helper_shra_ph(cpu_gpr[ret], t0, cpu_gpr[v2]);
> +                break;
> +            case OPC_SHRA_R_PH:
> +                check_dsp(ctx);
> +                gen_helper_shra_r_ph(cpu_gpr[ret], t0, cpu_gpr[v2]);
> +                break;
> +            case OPC_SHRAV_PH:
> +                check_dsp(ctx);
> +                gen_helper_shra_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +                break;
> +            case OPC_SHRAV_R_PH:
> +                check_dsp(ctx);
> +                gen_helper_shra_r_ph(cpu_gpr[ret], cpu_gpr[v1],
> +                                      cpu_gpr[v2]);
> +                break;
> +            case OPC_SHRA_R_W:
> +                check_dsp(ctx);
> +                gen_helper_shra_r_w(cpu_gpr[ret], t0, cpu_gpr[v2]);
> +                break;
> +            case OPC_SHRAV_R_W:
> +                check_dsp(ctx);
> +                gen_helper_shra_r_w(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +                break;
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK SHLL.QB");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
> +        }
> +#ifdef TARGET_MIPS64
> +    case OPC_SHLL_OB_DSP:
> +        op2 = MASK_SHLL_OB(ctx->opcode);
> +        switch (op2) {
> +        case OPC_SHLL_PW:
> +            check_dsp(ctx);
> +            gen_helper_shll_pw(cpu_gpr[ret], cpu_gpr[v2],
> +                               t0, cpu_env);
> +            break;
> +        case OPC_SHLLV_PW:
> +            check_dsp(ctx);
> +            gen_helper_shll_pw(cpu_gpr[ret], cpu_gpr[v2],
> +                                cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_SHLL_S_PW:
> +            check_dsp(ctx);
> +            gen_helper_shll_s_pw(cpu_gpr[ret], cpu_gpr[v2],
> +                                 t0, cpu_env);
> +            break;
> +        case OPC_SHLLV_S_PW:
> +            check_dsp(ctx);
> +            gen_helper_shll_s_pw(cpu_gpr[ret], cpu_gpr[v2],
> +                                  cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_SHLL_OB:
> +            check_dsp(ctx);
> +            gen_helper_shll_ob(cpu_gpr[ret], cpu_gpr[v2],
> +                               t0, cpu_env);
> +            break;
> +        case OPC_SHLLV_OB:
> +            check_dsp(ctx);
> +            gen_helper_shll_ob(cpu_gpr[ret], cpu_gpr[v2],
> +                                cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_SHLL_QH:
> +            check_dsp(ctx);
> +            gen_helper_shll_qh(cpu_gpr[ret], cpu_gpr[v2],
> +                               t0, cpu_env);
> +            break;
> +        case OPC_SHLLV_QH:
> +            check_dsp(ctx);
> +            gen_helper_shll_qh(cpu_gpr[ret], cpu_gpr[v2],
> +                                cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_SHLL_S_QH:
> +            check_dsp(ctx);
> +            gen_helper_shll_s_qh(cpu_gpr[ret], cpu_gpr[v2],
> +                                 t0, cpu_env);
> +            break;
> +        case OPC_SHLLV_S_QH:
> +            check_dsp(ctx);
> +            gen_helper_shll_s_qh(cpu_gpr[ret], cpu_gpr[v2],
> +                                  cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_SHRA_OB:
> +            check_dspr2(ctx);
> +            gen_helper_shra_ob(cpu_gpr[ret], cpu_gpr[v2], t0);
> +            break;
> +        case OPC_SHRAV_OB:
> +            check_dspr2(ctx);
> +            gen_helper_shra_ob(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
> +            break;
> +        case OPC_SHRA_R_OB:
> +            check_dspr2(ctx);
> +            gen_helper_shra_r_ob(cpu_gpr[ret], cpu_gpr[v2], t0);
> +            break;
> +        case OPC_SHRAV_R_OB:
> +            check_dspr2(ctx);
> +            gen_helper_shra_r_ob(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
> +            break;
> +        case OPC_SHRA_PW:
> +            check_dsp(ctx);
> +            gen_helper_shra_pw(cpu_gpr[ret], cpu_gpr[v2], t0);
> +            break;
> +        case OPC_SHRAV_PW:
> +            check_dsp(ctx);
> +            gen_helper_shra_pw(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
> +            break;
> +        case OPC_SHRA_R_PW:
> +            check_dsp(ctx);
> +            gen_helper_shra_r_pw(cpu_gpr[ret], cpu_gpr[v2], t0);
> +            break;
> +        case OPC_SHRAV_R_PW:
> +            check_dsp(ctx);
> +            gen_helper_shra_r_pw(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
> +            break;
> +        case OPC_SHRA_QH:
> +            check_dsp(ctx);
> +            gen_helper_shra_qh(cpu_gpr[ret], cpu_gpr[v2], t0);
> +            break;
> +        case OPC_SHRAV_QH:
> +            check_dsp(ctx);
> +            gen_helper_shra_qh(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
> +            break;
> +        case OPC_SHRA_R_QH:
> +            check_dsp(ctx);
> +            gen_helper_shra_r_qh(cpu_gpr[ret], cpu_gpr[v2], t0);
> +            break;
> +        case OPC_SHRAV_R_QH:
> +            check_dsp(ctx);
> +            gen_helper_shra_r_qh(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
> +            break;
> +        case OPC_SHRL_OB:
> +            check_dsp(ctx);
> +            gen_helper_shrl_ob(cpu_gpr[ret], cpu_gpr[v2], t0);
> +            break;
> +        case OPC_SHRLV_OB:
> +            check_dsp(ctx);
> +            gen_helper_shrl_ob(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
> +            break;
> +        case OPC_SHRL_QH:
> +            check_dspr2(ctx);
> +            gen_helper_shrl_qh(cpu_gpr[ret], cpu_gpr[v2], t0);
> +            break;
> +        case OPC_SHRLV_QH:
> +            check_dspr2(ctx);
> +            gen_helper_shrl_qh(cpu_gpr[ret], cpu_gpr[v2], cpu_gpr[v1]);
> +            break;
> +        default:            /* Invalid */
> +            MIPS_INVAL("MASK SHLL.OB");
> +            generate_exception(ctx, EXCP_RI);
> +            break;

All these functions should check for v1 and v2 being 0.

> +        }
> +        break;
> +#endif
> +    }
> +
> +    tcg_temp_free(t0);
> +    (void)opn; /* avoid a compiler warning */
> +    MIPS_DEBUG("%s", opn);
> +}
> +
>  /* End MIPSDSP functions. */
>  
>  static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
> @@ -13394,6 +13720,9 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>                  break;
>              }
>              break;
> +        case OPC_SHLL_QB_DSP:
> +            gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
> +            break;
>  #if defined(TARGET_MIPS64)
>          case OPC_DEXTM ... OPC_DEXT:
>          case OPC_DINSM ... OPC_DINS:
> @@ -13495,6 +13824,9 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>                  break;
>              }
>              break;
> +        case OPC_SHLL_OB_DSP:
> +            gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
> +            break;
>  #endif
>          default:            /* Invalid */
>              MIPS_INVAL("special3");
> -- 
> 1.7.10.2 (Apple Git-33)
> 
> 

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

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

* Re: [Qemu-devel] [PATCH v9 08/14] target-mips-ase-dsp: Add multiply instructions
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 08/14] target-mips-ase-dsp: Add multiply instructions Jia Liu
@ 2012-10-06 14:51   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:51 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:45PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP Multiply instructions.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/dsp_helper.c |  938 ++++++++++++++++++++++++++++++++++++++++++++++
>  target-mips/helper.h     |   91 +++++
>  target-mips/translate.c  |  531 ++++++++++++++++++++++++++
>  3 files changed, 1560 insertions(+)
> 
> diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
> index 476f4e5..b98be0d 100644
> --- a/target-mips/dsp_helper.c
> +++ b/target-mips/dsp_helper.c
> @@ -2248,6 +2248,944 @@ SHIFT_PH(shra_r, rnd16_rashift);
>  
>  #undef SHIFT_PH
>  
> +/** DSP Multiply Sub-class insns **/
> +/* Return value made up by two 16bits value.
> + * FIXME give the macro a better name.
> + */
> +#define MUL_RETURN32_16_PH(name, func, \
> +                           rsmov1, rsmov2, rsfilter, \
> +                           rtmov1, rtmov2, rtfilter) \
> +target_ulong helper_##name(target_ulong rs, target_ulong rt, \
> +                           CPUMIPSState *env)                \
> +{                                                            \
> +    uint16_t rsB, rsA, rtB, rtA;                             \
> +                                                             \
> +    rsB = (rs >> rsmov1) & rsfilter;                         \
> +    rsA = (rs >> rsmov2) & rsfilter;                         \
> +    rtB = (rt >> rtmov1) & rtfilter;                         \
> +    rtA = (rt >> rtmov2) & rtfilter;                         \
> +                                                             \
> +    rsB = mipsdsp_##func(rsB, rtB, env);                     \
> +    rsA = mipsdsp_##func(rsA, rtA, env);                     \
> +                                                             \
> +    return MIPSDSP_RETURN32_16(rsB, rsA);                    \
> +}
> +
> +MUL_RETURN32_16_PH(muleu_s_ph_qbl, mul_u8_u16, \
> +                      24, 16, MIPSDSP_Q0, \
> +                      16, 0, MIPSDSP_LO);
> +MUL_RETURN32_16_PH(muleu_s_ph_qbr, mul_u8_u16, \
> +                      8, 0, MIPSDSP_Q0, \
> +                      16, 0, MIPSDSP_LO);
> +MUL_RETURN32_16_PH(mulq_rs_ph, rndq15_mul_q15_q15, \
> +                      16, 0, MIPSDSP_LO, \
> +                      16, 0, MIPSDSP_LO);
> +MUL_RETURN32_16_PH(mul_ph, mul_i16_i16, \
> +                      16, 0, MIPSDSP_LO, \
> +                      16, 0, MIPSDSP_LO);
> +MUL_RETURN32_16_PH(mul_s_ph, sat16_mul_i16_i16, \
> +                      16, 0, MIPSDSP_LO, \
> +                      16, 0, MIPSDSP_LO);
> +MUL_RETURN32_16_PH(mulq_s_ph, sat16_mul_q15_q15, \
> +                      16, 0, MIPSDSP_LO, \
> +                      16, 0, MIPSDSP_LO);
> +
> +#undef MUL_RETURN32_16_PH
> +
> +#define MUL_RETURN32_32_ph(name, func, movbits) \
> +target_ulong helper_##name(target_ulong rs, target_ulong rt, \
> +                                  CPUMIPSState *env)         \
> +{                                                            \
> +    int16_t rsh, rth;                                        \
> +    int32_t temp;                                            \
> +                                                             \
> +    rsh = (rs >> movbits) & MIPSDSP_LO;                      \
> +    rth = (rt >> movbits) & MIPSDSP_LO;                      \
> +    temp = mipsdsp_##func(rsh, rth, env);                    \
> +                                                             \
> +    return (target_long)(int32_t)temp;                       \
> +}
> +
> +MUL_RETURN32_32_ph(muleq_s_w_phl, mul_q15_q15_overflowflag21, 16);
> +MUL_RETURN32_32_ph(muleq_s_w_phr, mul_q15_q15_overflowflag21, 0);
> +
> +#undef MUL_RETURN32_32_ph
> +
> +#define MUL_VOID_PH(name, use_ac_env) \
> +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
> +                          CPUMIPSState *env)                             \
> +{                                                                        \
> +    int16_t rsh, rsl, rth, rtl;                                          \
> +    int32_t tempB, tempA;                                                \
> +    int64_t acc, dotp;                                                   \
> +                                                                         \
> +    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                                    \
> +    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                    \
> +                                                                         \
> +    if (use_ac_env == 1) {                                               \
> +        tempB = mipsdsp_mul_q15_q15(ac, rsh, rth, env);                  \
> +        tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl, env);                  \
> +    } else {                                                             \
> +        tempB = mipsdsp_mul_u16_u16(rsh, rth);                           \
> +        tempA = mipsdsp_mul_u16_u16(rsl, rtl);                           \
> +    }                                                                    \
> +                                                                         \
> +    dotp = (int64_t)tempB - (int64_t)tempA;                              \
> +    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);  \
> +}
> +
> +MUL_VOID_PH(mulsaq_s_w_ph, 1);
> +MUL_VOID_PH(mulsa_w_ph, 0);
> +
> +#undef MUL_VOID_PH
> +
> +#if defined(TARGET_MIPS64)
> +#define MUL_RETURN64_16_QH(name, func, \
> +                           rsmov1, rsmov2, rsmov3, rsmov4, rsfilter, \
> +                           rtmov1, rtmov2, rtmov3, rtmov4, rtfilter) \
> +target_ulong helper_##name(target_ulong rs, target_ulong rt,         \
> +                           CPUMIPSState *env)                        \
> +{                                                                    \
> +    uint16_t rs3, rs2, rs1, rs0;                                     \
> +    uint16_t rt3, rt2, rt1, rt0;                                     \
> +    uint16_t tempD, tempC, tempB, tempA;                             \
> +                                                                     \
> +    rs3 = (rs >> rsmov1) & rsfilter;                                 \
> +    rs2 = (rs >> rsmov2) & rsfilter;                                 \
> +    rs1 = (rs >> rsmov3) & rsfilter;                                 \
> +    rs0 = (rs >> rsmov4) & rsfilter;                                 \
> +    rt3 = (rt >> rtmov1) & rtfilter;                                 \
> +    rt2 = (rt >> rtmov2) & rtfilter;                                 \
> +    rt1 = (rt >> rtmov3) & rtfilter;                                 \
> +    rt0 = (rt >> rtmov4) & rtfilter;                                 \
> +                                                                     \
> +    tempD = mipsdsp_##func(rs3, rt3, env);                           \
> +    tempC = mipsdsp_##func(rs2, rt2, env);                           \
> +    tempB = mipsdsp_##func(rs1, rt1, env);                           \
> +    tempA = mipsdsp_##func(rs0, rt0, env);                           \
> +                                                                     \
> +    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);          \
> +}
> +
> +MUL_RETURN64_16_QH(muleu_s_qh_obl, mul_u8_u16, \
> +                   56, 48, 40, 32, MIPSDSP_Q0, \
> +                   48, 32, 16, 0, MIPSDSP_LO);
> +MUL_RETURN64_16_QH(muleu_s_qh_obr, mul_u8_u16, \
> +                   24, 16, 8, 0, MIPSDSP_Q0, \
> +                   48, 32, 16, 0, MIPSDSP_LO);
> +MUL_RETURN64_16_QH(mulq_rs_qh, rndq15_mul_q15_q15, \
> +                   48, 32, 16, 0, MIPSDSP_LO, \
> +                   48, 32, 16, 0, MIPSDSP_LO);
> +
> +#undef MUL_RETURN64_16_QH
> +
> +#define MUL_RETURN64_32_QH(name, \
> +                           rsmov1, rsmov2, \
> +                           rtmov1, rtmov2) \
> +target_ulong helper_##name(target_ulong rs, target_ulong rt, \
> +                           CPUMIPSState *env)                \
> +{                                                            \
> +    uint16_t rsB, rsA;                                       \
> +    uint16_t rtB, rtA;                                       \
> +    uint32_t tempB, tempA;                                   \
> +                                                             \
> +    rsB = (rs >> rsmov1) & MIPSDSP_LO;                       \
> +    rsA = (rs >> rsmov2) & MIPSDSP_LO;                       \
> +    rtB = (rt >> rtmov1) & MIPSDSP_LO;                       \
> +    rtA = (rt >> rtmov2) & MIPSDSP_LO;                       \
> +                                                             \
> +    tempB = mipsdsp_mul_q15_q15(5, rsB, rtB, env);           \
> +    tempA = mipsdsp_mul_q15_q15(5, rsA, rtA, env);           \
> +                                                             \
> +    return ((uint64_t)tempB << 32) | (uint64_t)tempA;        \
> +}
> +
> +MUL_RETURN64_32_QH(muleq_s_pw_qhl, 48, 32, 48, 32);
> +MUL_RETURN64_32_QH(muleq_s_pw_qhr, 16, 0, 16, 0);
> +
> +#undef MUL_RETURN64_32_QH
> +
> +void helper_mulsaq_s_w_qh(target_ulong rs, target_ulong rt, uint32_t ac,
> +                          CPUMIPSState *env)
> +{
> +    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;
> +
> +    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
> +    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
> +
> +    tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env);
> +    tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env);
> +    tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env);
> +    tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env);
> +
> +    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] = ~0ull;
> +    }
> +
> +    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
> +
> +#define DP_QB(name, func, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
> +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
> +                   CPUMIPSState *env)                                    \
> +{                                                                        \
> +    uint8_t rs3, rs2;                                                    \
> +    uint8_t rt3, rt2;                                                    \
> +    uint16_t tempB, tempA;                                               \
> +    uint64_t tempC, dotp;                                                \
> +                                                                         \
> +    rs3 = (rs >> rsmov1) & MIPSDSP_Q0;                                   \
> +    rs2 = (rs >> rsmov2) & MIPSDSP_Q0;                                   \
> +    rt3 = (rt >> rtmov1) & MIPSDSP_Q0;                                   \
> +    rt2 = (rt >> rtmov2) & MIPSDSP_Q0;                                   \
> +    tempB = mipsdsp_##func(rs3, rt3);                                    \
> +    tempA = mipsdsp_##func(rs2, rt2);                                    \
> +    dotp = (int64_t)tempB + (int64_t)tempA;                              \
> +    if (is_add) {                                                        \
> +        tempC = (((uint64_t)env->active_tc.HI[ac] << 32) |               \
> +                 ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO))        \
> +            + dotp;                                                      \
> +    } else {                                                             \
> +        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); \
> +}
> +
> +DP_QB(dpau_h_qbl, mul_u8_u8, 1, 24, 16, 24, 16);
> +DP_QB(dpau_h_qbr, mul_u8_u8, 1, 8, 0, 8, 0);
> +DP_QB(dpsu_h_qbl, mul_u8_u8, 0, 24, 16, 24, 16);
> +DP_QB(dpsu_h_qbr, mul_u8_u8, 0, 8, 0, 8, 0);
> +
> +#undef DP_QB
> +
> +#if defined(TARGET_MIPS64)
> +#define DP_OB(name, add_sub, \
> +              rsmov1, rsmov2, rsmov3, rsmov4, \
> +              rtmov1, rtmov2, rtmov3, rtmov4) \
> +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,       \
> +                       CPUMIPSState *env)                               \
> +{                                                                       \
> +    uint8_t rsD, rsC, rsB, rsA;                                         \
> +    uint8_t rtD, rtC, rtB, rtA;                                         \
> +    uint16_t tempD, tempC, tempB, tempA;                                \
> +    uint64_t temp[2];                                                   \
> +    uint64_t acc[2];                                                    \
> +    uint64_t temp_sum;                                                  \
> +                                                                        \
> +    temp[0] = 0;                                                        \
> +    temp[1] = 0;                                                        \
> +                                                                        \
> +    rsD = (rs >> rsmov1) & MIPSDSP_Q0;                                  \
> +    rsC = (rs >> rsmov2) & MIPSDSP_Q0;                                  \
> +    rsB = (rs >> rsmov3) & MIPSDSP_Q0;                                  \
> +    rsA = (rs >> rsmov4) & MIPSDSP_Q0;                                  \
> +    rtD = (rt >> rtmov1) & MIPSDSP_Q0;                                  \
> +    rtC = (rt >> rtmov2) & MIPSDSP_Q0;                                  \
> +    rtB = (rt >> rtmov3) & MIPSDSP_Q0;                                  \
> +    rtA = (rt >> rtmov4) & MIPSDSP_Q0;                                  \
> +                                                                        \
> +    tempD = mipsdsp_mul_u8_u8(rsD, rtD);                                \
> +    tempC = mipsdsp_mul_u8_u8(rsC, rtC);                                \
> +    tempB = mipsdsp_mul_u8_u8(rsB, rtB);                                \
> +    tempA = mipsdsp_mul_u8_u8(rsA, rtA);                                \
> +                                                                        \
> +    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];                                     \
> +                                                                        \
> +    if (add_sub) {                                                      \
> +        temp_sum = acc[0] + temp[0];                                    \
> +        acc[1] = acc[1] + MIPSDSP_OVERFLOW(acc[0], temp[0], temp_sum,   \
> +                                             0x8000000000000000ull);    \
> +        temp[0] = temp_sum;                                             \
> +        temp[1] = acc[1] + temp[1];                                     \
> +    } else {                                                            \
> +        temp_sum = acc[0] - temp[0];                                    \
> +        acc[1] = acc[1] + MIPSDSP_OVERFLOW(acc[0], -temp[0], temp_sum,  \
> +                                             0x8000000000000000ull);    \
> +        temp[0] = temp_sum;                                             \
> +        temp[1] = acc[1] - temp[1];                                     \
> +    }                                                                   \
> +                                                                        \
> +    env->active_tc.HI[ac] = temp[1];                                    \
> +    env->active_tc.LO[ac] = temp[0];                                    \
> +}
> +
> +DP_OB(dpau_h_obl, 1, 56, 48, 40, 32, 56, 48, 40, 32);
> +DP_OB(dpau_h_obr, 1, 24, 16, 8, 0, 24, 16, 8, 0);
> +DP_OB(dpsu_h_obl, 0, 56, 48, 40, 32, 56, 48, 40, 32);
> +DP_OB(dpsu_h_obr, 0, 24, 16, 8, 0, 24, 16, 8, 0);
> +
> +#undef DP_OB
> +#endif
> +
> +#define DP_NOFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2)             \
> +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,              \
> +                   CPUMIPSState *env)                                          \
> +{                                                                              \
> +    uint16_t rsB, rsA, rtB, rtA;                                               \
> +    int32_t  tempA, tempB;                                                     \
> +    int64_t  acc;                                                              \
> +                                                                               \
> +    rsB = (rs >> rsmov1) & MIPSDSP_LO;                                         \
> +    rsA = (rs >> rsmov2) & MIPSDSP_LO;                                         \
> +    rtB = (rt >> rtmov1) & MIPSDSP_LO;                                         \
> +    rtA = (rt >> rtmov2) & MIPSDSP_LO;                                         \
> +                                                                               \
> +    tempB = (int32_t)rsB * (int32_t)rtB;                                       \
> +    tempA = (int32_t)rsA * (int32_t)rtA;                                       \
> +                                                                               \
> +    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                            \
> +          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);                     \
> +                                                                               \
> +    if (is_add) {                                                              \
> +        acc = acc + ((int64_t)tempB + (int64_t)tempA);                         \
> +    } else {                                                                   \
> +        acc = acc - ((int64_t)tempB + (int64_t)tempA);                         \
> +    }                                                                          \
> +                                                                               \
> +    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);         \
> +}
> +
> +DP_NOFUNC_PH(dpa_w_ph, 1, 16, 0, 16, 0);
> +DP_NOFUNC_PH(dpax_w_ph, 1, 16, 0, 0, 16);
> +DP_NOFUNC_PH(dps_w_ph, 0, 16, 0, 16, 0);
> +DP_NOFUNC_PH(dpsx_w_ph, 0, 16, 0, 0, 16);
> +#undef DP_NOFUNC_PH
> +
> +#define DP_HASFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
> +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,   \
> +                   CPUMIPSState *env)                      \
> +{                                                          \
> +    int16_t rsB, rsA, rtB, rtA;                            \
> +    int32_t tempB, tempA;                                  \
> +    int64_t acc, dotp;                                     \
> +                                                           \
> +    rsB = (rs >> rsmov1) & MIPSDSP_LO;                     \
> +    rsA = (rs >> rsmov2) & MIPSDSP_LO;                     \
> +    rtB = (rt >> rtmov1) & MIPSDSP_LO;                     \
> +    rtA = (rt >> rtmov2) & MIPSDSP_LO;                     \
> +                                                           \
> +    tempB = mipsdsp_mul_q15_q15(ac, rsB, rtB, env);        \
> +    tempA = mipsdsp_mul_q15_q15(ac, rsA, rtA, env);        \
> +                                                           \
> +    dotp = (int64_t)tempB + (int64_t)tempA;                \
> +    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |        \
> +          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
> +                                                           \
> +    if (is_add) {                                          \
> +        acc = acc + dotp;                                  \
> +    } else {                                               \
> +        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);                               \
> +}
> +
> +DP_HASFUNC_PH(dpaq_s_w_ph, 1, 16, 0, 16, 0);
> +DP_HASFUNC_PH(dpaqx_s_w_ph, 1, 16, 0, 0, 16);
> +DP_HASFUNC_PH(dpsq_s_w_ph, 0, 16, 0, 16, 0);
> +DP_HASFUNC_PH(dpsqx_s_w_ph, 0, 16, 0, 0, 16);
> +
> +#undef DP_HASFUNC_PH
> +
> +#define DP_128OPERATION_PH(name, is_add) \
> +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
> +                          CPUMIPSState *env)                             \
> +{                                                                        \
> +    int16_t rsh, rsl, rth, rtl;                                          \
> +    int32_t tempB, tempA, tempC62_31, tempC63;                           \
> +    int64_t acc, dotp, tempC;                                            \
> +                                                                         \
> +    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                                    \
> +    MIPSDSP_SPLIT32_16(rt, rth, rtl);                                    \
> +                                                                         \
> +    tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl, env);                      \
> +    tempA = mipsdsp_mul_q15_q15(ac, rsl, rth, env);                      \
> +                                                                         \
> +    dotp = (int64_t)tempB + (int64_t)tempA;                              \
> +    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                      \
> +          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);               \
> +    if (is_add) {                                                        \
> +        tempC = acc + dotp;                                              \
> +    } else {                                                             \
> +        tempC = acc - dotp;                                              \
> +    }                                                                    \
> +    tempC63 = (tempC >> 63) & 0x01;                                      \
> +    tempC62_31 = (tempC >> 31) & 0xFFFFFFFF;                             \
> +                                                                         \
> +    if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) {                  \
> +        tempC = 0x7FFFFFFF;                                              \
> +        set_DSPControl_overflow_flag(1, 16 + ac, env);                   \
> +    }                                                                    \
> +                                                                         \
> +    if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) {                  \
> +        tempC = 0xFFFFFFFF80000000ull;                                   \
> +        set_DSPControl_overflow_flag(1, 16 + ac, env);                   \
> +    }                                                                    \
> +                                                                         \
> +    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);                                           \
> +}
> +
> +DP_128OPERATION_PH(dpaqx_sa_w_ph, 1);
> +DP_128OPERATION_PH(dpsqx_sa_w_ph, 0);
> +
> +#undef DP_128OPERATION_HP
> +
> +#if defined(TARGET_MIPS64)
> +#define DP_QH(name, is_add, use_ac_env) \
> +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,    \
> +                   CPUMIPSState *env)                                \
> +{                                                                    \
> +    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;                                                \
> +                                                                     \
> +    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);                      \
> +    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);                      \
> +                                                                     \
> +    if (use_ac_env) {                                                \
> +        tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env);              \
> +        tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env);              \
> +        tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env);              \
> +        tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env);              \
> +    } else {                                                         \
> +        tempD = mipsdsp_mul_u16_u16(rs3, rt3);                       \
> +        tempC = mipsdsp_mul_u16_u16(rs2, rt2);                       \
> +        tempB = mipsdsp_mul_u16_u16(rs1, rt1);                       \
> +        tempA = mipsdsp_mul_u16_u16(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] >= 0) {                                              \
> +        temp[1] = 0;                                                 \
> +    } else {                                                         \
> +        temp[1] = ~0ull;                                             \
> +    }                                                                \
> +                                                                     \
> +    acc[1] = env->active_tc.HI[ac];                                  \
> +    acc[0] = env->active_tc.LO[ac];                                  \
> +                                                                     \
> +    if (is_add) {                                                    \
> +        temp_sum = acc[0] + temp[0];                                 \
> +        if (MIPSDSP_OVERFLOW(acc[0], temp[0], temp_sum,              \
> +                               0x8000000000000000ull)) {             \
> +            acc[1] = acc[1] + 1;                                     \
> +        }                                                            \
> +        temp[0] = temp_sum;                                          \
> +        temp[1] = acc[1] + temp[1];                                  \
> +    } else {                                                         \
> +        temp_sum = acc[0] - temp[0];                                 \
> +        if (MIPSDSP_OVERFLOW(acc[0], -temp[0], temp_sum,             \
> +                               0x8000000000000000ull)) {             \
> +            acc[1] = acc[1] - 1;                                     \
> +        }                                                            \
> +        temp[0] = temp_sum;                                          \
> +        temp[1] = acc[1] - temp[1];                                  \
> +    }                                                                \
> +                                                                     \
> +    env->active_tc.HI[ac] = temp[1];                                 \
> +    env->active_tc.LO[ac] = temp[0];                                 \
> +}
> +
> +DP_QH(dpa_w_qh, 1, 0);
> +DP_QH(dpaq_s_w_qh, 1, 1);
> +DP_QH(dps_w_qh, 0, 0);
> +DP_QH(dpsq_s_w_qh, 0, 1);
> +
> +#undef DP_QH
> +
> +#endif
> +
> +#define DP_L_W(name, is_add) \
> +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,     \
> +                   CPUMIPSState *env)                                 \
> +{                                                                     \
> +    int32_t temp64, temp63, tempacc63, tempdotp63, tempDL63;          \
> +    int64_t dotp, acc;                                                \
> +    int64_t tempDL[2];                                                \
> +    uint64_t temp;                                                    \
> +                                                                      \
> +    dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env);                      \
> +    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                   \
> +          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);            \
> +    if (is_add) {                                                     \
> +        tempDL[0] = acc + dotp;                                       \
> +    } else {                                                          \
> +        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(1, 16 + ac, env);                \
> +    }                                                                 \
> +                                                                      \
> +    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);                                         \
> +}
> +
> +DP_L_W(dpaq_sa_l_w, 1);
> +DP_L_W(dpsq_sa_l_w, 0);
> +
> +#undef DP_L_W
> +
> +#if defined(TARGET_MIPS64)
> +#define DP_L_PW(name, func) \
> +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
> +                   CPUMIPSState *env)                             \
> +{                                                                 \
> +    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;                                                  \
> +                                                                  \
> +    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                             \
> +    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
> +                                                                  \
> +    tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env);            \
> +    tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);            \
> +                                                                  \
> +    if (tempB[0] >= 0) {                                          \
> +        tempB[1] = 0x00;                                          \
> +    } else {                                                      \
> +        tempB[1] = ~0ull;                                         \
> +    }                                                             \
> +                                                                  \
> +    if (tempA[0] >= 0) {                                          \
> +        tempA[1] = 0x00;                                          \
> +    } else {                                                      \
> +        tempA[1] = ~0ull;                                         \
> +    }                                                             \
> +                                                                  \
> +    temp_sum = tempB[0] + tempA[0];                               \
> +    if (MIPSDSP_OVERFLOW(tempB[0], tempA[0], temp_sum,            \
> +                           0x8000000000000000ull)) {              \
> +        temp[1] += 1;                                             \
> +    }                                                             \
> +    temp[0] = temp_sum;                                           \
> +    temp[1] += tempB[1] + tempA[1];                               \
> +                                                                  \
> +    mipsdsp_##func(acc, ac, temp, env);                           \
> +                                                                  \
> +    env->active_tc.HI[ac] = acc[1];                               \
> +    env->active_tc.LO[ac] = acc[0];                               \
> +}
> +
> +DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63);
> +DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63);
> +
> +#undef DP_L_PW
> +
> +void helper_mulsaq_s_l_pw(target_ulong rs, target_ulong rt, uint32_t ac,
> +                          CPUMIPSState *env)
> +{
> +    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(ac, rs1, rt1, env);
> +    tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);
> +
> +    if (tempB[0] >= 0) {
> +        tempB[1] = 0x00;
> +    } else {
> +        tempB[1] = ~0ull;
> +    }
> +
> +    if (tempA[0] >= 0) {
> +        tempA[1] = 0x00;
> +    } else {
> +        tempA[1] = ~0ull;
> +    }
> +
> +    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] = ~0ull;
> +    }
> +
> +    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
> +
> +#define MAQ_S_W(name, mov) \
> +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
> +                   CPUMIPSState *env)                             \
> +{                                                                 \
> +    int16_t rsh, rth;                                             \
> +    int32_t tempA;                                                \
> +    int64_t tempL, acc;                                           \
> +                                                                  \
> +    rsh = (rs >> mov) & MIPSDSP_LO;                               \
> +    rth = (rt >> mov) & MIPSDSP_LO;                               \
> +    tempA  = mipsdsp_mul_q15_q15(ac, rsh, rth, env);              \
> +    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |               \
> +          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);        \
> +    tempL  = (int64_t)tempA + 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);                                    \
> +}
> +
> +MAQ_S_W(maq_s_w_phl, 16);
> +MAQ_S_W(maq_s_w_phr, 0);
> +
> +#undef MAQ_S_W
> +
> +#define MAQ_SA_W(name, mov) \
> +void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,        \
> +                   CPUMIPSState *env)                                    \
> +{                                                                        \
> +    int16_t rsh, rth;                                                    \
> +    int32_t tempA;                                                       \
> +                                                                         \
> +    rsh = (rs >> mov) & MIPSDSP_LO;                                      \
> +    rth = (rt >> mov) & MIPSDSP_LO;                                      \
> +    tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env);                      \
> +    tempA = mipsdsp_sat32_acc_q31(ac, tempA, env);                       \
> +                                                                         \
> +    env->active_tc.HI[ac] = (target_long)(int32_t)(((int64_t)tempA &     \
> +                                                    MIPSDSP_LHI) >> 32); \
> +    env->active_tc.LO[ac] = (target_long)(int32_t)((int64_t)tempA &      \
> +                                                   MIPSDSP_LLO);         \
> +}
> +
> +MAQ_SA_W(maq_sa_w_phl, 16);
> +MAQ_SA_W(maq_sa_w_phr, 0);
> +
> +#undef MAQ_SA_W
> +
> +#define MULQ_W(name, addvar) \
> +target_ulong helper_##name(target_ulong rs, target_ulong rt,   \
> +                           CPUMIPSState *env)                  \
> +{                                                              \
> +    uint32_t rs_t, rt_t;                                       \
> +    int32_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(1, 21, env);              \
> +    } else {                                                   \
> +        tempL  = ((int64_t)rs_t * (int64_t)rt_t) << 1;         \
> +        tempL += addvar;                                       \
> +    }                                                          \
> +    tempI = (tempL & MIPSDSP_LHI) >> 32;                       \
> +                                                               \
> +    return (target_long)(int32_t)tempI;                        \
> +}
> +
> +MULQ_W(mulq_s_w, 0);
> +MULQ_W(mulq_rs_w, 0x80000000ull);
> +
> +#undef MULQ_W
> +
> +#if defined(TARGET_MIPS64)
> +
> +#define MAQ_S_W_QH(name, mov) \
> +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
> +                   CPUMIPSState *env)                             \
> +{                                                                 \
> +    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 >> mov) & MIPSDSP_LO;                              \
> +    rt_t = (rt >> mov) & MIPSDSP_LO;                              \
> +    temp_mul = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env);          \
> +                                                                  \
> +    temp[0] = (int64_t)temp_mul;                                  \
> +    if (temp[0] >= 0) {                                           \
> +        temp[1] = 0x00;                                           \
> +    } else {                                                      \
> +        temp[1] = ~0ull;                                          \
> +    }                                                             \
> +                                                                  \
> +    acc[0] = env->active_tc.LO[ac];                               \
> +    acc[1] = env->active_tc.HI[ac];                               \
> +                                                                  \
> +    temp_sum = acc[0] + temp[0];                                  \
> +    if (MIPSDSP_OVERFLOW(acc[0], temp[0], temp_sum,               \
> +                           0x8000000000000000ull)) {              \
> +        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];                               \
> +}
> +
> +MAQ_S_W_QH(maq_s_w_qhll, 48);
> +MAQ_S_W_QH(maq_s_w_qhlr, 32);
> +MAQ_S_W_QH(maq_s_w_qhrl, 16);
> +MAQ_S_W_QH(maq_s_w_qhrr, 0);
> +
> +#undef MAQ_S_W_QH
> +
> +#define MAQ_SA_W(name, mov) \
> +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
> +                   CPUMIPSState *env)                             \
> +{                                                                 \
> +    int16_t rs_t, rt_t;                                           \
> +    int32_t temp;                                                 \
> +    int64_t acc[2];                                               \
> +                                                                  \
> +    rs_t = (rs >> mov) & MIPSDSP_LO;                              \
> +    rt_t = (rt >> mov) & MIPSDSP_LO;                              \
> +    temp = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env);              \
> +    temp = mipsdsp_sat32_acc_q31(ac, temp, env);                  \
> +                                                                  \
> +    acc[0] = (int64_t)(int32_t)temp;                              \
> +    if (acc[0] >= 0) {                                            \
> +        acc[1] = 0x00;                                            \
> +    } else {                                                      \
> +        acc[1] = ~0ull;                                           \
> +    }                                                             \
> +                                                                  \
> +    env->active_tc.HI[ac] = acc[1];                               \
> +    env->active_tc.LO[ac] = acc[0];                               \
> +}
> +
> +MAQ_SA_W(maq_sa_w_qhll, 48);
> +MAQ_SA_W(maq_sa_w_qhlr, 32);
> +MAQ_SA_W(maq_sa_w_qhrl, 16);
> +MAQ_SA_W(maq_sa_w_qhrr, 0);
> +
> +#undef MAQ_SA_W
> +
> +#define MAQ_S_L_PW(name, mov) \
> +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
> +                   CPUMIPSState *env)                             \
> +{                                                                 \
> +    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 >> mov) & MIPSDSP_LLO;                             \
> +    rt_t = (rt >> mov) & MIPSDSP_LLO;                             \
> +                                                                  \
> +    temp[0] = mipsdsp_mul_q31_q31(ac, rs_t, rt_t, env);           \
> +    if (temp[0] >= 0) {                                           \
> +        temp[1] = 0x00;                                           \
> +    } else {                                                      \
> +        temp[1] = ~0ull;                                          \
> +    }                                                             \
> +                                                                  \
> +    acc[0] = env->active_tc.LO[ac];                               \
> +    acc[1] = env->active_tc.HI[ac];                               \
> +                                                                  \
> +    temp_sum = acc[0] + temp[0];                                  \
> +    if (MIPSDSP_OVERFLOW(acc[0], temp[0], temp_sum,               \
> +                         0x8000000000000000ull)) {                \
> +        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];                               \
> +}
> +
> +MAQ_S_L_PW(maq_s_l_pwl, 32);
> +MAQ_S_L_PW(maq_s_l_pwr, 0);
> +
> +#undef MAQ_S_L_PW
> +
> +#define DM_OPERATE(name, func, is_add, sigext) \
> +void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac,    \
> +                  CPUMIPSState *env)                                 \
> +{                                                                    \
> +    int32_t rs1, rs0;                                                \
> +    int32_t rt1, rt0;                                                \
> +    int64_t tempBL[2], tempAL[2];                                    \
> +    int64_t acc[2];                                                  \
> +    int64_t temp[2];                                                 \
> +    int64_t temp_sum;                                                \
> +                                                                     \
> +    temp[0] = 0x00;                                                  \
> +    temp[1] = 0x00;                                                  \
> +                                                                     \
> +    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                                \
> +    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                                \
> +                                                                     \
> +    if (sigext) {                                                    \
> +        tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1);               \
> +        tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0);               \
> +                                                                     \
> +        if (tempBL[0] >= 0) {                                        \
> +            tempBL[1] = 0x0;                                         \
> +        } else {                                                     \
> +            tempBL[1] = ~0ull;                                       \
> +        }                                                            \
> +                                                                     \
> +        if (tempAL[0] >= 0) {                                        \
> +            tempAL[1] = 0x0;                                         \
> +        } else {                                                     \
> +            tempAL[1] = ~0ull;                                       \
> +        }                                                            \
> +    } else {                                                         \
> +        tempBL[0] = mipsdsp_##func(rs1, rt1);                        \
> +        tempAL[0] = mipsdsp_##func(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 (MIPSDSP_OVERFLOW(tempBL[0], tempAL[0], temp_sum,             \
> +                         0x8000000000000000ull)) {                   \
> +        temp[1] += 1;                                                \
> +    }                                                                \
> +    temp[0] = temp_sum;                                              \
> +    temp[1] += tempBL[1] + tempAL[1];                                \
> +                                                                     \
> +    if (is_add) {                                                    \
> +        temp_sum = acc[0] + temp[0];                                 \
> +        if (MIPSDSP_OVERFLOW(acc[0], temp[0], temp_sum,              \
> +                             0x8000000000000000ull)) {               \
> +            acc[1] = acc[1] + 1;                                     \
> +        }                                                            \
> +        temp[0] = temp_sum;                                          \
> +        temp[1] = acc[1] + temp[1];                                  \
> +    } else {                                                         \
> +        temp_sum = acc[0] - temp[0];                                 \
> +        if (MIPSDSP_OVERFLOW(acc[0], -temp[0], temp_sum,             \
> +                             0x8000000000000000ull)) {               \
> +            acc[1] = acc[1] - 1;                                     \
> +        }                                                            \
> +        temp[0] = temp_sum;                                          \
> +        temp[1] = acc[1] - temp[1];                                  \
> +    }                                                                \
> +                                                                     \
> +    env->active_tc.HI[ac] = temp[1];                                 \
> +    env->active_tc.LO[ac] = temp[0];                                 \
> +}
> +
> +DM_OPERATE(dmadd, mul_i32_i32, 1, 1);
> +DM_OPERATE(dmaddu, mul_u32_u32, 1, 0);
> +DM_OPERATE(dmsub, mul_i32_i32, 0, 1);
> +DM_OPERATE(dmsubu, mul_u32_u32, 0, 0);
> +#undef DM_OPERATE
> +#endif
> +
>  #undef MIPSDSP_LHI
>  #undef MIPSDSP_LLO
>  #undef MIPSDSP_HI
> diff --git a/target-mips/helper.h b/target-mips/helper.h
> index 5258ef6..6a6ca99 100644
> --- a/target-mips/helper.h
> +++ b/target-mips/helper.h
> @@ -526,4 +526,95 @@ DEF_HELPER_FLAGS_2(shra_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, tl)
>  #endif
>  
> +/* DSP Multiply Sub-class insns */
> +DEF_HELPER_FLAGS_3(muleu_s_ph_qbl, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(muleu_s_ph_qbr, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(muleu_s_qh_obl, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(muleu_s_qh_obr, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(mulq_rs_ph, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(mulq_rs_qh, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(muleq_s_w_phl, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(muleq_s_w_phr, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(muleq_s_pw_qhl, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(muleq_s_pw_qhr, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_4(dpau_h_qbl, 0, void, i32, tl, tl, env)
> +DEF_HELPER_FLAGS_4(dpau_h_qbr, 0, void, i32, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_4(dpau_h_obl, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(dpau_h_obr, 0, void, tl, tl, i32, env)
> +#endif
> +DEF_HELPER_FLAGS_4(dpsu_h_qbl, 0, void, i32, tl, tl, env)
> +DEF_HELPER_FLAGS_4(dpsu_h_qbr, 0, void, i32, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_4(dpsu_h_obl, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(dpsu_h_obr, 0, void, tl, tl, i32, env)
> +#endif
> +DEF_HELPER_FLAGS_4(dpa_w_ph, 0, void, i32, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_4(dpa_w_qh, 0, void, tl, tl, i32, env)
> +#endif
> +DEF_HELPER_FLAGS_4(dpax_w_ph, 0, void, i32, tl, tl, env)
> +DEF_HELPER_FLAGS_4(dpaq_s_w_ph, 0, void, i32, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_4(dpaq_s_w_qh, 0, void, tl, tl, i32, env)
> +#endif
> +DEF_HELPER_FLAGS_4(dpaqx_s_w_ph, 0, void, i32, tl, tl, env)
> +DEF_HELPER_FLAGS_4(dpaqx_sa_w_ph, 0, void, i32, tl, tl, env)
> +DEF_HELPER_FLAGS_4(dps_w_ph, 0, void, i32, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_4(dps_w_qh, 0, void, tl, tl, i32, env)
> +#endif
> +DEF_HELPER_FLAGS_4(dpsx_w_ph, 0, void, i32, tl, tl, env)
> +DEF_HELPER_FLAGS_4(dpsq_s_w_ph, 0, void, i32, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_4(dpsq_s_w_qh, 0, void, tl, tl, i32, env)
> +#endif
> +DEF_HELPER_FLAGS_4(dpsqx_s_w_ph, 0, void, i32, tl, tl, env)
> +DEF_HELPER_FLAGS_4(dpsqx_sa_w_ph, 0, void, i32, tl, tl, env)
> +DEF_HELPER_FLAGS_4(mulsaq_s_w_ph, 0, void, i32, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_4(mulsaq_s_w_qh, 0, void, tl, tl, i32, env)
> +#endif
> +DEF_HELPER_FLAGS_4(dpaq_sa_l_w, 0, void, i32, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_4(dpaq_sa_l_pw, 0, void, tl, tl, i32, env)
> +#endif
> +DEF_HELPER_FLAGS_4(dpsq_sa_l_w, 0, void, i32, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_4(dpsq_sa_l_pw, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(mulsaq_s_l_pw, 0, void, tl, tl, i32, env)
> +#endif
> +DEF_HELPER_FLAGS_4(maq_s_w_phl, 0, void, i32, tl, tl, env)
> +DEF_HELPER_FLAGS_4(maq_s_w_phr, 0, void, i32, tl, tl, env)
> +DEF_HELPER_FLAGS_4(maq_sa_w_phl, 0, void, i32, tl, tl, env)
> +DEF_HELPER_FLAGS_4(maq_sa_w_phr, 0, void, i32, tl, tl, env)
> +DEF_HELPER_FLAGS_3(mul_ph, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(mul_s_ph, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(mulq_s_ph, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(mulq_s_w, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(mulq_rs_w, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_4(mulsa_w_ph, 0, void, i32, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_4(maq_s_w_qhll, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(maq_s_w_qhlr, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(maq_s_w_qhrl, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(maq_s_w_qhrr, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(maq_sa_w_qhll, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(maq_sa_w_qhlr, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(maq_sa_w_qhrl, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(maq_sa_w_qhrr, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(maq_s_l_pwl, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(maq_s_l_pwr, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(dmadd, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(dmaddu, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(dmsub, 0, void, tl, tl, i32, env)
> +DEF_HELPER_FLAGS_4(dmsubu, 0, void, tl, tl, i32, env)
> +#endif
> +
>  #include "def-helper.h"
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index 72e2703..1ec6edc 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 */
> @@ -13244,6 +13323,365 @@ static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
>      MIPS_DEBUG("%s", opn);
>  }
>  
> +static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
> +                                 int ret, int rs, int rt, int check_ret)
> +{
> +    const char *opn = "mipsdsp multiply";
> +    TCGv_i32 t0 = tcg_const_i32(ret);
> +
> +    if ((ret == 0) && (check_ret == 1)) {
> +        /* Treat as NOP. */
> +        MIPS_DEBUG("NOP");
> +        return;
> +    }
> +
> +    switch (op1) {
> +    /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
> +     * the same mask and op1. */
> +    case OPC_MULT_G_2E:
> +        switch (op2) {
> +        case  OPC_MUL_PH:
> +            gen_helper_mul_ph(cpu_gpr[ret], cpu_gpr[rs],
> +                              cpu_gpr[rt], cpu_env);
> +            break;
> +        case  OPC_MUL_S_PH:
> +            gen_helper_mul_s_ph(cpu_gpr[ret], cpu_gpr[rs],
> +                                cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MULQ_S_W:
> +            gen_helper_mulq_s_w(cpu_gpr[ret], cpu_gpr[rs],
> +                                cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MULQ_RS_W:
> +            gen_helper_mulq_rs_w(cpu_gpr[ret], cpu_gpr[rs],
> +                                 cpu_gpr[rt], cpu_env);
> +            break;
> +        }
> +        break;
> +    case OPC_DPA_W_PH_DSP:
> +        switch (op2) {
> +        case OPC_DPAU_H_QBL:
> +            check_dsp(ctx);
> +            gen_helper_dpau_h_qbl(t0, cpu_gpr[rs],
> +                                  cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPAU_H_QBR:
> +            check_dsp(ctx);
> +            gen_helper_dpau_h_qbr(t0, cpu_gpr[rs],
> +                                  cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPSU_H_QBL:
> +            check_dsp(ctx);
> +            gen_helper_dpsu_h_qbl(t0, cpu_gpr[rs],
> +                                  cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPSU_H_QBR:
> +            check_dsp(ctx);
> +            gen_helper_dpsu_h_qbr(t0, cpu_gpr[rs],
> +                                  cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPA_W_PH:
> +            check_dspr2(ctx);
> +            gen_helper_dpa_w_ph(t0, cpu_gpr[rs],
> +                                cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPAX_W_PH:
> +            check_dspr2(ctx);
> +            gen_helper_dpax_w_ph(t0, cpu_gpr[rs],
> +                                 cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPAQ_S_W_PH:
> +            check_dsp(ctx);
> +            gen_helper_dpaq_s_w_ph(t0, cpu_gpr[rs],
> +                                   cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPAQX_S_W_PH:
> +            check_dspr2(ctx);
> +            gen_helper_dpaqx_s_w_ph(t0, cpu_gpr[rs],
> +                                    cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPAQX_SA_W_PH:
> +            check_dspr2(ctx);
> +            gen_helper_dpaqx_sa_w_ph(t0, cpu_gpr[rs],
> +                                     cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPS_W_PH:
> +            check_dspr2(ctx);
> +            gen_helper_dps_w_ph(t0, cpu_gpr[rs],
> +                                cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPSX_W_PH:
> +            check_dspr2(ctx);
> +            gen_helper_dpsx_w_ph(t0, cpu_gpr[rs],
> +                                 cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPSQ_S_W_PH:
> +            check_dsp(ctx);
> +            gen_helper_dpsq_s_w_ph(t0, cpu_gpr[rs],
> +                                   cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPSQX_S_W_PH:
> +            check_dspr2(ctx);
> +            gen_helper_dpsqx_s_w_ph(t0, cpu_gpr[rs],
> +                                    cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPSQX_SA_W_PH:
> +            check_dspr2(ctx);
> +            {
> +                gen_helper_dpsqx_sa_w_ph(t0, cpu_gpr[rs],
> +                                         cpu_gpr[rt], cpu_env);
> +                break;
> +            }
> +        case OPC_MULSAQ_S_W_PH:
> +            check_dsp(ctx);
> +            gen_helper_mulsaq_s_w_ph(t0, cpu_gpr[rs],
> +                                     cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPAQ_SA_L_W:
> +            check_dsp(ctx);
> +            gen_helper_dpaq_sa_l_w(t0, cpu_gpr[rs],
> +                                   cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_DPSQ_SA_L_W:
> +            check_dsp(ctx);
> +            gen_helper_dpsq_sa_l_w(t0, cpu_gpr[rs],
> +                                   cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MAQ_S_W_PHL:
> +            check_dsp(ctx);
> +            gen_helper_maq_s_w_phl(t0, cpu_gpr[rs],
> +                                   cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MAQ_S_W_PHR:
> +            check_dsp(ctx);
> +            gen_helper_maq_s_w_phr(t0, cpu_gpr[rs],
> +                                   cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MAQ_SA_W_PHL:
> +            check_dsp(ctx);
> +            gen_helper_maq_sa_w_phl(t0, cpu_gpr[rs],
> +                                    cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MAQ_SA_W_PHR:
> +            check_dsp(ctx);
> +            gen_helper_maq_sa_w_phr(t0, cpu_gpr[rs],
> +                                    cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MULSA_W_PH:
> +            check_dspr2(ctx);
> +            gen_helper_mulsa_w_ph(t0, cpu_gpr[rs],
> +                                  cpu_gpr[rt], cpu_env);
> +            break;
> +        }
> +#ifdef TARGET_MIPS64
> +    case OPC_DPAQ_W_QH_DSP:
> +        {
> +            int ac = ret & 0x03;
> +            tcg_gen_movi_i32(t0, ac);
> +
> +            switch (op2) {
> +            case OPC_DMADD:
> +                check_dsp(ctx);
> +                gen_helper_dmadd(cpu_gpr[rs], cpu_gpr[rt], t0, cpu_env);
> +                break;
> +            case OPC_DMADDU:
> +                check_dsp(ctx);
> +                gen_helper_dmaddu(cpu_gpr[rs], cpu_gpr[rt], t0, cpu_env);
> +                break;
> +            case OPC_DMSUB:
> +                check_dsp(ctx);
> +                gen_helper_dmsub(cpu_gpr[rs], cpu_gpr[rt], t0, cpu_env);
> +                break;
> +            case OPC_DMSUBU:
> +                check_dsp(ctx);
> +                gen_helper_dmsubu(cpu_gpr[rs], cpu_gpr[rt], t0, cpu_env);
> +                break;
> +            case OPC_DPA_W_QH:
> +                check_dspr2(ctx);
> +                gen_helper_dpa_w_qh(cpu_gpr[rs], cpu_gpr[rt],
> +                                    t0, cpu_env);
> +                break;
> +            case OPC_DPAQ_S_W_QH:
> +                check_dsp(ctx);
> +                gen_helper_dpaq_s_w_qh(cpu_gpr[rs], cpu_gpr[rt],
> +                                       t0, cpu_env);
> +                break;
> +            case OPC_DPAQ_SA_L_PW:
> +                check_dsp(ctx);
> +                gen_helper_dpaq_sa_l_pw(cpu_gpr[rs], cpu_gpr[rt],
> +                                        t0, cpu_env);
> +                break;
> +            case OPC_DPAU_H_OBL:
> +                check_dsp(ctx);
> +                gen_helper_dpau_h_obl(cpu_gpr[rs], cpu_gpr[rt],
> +                                      t0, cpu_env);
> +                break;
> +            case OPC_DPAU_H_OBR:
> +                check_dsp(ctx);
> +                gen_helper_dpau_h_obr(cpu_gpr[rs], cpu_gpr[rt],
> +                                      t0, cpu_env);
> +                break;
> +            case OPC_DPS_W_QH:
> +                check_dspr2(ctx);
> +                gen_helper_dps_w_qh(cpu_gpr[rs], cpu_gpr[rt],
> +                                    t0, cpu_env);
> +                break;
> +            case OPC_DPSQ_S_W_QH:
> +                check_dsp(ctx);
> +                gen_helper_dpsq_s_w_qh(cpu_gpr[rs], cpu_gpr[rt],
> +                                       t0, cpu_env);
> +                break;
> +            case OPC_DPSQ_SA_L_PW:
> +                check_dsp(ctx);
> +                gen_helper_dpsq_sa_l_pw(cpu_gpr[rs], cpu_gpr[rt],
> +                                        t0, cpu_env);
> +                break;
> +            case OPC_DPSU_H_OBL:
> +                check_dsp(ctx);
> +                gen_helper_dpsu_h_obl(cpu_gpr[rs], cpu_gpr[rt],
> +                                      t0, cpu_env);
> +                break;
> +            case OPC_DPSU_H_OBR:
> +                check_dsp(ctx);
> +                gen_helper_dpsu_h_obr(cpu_gpr[rs], cpu_gpr[rt],
> +                                      t0, cpu_env);
> +                break;
> +            case OPC_MAQ_S_L_PWL:
> +                check_dsp(ctx);
> +                gen_helper_maq_s_l_pwl(cpu_gpr[rs], cpu_gpr[rt],
> +                                       t0, cpu_env);
> +                break;
> +            case OPC_MAQ_S_L_PWR:
> +                check_dsp(ctx);
> +                gen_helper_maq_s_l_pwr(cpu_gpr[rs], cpu_gpr[rt],
> +                                       t0, cpu_env);
> +                break;
> +            case OPC_MAQ_S_W_QHLL:
> +                check_dsp(ctx);
> +                gen_helper_maq_s_w_qhll(cpu_gpr[rs], cpu_gpr[rt],
> +                                        t0, cpu_env);
> +                break;
> +            case OPC_MAQ_SA_W_QHLL:
> +                check_dsp(ctx);
> +                gen_helper_maq_sa_w_qhll(cpu_gpr[rs], cpu_gpr[rt],
> +                                         t0, cpu_env);
> +                break;
> +            case OPC_MAQ_S_W_QHLR:
> +                check_dsp(ctx);
> +                gen_helper_maq_s_w_qhlr(cpu_gpr[rs], cpu_gpr[rt],
> +                                        t0, cpu_env);
> +                break;
> +            case OPC_MAQ_SA_W_QHLR:
> +                check_dsp(ctx);
> +                gen_helper_maq_sa_w_qhlr(cpu_gpr[rs], cpu_gpr[rt],
> +                                         t0, cpu_env);
> +                break;
> +            case OPC_MAQ_S_W_QHRL:
> +                check_dsp(ctx);
> +                gen_helper_maq_s_w_qhrl(cpu_gpr[rs], cpu_gpr[rt],
> +                                        t0, cpu_env);
> +                break;
> +            case OPC_MAQ_SA_W_QHRL:
> +                check_dsp(ctx);
> +                gen_helper_maq_sa_w_qhrl(cpu_gpr[rs], cpu_gpr[rt],
> +                                         t0, cpu_env);
> +                break;
> +            case OPC_MAQ_S_W_QHRR:
> +                check_dsp(ctx);
> +                gen_helper_maq_s_w_qhrr(cpu_gpr[rs], cpu_gpr[rt],
> +                                        t0, cpu_env);
> +                break;
> +            case OPC_MAQ_SA_W_QHRR:
> +                check_dsp(ctx);
> +                gen_helper_maq_sa_w_qhrr(cpu_gpr[rs], cpu_gpr[rt],
> +                                         t0, cpu_env);
> +                break;
> +            case OPC_MULSAQ_S_L_PW:
> +                check_dsp(ctx);
> +                gen_helper_mulsaq_s_l_pw(cpu_gpr[rs], cpu_gpr[rt],
> +                                         t0, cpu_env);
> +                break;
> +            case OPC_MULSAQ_S_W_QH:
> +                check_dsp(ctx);
> +                gen_helper_mulsaq_s_w_qh(cpu_gpr[rs], cpu_gpr[rt],
> +                                         t0, cpu_env);
> +                break;
> +            }
> +        }
> +        break;
> +#endif
> +    case OPC_ADDU_QB_DSP:
> +        switch (op2) {
> +        case OPC_MULEU_S_PH_QBL:
> +            check_dsp(ctx);
> +            gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], cpu_gpr[rs],
> +                                      cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MULEU_S_PH_QBR:
> +            check_dsp(ctx);
> +            gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], cpu_gpr[rs],
> +                                      cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MULQ_RS_PH:
> +            check_dsp(ctx);
> +            gen_helper_mulq_rs_ph(cpu_gpr[ret], cpu_gpr[rs],
> +                                  cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MULEQ_S_W_PHL:
> +            check_dsp(ctx);
> +            gen_helper_muleq_s_w_phl(cpu_gpr[ret], cpu_gpr[rs],
> +                                     cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MULEQ_S_W_PHR:
> +            check_dsp(ctx);
> +            gen_helper_muleq_s_w_phr(cpu_gpr[ret], cpu_gpr[rs],
> +                                     cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MULQ_S_PH:
> +            check_dspr2(ctx);
> +            gen_helper_mulq_s_ph(cpu_gpr[ret], cpu_gpr[rs],
> +                                 cpu_gpr[rt], cpu_env);
> +            break;
> +        }
> +#ifdef TARGET_MIPS64
> +    case OPC_ADDU_OB_DSP:
> +        switch (op2) {
> +        case OPC_MULEQ_S_PW_QHL:
> +            check_dsp(ctx);
> +            gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], cpu_gpr[rs],
> +                                      cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MULEQ_S_PW_QHR:
> +            check_dsp(ctx);
> +            gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], cpu_gpr[rs],
> +                                      cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MULEU_S_QH_OBL:
> +            check_dsp(ctx);
> +            gen_helper_muleu_s_qh_obl(cpu_gpr[ret], cpu_gpr[rs],
> +                                      cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MULEU_S_QH_OBR:
> +            check_dsp(ctx);
> +            gen_helper_muleu_s_qh_obr(cpu_gpr[ret], cpu_gpr[rs],
> +                                      cpu_gpr[rt], cpu_env);
> +            break;
> +        case OPC_MULQ_RS_QH:
> +            check_dsp(ctx);
> +            gen_helper_mulq_rs_qh(cpu_gpr[ret], cpu_gpr[rs],
> +                                  cpu_gpr[rt], cpu_env);
> +            break;

All these functions should check for rs and rt being 0.

> +        }
> +#endif
> +        break;
> +    }
> +    tcg_temp_free_i32(t0);
> +
> +    (void)opn; /* avoid a compiler warning */
> +    MIPS_DEBUG("%s", opn);
> +
> +}
> +
>  /* End MIPSDSP functions. */
>  
>  static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
> @@ -13617,6 +14055,12 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>                  case OPC_SUBQH_R_W:
>                      gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
>                      break;
> +                case OPC_MUL_PH:
> +                case OPC_MUL_S_PH:
> +                case OPC_MULQ_S_W:
> +                case OPC_MULQ_RS_W:
> +                    gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
> +                    break;
>                  default:
>                      MIPS_INVAL("MASK ADDUH.QB");
>                      generate_exception(ctx, EXCP_RI);
> @@ -13693,6 +14137,14 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>              case OPC_RADDU_W_QB:
>                  gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
>                  break;
> +            case OPC_MULEU_S_PH_QBL:
> +            case OPC_MULEU_S_PH_QBR:
> +            case OPC_MULQ_RS_PH:
> +            case OPC_MULEQ_S_W_PHL:
> +            case OPC_MULEQ_S_W_PHR:
> +            case OPC_MULQ_S_PH:
> +                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
> +                break;
>              default:            /* Invalid */
>                  MIPS_INVAL("MASK ADDU.QB");
>                  generate_exception(ctx, EXCP_RI);
> @@ -13723,6 +14175,39 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>          case OPC_SHLL_QB_DSP:
>              gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
>              break;
> +        case OPC_DPA_W_PH_DSP:
> +            op2 = MASK_DPA_W_PH(ctx->opcode);
> +            switch (op2) {
> +            case OPC_DPAU_H_QBL:
> +            case OPC_DPAU_H_QBR:
> +            case OPC_DPSU_H_QBL:
> +            case OPC_DPSU_H_QBR:
> +            case OPC_DPA_W_PH:
> +            case OPC_DPAX_W_PH:
> +            case OPC_DPAQ_S_W_PH:
> +            case OPC_DPAQX_S_W_PH:
> +            case OPC_DPAQX_SA_W_PH:
> +            case OPC_DPS_W_PH:
> +            case OPC_DPSX_W_PH:
> +            case OPC_DPSQ_S_W_PH:
> +            case OPC_DPSQX_S_W_PH:
> +            case OPC_DPSQX_SA_W_PH:
> +            case OPC_MULSAQ_S_W_PH:
> +            case OPC_DPAQ_SA_L_W:
> +            case OPC_DPSQ_SA_L_W:
> +            case OPC_MAQ_S_W_PHL:
> +            case OPC_MAQ_S_W_PHR:
> +            case OPC_MAQ_SA_W_PHL:
> +            case OPC_MAQ_SA_W_PHR:
> +            case OPC_MULSA_W_PH:
> +                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
> +                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:
> @@ -13796,6 +14281,13 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>              case OPC_ADDUH_R_OB:
>                  gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
>                  break;
> +            case OPC_MULEQ_S_PW_QHL:
> +            case OPC_MULEQ_S_PW_QHR:
> +            case OPC_MULEU_S_QH_OBL:
> +            case OPC_MULEU_S_QH_OBR:
> +            case OPC_MULQ_RS_QH:
> +                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
> +                break;
>              default:            /* Invalid */
>                  MIPS_INVAL("MASK ADDU.OB");
>                  generate_exception(ctx, EXCP_RI);
> @@ -13824,6 +14316,45 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>                  break;
>              }
>              break;
> +        case OPC_DPAQ_W_QH_DSP:
> +            op2 = MASK_DPAQ_W_QH(ctx->opcode);
> +            switch (op2) {
> +            case OPC_DPAU_H_OBL:
> +            case OPC_DPAU_H_OBR:
> +            case OPC_DPSU_H_OBL:
> +            case OPC_DPSU_H_OBR:
> +            case OPC_DPA_W_QH:
> +            case OPC_DPAQ_S_W_QH:
> +            case OPC_DPS_W_QH:
> +            case OPC_DPSQ_S_W_QH:
> +            case OPC_MULSAQ_S_W_QH:
> +            case OPC_DPAQ_SA_L_PW:
> +            case OPC_DPSQ_SA_L_PW:
> +            case OPC_MULSAQ_S_L_PW:
> +                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
> +                break;
> +            case OPC_MAQ_S_W_QHLL:
> +            case OPC_MAQ_S_W_QHLR:
> +            case OPC_MAQ_S_W_QHRL:
> +            case OPC_MAQ_S_W_QHRR:
> +            case OPC_MAQ_SA_W_QHLL:
> +            case OPC_MAQ_SA_W_QHLR:
> +            case OPC_MAQ_SA_W_QHRL:
> +            case OPC_MAQ_SA_W_QHRR:
> +            case OPC_MAQ_S_L_PWL:
> +            case OPC_MAQ_S_L_PWR:
> +            case OPC_DMADD:
> +            case OPC_DMADDU:
> +            case OPC_DMSUB:
> +            case OPC_DMSUBU:
> +                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
> +                break;
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK DPAQ.W.QH");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
>          case OPC_SHLL_OB_DSP:
>              gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
>              break;
> -- 
> 1.7.10.2 (Apple Git-33)
> 
> 

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

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

* Re: [Qemu-devel] [PATCH v9 09/14] target-mips-ase-dsp: Add bit/manipulation instructions
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 09/14] target-mips-ase-dsp: Add bit/manipulation instructions Jia Liu
@ 2012-10-06 14:51   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:51 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:46PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP Bit/Manipulation instructions.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/dsp_helper.c |   55 ++++++++++
>  target-mips/helper.h     |    7 ++
>  target-mips/translate.c  |  268 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 330 insertions(+)
> 
> diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
> index b98be0d..7516242 100644
> --- a/target-mips/dsp_helper.c
> +++ b/target-mips/dsp_helper.c
> @@ -3186,6 +3186,61 @@ DM_OPERATE(dmsubu, mul_u32_u32, 0, 0);
>  #undef DM_OPERATE
>  #endif
>  
> +/** DSP Bit/Manipulation Sub-class insns **/
> +target_ulong helper_bitrev(target_ulong rt)
> +{
> +    int32_t temp;
> +    uint32_t rd;
> +    int i;
> +
> +    temp = rt & MIPSDSP_LO;
> +    rd = 0;
> +    for (i = 0; i < 16; i++) {
> +        rd = (rd << 1) | (temp & 1);
> +        temp = temp >> 1;
> +    }
> +
> +    return (target_ulong)rd;
> +}
> +
> +#define BIT_INSV(name, posfilter, sizefilter, ret_type)         \
> +target_ulong helper_##name(CPUMIPSState *env, target_ulong rs,  \
> +                           target_ulong rt)                     \
> +{                                                               \
> +    uint32_t pos, size, msb, lsb;                               \
> +    target_ulong filter;                                        \
> +    target_ulong temp, temprs, temprt;                          \
> +    target_ulong dspc;                                          \
> +                                                                \
> +    dspc = env->active_tc.DSPControl;                           \
> +                                                                \
> +    pos  = dspc & posfilter;                                    \
> +    size = (dspc >> 7) & sizefilter;                            \
> +                                                                \
> +    msb  = pos + size - 1;                                      \
> +    lsb  = pos;                                                 \
> +                                                                \
> +    if (lsb > msb || (msb > TARGET_LONG_BITS)) {                \
> +        return rt;                                              \
> +    }                                                           \
> +                                                                \
> +    filter = ((int32_t)0x01 << size) - 1;                       \
> +    filter = filter << pos;                                     \
> +    temprs = rs & filter;                                       \
> +    temprt = rt & ~filter;                                      \
> +    temp = temprs | temprt;                                     \
> +                                                                \
> +    return (target_long)(ret_type)temp;                         \
> +}
> +
> +BIT_INSV(insv, 0x1F, 0x1F, int32_t);
> +#ifdef TARGET_MIPS64
> +BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
> +#endif
> +
> +#undef BIT_INSV
> +
> +
>  #undef MIPSDSP_LHI
>  #undef MIPSDSP_LLO
>  #undef MIPSDSP_HI
> diff --git a/target-mips/helper.h b/target-mips/helper.h
> index 6a6ca99..31475a2 100644
> --- a/target-mips/helper.h
> +++ b/target-mips/helper.h
> @@ -617,4 +617,11 @@ DEF_HELPER_FLAGS_4(dmsub, 0, void, tl, tl, i32, env)
>  DEF_HELPER_FLAGS_4(dmsubu, 0, void, tl, tl, i32, env)
>  #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 1ec6edc..d5c2419 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 */
> @@ -13682,6 +13714,189 @@ static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
>  
>  }
>  
> +static void gen_mipsdsp_bitinsn(CPUMIPSState *env, DisasContext *ctx,
> +                                uint32_t op1, uint32_t op2,
> +                                int ret, int val)
> +{
> +    const char *opn = "mipsdsp Bit/ Manipulation";
> +    TCGv t0 = tcg_temp_new();
> +    int16_t imm;
> +
> +    if (ret == 0) {
> +        /* Treat as NOP. */
> +        MIPS_DEBUG("NOP");
> +        return;
> +    }
> +
> +    switch (op1) {
> +    case OPC_ABSQ_S_PH_DSP:
> +        switch (op2) {
> +        case OPC_BITREV:
> +            check_dsp(ctx);
> +            gen_helper_bitrev(cpu_gpr[ret], cpu_gpr[val]);

You should check for val being register 0.

> +            break;
> +        case OPC_REPL_QB:
> +            check_dsp(ctx);
> +            {
> +                target_long result;
> +                imm = (ctx->opcode >> 16) & 0xFF;
> +                result = (uint32_t)imm << 24 | \
> +                         (uint32_t)imm << 16 | \
> +                         (uint32_t)imm << 8  | \
> +                         (uint32_t)imm;
> +#ifdef TARGET_MIPS64
> +                result = (target_long)(result << 32) >> 32;

result = (int32_t)result should do it, and doesn't need to be
conditional on TARGET_MIPS64.

> +#endif
> +                tcg_gen_movi_tl(cpu_gpr[ret], result);
> +            }
> +            break;
> +        case OPC_REPLV_QB:
> +            check_dsp(ctx);
> +            {
> +                TCGv temp_rd;
> +
> +                temp_rd = tcg_temp_new();
> +
> +                /* we need t0 to save gpr[val] 7..0 bits. */
> +                tcg_gen_ext8u_tl(t0, cpu_gpr[val]);

val could be register 0.

> +                tcg_gen_mov_tl(temp_rd, t0);
> +                tcg_gen_shli_tl(t0, t0, 8);
> +                tcg_gen_or_tl(temp_rd, temp_rd, t0);
> +                tcg_gen_mov_tl(t0, temp_rd);
> +                tcg_gen_shli_tl(t0, t0, 16);
> +                tcg_gen_or_tl(temp_rd, temp_rd, t0);
> +#if defined(TARGET_MIPS64)
> +                tcg_gen_ext32s_i64(temp_rd, temp_rd);
> +#endif
> +                tcg_gen_mov_tl(cpu_gpr[ret], temp_rd);

As previously said, this can be written as:

    tcg_gen_ext8u_tl(cpu_gpr[ret], cpu_gpr[val]);
    tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
    tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
    tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
    tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
    tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);

(The latest operation being a nop on 32-bit).

> +                tcg_temp_free(temp_rd);
> +            }
> +            break;
> +        case OPC_REPL_PH:
> +            check_dsp(ctx);
> +            {
> +                imm = (ctx->opcode >> 16) & 0x03FF;
> +                tcg_gen_movi_tl(cpu_gpr[ret], \
> +                                (target_long)((int32_t)imm << 16 | \
> +                                (uint32_t)(uint16_t)imm));
> +            }
> +            break;
> +        case OPC_REPLV_PH:
> +            check_dsp(ctx);
> +            {
> +                TCGv temp_rd;
> +
> +                temp_rd = tcg_temp_new();

You should check for val being register 0.

> +                tcg_gen_ext16u_tl(t0, cpu_gpr[val]);
> +                tcg_gen_ext16s_tl(temp_rd, cpu_gpr[val]);
> +                tcg_gen_shli_tl(temp_rd, temp_rd, 16);
> +                tcg_gen_or_tl(temp_rd, temp_rd, t0);
> +                tcg_gen_mov_tl(cpu_gpr[ret], temp_rd);
> +

This can be written as:
    tcg_gen_ext16u_tl(cpu_gpr[ret], cpu_gpr[val]);
    tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
    tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
    tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);

> +                tcg_temp_free(temp_rd);
> +            }
> +            break;
> +        }
> +        break;
> +#ifdef TARGET_MIPS64
> +    case OPC_ABSQ_S_QH_DSP:
> +        switch (op2) {
> +        case OPC_REPL_OB:
> +            check_dsp(ctx);
> +            {
> +                target_long temp;
> +
> +                imm = (ctx->opcode >> 16) & 0xFF;
> +                temp = imm;
> +                temp = (temp << 8) | temp;
> +                temp = (temp << 16) | temp;
> +                temp = (temp << 32) | temp;
> +                tcg_gen_movi_tl(cpu_gpr[ret], temp);

According to the manual, REPL.OB is working on 64-bit values and thus
replicating the value 8 times.

> +                break;
> +            }
> +        case OPC_REPL_PW:
> +            check_dsp(ctx);
> +            {
> +                target_long temp;
> +
> +                imm = (ctx->opcode >> 16) & 0x03FF;
> +                imm = (int16_t)(imm << 6) >> 6;
> +                temp = ((target_long)imm << 32) \
> +                       | ((target_long)imm & 0xFFFFFFFF);
> +                tcg_gen_movi_tl(cpu_gpr[ret], temp);
> +                break;
> +            }
> +        case OPC_REPL_QH:
> +            check_dsp(ctx);
> +            {
> +                target_long temp;
> +
> +                imm = (ctx->opcode >> 16) & 0x03FF;
> +                imm = (int16_t)(imm << 6) >> 6;
> +
> +                temp = ((uint64_t)(uint16_t)imm << 48) | \
> +                       ((uint64_t)(uint16_t)imm << 32) | \
> +                       ((uint64_t)(uint16_t)imm << 16) | \
> +                       (uint64_t)(uint16_t)imm;
> +                tcg_gen_movi_tl(cpu_gpr[ret], temp);
> +                break;
> +            }
> +        case OPC_REPLV_OB:
> +            check_dsp(ctx);
> +            {
> +                TCGv temp_rd;
> +
> +                temp_rd = tcg_temp_new();
> +
> +                tcg_gen_ext8u_tl(t0, cpu_gpr[val]);
> +                tcg_gen_mov_tl(temp_rd, t0);
> +                tcg_gen_shli_tl(temp_rd, temp_rd, 8);
> +                tcg_gen_or_tl(temp_rd, temp_rd, t0);
> +                tcg_gen_mov_tl(t0, temp_rd);
> +                tcg_gen_shli_tl(temp_rd, temp_rd, 16);
> +                tcg_gen_or_tl(temp_rd, temp_rd, t0);
> +                tcg_gen_concat_tl_i64(temp_rd, temp_rd, temp_rd);

As previously said, tcg_gen_concat_tl_i64 is no the best way to do that
as it does a zero extension first, which is not needed here.

This can be written as:

    tcg_gen_ext8u_tl(cpu_gpr[ret], cpu_gpr[ret]);
    tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
    tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
    tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
    tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
    tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
    tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);

> +
> +                gen_store_gpr(temp_rd, ret);
> +

You can work directly on the gpr (as on the code I have written above),
because the check for ret == 0 is already done at the top.

> +                tcg_temp_free(temp_rd);
> +                break;
> +            }
> +        case OPC_REPLV_PW:
> +            check_dsp(ctx);
> +            {
> +                tcg_gen_ext32u_i64(t0, cpu_gpr[val]);
> +                tcg_gen_concat_tl_i64(cpu_gpr[ret], t0, t0);

concat already does the zero extension and is therefore not needed.

> +                break;
> +            }
> +        case OPC_REPLV_QH:
> +            check_dsp(ctx);
> +            {
> +                TCGv temp_rd;
> +
> +                temp_rd = tcg_temp_new();
> +
> +                tcg_gen_ext16u_tl(t0, cpu_gpr[val]);
> +                tcg_gen_mov_tl(temp_rd, t0);
> +                tcg_gen_shli_tl(temp_rd, temp_rd, 16);
> +                tcg_gen_or_tl(temp_rd, temp_rd, t0);
> +                tcg_gen_concat_tl_i64(cpu_gpr[ret], temp_rd, temp_rd);
> +

This can be written as:
    tcg_gen_ext16u_tl(cpu_gpr[ret], cpu_gpr[val]);
    tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
    tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
    tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
    tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);


> +                tcg_temp_free(temp_rd);
> +                break;
> +            }
> +        }
> +        break;
> +#endif
> +    }
> +    tcg_temp_free(t0);
> +
> +    (void)opn; /* avoid a compiler warning */
> +    MIPS_DEBUG("%s", opn);
> +}
> +
>  /* End MIPSDSP functions. */
>  
>  static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
> @@ -14108,6 +14323,13 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>              case OPC_PRECEU_PH_QBRA:
>                  gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
>                  break;
> +            case OPC_BITREV:
> +            case OPC_REPL_QB:
> +            case OPC_REPLV_QB:
> +            case OPC_REPL_PH:
> +            case OPC_REPLV_PH:
> +                gen_mipsdsp_bitinsn(env, ctx, op1, op2, rd, rt);
> +                break;
>              default:
>                  MIPS_INVAL("MASK ABSQ_S.PH");
>                  generate_exception(ctx, EXCP_RI);
> @@ -14208,6 +14430,26 @@ 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_dsp(ctx);
> +                {
> +                    if (rt == 0) {
> +                        MIPS_DEBUG("NOP");
> +                        break;
> +                    }
> +                    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:
> @@ -14249,6 +14491,14 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>              case OPC_ABSQ_S_QH:
>                  gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
>                  break;
> +            case OPC_REPL_OB:
> +            case OPC_REPL_PW:
> +            case OPC_REPL_QH:
> +            case OPC_REPLV_OB:
> +            case OPC_REPLV_PW:
> +            case OPC_REPLV_QH:
> +                gen_mipsdsp_bitinsn(env, ctx, op1, op2, rd, rt);
> +                break;
>              default:            /* Invalid */
>                  MIPS_INVAL("MASK ABSQ_S.QH");
>                  generate_exception(ctx, EXCP_RI);
> @@ -14355,6 +14605,24 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>                  break;
>              }
>              break;
> +        case OPC_DINSV_DSP:
> +            op2 = MASK_INSV(ctx->opcode);
> +            switch (op2) {
> +            case OPC_DINSV:
> +                check_dsp(ctx);
> +                if (rt == 0) {
> +                    MIPS_DEBUG("NOP");
> +                    break;
> +                }
> +                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;
>          case OPC_SHLL_OB_DSP:
>              gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
>              break;
> -- 
> 1.7.10.2 (Apple Git-33)
> 
> 

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

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

* Re: [Qemu-devel] [PATCH v9 10/14] target-mips-ase-dsp: Add compare-pick instructions
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 10/14] target-mips-ase-dsp: Add compare-pick instructions Jia Liu
@ 2012-10-06 14:51   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:51 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:47PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP Compare-Pick instructions.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/dsp_helper.c |  235 ++++++++++++++++++++++++++++++
>  target-mips/helper.h     |   52 +++++++
>  target-mips/translate.c  |  356 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 643 insertions(+)
> 
> diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
> index 7516242..dabece4 100644
> --- a/target-mips/dsp_helper.c
> +++ b/target-mips/dsp_helper.c
> @@ -3241,6 +3241,241 @@ BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
>  #undef BIT_INSV
>  
>  
> +/** DSP Compare-Pick Sub-class insns **/
> +#define CMP_HAS_RET(name, func, split_num, filter, bit_size) \
> +target_ulong helper_##name(target_ulong rs, target_ulong rt) \
> +{                                                       \
> +    uint32_t rs_t[split_num];                            \
> +    uint32_t rt_t[split_num];                            \
> +    uint8_t cc[split_num];                              \
> +    uint32_t temp = 0;                                  \
> +    int i;                                              \
> +                                                        \
> +    for (i = 0; i < split_num; i++) {                   \
> +        rs_t[i] = (rs >> (bit_size * i)) & filter;      \
> +        rt_t[i] = (rt >> (bit_size * i)) & filter;      \
> +        cc[i] = mipsdsp_##func(rs_t[i], rt_t[i]);       \
> +        temp |= cc[i] << i;                             \
> +    }                                                   \
> +                                                         \

I don't think you need arrays there, as they are only used in the loop.

> +    return (target_ulong)temp;                          \
> +}
> +
> +CMP_HAS_RET(cmpgu_eq_qb, cmp_eq, 4, MIPSDSP_Q0, 8);
> +CMP_HAS_RET(cmpgu_lt_qb, cmp_lt, 4, MIPSDSP_Q0, 8);
> +CMP_HAS_RET(cmpgu_le_qb, cmp_le, 4, MIPSDSP_Q0, 8);
> +
> +#ifdef TARGET_MIPS64
> +CMP_HAS_RET(cmpgu_eq_ob, cmp_eq, 8, MIPSDSP_Q0, 8);
> +CMP_HAS_RET(cmpgu_lt_ob, cmp_lt, 8, MIPSDSP_Q0, 8);
> +CMP_HAS_RET(cmpgu_le_ob, cmp_le, 8, MIPSDSP_Q0, 8);
> +#endif
> +
> +#undef CMP_HAS_RET
> +
> +
> +#define CMP_NO_RET(name, func, split_num, filter, bit_size)   \
> +void helper_##name(target_ulong rs, target_ulong rt,      \
> +                            CPUMIPSState *env)            \
> +{                                                         \
> +    int32_t rs_t[split_num], rt_t[split_num];             \
> +    int32_t flag = 0;                                     \
> +    int32_t cc[split_num];                                \
> +    int i;                                                \
> +                                                          \
> +    for (i = 0; i < split_num; i++) {                     \
> +        rs_t[i] = (rs >> (bit_size * i)) & filter;        \
> +        rt_t[i] = (rt >> (bit_size * i)) & filter;        \
> +                                                          \
> +        cc[i] = mipsdsp_##func(rs_t[i], rt_t[i]);         \
> +        flag |= cc[i] << i;                               \
> +    }                                                     \
> +                                                          \
> +    set_DSPControl_24(flag, split_num, env);              \
> +}
> +

Same there.

> +CMP_NO_RET(cmpu_eq_qb, cmp_eq, 4, MIPSDSP_Q0, 8);
> +CMP_NO_RET(cmpu_lt_qb, cmp_lt, 4, MIPSDSP_Q0, 8);
> +CMP_NO_RET(cmpu_le_qb, cmp_le, 4, MIPSDSP_Q0, 8);
> +
> +CMP_NO_RET(cmp_eq_ph, cmp_eq, 2, MIPSDSP_LO, 16);
> +CMP_NO_RET(cmp_lt_ph, cmp_lt, 2, MIPSDSP_LO, 16);
> +CMP_NO_RET(cmp_le_ph, cmp_le, 2, MIPSDSP_LO, 16);
> +
> +#ifdef TARGET_MIPS64
> +CMP_NO_RET(cmpu_eq_ob, cmp_eq, 8, MIPSDSP_Q0, 8);
> +CMP_NO_RET(cmpu_lt_ob, cmp_lt, 8, MIPSDSP_Q0, 8);
> +CMP_NO_RET(cmpu_le_ob, cmp_le, 8, MIPSDSP_Q0, 8);
> +
> +CMP_NO_RET(cmp_eq_qh, cmp_eq, 4, MIPSDSP_LO, 16);
> +CMP_NO_RET(cmp_lt_qh, cmp_lt, 4, MIPSDSP_LO, 16);
> +CMP_NO_RET(cmp_le_qh, cmp_le, 4, MIPSDSP_LO, 16);
> +
> +CMP_NO_RET(cmp_eq_pw, cmp_eq, 2, MIPSDSP_LLO, 32);
> +CMP_NO_RET(cmp_lt_pw, cmp_lt, 2, MIPSDSP_LLO, 32);
> +CMP_NO_RET(cmp_le_pw, cmp_le, 2, MIPSDSP_LLO, 32);
> +#endif
> +#undef CMP_NO_RET
> +
> +#if defined(TARGET_MIPS64)
> +
> +#define CMPGDU_OB(name) \
> +target_ulong helper_cmpgdu_##name##_ob(target_ulong rs, target_ulong rt, \
> +                                       CPUMIPSState *env)  \
> +{                                                     \
> +    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 (mipsdsp_cmp_##name(rs_t[i], rt_t[i])) {   \
> +            cond |= 0x01 << i;                        \
> +        }                                             \
> +    }                                                 \
> +                                                      \
> +    set_DSPControl_24(cond, 8, env);                  \
> +                                                      \
> +    return (uint64_t)cond;                            \
> +}

Ant there.

> +
> +CMPGDU_OB(eq)
> +CMPGDU_OB(lt)
> +CMPGDU_OB(le)
> +#undef CMPGDU_OB
> +#endif
> +
> +#define PICK_INSN(name, split_num, filter, bit_size, ret32bit) \
> +target_ulong helper_##name(target_ulong rs, target_ulong rt,   \
> +                            CPUMIPSState *env)                 \
> +{                                                              \
> +    uint32_t rs_t[split_num];                                  \
> +    uint32_t rt_t[split_num];                                  \
> +    uint32_t cc[split_num];                                    \
> +    target_ulong dsp;                                          \
> +    int i;                                                     \
> +    target_ulong result = 0;                                   \
> +                                                               \
> +    dsp = env->active_tc.DSPControl;                           \
> +    for (i = 0; i < split_num; i++) {                          \
> +        rs_t[i] = (rs >> (bit_size * i)) & filter;             \
> +        rt_t[i] = (rt >> (bit_size * i)) & filter;             \
> +        cc[i] = (dsp >> (24 + i)) & 0x01;                      \
> +        cc[i] = cc[i] == 1 ? rs_t[i] : rt_t[i];                \
> +                                                               \
> +        result |= (target_ulong)cc[i] << (bit_size * i);       \
> +    }                                                          \
> +                                                               \
> +    if (ret32bit) {                                            \
> +        result = (target_long)(int32_t)(result & MIPSDSP_LLO); \
> +    }                                                          \
> +                                                               \
> +    return result;                                             \
> +}
> +
> +PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1);
> +PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1);
> +
> +#ifdef TARGET_MIPS64
> +PICK_INSN(pick_ob, 8, MIPSDSP_Q0, 8, 0);
> +PICK_INSN(pick_qh, 4, MIPSDSP_LO, 16, 0);
> +PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0);
> +#endif
> +#undef PICK_INSN
> +
> +#define APPEND_INSN(name, ret_32) \
> +target_ulong helper_##name(target_ulong rt, target_ulong rs, uint32_t sa) \
> +{                                                                         \
> +    target_ulong temp;                                                    \
> +                                                                          \
> +    if (ret_32) {                                                         \
> +        temp = ((rt & MIPSDSP_LLO) << sa) |                               \
> +               ((rs & MIPSDSP_LLO) & ((0x01 << sa) - 1));                 \
> +        temp = (target_long)(int32_t)(temp & MIPSDSP_LLO);                \
> +    } else {                                                              \
> +        temp = (rt << sa) | (rs & ((0x01 << sa) - 1));                    \
> +    }                                                                     \
> +                                                                          \
> +    return temp;                                                          \
> +}
> +
> +APPEND_INSN(append, 1);
> +#ifdef TARGET_MIPS64
> +APPEND_INSN(dappend, 0);
> +#endif
> +#undef APPEND_INSN
> +
> +#define PREPEND_INSN(name, or_val, ret_32)                    \
> +target_ulong helper_##name(target_ulong rs, target_ulong rt,  \
> +                           uint32_t sa)                       \
> +{                                                             \
> +    sa |= or_val;                                             \
> +                                                              \
> +    if (1) {                                                  \
> +        return (target_long)(int32_t)(uint32_t)               \
> +            (((rs & MIPSDSP_LLO) << (32 - sa)) |              \
> +             ((rt & MIPSDSP_LLO) >> sa));                     \
> +    } else {                                                  \
> +        return (rs << (64 - sa)) | (rt >> sa);                \
> +    }                                                         \
> +}
> +
> +PREPEND_INSN(prepend, 0, 1);
> +#ifdef TARGET_MIPS64
> +PREPEND_INSN(prependw, 0, 0);
> +PREPEND_INSN(prependd, 0x20, 0);
> +#endif
> +#undef PREPEND_INSN
> +
> +#define BALIGN_INSN(name, filter, ret32) \
> +target_ulong helper_##name(target_ulong rs, target_ulong rt, uint32_t bp) \
> +{                                                                         \
> +    bp = bp & 0x03;                                                       \
> +                                                                          \
> +    if ((bp & 1) == 0) {                                                  \
> +        return rt;                                                        \
> +    } else {                                                              \
> +        if (ret32) {                                                      \
> +            return (target_long)(int32_t)((rt << (8 * bp)) |              \
> +                                          (rs >> (8 * (4 - bp))));        \
> +        } else {                                                          \
> +            return (rt << (8 * bp)) | (rs >> (8 * (8 - bp)));             \
> +        }                                                                 \
> +    }                                                                     \
> +}
> +
> +BALIGN_INSN(balign, 0x03, 1);
> +#if defined(TARGET_MIPS64)
> +BALIGN_INSN(dbalign, 0x07, 0);
> +#endif
> +#undef BALIGN_INSN
> +
> +target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rsl, rth;
> +
> +    rsl =  rs & MIPSDSP_LO;
> +    rth = (rt & MIPSDSP_HI) >> 16;
> +
> +    return (target_long)(int32_t)((rsl << 16) | rth);
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt)
> +{
> +    uint32_t rs0, rt1;
> +
> +    rs0 = rs & MIPSDSP_LLO;
> +    rt1 = (rt >> 32) & MIPSDSP_LLO;
> +
> +    return ((uint64_t)rs0 << 32) | (uint64_t)rt1;
> +}
> +#endif
> +
>  #undef MIPSDSP_LHI
>  #undef MIPSDSP_LLO
>  #undef MIPSDSP_HI
> diff --git a/target-mips/helper.h b/target-mips/helper.h
> index 31475a2..3d3c596 100644
> --- a/target-mips/helper.h
> +++ b/target-mips/helper.h
> @@ -624,4 +624,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, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmpu_lt_qb, 0, void, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmpu_le_qb, 0, void, tl, tl, env)
> +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, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmp_lt_ph, 0, void, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmp_le_ph, 0, void, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(cmpu_eq_ob, 0, void, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmpu_lt_ob, 0, void, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmpu_le_ob, 0, void, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmpgdu_eq_ob, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmpgdu_lt_ob, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmpgdu_le_ob, 0, tl, tl, tl, env)
> +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, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmp_lt_qh, 0, void, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmp_le_qh, 0, void, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmp_eq_pw, 0, void, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmp_lt_pw, 0, void, tl, tl, env)
> +DEF_HELPER_FLAGS_3(cmp_le_pw, 0, void, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(pick_qb, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(pick_ph, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(pick_ob, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(pick_qh, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(pick_pw, 0, tl, tl, tl, env)
> +#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, tl, tl, i32)
> +#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, tl, tl, i32)
> +#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 d5c2419..7102074 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 */
> @@ -13897,6 +13957,250 @@ static void gen_mipsdsp_bitinsn(CPUMIPSState *env, DisasContext *ctx,
>      MIPS_DEBUG("%s", opn);
>  }
>  
> +static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
> +                                     uint32_t op1, uint32_t op2,
> +                                     int ret, int v1, int v2, int check_ret)
> +{
> +    const char *opn = "mipsdsp add compare pick";
> +    TCGv_i32 t0 = tcg_temp_new_i32();
> +    TCGv t1 = tcg_temp_new();
> +
> +    if ((ret == 0) && (check_ret == 1)) {
> +        /* Treat as NOP. */
> +        MIPS_DEBUG("NOP");
> +        return;
> +    }
> +
> +    switch (op1) {
> +    case OPC_APPEND_DSP:
> +        switch (op2) {
> +        case OPC_APPEND:
> +            tcg_gen_movi_i32(t0, v2);
> +            gen_helper_append(cpu_gpr[ret], cpu_gpr[ret],
> +                              cpu_gpr[v1], t0);
> +            break;
> +        case OPC_PREPEND:
> +            tcg_gen_movi_i32(t0, v2);
> +            gen_helper_prepend(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[ret], t0);
> +            break;
> +        case OPC_BALIGN:
> +            tcg_gen_movi_i32(t0, v2);
> +                gen_helper_balign(cpu_gpr[ret], cpu_gpr[v1],
> +                                  cpu_gpr[ret], t0);
> +                break;
> +        default:            /* Invid */
> +            MIPS_INVAL("MASK APPEND");
> +            generate_exception(ctx, EXCP_RI);
> +            break;
> +        }
> +        break;
> +    case OPC_CMPU_EQ_QB_DSP:
> +        switch (op2) {
> +        case OPC_CMPU_EQ_QB:
> +            check_dsp(ctx);
> +            gen_helper_cmpu_eq_qb(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMPU_LT_QB:
> +            check_dsp(ctx);
> +            gen_helper_cmpu_lt_qb(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMPU_LE_QB:
> +            check_dsp(ctx);
> +            gen_helper_cmpu_le_qb(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMPGU_EQ_QB:
> +            check_dsp(ctx);
> +            gen_helper_cmpgu_eq_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_CMPGU_LT_QB:
> +            check_dsp(ctx);
> +            gen_helper_cmpgu_lt_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_CMPGU_LE_QB:
> +            check_dsp(ctx);
> +            gen_helper_cmpgu_le_qb(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_CMPGDU_EQ_QB:
> +            check_dspr2(ctx);
> +            gen_helper_cmpgu_eq_qb(t1, cpu_gpr[v1], cpu_gpr[v2]);
> +            tcg_gen_mov_tl(cpu_gpr[ret], t1);
> +            tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
> +            tcg_gen_shli_tl(t1, t1, 24);
> +            tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
> +            break;
> +        case OPC_CMPGDU_LT_QB:
> +            check_dspr2(ctx);
> +            gen_helper_cmpgu_lt_qb(t1, cpu_gpr[v1], cpu_gpr[v2]);
> +            tcg_gen_mov_tl(cpu_gpr[ret], t1);
> +            tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
> +            tcg_gen_shli_tl(t1, t1, 24);
> +            tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
> +            break;
> +        case OPC_CMPGDU_LE_QB:
> +            check_dspr2(ctx);
> +            gen_helper_cmpgu_le_qb(t1, cpu_gpr[v1], cpu_gpr[v2]);
> +            tcg_gen_mov_tl(cpu_gpr[ret], t1);
> +            tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
> +            tcg_gen_shli_tl(t1, t1, 24);
> +            tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
> +            break;
> +        case OPC_CMP_EQ_PH:
> +            check_dsp(ctx);
> +            gen_helper_cmp_eq_ph(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMP_LT_PH:
> +            check_dsp(ctx);
> +            gen_helper_cmp_lt_ph(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMP_LE_PH:
> +            check_dsp(ctx);
> +            gen_helper_cmp_le_ph(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_PICK_QB:
> +            check_dsp(ctx);
> +            gen_helper_pick_qb(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_PICK_PH:
> +            check_dsp(ctx);
> +            gen_helper_pick_ph(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_PACKRL_PH:
> +            check_dsp(ctx);
> +            gen_helper_packrl_ph(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        }
> +        break;
> +#ifdef TARGET_MIPS64
> +    case OPC_CMPU_EQ_OB_DSP:
> +        switch (op2) {
> +        case OPC_CMP_EQ_PW:
> +            check_dsp(ctx);
> +            gen_helper_cmp_eq_pw(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMP_LT_PW:
> +            check_dsp(ctx);
> +            gen_helper_cmp_lt_pw(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMP_LE_PW:
> +            check_dsp(ctx);
> +            gen_helper_cmp_le_pw(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMP_EQ_QH:
> +            check_dsp(ctx);
> +            gen_helper_cmp_eq_qh(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMP_LT_QH:
> +            check_dsp(ctx);
> +            gen_helper_cmp_lt_qh(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMP_LE_QH:
> +            check_dsp(ctx);
> +            gen_helper_cmp_le_qh(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMPGDU_EQ_OB:
> +            check_dspr2(ctx);
> +            gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], cpu_gpr[v1],
> +                                    cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMPGDU_LT_OB:
> +            check_dspr2(ctx);
> +            gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], cpu_gpr[v1],
> +                                    cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMPGDU_LE_OB:
> +            check_dspr2(ctx);
> +            gen_helper_cmpgdu_le_ob(cpu_gpr[ret], cpu_gpr[v1],
> +                                    cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMPGU_EQ_OB:
> +            check_dsp(ctx);
> +            gen_helper_cmpgu_eq_ob(cpu_gpr[ret], cpu_gpr[v1],
> +                                   cpu_gpr[v2]);
> +            break;
> +        case OPC_CMPGU_LT_OB:
> +            check_dsp(ctx);
> +            gen_helper_cmpgu_lt_ob(cpu_gpr[ret], cpu_gpr[v1],
> +                                   cpu_gpr[v2]);
> +            break;
> +        case OPC_CMPGU_LE_OB:
> +            check_dsp(ctx);
> +            gen_helper_cmpgu_le_ob(cpu_gpr[ret], cpu_gpr[v1],
> +                                   cpu_gpr[v2]);
> +            break;
> +        case OPC_CMPU_EQ_OB:
> +            check_dsp(ctx);
> +            gen_helper_cmpu_eq_ob(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMPU_LT_OB:
> +            check_dsp(ctx);
> +            gen_helper_cmpu_lt_ob(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_CMPU_LE_OB:
> +            check_dsp(ctx);
> +            gen_helper_cmpu_le_ob(cpu_gpr[v1], cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_PACKRL_PW:
> +            check_dsp(ctx);
> +            gen_helper_packrl_pw(cpu_gpr[ret], cpu_gpr[v1], cpu_gpr[v2]);
> +            break;
> +        case OPC_PICK_OB:
> +            check_dsp(ctx);
> +            gen_helper_pick_ob(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_PICK_PW:
> +            check_dsp(ctx);
> +            gen_helper_pick_pw(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        case OPC_PICK_QH:
> +            check_dsp(ctx);
> +            gen_helper_pick_qh(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[v2], cpu_env);
> +            break;
> +        }
> +        break;
> +    case OPC_DAPPEND_DSP:
> +        switch (op2) {
> +        case OPC_DAPPEND:
> +            tcg_gen_movi_i32(t0, v2);
> +            gen_helper_dappend(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[ret], t0);
> +            break;
> +        case OPC_PREPENDD:
> +            tcg_gen_movi_i32(t0, v2);
> +            gen_helper_prependd(cpu_gpr[ret], cpu_gpr[v1],
> +                                cpu_gpr[ret], t0);
> +            break;
> +        case OPC_PREPENDW:
> +            tcg_gen_movi_i32(t0, v2);
> +            gen_helper_prependw(cpu_gpr[ret], cpu_gpr[v1],
> +                                cpu_gpr[ret], t0);
> +            break;
> +        case OPC_DBALIGN:
> +            tcg_gen_movi_i32(t0, v2);
> +            gen_helper_dbalign(cpu_gpr[ret], cpu_gpr[v1],
> +                               cpu_gpr[ret], t0);
> +            break;
> +        default:            /* Invalid */
> +            MIPS_INVAL("MASK DAPPEND");
> +            generate_exception(ctx, EXCP_RI);
> +            break;
> +        }

In all the functions above, v1 or v2 can be the register 0.

> +        break;
> +#endif
> +    }
> +
> +    tcg_temp_free_i32(t0);
> +    tcg_temp_free(t1);
> +
> +    (void)opn; /* avoid a compiler warning */
> +    MIPS_DEBUG("%s", opn);
> +}
> +
>  /* End MIPSDSP functions. */
>  
>  static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
> @@ -14388,6 +14692,25 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>              case OPC_PRECRQU_S_QB_PH:
>                  gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
>                  break;
> +            case OPC_CMPU_EQ_QB:
> +            case OPC_CMPU_LT_QB:
> +            case OPC_CMPU_LE_QB:
> +            case OPC_CMP_EQ_PH:
> +            case OPC_CMP_LT_PH:
> +            case OPC_CMP_LE_PH:
> +                gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
> +                break;
> +            case OPC_CMPGU_EQ_QB:
> +            case OPC_CMPGU_LT_QB:
> +            case OPC_CMPGU_LE_QB:
> +            case OPC_CMPGDU_EQ_QB:
> +            case OPC_CMPGDU_LT_QB:
> +            case OPC_CMPGDU_LE_QB:
> +            case OPC_PICK_QB:
> +            case OPC_PICK_PH:
> +            case OPC_PACKRL_PH:
> +                gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
> +                break;
>              default:            /* Invalid */
>                  MIPS_INVAL("MASK CMPU.EQ.QB");
>                  generate_exception(ctx, EXCP_RI);
> @@ -14450,6 +14773,11 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>                  break;
>              }
>              break;
> +        case OPC_APPEND_DSP:
> +            check_dspr2(ctx);
> +            op2 = MASK_APPEND(ctx->opcode);
> +            gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
> +            break;
>  #if defined(TARGET_MIPS64)
>          case OPC_DEXTM ... OPC_DEXT:
>          case OPC_DINSM ... OPC_DINS:
> @@ -14560,12 +14888,40 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>              case OPC_PRECRQU_S_OB_QH:
>                  gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
>                  break;
> +            case OPC_CMPU_EQ_OB:
> +            case OPC_CMPU_LT_OB:
> +            case OPC_CMPU_LE_OB:
> +            case OPC_CMP_EQ_QH:
> +            case OPC_CMP_LT_QH:
> +            case OPC_CMP_LE_QH:
> +            case OPC_CMP_EQ_PW:
> +            case OPC_CMP_LT_PW:
> +            case OPC_CMP_LE_PW:
> +                gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
> +                break;
> +            case OPC_CMPGDU_EQ_OB:
> +            case OPC_CMPGDU_LT_OB:
> +            case OPC_CMPGDU_LE_OB:
> +            case OPC_CMPGU_EQ_OB:
> +            case OPC_CMPGU_LT_OB:
> +            case OPC_CMPGU_LE_OB:
> +            case OPC_PACKRL_PW:
> +            case OPC_PICK_OB:
> +            case OPC_PICK_PW:
> +            case OPC_PICK_QH:
> +                gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
> +                break;
>              default:            /* Invalid */
>                  MIPS_INVAL("MASK CMPU_EQ.OB");
>                  generate_exception(ctx, EXCP_RI);
>                  break;
>              }
>              break;
> +        case OPC_DAPPEND_DSP:
> +            check_dspr2(ctx);
> +            op2 = MASK_DAPPEND(ctx->opcode);
> +            gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
> +            break;
>          case OPC_DPAQ_W_QH_DSP:
>              op2 = MASK_DPAQ_W_QH(ctx->opcode);
>              switch (op2) {
> -- 
> 1.7.10.2 (Apple Git-33)
> 
> 

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

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

* Re: [Qemu-devel] [PATCH v9 11/14] target-mips-ase-dsp: Add DSP accumulator instructions
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 11/14] target-mips-ase-dsp: Add DSP accumulator instructions Jia Liu
@ 2012-10-06 14:51   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:51 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:48PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP Accumulator and DSPControl Access instructions.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/dsp_helper.c |  609 ++++++++++++++++++++++++++++++++++++++++++++++
>  target-mips/helper.h     |   35 +++
>  target-mips/translate.c  |  340 ++++++++++++++++++++++++++
>  3 files changed, 984 insertions(+)
> 
> diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
> index dabece4..6ff063b 100644
> --- a/target-mips/dsp_helper.c
> +++ b/target-mips/dsp_helper.c
> @@ -3476,6 +3476,615 @@ 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(target_ulong ac, target_ulong shift,
> +                           CPUMIPSState *env)
> +{
> +    int32_t tempI;
> +    int64_t tempDL[2];
> +
> +    shift = shift & 0x0F;
> +
> +    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
> +    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
> +        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
> +        set_DSPControl_overflow_flag(1, 23, env);
> +    }
> +
> +    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(1, 23, env);
> +    }
> +
> +    return (target_long)tempI;
> +}
> +
> +target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
> +                             CPUMIPSState *env)
> +{
> +    int64_t tempDL[2];
> +
> +    shift = shift & 0x0F;
> +
> +    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
> +    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
> +        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
> +        set_DSPControl_overflow_flag(1, 23, env);
> +    }
> +
> +    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(1, 23, env);
> +    }
> +
> +    return (target_long)(int32_t)(tempDL[0] >> 1);
> +}
> +
> +target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
> +                              CPUMIPSState *env)
> +{
> +    int32_t tempI, temp64;
> +    int64_t tempDL[2];
> +
> +    shift = shift & 0x0F;
> +
> +    mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
> +    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
> +        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
> +        set_DSPControl_overflow_flag(1, 23, env);
> +    }
> +    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(1, 23, env);
> +    }
> +
> +    return (target_long)tempI;
> +}
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_dextr_w(target_ulong ac, target_ulong shift,
> +                            CPUMIPSState *env)
> +{
> +    uint64_t temp[3];
> +
> +    shift = shift & 0x3F;
> +
> +    mipsdsp_rndrashift_acc(temp, ac, shift, env);
> +
> +    return (int64_t)(int32_t)(temp[0] >> 1);
> +}
> +
> +target_ulong helper_dextr_r_w(target_ulong ac, target_ulong shift,
> +                              CPUMIPSState *env)
> +{
> +    uint64_t temp[3];
> +    uint32_t temp128;
> +
> +    shift = shift & 0x3F;
> +    mipsdsp_rndrashift_acc(temp, ac, shift, env);
> +
> +    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] != ~0ull)) {
> +        set_DSPControl_overflow_flag(1, 23, env);
> +    }
> +
> +    return (int64_t)(int32_t)(temp[0] >> 1);
> +}
> +
> +target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift,
> +                               CPUMIPSState *env)
> +{
> +    uint64_t temp[3];
> +    uint32_t temp128;
> +
> +    shift = shift & 0x3F;
> +    mipsdsp_rndrashift_acc(temp, ac, shift, env);
> +
> +    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] != ~0ull)) {
> +        if (temp128 == 0) {
> +            temp[0] = 0x0FFFFFFFF;
> +        } else {
> +            temp[0] = 0x0100000000;
> +        }
> +        set_DSPControl_overflow_flag(1, 23, env);
> +    }
> +
> +    return (int64_t)(int32_t)(temp[0] >> 1);
> +}
> +
> +target_ulong helper_dextr_l(target_ulong ac, target_ulong shift,
> +                            CPUMIPSState *env)
> +{
> +    uint64_t temp[3];
> +    target_ulong result;
> +
> +    shift = shift & 0x3F;
> +
> +    mipsdsp_rndrashift_acc(temp, ac, shift, env);
> +    result = (temp[1] << 63) | (temp[0] >> 1);
> +
> +    return result;
> +}
> +
> +target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift,
> +                              CPUMIPSState *env)
> +{
> +    uint64_t temp[3];
> +    uint32_t temp128;
> +    target_ulong result;
> +
> +    shift = shift & 0x3F;
> +    mipsdsp_rndrashift_acc(temp, ac, shift, env);
> +
> +    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] != ~0ull)) {
> +        set_DSPControl_overflow_flag(1, 23, env);
> +    }
> +
> +    result = (temp[1] << 63) | (temp[0] >> 1);
> +
> +    return result;
> +}
> +
> +target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift,
> +                               CPUMIPSState *env)
> +{
> +    uint64_t temp[3];
> +    uint32_t temp128;
> +    target_ulong result;
> +
> +    shift = shift & 0x3F;
> +    mipsdsp_rndrashift_acc(temp, ac, shift, env);
> +
> +    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] != ~0ull)) {
> +        if (temp128 == 0) {
> +            temp[1] &= 0xFFFFFFFFFFFFFFFEull;
> +            temp[0] |= 0xFFFFFFFFFFFFFFFEull;
> +        } else {
> +            temp[1] |= 0x01;
> +            temp[0] &= 0x01;
> +        }
> +        set_DSPControl_overflow_flag(1, 23, env);
> +    }
> +    result = (temp[1] << 63) | (temp[0] >> 1);
> +
> +    return result;
> +}
> +#endif
> +
> +target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift,
> +                             CPUMIPSState *env)
> +{
> +    int64_t temp;
> +
> +    shift = shift & 0x0F;
> +
> +    temp = mipsdsp_rashift_short_acc(ac, shift, env);
> +    if (temp > 0x0000000000007FFFull) {
> +        temp = 0x00007FFF;
> +        set_DSPControl_overflow_flag(1, 23, env);
> +    } else if (temp < 0xFFFFFFFFFFFF8000ull) {
> +        temp = 0xFFFF8000;
> +        set_DSPControl_overflow_flag(1, 23, env);
> +    }
> +
> +    return (target_long)(int32_t)(temp & 0xFFFFFFFF);
> +}
> +
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_dextr_s_h(target_ulong ac, target_ulong shift,
> +                              CPUMIPSState *env)
> +{
> +    int64_t temp[2];
> +    uint32_t temp127;
> +
> +    shift = shift & 0x1F;
> +
> +    mipsdsp_rashift_acc((uint64_t *)temp, ac, shift, env);
> +
> +    temp127 = (temp[1] >> 63) & 0x01;
> +
> +    if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) {
> +        temp[0] &= 0xFFFF0000;
> +        temp[0] |= 0x00007FFF;
> +        set_DSPControl_overflow_flag(1, 23, env);
> +    } else if ((temp127 == 1) &&
> +            (temp[1] < 0xFFFFFFFFFFFFFFFFll
> +             || temp[0] < 0xFFFFFFFFFFFF1000ll)) {
> +        temp[0] &= 0xFFFF0000;
> +        temp[0] |= 0x00008000;
> +        set_DSPControl_overflow_flag(1, 23, env);
> +    }
> +
> +    return (int64_t)(int16_t)(temp[0] & MIPSDSP_LO);
> +}
> +
> +#endif
> +
> +target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState *env)
> +{
> +    int32_t start_pos;
> +    int sub;
> +    uint32_t temp;
> +    uint64_t acc;
> +
> +    size = size & 0x1F;
> +
> +    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(0, env);
> +    } else {
> +        set_DSPControl_efi(1, env);
> +    }
> +
> +    return (target_ulong)temp;
> +}
> +
> +target_ulong helper_extpdp(target_ulong ac, target_ulong size,
> +                           CPUMIPSState *env)
> +{
> +    int32_t start_pos;
> +    int sub;
> +    uint32_t temp;
> +    uint64_t acc;
> +
> +    size = size & 0x1F;
> +    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(start_pos - (size + 1), env);
> +        set_DSPControl_efi(0, env);
> +    } else {
> +        set_DSPControl_efi(1, env);
> +    }
> +
> +    return (target_ulong)temp;
> +}
> +
> +
> +#if defined(TARGET_MIPS64)
> +target_ulong helper_dextp(target_ulong ac, target_ulong size, CPUMIPSState *env)
> +{
> +    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(0, env);
> +    } else {
> +        set_DSPControl_efi(1, env);
> +    }
> +
> +    return temp;
> +}
> +
> +target_ulong helper_dextpdp(target_ulong ac, target_ulong size,
> +                            CPUMIPSState *env)
> +{
> +    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_pos(sub, env);
> +        set_DSPControl_efi(0, env);
> +    } else {
> +        set_DSPControl_efi(1, env);
> +    }
> +
> +    return temp;
> +}
> +
> +#endif
> +
> +void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env)
> +{
> +    int8_t  rs5_0;
> +    uint64_t temp, acc;
> +
> +    rs5_0 = rs & 0x3F;
> +    rs5_0 = (int8_t)(rs5_0 << 2) >> 2;
> +    rs5_0 = MIPSDSP_ABS(rs5_0);
> +    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 (rs5_0 > 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(target_ulong shift, target_ulong ac, CPUMIPSState *env)
> +{
> +    int8_t shift_t;
> +    uint64_t tempB, tempA;
> +
> +    shift_t = (uint8_t)(shift << 1) >> 1;
> +    shift_t = MIPSDSP_ABS(shift_t);
> +
> +    tempB = env->active_tc.HI[ac];
> +    tempA = env->active_tc.LO[ac];
> +
> +    if (shift_t != 0) {
> +        if (shift_t >= 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(target_ulong ac, target_ulong rs, CPUMIPSState *env)
> +{
> +    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(pos + 32, env);
> +    }
> +}
> +
> +#if defined(TARGET_MIPS64)
> +void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env)
> +{
> +    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(pos, env);
> +    }
> +}
> +#endif
> +
> +void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
> +{
> +    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(target_ulong masknum, CPUMIPSState *env)
> +{
> +    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 3d3c596..45af62f 100644
> --- a/target-mips/helper.h
> +++ b/target-mips/helper.h
> @@ -676,4 +676,39 @@ 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, tl, tl, env)
> +DEF_HELPER_FLAGS_3(extr_r_w, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(extr_rs_w, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(dextr_w, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(dextr_r_w, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(dextr_rs_w, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(dextr_l, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(dextr_r_l, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(dextr_rs_l, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(extr_s_h, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(dextr_s_h, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(extp, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(extpdp, 0, tl, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(dextp, 0, tl, tl, tl, env)
> +DEF_HELPER_FLAGS_3(dextpdp, 0, tl, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(shilo, 0, void, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(dshilo, 0, void, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(mthlip, 0, void, tl, tl, env)
> +#if defined(TARGET_MIPS64)
> +DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env)
> +#endif
> +DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env)
> +DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env)
> +
> +
> +
>  #include "def-helper.h"
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index 7102074..fc034b8 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,30 @@ 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 +705,32 @@ 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,
> +};
> +
>  #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
>  enum {
>      /* DSP Bit/Manipulation Sub-class */
> @@ -14201,6 +14256,225 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
>      MIPS_DEBUG("%s", opn);
>  }
>  
> +static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
> +                                int ret, int v1, int v2, int check_ret)
> +
> +{
> +    const char *opn = "mipsdsp accumulator";
> +    TCGv t0 = tcg_temp_new();
> +    TCGv t1 = tcg_temp_new();
> +    int16_t imm;
> +
> +    if ((ret == 0) && (check_ret == 1)) {
> +        /* Treat as NOP. */
> +        MIPS_DEBUG("NOP");
> +        return;
> +    }
> +
> +    switch (op1) {
> +    case OPC_EXTR_W_DSP:
> +        check_dsp(ctx);
> +        switch (op2) {
> +        case OPC_EXTR_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_EXTR_R_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_EXTR_RS_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_EXTR_S_H:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_EXTRV_S_H:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_extr_s_h(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_EXTRV_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_extr_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_EXTRV_R_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_extr_r_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_EXTRV_RS_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_extr_rs_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_EXTP:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_EXTPV:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_extp(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_EXTPDP:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_EXTPDPV:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_extpdp(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_SHILO:
> +            imm = (ctx->opcode >> 20) & 0x3F;
> +            tcg_gen_movi_tl(t0, ret);
> +            tcg_gen_movi_tl(t1, imm);
> +            gen_helper_shilo(t0, t1, cpu_env);
> +            break;
> +        case OPC_SHILOV:
> +            tcg_gen_movi_tl(t0, ret);
> +            gen_helper_shilo(t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_MTHLIP:
> +            tcg_gen_movi_tl(t0, ret);
> +            gen_helper_mthlip(t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_WRDSP:
> +            imm = (ctx->opcode >> 11) & 0x3FF;
> +            tcg_gen_movi_tl(t0, imm);
> +            gen_helper_wrdsp(cpu_gpr[v1], t0, cpu_env);
> +            break;
> +        case OPC_RDDSP:
> +            imm = (ctx->opcode >> 16) & 0x03FF;
> +            tcg_gen_movi_tl(t0, imm);
> +            gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
> +            break;
> +        }
> +        break;
> +#ifdef TARGET_MIPS64
> +    case OPC_DEXTR_W_DSP:
> +        check_dsp(ctx);
> +        switch (op2) {
> +        case OPC_DMTHLIP:
> +            tcg_gen_movi_tl(t0, ret);
> +            gen_helper_dmthlip(cpu_gpr[v1], t0, cpu_env);
> +            break;
> +        case OPC_DSHILO:
> +            {
> +                int shift = (ctx->opcode >> 19) & 0x7F;
> +                int ac = (ctx->opcode >> 11) & 0x03;
> +                tcg_gen_movi_tl(t0, shift);
> +                tcg_gen_movi_tl(t1, ac);
> +                gen_helper_dshilo(t0, t1, cpu_env);
> +                break;
> +            }
> +        case OPC_DSHILOV:
> +            {
> +                int ac = (ctx->opcode >> 11) & 0x03;
> +                tcg_gen_movi_tl(t0, ac);
> +                gen_helper_dshilo(cpu_gpr[v1], t0, cpu_env);
> +                break;
> +            }
> +        case OPC_DEXTP:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +
> +            gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_DEXTPV:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_dextp(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_DEXTPDP:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_DEXTPDPV:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_dextpdp(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_DEXTR_L:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_DEXTR_R_L:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_DEXTR_RS_L:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_DEXTR_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_DEXTR_R_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_DEXTR_RS_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_DEXTR_S_H:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_DEXTRV_S_H:
> +            tcg_gen_movi_tl(t0, v2);
> +            tcg_gen_movi_tl(t1, v1);
> +            gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
> +            break;
> +        case OPC_DEXTRV_L:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_dextr_l(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_DEXTRV_R_L:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_dextr_r_l(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_DEXTRV_RS_L:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_dextr_rs_l(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_DEXTRV_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_dextr_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_DEXTRV_R_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_dextr_r_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        case OPC_DEXTRV_RS_W:
> +            tcg_gen_movi_tl(t0, v2);
> +            gen_helper_dextr_rs_w(cpu_gpr[ret], t0, cpu_gpr[v1], cpu_env);
> +            break;
> +        }

In all the functions above, v0 and v1 can be the zero register.

> +        break;
> +#endif
> +    }
> +
> +
> +    tcg_temp_free(t0);
> +    tcg_temp_free(t1);
> +
> +    (void)opn; /* avoid a compiler warning */
> +    MIPS_DEBUG("%s", opn);
> +}
> +
>  /* End MIPSDSP functions. */
>  
>  static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
> @@ -14778,6 +15052,38 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>              op2 = MASK_APPEND(ctx->opcode);
>              gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
>              break;
> +        case OPC_EXTR_W_DSP:
> +            op2 = MASK_EXTR_W(ctx->opcode);
> +            switch (op2) {
> +            case OPC_EXTR_W:
> +            case OPC_EXTR_R_W:
> +            case OPC_EXTR_RS_W:
> +            case OPC_EXTR_S_H:
> +            case OPC_EXTRV_S_H:
> +            case OPC_EXTRV_W:
> +            case OPC_EXTRV_R_W:
> +            case OPC_EXTRV_RS_W:
> +            case OPC_EXTP:
> +            case OPC_EXTPV:
> +            case OPC_EXTPDP:
> +            case OPC_EXTPDPV:
> +                gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
> +                break;
> +            case OPC_RDDSP:
> +                gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
> +                break;
> +            case OPC_SHILO:
> +            case OPC_SHILOV:
> +            case OPC_MTHLIP:
> +            case OPC_WRDSP:
> +                gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
> +                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:
> @@ -14922,6 +15228,40 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
>              op2 = MASK_DAPPEND(ctx->opcode);
>              gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
>              break;
> +        case OPC_DEXTR_W_DSP:
> +            op2 = MASK_DEXTR_W(ctx->opcode);
> +            switch (op2) {
> +            case OPC_DEXTP:
> +            case OPC_DEXTPDP:
> +            case OPC_DEXTPDPV:
> +            case OPC_DEXTPV:
> +            case OPC_DEXTR_L:
> +            case OPC_DEXTR_R_L:
> +            case OPC_DEXTR_RS_L:
> +            case OPC_DEXTR_W:
> +            case OPC_DEXTR_R_W:
> +            case OPC_DEXTR_RS_W:
> +            case OPC_DEXTR_S_H:
> +            case OPC_DEXTRV_L:
> +            case OPC_DEXTRV_R_L:
> +            case OPC_DEXTRV_RS_L:
> +            case OPC_DEXTRV_S_H:
> +            case OPC_DEXTRV_W:
> +            case OPC_DEXTRV_R_W:
> +            case OPC_DEXTRV_RS_W:
> +                gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
> +                break;
> +            case OPC_DMTHLIP:
> +            case OPC_DSHILO:
> +            case OPC_DSHILOV:
> +                gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
> +                break;
> +            default:            /* Invalid */
> +                MIPS_INVAL("MASK EXTR.W");
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            break;
>          case OPC_DPAQ_W_QH_DSP:
>              op2 = MASK_DPAQ_W_QH(ctx->opcode);
>              switch (op2) {
> -- 
> 1.7.10.2 (Apple Git-33)
> 
> 

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

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

* Re: [Qemu-devel] [PATCH v9 12/14] target-mips-ase-dsp: Add MIPS DSP processors
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 12/14] target-mips-ase-dsp: Add MIPS DSP processors Jia Liu
@ 2012-10-06 14:51   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:51 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:49PM +0800, Jia Liu wrote:
> Add 74kf and mips64dspr2-generic-cpu model for test.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-mips/translate_init.c |   52 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
> index c39138f..73a14a9 100644
> --- a/target-mips/translate_init.c
> +++ b/target-mips/translate_init.c
> @@ -311,6 +311,29 @@ static const mips_def_t mips_defs[] =
>          .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT,
>          .mmu_type = MMU_TYPE_R4000,
>      },
> +    {
> +        .name = "74Kf",
> +        .CP0_PRid = 0x97,

According to the documentation, this should be 0x00019700;

> +        .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) | (1 << CP0C3_DSPP),
> +        .CP0_LLAddr_rw_bitmask = 0,
> +        .CP0_LLAddr_shift = 4,
> +        .SYNCI_Step = 32,
> +        .CCRes = 2,
> +        .CP0_Status_rw_bitmask = 0x3778FF1F,
> +        .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 +507,35 @@ static const mips_def_t mips_defs[] =
>        .insn_flags = CPU_LOONGSON2F,
>        .mmu_type = MMU_TYPE_R4000,
>      },
> +    {
> +        /* A generic CPU providing MIPS64 ASE DSP 2 features.
> +           FIXME: Eventually this should be replaced by a real CPU model. */
> +        .name = "mips64dspr2",
> +        .CP0_PRid = 0x00010000,
> +        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
> +                       (MMU_TYPE_R4000 << CP0C0_MT),
> +        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << 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 | (1 << CP0C3_LPA),
> +        .CP0_LLAddr_rw_bitmask = 0,
> +        .CP0_LLAddr_shift = 0,
> +        .SYNCI_Step = 32,
> +        .CCRes = 2,
> +        .CP0_Status_rw_bitmask = 0x36FBFFFF,
> +        .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) |
> +                    (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
> +                    (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
> +        .SEGBITS = 42,
> +        /* The architectural limit is 59, but we have hardcoded 36 bit
> +           in some places...
> +        .PABITS = 59, */ /* the architectural limit */
> +        .PABITS = 36,
> +        .insn_flags = CPU_MIPS64R2 | ASE_DSP | ASE_DSPR2,
> +        .mmu_type = MMU_TYPE_R4000,
> +    },
>  
>  #endif
>  };
> -- 
> 1.7.10.2 (Apple Git-33)
> 
> 

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

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

* Re: [Qemu-devel] [PATCH v9 13/14] target-mips-ase-dsp: Add testcases
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 13/14] target-mips-ase-dsp: Add testcases Jia Liu
@ 2012-10-06 14:51   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:51 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:50PM +0800, Jia Liu wrote:
> Add MIPS ASE DSP testcases.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  tests/tcg/mips/mips32-dsp/Makefile             |  135 +++++++++++
>  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_phl.c      |   41 ++++
>  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/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             |  305 ++++++++++++++++++++++++
>  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               |   16 ++
>  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      |   62 +++++
>  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_phl.c      |   46 ++++
>  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/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             |   16 ++
>  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, 15870 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_phl.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/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_phl.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/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..232527b
> --- /dev/null
> +++ b/tests/tcg/mips/mips32-dsp/Makefile
> @@ -0,0 +1,135 @@
> +-include ../../config-host.mak
> +
> +CROSS=mips64el-unknown-linux-gnu-
> +
> +SIM=qemu-mipsel
> +SIM_FLAGS=-cpu 74Kf
> +
> +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_phl.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..2337abe
> --- /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 addr, index;
> +    int result;
> +
> +    value  = 0xBCDEF389;
> +    p = &value;
> +    addr = (unsigned 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..10be3b3
> --- /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 addr, index;
> +    int result;
> +
> +    value  = 0xBCDEF389;
> +    p = &value;
> +    addr = (unsigned 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..e6543c9
> --- /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 addr, index;
> +    int result;
> +
> +    value  = 0xBCDEF389;
> +    p = &value;
> +    addr = (unsigned 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..6111d8d
> --- /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 = 0x00;
> +    resultl = 0x7FFFFFFF;
> +
> +    __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..96b4915
> --- /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 = 0x00;
> +    resultl = 0x7FFFFFFF;
> +
> +    __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_phl.c b/tests/tcg/mips/mips32-dsp/muleq_s_w_phl.c
> new file mode 100644
> index 0000000..b3a5370
> --- /dev/null
> +++ b/tests/tcg/mips/mips32-dsp/muleq_s_w_phl.c
> @@ -0,0 +1,41 @@
> +#include<stdio.h>
> +#include<assert.h>
> +
> +int main()
> +{
> +    int rd, rs, rt, dsp;
> +    int result, resultdsp;
> +
> +    rs = 0x80001234;
> +    rt = 0x80001234;
> +    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 = 0x12349988;
> +    rt = 0x43219988;
> +    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-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/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..5a07a72
> --- /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 74Kf
> +
> +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..244ecea
> --- /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 = 0x87654321;
> +    rt = 0x12345678;
> +    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..8e4da4f
> --- /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 = 0x87654321;
> +    rt = 0x12345678;
> +    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..b6e358d
> --- /dev/null
> +++ b/tests/tcg/mips/mips64-dsp/Makefile
> @@ -0,0 +1,305 @@
> +
> +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_phl.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..dd0565f
> --- /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 = 0x2100000000123456;
> +
> +    __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..ab3c351
> --- /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 = 0x2100000000123456;
> +    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..e4a2072
> --- /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 = 0x123456;
> +    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..654dfaf
> --- /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 = 0x123456;
> +
> +    __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..44b0160
> --- /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 = 0x2100000000123456;
> +
> +    __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..c5b3850
> --- /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 = 0x2100000000123456;
> +    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..7cefdab
> --- /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 = 0x123456;
> +    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..4028a7a
> --- /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 = 0x123456;
> +
> +    __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..8789e84
> --- /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 = 0x1;
> +    resl = 0x9;
> +    resdsp = 0x00;
> +
> +    __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..4bfb00b
> --- /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 = 0xffffffffffffffff;
> +    resl = 0x00;
> +
> +    resdsp = 0x01;
> +
> +    __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..9a099ae
> --- /dev/null
> +++ b/tests/tcg/mips/mips64-dsp/head.S
> @@ -0,0 +1,16 @@
> +/*
> + *  Startup Code for MIPS64 CPU-core
> + *
> + */
> +.text
> +.globl _start
> +.align 4
> +_start:
> +    ori    $2, $2, 0xffff
> +    sll    $2, $2, 16
> +    ori    $2, $2, 0xffff
> +    mtc0   $2, $12, 0
> +    jal    main
> +
> +end:
> +    b end
> 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..e467aa2
> --- /dev/null
> +++ b/tests/tcg/mips/mips64-dsp/maq_sa_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 = 0x00;
> +    resultl = 0x15ae87f5;
> +
> +    __asm
> +        ("mthi %2, $ac1\n\t"
> +         "mtlo %3, $ac1\n\t"
> +         "maq_sa.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("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_phl.c b/tests/tcg/mips/mips64-dsp/muleq_s_w_phl.c
> new file mode 100644
> index 0000000..76c615b
> --- /dev/null
> +++ b/tests/tcg/mips/mips64-dsp/muleq_s_w_phl.c
> @@ -0,0 +1,46 @@
> +#include "io.h"
> +
> +int main(void)
> +{
> +    long long rd, rs, rt, dsp;
> +    long long result, resultdsp;
> +
> +    rs = 0x80009988;
> +    rt = 0x80009988;
> +    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.phr wrong\n");
> +
> +        return -1;
> +    }
> +
> +    rs = 0x12343322;
> +    rt = 0x43213322;
> +    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.phr wrong\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/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..d35376a
> --- /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 error1\n");
> +
> +        return -1;
> +    }
> +
> +    rd = 0;
> +    result = 0xFFFFFE00FFFFFE00;
> +    __asm
> +        ("repl.pw %0, 0xFFFFFFFFFFFFFE00\n\t"
> +         : "=r"(rd)
> +        );
> +
> +    if (result != rd) {
> +        printf("repl.pw error2\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..9a099ae
> --- /dev/null
> +++ b/tests/tcg/mips/mips64-dspr2/head.S
> @@ -0,0 +1,16 @@
> +/*
> + *  Startup Code for MIPS64 CPU-core
> + *
> + */
> +.text
> +.globl _start
> +.align 4
> +_start:
> +    ori    $2, $2, 0xffff
> +    sll    $2, $2, 16
> +    ori    $2, $2, 0xffff
> +    mtc0   $2, $12, 0
> +    jal    main
> +
> +end:
> +    b end
> 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..db609b2
> --- /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 = 0xFFFFFFFFF504F4B4;
> +    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..60a6b1b
> --- /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 = 0x87654321;
> +    rt = 0x12345678;
> +    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..ae32cc0
> --- /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 = 0x87654321;
> +    rt = 0x12345678;
> +    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.10.2 (Apple Git-33)
> 
> 

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

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

* Re: [Qemu-devel] [PATCH v9 14/14] target-mips-ase-dsp: Change TODO file
  2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 14/14] target-mips-ase-dsp: Change TODO file Jia Liu
@ 2012-10-06 14:52   ` Aurelien Jarno
  0 siblings, 0 replies; 30+ messages in thread
From: Aurelien Jarno @ 2012-10-06 14:52 UTC (permalink / raw)
  To: Jia Liu; +Cc: qemu-devel

On Thu, Sep 27, 2012 at 09:24:51PM +0800, Jia Liu wrote:
> Delete DSP r1 & DSP r2 from TODO file.
> 
> 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.10.2 (Apple Git-33)
> 
> 

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

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

end of thread, other threads:[~2012-10-06 14:53 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-27 13:24 [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support Jia Liu
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 01/14] target-mips-ase-dsp: Add internal funtions Jia Liu
2012-10-06 14:51   ` Aurelien Jarno
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 02/14] target-mips-ase-dsp: Add dsp resources access check Jia Liu
2012-10-06 14:51   ` Aurelien Jarno
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 03/14] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Jia Liu
2012-10-06 14:51   ` Aurelien Jarno
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 04/14] target-mips-ase-dsp: Add branch instructions Jia Liu
2012-10-06 14:51   ` Aurelien Jarno
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 05/14] target-mips-ase-dsp: Add load instructions Jia Liu
2012-10-06 14:51   ` Aurelien Jarno
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 06/14] target-mips-ase-dsp: Add arithmetic instructions Jia Liu
2012-10-06 14:51   ` Aurelien Jarno
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 07/14] target-mips-ase-dsp: Add GPR-based shift instructions Jia Liu
2012-10-06 14:51   ` Aurelien Jarno
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 08/14] target-mips-ase-dsp: Add multiply instructions Jia Liu
2012-10-06 14:51   ` Aurelien Jarno
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 09/14] target-mips-ase-dsp: Add bit/manipulation instructions Jia Liu
2012-10-06 14:51   ` Aurelien Jarno
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 10/14] target-mips-ase-dsp: Add compare-pick instructions Jia Liu
2012-10-06 14:51   ` Aurelien Jarno
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 11/14] target-mips-ase-dsp: Add DSP accumulator instructions Jia Liu
2012-10-06 14:51   ` Aurelien Jarno
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 12/14] target-mips-ase-dsp: Add MIPS DSP processors Jia Liu
2012-10-06 14:51   ` Aurelien Jarno
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 13/14] target-mips-ase-dsp: Add testcases Jia Liu
2012-10-06 14:51   ` Aurelien Jarno
2012-09-27 13:24 ` [Qemu-devel] [PATCH v9 14/14] target-mips-ase-dsp: Change TODO file Jia Liu
2012-10-06 14:52   ` Aurelien Jarno
2012-10-06  2:33 ` [Qemu-devel] [PATCH v9 00/14] QEMU MIPS ASE DSP support 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.