summaryrefslogtreecommitdiffstats
path: root/src/tests/tcg
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/tcg')
-rw-r--r--src/tests/tcg/Makefile156
-rw-r--r--src/tests/tcg/alpha/Makefile35
-rw-r--r--src/tests/tcg/alpha/crt.s26
-rw-r--r--src/tests/tcg/alpha/hello-alpha.c5
-rw-r--r--src/tests/tcg/alpha/test-cond.c87
-rw-r--r--src/tests/tcg/alpha/test-ovf.c29
-rw-r--r--src/tests/tcg/cris/.gdbinit11
-rw-r--r--src/tests/tcg/cris/Makefile155
-rw-r--r--src/tests/tcg/cris/README1
-rw-r--r--src/tests/tcg/cris/check_abs.c40
-rw-r--r--src/tests/tcg/cris/check_addc.c58
-rw-r--r--src/tests/tcg/cris/check_addcm.c85
-rw-r--r--src/tests/tcg/cris/check_addi.s57
-rw-r--r--src/tests/tcg/cris/check_addiv32.s62
-rw-r--r--src/tests/tcg/cris/check_addm.s96
-rw-r--r--src/tests/tcg/cris/check_addo.c125
-rw-r--r--src/tests/tcg/cris/check_addoq.c44
-rw-r--r--src/tests/tcg/cris/check_addq.s47
-rw-r--r--src/tests/tcg/cris/check_addr.s96
-rw-r--r--src/tests/tcg/cris/check_addxc.s91
-rw-r--r--src/tests/tcg/cris/check_addxm.s106
-rw-r--r--src/tests/tcg/cris/check_addxr.s96
-rw-r--r--src/tests/tcg/cris/check_andc.s80
-rw-r--r--src/tests/tcg/cris/check_andm.s90
-rw-r--r--src/tests/tcg/cris/check_andq.s46
-rw-r--r--src/tests/tcg/cris/check_andr.s95
-rw-r--r--src/tests/tcg/cris/check_asr.s230
-rw-r--r--src/tests/tcg/cris/check_ba.s93
-rw-r--r--src/tests/tcg/cris/check_bas.s102
-rw-r--r--src/tests/tcg/cris/check_bcc.s197
-rw-r--r--src/tests/tcg/cris/check_bound.c142
-rw-r--r--src/tests/tcg/cris/check_boundc.s101
-rw-r--r--src/tests/tcg/cris/check_boundr.s125
-rw-r--r--src/tests/tcg/cris/check_btst.s96
-rw-r--r--src/tests/tcg/cris/check_clearfv32.s19
-rw-r--r--src/tests/tcg/cris/check_clrjmp1.s36
-rw-r--r--src/tests/tcg/cris/check_cmp-2.s15
-rw-r--r--src/tests/tcg/cris/check_cmpc.s86
-rw-r--r--src/tests/tcg/cris/check_cmpm.s96
-rw-r--r--src/tests/tcg/cris/check_cmpq.s75
-rw-r--r--src/tests/tcg/cris/check_cmpr.s102
-rw-r--r--src/tests/tcg/cris/check_cmpxc.s92
-rw-r--r--src/tests/tcg/cris/check_cmpxm.s106
-rw-r--r--src/tests/tcg/cris/check_dstep.s42
-rw-r--r--src/tests/tcg/cris/check_ftag.c37
-rw-r--r--src/tests/tcg/cris/check_gcctorture_pr28634-1.c15
-rw-r--r--src/tests/tcg/cris/check_gcctorture_pr28634.c15
-rw-r--r--src/tests/tcg/cris/check_glibc_kernelversion.c116
-rw-r--r--src/tests/tcg/cris/check_hello.c7
-rw-r--r--src/tests/tcg/cris/check_int64.c47
-rw-r--r--src/tests/tcg/cris/check_jsr.s85
-rw-r--r--src/tests/tcg/cris/check_lapc.s78
-rw-r--r--src/tests/tcg/cris/check_lsl.s217
-rw-r--r--src/tests/tcg/cris/check_lsr.s218
-rw-r--r--src/tests/tcg/cris/check_lz.c49
-rw-r--r--src/tests/tcg/cris/check_mapbrk.c39
-rw-r--r--src/tests/tcg/cris/check_mcp.s49
-rw-r--r--src/tests/tcg/cris/check_mmap1.c48
-rw-r--r--src/tests/tcg/cris/check_mmap2.c48
-rw-r--r--src/tests/tcg/cris/check_mmap3.c33
-rw-r--r--src/tests/tcg/cris/check_movdelsr1.s33
-rw-r--r--src/tests/tcg/cris/check_movecr.s37
-rw-r--r--src/tests/tcg/cris/check_movei.s50
-rw-r--r--src/tests/tcg/cris/check_movemr.s78
-rw-r--r--src/tests/tcg/cris/check_movemrv32.s96
-rw-r--r--src/tests/tcg/cris/check_moveq.c51
-rw-r--r--src/tests/tcg/cris/check_mover.s28
-rw-r--r--src/tests/tcg/cris/check_moverm.s45
-rw-r--r--src/tests/tcg/cris/check_movmp.s131
-rw-r--r--src/tests/tcg/cris/check_movpmv32.s35
-rw-r--r--src/tests/tcg/cris/check_movpr.s28
-rw-r--r--src/tests/tcg/cris/check_movprv32.s21
-rw-r--r--src/tests/tcg/cris/check_movscr.s29
-rw-r--r--src/tests/tcg/cris/check_movsm.s44
-rw-r--r--src/tests/tcg/cris/check_movsr.s46
-rw-r--r--src/tests/tcg/cris/check_movucr.s33
-rw-r--r--src/tests/tcg/cris/check_movum.s40
-rw-r--r--src/tests/tcg/cris/check_movur.s45
-rw-r--r--src/tests/tcg/cris/check_mulv32.s51
-rw-r--r--src/tests/tcg/cris/check_mulx.s246
-rw-r--r--src/tests/tcg/cris/check_neg.s104
-rw-r--r--src/tests/tcg/cris/check_not.s31
-rw-r--r--src/tests/tcg/cris/check_openpf1.c38
-rw-r--r--src/tests/tcg/cris/check_openpf2.c16
-rw-r--r--src/tests/tcg/cris/check_openpf3.c49
-rw-r--r--src/tests/tcg/cris/check_openpf4.c5
-rw-r--r--src/tests/tcg/cris/check_openpf5.c56
-rw-r--r--src/tests/tcg/cris/check_orc.s71
-rw-r--r--src/tests/tcg/cris/check_orm.s75
-rw-r--r--src/tests/tcg/cris/check_orq.s41
-rw-r--r--src/tests/tcg/cris/check_orr.s84
-rw-r--r--src/tests/tcg/cris/check_ret.s25
-rw-r--r--src/tests/tcg/cris/check_scc.s95
-rw-r--r--src/tests/tcg/cris/check_settls1.c45
-rw-r--r--src/tests/tcg/cris/check_sigalrm.c26
-rw-r--r--src/tests/tcg/cris/check_stat1.c16
-rw-r--r--src/tests/tcg/cris/check_stat2.c20
-rw-r--r--src/tests/tcg/cris/check_stat3.c25
-rw-r--r--src/tests/tcg/cris/check_stat4.c27
-rw-r--r--src/tests/tcg/cris/check_subc.s87
-rw-r--r--src/tests/tcg/cris/check_subm.s96
-rw-r--r--src/tests/tcg/cris/check_subq.s52
-rw-r--r--src/tests/tcg/cris/check_subr.s102
-rw-r--r--src/tests/tcg/cris/check_swap.c76
-rw-r--r--src/tests/tcg/cris/check_time1.c46
-rw-r--r--src/tests/tcg/cris/check_time2.c18
-rw-r--r--src/tests/tcg/cris/check_xarith.s72
-rw-r--r--src/tests/tcg/cris/crisutils.h76
-rw-r--r--src/tests/tcg/cris/crt.s13
-rw-r--r--src/tests/tcg/cris/sys.c51
-rw-r--r--src/tests/tcg/cris/sys.h16
-rw-r--r--src/tests/tcg/cris/testutils.inc117
-rw-r--r--src/tests/tcg/hello-arm.c113
-rw-r--r--src/tests/tcg/hello-i386.c27
-rw-r--r--src/tests/tcg/hello-mips.c64
-rw-r--r--src/tests/tcg/linux-test.c538
-rw-r--r--src/tests/tcg/lm32/Makefile106
-rw-r--r--src/tests/tcg/lm32/crt.S84
-rw-r--r--src/tests/tcg/lm32/helper.S65
-rw-r--r--src/tests/tcg/lm32/linker.ld55
-rw-r--r--src/tests/tcg/lm32/macros.inc90
-rw-r--r--src/tests/tcg/lm32/test_add.S75
-rw-r--r--src/tests/tcg/lm32/test_addi.S56
-rw-r--r--src/tests/tcg/lm32/test_and.S45
-rw-r--r--src/tests/tcg/lm32/test_andhi.S35
-rw-r--r--src/tests/tcg/lm32/test_andi.S35
-rw-r--r--src/tests/tcg/lm32/test_b.S13
-rw-r--r--src/tests/tcg/lm32/test_be.S48
-rw-r--r--src/tests/tcg/lm32/test_bg.S78
-rw-r--r--src/tests/tcg/lm32/test_bge.S78
-rw-r--r--src/tests/tcg/lm32/test_bgeu.S78
-rw-r--r--src/tests/tcg/lm32/test_bgu.S78
-rw-r--r--src/tests/tcg/lm32/test_bi.S23
-rw-r--r--src/tests/tcg/lm32/test_bne.S48
-rw-r--r--src/tests/tcg/lm32/test_break.S20
-rw-r--r--src/tests/tcg/lm32/test_bret.S38
-rw-r--r--src/tests/tcg/lm32/test_call.S16
-rw-r--r--src/tests/tcg/lm32/test_calli.S15
-rw-r--r--src/tests/tcg/lm32/test_cmpe.S40
-rw-r--r--src/tests/tcg/lm32/test_cmpei.S35
-rw-r--r--src/tests/tcg/lm32/test_cmpg.S64
-rw-r--r--src/tests/tcg/lm32/test_cmpge.S64
-rw-r--r--src/tests/tcg/lm32/test_cmpgei.S70
-rw-r--r--src/tests/tcg/lm32/test_cmpgeu.S64
-rw-r--r--src/tests/tcg/lm32/test_cmpgeui.S70
-rw-r--r--src/tests/tcg/lm32/test_cmpgi.S70
-rw-r--r--src/tests/tcg/lm32/test_cmpgu.S64
-rw-r--r--src/tests/tcg/lm32/test_cmpgui.S70
-rw-r--r--src/tests/tcg/lm32/test_cmpne.S40
-rw-r--r--src/tests/tcg/lm32/test_cmpnei.S35
-rw-r--r--src/tests/tcg/lm32/test_divu.S29
-rw-r--r--src/tests/tcg/lm32/test_eret.S38
-rw-r--r--src/tests/tcg/lm32/test_lb.S49
-rw-r--r--src/tests/tcg/lm32/test_lbu.S49
-rw-r--r--src/tests/tcg/lm32/test_lh.S49
-rw-r--r--src/tests/tcg/lm32/test_lhu.S49
-rw-r--r--src/tests/tcg/lm32/test_lw.S32
-rw-r--r--src/tests/tcg/lm32/test_modu.S35
-rw-r--r--src/tests/tcg/lm32/test_mul.S70
-rw-r--r--src/tests/tcg/lm32/test_muli.S45
-rw-r--r--src/tests/tcg/lm32/test_nor.S51
-rw-r--r--src/tests/tcg/lm32/test_nori.S35
-rw-r--r--src/tests/tcg/lm32/test_or.S51
-rw-r--r--src/tests/tcg/lm32/test_orhi.S35
-rw-r--r--src/tests/tcg/lm32/test_ori.S35
-rw-r--r--src/tests/tcg/lm32/test_ret.S14
-rw-r--r--src/tests/tcg/lm32/test_sb.S32
-rw-r--r--src/tests/tcg/lm32/test_scall.S24
-rw-r--r--src/tests/tcg/lm32/test_sextb.S20
-rw-r--r--src/tests/tcg/lm32/test_sexth.S20
-rw-r--r--src/tests/tcg/lm32/test_sh.S32
-rw-r--r--src/tests/tcg/lm32/test_sl.S45
-rw-r--r--src/tests/tcg/lm32/test_sli.S30
-rw-r--r--src/tests/tcg/lm32/test_sr.S57
-rw-r--r--src/tests/tcg/lm32/test_sri.S40
-rw-r--r--src/tests/tcg/lm32/test_sru.S57
-rw-r--r--src/tests/tcg/lm32/test_srui.S40
-rw-r--r--src/tests/tcg/lm32/test_sub.S75
-rw-r--r--src/tests/tcg/lm32/test_sw.S38
-rw-r--r--src/tests/tcg/lm32/test_xnor.S51
-rw-r--r--src/tests/tcg/lm32/test_xnori.S35
-rw-r--r--src/tests/tcg/lm32/test_xor.S51
-rw-r--r--src/tests/tcg/lm32/test_xori.S35
-rw-r--r--src/tests/tcg/mips/mips32-dsp/Makefile136
-rw-r--r--src/tests/tcg/mips/mips32-dsp/absq_s_ph.c31
-rw-r--r--src/tests/tcg/mips/mips32-dsp/absq_s_w.c37
-rw-r--r--src/tests/tcg/mips/mips32-dsp/addq_ph.c46
-rw-r--r--src/tests/tcg/mips/mips32-dsp/addq_s_ph.c69
-rw-r--r--src/tests/tcg/mips/mips32-dsp/addq_s_w.c44
-rw-r--r--src/tests/tcg/mips/mips32-dsp/addsc.c33
-rw-r--r--src/tests/tcg/mips/mips32-dsp/addu_qb.c35
-rw-r--r--src/tests/tcg/mips/mips32-dsp/addu_s_qb.c35
-rw-r--r--src/tests/tcg/mips/mips32-dsp/addwc.c49
-rw-r--r--src/tests/tcg/mips/mips32-dsp/bitrev.c20
-rw-r--r--src/tests/tcg/mips/mips32-dsp/bposge32.c44
-rw-r--r--src/tests/tcg/mips/mips32-dsp/cmp_eq_ph.c35
-rw-r--r--src/tests/tcg/mips/mips32-dsp/cmp_le_ph.c35
-rw-r--r--src/tests/tcg/mips/mips32-dsp/cmp_lt_ph.c35
-rw-r--r--src/tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c31
-rw-r--r--src/tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c31
-rw-r--r--src/tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c31
-rw-r--r--src/tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c35
-rw-r--r--src/tests/tcg/mips/mips32-dsp/cmpu_le_qb.c35
-rw-r--r--src/tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c35
-rw-r--r--src/tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c31
-rw-r--r--src/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c125
-rw-r--r--src/tests/tcg/mips/mips32-dsp/dpau_h_qbl.c27
-rw-r--r--src/tests/tcg/mips/mips32-dsp/dpau_h_qbr.c27
-rw-r--r--src/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c45
-rw-r--r--src/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c55
-rw-r--r--src/tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c27
-rw-r--r--src/tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c27
-rw-r--r--src/tests/tcg/mips/mips32-dsp/extp.c62
-rw-r--r--src/tests/tcg/mips/mips32-dsp/extpdp.c64
-rw-r--r--src/tests/tcg/mips/mips32-dsp/extpdpv.c47
-rw-r--r--src/tests/tcg/mips/mips32-dsp/extpv.c45
-rw-r--r--src/tests/tcg/mips/mips32-dsp/extr_r_w.c94
-rw-r--r--src/tests/tcg/mips/mips32-dsp/extr_rs_w.c117
-rw-r--r--src/tests/tcg/mips/mips32-dsp/extr_s_h.c86
-rw-r--r--src/tests/tcg/mips/mips32-dsp/extr_w.c94
-rw-r--r--src/tests/tcg/mips/mips32-dsp/extrv_r_w.c79
-rw-r--r--src/tests/tcg/mips/mips32-dsp/extrv_rs_w.c77
-rw-r--r--src/tests/tcg/mips/mips32-dsp/extrv_s_h.c88
-rw-r--r--src/tests/tcg/mips/mips32-dsp/extrv_w.c80
-rw-r--r--src/tests/tcg/mips/mips32-dsp/insv.c36
-rw-r--r--src/tests/tcg/mips/mips32-dsp/lbux.c25
-rw-r--r--src/tests/tcg/mips/mips32-dsp/lhx.c25
-rw-r--r--src/tests/tcg/mips/mips32-dsp/lwx.c25
-rw-r--r--src/tests/tcg/mips/mips32-dsp/madd.c31
-rw-r--r--src/tests/tcg/mips/mips32-dsp/maddu.c31
-rw-r--r--src/tests/tcg/mips/mips32-dsp/main.c6
-rw-r--r--src/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c55
-rw-r--r--src/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c55
-rw-r--r--src/tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c55
-rw-r--r--src/tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c55
-rw-r--r--src/tests/tcg/mips/mips32-dsp/mfhi.c21
-rw-r--r--src/tests/tcg/mips/mips32-dsp/mflo.c21
-rw-r--r--src/tests/tcg/mips/mips32-dsp/modsub.c30
-rw-r--r--src/tests/tcg/mips/mips32-dsp/msub.c30
-rw-r--r--src/tests/tcg/mips/mips32-dsp/msubu.c30
-rw-r--r--src/tests/tcg/mips/mips32-dsp/mthi.c21
-rw-r--r--src/tests/tcg/mips/mips32-dsp/mthlip.c58
-rw-r--r--src/tests/tcg/mips/mips32-dsp/mtlo.c21
-rw-r--r--src/tests/tcg/mips/mips32-dsp/muleq_s_w_phl.c41
-rw-r--r--src/tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c40
-rw-r--r--src/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c25
-rw-r--r--src/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c25
-rw-r--r--src/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c42
-rw-r--r--src/tests/tcg/mips/mips32-dsp/mult.c24
-rw-r--r--src/tests/tcg/mips/mips32-dsp/multu.c24
-rw-r--r--src/tests/tcg/mips/mips32-dsp/packrl_ph.c21
-rw-r--r--src/tests/tcg/mips/mips32-dsp/pick_ph.c49
-rw-r--r--src/tests/tcg/mips/mips32-dsp/pick_qb.c36
-rw-r--r--src/tests/tcg/mips/mips32-dsp/preceq_w_phl.c20
-rw-r--r--src/tests/tcg/mips/mips32-dsp/preceq_w_phr.c20
-rw-r--r--src/tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c20
-rw-r--r--src/tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c20
-rw-r--r--src/tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c20
-rw-r--r--src/tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c20
-rw-r--r--src/tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c20
-rw-r--r--src/tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c20
-rw-r--r--src/tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c20
-rw-r--r--src/tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c20
-rw-r--r--src/tests/tcg/mips/mips32-dsp/precrq_ph_w.c21
-rw-r--r--src/tests/tcg/mips/mips32-dsp/precrq_qb_ph.c21
-rw-r--r--src/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c51
-rw-r--r--src/tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c24
-rw-r--r--src/tests/tcg/mips/mips32-dsp/raddu_w_qb.c20
-rw-r--r--src/tests/tcg/mips/mips32-dsp/rddsp.c46
-rw-r--r--src/tests/tcg/mips/mips32-dsp/repl_ph.c23
-rw-r--r--src/tests/tcg/mips/mips32-dsp/repl_qb.c16
-rw-r--r--src/tests/tcg/mips/mips32-dsp/replv_ph.c19
-rw-r--r--src/tests/tcg/mips/mips32-dsp/replv_qb.c19
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shilo.c45
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shilov.c49
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shll_ph.c55
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shll_qb.c55
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shll_s_ph.c24
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shll_s_w.c52
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shllv_ph.c40
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shllv_qb.c38
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shllv_s_ph.c40
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shllv_s_w.c40
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shra_ph.c30
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shra_r_ph.c30
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shra_r_w.c30
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shrav_ph.c32
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shrav_r_ph.c32
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shrav_r_w.c32
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shrl_qb.c31
-rw-r--r--src/tests/tcg/mips/mips32-dsp/shrlv_qb.c32
-rw-r--r--src/tests/tcg/mips/mips32-dsp/subq_ph.c40
-rw-r--r--src/tests/tcg/mips/mips32-dsp/subq_s_ph.c58
-rw-r--r--src/tests/tcg/mips/mips32-dsp/subq_s_w.c74
-rw-r--r--src/tests/tcg/mips/mips32-dsp/subu_qb.c25
-rw-r--r--src/tests/tcg/mips/mips32-dsp/subu_s_qb.c25
-rw-r--r--src/tests/tcg/mips/mips32-dsp/wrdsp.c46
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/Makefile71
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/absq_s_qb.c35
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/addqh_ph.c30
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/addqh_r_ph.c30
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/addqh_r_w.c34
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/addqh_w.c34
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/addu_ph.c33
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/addu_s_ph.c33
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/adduh_qb.c30
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/adduh_r_qb.c30
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/append.c30
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/balign.c30
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c37
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c37
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c37
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c44
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c79
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c57
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c44
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/dps_w_ph.c44
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c54
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c53
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c27
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/mul_ph.c47
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/mul_s_ph.c62
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/mulq_rs_w.c36
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/mulq_s_ph.c40
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/mulq_s_w.c36
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c29
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c29
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/precr_qb_ph.c21
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c32
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c32
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/prepend.c30
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/shra_qb.c30
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/shra_r_qb.c30
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/shrav_qb.c32
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/shrav_r_qb.c32
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/shrl_ph.c20
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/shrlv_ph.c21
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/subqh_ph.c21
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/subqh_r_ph.c21
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/subqh_r_w.c21
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/subqh_w.c21
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/subu_ph.c40
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/subu_s_ph.c25
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/subuh_qb.c21
-rw-r--r--src/tests/tcg/mips/mips32-dspr2/subuh_r_qb.c32
-rw-r--r--src/tests/tcg/mips/mips64-dsp/Makefile306
-rw-r--r--src/tests/tcg/mips/mips64-dsp/absq_s_ob.c63
-rw-r--r--src/tests/tcg/mips/mips64-dsp/absq_s_ph.c37
-rw-r--r--src/tests/tcg/mips/mips64-dsp/absq_s_pw.c66
-rw-r--r--src/tests/tcg/mips/mips64-dsp/absq_s_qh.c40
-rw-r--r--src/tests/tcg/mips/mips64-dsp/absq_s_w.c48
-rw-r--r--src/tests/tcg/mips/mips64-dsp/addq_ph.c57
-rw-r--r--src/tests/tcg/mips/mips64-dsp/addq_pw.c46
-rw-r--r--src/tests/tcg/mips/mips64-dsp/addq_qh.c28
-rw-r--r--src/tests/tcg/mips/mips64-dsp/addq_s_ph.c84
-rw-r--r--src/tests/tcg/mips/mips64-dsp/addq_s_pw.c45
-rw-r--r--src/tests/tcg/mips/mips64-dsp/addq_s_qh.c26
-rw-r--r--src/tests/tcg/mips/mips64-dsp/addq_s_w.c48
-rw-r--r--src/tests/tcg/mips/mips64-dsp/addsc.c39
-rw-r--r--src/tests/tcg/mips/mips64-dsp/addu_ob.c28
-rw-r--r--src/tests/tcg/mips/mips64-dsp/addu_qb.c40
-rw-r--r--src/tests/tcg/mips/mips64-dsp/addu_s_ob.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/addu_s_qb.c40
-rw-r--r--src/tests/tcg/mips/mips64-dsp/addwc.c59
-rw-r--r--src/tests/tcg/mips/mips64-dsp/bitrev.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/bposge32.c50
-rw-r--r--src/tests/tcg/mips/mips64-dsp/bposge64.c50
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmp_eq_ph.c42
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmp_eq_pw.c46
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmp_eq_qh.c46
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmp_le_ph.c40
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmp_le_pw.c46
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmp_le_qh.c46
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmp_lt_ph.c41
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmp_lt_pw.c46
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmp_lt_qh.c46
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c40
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c38
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c40
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c37
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c40
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c38
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c46
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c42
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmpu_le_ob.c44
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmpu_le_qb.c41
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c44
-rw-r--r--src/tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c42
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dappend.c37
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextp.c54
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextpdp.c59
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextpdpv.c63
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextpv.c58
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextr_l.c44
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextr_r_l.c54
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextr_r_w.c54
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextr_rs_l.c52
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextr_rs_w.c52
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextr_s_h.c73
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextr_w.c44
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextrv_l.c46
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextrv_r_l.c56
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextrv_r_w.c56
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextrv_rs_l.c54
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextrv_rs_w.c54
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextrv_s_h.c32
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dextrv_w.c46
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dinsv.c26
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dmadd.c57
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dmaddu.c56
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dmsub.c59
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dmsubu.c59
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dmthlip.c41
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c32
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c57
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c88
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c82
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpau_h_obl.c59
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpau_h_obr.c59
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpau_h_qbl.c29
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpau_h_qbr.c29
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c51
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c56
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c76
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c59
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpsu_h_obl.c32
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpsu_h_obr.c32
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c29
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c29
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dshilo.c52
-rw-r--r--src/tests/tcg/mips/mips64-dsp/dshilov.c54
-rw-r--r--src/tests/tcg/mips/mips64-dsp/extp.c50
-rw-r--r--src/tests/tcg/mips/mips64-dsp/extpdp.c51
-rw-r--r--src/tests/tcg/mips/mips64-dsp/extpdpv.c52
-rw-r--r--src/tests/tcg/mips/mips64-dsp/extpv.c51
-rw-r--r--src/tests/tcg/mips/mips64-dsp/extr_r_w.c53
-rw-r--r--src/tests/tcg/mips/mips64-dsp/extr_rs_w.c53
-rw-r--r--src/tests/tcg/mips/mips64-dsp/extr_s_h.c71
-rw-r--r--src/tests/tcg/mips/mips64-dsp/extr_w.c53
-rw-r--r--src/tests/tcg/mips/mips64-dsp/extrv_r_w.c59
-rw-r--r--src/tests/tcg/mips/mips64-dsp/extrv_rs_w.c59
-rw-r--r--src/tests/tcg/mips/mips64-dsp/extrv_s_h.c79
-rw-r--r--src/tests/tcg/mips/mips64-dsp/extrv_w.c59
-rw-r--r--src/tests/tcg/mips/mips64-dsp/head.S16
-rw-r--r--src/tests/tcg/mips/mips64-dsp/insv.c26
-rw-r--r--src/tests/tcg/mips/mips64-dsp/io.h22
-rw-r--r--src/tests/tcg/mips/mips64-dsp/lbux.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/ldx.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/lhx.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/lwx.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/madd.c33
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maddu.c33
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c56
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c56
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_s_w_phl.c60
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_s_w_phr.c60
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c62
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c62
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c63
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c63
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c60
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c60
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c62
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c64
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c64
-rw-r--r--src/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c64
-rw-r--r--src/tests/tcg/mips/mips64-dsp/mfhi.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/mflo.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/mips_boot.lds31
-rw-r--r--src/tests/tcg/mips/mips64-dsp/modsub.c37
-rw-r--r--src/tests/tcg/mips/mips64-dsp/msub.c32
-rw-r--r--src/tests/tcg/mips/mips64-dsp/msubu.c32
-rw-r--r--src/tests/tcg/mips/mips64-dsp/mthi.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/mthlip.c61
-rw-r--r--src/tests/tcg/mips/mips64-dsp/mtlo.c22
-rw-r--r--src/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c56
-rw-r--r--src/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c57
-rw-r--r--src/tests/tcg/mips/mips64-dsp/muleq_s_w_phl.c46
-rw-r--r--src/tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c45
-rw-r--r--src/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c30
-rw-r--r--src/tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c31
-rw-r--r--src/tests/tcg/mips/mips64-dsp/mulq_rs_ph.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/mulq_rs_qh.c33
-rw-r--r--src/tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c59
-rw-r--r--src/tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c57
-rw-r--r--src/tests/tcg/mips/mips64-dsp/mult.c26
-rw-r--r--src/tests/tcg/mips/mips64-dsp/multu.c26
-rw-r--r--src/tests/tcg/mips/mips64-dsp/packrl_ph.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/packrl_pw.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/pick_ob.c66
-rw-r--r--src/tests/tcg/mips/mips64-dsp/pick_ph.c60
-rw-r--r--src/tests/tcg/mips/mips64-dsp/pick_pw.c48
-rw-r--r--src/tests/tcg/mips/mips64-dsp/pick_qb.c43
-rw-r--r--src/tests/tcg/mips/mips64-dsp/pick_qh.c48
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceq_l_pwl.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceq_l_pwr.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c21
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c21
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceq_w_phl.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceq_w_phr.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precequ_qh_obl.c22
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precequ_qh_obla.c22
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precequ_qh_obr.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precequ_qh_obra.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceu_qh_obl.c22
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceu_qh_obla.c22
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceu_qh_obr.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/preceu_qh_obra.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precr_ob_qh.c25
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c40
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c40
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precrq_ob_qh.c25
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precrq_ph_w.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precrq_pw_l.c25
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precrq_qb_ph.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precrq_qh_pw.c25
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c41
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c43
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c26
-rw-r--r--src/tests/tcg/mips/mips64-dsp/prependd.c37
-rw-r--r--src/tests/tcg/mips/mips64-dsp/prependw.c37
-rw-r--r--src/tests/tcg/mips/mips64-dsp/printf.c266
-rw-r--r--src/tests/tcg/mips/mips64-dsp/raddu_l_ob.c22
-rw-r--r--src/tests/tcg/mips/mips64-dsp/raddu_w_qb.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/rddsp.c53
-rw-r--r--src/tests/tcg/mips/mips64-dsp/repl_ob.c21
-rw-r--r--src/tests/tcg/mips/mips64-dsp/repl_ph.c30
-rw-r--r--src/tests/tcg/mips/mips64-dsp/repl_pw.c34
-rw-r--r--src/tests/tcg/mips/mips64-dsp/repl_qb.c19
-rw-r--r--src/tests/tcg/mips/mips64-dsp/repl_qh.c34
-rw-r--r--src/tests/tcg/mips/mips64-dsp/replv_ob.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/replv_ph.c22
-rw-r--r--src/tests/tcg/mips/mips64-dsp/replv_pw.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/replv_qb.c22
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shilo.c29
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shilov.c31
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shll_ob.c43
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shll_ph.c43
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shll_pw.c43
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shll_qb.c26
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shll_qh.c42
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shll_s_ph.c43
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shll_s_pw.c43
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shll_s_qh.c43
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shll_s_w.c26
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shllv_ob.c45
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shllv_ph.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shllv_pw.c45
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shllv_qb.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shllv_qh.c45
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shllv_s_ph.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shllv_s_pw.c45
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shllv_s_qh.c45
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shllv_s_w.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shra_ob.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shra_ph.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shra_pw.c36
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shra_qh.c37
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shra_r_ob.c22
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shra_r_ph.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shra_r_pw.c36
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shra_r_qh.c37
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shra_r_w.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shrav_ph.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shrav_pw.c38
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shrav_qh.c39
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shrav_r_ph.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shrav_r_pw.c37
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shrav_r_qh.c39
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shrav_r_w.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shrl_ob.c38
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shrl_qb.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shrl_qh.c22
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shrlv_ob.c39
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shrlv_qb.c24
-rw-r--r--src/tests/tcg/mips/mips64-dsp/shrlv_qh.c23
-rw-r--r--src/tests/tcg/mips/mips64-dsp/subq_ph.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/subq_pw.c44
-rw-r--r--src/tests/tcg/mips/mips64-dsp/subq_qh.c26
-rw-r--r--src/tests/tcg/mips/mips64-dsp/subq_s_ph.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/subq_s_pw.c63
-rw-r--r--src/tests/tcg/mips/mips64-dsp/subq_s_qh.c61
-rw-r--r--src/tests/tcg/mips/mips64-dsp/subq_s_w.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/subu_ob.c26
-rw-r--r--src/tests/tcg/mips/mips64-dsp/subu_qb.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/subu_s_ob.c26
-rw-r--r--src/tests/tcg/mips/mips64-dsp/subu_s_qb.c27
-rw-r--r--src/tests/tcg/mips/mips64-dsp/wrdsp.c48
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/.directory2
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/Makefile116
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/absq_s_qb.c42
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/addqh_ph.c35
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/addqh_r_ph.c35
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/addqh_r_w.c38
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/addqh_w.c39
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/addu_ph.c37
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/addu_qh.c43
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/addu_s_ph.c37
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/addu_s_qh.c43
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/adduh_ob.c35
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/adduh_qb.c35
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/adduh_r_ob.c35
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/adduh_r_qb.c35
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/append.c35
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/balign.c35
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c44
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c41
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c44
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c48
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c44
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c48
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/dbalign.c39
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/dpa_w_ph.c47
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/dpa_w_qh.c56
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c97
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c54
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/dpax_w_ph.c32
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/dps_w_ph.c28
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/dps_w_qh.c55
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c55
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c53
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c28
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/head.S16
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/io.h22
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/mips_boot.lds31
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/mul_ph.c50
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/mul_s_ph.c67
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/mulq_rs_w.c40
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/mulq_s_ph.c26
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/mulq_s_w.c40
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c30
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c30
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/precr_qb_ph.c23
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c37
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c37
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/prepend.c35
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/printf.c266
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/shra_qb.c35
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/shra_r_qb.c35
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/shrav_ob.c22
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/shrav_qb.c37
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/shrav_r_ob.c22
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/shrav_r_qb.c37
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/shrl_ph.c22
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/shrlv_ph.c23
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/subqh_ph.c23
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/subqh_r_ph.c23
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/subqh_r_w.c23
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/subqh_w.c23
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/subu_ph.c26
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/subu_qh.c24
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/subu_s_ph.c25
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/subu_s_qh.c42
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/subuh_ob.c36
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/subuh_qb.c23
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/subuh_r_ob.c23
-rw-r--r--src/tests/tcg/mips/mips64-dspr2/subuh_r_qb.c37
-rw-r--r--src/tests/tcg/openrisc/Makefile71
-rw-r--r--src/tests/tcg/openrisc/test_add.c43
-rw-r--r--src/tests/tcg/openrisc/test_addc.c40
-rw-r--r--src/tests/tcg/openrisc/test_addi.c33
-rw-r--r--src/tests/tcg/openrisc/test_addic.c35
-rw-r--r--src/tests/tcg/openrisc/test_and_or.c65
-rw-r--r--src/tests/tcg/openrisc/test_bf.c47
-rw-r--r--src/tests/tcg/openrisc/test_bnf.c51
-rw-r--r--src/tests/tcg/openrisc/test_div.c54
-rw-r--r--src/tests/tcg/openrisc/test_divu.c34
-rw-r--r--src/tests/tcg/openrisc/test_extx.c78
-rw-r--r--src/tests/tcg/openrisc/test_fx.c57
-rw-r--r--src/tests/tcg/openrisc/test_j.c26
-rw-r--r--src/tests/tcg/openrisc/test_jal.c26
-rw-r--r--src/tests/tcg/openrisc/test_lf_add.c39
-rw-r--r--src/tests/tcg/openrisc/test_lf_div.c37
-rw-r--r--src/tests/tcg/openrisc/test_lf_eqs.c88
-rw-r--r--src/tests/tcg/openrisc/test_lf_ges.c88
-rw-r--r--src/tests/tcg/openrisc/test_lf_gts.c86
-rw-r--r--src/tests/tcg/openrisc/test_lf_les.c88
-rw-r--r--src/tests/tcg/openrisc/test_lf_lts.c92
-rw-r--r--src/tests/tcg/openrisc/test_lf_mul.c22
-rw-r--r--src/tests/tcg/openrisc/test_lf_nes.c89
-rw-r--r--src/tests/tcg/openrisc/test_lf_rem.c32
-rw-r--r--src/tests/tcg/openrisc/test_lf_sub.c35
-rw-r--r--src/tests/tcg/openrisc/test_logic.c105
-rw-r--r--src/tests/tcg/openrisc/test_lx.c84
-rw-r--r--src/tests/tcg/openrisc/test_movhi.c31
-rw-r--r--src/tests/tcg/openrisc/test_mul.c61
-rw-r--r--src/tests/tcg/openrisc/test_muli.c48
-rw-r--r--src/tests/tcg/openrisc/test_mulu.c48
-rw-r--r--src/tests/tcg/openrisc/test_sfeq.c43
-rw-r--r--src/tests/tcg/openrisc/test_sfeqi.c39
-rw-r--r--src/tests/tcg/openrisc/test_sfges.c44
-rw-r--r--src/tests/tcg/openrisc/test_sfgesi.c40
-rw-r--r--src/tests/tcg/openrisc/test_sfgeu.c44
-rw-r--r--src/tests/tcg/openrisc/test_sfgeui.c41
-rw-r--r--src/tests/tcg/openrisc/test_sfgts.c45
-rw-r--r--src/tests/tcg/openrisc/test_sfgtsi.c41
-rw-r--r--src/tests/tcg/openrisc/test_sfgtu.c43
-rw-r--r--src/tests/tcg/openrisc/test_sfgtui.c42
-rw-r--r--src/tests/tcg/openrisc/test_sfles.c26
-rw-r--r--src/tests/tcg/openrisc/test_sflesi.c39
-rw-r--r--src/tests/tcg/openrisc/test_sfleu.c43
-rw-r--r--src/tests/tcg/openrisc/test_sfleui.c39
-rw-r--r--src/tests/tcg/openrisc/test_sflts.c43
-rw-r--r--src/tests/tcg/openrisc/test_sfltsi.c39
-rw-r--r--src/tests/tcg/openrisc/test_sfltu.c43
-rw-r--r--src/tests/tcg/openrisc/test_sfltui.c39
-rw-r--r--src/tests/tcg/openrisc/test_sfne.c43
-rw-r--r--src/tests/tcg/openrisc/test_sfnei.c39
-rw-r--r--src/tests/tcg/openrisc/test_sub.c35
-rw-r--r--src/tests/tcg/pi_10.combin0 -> 54 bytes
-rw-r--r--src/tests/tcg/runcom.c192
-rw-r--r--src/tests/tcg/sha1.c240
-rw-r--r--src/tests/tcg/test-arm-iwmmxt.s49
-rw-r--r--src/tests/tcg/test-i386-code16.S79
-rw-r--r--src/tests/tcg/test-i386-fprem.c353
-rw-r--r--src/tests/tcg/test-i386-muldiv.h76
-rw-r--r--src/tests/tcg/test-i386-shift.h185
-rw-r--r--src/tests/tcg/test-i386-ssse3.c57
-rw-r--r--src/tests/tcg/test-i386-vm86.S103
-rw-r--r--src/tests/tcg/test-i386.c2765
-rw-r--r--src/tests/tcg/test-i386.h152
-rw-r--r--src/tests/tcg/test-mmap.c484
-rw-r--r--src/tests/tcg/test_path.c157
-rw-r--r--src/tests/tcg/testthread.c57
-rw-r--r--src/tests/tcg/xtensa/Makefile92
-rw-r--r--src/tests/tcg/xtensa/crt.S24
-rw-r--r--src/tests/tcg/xtensa/linker.ld.S130
-rw-r--r--src/tests/tcg/xtensa/macros.inc91
-rw-r--r--src/tests/tcg/xtensa/test_b.S221
-rw-r--r--src/tests/tcg/xtensa/test_bi.S103
-rw-r--r--src/tests/tcg/xtensa/test_boolean.S23
-rw-r--r--src/tests/tcg/xtensa/test_break.S257
-rw-r--r--src/tests/tcg/xtensa/test_bz.S57
-rw-r--r--src/tests/tcg/xtensa/test_cache.S97
-rw-r--r--src/tests/tcg/xtensa/test_clamps.S42
-rw-r--r--src/tests/tcg/xtensa/test_extui.S26
-rw-r--r--src/tests/tcg/xtensa/test_fail.S9
-rw-r--r--src/tests/tcg/xtensa/test_interrupt.S194
-rw-r--r--src/tests/tcg/xtensa/test_loop.S163
-rw-r--r--src/tests/tcg/xtensa/test_mac16.S243
-rw-r--r--src/tests/tcg/xtensa/test_max.S81
-rw-r--r--src/tests/tcg/xtensa/test_min.S81
-rw-r--r--src/tests/tcg/xtensa/test_mmu.S743
-rw-r--r--src/tests/tcg/xtensa/test_mul16.S83
-rw-r--r--src/tests/tcg/xtensa/test_mul32.S20
-rw-r--r--src/tests/tcg/xtensa/test_nsa.S59
-rw-r--r--src/tests/tcg/xtensa/test_pipeline.S157
-rw-r--r--src/tests/tcg/xtensa/test_quo.S147
-rw-r--r--src/tests/tcg/xtensa/test_rem.S147
-rw-r--r--src/tests/tcg/xtensa/test_rst0.S148
-rw-r--r--src/tests/tcg/xtensa/test_s32c1i.S39
-rw-r--r--src/tests/tcg/xtensa/test_sar.S111
-rw-r--r--src/tests/tcg/xtensa/test_sext.S69
-rw-r--r--src/tests/tcg/xtensa/test_shift.S206
-rw-r--r--src/tests/tcg/xtensa/test_sr.S90
-rw-r--r--src/tests/tcg/xtensa/test_timer.S178
-rw-r--r--src/tests/tcg/xtensa/test_windowed.S353
-rw-r--r--src/tests/tcg/xtensa/vectors.S39
771 files changed, 43240 insertions, 0 deletions
diff --git a/src/tests/tcg/Makefile b/src/tests/tcg/Makefile
new file mode 100644
index 0000000..89e3342
--- /dev/null
+++ b/src/tests/tcg/Makefile
@@ -0,0 +1,156 @@
+-include ../../config-host.mak
+-include $(SRC_PATH)/rules.mak
+
+$(call set-vpath, $(SRC_PATH)/tests/tcg)
+
+QEMU=../../i386-linux-user/qemu-i386
+QEMU_X86_64=../../x86_64-linux-user/qemu-x86_64
+CC_X86_64=$(CC_I386) -m64
+
+QEMU_INCLUDES += -I../..
+CFLAGS=-Wall -O2 -g -fno-strict-aliasing
+#CFLAGS+=-msse2
+LDFLAGS=
+
+# TODO: automatically detect ARM and MIPS compilers, and run those too
+
+# runcom maps page 0, so it requires root privileges
+# also, pi_10.com runs indefinitely
+
+I386_TESTS=hello-i386 \
+ linux-test \
+ testthread \
+ sha1-i386 \
+ test-i386 \
+ test-i386-fprem \
+ test-mmap \
+ # runcom
+
+# native i386 compilers sometimes are not biarch. assume cross-compilers are
+ifneq ($(ARCH),i386)
+I386_TESTS+=run-test-x86_64
+endif
+
+TESTS = test_path
+ifneq ($(call find-in-path, $(CC_I386)),)
+TESTS += $(I386_TESTS)
+endif
+
+all: $(patsubst %,run-%,$(TESTS))
+test: all
+
+# rules to run tests
+
+.PHONY: $(patsubst %,run-%,$(TESTS))
+
+run-%: %
+ -$(QEMU) ./$*
+
+run-hello-i386: hello-i386
+run-linux-test: linux-test
+run-testthread: testthread
+run-sha1-i386: sha1-i386
+
+run-test-i386: test-i386
+ ./test-i386 > test-i386.ref
+ -$(QEMU) test-i386 > test-i386.out
+ @if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi
+
+run-test-i386-fprem: test-i386-fprem
+ ./test-i386-fprem > test-i386-fprem.ref
+ -$(QEMU) test-i386-fprem > test-i386-fprem.out
+ @if diff -u test-i386-fprem.ref test-i386-fprem.out ; then echo "Auto Test OK"; fi
+
+run-test-x86_64: test-x86_64
+ ./test-x86_64 > test-x86_64.ref
+ -$(QEMU_X86_64) test-x86_64 > test-x86_64.out
+ @if diff -u test-x86_64.ref test-x86_64.out ; then echo "Auto Test OK"; fi
+
+run-test-mmap: test-mmap
+ -$(QEMU) ./test-mmap
+ -$(QEMU) -p 8192 ./test-mmap 8192
+ -$(QEMU) -p 16384 ./test-mmap 16384
+ -$(QEMU) -p 32768 ./test-mmap 32768
+
+run-runcom: runcom
+ -$(QEMU) ./runcom $(SRC_PATH)/tests/pi_10.com
+
+run-test_path: test_path
+ ./test_path
+
+# rules to compile tests
+
+test_path: test_path.o
+
+test_path.o: test_path.c
+
+hello-i386: hello-i386.c
+ $(CC_I386) -nostdlib $(CFLAGS) -static $(LDFLAGS) -o $@ $<
+ strip $@
+
+testthread: testthread.c
+ $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $< -lpthread
+
+# i386/x86_64 emulation test (test various opcodes) */
+test-i386: test-i386.c test-i386-code16.S test-i386-vm86.S \
+ test-i386.h test-i386-shift.h test-i386-muldiv.h
+ $(CC_I386) $(QEMU_INCLUDES) $(CFLAGS) $(LDFLAGS) -o $@ \
+ $(<D)/test-i386.c $(<D)/test-i386-code16.S $(<D)/test-i386-vm86.S -lm
+
+test-i386-fprem: test-i386-fprem.c
+ $(CC_I386) $(QEMU_INCLUDES) $(CFLAGS) $(LDFLAGS) -o $@ $^
+
+test-x86_64: test-i386.c \
+ test-i386.h test-i386-shift.h test-i386-muldiv.h
+ $(CC_X86_64) $(QEMU_INCLUDES) $(CFLAGS) $(LDFLAGS) -o $@ $(<D)/test-i386.c -lm
+
+# generic Linux and CPU test
+linux-test: linux-test.c
+ $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $< -lm
+
+# vm86 test
+runcom: runcom.c
+ $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+test-mmap: test-mmap.c
+ $(CC_I386) -m32 $(CFLAGS) -Wall -O2 $(LDFLAGS) -o $@ $<
+
+# speed test
+sha1-i386: sha1.c
+ $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+sha1: sha1.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+speed: sha1 sha1-i386
+ time ./sha1
+ time $(QEMU) ./sha1-i386
+
+# arm test
+hello-arm: hello-arm.o
+ arm-linux-ld -o $@ $<
+
+hello-arm.o: hello-arm.c
+ arm-linux-gcc -Wall -g -O2 -c -o $@ $<
+
+test-arm-iwmmxt: test-arm-iwmmxt.s
+ cpp < $< | arm-linux-gnu-gcc -Wall -static -march=iwmmxt -mabi=aapcs -x assembler - -o $@
+
+# MIPS test
+hello-mips: hello-mips.c
+ mips-linux-gnu-gcc -nostdlib -static -mno-abicalls -fno-PIC -mabi=32 -Wall -Wextra -g -O2 -o $@ $<
+
+hello-mipsel: hello-mips.c
+ mipsel-linux-gnu-gcc -nostdlib -static -mno-abicalls -fno-PIC -mabi=32 -Wall -Wextra -g -O2 -o $@ $<
+
+# testsuite for the CRIS port.
+test-cris:
+ $(MAKE) -C cris check
+
+# testsuite for the LM32 port.
+test-lm32:
+ $(MAKE) -C lm32 check
+
+clean:
+ rm -f *~ *.o test-i386.out test-i386.ref \
+ test-x86_64.log test-x86_64.ref qruncom $(TESTS)
diff --git a/src/tests/tcg/alpha/Makefile b/src/tests/tcg/alpha/Makefile
new file mode 100644
index 0000000..2b1f03d
--- /dev/null
+++ b/src/tests/tcg/alpha/Makefile
@@ -0,0 +1,35 @@
+CROSS=alpha-linux-gnu-
+CC=$(CROSS)gcc
+AS=$(CROSS)as
+
+SIM=../../alpha-linux-user/qemu-alpha
+
+CFLAGS=-O
+LINK=$(CC) -o $@ crt.o $< -nostdlib
+
+TESTS=test-cond test-cmov
+
+all: hello-alpha $(TESTS)
+
+hello-alpha: hello-alpha.o crt.o
+ $(LINK)
+
+test-cond: test-cond.o crt.o
+ $(LINK)
+
+test-cmov.o: test-cond.c
+ $(CC) -c $(CFLAGS) -DTEST_CMOV -o $@ $<
+
+test-cmov: test-cmov.o crt.o
+ $(LINK)
+
+test-ovf: test-ovf.o crt.o
+ $(LINK)
+
+check: $(TESTS)
+ for f in $(TESTS); do $(SIM) $$f || exit 1; done
+
+clean:
+ $(RM) *.o *~ hello-alpha $(TESTS)
+
+.PHONY: clean all check
diff --git a/src/tests/tcg/alpha/crt.s b/src/tests/tcg/alpha/crt.s
new file mode 100644
index 0000000..31af882
--- /dev/null
+++ b/src/tests/tcg/alpha/crt.s
@@ -0,0 +1,26 @@
+ .text
+
+ .globl _start
+ .ent _start,0
+_start:
+ .frame $15,0,$15
+ br $29,1f
+1: ldgp $29, 0($29)
+ .prologue 0
+ ldq $27,main($29) !literal!1
+ jsr $26,($27)
+ or $0,$0,$16
+ .end _start
+
+ .globl _exit
+_exit:
+ lda $0,1
+ callsys
+
+ call_pal 0
+
+ .globl write
+write:
+ lda $0,4
+ callsys
+ ret
diff --git a/src/tests/tcg/alpha/hello-alpha.c b/src/tests/tcg/alpha/hello-alpha.c
new file mode 100644
index 0000000..79892e6
--- /dev/null
+++ b/src/tests/tcg/alpha/hello-alpha.c
@@ -0,0 +1,5 @@
+int main (void)
+{
+ write (1, "hello\n", 6);
+ return 0;
+}
diff --git a/src/tests/tcg/alpha/test-cond.c b/src/tests/tcg/alpha/test-cond.c
new file mode 100644
index 0000000..74adffa
--- /dev/null
+++ b/src/tests/tcg/alpha/test-cond.c
@@ -0,0 +1,87 @@
+
+#ifdef TEST_CMOV
+
+#define TEST_COND(N) \
+int test_##N (long a) \
+{ \
+ int res = 1; \
+ \
+ asm ("cmov"#N" %1,$31,%0" \
+ : "+r" (res) : "r" (a)); \
+ return !res; \
+}
+
+#else
+
+#define TEST_COND(N) \
+int test_##N (long a) \
+{ \
+ int res = 1; \
+ \
+ asm ("b"#N" %1,1f\n\t" \
+ "addq $31,$31,%0\n\t" \
+ "1: unop\n" \
+ : "+r" (res) : "r" (a)); \
+ return res; \
+}
+
+#endif
+
+TEST_COND(eq)
+TEST_COND(ne)
+TEST_COND(ge)
+TEST_COND(gt)
+TEST_COND(lbc)
+TEST_COND(lbs)
+TEST_COND(le)
+TEST_COND(lt)
+
+static struct {
+ int (*func)(long);
+ long v;
+ int r;
+} vectors[] =
+ {
+ {test_eq, 0, 1},
+ {test_eq, 1, 0},
+
+ {test_ne, 0, 0},
+ {test_ne, 1, 1},
+
+ {test_ge, 0, 1},
+ {test_ge, 1, 1},
+ {test_ge, -1, 0},
+
+ {test_gt, 0, 0},
+ {test_gt, 1, 1},
+ {test_gt, -1, 0},
+
+ {test_lbc, 0, 1},
+ {test_lbc, 1, 0},
+ {test_lbc, -1, 0},
+
+ {test_lbs, 0, 0},
+ {test_lbs, 1, 1},
+ {test_lbs, -1, 1},
+
+ {test_le, 0, 1},
+ {test_le, 1, 0},
+ {test_le, -1, 1},
+
+ {test_lt, 0, 0},
+ {test_lt, 1, 0},
+ {test_lt, -1, 1},
+ };
+
+int main (void)
+{
+ int i;
+
+ for (i = 0; i < sizeof (vectors)/sizeof(vectors[0]); i++)
+ if ((*vectors[i].func)(vectors[i].v) != vectors[i].r) {
+ write(1, "Failed\n", 7);
+ return 1;
+ }
+ write(1, "OK\n", 3);
+ return 0;
+}
diff --git a/src/tests/tcg/alpha/test-ovf.c b/src/tests/tcg/alpha/test-ovf.c
new file mode 100644
index 0000000..01c80e7
--- /dev/null
+++ b/src/tests/tcg/alpha/test-ovf.c
@@ -0,0 +1,29 @@
+static long test_subqv (long a, long b)
+{
+ long res;
+
+ asm ("subq/v %1,%2,%0"
+ : "=r" (res) : "r" (a), "r" (b));
+ return res;
+}
+static struct {
+ long (*func)(long, long);
+ long a;
+ long b;
+ long r;
+} vectors[] =
+ {
+ {test_subqv, 0, 0x7d54000, 0xfffffffff82ac000L}
+ };
+
+int main (void)
+{
+ int i;
+
+ for (i = 0; i < sizeof (vectors)/sizeof(vectors[0]); i++)
+ if ((*vectors[i].func)(vectors[i].a, vectors[i].b) != vectors[i].r) {
+ write(1, "Failed\n", 7);
+ }
+ write(1, "OK\n", 3);
+ return 0;
+}
diff --git a/src/tests/tcg/cris/.gdbinit b/src/tests/tcg/cris/.gdbinit
new file mode 100644
index 0000000..5e8c1d3
--- /dev/null
+++ b/src/tests/tcg/cris/.gdbinit
@@ -0,0 +1,11 @@
+b main
+b _fail
+b exit
+display /i $pc
+display /x $srp
+display /x $r0
+display /x $r1
+display /x $r2
+display /x $r3
+display /x $r4
+display /t $ccs
diff --git a/src/tests/tcg/cris/Makefile b/src/tests/tcg/cris/Makefile
new file mode 100644
index 0000000..d34bfd8
--- /dev/null
+++ b/src/tests/tcg/cris/Makefile
@@ -0,0 +1,155 @@
+-include ../../../config-host.mak
+
+CROSS=crisv32-axis-linux-gnu-
+SIM=../../../cris-linux-user/qemu-cris -L ./
+SIMG=cris-axis-linux-gnu-run --sysroot=./
+
+CC = $(CROSS)gcc
+#AS = $(CROSS)as
+AS = $(CC) -x assembler-with-cpp
+SIZE = $(CROSS)size
+LD = $(CC)
+OBJCOPY = $(CROSS)objcopy
+
+# we rely on GCC inline:ing the stuff we tell it to in many places here.
+CFLAGS = -Winline -Wall -g -O2 -static
+NOSTDFLAGS = -nostartfiles -nostdlib
+ASFLAGS += -g -Wa,-I,$(SRC_PATH)/tests/tcg/cris/
+LDLIBS =
+NOSTDLIBS = -lgcc
+
+CRT = crt.o
+SYS = sys.o
+TESTCASES += check_abs.tst
+TESTCASES += check_addc.tst
+TESTCASES += check_addcm.tst
+TESTCASES += check_addo.tst
+TESTCASES += check_addoq.tst
+TESTCASES += check_addi.tst
+TESTCASES += check_addiv32.tst
+TESTCASES += check_addm.tst
+TESTCASES += check_addr.tst
+TESTCASES += check_addq.tst
+TESTCASES += check_addxc.tst
+TESTCASES += check_addxm.tst
+TESTCASES += check_addxr.tst
+TESTCASES += check_andc.tst
+TESTCASES += check_andm.tst
+TESTCASES += check_andr.tst
+TESTCASES += check_andq.tst
+TESTCASES += check_asr.tst
+TESTCASES += check_ba.tst
+TESTCASES += check_bas.tst
+TESTCASES += check_bcc.tst
+TESTCASES += check_bound.tst
+TESTCASES += check_boundc.tst
+TESTCASES += check_boundr.tst
+TESTCASES += check_btst.tst
+TESTCASES += check_clearfv32.tst
+TESTCASES += check_cmpc.tst
+TESTCASES += check_cmpr.tst
+TESTCASES += check_cmpq.tst
+TESTCASES += check_cmpm.tst
+TESTCASES += check_cmpxc.tst
+TESTCASES += check_cmpxm.tst
+TESTCASES += check_cmp-2.tst
+TESTCASES += check_clrjmp1.tst
+TESTCASES += check_dstep.tst
+TESTCASES += check_ftag.tst
+TESTCASES += check_int64.tst
+# check_jsr is broken.
+#TESTCASES += check_jsr.tst
+TESTCASES += check_mcp.tst
+TESTCASES += check_movei.tst
+TESTCASES += check_mover.tst
+TESTCASES += check_moverm.tst
+TESTCASES += check_moveq.tst
+TESTCASES += check_movemr.tst
+TESTCASES += check_movemrv32.tst
+TESTCASES += check_movecr.tst
+TESTCASES += check_movmp.tst
+TESTCASES += check_movpr.tst
+TESTCASES += check_movprv32.tst
+TESTCASES += check_movdelsr1.tst
+TESTCASES += check_movpmv32.tst
+TESTCASES += check_movsr.tst
+TESTCASES += check_movsm.tst
+TESTCASES += check_movscr.tst
+TESTCASES += check_movur.tst
+TESTCASES += check_movum.tst
+TESTCASES += check_movucr.tst
+TESTCASES += check_mulx.tst
+TESTCASES += check_mulv32.tst
+TESTCASES += check_neg.tst
+TESTCASES += check_not.tst
+TESTCASES += check_lz.tst
+TESTCASES += check_lapc.tst
+TESTCASES += check_lsl.tst
+TESTCASES += check_lsr.tst
+TESTCASES += check_orc.tst
+TESTCASES += check_orm.tst
+TESTCASES += check_orr.tst
+TESTCASES += check_orq.tst
+TESTCASES += check_ret.tst
+TESTCASES += check_swap.tst
+TESTCASES += check_scc.tst
+TESTCASES += check_subc.tst
+TESTCASES += check_subq.tst
+TESTCASES += check_subr.tst
+TESTCASES += check_subm.tst
+TESTCASES += check_glibc_kernelversion.tst
+TESTCASES += check_xarith.tst
+
+TESTCASES += check_hello.ctst
+TESTCASES += check_stat1.ctst
+TESTCASES += check_stat2.ctst
+TESTCASES += check_stat3.ctst
+TESTCASES += check_stat4.ctst
+TESTCASES += check_openpf1.ctst
+TESTCASES += check_openpf2.ctst
+TESTCASES += check_openpf3.ctst
+TESTCASES += check_openpf4.ctst
+TESTCASES += check_openpf5.ctst
+TESTCASES += check_mapbrk.ctst
+TESTCASES += check_mmap1.ctst
+TESTCASES += check_mmap2.ctst
+TESTCASES += check_mmap3.ctst
+TESTCASES += check_sigalrm.ctst
+TESTCASES += check_time1.ctst
+TESTCASES += check_time2.ctst
+TESTCASES += check_settls1.ctst
+
+TESTCASES += check_gcctorture_pr28634-1.ctst
+#TESTCASES += check_gcctorture_pr28634.ctst
+
+all: build
+
+%.o: $(SRC_PATH)/tests/tcg/cris/%.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+%.o: $(SRC_PATH)/tests/tcg/cris/%.s
+ $(AS) $(ASFLAGS) -c $< -o $@
+
+%.tst: %.o
+ $(CC) $(CFLAGS) $(NOSTDFLAGS) $(LDLIBS) $(NOSTDLIBS) $(CRT) $< $(SYS) -o $@
+
+%.ctst: %.o
+ $(CC) $(CFLAGS) $(LDLIBS) $< -o $@
+
+build: $(CRT) $(SYS) $(TESTCASES)
+
+check: $(CRT) $(SYS) $(TESTCASES)
+ @echo -e "\nQEMU simulator."
+ for case in $(TESTCASES); do \
+ echo -n "$$case "; \
+ $(SIM) ./$$case; \
+ done
+check-g: $(CRT) $(SYS) $(TESTCASES)
+ @echo -e "\nGDB simulator."
+ @for case in $(TESTCASES); do \
+ echo -n "$$case "; \
+ $(SIMG) $$case; \
+ done
+
+clean:
+ $(RM) -fr $(TESTCASES) $(CRT) $(SYS)
diff --git a/src/tests/tcg/cris/README b/src/tests/tcg/cris/README
new file mode 100644
index 0000000..2e65a76
--- /dev/null
+++ b/src/tests/tcg/cris/README
@@ -0,0 +1 @@
+Test-suite for the cris port. Heavily based on the test-suite for the CRIS port of sim by Hans-Peter Nilsson.
diff --git a/src/tests/tcg/cris/check_abs.c b/src/tests/tcg/cris/check_abs.c
new file mode 100644
index 0000000..9770a8d
--- /dev/null
+++ b/src/tests/tcg/cris/check_abs.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+static inline int cris_abs(int n)
+{
+ int r;
+ asm ("abs\t%1, %0\n" : "=r" (r) : "r" (n));
+ return r;
+}
+
+static inline void
+verify_abs(int val, int res,
+ const int n, const int z, const int v, const int c)
+{
+ int r;
+
+ cris_tst_cc_init();
+ r = cris_abs(val);
+ cris_tst_cc(n, z, v, c);
+ if (r != res)
+ err();
+}
+
+int main(void)
+{
+ verify_abs(-1, 1, 0, 0, 0, 0);
+ verify_abs(0x80000000, 0x80000000, 1, 0, 0, 0);
+ verify_abs(0x7fffffff, 0x7fffffff, 0, 0, 0, 0);
+ verify_abs(42, 42, 0, 0, 0, 0);
+ verify_abs(1, 1, 0, 0, 0, 0);
+ verify_abs(0xffff, 0xffff, 0, 0, 0, 0);
+ verify_abs(0xffff, 0xffff, 0, 0, 0, 0);
+ verify_abs(-31, 0x1f, 0, 0, 0, 0);
+ verify_abs(0, 0, 0, 1, 0, 0);
+ pass();
+ return 0;
+}
diff --git a/src/tests/tcg/cris/check_addc.c b/src/tests/tcg/cris/check_addc.c
new file mode 100644
index 0000000..facd1be
--- /dev/null
+++ b/src/tests/tcg/cris/check_addc.c
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+static inline int cris_addc(int a, const int b)
+{
+ asm ("addc\t%1, %0\n" : "+r" (a) : "r" (b));
+ return a;
+}
+
+#define verify_addc(a, b, res, n, z, v, c) \
+{ \
+ int r; \
+ r = cris_addc((a), (b)); \
+ cris_tst_cc((n), (z), (v), (c)); \
+ if (r != (res)) \
+ err(); \
+}
+
+int main(void)
+{
+ cris_tst_cc_init();
+ asm volatile ("clearf cz");
+ verify_addc(0, 0, 0, 0, 0, 0, 0);
+
+ cris_tst_cc_init();
+ asm volatile ("setf z");
+ verify_addc(0, 0, 0, 0, 1, 0, 0);
+
+ cris_tst_cc_init();
+ asm volatile ("setf cz");
+ verify_addc(0, 0, 1, 0, 0, 0, 0);
+ cris_tst_cc_init();
+ asm volatile ("clearf c");
+ verify_addc(-1, 2, 1, 0, 0, 0, 1);
+
+ cris_tst_cc_init();
+ asm volatile ("clearf nzv");
+ asm volatile ("setf c");
+ verify_addc(-1, 2, 2, 0, 0, 0, 1);
+
+ cris_tst_cc_init();
+ asm volatile ("setf c");
+ verify_addc(0xffff, 0xffff, 0x1ffff, 0, 0, 0, 0);
+
+ cris_tst_cc_init();
+ asm volatile ("clearf nzvc");
+ verify_addc(-1, -1, 0xfffffffe, 1, 0, 0, 1);
+
+ cris_tst_cc_init();
+ asm volatile ("setf c");
+ verify_addc(0x78134452, 0x5432f789, 0xcc463bdc, 1, 0, 1, 0);
+
+ pass();
+ return 0;
+}
diff --git a/src/tests/tcg/cris/check_addcm.c b/src/tests/tcg/cris/check_addcm.c
new file mode 100644
index 0000000..7928bc9
--- /dev/null
+++ b/src/tests/tcg/cris/check_addcm.c
@@ -0,0 +1,85 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+/* need to avoid acr as source here. */
+static inline int cris_addc_m(int a, const int *b)
+{
+ asm volatile ("addc [%1], %0\n" : "+r" (a) : "r" (b));
+ return a;
+}
+
+/* 'b' is a crisv32 constrain to avoid postinc with $acr. */
+static inline int cris_addc_pi_m(int a, int **b)
+{
+ asm volatile ("addc [%1+], %0\n" : "+r" (a), "+b" (*b));
+ return a;
+}
+
+#define verify_addc_m(a, b, res, n, z, v, c) \
+{ \
+ int r; \
+ r = cris_addc_m((a), (b)); \
+ cris_tst_cc((n), (z), (v), (c)); \
+ if (r != (res)) \
+ err(); \
+}
+
+#define verify_addc_pi_m(a, b, res, n, z, v, c) \
+{ \
+ int r; \
+ r = cris_addc_pi_m((a), (b)); \
+ cris_tst_cc((n), (z), (v), (c)); \
+ if (r != (res)) \
+ err(); \
+}
+
+int x[] = { 0, 0, 2, -1, 0xffff, -1, 0x5432f789};
+
+int main(void)
+{
+ int *p = (void *)&x[0];
+#if 1
+ cris_tst_cc_init();
+ asm volatile ("clearf cz");
+ verify_addc_m(0, p, 0, 0, 0, 0, 0);
+
+ cris_tst_cc_init();
+ asm volatile ("setf z");
+ verify_addc_m(0, p, 0, 0, 1, 0, 0);
+
+ cris_tst_cc_init();
+ asm volatile ("setf c");
+ verify_addc_m(0, p, 1, 0, 0, 0, 0);
+
+ cris_tst_cc_init();
+ asm volatile ("clearf c");
+ verify_addc_pi_m(0, &p, 0, 0, 1, 0, 0);
+
+ p = &x[1];
+ cris_tst_cc_init();
+ asm volatile ("setf c");
+ verify_addc_pi_m(0, &p, 1, 0, 0, 0, 0);
+
+ if (p != &x[2])
+ err();
+
+ cris_tst_cc_init();
+ asm volatile ("clearf c");
+ verify_addc_pi_m(-1, &p, 1, 0, 0, 0, 1);
+
+ if (p != &x[3])
+ err();
+#endif
+ p = &x[3];
+ /* TODO: investigate why this one fails. */
+ cris_tst_cc_init();
+ asm volatile ("setf c");
+ verify_addc_m(2, p, 2, 0, 0, 0, 1);
+ p += 4;
+
+ pass();
+ return 0;
+}
diff --git a/src/tests/tcg/cris/check_addi.s b/src/tests/tcg/cris/check_addi.s
new file mode 100644
index 0000000..a00dec0
--- /dev/null
+++ b/src/tests/tcg/cris/check_addi.s
@@ -0,0 +1,57 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 0\n1\n2\n4\nbe02460f\n69d035a6\nc16c14d4\n
+
+ .include "testutils.inc"
+ start
+ moveq 0,r3
+ moveq 0,r4
+ clearf zcvn
+ addi r4.b,r3
+ test_cc 0 0 0 0
+ checkr3 0
+
+ moveq 0,r3
+ moveq 1,r4
+ setf zcvn
+ addi r4.b,r3
+ test_cc 1 1 1 1
+ checkr3 1
+
+ moveq 0,r3
+ moveq 1,r4
+ setf cv
+ clearf zn
+ addi r4.w,r3
+ test_cc 0 0 1 1
+ checkr3 2
+
+ moveq 0,r3
+ moveq 1,r4
+ clearf cv
+ setf zn
+ addi r4.d,r3
+ test_cc 1 1 0 0
+ checkr3 4
+
+ move.d 0x12345678,r3
+ move.d 0xabcdef97,r4
+ clearf cn
+ setf zv
+ addi r4.b,r3
+ test_cc 0 1 1 0
+ checkr3 be02460f
+
+ move.d 0x12345678,r3
+ move.d 0xabcdef97,r4
+ setf cn
+ clearf zv
+ addi r4.w,r3
+ test_cc 1 0 0 1
+ checkr3 69d035a6
+
+ move.d 0x12345678,r3
+ move.d 0xabcdef97,r4
+ addi r4.d,r3
+ checkr3 c16c14d4
+
+ quit
diff --git a/src/tests/tcg/cris/check_addiv32.s b/src/tests/tcg/cris/check_addiv32.s
new file mode 100644
index 0000000..20ba25d
--- /dev/null
+++ b/src/tests/tcg/cris/check_addiv32.s
@@ -0,0 +1,62 @@
+# mach: crisv32
+# output: 4455aa77\n4455aa77\nee19ccff\nff22\n4455aa77\nff224455\n55aa77ff\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 0x55aa77ff
+ .dword 0xccff2244
+ .dword 0x88ccee19
+
+ start
+ setf cv
+ moveq -1,r0
+ move.d x-32768,r5
+ move.d 32769,r6
+ addi r6.b,r5,acr
+ test_cc 0 0 1 1
+ move.d [acr],r3
+ checkr3 4455aa77
+
+ addu.w 32771,r5
+ setf znvc
+ moveq -1,r8
+ addi r8.w,r5,acr
+ test_cc 1 1 1 1
+ move.d [acr],r3
+ checkr3 4455aa77
+
+ moveq 5,r10
+ clearf znvc
+ addi r10.b,acr,acr
+ test_cc 0 0 0 0
+ move.d [acr],r3
+ checkr3 ee19ccff
+
+ subq 1,r5
+ move.d r5,r8
+ subq 1,r8
+ moveq 1,r9
+ addi r9.d,r8,acr
+ test_cc 0 0 0 0
+ movu.w [acr],r3
+ checkr3 ff22
+
+ moveq -2,r11
+ addi r11.w,acr,acr
+ move.d [acr],r3
+ checkr3 4455aa77
+
+ moveq 5,r9
+ addi r9.d,acr,acr
+ subq 18,acr
+ move.d [acr],r3
+ checkr3 ff224455
+
+ move.d -76789888/4,r12
+ addi r12.d,r5,acr
+ add.d 76789886,acr
+ move.d [acr],r3
+ checkr3 55aa77ff
+
+ quit
diff --git a/src/tests/tcg/cris/check_addm.s b/src/tests/tcg/cris/check_addm.s
new file mode 100644
index 0000000..efece9f
--- /dev/null
+++ b/src/tests/tcg/cris/check_addm.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n781344d0\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 2,-1,0xffff,-1,0x5432f789
+ .word 2,-1,0xffff,0xf789
+ .byte 2,0xff,0x89
+ .byte 0x7e
+
+ start
+ moveq -1,r3
+ move.d x,r5
+ add.d [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ add.d [r5],r3
+ test_cc 0 0 0 1
+ addq 4,r5
+ checkr3 1
+
+ move.d 0xffff,r3
+ add.d [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ moveq -1,r3
+ add.d [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ add.d [r5+],r3
+ test_cc 1 0 1 0
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ add.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 ffff0001
+
+ moveq 2,r3
+ add.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r3
+ add.w [r5],r3
+ test_cc 1 0 0 1
+ checkr3 fffe
+
+ move.d 0xfedaffff,r3
+ add.w [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 fedafffe
+
+ move.d 0x78134452,r3
+ add.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ moveq -1,r3
+ add.b [r5],r3
+ test_cc 0 0 0 1
+ addq 1,r5
+ checkr3 ffffff01
+
+ moveq 2,r3
+ add.b [r5],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xff,r3
+ add.b [r5],r3
+ test_cc 1 0 0 1
+ checkr3 fe
+
+ move.d 0xfeda49ff,r3
+ add.b [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 feda49fe
+
+ move.d 0x78134452,r3
+ add.b [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 781344db
+
+ move.d 0x78134452,r3
+ add.b [r5],r3
+ test_cc 1 0 1 0
+ checkr3 781344d0
+
+ quit
diff --git a/src/tests/tcg/cris/check_addo.c b/src/tests/tcg/cris/check_addo.c
new file mode 100644
index 0000000..3d8e789
--- /dev/null
+++ b/src/tests/tcg/cris/check_addo.c
@@ -0,0 +1,125 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+/* this would be better to do in asm, it's an orgy in GCC inline asm now. */
+
+#define cris_addo_b(o, v) \
+ asm volatile ("addo.b\t[%0], %1, $acr\n" : : "r" (o), "r" (v) : "acr");
+#define cris_addo_w(o, v) \
+ asm volatile ("addo.w\t[%0], %1, $acr\n" : : "r" (o), "r" (v) : "acr");
+#define cris_addo_d(o, v) \
+ asm volatile ("addo.d\t[%0], %1, $acr\n" : : "r" (o), "r" (v) : "acr");
+#define cris_addo_pi_b(o, v) \
+ asm volatile ("addo.b\t[%0+], %1, $acr\n" \
+ : "+b" (o): "r" (v) : "acr");
+#define cris_addo_pi_w(o, v) \
+ asm volatile ("addo.w\t[%0+], %1, $acr\n" \
+ : "+b" (o): "r" (v) : "acr");
+#define cris_addo_pi_d(o, v) \
+ asm volatile ("addo.d\t[%0+], %1, $acr\n" \
+ : "+b" (o): "r" (v) : "acr");
+
+struct {
+ uint32_t v1;
+ uint16_t v2;
+ uint32_t v3;
+ uint8_t v4;
+ uint8_t v5;
+ uint16_t v6;
+ uint32_t v7;
+} y = {
+ 32769,
+ -1,
+ 5,
+ 3, -4,
+ 2,
+ -76789887
+};
+
+static int x[3] = {0x55aa77ff, 0xccff2244, 0x88ccee19};
+
+int main(void)
+{
+ int *r;
+ unsigned char *t, *p;
+
+ /* Note, this test-case will trig an unaligned access, partly
+ to x[0] and to [x1]. */
+ t = (unsigned char *)x;
+ t -= 32768;
+ p = (unsigned char *) &y.v1;
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_pi_d(p, t);
+ cris_tst_cc(1, 1, 1, 1);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ if (*r != 0x4455aa77)
+ err();
+
+
+ t += 32770;
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_pi_w(p, t);
+ cris_tst_cc(1, 1, 1, 1);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ if (*r != 0x4455aa77)
+ err();
+
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_d(p, r);
+ cris_tst_cc(1, 1, 1, 1);
+ p += 4;
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ if (*r != 0xee19ccff)
+ err();
+
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_pi_b(p, t);
+ cris_tst_cc(0, 0, 0, 0);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ if (*(uint16_t*)r != 0xff22)
+ err();
+
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_b(p, r);
+ cris_tst_cc(1, 1, 1, 1);
+ p += 1;
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ if (*r != 0x4455aa77)
+ err();
+
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_w(p, r);
+ cris_tst_cc(1, 1, 1, 1);
+ p += 2;
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ if (*r != 0xff224455)
+ err();
+
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_pi_d(p, t);
+ cris_tst_cc(0, 0, 0, 0);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ r = (void*)(((char *)r) + 76789885);
+ if (*r != 0x55aa77ff)
+ err();
+
+ pass();
+ return 0;
+}
diff --git a/src/tests/tcg/cris/check_addoq.c b/src/tests/tcg/cris/check_addoq.c
new file mode 100644
index 0000000..ed509e2
--- /dev/null
+++ b/src/tests/tcg/cris/check_addoq.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+/* this would be better to do in asm, it's an orgy in GCC inline asm now. */
+
+/* ACR will be clobbered. */
+#define cris_addoq(o, v) \
+ asm volatile ("addoq\t%1, %0, $acr\n" : : "r" (v), "i" (o) : "acr");
+
+
+int main(void)
+{
+ int x[3] = {0x55aa77ff, 0xccff2244, 0x88ccee19};
+ int *p, *t = x + 1;
+
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addoq(0, t);
+ cris_tst_cc(1, 1, 1, 1);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (p));
+ if (*p != 0xccff2244)
+ err();
+
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addoq(4, t);
+ cris_tst_cc(0, 0, 0, 0);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (p));
+ if (*p != 0x88ccee19)
+ err();
+
+ cris_tst_cc_init();
+ asm volatile ("clearf\tzvnc\n");
+ cris_addoq(-8, t + 1);
+ cris_tst_cc(0, 0, 0, 0);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (p));
+ if (*p != 0x55aa77ff)
+ err();
+ pass();
+ return 0;
+}
diff --git a/src/tests/tcg/cris/check_addq.s b/src/tests/tcg/cris/check_addq.s
new file mode 100644
index 0000000..e6f874f
--- /dev/null
+++ b/src/tests/tcg/cris/check_addq.s
@@ -0,0 +1,47 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n0\n1\n100\n10000\n47\n67\na6\n80000001\n
+
+ .include "testutils.inc"
+ start
+ moveq -2,r3
+ addq 1,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ addq 1,r3
+ test_cc 0 1 0 1
+ checkr3 0
+
+ addq 1,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xff,r3
+ addq 1,r3
+ test_cc 0 0 0 0
+ checkr3 100
+
+ move.d 0xffff,r3
+ addq 1,r3
+ test_cc 0 0 0 0
+ checkr3 10000
+
+ move.d 0x42,r3
+ addq 5,r3
+ test_cc 0 0 0 0
+ checkr3 47
+
+ addq 32,r3
+ test_cc 0 0 0 0
+ checkr3 67
+
+ addq 63,r3
+ test_cc 0 0 0 0
+ checkr3 a6
+
+ move.d 0x7ffffffe,r3
+ addq 3,r3
+ test_cc 1 0 1 0
+ checkr3 80000001
+
+ quit
diff --git a/src/tests/tcg/cris/check_addr.s b/src/tests/tcg/cris/check_addr.s
new file mode 100644
index 0000000..7f55cdc
--- /dev/null
+++ b/src/tests/tcg/cris/check_addr.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ add.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ moveq -1,r4
+ add.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ add.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ moveq -1,r4
+ move.d r4,r3
+ add.d r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.d r4,r3
+ test_cc 1 0 1 0
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ moveq 2,r4
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffff0001
+
+ moveq 2,r3
+ moveq -1,r4
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ add.w r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffe
+
+ move.d 0xfedaffff,r4
+ move.d r4,r3
+ add.w r4,r3
+ test_cc 1 0 0 1
+ checkr3 fedafffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ moveq -1,r3
+ moveq 2,r4
+ add.b r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffffff01
+
+ moveq 2,r3
+ moveq -1,r4
+ add.b r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xff,r4
+ move.d r4,r3
+ add.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 fe
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ add.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 feda49fe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/src/tests/tcg/cris/check_addxc.s b/src/tests/tcg/cris/check_addxc.s
new file mode 100644
index 0000000..09c8355
--- /dev/null
+++ b/src/tests/tcg/cris/check_addxc.s
@@ -0,0 +1,91 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n101\n10001\n100fe\n1fffe\nfffe\nfffe\nfffffffe\nfe\nfffffffe\n781344db\n781343db\n78143bdb\n78133bdb\n800000ed\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq 2,r3
+ adds.b 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ adds.w 0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ addu.b 0xff,r3
+ checkr3 101
+
+ moveq 2,r3
+ move.d 0xffffffff,r4
+ addu.w -1,r3
+ test_cc 0 0 0 0
+ checkr3 10001
+
+ move.d 0xffff,r3
+ addu.b -1,r3
+ test_cc 0 0 0 0
+ checkr3 100fe
+
+ move.d 0xffff,r3
+ addu.w -1,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ move.d 0xffff,r3
+ adds.b 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 fffe
+
+ move.d 0xffff,r3
+ adds.w 0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 fffe
+
+ moveq -1,r3
+ adds.b 0xff,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ moveq -1,r3
+ adds.w 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 fe
+
+ moveq -1,r3
+ adds.w 0xffff,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ addu.b 0x89,r3
+ test_cc 0 0 0 0
+ checkr3 781344db
+
+ move.d 0x78134452,r3
+ adds.b 0x89,r3
+ test_cc 0 0 0 1
+ checkr3 781343db
+
+ move.d 0x78134452,r3
+ addu.w 0xf789,r3
+ test_cc 0 0 0 0
+ checkr3 78143bdb
+
+ move.d 0x78134452,r3
+ adds.w 0xf789,r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ move.d 0x7fffffee,r3
+ addu.b 0xff,r3
+ test_cc 1 0 1 0
+ checkr3 800000ed
+
+ move.d 0x1,r3
+ adds.w 0xffff,r3
+ test_cc 0 1 0 1
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_addxm.s b/src/tests/tcg/cris/check_addxm.s
new file mode 100644
index 0000000..7563494
--- /dev/null
+++ b/src/tests/tcg/cris/check_addxm.s
@@ -0,0 +1,106 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n101\n10001\n100fe\n1fffe\nfffe\nfffe\nfffffffe\nfe\nfffffffe\n781344db\n781343db\n78143bdb\n78133bdb\n800000ed\n0\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .byte 0xff
+ .word 0xffff
+ .word 0xff
+ .word 0xffff
+ .byte 0x89
+ .word 0xf789
+ .byte 0xff
+ .word 0xffff
+
+ start
+ moveq 2,r3
+ move.d x,r5
+ adds.b [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ adds.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ subq 3,r5
+ addu.b [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 101
+
+ moveq 2,r3
+ addu.w [r5+],r3
+ subq 3,r5
+ test_cc 0 0 0 0
+ checkr3 10001
+
+ move.d 0xffff,r3
+ addu.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 100fe
+
+ move.d 0xffff,r3
+ addu.w [r5],r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ move.d 0xffff,r3
+ adds.b [r5],r3
+ test_cc 0 0 0 1
+ checkr3 fffe
+
+ move.d 0xffff,r3
+ adds.w [r5],r3
+ test_cc 0 0 0 1
+ checkr3 fffe
+
+ moveq -1,r3
+ adds.b [r5],r3
+ test_cc 1 0 0 1
+ addq 3,r5
+ checkr3 fffffffe
+
+ moveq -1,r3
+ adds.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 fe
+
+ moveq -1,r3
+ adds.w [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ addu.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 781344db
+
+ move.d 0x78134452,r3
+ adds.b [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 781343db
+
+ move.d 0x78134452,r3
+ addu.w [r5],r3
+ test_cc 0 0 0 0
+ checkr3 78143bdb
+
+ move.d 0x78134452,r3
+ adds.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ move.d 0x7fffffee,r3
+ addu.b [r5+],r3
+ test_cc 1 0 1 0
+ checkr3 800000ed
+
+ move.d 0x1,r3
+ adds.w [r5+],r3
+ test_cc 0 1 0 1
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_addxr.s b/src/tests/tcg/cris/check_addxr.s
new file mode 100644
index 0000000..7f55cdc
--- /dev/null
+++ b/src/tests/tcg/cris/check_addxr.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ add.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ moveq -1,r4
+ add.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ add.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ moveq -1,r4
+ move.d r4,r3
+ add.d r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.d r4,r3
+ test_cc 1 0 1 0
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ moveq 2,r4
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffff0001
+
+ moveq 2,r3
+ moveq -1,r4
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ add.w r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffe
+
+ move.d 0xfedaffff,r4
+ move.d r4,r3
+ add.w r4,r3
+ test_cc 1 0 0 1
+ checkr3 fedafffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ moveq -1,r3
+ moveq 2,r4
+ add.b r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffffff01
+
+ moveq 2,r3
+ moveq -1,r4
+ add.b r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xff,r4
+ move.d r4,r3
+ add.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 fe
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ add.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 feda49fe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/src/tests/tcg/cris/check_andc.s b/src/tests/tcg/cris/check_andc.s
new file mode 100644
index 0000000..a947b77
--- /dev/null
+++ b/src/tests/tcg/cris/check_andc.s
@@ -0,0 +1,80 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n50124400\nffff0002\n2\nfffff\nfedaff0f\n78134400\nffffff02\n2\nf02\n78134401\n78134400\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ and.d 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ and.d -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ and.d 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ and.d -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ and.d 0x5432f789,r3
+ test_move_cc 0 0 0 0
+ checkr3 50124400
+
+ moveq -1,r3
+ and.w 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0002
+
+ moveq 2,r3
+ and.w -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfffff,r3
+ and.w 0xffff,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffff
+
+ move.d 0xfedaffaf,r3
+ and.w 0xff5f,r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaff0f
+
+ move.d 0x78134452,r3
+ and.w 0xf789,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134400
+
+ moveq -1,r3
+ and.b 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff02
+
+ moveq 2,r3
+ and.b -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfa7,r3
+ and.b 0x5a,r3
+ test_move_cc 0 0 0 0
+ checkr3 f02
+
+ move.d 0x78134453,r3
+ and.b 0x89,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134401
+
+ and.b 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 78134400
+
+ quit
diff --git a/src/tests/tcg/cris/check_andm.s b/src/tests/tcg/cris/check_andm.s
new file mode 100644
index 0000000..9385886
--- /dev/null
+++ b/src/tests/tcg/cris/check_andm.s
@@ -0,0 +1,90 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n50124400\nffff0002\n2\nfffff\nfedaff0f\n78134400\nffffff02\n2\nf02\n78134401\n78134400\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 2,-1,0xffff,-1,0x5432f789
+ .word 2,-1,0xffff,0xff5f,0xf789
+ .byte 2,-1,0x5a,0x89,0
+
+ start
+ moveq -1,r3
+ move.d x,r5
+ and.d [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ and.d [r5],r3
+ test_move_cc 0 0 0 0
+ addq 4,r5
+ checkr3 2
+
+ move.d 0xffff,r3
+ and.d [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ and.d [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ and.d [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 50124400
+
+ moveq -1,r3
+ and.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0002
+
+ moveq 2,r3
+ and.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfffff,r3
+ and.w [r5],r3
+ test_move_cc 1 0 0 0
+ addq 2,r5
+ checkr3 fffff
+
+ move.d 0xfedaffaf,r3
+ and.w [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaff0f
+
+ move.d 0x78134452,r3
+ and.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 78134400
+
+ moveq -1,r3
+ and.b [r5],r3
+ test_move_cc 0 0 0 0
+ addq 1,r5
+ checkr3 ffffff02
+
+ moveq 2,r3
+ and.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfa7,r3
+ and.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 f02
+
+ move.d 0x78134453,r3
+ and.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 78134401
+
+ and.b [r5],r3
+ test_move_cc 0 1 0 0
+ checkr3 78134400
+
+ quit
diff --git a/src/tests/tcg/cris/check_andq.s b/src/tests/tcg/cris/check_andq.s
new file mode 100644
index 0000000..55aa7b0
--- /dev/null
+++ b/src/tests/tcg/cris/check_andq.s
@@ -0,0 +1,46 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n1f\nffffffe0\n78134452\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ andq 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ andq -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ andq -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ andq -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ andq 31,r3
+ test_move_cc 0 0 0 0
+ checkr3 1f
+
+ moveq -1,r3
+ andq -32,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffe0
+
+ move.d 0x78134457,r3
+ andq -14,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134452
+
+ moveq 0,r3
+ andq -14,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_andr.s b/src/tests/tcg/cris/check_andr.s
new file mode 100644
index 0000000..61aa1dc
--- /dev/null
+++ b/src/tests/tcg/cris/check_andr.s
@@ -0,0 +1,95 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n50124400\nffff0002\n2\nfffff\nfedaff0f\n78134400\nffffff02\n2\nf02\n78134401\n78134400\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ and.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ moveq -1,r4
+ and.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ and.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r4
+ move.d r4,r3
+ and.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ and.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 50124400
+
+ moveq -1,r3
+ moveq 2,r4
+ and.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0002
+
+ moveq 2,r3
+ moveq -1,r4
+ and.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfffff,r3
+ move.d 0xffff,r4
+ and.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffff
+
+ move.d 0xfedaffaf,r3
+ move.d 0xff5f,r4
+ and.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaff0f
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ and.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134400
+
+ moveq -1,r3
+ moveq 2,r4
+ and.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff02
+
+ moveq 2,r3
+ moveq -1,r4
+ and.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0x5a,r4
+ move.d 0xfa7,r3
+ and.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 f02
+
+ move.d 0x5432f789,r4
+ move.d 0x78134453,r3
+ and.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134401
+
+ moveq 0,r7
+ and.b r7,r3
+ test_move_cc 0 1 0 0
+ checkr3 78134400
+
+ quit
diff --git a/src/tests/tcg/cris/check_asr.s b/src/tests/tcg/cris/check_asr.s
new file mode 100644
index 0000000..0a02ae6
--- /dev/null
+++ b/src/tests/tcg/cris/check_asr.s
@@ -0,0 +1,230 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n1\nffffffff\nffffffff\n5a67f\nffffffff\nffffffff\nffffffff\nf699fc67\nffffffff\n1\nffffffff\nffffffff\n5a67f\nda67ffff\nda67ffff\nda67ffff\nda67fc67\nffffffff\nffffffff\n1\nffffffff\nffffffff\n5a670007\nda67f1ff\nda67f1ff\nda67f1ff\nda67f1e7\nffffffff\nffffffff\n1\nffffffff\nffffffff\nffffffff\n5a67f1ff\n5a67f1f9\n0\n5a670000\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ asrq 0,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ asrq 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ asrq 31,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ asrq 15,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5a67f19f,r3
+ asrq 12,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 f699fc67
+
+ moveq -1,r3
+ moveq 0,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ asr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 15,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ asr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67ffff
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67ffff
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67ffff
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67fc67
+
+ moveq -1,r3
+ moveq 0,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 1,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ asr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 15,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5a67719f,r3
+ moveq 12,r4
+ asr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a670007
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67f1ff
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67f1ff
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67f1ff
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67f1e7
+
+ moveq -1,r3
+ moveq 0,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 1,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ asr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 15,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 7,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+; FIXME: was wrong.
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 5a67f1ff
+
+; FIXME: was wrong.
+ move.d 0x5a67f19f,r3
+ moveq 4,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 5a67f1f9
+
+ move.d 0x5a67f19f,r3
+ asrq 31,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x5a67419f,r3
+ moveq 16,r4
+ asr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 5a670000
+
+ quit
diff --git a/src/tests/tcg/cris/check_ba.s b/src/tests/tcg/cris/check_ba.s
new file mode 100644
index 0000000..873a408
--- /dev/null
+++ b/src/tests/tcg/cris/check_ba.s
@@ -0,0 +1,93 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: a\n
+
+
+ .set smalloffset,0
+ .set largeoffset,0
+
+
+ .macro fail
+ jump _fail
+ .endm
+
+ .global main
+main:
+ moveq 0,$r3
+
+; Short forward branch.
+ ba 0f
+ addq 1,$r3
+ fail
+
+; Max short forward branch.
+1:
+ ba 2f
+ addq 1,$r3
+ fail
+
+; Short backward branch.
+0:
+ ba 1b
+ addq 1,$r3
+ fail
+
+ .space 254-2+smalloffset+1b-.,0
+ moveq 0,$r3
+
+2:
+; Transit branch (long).
+ ba 3f
+ addq 1,$r3
+ fail
+
+ moveq 0,$r3
+4:
+; Long forward branch.
+ ba 5f
+ addq 1,$r3
+ fail
+
+ .space 256-2-smalloffset+4b-.,0
+
+ moveq 0,$r3
+
+; Max short backward branch.
+3:
+ ba 4b
+ addq 1,$r3
+ fail
+
+5:
+; Max long forward branch.
+ ba 6f
+ addq 1,$r3
+ fail
+
+ .space 32766+largeoffset-2+5b-.,0
+
+ moveq 0,$r3
+6:
+; Transit branch.
+ ba 7f
+ addq 1,$r3
+ fail
+
+ moveq 0,$r3
+9:
+ jsr pass
+ nop
+
+; Transit branch.
+ moveq 0,$r3
+7:
+ ba 8f
+ addq 1,$r3
+ fail
+
+ .space 32768-largeoffset+9b-.,0
+
+8:
+; Max long backward branch.
+ ba 9b
+ addq 1,$r3
+ fail
diff --git a/src/tests/tcg/cris/check_bas.s b/src/tests/tcg/cris/check_bas.s
new file mode 100644
index 0000000..11929d4
--- /dev/null
+++ b/src/tests/tcg/cris/check_bas.s
@@ -0,0 +1,102 @@
+# mach: crisv32
+# output: 0\n0\n0\nfb349abc\n0\n12124243\n0\n0\neab5baad\n0\nefb37832\n
+
+ .include "testutils.inc"
+ start
+x:
+ setf zncv
+ bsr 0f
+ nop
+0:
+ test_cc 1 1 1 1
+ move srp,r3
+ sub.d 0b,r3
+ checkr3 0
+
+ bas 1f,mof
+ moveq 0,r0
+6:
+ nop
+ quit
+
+2:
+ move srp,r3
+ sub.d 3f,r3
+ checkr3 0
+ move srp,r4
+ subq 4,r4
+ move.d [r4],r3
+ checkr3 fb349abc
+
+ basc 4f,mof
+ nop
+ .dword 0x12124243
+7:
+ nop
+ quit
+
+8:
+ move mof,r3
+ sub.d 7f,r3
+ checkr3 0
+
+ move mof,r4
+ subq 4,r4
+ move.d [r4],r3
+ checkr3 eab5baad
+
+ jasc 9f,mof
+ nop
+ .dword 0xefb37832
+0:
+ quit
+
+ quit
+9:
+ move mof,r3
+ sub.d 0b,r3
+ checkr3 0
+
+ move mof,r4
+ subq 4,r4
+ move.d [r4],r3
+ checkr3 efb37832
+
+ quit
+
+4:
+ move mof,r3
+ sub.d 7b,r3
+ checkr3 0
+ move mof,r4
+ subq 4,r4
+ move.d [r4],r3
+ checkr3 12124243
+ basc 5f,bz
+ moveq 0,r3
+ .dword 0x7634aeba
+ quit
+
+ .space 32770,0
+1:
+ move mof,r3
+ sub.d 6b,r3
+ checkr3 0
+
+ bsrc 2b
+ nop
+ .dword 0xfb349abc
+3:
+
+ quit
+
+5:
+ move mof,r3
+ sub.d 7b,r3
+ checkr3 0
+ move.d 8b,r6
+ jasc r6,mof
+ nop
+ .dword 0xeab5baad
+7:
+ quit
diff --git a/src/tests/tcg/cris/check_bcc.s b/src/tests/tcg/cris/check_bcc.s
new file mode 100644
index 0000000..c57ffa6
--- /dev/null
+++ b/src/tests/tcg/cris/check_bcc.s
@@ -0,0 +1,197 @@
+ .global main
+ .type main, @function
+main:
+ clearf nzvc
+ setf nzv
+ bcc 0f
+ addq 1, $r3
+ jump dofail
+
+0:
+ clearf nzvc
+ setf nzv
+ bcs dofail
+ addq 1,$r3
+
+ clearf nzvc
+ setf ncv
+ bne 1f
+ addq 1, $r3
+
+fail:
+dofail:
+ jump _fail
+
+1:
+ clearf nzvc
+ setf ncv
+ beq dofail
+ addq 1,$r3
+
+ clearf nzvc
+ setf ncz
+ bvc 2f
+ addq 1,$r3
+ jump dofail
+
+2:
+ clearf nzvc
+ setf ncz
+ bvs dofail
+ addq 1,$r3
+
+ clearf nzvc
+ setf vcz
+ bpl 3f
+ addq 1,$r3
+ jump fail
+3:
+ clearf nzvc
+ setf vcz
+ bmi dofail
+ addq 1,$r3
+
+ clearf nzvc
+ setf nv
+ bls dofail
+ addq 1,$r3
+
+ clearf nzvc
+ setf nv
+ bhi 4f
+ addq 1,$r3
+ jump dofail
+
+4:
+ clearf nzvc
+ setf zc
+ bge 5f
+ addq 1,$r3
+ jump dofail
+
+5:
+ clearf nzvc
+ setf zc
+ blt dofail
+ addq 1,$r3
+
+ clearf nzvc
+ setf c
+ bgt 6f
+ addq 1,$r3
+ jump fail
+
+6:
+ clearf nzvc
+ setf c
+ ble dofail
+ addq 1,$r3
+
+;;;;;;;;;;
+
+ setf nzvc
+ clearf nzv
+ bcc dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf nzv
+ bcs 0f
+ addq 1,$r3
+ jump fail
+
+0:
+ setf nzvc
+ clearf ncv
+ bne dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf ncv
+ beq 1f
+ addq 1,$r3
+ jump fail
+
+1:
+ setf nzvc
+ clearf ncz
+ bvc dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf ncz
+ bvs 2f
+ addq 1,$r3
+ jump fail
+
+2:
+ setf nzvc
+ clearf vcz
+ bpl dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf vcz
+ bmi 3f
+ addq 1,$r3
+ jump fail
+
+3:
+ setf nzvc
+ clearf nv
+ bls 4f
+ addq 1,$r3
+ jump fail
+
+4:
+ setf nzvc
+ clearf nv
+ bhi dofail
+ addq 1,$r3
+
+ setf zvc
+ clearf nzc
+ bge dofail
+ addq 1,$r3
+
+ setf nzc
+ clearf vzc
+ blt 5f
+ addq 1,$r3
+ jump fail
+
+5:
+ setf nzvc
+ clearf c
+ bgt dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf c
+ ble 6f
+ addq 1,$r3
+ jump fail
+
+6:
+ ; do a forward branch.
+ ba 2f
+ nop
+ .fill 100
+1:
+ ba 3f
+ nop
+ .fill 800
+2:
+ ba 1b
+ nop
+ .fill 1024
+3:
+
+ moveq 31, $r0
+1: bne 1b
+ subq 1, $r0
+
+ jsr pass
+ moveq 0, $r10
+ ret
+ nop
diff --git a/src/tests/tcg/cris/check_bound.c b/src/tests/tcg/cris/check_bound.c
new file mode 100644
index 0000000..e883175
--- /dev/null
+++ b/src/tests/tcg/cris/check_bound.c
@@ -0,0 +1,142 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+static inline int cris_bound_b(int v, int b)
+{
+ int r = v;
+ asm ("bound.b\t%1, %0\n" : "+r" (r) : "ri" (b));
+ return r;
+}
+
+static inline int cris_bound_w(int v, int b)
+{
+ int r = v;
+ asm ("bound.w\t%1, %0\n" : "+r" (r) : "ri" (b));
+ return r;
+}
+
+static inline int cris_bound_d(int v, int b)
+{
+ int r = v;
+ asm ("bound.d\t%1, %0\n" : "+r" (r) : "ri" (b));
+ return r;
+}
+
+int main(void)
+{
+ int r;
+
+ cris_tst_cc_init();
+ r = cris_bound_d(-1, 2);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 2)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_d(2, 0xffffffff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 2)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_d(0xffff, 0xffff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xffff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_d(-1, 0xffffffff);
+ cris_tst_cc(1, 0, 0, 0);
+ if (r != 0xffffffff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_d(0x78134452, 0x5432f789);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0x5432f789)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_w(-1, 2);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 2)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_w(-1, 0xffff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xffff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_w(2, 0xffff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 2)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_w(0xfedaffff, 0xffff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xffff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_w(0x78134452, 0xf789);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xf789)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(-1, 2);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 2)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(2, 0xff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 2)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(-1, 0xff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(0xff, 0xff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(0xfeda49ff, 0xff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(0x78134452, 0x89);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0x89)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_w(0x78134452, 0);
+ cris_tst_cc(0, 1, 0, 0);
+ if (r != 0)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(0xffff, -1);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xff)
+ err();
+
+ pass();
+ return 0;
+}
diff --git a/src/tests/tcg/cris/check_boundc.s b/src/tests/tcg/cris/check_boundc.s
new file mode 100644
index 0000000..fb9e5bc
--- /dev/null
+++ b/src/tests/tcg/cris/check_boundc.s
@@ -0,0 +1,101 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n5432f789\n2\nffff\n2\nffff\nffff\nf789\n2\n2\nff\nff\nff\n89\n0\nff\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ bound.d 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ bound.d 0xffffffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ bound.d 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ bound.d 0xffffffff,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ bound.d 0x5432f789,r3
+ test_move_cc 0 0 0 0
+ checkr3 5432f789
+
+ moveq -1,r3
+ bound.w 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq -1,r3
+ bound.w 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq 2,r3
+ bound.w 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ bound.w 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r3
+ bound.w 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0x78134452,r3
+ bound.w 0xf789,r3
+ test_move_cc 0 0 0 0
+ checkr3 f789
+
+ moveq -1,r3
+ bound.b 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ bound.b 0xff,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq -1,r3
+ bound.b 0xff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0xff,r3
+ bound.b 0xff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0xfeda49ff,r3
+ bound.b 0xff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0x78134452,r3
+ bound.b 0x89,r3
+ test_move_cc 0 0 0 0
+ checkr3 89
+
+ bound.w 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xffff,r3
+ bound.b -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ quit
diff --git a/src/tests/tcg/cris/check_boundr.s b/src/tests/tcg/cris/check_boundr.s
new file mode 100644
index 0000000..5c50cc5
--- /dev/null
+++ b/src/tests/tcg/cris/check_boundr.s
@@ -0,0 +1,125 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n5432f789\n2\n2\nffff\nffff\nffff\nf789\n2\n2\nff\nff\n89\nfeda4953\nfeda4962\n0\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ bound.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ moveq -1,r4
+ bound.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ bound.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r4
+ move.d r4,r3
+ bound.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ bound.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5432f789
+
+ moveq -1,r3
+ moveq 2,r4
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ moveq -1,r4
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq -1,r3
+ bound.w r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r4
+ move.d r4,r3
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 f789
+
+ moveq -1,r3
+ moveq 2,r4
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ moveq -1,r4
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xff,r4
+ move.d r4,r3
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 89
+
+ move.d 0xfeda4956,r3
+ move.d 0xfeda4953,r4
+ bound.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 feda4953
+
+ move.d 0xfeda4962,r3
+ move.d 0xfeda4963,r4
+ bound.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 feda4962
+
+ move.d 0xfeda4956,r3
+ move.d 0,r4
+ bound.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xfeda4956,r4
+ move.d 0,r3
+ bound.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_btst.s b/src/tests/tcg/cris/check_btst.s
new file mode 100644
index 0000000..e39fc8f
--- /dev/null
+++ b/src/tests/tcg/cris/check_btst.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1111\n
+
+ .include "testutils.inc"
+ start
+ clearf nzvc
+ moveq -1,r3
+ .if 1 ;..asm.arch.cris.v32
+ .else
+ setf vc
+ .endif
+ btstq 0,r3
+ test_cc 1 0 0 0
+
+ moveq 2,r3
+ btstq 1,r3
+ test_cc 1 0 0 0
+
+ moveq 4,r3
+ btstq 1,r3
+ test_cc 0 1 0 0
+
+ moveq -1,r3
+ btstq 31,r3
+ test_cc 1 0 0 0
+
+ move.d 0x5a67f19f,r3
+ btstq 12,r3
+ test_cc 1 0 0 0
+
+ move.d 0xda67f19f,r3
+ move.d 29,r4
+ btst r4,r3
+ test_cc 0 0 0 0
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ move.d 0xda67f191,r3
+ move.d 33,r4
+ btst r4,r3
+ test_cc 0 0 0 0
+
+ moveq -1,r3
+ moveq 0,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ moveq 2,r3
+ moveq 1,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ moveq -1,r3
+ moveq 31,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ moveq 4,r3
+ btstq 1,r3
+ test_cc 0 1 0 0
+
+ moveq -1,r3
+ moveq 15,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ move.d 0x5a678000,r3
+ moveq 11,r4
+ btst r4,r3
+ test_cc 0 1 0 0
+
+ move.d 0x5a67f19f,r3
+ btst r3,r3
+ test_cc 0 0 0 0
+
+ move.d 0x1111,r3
+ checkr3 1111
+
+ ; check that X gets cleared and that only the NZ flags are touched.
+ move.d 0xff, $r0
+ move $r0, $ccs
+ btst r3,r3
+ move $ccs, $r0
+ and.d 0xff, $r0
+ cmp.d 0xe3, $r0
+ test_cc 0 1 0 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_clearfv32.s b/src/tests/tcg/cris/check_clearfv32.s
new file mode 100644
index 0000000..4e91360
--- /dev/null
+++ b/src/tests/tcg/cris/check_clearfv32.s
@@ -0,0 +1,19 @@
+# mach: crisv32
+# output: ef\nef\n
+
+; Check that "clearf x" doesn't trivially fail.
+
+ .include "testutils.inc"
+ start
+ setf puixnzvc
+ clearf x ; Actually, x would be cleared by almost-all other insns.
+ move ccs,r3
+ and.d 0xff, $r3
+ checkr3 ef
+
+ setf puixnzvc
+ moveq 0, $r3 ; moveq should only clear the xflag.
+ move ccs,r3
+ and.d 0xff, $r3
+ checkr3 ef
+ quit
diff --git a/src/tests/tcg/cris/check_clrjmp1.s b/src/tests/tcg/cris/check_clrjmp1.s
new file mode 100644
index 0000000..45a7005
--- /dev/null
+++ b/src/tests/tcg/cris/check_clrjmp1.s
@@ -0,0 +1,36 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff00\n
+
+; A bug resulting in a non-effectual clear.b discovered running the GCC
+; testsuite; jump actually wrote to p0.
+
+ .include "testutils.inc"
+
+ start
+ jump 1f
+ nop
+ .p2align 8
+1:
+ move.d y,r4
+
+ .if 0 ;0 == ..asm.arch.cris.v32
+; There was a bug causing this insn to set special register p0
+; (byte-clear) to 8 (low 8 bits of location after insn).
+ jump [r4+]
+ .endif
+
+1:
+ move.d 0f,r4
+
+; The corresponding bug would cause this insn too, to set p0.
+ jump r4
+ nop
+ quit
+0:
+ moveq -1,r3
+ clear.b r3
+ checkr3 ffffff00
+ quit
+
+y:
+ .dword 1b
diff --git a/src/tests/tcg/cris/check_cmp-2.s b/src/tests/tcg/cris/check_cmp-2.s
new file mode 100644
index 0000000..414d370
--- /dev/null
+++ b/src/tests/tcg/cris/check_cmp-2.s
@@ -0,0 +1,15 @@
+
+
+.include "testutils.inc"
+
+ start
+
+ move.d 4294967283, $r0
+ move.d $r0, $r10
+ cmp.d $r0, $r10
+ beq 1f
+ move.d $r10, $r3
+ fail
+1:
+ pass
+ quit
diff --git a/src/tests/tcg/cris/check_cmpc.s b/src/tests/tcg/cris/check_cmpc.s
new file mode 100644
index 0000000..267c9ba
--- /dev/null
+++ b/src/tests/tcg/cris/check_cmpc.s
@@ -0,0 +1,86 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n2\nffff\nffffffff\n78134452\nffffffff\n2\nffff\nfedaffff\n78134452\nffffffff\n2\nff\nfeda49ff\n78134452\n85649282\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ cmp.d -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.d 1,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmp.d -0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq -1,r3
+ cmp.d 1,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ cmp.d -0x5432f789,r3
+ test_cc 1 0 1 1
+ checkr3 78134452
+
+ moveq -1,r3
+ cmp.w -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.w 1,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmp.w 1,r3
+ test_cc 1 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r3
+ cmp.w 1,r3
+ test_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x78134452,r3
+ cmp.w 0x877,r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ moveq -1,r3
+ cmp.b -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.b 1,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xff,r3
+ cmp.b 1,r3
+ test_cc 1 0 0 0
+ checkr3 ff
+
+ move.d 0xfeda49ff,r3
+ cmp.b 1,r3
+ test_cc 1 0 0 0
+ checkr3 feda49ff
+
+ move.d 0x78134452,r3
+ cmp.b 0x77,r3
+ test_cc 1 0 0 1
+ checkr3 78134452
+
+ move.d 0x85649282,r3
+ cmp.b 0x82,r3
+ test_cc 0 1 0 0
+ checkr3 85649282
+
+ quit
diff --git a/src/tests/tcg/cris/check_cmpm.s b/src/tests/tcg/cris/check_cmpm.s
new file mode 100644
index 0000000..e4dde15
--- /dev/null
+++ b/src/tests/tcg/cris/check_cmpm.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n2\nffff\nffffffff\n78134452\nffffffff\n2\nffff\nfedaffff\n78134452\nffffffff\n2\nff\nfeda49ff\n78134452\n85649222\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword -2,1,-0xffff,1,-0x5432f789
+ .word -2,1,1,0x877
+ .byte -2,1,0x77
+ .byte 0x22
+
+ start
+ moveq -1,r3
+ move.d x,r5
+ cmp.d [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.d [r5],r3
+ test_cc 0 0 0 0
+ addq 4,r5
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmp.d [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq -1,r3
+ cmp.d [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ cmp.d [r5+],r3
+ test_cc 1 0 1 1
+ checkr3 78134452
+
+ moveq -1,r3
+ cmp.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmp.w [r5],r3
+ test_cc 1 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r3
+ cmp.w [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x78134452,r3
+ cmp.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ moveq -1,r3
+ cmp.b [r5],r3
+ test_cc 0 0 0 0
+ addq 1,r5
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xff,r3
+ cmp.b [r5],r3
+ test_cc 1 0 0 0
+ checkr3 ff
+
+ move.d 0xfeda49ff,r3
+ cmp.b [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 feda49ff
+
+ move.d 0x78134452,r3
+ cmp.b [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 78134452
+
+ move.d 0x85649222,r3
+ cmp.b [r5],r3
+ test_cc 0 1 0 0
+ checkr3 85649222
+
+ quit
diff --git a/src/tests/tcg/cris/check_cmpq.s b/src/tests/tcg/cris/check_cmpq.s
new file mode 100644
index 0000000..5469141
--- /dev/null
+++ b/src/tests/tcg/cris/check_cmpq.s
@@ -0,0 +1,75 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1\n1f\n1f\nffffffe1\nffffffe1\nffffffe0\n0\n0\nffffffff\nffffffff\n10000\n100\n5678900\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ cmpq 1,r3
+ test_cc 0 1 0 0
+ checkr3 1
+
+ cmpq -1,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ cmpq 31,r3
+ test_cc 1 0 0 1
+ checkr3 1
+
+ moveq 31,r3
+ cmpq 31,r3
+ test_cc 0 1 0 0
+ checkr3 1f
+
+ cmpq -31,r3
+ test_cc 0 0 0 1
+ checkr3 1f
+
+ movs.b -31,r3
+ cmpq -31,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffe1
+
+ cmpq -32,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffe1
+
+ movs.b -32,r3
+ cmpq -32,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffe0
+
+ moveq 0,r3
+ cmpq 1,r3
+ test_cc 1 0 0 1
+ checkr3 0
+
+ cmpq -32,r3
+ test_cc 0 0 0 1
+ checkr3 0
+
+ moveq -1,r3
+ cmpq 1,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ cmpq -1,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffff
+
+ move.d 0x10000,r3
+ cmpq 1,r3
+ test_cc 0 0 0 0
+ checkr3 10000
+
+ move.d 0x100,r3
+ cmpq 1,r3
+ test_cc 0 0 0 0
+ checkr3 100
+
+ move.d 0x5678900,r3
+ cmpq 7,r3
+ test_cc 0 0 0 0
+ checkr3 5678900
+
+ quit
diff --git a/src/tests/tcg/cris/check_cmpr.s b/src/tests/tcg/cris/check_cmpr.s
new file mode 100644
index 0000000..b30af7a
--- /dev/null
+++ b/src/tests/tcg/cris/check_cmpr.s
@@ -0,0 +1,102 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n2\nffff\nffffffff\n78134452\nffffffff\n2\nffff\nfedaffff\n78134452\nffffffff\n2\nff\nfeda49ff\n78134452\n85649222\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq -2,r4
+ cmp.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ cmp.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ move.d -0xffff,r4
+ cmp.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq 1,r4
+ moveq -1,r3
+ cmp.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ cmp.d r4,r3
+ test_cc 1 0 1 1
+ checkr3 78134452
+
+ moveq -1,r3
+ moveq -2,r4
+ cmp.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ cmp.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ move.d -0xffff,r4
+ cmp.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r3
+ move.d -0xfedaffff,r4
+ cmp.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ cmp.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ moveq -1,r3
+ moveq -2,r4
+ cmp.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ cmp.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d -0xff,r4
+ move.d 0xff,r3
+ cmp.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 ff
+
+ move.d -0xfeda49ff,r4
+ move.d 0xfeda49ff,r3
+ cmp.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 feda49ff
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ cmp.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 78134452
+
+ move.d 0x85649222,r3
+ move.d 0x77445622,r4
+ cmp.b r4,r3
+ test_cc 0 1 0 0
+ checkr3 85649222
+
+ quit
diff --git a/src/tests/tcg/cris/check_cmpxc.s b/src/tests/tcg/cris/check_cmpxc.s
new file mode 100644
index 0000000..b237a93
--- /dev/null
+++ b/src/tests/tcg/cris/check_cmpxc.s
@@ -0,0 +1,92 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\n2\n2\nffff\nffff\nffff\nffff\nffffffff\nffffffff\nffffffff\n78134452\n78134452\n78134452\n78134452\n4452\n80000032\n
+
+ .include "testutils.inc"
+ start
+ moveq 2,r3
+ cmps.b 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ cmps.w 0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ cmpu.b 0xff,r3
+ test_cc 1 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ move.d 0xffffffff,r4
+ cmpu.w -1,r3
+ test_cc 1 0 0 1
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmpu.b -1,r3
+ test_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmpu.w -1,r3
+ test_cc 0 1 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmps.b 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmps.w 0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq -1,r3
+ cmps.b 0xff,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ cmps.w 0xff,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ cmps.w 0xffff,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ cmpu.b 0x89,r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmps.b 0x89,r3
+ test_cc 0 0 0 1
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmpu.w 0xf789,r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmps.w 0xf789,r3
+ test_cc 0 0 0 1
+ checkr3 78134452
+
+ move.d 0x4452,r3
+ cmps.w 0x8002,r3
+ test_cc 0 0 0 1
+ checkr3 4452
+
+ move.d 0x80000032,r3
+ cmpu.w 0x764,r3
+ test_cc 0 0 1 0
+ checkr3 80000032
+
+ quit
diff --git a/src/tests/tcg/cris/check_cmpxm.s b/src/tests/tcg/cris/check_cmpxm.s
new file mode 100644
index 0000000..87ea5bf
--- /dev/null
+++ b/src/tests/tcg/cris/check_cmpxm.s
@@ -0,0 +1,106 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\n2\n2\nffff\nffff\nffff\nffff\nffffffff\nffffffff\nffffffff\n78134452\n78134452\n78134452\n78134452\n4452\n80000032\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .byte 0xff
+ .word 0xffff
+ .word 0xff
+ .word 0xffff
+ .byte 0x89
+ .word 0xf789
+ .word 0x8002
+ .word 0x764
+
+ start
+ moveq 2,r3
+ move.d x,r5
+ cmps.b [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ cmps.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ subq 3,r5
+ cmpu.b [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ cmpu.w [r5+],r3
+ test_cc 1 0 0 1
+ subq 3,r5
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmpu.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmpu.w [r5],r3
+ test_cc 0 1 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmps.b [r5],r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmps.w [r5],r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq -1,r3
+ cmps.b [r5],r3
+ test_cc 0 1 0 0
+ addq 3,r5
+ checkr3 ffffffff
+
+ moveq -1,r3
+ cmps.w [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ cmps.w [r5+],r3
+ test_cc 0 1 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ cmpu.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmps.b [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmpu.w [r5],r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmps.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 78134452
+
+ move.d 0x4452,r3
+ cmps.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 4452
+
+ move.d 0x80000032,r3
+ cmpu.w [r5+],r3
+ test_cc 0 0 1 0
+ checkr3 80000032
+
+ quit
diff --git a/src/tests/tcg/cris/check_dstep.s b/src/tests/tcg/cris/check_dstep.s
new file mode 100644
index 0000000..bd43b83
--- /dev/null
+++ b/src/tests/tcg/cris/check_dstep.s
@@ -0,0 +1,42 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: fffffffc\n4\nffff\nfffffffe\n9bf3911b\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ dstep r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffffc
+
+ moveq 2,r3
+ moveq -1,r4
+ dstep r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ dstep r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r4
+ move.d r4,r3
+ dstep r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ dstep r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 9bf3911b
+
+ move.d 0xffff,r3
+ move.d 0x1fffe,r4
+ dstep r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_ftag.c b/src/tests/tcg/cris/check_ftag.c
new file mode 100644
index 0000000..908773a
--- /dev/null
+++ b/src/tests/tcg/cris/check_ftag.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+static inline void cris_ftag_i(unsigned int x)
+{
+ register unsigned int v asm("$r10") = x;
+ asm ("ftagi\t[%0]\n" : : "r" (v) );
+}
+static inline void cris_ftag_d(unsigned int x)
+{
+ register unsigned int v asm("$r10") = x;
+ asm ("ftagd\t[%0]\n" : : "r" (v) );
+}
+static inline void cris_fidx_i(unsigned int x)
+{
+ register unsigned int v asm("$r10") = x;
+ asm ("fidxi\t[%0]\n" : : "r" (v) );
+}
+static inline void cris_fidx_d(unsigned int x)
+{
+ register unsigned int v asm("$r10") = x;
+ asm ("fidxd\t[%0]\n" : : "r" (v) );
+}
+
+
+int main(void)
+{
+ cris_ftag_i(0);
+ cris_ftag_d(0);
+ cris_fidx_i(0);
+ cris_fidx_d(0);
+ pass();
+ return 0;
+}
diff --git a/src/tests/tcg/cris/check_gcctorture_pr28634-1.c b/src/tests/tcg/cris/check_gcctorture_pr28634-1.c
new file mode 100644
index 0000000..45ecd15
--- /dev/null
+++ b/src/tests/tcg/cris/check_gcctorture_pr28634-1.c
@@ -0,0 +1,15 @@
+/* PR rtl-optimization/28634. On targets with delayed branches,
+ dbr_schedule could do the next iteration's addition in the
+ branch delay slot, then subtract the value again if the branch
+ wasn't taken. This can lead to rounding errors. */
+int x = -1;
+int y = 1;
+int
+main (void)
+{
+ while (y > 0)
+ y += x;
+ if (y != x + 1)
+ abort ();
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_gcctorture_pr28634.c b/src/tests/tcg/cris/check_gcctorture_pr28634.c
new file mode 100644
index 0000000..a0c5254
--- /dev/null
+++ b/src/tests/tcg/cris/check_gcctorture_pr28634.c
@@ -0,0 +1,15 @@
+/* PR rtl-optimization/28634. On targets with delayed branches,
+ dbr_schedule could do the next iteration's addition in the
+ branch delay slot, then subtract the value again if the branch
+ wasn't taken. This can lead to rounding errors. */
+double x = -0x1.0p53;
+double y = 1;
+int
+main (void)
+{
+ while (y > 0)
+ y += x;
+ if (y != x + 1)
+ abort ();
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_glibc_kernelversion.c b/src/tests/tcg/cris/check_glibc_kernelversion.c
new file mode 100644
index 0000000..0744872
--- /dev/null
+++ b/src/tests/tcg/cris/check_glibc_kernelversion.c
@@ -0,0 +1,116 @@
+/*
+ * Check the lz insn.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+
+#define __LINUX_KERNEL_VERSION 131584
+
+#define DL_SYSDEP_OSCHECK(FATAL) \
+ do { \
+ /* Test whether the kernel is new enough. This test is only \
+ performed if the library is not compiled to run on all \
+ kernels. */ \
+ if (__LINUX_KERNEL_VERSION > 0) \
+ { \
+ char bufmem[64]; \
+ char *buf = bufmem; \
+ unsigned int version; \
+ int parts; \
+ char *cp; \
+ struct utsname uts; \
+ \
+ /* Try the uname syscall */ \
+ if (__uname (&uts)) \
+ { \
+ /* This was not successful. Now try reading the /proc \
+ filesystem. */ \
+ ssize_t reslen; \
+ int fd = __open ("/proc/sys/kernel/osrelease", O_RDONLY); \
+ if (fd == -1 \
+ || (reslen = __read (fd, bufmem, sizeof (bufmem))) <= 0) \
+ /* This also didn't work. We give up since we cannot \
+ make sure the library can actually work. */ \
+ FATAL ("FATAL: cannot determine library version\n"); \
+ __close (fd); \
+ buf[MIN (reslen, (ssize_t) sizeof (bufmem) - 1)] = '\0'; \
+ } \
+ else \
+ buf = uts.release; \
+ \
+ /* Now convert it into a number. The string consists of at most \
+ three parts. */ \
+ version = 0; \
+ parts = 0; \
+ cp = buf; \
+ while ((*cp >= '0') && (*cp <= '9')) \
+ { \
+ unsigned int here = *cp++ - '0'; \
+ \
+ while ((*cp >= '0') && (*cp <= '9')) \
+ { \
+ here *= 10; \
+ here += *cp++ - '0'; \
+ } \
+ \
+ ++parts; \
+ version <<= 8; \
+ version |= here; \
+ \
+ if (*cp++ != '.') \
+ /* Another part following? */ \
+ break; \
+ } \
+ \
+ if (parts < 3) \
+ version <<= 8 * (3 - parts); \
+ \
+ /* Now we can test with the required version. */ \
+ if (version < __LINUX_KERNEL_VERSION) \
+ /* Not sufficient. */ \
+ FATAL ("FATAL: kernel too old\n"); \
+ \
+ _dl_osversion = version; \
+ } \
+ } while (0)
+
+int main(void)
+{
+ char bufmem[64] = "2.6.22";
+ char *buf = bufmem;
+ unsigned int version;
+ int parts;
+ char *cp;
+
+ version = 0;
+ parts = 0;
+ cp = buf;
+ while ((*cp >= '0') && (*cp <= '9'))
+ {
+ unsigned int here = *cp++ - '0';
+
+ while ((*cp >= '0') && (*cp <= '9'))
+ {
+ here *= 10;
+ here += *cp++ - '0';
+ }
+
+ ++parts;
+ version <<= 8;
+ version |= here;
+
+ if (*cp++ != '.')
+ /* Another part following? */
+ break;
+ }
+
+ if (parts < 3)
+ version <<= 8 * (3 - parts);
+ if (version < __LINUX_KERNEL_VERSION)
+ err();
+ pass();
+ exit(0);
+}
diff --git a/src/tests/tcg/cris/check_hello.c b/src/tests/tcg/cris/check_hello.c
new file mode 100644
index 0000000..fb403ba
--- /dev/null
+++ b/src/tests/tcg/cris/check_hello.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <stdlib.h>
+int main ()
+{
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_int64.c b/src/tests/tcg/cris/check_int64.c
new file mode 100644
index 0000000..fc60017
--- /dev/null
+++ b/src/tests/tcg/cris/check_int64.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+
+static inline int64_t add64(const int64_t a, const int64_t b)
+{
+ return a + b;
+}
+
+static inline int64_t sub64(const int64_t a, const int64_t b)
+{
+ return a - b;
+}
+
+int main(void)
+{
+ int64_t a = 1;
+ int64_t b = 2;
+
+ /* FIXME: add some tests. */
+ a = add64(a, b);
+ if (a != 3)
+ err();
+
+ a = sub64(a, b);
+ if (a != 1)
+ err();
+
+ a = add64(a, -4);
+ if (a != -3)
+ err();
+
+ a = add64(a, 3);
+ if (a != 0)
+ err();
+
+ a = 0;
+ a = sub64(a, 1);
+ if (a != -1)
+ err();
+
+ pass();
+ return 0;
+}
diff --git a/src/tests/tcg/cris/check_jsr.s b/src/tests/tcg/cris/check_jsr.s
new file mode 100644
index 0000000..1060237
--- /dev/null
+++ b/src/tests/tcg/cris/check_jsr.s
@@ -0,0 +1,85 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 0\n0\n0\n0\n0\n0\n
+
+# Test that jsr Rn and jsr [PC+] work.
+
+ .include "testutils.inc"
+ start
+x:
+ move.d 0f,r6
+ setf nzvc
+ jsr r6
+ .if 1; ..asm.arch.cris.v32
+ nop
+ .endif
+0:
+ test_move_cc 1 1 1 1
+ move srp,r3
+ sub.d 0b,r3
+ checkr3 0
+
+ move.d 1f,r0
+ setf nzvc
+ jsr r0
+ .if 1 ; ..asm.arch.cris.v32
+ moveq 0,r0
+ .endif
+6:
+ nop
+ quit
+
+2:
+ test_move_cc 0 0 0 0
+ move srp,r3
+ sub.d 3f,r3
+ checkr3 0
+ jsr 4f
+ .if 1 ; ..asm.arch.cris.v32
+ nop
+ .endif
+7:
+ nop
+ quit
+
+8:
+ move srp,r3
+ sub.d 7b,r3
+ checkr3 0
+ quit
+
+4:
+ move srp,r3
+ sub.d 7b,r3
+ checkr3 0
+ move.d 5f,r3
+ jump r3
+ .if 1; ..asm.arch.cris.v32
+ moveq 0,r3
+ .endif
+ quit
+
+ .space 32770,0
+1:
+ test_move_cc 1 1 1 1
+ move srp,r3
+ sub.d 6b,r3
+ checkr3 0
+
+ clearf cznv
+ jsr 2b
+ .if 1; ..asm.arch.cris.v32
+ nop
+ .endif
+3:
+
+ quit
+
+5:
+ move srp,r3
+ sub.d 7b,r3
+ checkr3 0
+ jump 8b
+ .if 1 ; ..asm.arch.cris.v32
+ nop
+ .endif
+ quit
diff --git a/src/tests/tcg/cris/check_lapc.s b/src/tests/tcg/cris/check_lapc.s
new file mode 100644
index 0000000..9a6150b
--- /dev/null
+++ b/src/tests/tcg/cris/check_lapc.s
@@ -0,0 +1,78 @@
+# mach: crisv32
+# output: 0\n0\nfffffffa\nfffffffe\nffffffda\n1e\n1e\n0\n
+
+.include "testutils.inc"
+
+; To accommodate dumpr3 with more than one instruction, keep it
+; out of lapc operand ranges and difference calculations.
+
+ start
+ lapc.d 0f,r3
+0:
+ sub.d .,r3
+ checkr3 0
+
+ lapcq 0f,r3
+0:
+ sub.d .,r3
+ checkr3 0
+
+ lapc.d .,r3
+ sub.d .,r3
+ checkr3 fffffffa
+
+ lapcq .,r3
+ sub.d .,r3
+ checkr3 fffffffe
+
+0:
+ .rept 16
+ nop
+ .endr
+ lapc.d 0b,r3
+ sub.d .,r3
+ checkr3 ffffffda
+
+ setf zcvn
+ lapc.d 0f,r3
+ test_cc 1 1 1 1
+ sub.d .,r3
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+0:
+ checkr3 1e
+0:
+ lapcq 0f,r3
+ sub.d 0b,r3
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+0:
+ checkr3 1e
+ clearf cn
+ setf zv
+1:
+ lapcq .,r3
+ test_cc 0 1 1 0
+ sub.d 1b,r3
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_lsl.s b/src/tests/tcg/cris/check_lsl.s
new file mode 100644
index 0000000..9e2ddd7
--- /dev/null
+++ b/src/tests/tcg/cris/check_lsl.s
@@ -0,0 +1,217 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n4\n80000000\nffff8000\n7f19f000\n80000000\n0\n0\n699fc67c\nffffffff\n4\n80000000\nffff8000\n7f19f000\nda670000\nda670000\nda670000\nda67c67c\nffffffff\nfffafffe\n4\nffff0000\nffff8000\n5a67f000\nda67f100\nda67f100\nda67f100\nda67f17c\nfff3faff\nfff3fafe\n4\nffffff00\nffffff00\nffffff80\n5a67f100\n5a67f1f0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ lslq 0,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ lslq 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ moveq -1,r3
+ lslq 31,r3
+ test_move_cc 1 0 0 0
+ checkr3 80000000
+
+ moveq -1,r3
+ lslq 15,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff8000
+
+ move.d 0x5a67f19f,r3
+ lslq 12,r3
+ test_move_cc 0 0 0 0
+ checkr3 7f19f000
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsl.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 80000000
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsl.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsl.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsl.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 699fc67c
+
+ moveq -1,r3
+ moveq 0,r4
+ lsl.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ lsl.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ moveq -1,r3
+ moveq 31,r4
+ lsl.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 80000000
+
+ moveq -1,r3
+ moveq 15,r4
+ lsl.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff8000
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsl.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 7f19f000
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsl.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsl.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsl.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67c67c
+
+ moveq -1,r3
+ moveq 0,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0xfffaffff,r3
+ moveq 1,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffafffe
+
+ moveq 2,r3
+ moveq 1,r4
+ lsl.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ moveq -1,r3
+ moveq 31,r4
+ lsl.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffff0000
+
+ moveq -1,r3
+ moveq 15,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff8000
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 5a67f000
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsl.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 da67f17c
+
+ move.d 0xfff3faff,r3
+ moveq 0,r4
+ lsl.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fff3faff
+
+ move.d 0xfff3faff,r3
+ moveq 1,r4
+ lsl.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fff3fafe
+
+ moveq 2,r3
+ moveq 1,r4
+ lsl.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ moveq -1,r3
+ moveq 31,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ moveq -1,r3
+ moveq 15,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ moveq -1,r3
+ moveq 7,r4
+ lsl.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffff80
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 5a67f100
+
+ move.d 0x5a67f19f,r3
+ moveq 4,r4
+ lsl.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 5a67f1f0
+
+ quit
diff --git a/src/tests/tcg/cris/check_lsr.s b/src/tests/tcg/cris/check_lsr.s
new file mode 100644
index 0000000..18fdbef
--- /dev/null
+++ b/src/tests/tcg/cris/check_lsr.s
@@ -0,0 +1,218 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n1\n1\n1ffff\n5a67f\n1\n0\n0\n3699fc67\nffffffff\n1\n1\n1ffff\n5a67f\nda670000\nda670000\nda670000\nda673c67\nffffffff\nffff7fff\n1\nffff0000\nffff0001\n5a67000f\nda67f100\nda67f100\nda67f100\nda67f127\nffffffff\nffffff7f\n1\nffffff00\nffffff00\nffffff01\n5a67f100\n5a67f109\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ lsrq 0,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ lsrq 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ lsrq 31,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ lsrq 15,r3
+ test_move_cc 0 0 0 0
+ checkr3 1ffff
+
+ move.d 0x5a67f19f,r3
+ lsrq 12,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsr.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsr.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3699fc67
+
+ moveq -1,r3
+ moveq 0,r4
+ lsr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 15,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1ffff
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 da673c67
+
+ moveq -1,r3
+ moveq 0,r4
+ lsr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 1,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff7fff
+
+ moveq 2,r3
+ moveq 1,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+;; FIXME: this was wrong. Z should be set.
+ moveq -1,r3
+ moveq 31,r4
+ lsr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffff0000
+
+ moveq -1,r3
+ moveq 15,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0001
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67000f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 da67f127
+
+ moveq -1,r3
+ moveq 0,r4
+ lsr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 1,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff7f
+
+ moveq 2,r3
+ moveq 1,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ moveq -1,r3
+ moveq 15,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ moveq -1,r3
+ moveq 7,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff01
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 5a67f100
+
+ move.d 0x5a67f19f,r3
+ moveq 4,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f109
+
+ quit
diff --git a/src/tests/tcg/cris/check_lz.c b/src/tests/tcg/cris/check_lz.c
new file mode 100644
index 0000000..69c2e6d
--- /dev/null
+++ b/src/tests/tcg/cris/check_lz.c
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+
+static inline int cris_lz(int x)
+{
+ int r;
+ asm ("lz\t%1, %0\n" : "=r" (r) : "r" (x));
+ return r;
+}
+
+void check_lz(void)
+{
+ int i;
+
+ if (cris_lz(0) != 32)
+ err();
+ if (cris_lz(1) != 31)
+ err();
+ if (cris_lz(2) != 30)
+ err();
+ if (cris_lz(4) != 29)
+ err();
+ if (cris_lz(8) != 28)
+ err();
+
+ /* try all positions with a single bit. */
+ for (i = 1; i < 32; i++) {
+ if (cris_lz(1 << (i-1)) != (32 - i))
+ err();
+ }
+
+ /* try all positions with all bits. */
+ for (i = 1; i < 32; i++) {
+ /* split up this computation to clarify it. */
+ uint32_t val;
+ val = (unsigned int)-1 >> (32 - i);
+ if (cris_lz(val) != (32 - i))
+ err();
+ }
+}
+
+int main(void)
+{
+ check_lz();
+ pass();
+ exit(0);
+}
diff --git a/src/tests/tcg/cris/check_mapbrk.c b/src/tests/tcg/cris/check_mapbrk.c
new file mode 100644
index 0000000..1aff762
--- /dev/null
+++ b/src/tests/tcg/cris/check_mapbrk.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Basic sanity check that syscalls to implement malloc (brk, mmap2,
+ munmap) are trivially functional. */
+
+int main ()
+{
+ void *p1, *p2, *p3, *p4, *p5, *p6;
+
+ if ((p1 = malloc (8100)) == NULL
+ || (p2 = malloc (16300)) == NULL
+ || (p3 = malloc (4000)) == NULL
+ || (p4 = malloc (500)) == NULL
+ || (p5 = malloc (1023*1024)) == NULL
+ || (p6 = malloc (8191*1024)) == NULL)
+ {
+ printf ("fail\n");
+ exit (1);
+ }
+
+ free (p1);
+ free (p2);
+ free (p3);
+ free (p4);
+ free (p5);
+ free (p6);
+
+ p1 = malloc (64000);
+ if (p1 == NULL)
+ {
+ printf ("fail\n");
+ exit (1);
+ }
+ free (p1);
+
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_mcp.s b/src/tests/tcg/cris/check_mcp.s
new file mode 100644
index 0000000..e65ccdd
--- /dev/null
+++ b/src/tests/tcg/cris/check_mcp.s
@@ -0,0 +1,49 @@
+# mach: crisv32
+# output: fffffffe\n1\n1ffff\nfffffffe\ncc463bdc\n4c463bdc\n0\n
+
+ .include "testutils.inc"
+ start
+
+; Set R, clear C.
+ move 0x100,ccs
+ moveq -5,r3
+ move 2,mof
+ mcp mof,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ moveq 2,r3
+ move -1,srp
+ mcp srp,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move 0xffff,srp
+ move srp,r3
+ mcp srp,r3
+ test_cc 0 0 0 0
+ checkr3 1ffff
+
+ move -1,mof
+ move mof,r3
+ mcp mof,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move 0x5432f789,mof
+ move.d 0x78134452,r3
+ mcp mof,r3
+ test_cc 1 0 1 0
+ checkr3 cc463bdc
+
+ move 0x80000000,srp
+ mcp srp,r3
+ test_cc 0 0 1 0
+ checkr3 4c463bdc
+
+ move 0xb3b9c423,srp
+ mcp srp,r3
+ test_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_mmap1.c b/src/tests/tcg/cris/check_mmap1.c
new file mode 100644
index 0000000..b803f0c
--- /dev/null
+++ b/src/tests/tcg/cris/check_mmap1.c
@@ -0,0 +1,48 @@
+/*
+#notarget: cris*-*-elf
+*/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int main (int argc, char *argv[])
+{
+ int fd = open (argv[0], O_RDONLY);
+ struct stat sb;
+ int size;
+ void *a;
+ const char *str = "a string you'll only find in the program";
+
+ if (fd == -1)
+ {
+ perror ("open");
+ abort ();
+ }
+
+ if (fstat (fd, &sb) < 0)
+ {
+ perror ("fstat");
+ abort ();
+ }
+
+ size = sb.st_size;
+
+ /* We want to test mmapping a size that isn't exactly a page. */
+ if ((size & 8191) == 0)
+ size--;
+
+ a = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+
+ if (memmem (a, size, str, strlen (str) + 1) == NULL)
+ abort ();
+
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_mmap2.c b/src/tests/tcg/cris/check_mmap2.c
new file mode 100644
index 0000000..35139a0
--- /dev/null
+++ b/src/tests/tcg/cris/check_mmap2.c
@@ -0,0 +1,48 @@
+/*
+#notarget: cris*-*-elf
+*/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int main (int argc, char *argv[])
+{
+ int fd = open (argv[0], O_RDONLY);
+ struct stat sb;
+ int size;
+ void *a;
+ const char *str = "a string you'll only find in the program";
+
+ if (fd == -1)
+ {
+ perror ("open");
+ abort ();
+ }
+
+ if (fstat (fd, &sb) < 0)
+ {
+ perror ("fstat");
+ abort ();
+ }
+
+ size = sb.st_size;
+
+ /* We want to test mmapping a size that isn't exactly a page. */
+ if ((size & 8191) == 0)
+ size--;
+
+ a = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+
+ if (memmem (a, size, str, strlen (str) + 1) == NULL)
+ abort ();
+
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_mmap3.c b/src/tests/tcg/cris/check_mmap3.c
new file mode 100644
index 0000000..34401fa
--- /dev/null
+++ b/src/tests/tcg/cris/check_mmap3.c
@@ -0,0 +1,33 @@
+/*
+#notarget: cris*-*-elf
+*/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int main (int argc, char *argv[])
+{
+ volatile unsigned char *a;
+
+ /* Check that we can map a non-multiple of a page and still get a full page. */
+ a = mmap (NULL, 0x4c, PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (a == NULL || a == (unsigned char *) -1)
+ abort ();
+
+ a[0] = 0xbe;
+ a[8191] = 0xef;
+ memset ((char *) a + 1, 0, 8190);
+
+ if (a[0] != 0xbe || a[8191] != 0xef)
+ abort ();
+
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_movdelsr1.s b/src/tests/tcg/cris/check_movdelsr1.s
new file mode 100644
index 0000000..300cc87
--- /dev/null
+++ b/src/tests/tcg/cris/check_movdelsr1.s
@@ -0,0 +1,33 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: aa117acd\n
+# output: eeaabb42\n
+
+; Bug with move to special register in delay slot, due to
+; special flush-insn-cache simulator use. Ordinary move worked;
+; special register caused branch to fail.
+
+ .include "testutils.inc"
+ start
+ move -1,srp
+
+ move.d 0xaa117acd,r1
+ moveq 3,r9
+ cmpq 1,r9
+ bhi 0f
+ move.d r1,r3
+
+ fail
+0:
+ checkr3 aa117acd
+
+ move.d 0xeeaabb42,r1
+ moveq 3,r9
+ cmpq 1,r9
+ bhi 0f
+ move r1,srp
+
+ fail
+0:
+ move srp,r3
+ checkr3 eeaabb42
+ quit
diff --git a/src/tests/tcg/cris/check_movecr.s b/src/tests/tcg/cris/check_movecr.s
new file mode 100644
index 0000000..da8ec26
--- /dev/null
+++ b/src/tests/tcg/cris/check_movecr.s
@@ -0,0 +1,37 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff42\n94\nffff4321\n9234\n76543210\n76540000\n
+
+; Move constant byte, word, dword to register. Check that no extension is
+; performed, that only part of the register is set.
+
+ .include "testutils.inc"
+ startnostack
+ moveq -1,r3
+ move.b 0x42,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff42
+
+ moveq 0,r3
+ move.b 0x94,r3
+ test_move_cc 1 0 0 0
+ checkr3 94
+
+ moveq -1,r3
+ move.w 0x4321,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff4321
+
+ moveq 0,r3
+ move.w 0x9234,r3
+ test_move_cc 1 0 0 0
+ checkr3 9234
+
+ move.d 0x76543210,r3
+ test_move_cc 0 0 0 0
+ checkr3 76543210
+
+ move.w 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 76540000
+
+ quit
diff --git a/src/tests/tcg/cris/check_movei.s b/src/tests/tcg/cris/check_movei.s
new file mode 100644
index 0000000..bbfa633
--- /dev/null
+++ b/src/tests/tcg/cris/check_movei.s
@@ -0,0 +1,50 @@
+# mach: crisv32
+# output: fffffffe\n
+# output: fffffffe\n
+
+; Check basic integral-write semantics regarding flags.
+
+ .include "testutils.inc"
+ start
+
+ move.d 0, $r3
+; A write that works. Check that flags are set correspondingly.
+ move.d d,r4
+ ;; store to bring it into the tlb with the right prot bits
+ move.d r3,[r4]
+ moveq -2,r5
+ setf c
+ clearf p
+ move.d [r4],r3
+ ax
+ move.d r5,[r4]
+ move.d [r4],r3
+
+ bcc 0f
+ nop
+ fail
+
+0:
+ checkr3 fffffffe
+
+; A write that fails; check flags too.
+ move.d d,r4
+ moveq 23,r5
+ setf p
+ clearf c
+ move.d [r4],r3
+ ax
+ move.d r5,[r4]
+ move.d [r4],r3
+
+ bcs 0f
+ nop
+ fail
+
+0:
+ checkr3 fffffffe
+ quit
+
+ .data
+d:
+ .dword 42424242
diff --git a/src/tests/tcg/cris/check_movemr.s b/src/tests/tcg/cris/check_movemr.s
new file mode 100644
index 0000000..88489de
--- /dev/null
+++ b/src/tests/tcg/cris/check_movemr.s
@@ -0,0 +1,78 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 12345678\n10234567\n12345678\n12344567\n12344523\n76543210\nffffffaa\naa\n9911\nffff9911\n78\n56\n3456\n6712\n
+
+ .include "testutils.inc"
+ start
+
+ .data
+mem1:
+ .dword 0x12345678
+mem2:
+ .word 0x4567
+mem3:
+ .byte 0x23
+ .dword 0x76543210
+ .byte 0xaa,0x11,0x99
+
+ .text
+ move.d mem1,r2
+ move.d [r2],r3
+ test_move_cc 0 0 0 0
+ checkr3 12345678
+
+ move.d mem2,r3
+ move.d [r3],r3
+ test_move_cc 0 0 0 0
+ checkr3 10234567
+
+ move.d mem1,r2
+ move.d [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 12345678
+
+ move.w [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 12344567
+
+ move.b [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 12344523
+
+ move.d [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 76543210
+
+ movs.b [r2],r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffaa
+
+ movu.b [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 aa
+
+ movu.w [r2],r3
+ test_move_cc 0 0 0 0
+ checkr3 9911
+
+ movs.w [r2+],r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff9911
+
+ move.d mem1,r13
+ movs.b [r13+],r3
+ test_move_cc 0 0 0 0
+ checkr3 78
+
+ movu.b [r13],r3
+ test_move_cc 0 0 0 0
+ checkr3 56
+
+ movs.w [r13+],r3
+ test_move_cc 0 0 0 0
+ checkr3 3456
+
+ movu.w [r13+],r3
+ test_move_cc 0 0 0 0
+ checkr3 6712
+
+ quit
diff --git a/src/tests/tcg/cris/check_movemrv32.s b/src/tests/tcg/cris/check_movemrv32.s
new file mode 100644
index 0000000..53950ab
--- /dev/null
+++ b/src/tests/tcg/cris/check_movemrv32.s
@@ -0,0 +1,96 @@
+# mach: crisv32
+# output: 15\n7\n2\nffff1234\nb\n16\nf\n2\nffffffef\nf\nffff1234\nf\nfffffff4\nd\nfffffff2\n10\nfffffff2\nd\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 8,9,10,11
+y:
+ .dword -12,13,-14,15,16
+
+ start
+ moveq 7,r0
+ moveq 2,r1
+ move.d 0xffff1234,r2
+ moveq 21,r3
+ move.d x,r4
+ setf zcvn
+ movem r2,[r4+]
+ test_cc 1 1 1 1
+ subq 12,r4
+
+ checkr3 15
+
+ move.d [r4+],r3
+ checkr3 7
+
+ move.d [r4+],r3
+ checkr3 2
+
+ move.d [r4+],r3
+ checkr3 ffff1234
+
+ move.d [r4+],r3
+ checkr3 b
+
+ subq 16,r4
+ moveq 22,r0
+ moveq 15,r1
+ clearf zcvn
+ movem r0,[r4]
+ test_cc 0 0 0 0
+ move.d [r4+],r3
+ checkr3 16
+
+ move.d r1,r3
+ checkr3 f
+
+ move.d [r4+],r3
+ checkr3 2
+
+ subq 8,r4
+ moveq 10,r2
+ moveq -17,r0
+ clearf zc
+ setf vn
+ movem r1,[r4]
+ test_cc 1 0 1 0
+ move.d [r4+],r3
+ checkr3 ffffffef
+
+ move.d [r4+],r3
+ checkr3 f
+
+ move.d [r4+],r3
+ checkr3 ffff1234
+
+ move.d y,r4
+ setf zc
+ clearf vn
+ movem [r4+],r3
+ test_cc 0 1 0 1
+ checkr3 f
+
+ move.d r0,r3
+ checkr3 fffffff4
+
+ move.d r1,r3
+ checkr3 d
+
+ move.d r2,r3
+ checkr3 fffffff2
+
+ move.d [r4],r3
+ checkr3 10
+
+ subq 8,r4
+ setf zcvn
+ movem [r4+],r0
+ test_cc 1 1 1 1
+ move.d r0,r3
+ checkr3 fffffff2
+
+ move.d r1,r3
+ checkr3 d
+
+ quit
diff --git a/src/tests/tcg/cris/check_moveq.c b/src/tests/tcg/cris/check_moveq.c
new file mode 100644
index 0000000..80f2dff
--- /dev/null
+++ b/src/tests/tcg/cris/check_moveq.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+#define cris_moveq(dst, src) \
+ asm volatile ("moveq %1, %0\n" : "=r" (dst) : "i" (src));
+
+
+
+int main(void)
+{
+ int t;
+
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_moveq(t, 10);
+ cris_tst_cc(1, 1, 1, 1);
+ if (t != 10)
+ err();
+
+ /* make sure moveq doesn't clobber the zflag. */
+ cris_tst_cc_init();
+ asm volatile ("setf vnc\n");
+ asm volatile ("clearf z\n");
+ cris_moveq(t, 0);
+ cris_tst_cc(1, 0, 1, 1);
+ if (t != 0)
+ err();
+
+ /* make sure moveq doesn't clobber the nflag.
+ Also check large immediates */
+ cris_tst_cc_init();
+ asm volatile ("setf zvc\n");
+ asm volatile ("clearf n\n");
+ cris_moveq(t, -31);
+ cris_tst_cc(0, 1, 1, 1);
+ if (t != -31)
+ err();
+
+ cris_tst_cc_init();
+ asm volatile ("setf nzvc\n");
+ cris_moveq(t, 31);
+ cris_tst_cc(1, 1, 1, 1);
+ if (t != 31)
+ err();
+
+ pass();
+ return 0;
+}
diff --git a/src/tests/tcg/cris/check_mover.s b/src/tests/tcg/cris/check_mover.s
new file mode 100644
index 0000000..b4db595
--- /dev/null
+++ b/src/tests/tcg/cris/check_mover.s
@@ -0,0 +1,28 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff05\nffff0005\n5\nffffff00\n
+
+; Move between registers. Check that just the subreg is copied.
+
+ .include "testutils.inc"
+ startnostack
+ moveq -30,r3
+ moveq 5,r4
+ move.b r4,r3
+ test_move_cc 0 0 0 0 ; FIXME
+ checkr3 ffffff05
+
+ move.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0005
+
+ move.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq -1,r3
+ moveq 0,r4
+ move.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ quit
diff --git a/src/tests/tcg/cris/check_moverm.s b/src/tests/tcg/cris/check_moverm.s
new file mode 100644
index 0000000..eabc958
--- /dev/null
+++ b/src/tests/tcg/cris/check_moverm.s
@@ -0,0 +1,45 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 7823fec2\n10231879\n102318fe\n
+
+ .include "testutils.inc"
+ start
+
+ .data
+mem1:
+ .dword 0x12345678
+mem2:
+ .word 0x4567
+mem3:
+ .byte 0x23
+ .dword 0x76543210
+ .byte 0xaa,0x11,0x99
+
+ .text
+ move.d mem1,r2
+ move.d 0x7823fec2,r4
+ setf nzvc
+ move.d r4,[r2+]
+ test_cc 1 1 1 1
+ subq 4,r2
+ move.d [r2],r3
+ checkr3 7823fec2
+
+ move.d mem2,r3
+ move.d 0x45231879,r4
+ clearf nzvc
+ move.w r4,[r3]
+ test_cc 0 0 0 0
+ move.d [r3],r3
+ checkr3 10231879
+
+ move.d mem2,r2
+ moveq -2,r4
+ clearf nc
+ setf zv
+ move.b r4,[r2+]
+ test_cc 0 1 1 0
+ subq 1,r2
+ move.d [r2],r3
+ checkr3 102318fe
+
+ quit
diff --git a/src/tests/tcg/cris/check_movmp.s b/src/tests/tcg/cris/check_movmp.s
new file mode 100644
index 0000000..7fc11f0
--- /dev/null
+++ b/src/tests/tcg/cris/check_movmp.s
@@ -0,0 +1,131 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff00\nffff0000\n0\nffffff00\nffff0000\n0\nffffff00\nffff0000\n0\nbb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
+
+# Test generic "move Ps,[]" and "move [],Pd" insns; the ones with
+# functionality common to all models.
+
+ .include "testutils.inc"
+ start
+
+ .data
+filler:
+ .byte 0xaa
+ .word 0x4433
+ .dword 0x55778866
+ .byte 0xcc
+
+ .text
+; Test that writing to zero-registers is a nop
+ .if 0
+ ; We used to just ignore the writes, but now an error is emitted. We
+ ; keep the test-code but disabled, in case we need to change this again.
+ move 0xaa,p0
+ move 0x4433,p4
+ move 0x55774433,p8
+ .endif
+
+ moveq -1,r3
+ setf zcvn
+ clear.b r3
+ test_cc 1 1 1 1
+ checkr3 ffffff00
+
+ moveq -1,r3
+ clearf zcvn
+ clear.w r3
+ test_cc 0 0 0 0
+ checkr3 ffff0000
+
+ moveq -1,r3
+ clear.d r3
+ checkr3 0
+
+; "Write" using ordinary memory references too.
+ .if 0 ; See ".if 0" above.
+ move.d filler,r6
+ move [r6],p0
+ move [r6],p4
+ move [r6],p8
+ .endif
+
+# ffffff00\nffff0000\n0\nffffff00\nffff0000\n0\nbb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
+
+ moveq -1,r3
+ clear.b r3
+ checkr3 ffffff00
+
+ moveq -1,r3
+ clear.w r3
+ checkr3 ffff0000
+
+ moveq -1,r3
+ clear.d r3
+ checkr3 0
+
+; And postincremented.
+ .if 0 ; See ".if 0" above.
+ move [r6+],p0
+ move [r6+],p4
+ move [r6+],p8
+ .endif
+
+# ffffff00\nffff0000\n0\nbb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
+
+ moveq -1,r3
+ clear.b r3
+ checkr3 ffffff00
+
+ moveq -1,r3
+ clear.w r3
+ checkr3 ffff0000
+
+ moveq -1,r3
+ clear.d r3
+ checkr3 0
+
+; Now see that we can write to the registers too.
+# bb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
+; [PC+]
+ move.d filler,r9
+ move 0xbb113344,srp
+ move srp,r3
+ checkr3 bb113344
+
+; [R+]
+ move [r9+],srp
+ move srp,r3
+ checkr3 664433aa
+
+; [R]
+ move [r9],srp
+ move srp,r3
+ checkr3 cc557788
+
+; And check writing to memory, clear and srp.
+
+ move.d filler,r9
+ move 0xabcde012,srp
+ setf zcvn
+ move srp,[r9+]
+ test_cc 1 1 1 1
+ subq 4,r9
+ move.d [r9],r3
+ checkr3 abcde012
+
+ clearf zcvn
+ clear.b [r9]
+ test_cc 0 0 0 0
+ move.d [r9],r3
+ checkr3 abcde000
+
+ addq 2,r9
+ clear.w [r9+]
+ subq 2,r9
+ move.d [r9],r3
+ checkr3 77880000
+
+ clear.d [r9]
+ move.d [r9],r3
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_movpmv32.s b/src/tests/tcg/cris/check_movpmv32.s
new file mode 100644
index 0000000..daf0970
--- /dev/null
+++ b/src/tests/tcg/cris/check_movpmv32.s
@@ -0,0 +1,35 @@
+# mach: crisv32
+# output: 11223320\nbb113344\naa557711\n
+
+# Test v32-specific special registers. FIXME: more registers.
+
+ .include "testutils.inc"
+ start
+ .data
+store:
+ .dword 0x11223344
+ .dword 0x77665544
+
+ .text
+ moveq -1,r3
+ move.d store,r4
+ move vr,[r4]
+ move [r4+],mof
+ move mof,r3
+ checkr3 11223320
+
+ moveq -1,r3
+ clearf zcvn
+ move 0xbb113344,mof
+ test_cc 0 0 0 0
+ move mof,r3
+ checkr3 bb113344
+
+ setf zcvn
+ move 0xaa557711,mof
+ test_cc 1 1 1 1
+ move mof,[r4]
+ move.d [r4],r3
+ checkr3 aa557711
+
+ quit
diff --git a/src/tests/tcg/cris/check_movpr.s b/src/tests/tcg/cris/check_movpr.s
new file mode 100644
index 0000000..eef9bdb
--- /dev/null
+++ b/src/tests/tcg/cris/check_movpr.s
@@ -0,0 +1,28 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff00\nffff0000\n0\nbb113344\n
+
+# Test generic "move Ps,Rd" and "move Rs,Pd" insns; the ones with
+# functionality common to all models.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ clear.b r3
+ checkr3 ffffff00
+
+ moveq -1,r3
+ clear.w r3
+ checkr3 ffff0000
+
+ moveq -1,r3
+ clear.d r3
+ checkr3 0
+
+ moveq -1,r3
+ move.d 0xbb113344,r4
+ setf zcvn
+ move r4,srp
+ move srp,r3
+ test_cc 1 1 1 1
+ checkr3 bb113344
+ quit
diff --git a/src/tests/tcg/cris/check_movprv32.s b/src/tests/tcg/cris/check_movprv32.s
new file mode 100644
index 0000000..d0d90e1
--- /dev/null
+++ b/src/tests/tcg/cris/check_movprv32.s
@@ -0,0 +1,21 @@
+# mach: crisv32
+# output: ffffff20\nbb113344\n
+
+# Test v32-specific special registers. FIXME: more registers.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ setf zcvn
+ move vr,r3
+ test_cc 1 1 1 1
+ checkr3 ffffff20
+
+ moveq -1,r3
+ move.d 0xbb113344,r4
+ clearf cvnz
+ move r4,mof
+ test_cc 0 0 0 0
+ move mof,r3
+ checkr3 bb113344
+ quit
diff --git a/src/tests/tcg/cris/check_movscr.s b/src/tests/tcg/cris/check_movscr.s
new file mode 100644
index 0000000..53c8ce6
--- /dev/null
+++ b/src/tests/tcg/cris/check_movscr.s
@@ -0,0 +1,29 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 42\nffffff85\n7685\nffff8765\n0\n
+
+; Move constant byte, word, dword to register. Check that sign-extension
+; is performed.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ movs.b 0x42,r3
+ checkr3 42
+
+ movs.b 0x85,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffff85
+
+ movs.w 0x7685,r3
+ test_move_cc 0 0 0 0
+ checkr3 7685
+
+ movs.w 0x8765,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff8765
+
+ movs.w 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_movsm.s b/src/tests/tcg/cris/check_movsm.s
new file mode 100644
index 0000000..7074336
--- /dev/null
+++ b/src/tests/tcg/cris/check_movsm.s
@@ -0,0 +1,44 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 5\nfffffff5\n5\nfffffff5\n0\n
+
+; Movs between registers. Check that sign-extension is performed and the
+; full register is set.
+
+ .include "testutils.inc"
+
+ .data
+x:
+ .byte 5,-11
+ .word 5,-11
+ .word 0
+
+ start
+ move.d x,r5
+
+ moveq -1,r3
+ movs.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r3
+ movs.b [r5],r3
+ test_move_cc 1 0 0 0
+ addq 1,r5
+ checkr3 fffffff5
+
+ moveq -1,r3
+ movs.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r3
+ movs.w [r5],r3
+ test_move_cc 1 0 0 0
+ addq 2,r5
+ checkr3 fffffff5
+
+ movs.w [r5],r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_movsr.s b/src/tests/tcg/cris/check_movsr.s
new file mode 100644
index 0000000..d1889a7
--- /dev/null
+++ b/src/tests/tcg/cris/check_movsr.s
@@ -0,0 +1,46 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 5\nfffffff5\n5\nfffffff5\n0\n
+
+; Movs between registers. Check that sign-extension is performed and the
+; full register is set.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r5
+ moveq 5,r4
+ move.b r4,r5
+ moveq -1,r3
+ movs.b r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r5
+ moveq -11,r4
+ move.b r4,r5
+ moveq 0,r3
+ movs.b r5,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffff5
+
+ moveq -1,r5
+ moveq 5,r4
+ move.w r4,r5
+ moveq -1,r3
+ movs.w r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r5
+ moveq -11,r4
+ move.w r4,r5
+ moveq 0,r3
+ movs.w r5,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffff5
+
+ moveq 0,r5
+ movs.b r5,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_movucr.s b/src/tests/tcg/cris/check_movucr.s
new file mode 100644
index 0000000..7c8487d
--- /dev/null
+++ b/src/tests/tcg/cris/check_movucr.s
@@ -0,0 +1,33 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 42\n85\n7685\n8765\n0\n
+
+; Move constant byte, word, dword to register. Check that zero-extension
+; is performed.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ movu.b 0x42,r3
+ test_move_cc 0 0 0 0
+ checkr3 42
+
+ moveq -1,r3
+ movu.b 0x85,r3
+ test_move_cc 0 0 0 0
+ checkr3 85
+
+ moveq -1,r3
+ movu.w 0x7685,r3
+ test_move_cc 0 0 0 0
+ checkr3 7685
+
+ moveq -1,r3
+ movu.w 0x8765,r3
+ test_move_cc 0 0 0 0
+ checkr3 8765
+
+ movu.b 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_movum.s b/src/tests/tcg/cris/check_movum.s
new file mode 100644
index 0000000..038e539
--- /dev/null
+++ b/src/tests/tcg/cris/check_movum.s
@@ -0,0 +1,40 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 5\nf5\n5\nfff5\n0\n
+
+; Movu between registers. Check that zero-extension is performed and the
+; full register is set.
+
+ .include "testutils.inc"
+
+ .data
+x:
+ .byte 5,-11
+ .word 5,-11
+ .word 0
+
+ start
+ move.d x,r5
+
+ movu.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ movu.b [r5],r3
+ test_move_cc 0 0 0 0
+ addq 1,r5
+ checkr3 f5
+
+ movu.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ movu.w [r5],r3
+ test_move_cc 0 0 0 0
+ addq 2,r5
+ checkr3 fff5
+
+ movu.w [r5],r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_movur.s b/src/tests/tcg/cris/check_movur.s
new file mode 100644
index 0000000..3ecf475
--- /dev/null
+++ b/src/tests/tcg/cris/check_movur.s
@@ -0,0 +1,45 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 5\nf5\n5\nfff5\n0\n
+
+; Movu between registers. Check that zero-extension is performed and the
+; full register is set.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r5
+ moveq 5,r4
+ move.b r4,r5
+ moveq -1,r3
+ movu.b r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r5
+ moveq -11,r4
+ move.b r4,r5
+ moveq -1,r3
+ movu.b r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 f5
+
+ moveq -1,r5
+ moveq 5,r4
+ move.w r4,r5
+ moveq -1,r3
+ movu.w r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r5
+ moveq -11,r4
+ move.w r4,r5
+ moveq -1,r3
+ movu.w r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 fff5
+
+ movu.w 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_mulv32.s b/src/tests/tcg/cris/check_mulv32.s
new file mode 100644
index 0000000..f379358
--- /dev/null
+++ b/src/tests/tcg/cris/check_mulv32.s
@@ -0,0 +1,51 @@
+# mach: crisv32
+# output: fffffffe\n
+# output: ffffffff\n
+# output: fffffffe\n
+# output: 1\n
+# output: fffffffe\n
+# output: ffffffff\n
+# output: fffffffe\n
+# output: 1\n
+
+; Check that carry is not modified on v32.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ setf c
+ muls.d r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ setf c
+ mulu.d r4,r3
+ test_cc 0 0 1 1
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 1
+
+ moveq -1,r3
+ moveq 2,r4
+ clearf c
+ muls.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ clearf c
+ mulu.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 1
+
+ quit
diff --git a/src/tests/tcg/cris/check_mulx.s b/src/tests/tcg/cris/check_mulx.s
new file mode 100644
index 0000000..d43241a
--- /dev/null
+++ b/src/tests/tcg/cris/check_mulx.s
@@ -0,0 +1,246 @@
+# mach: crisv10 crisv32
+# output: fffffffe\nffffffff\nfffffffe\n1\nfffffffe\nffffffff\nfffffffe\n1\nfffe0001\n0\nfffe0001\n0\n1\n0\n1\nfffffffe\n193eade2\n277e3a49\n193eade2\n277e3a49\nfffffffe\nffffffff\n1fffe\n0\nfffffffe\nffffffff\n1fffe\n0\n1\n0\nfffe0001\n0\nfdbdade2\nffffffff\n420fade2\n0\nfffffffe\nffffffff\n1fe\n0\nfffffffe\nffffffff\n1fe\n0\n1\n0\nfe01\n0\n1\n0\nfe01\n0\nffffd9e2\nffffffff\n2be2\n0\n0\n0\n0\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ muls.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ mulu.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 1
+
+ moveq 2,r3
+ moveq -1,r4
+ muls.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq -1,r4
+ mulu.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ muls.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 fffe0001
+ move mof,r3
+ checkr3 0
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ mulu.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 fffe0001
+ move mof,r3
+ checkr3 0
+
+ moveq -1,r4
+ move.d r4,r3
+ muls.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+ move mof,r3
+ checkr3 0
+
+ moveq -1,r4
+ move.d r4,r3
+ mulu.d r4,r3
+ test_cc 1 0 1 0
+ checkr3 1
+ move mof,r3
+ checkr3 fffffffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ muls.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 193eade2
+ move mof,r3
+ checkr3 277e3a49
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ mulu.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 193eade2
+ move mof,r3
+ checkr3 277e3a49
+
+ move.d 0xffff,r3
+ moveq 2,r4
+ muls.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ mulu.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+ move mof,r3
+ checkr3 0
+
+ moveq 2,r3
+ move.d 0xffff,r4
+ muls.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq -1,r4
+ mulu.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+ move mof,r3
+ checkr3 0
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ muls.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+ move mof,r3
+ checkr3 0
+
+ moveq -1,r4
+ move.d r4,r3
+ mulu.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 fffe0001
+ move mof,r3
+ checkr3 0
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ muls.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fdbdade2
+ move mof,r3
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ mulu.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 420fade2
+ move mof,r3
+ checkr3 0
+
+ move.d 0xff,r3
+ moveq 2,r4
+ muls.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fe
+ move mof,r3
+ checkr3 0
+
+ moveq 2,r3
+ moveq -1,r4
+ muls.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq -1,r4
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fe
+ move mof,r3
+ checkr3 0
+
+ move.d 0xff,r4
+ move.d r4,r3
+ muls.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+ move mof,r3
+ checkr3 0
+
+ moveq -1,r4
+ move.d r4,r3
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 fe01
+ move mof,r3
+ checkr3 0
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ muls.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+ move mof,r3
+ checkr3 0
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 fe01
+ move mof,r3
+ checkr3 0
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ muls.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 ffffd9e2
+ move mof,r3
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 2be2
+ move mof,r3
+ checkr3 0
+
+ moveq 0,r3
+ move.d 0xf87f4aeb,r4
+ muls.d r4,r3
+ test_cc 0 1 0 0
+ checkr3 0
+ move mof,r3
+ checkr3 0
+
+ move.d 0xf87f4aeb,r3
+ moveq 0,r4
+ mulu.d r4,r3
+ test_cc 0 1 0 0
+ checkr3 0
+ move mof,r3
+ checkr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_neg.s b/src/tests/tcg/cris/check_neg.s
new file mode 100644
index 0000000..963c4b6
--- /dev/null
+++ b/src/tests/tcg/cris/check_neg.s
@@ -0,0 +1,104 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\nffffffff\n0\n80000000\n1\nba987655\nffff\nffff\n0\n89ab8000\nffff0001\n45677655\nff\nff\n0\n89abae80\nffffff01\n45678955\n
+
+ .include "testutils.inc"
+ start
+ moveq 0,r3
+ moveq 1,r4
+ neg.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 1,r3
+ moveq 0,r4
+ neg.d r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+;; FIXME: this was wrong.
+ moveq 0,r3
+ neg.d r3,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x80000000,r3
+ neg.d r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 80000000
+
+ moveq -1,r3
+ neg.d r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0x456789ab,r3
+ neg.d r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 ba987655
+
+ moveq 0,r3
+ moveq 1,r4
+ neg.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff
+
+ moveq 1,r3
+ moveq 0,r4
+ neg.w r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff
+
+ moveq 0,r3
+ neg.w r3,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x89ab8000,r3
+ neg.w r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 89ab8000
+
+ moveq -1,r3
+ neg.w r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0001
+
+ move.d 0x456789ab,r3
+ neg.w r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 45677655
+
+ moveq 0,r3
+ moveq 1,r4
+ neg.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ff
+
+ moveq 1,r3
+ moveq 0,r4
+ neg.b r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 ff
+
+ moveq 0,r3
+ neg.b r3,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+;; FIXME: was wrong.
+ move.d 0x89abae80,r3
+ neg.b r3,r3
+ test_move_cc 1 0 0 1
+ checkr3 89abae80
+
+ moveq -1,r3
+ neg.b r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff01
+
+ move.d 0x456789ab,r3
+ neg.b r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 45678955
+
+ quit
diff --git a/src/tests/tcg/cris/check_not.s b/src/tests/tcg/cris/check_not.s
new file mode 100644
index 0000000..33bcf15
--- /dev/null
+++ b/src/tests/tcg/cris/check_not.s
@@ -0,0 +1,31 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: fffffffe\nfffffffd\nffff0f00\n0\n87ecbbad\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ not r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffffe
+
+ moveq 2,r3
+ not r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffffd
+
+ move.d 0xf0ff,r3
+ not r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff0f00
+
+ moveq -1,r3
+ not r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x78134452,r3
+ not r3
+ test_move_cc 1 0 0 0
+ checkr3 87ecbbad
+
+ quit
diff --git a/src/tests/tcg/cris/check_openpf1.c b/src/tests/tcg/cris/check_openpf1.c
new file mode 100644
index 0000000..fdcf4c5
--- /dev/null
+++ b/src/tests/tcg/cris/check_openpf1.c
@@ -0,0 +1,38 @@
+/* Check that --sysroot is applied to open(2).
+#sim: --sysroot=@exedir@
+
+ We assume, with EXE being the name of the executable:
+ - The simulator executes with cwd the same directory where the executable
+ is located (so argv[0] contains a plain filename without directory
+ components).
+ - There's no /EXE on the host file system. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+int main (int argc, char *argv[])
+{
+ char *fnam = argv[0];
+ FILE *f;
+ if (argv[0][0] != '/')
+ {
+ fnam = malloc (strlen (argv[0]) + 2);
+ if (fnam == NULL)
+ abort ();
+ strcpy (fnam, "/");
+ strcat (fnam, argv[0]);
+ }
+
+ f = fopen (fnam, "rb");
+ if (f == NULL)
+ abort ();
+ fclose(f);
+
+ /* Cover another execution path. */
+ if (fopen ("/nonexistent", "rb") != NULL
+ || errno != ENOENT)
+ abort ();
+ printf ("pass\n");
+ return 0;
+}
diff --git a/src/tests/tcg/cris/check_openpf2.c b/src/tests/tcg/cris/check_openpf2.c
new file mode 100644
index 0000000..5d56189
--- /dev/null
+++ b/src/tests/tcg/cris/check_openpf2.c
@@ -0,0 +1,16 @@
+/* Check that the simulator has chdir:ed to the --sysroot argument
+#sim: --sysroot=@srcdir@
+ (or that --sysroot is applied to relative file paths). */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+int main (int argc, char *argv[])
+{
+ FILE *f = fopen ("check_openpf2.c", "rb");
+ if (f == NULL)
+ abort ();
+ fclose(f);
+ printf ("pass\n");
+ return 0;
+}
diff --git a/src/tests/tcg/cris/check_openpf3.c b/src/tests/tcg/cris/check_openpf3.c
new file mode 100644
index 0000000..557adee
--- /dev/null
+++ b/src/tests/tcg/cris/check_openpf3.c
@@ -0,0 +1,49 @@
+/* Basic file operations (rename, unlink); once without sysroot. We
+ also test that the simulator has chdir:ed to PREFIX, when defined. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifndef PREFIX
+#define PREFIX
+#endif
+
+void err (const char *s)
+{
+ perror (s);
+ abort ();
+}
+
+int main (int argc, char *argv[])
+{
+ FILE *f;
+ struct stat buf;
+
+ unlink (PREFIX "testfoo2.tmp");
+
+ f = fopen ("testfoo1.tmp", "w");
+ if (f == NULL)
+ err ("open");
+ fclose (f);
+
+ if (rename (PREFIX "testfoo1.tmp", PREFIX "testfoo2.tmp") != 0)
+ err ("rename");
+
+ if (stat (PREFIX "testfoo2.tmp", &buf) != 0
+ || !S_ISREG (buf.st_mode))
+ err ("stat 1");
+
+ if (stat ("testfoo2.tmp", &buf) != 0
+ || !S_ISREG (buf.st_mode))
+ err ("stat 2");
+
+ if (unlink (PREFIX "testfoo2.tmp") != 0)
+ err ("unlink");
+
+ printf ("pass\n");
+ return 0;
+}
diff --git a/src/tests/tcg/cris/check_openpf4.c b/src/tests/tcg/cris/check_openpf4.c
new file mode 100644
index 0000000..8bbee41
--- /dev/null
+++ b/src/tests/tcg/cris/check_openpf4.c
@@ -0,0 +1,5 @@
+/* Basic file operations, now *with* sysroot.
+#sim: --sysroot=@exedir@
+*/
+#define PREFIX "/"
+#include "check_openpf3.c"
diff --git a/src/tests/tcg/cris/check_openpf5.c b/src/tests/tcg/cris/check_openpf5.c
new file mode 100644
index 0000000..1f86ea2
--- /dev/null
+++ b/src/tests/tcg/cris/check_openpf5.c
@@ -0,0 +1,56 @@
+/* Check that TRT happens when error on too many opened files.
+#notarget: cris*-*-elf
+#sim: --sysroot=@exedir@
+*/
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+int main (int argc, char *argv[])
+{
+ int i;
+ int filemax;
+
+#ifdef OPEN_MAX
+ filemax = OPEN_MAX;
+#else
+ filemax = sysconf (_SC_OPEN_MAX);
+#endif
+
+ char *fn = malloc (strlen (argv[0]) + 2);
+ if (fn == NULL)
+ abort ();
+ strcpy (fn, "/");
+ strcat (fn, argv[0]);
+
+ for (i = 0; i < filemax + 1; i++)
+ {
+ if (open (fn, O_RDONLY) < 0)
+ {
+ /* Shouldn't happen too early. */
+ if (i < filemax - 3 - 1)
+ {
+ fprintf (stderr, "i: %d\n", i);
+ abort ();
+ }
+ if (errno != EMFILE)
+ {
+ perror ("open");
+ abort ();
+ }
+ goto ok;
+ }
+ }
+ abort ();
+
+ok:
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_orc.s b/src/tests/tcg/cris/check_orc.s
new file mode 100644
index 0000000..c733f03
--- /dev/null
+++ b/src/tests/tcg/cris/check_orc.s
@@ -0,0 +1,71 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 3\n3\nffff\nffffffff\n7c33f7db\nffff0003\n3\nfedaffff\n7813f7db\n3\n3\nfeb\n781344db\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ or.d 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ or.d 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xf0ff,r3
+ or.d 0xff0f,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ or.d -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ or.d 0x5432f789,r3
+ test_move_cc 0 0 0 0
+ checkr3 7c33f7db
+
+ move.d 0xffff0001,r3
+ or.w 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0003
+
+ moveq 2,r3
+ or.w 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfedaffaf,r3
+ or.w 0xff5f,r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x78134452,r3
+ or.w 0xf789,r3
+ test_move_cc 1 0 0 0
+ checkr3 7813f7db
+
+ moveq 1,r3
+ or.b 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ or.b 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfa3,r3
+ or.b 0x4a,r3
+ test_move_cc 1 0 0 0
+ checkr3 feb
+
+ move.d 0x78134453,r3
+ or.b 0x89,r3
+ test_move_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/src/tests/tcg/cris/check_orm.s b/src/tests/tcg/cris/check_orm.s
new file mode 100644
index 0000000..ee723a6
--- /dev/null
+++ b/src/tests/tcg/cris/check_orm.s
@@ -0,0 +1,75 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 3\n3\nffff\nffffffff\n7c33f7db\nffff0003\n3\nfedaffff\n7813f7db\n3\n3\nfeb\n781344db\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 2,1,0xff0f,-1,0x5432f789
+ .word 2,1,0xff5f,0xf789
+ .byte 2,1,0x4a,0x89
+
+ start
+ moveq 1,r3
+ move.d x,r5
+ or.d [r5+],r3
+ checkr3 3
+
+ moveq 2,r3
+ or.d [r5],r3
+ addq 4,r5
+ checkr3 3
+
+ move.d 0xf0ff,r3
+ or.d [r5+],r3
+ checkr3 ffff
+
+ moveq -1,r3
+ or.d [r5+],r3
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ or.d [r5+],r3
+ checkr3 7c33f7db
+
+ move.d 0xffff0001,r3
+ or.w [r5+],r3
+ checkr3 ffff0003
+
+ moveq 2,r3
+ or.w [r5],r3
+ addq 2,r5
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfedaffaf,r3
+ or.w [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x78134452,r3
+ or.w [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 7813f7db
+
+ moveq 1,r3
+ or.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ or.b [r5],r3
+ addq 1,r5
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfa3,r3
+ or.b [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 feb
+
+ move.d 0x78134453,r3
+ or.b [r5],r3
+ test_move_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/src/tests/tcg/cris/check_orq.s b/src/tests/tcg/cris/check_orq.s
new file mode 100644
index 0000000..5060edc
--- /dev/null
+++ b/src/tests/tcg/cris/check_orq.s
@@ -0,0 +1,41 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 3\n3\nffffffff\nffffffff\n1f\nffffffe0\n7813445e\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ orq 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ orq 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xf0ff,r3
+ orq -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 0,r3
+ orq -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 0,r3
+ orq 31,r3
+ test_move_cc 0 0 0 0
+ checkr3 1f
+
+ moveq 0,r3
+ orq -32,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffe0
+
+ move.d 0x78134452,r3
+ orq 12,r3
+ test_move_cc 0 0 0 0
+ checkr3 7813445e
+
+ quit
diff --git a/src/tests/tcg/cris/check_orr.s b/src/tests/tcg/cris/check_orr.s
new file mode 100644
index 0000000..a514c11
--- /dev/null
+++ b/src/tests/tcg/cris/check_orr.s
@@ -0,0 +1,84 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 3\n3\nffff\nffffffff\n7c33f7db\nffff0003\n3\nfedaffff\n7813f7db\n3\n3\nfeb\n781344db\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ moveq 2,r4
+ or.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ moveq 1,r4
+ or.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xff0f,r4
+ move.d 0xf0ff,r3
+ or.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r4
+ move.d r4,r3
+ or.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ or.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 7c33f7db
+
+ move.d 0xffff0001,r3
+ moveq 2,r4
+ or.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0003
+
+ moveq 2,r3
+ move.d 0xffff0001,r4
+ or.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfedaffaf,r3
+ move.d 0xffffff5f,r4
+ or.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ or.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 7813f7db
+
+ moveq 1,r3
+ move.d 0xffffff02,r4
+ or.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ moveq 1,r4
+ or.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0x4a,r4
+ move.d 0xfa3,r3
+ or.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 feb
+
+ move.d 0x5432f789,r4
+ move.d 0x78134453,r3
+ or.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/src/tests/tcg/cris/check_ret.s b/src/tests/tcg/cris/check_ret.s
new file mode 100644
index 0000000..b44fb25
--- /dev/null
+++ b/src/tests/tcg/cris/check_ret.s
@@ -0,0 +1,25 @@
+# mach: crisv3 crisv8 crisv10
+# output: 3\n
+
+# Test that ret works.
+
+ .include "testutils.inc"
+ start
+x:
+ moveq 0,r3
+ jsr z
+w:
+ quit
+y:
+ addq 1,r3
+ checkr3 3
+ quit
+
+z:
+ addq 1,r3
+ move srp,r2
+ add.d y-w,r2
+ move r2,srp
+ ret
+ addq 1,r3
+ quit
diff --git a/src/tests/tcg/cris/check_scc.s b/src/tests/tcg/cris/check_scc.s
new file mode 100644
index 0000000..4a8674c
--- /dev/null
+++ b/src/tests/tcg/cris/check_scc.s
@@ -0,0 +1,95 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n0\n1\n0\n1\n0\n1\n0\n0\n1\n1\n0\n1\n0\n1\n0\n1\n0\n0\n1\n0\n1\n1\n0\n1\n0\n0\n1\n1\n0\n1\n1\n0\n
+
+ .include "testutils.inc"
+
+ .macro lcheckr3 v
+ move $ccs, $r9
+ checkr3 \v
+ move $r9, $ccs
+ .endm
+
+ start
+ clearf nzvc
+ scc r3
+ lcheckr3 1
+ scs r3
+ lcheckr3 0
+ sne r3
+ lcheckr3 1
+ seq r3
+ lcheckr3 0
+ svc r3
+ lcheckr3 1
+ svs r3
+ lcheckr3 0
+ spl r3
+ lcheckr3 1
+ smi r3
+ lcheckr3 0
+ sls r3
+ lcheckr3 0
+ shi r3
+ lcheckr3 1
+ sge r3
+ lcheckr3 1
+ slt r3
+ lcheckr3 0
+ sgt r3
+ lcheckr3 1
+ sle r3
+ lcheckr3 0
+ sa r3
+ lcheckr3 1
+ setf nzvc
+ scc r3
+ lcheckr3 0
+ scs r3
+ lcheckr3 1
+ sne r3
+ lcheckr3 0
+ svc r3
+ lcheckr3 0
+ svs r3
+ lcheckr3 1
+ spl r3
+ lcheckr3 0
+ smi r3
+ lcheckr3 1
+ sls r3
+ lcheckr3 1
+ shi r3
+ lcheckr3 0
+ sge r3
+ lcheckr3 1
+ slt r3
+ lcheckr3 0
+ sgt r3
+ lcheckr3 0
+ sle r3
+ lcheckr3 1
+ sa r3
+ lcheckr3 1
+ clearf n
+ sge r3
+ lcheckr3 0
+ slt r3
+ lcheckr3 1
+
+ .if 1 ;..asm.arch.cris.v32
+ setf p
+ ssb r3
+ .else
+ moveq 1,r3
+ .endif
+ lcheckr3 1
+
+ .if 1 ;..asm.arch.cris.v32
+ clearf p
+ ssb r3
+ .else
+ moveq 0,r3
+ .endif
+ lcheckr3 0
+
+ quit
diff --git a/src/tests/tcg/cris/check_settls1.c b/src/tests/tcg/cris/check_settls1.c
new file mode 100644
index 0000000..69d2026
--- /dev/null
+++ b/src/tests/tcg/cris/check_settls1.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/syscall.h>
+
+#ifndef SYS_set_thread_area
+#define SYS_set_thread_area 243
+#endif
+
+int main (void)
+{
+ unsigned long tp, old_tp;
+ int ret;
+
+ asm volatile ("move $pid,%0" : "=r" (old_tp));
+ old_tp &= ~0xff;
+
+ ret = syscall (SYS_set_thread_area, 0xf0);
+ if (ret != -1 || errno != EINVAL) {
+ syscall (SYS_set_thread_area, old_tp);
+ perror ("Invalid thread area accepted:");
+ abort();
+ }
+
+ ret = syscall (SYS_set_thread_area, 0xeddeed00);
+ if (ret != 0) {
+ perror ("Valid thread area not accepted: ");
+ abort ();
+ }
+
+ asm volatile ("move $pid,%0" : "=r" (tp));
+ tp &= ~0xff;
+ syscall (SYS_set_thread_area, old_tp);
+
+ if (tp != 0xeddeed00) {
+ * (volatile int *) 0 = 0;
+ perror ("tls2");
+ abort ();
+ }
+
+ printf ("pass\n");
+ return EXIT_SUCCESS;
+}
diff --git a/src/tests/tcg/cris/check_sigalrm.c b/src/tests/tcg/cris/check_sigalrm.c
new file mode 100644
index 0000000..39fa8d9
--- /dev/null
+++ b/src/tests/tcg/cris/check_sigalrm.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+#define MAGIC (0xdeadbeef)
+
+int s = 0;
+void sighandler(int sig)
+{
+ s = MAGIC;
+}
+
+int main(int argc, char **argv)
+{
+ int p;
+
+ p = getpid();
+ signal(SIGALRM, sighandler);
+ kill(p, SIGALRM);
+ if (s != MAGIC)
+ return EXIT_FAILURE;
+
+ printf ("passed\n");
+ return EXIT_SUCCESS;
+}
diff --git a/src/tests/tcg/cris/check_stat1.c b/src/tests/tcg/cris/check_stat1.c
new file mode 100644
index 0000000..2e2cae5
--- /dev/null
+++ b/src/tests/tcg/cris/check_stat1.c
@@ -0,0 +1,16 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main (void)
+{
+ struct stat buf;
+
+ if (stat (".", &buf) != 0
+ || !S_ISDIR (buf.st_mode))
+ abort ();
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_stat2.c b/src/tests/tcg/cris/check_stat2.c
new file mode 100644
index 0000000..e36172e
--- /dev/null
+++ b/src/tests/tcg/cris/check_stat2.c
@@ -0,0 +1,20 @@
+/*
+#notarget: cris*-*-elf
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main (void)
+{
+ struct stat buf;
+
+ if (lstat (".", &buf) != 0
+ || !S_ISDIR (buf.st_mode))
+ abort ();
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_stat3.c b/src/tests/tcg/cris/check_stat3.c
new file mode 100644
index 0000000..36a9d5d
--- /dev/null
+++ b/src/tests/tcg/cris/check_stat3.c
@@ -0,0 +1,25 @@
+/* Simulator options:
+#sim: --sysroot=@exedir@
+*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int main (int argc, char *argv[])
+{
+ char path[1024] = "/";
+ struct stat buf;
+
+ strncat(path, argv[0], sizeof(path) - 2);
+ if (stat (".", &buf) != 0
+ || !S_ISDIR (buf.st_mode))
+ abort ();
+ if (stat (path, &buf) != 0
+ || !S_ISREG (buf.st_mode))
+ abort ();
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_stat4.c b/src/tests/tcg/cris/check_stat4.c
new file mode 100644
index 0000000..04f21fe
--- /dev/null
+++ b/src/tests/tcg/cris/check_stat4.c
@@ -0,0 +1,27 @@
+/* Simulator options:
+#notarget: cris*-*-elf
+#sim: --sysroot=@exedir@
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int main (int argc, char *argv[])
+{
+ char path[1024] = "/";
+ struct stat buf;
+
+ strncat(path, argv[0], sizeof(path) - 2);
+ if (lstat (".", &buf) != 0
+ || !S_ISDIR (buf.st_mode))
+ abort ();
+ if (lstat (path, &buf) != 0
+ || !S_ISREG (buf.st_mode))
+ abort ();
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_subc.s b/src/tests/tcg/cris/check_subc.s
new file mode 100644
index 0000000..e34b544
--- /dev/null
+++ b/src/tests/tcg/cris/check_subc.s
@@ -0,0 +1,87 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n85649200\n
+
+ .include "testutils.inc"
+ start
+
+ moveq -1,r3
+ sub.d -2,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ moveq 2,r3
+ sub.d 1,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ sub.d -0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 1fffe
+
+ moveq -1,r3
+ sub.d 1,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ sub.d -0x5432f789,r3
+ test_cc 1 0 1 1
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ sub.w -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffff0001
+
+ moveq 2,r3
+ sub.w 1,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ sub.w 1,r3
+ test_cc 1 0 0 0
+ checkr3 fffe
+
+ move.d 0xfedaffff,r3
+ sub.w 1,r3
+ test_cc 1 0 0 0
+ checkr3 fedafffe
+
+ move.d 0x78134452,r3
+ sub.w 0x877,r3
+ test_cc 0 0 0 0
+ checkr3 78133bdb
+
+ moveq -1,r3
+ sub.b -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffffff01
+
+ moveq 2,r3
+ sub.b 1,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xff,r3
+ sub.b 1,r3
+ test_cc 1 0 0 0
+ checkr3 fe
+
+ move.d 0xfeda49ff,r3
+ sub.b 1,r3
+ test_cc 1 0 0 0
+ checkr3 feda49fe
+
+ move.d 0x78134452,r3
+ sub.b 0x77,r3
+ test_cc 1 0 0 1
+ checkr3 781344db
+
+ move.d 0x85649282,r3
+ sub.b 0x82,r3
+ test_cc 0 1 0 0
+ checkr3 85649200
+
+ quit
diff --git a/src/tests/tcg/cris/check_subm.s b/src/tests/tcg/cris/check_subm.s
new file mode 100644
index 0000000..e07ea02
--- /dev/null
+++ b/src/tests/tcg/cris/check_subm.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n85649200\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword -2,1,-0xffff,1,-0x5432f789
+ .word -2,1,1,0x877
+ .byte -2,1,0x77
+ .byte 0x22
+
+ start
+ moveq -1,r3
+ move.d x,r5
+ sub.d [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ moveq 2,r3
+ sub.d [r5],r3
+ test_cc 0 0 0 0
+ addq 4,r5
+ checkr3 1
+
+ move.d 0xffff,r3
+ sub.d [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1fffe
+
+ moveq -1,r3
+ sub.d [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ sub.d [r5+],r3
+ test_cc 1 0 1 1
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ sub.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 ffff0001
+
+ moveq 2,r3
+ sub.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ sub.w [r5],r3
+ test_cc 1 0 0 0
+ checkr3 fffe
+
+ move.d 0xfedaffff,r3
+ sub.w [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 fedafffe
+
+ move.d 0x78134452,r3
+ sub.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 78133bdb
+
+ moveq -1,r3
+ sub.b [r5],r3
+ test_cc 0 0 0 0
+ addq 1,r5
+ checkr3 ffffff01
+
+ moveq 2,r3
+ sub.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xff,r3
+ sub.b [r5],r3
+ test_cc 1 0 0 0
+ checkr3 fe
+
+ move.d 0xfeda49ff,r3
+ sub.b [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 feda49fe
+
+ move.d 0x78134452,r3
+ sub.b [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 781344db
+
+ move.d 0x85649222,r3
+ sub.b [r5],r3
+ test_cc 0 1 0 0
+ checkr3 85649200
+
+ quit
diff --git a/src/tests/tcg/cris/check_subq.s b/src/tests/tcg/cris/check_subq.s
new file mode 100644
index 0000000..9e34fa3
--- /dev/null
+++ b/src/tests/tcg/cris/check_subq.s
@@ -0,0 +1,52 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 0\nffffffff\nfffffffe\nffff\nff\n56788f9\n56788d9\n567889a\n0\n7ffffffc\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ subq 1,r3
+ test_cc 0 1 0 0
+ checkr3 0
+
+ subq 1,r3
+ test_cc 1 0 0 1
+ checkr3 ffffffff
+
+ subq 1,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d 0x10000,r3
+ subq 1,r3
+ test_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0x100,r3
+ subq 1,r3
+ test_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0x5678900,r3
+ subq 7,r3
+ test_cc 0 0 0 0
+ checkr3 56788f9
+
+ subq 32,r3
+ test_cc 0 0 0 0
+ checkr3 56788d9
+
+ subq 63,r3
+ test_cc 0 0 0 0
+ checkr3 567889a
+
+ move.d 34,r3
+ subq 34,r3
+ test_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x80000024,r3
+ subq 40,r3
+ test_cc 0 0 1 0
+ checkr3 7ffffffc
+
+ quit
diff --git a/src/tests/tcg/cris/check_subr.s b/src/tests/tcg/cris/check_subr.s
new file mode 100644
index 0000000..742fbc8
--- /dev/null
+++ b/src/tests/tcg/cris/check_subr.s
@@ -0,0 +1,102 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n85649200\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq -2,r4
+ sub.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ moveq 2,r3
+ moveq 1,r4
+ sub.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ move.d -0xffff,r4
+ sub.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1fffe
+
+ moveq 1,r4
+ moveq -1,r3
+ sub.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ sub.d r4,r3
+ test_cc 1 0 1 1
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ moveq -2,r4
+ sub.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffff0001
+
+ moveq 2,r3
+ moveq 1,r4
+ sub.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ move.d -0xffff,r4
+ sub.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffe
+
+ move.d 0xfedaffff,r3
+ move.d -0xfedaffff,r4
+ sub.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fedafffe
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ sub.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 78133bdb
+
+ moveq -1,r3
+ moveq -2,r4
+ sub.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffffff01
+
+ moveq 2,r3
+ moveq 1,r4
+ sub.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d -0xff,r4
+ move.d 0xff,r3
+ sub.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 fe
+
+ move.d -0xfeda49ff,r4
+ move.d 0xfeda49ff,r3
+ sub.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 feda49fe
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ sub.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 781344db
+
+ move.d 0x85649222,r3
+ move.d 0x77445622,r4
+ sub.b r4,r3
+ test_cc 0 1 0 0
+ checkr3 85649200
+
+ quit
diff --git a/src/tests/tcg/cris/check_swap.c b/src/tests/tcg/cris/check_swap.c
new file mode 100644
index 0000000..f851cbc
--- /dev/null
+++ b/src/tests/tcg/cris/check_swap.c
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+#define N 8
+#define W 4
+#define B 2
+#define R 1
+
+static inline int cris_swap(const int mode, int x)
+{
+ switch (mode)
+ {
+ case N: asm ("swapn\t%0\n" : "+r" (x) : "0" (x)); break;
+ case W: asm ("swapw\t%0\n" : "+r" (x) : "0" (x)); break;
+ case B: asm ("swapb\t%0\n" : "+r" (x) : "0" (x)); break;
+ case R: asm ("swapr\t%0\n" : "+r" (x) : "0" (x)); break;
+ case B|R: asm ("swapbr\t%0\n" : "+r" (x) : "0" (x)); break;
+ case W|R: asm ("swapwr\t%0\n" : "+r" (x) : "0" (x)); break;
+ case W|B: asm ("swapwb\t%0\n" : "+r" (x) : "0" (x)); break;
+ case W|B|R: asm ("swapwbr\t%0\n" : "+r" (x) : "0" (x)); break;
+ case N|R: asm ("swapnr\t%0\n" : "+r" (x) : "0" (x)); break;
+ case N|B: asm ("swapnb\t%0\n" : "+r" (x) : "0" (x)); break;
+ case N|B|R: asm ("swapnbr\t%0\n" : "+r" (x) : "0" (x)); break;
+ case N|W: asm ("swapnw\t%0\n" : "+r" (x) : "0" (x)); break;
+ default:
+ err();
+ break;
+ }
+ return x;
+}
+
+/* Made this a macro to be able to pick up the location of the errors. */
+#define verify_swap(mode, val, expected, n, z) \
+do { \
+ int r; \
+ cris_tst_cc_init(); \
+ r = cris_swap(mode, val); \
+ cris_tst_mov_cc(n, z); \
+ if (r != expected) \
+ err(); \
+} while(0)
+
+void check_swap(void)
+{
+ /* Some of these numbers are borrowed from GDB's cris sim
+ testsuite. */
+ if (cris_swap(N, 0) != 0xffffffff)
+ err();
+ if (cris_swap(W, 0x12345678) != 0x56781234)
+ err();
+ if (cris_swap(B, 0x12345678) != 0x34127856)
+ err();
+
+ verify_swap(R, 0x78134452, 0x1ec8224a, 0, 0);
+ verify_swap(B, 0x78134452, 0x13785244, 0, 0);
+ verify_swap(B|R, 0x78134452, 0xc81e4a22, 1, 0);
+ verify_swap(W, 0x78134452, 0x44527813, 0, 0);
+ verify_swap(W|R, 0x78134452, 0x224a1ec8, 0, 0);
+ verify_swap(W|B|R, 0x78134452, 0x4a22c81e, 0, 0);
+ verify_swap(N, 0x78134452, 0x87ecbbad, 1, 0);
+ verify_swap(N|R, 0x78134452, 0xe137ddb5, 1, 0);
+ verify_swap(N|B, 0x78134452, 0xec87adbb, 1, 0);
+ verify_swap(N|B|R, 0x78134452, 0x37e1b5dd, 0, 0);
+ verify_swap(N|W, 0x78134452, 0xbbad87ec, 1, 0);
+ verify_swap(N|B|R, 0xffffffff, 0, 0, 1);
+}
+
+int main(void)
+{
+ check_swap();
+ pass();
+ return 0;
+}
diff --git a/src/tests/tcg/cris/check_time1.c b/src/tests/tcg/cris/check_time1.c
new file mode 100644
index 0000000..3fcf0e1
--- /dev/null
+++ b/src/tests/tcg/cris/check_time1.c
@@ -0,0 +1,46 @@
+/* Basic time functionality test: check that milliseconds are
+ incremented for each syscall (does not work on host). */
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+#include <string.h>
+#include <stdlib.h>
+
+void err (const char *s)
+{
+ perror (s);
+ abort ();
+}
+
+int
+main (void)
+{
+ struct timeval t_m = {0, 0};
+ struct timezone t_z = {0, 0};
+ struct timeval t_m1 = {0, 0};
+ int i;
+
+ if (gettimeofday (&t_m, &t_z) != 0)
+ err ("gettimeofday");
+
+ for (i = 1; i < 10000; i++)
+ if (gettimeofday (&t_m1, NULL) != 0)
+ err ("gettimeofday 1");
+ else
+ if (t_m1.tv_sec * 1000000 + t_m1.tv_usec
+ != (t_m.tv_sec * 1000000 + t_m.tv_usec + i * 1000))
+ {
+ fprintf (stderr, "t0 (%ld, %ld), i %d, t1 (%ld, %ld)\n",
+ t_m.tv_sec, t_m.tv_usec, i, t_m1.tv_sec, t_m1.tv_usec);
+ abort ();
+ }
+
+ if (time (NULL) != t_m1.tv_sec)
+ {
+ fprintf (stderr, "time != gettod\n");
+ abort ();
+ }
+
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_time2.c b/src/tests/tcg/cris/check_time2.c
new file mode 100644
index 0000000..20b69b4
--- /dev/null
+++ b/src/tests/tcg/cris/check_time2.c
@@ -0,0 +1,18 @@
+/* CB_SYS_time doesn't implement the Linux time syscall; the return
+ value isn't written to the argument. */
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+ time_t x = (time_t) -1;
+ time_t t = time (&x);
+
+ if (t == (time_t) -1 || t != x)
+ abort ();
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/src/tests/tcg/cris/check_xarith.s b/src/tests/tcg/cris/check_xarith.s
new file mode 100644
index 0000000..80038b2
--- /dev/null
+++ b/src/tests/tcg/cris/check_xarith.s
@@ -0,0 +1,72 @@
+
+.include "testutils.inc"
+
+ start
+
+ moveq -1, $r0
+ moveq 0, $r1
+ addq 1, $r0
+ ax
+ addq 0, $r1
+
+ move.d $r0, $r3
+ checkr3 0
+ move.d $r1, $r3
+ checkr3 1
+
+ move.d 0, $r0
+ moveq -1, $r1
+ subq 1, $r0
+ ax
+ subq 0, $r1
+
+ move.d $r0, $r3
+ checkr3 ffffffff
+ move.d $r1, $r3
+ checkr3 fffffffe
+
+
+ moveq -1, $r0
+ moveq -1, $r1
+ cmpq -1, $r0
+ ax
+ cmpq -1, $r1
+ beq 1f
+ nop
+ fail
+1:
+ cmpq 0, $r0
+ ax
+ cmpq -1, $r1
+ bne 1f
+ nop
+ fail
+1:
+
+ ;; test for broken X sequence, run it several times.
+ moveq 8, $r0
+1:
+ moveq 0, $r3
+ move.d $r0, $r1
+ andq 1, $r1
+ lslq 4, $r1
+ moveq 1, $r2
+ or.d $r1, $r2
+ ba 2f
+ move $r2, $ccs
+2:
+ addq 0, $r3
+ move.d $r0, $r4
+ move.d $r1, $r5
+ move.d $r2, $r6
+ move.d $r3, $r7
+ lsrq 4, $r1
+ move.d $r1, $r8
+ xor $r1, $r3
+ checkr3 0
+ subq 1, $r0
+ bne 1b
+ nop
+
+ pass
+ quit
diff --git a/src/tests/tcg/cris/crisutils.h b/src/tests/tcg/cris/crisutils.h
new file mode 100644
index 0000000..3456b9d
--- /dev/null
+++ b/src/tests/tcg/cris/crisutils.h
@@ -0,0 +1,76 @@
+#ifndef CRISUTILS_H
+#define CRISUTILS_H 1
+
+static char *tst_cc_loc = NULL;
+
+#define cris_tst_cc_init() \
+do { tst_cc_loc = "test_cc failed at " CURRENT_LOCATION; } while(0)
+
+/* We need a real symbol to signal error. */
+void _err(void) {
+ if (!tst_cc_loc)
+ tst_cc_loc = "tst_cc_failed\n";
+ _fail(tst_cc_loc);
+}
+
+static inline void cris_tst_cc_n1(void)
+{
+ asm volatile ("bpl _err\n"
+ "nop\n");
+}
+static inline void cris_tst_cc_n0(void)
+{
+ asm volatile ("bmi _err\n"
+ "nop\n");
+}
+
+static inline void cris_tst_cc_z1(void)
+{
+ asm volatile ("bne _err\n"
+ "nop\n");
+}
+static inline void cris_tst_cc_z0(void)
+{
+ asm volatile ("beq _err\n"
+ "nop\n");
+}
+static inline void cris_tst_cc_v1(void)
+{
+ asm volatile ("bvc _err\n"
+ "nop\n");
+}
+static inline void cris_tst_cc_v0(void)
+{
+ asm volatile ("bvs _err\n"
+ "nop\n");
+}
+
+static inline void cris_tst_cc_c1(void)
+{
+ asm volatile ("bcc _err\n"
+ "nop\n");
+}
+static inline void cris_tst_cc_c0(void)
+{
+ asm volatile ("bcs _err\n"
+ "nop\n");
+}
+
+static inline void cris_tst_mov_cc(int n, int z)
+{
+ if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
+ if (z) cris_tst_cc_z1(); else cris_tst_cc_z0();
+ asm volatile ("" : : "g" (_err));
+}
+
+static inline void cris_tst_cc(const int n, const int z,
+ const int v, const int c)
+{
+ if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
+ if (z) cris_tst_cc_z1(); else cris_tst_cc_z0();
+ if (v) cris_tst_cc_v1(); else cris_tst_cc_v0();
+ if (c) cris_tst_cc_c1(); else cris_tst_cc_c0();
+ asm volatile ("" : : "g" (_err));
+}
+
+#endif
diff --git a/src/tests/tcg/cris/crt.s b/src/tests/tcg/cris/crt.s
new file mode 100644
index 0000000..af027d7
--- /dev/null
+++ b/src/tests/tcg/cris/crt.s
@@ -0,0 +1,13 @@
+ .data
+_stack_start:
+ .space 8192, 0
+_stack_end:
+ .text
+ .global _start
+_start:
+ move.d _stack_end, $sp
+ jsr main
+ nop
+ moveq 0, $r10
+ jump exit
+ nop
diff --git a/src/tests/tcg/cris/sys.c b/src/tests/tcg/cris/sys.c
new file mode 100644
index 0000000..551c5dd
--- /dev/null
+++ b/src/tests/tcg/cris/sys.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static inline int mystrlen(char *s) {
+ int i = 0;
+ while (s[i])
+ i++;
+ return i;
+}
+
+void pass(void) {
+ char s[] = "passed.\n";
+ write (1, s, sizeof (s) - 1);
+ exit (0);
+}
+
+void _fail(char *reason) {
+ char s[] = "\nfailed: ";
+ int len = mystrlen(reason);
+ write (1, s, sizeof (s) - 1);
+ write (1, reason, len);
+ write (1, "\n", 1);
+// exit (1);
+}
+
+void *memset (void *s, int c, size_t n) {
+ char *p = s;
+ int i;
+ for (i = 0; i < n; i++)
+ p[i] = c;
+ return p;
+}
+
+void exit (int status) {
+ asm volatile ("moveq 1, $r9\n" /* NR_exit. */
+ "break 13\n");
+ while(1)
+ ;
+}
+
+ssize_t write (int fd, const void *buf, size_t count) {
+ int r;
+ asm ("move.d %0, $r10\n"
+ "move.d %1, $r11\n"
+ "move.d %2, $r12\n"
+ "moveq 4, $r9\n" /* NR_write. */
+ "break 13\n" : : "r" (fd), "r" (buf), "r" (count) : "memory");
+ asm ("move.d $r10, %0\n" : "=r" (r));
+ return r;
+}
diff --git a/src/tests/tcg/cris/sys.h b/src/tests/tcg/cris/sys.h
new file mode 100644
index 0000000..c5f88e1
--- /dev/null
+++ b/src/tests/tcg/cris/sys.h
@@ -0,0 +1,16 @@
+#include <unistd.h>
+
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+
+#define CURRENT_LOCATION __FILE__ ":" TOSTRING(__LINE__)
+
+#define err() \
+{ \
+ _fail("at " CURRENT_LOCATION " "); \
+}
+
+#define mb() asm volatile ("" : : : "memory")
+
+void pass(void);
+void _fail(char *reason);
diff --git a/src/tests/tcg/cris/testutils.inc b/src/tests/tcg/cris/testutils.inc
new file mode 100644
index 0000000..aa1641b
--- /dev/null
+++ b/src/tests/tcg/cris/testutils.inc
@@ -0,0 +1,117 @@
+ .syntax no_register_prefix
+
+ .macro start
+ .text
+ .global main
+main:
+ .endm
+
+ .macro quit
+ jump pass
+ nop
+ .endm
+
+ .macro pass
+ jump pass
+ nop
+ .endm
+
+ .macro startnostack
+ start
+ .endm
+
+ .macro fail
+ .data
+99:
+ .asciz " checkr3 failed\n"
+ .text
+ move.d 99b, $r10
+ jsr _fail
+ nop
+ .endm
+
+ .macro checkr3 val
+ cmp.d 0x\val, $r3
+ beq 100f
+ nop
+ .data
+99:
+ .asciz "checkr3 failed\n"
+ .text
+ move.d 99b, $r10
+ jsr _fail
+ nop
+100:
+ .endm
+
+; Test the condition codes
+ .macro test_cc N Z V C
+ .if \N
+ bpl 9f
+ nop
+ .else
+ bmi 9f
+ nop
+ .endif
+ .if \Z
+ bne 9f
+ nop
+ .else
+ beq 9f
+ nop
+ .endif
+ .if \V
+ bvc 9f
+ nop
+ .else
+ bvs 9f
+ nop
+ .endif
+ .if \C
+ bcc 9f
+ nop
+ .else
+ bcs 9f
+ nop
+ .endif
+ ba 8f
+ nop
+9:
+ .data
+99:
+ .asciz "test_move_cc failed\n"
+ .text
+ move.d 99b, $r10
+ jsr _fail
+ nop
+8:
+ .endm
+
+
+ .macro test_move_cc N Z V C
+ .if \N
+ bpl 9f
+ nop
+ .else
+ bmi 9f
+ nop
+ .endif
+ .if \Z
+ bne 9f
+ nop
+ .else
+ beq 9f
+ nop
+ .endif
+ ba 8f
+ nop
+9:
+ .data
+99:
+ .asciz "test_move_cc failed\n"
+ .text
+ move.d 99b, $r10
+ jsr _fail
+ nop
+8:
+ .endm
diff --git a/src/tests/tcg/hello-arm.c b/src/tests/tcg/hello-arm.c
new file mode 100644
index 0000000..e0daa7a
--- /dev/null
+++ b/src/tests/tcg/hello-arm.c
@@ -0,0 +1,113 @@
+#define __NR_SYSCALL_BASE 0x900000
+#define __NR_exit1 (__NR_SYSCALL_BASE+ 1)
+#define __NR_write (__NR_SYSCALL_BASE+ 4)
+
+#define __sys2(x) #x
+#define __sys1(x) __sys2(x)
+
+#ifndef __syscall
+#define __syscall(name) "swi\t" __sys1(__NR_##name) "\n\t"
+#endif
+
+#define __syscall_return(type, res) \
+do { \
+ return (type) (res); \
+} while (0)
+
+#define _syscall0(type,name) \
+type name(void) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ __syscall(name) \
+ "mov %0,r0" \
+ :"=r" (__res) : : "r0","lr"); \
+ __syscall_return(type,__res); \
+}
+
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ __syscall(name) \
+ "mov %0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)) \
+ : "r0","lr"); \
+ __syscall_return(type,__res); \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1,type2 arg2) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ "mov\tr1,%2\n\t" \
+ __syscall(name) \
+ "mov\t%0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)),"r" ((long)(arg2)) \
+ : "r0","r1","lr"); \
+ __syscall_return(type,__res); \
+}
+
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1,type2 arg2,type3 arg3) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ "mov\tr1,%2\n\t" \
+ "mov\tr2,%3\n\t" \
+ __syscall(name) \
+ "mov\t%0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)) \
+ : "r0","r1","r2","lr"); \
+ __syscall_return(type,__res); \
+}
+
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ "mov\tr1,%2\n\t" \
+ "mov\tr2,%3\n\t" \
+ "mov\tr3,%4\n\t" \
+ __syscall(name) \
+ "mov\t%0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4)) \
+ : "r0","r1","r2","r3","lr"); \
+ __syscall_return(type,__res); \
+}
+
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ "mov\tr1,%2\n\t" \
+ "mov\tr2,%3\n\t" \
+ "mov\tr3,%4\n\t" \
+ "mov\tr4,%5\n\t" \
+ __syscall(name) \
+ "mov\t%0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4)), \
+ "r" ((long)(arg5)) \
+ : "r0","r1","r2","r3","r4","lr"); \
+ __syscall_return(type,__res); \
+}
+
+_syscall1(int,exit1,int,status);
+_syscall3(int,write,int,fd,const char *,buf, int, len);
+
+void _start(void)
+{
+ write(1, "Hello World\n", 12);
+ exit1(0);
+}
diff --git a/src/tests/tcg/hello-i386.c b/src/tests/tcg/hello-i386.c
new file mode 100644
index 0000000..fa00380
--- /dev/null
+++ b/src/tests/tcg/hello-i386.c
@@ -0,0 +1,27 @@
+#include <asm/unistd.h>
+
+static inline void exit(int status)
+{
+ int __res;
+ __asm__ volatile ("movl %%ecx,%%ebx\n"\
+ "int $0x80" \
+ : "=a" (__res) : "0" (__NR_exit),"c" ((long)(status)));
+}
+
+static inline int write(int fd, const char * buf, int len)
+{
+ int status;
+ __asm__ volatile ("pushl %%ebx\n"\
+ "movl %%esi,%%ebx\n"\
+ "int $0x80\n" \
+ "popl %%ebx\n"\
+ : "=a" (status) \
+ : "0" (__NR_write),"S" ((long)(fd)),"c" ((long)(buf)),"d" ((long)(len)));
+ return status;
+}
+
+void _start(void)
+{
+ write(1, "Hello World\n", 12);
+ exit(0);
+}
diff --git a/src/tests/tcg/hello-mips.c b/src/tests/tcg/hello-mips.c
new file mode 100644
index 0000000..f825673
--- /dev/null
+++ b/src/tests/tcg/hello-mips.c
@@ -0,0 +1,64 @@
+/*
+* MIPS o32 Linux syscall example
+*
+* http://www.linux-mips.org/wiki/RISC/os
+* http://www.linux-mips.org/wiki/MIPSABIHistory
+* http://www.linux.com/howtos/Assembly-HOWTO/mips.shtml
+*
+* mipsel-linux-gcc -nostdlib -mno-abicalls -fno-PIC -mabi=32 \
+* -O2 -static -o hello-mips hello-mips.c
+*
+*/
+#define __NR_SYSCALL_BASE 4000
+#define __NR_exit (__NR_SYSCALL_BASE+ 1)
+#define __NR_write (__NR_SYSCALL_BASE+ 4)
+
+static inline void exit1(int status)
+{
+ register unsigned long __a0 asm("$4") = (unsigned long) status;
+
+ __asm__ __volatile__ (
+ " .set push \n"
+ " .set noreorder \n"
+ " li $2, %0 \n"
+ " syscall \n"
+ " .set pop "
+ :
+ : "i" (__NR_exit), "r" (__a0)
+ : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24",
+ "memory");
+}
+
+static inline int write(int fd, const char *buf, int len)
+{
+ register unsigned long __a0 asm("$4") = (unsigned long) fd;
+ register unsigned long __a1 asm("$5") = (unsigned long) buf;
+ register unsigned long __a2 asm("$6") = (unsigned long) len;
+ register unsigned long __a3 asm("$7");
+ unsigned long __v0;
+
+ __asm__ __volatile__ (
+ " .set push \n"
+ " .set noreorder \n"
+ " li $2, %2 \n"
+ " syscall \n"
+ " move %0, $2 \n"
+ " .set pop "
+ : "=r" (__v0), "=r" (__a3)
+ : "i" (__NR_write), "r" (__a0), "r" (__a1), "r" (__a2)
+ : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24",
+ "memory");
+
+/* if (__a3 == 0) */
+ return (int) __v0;
+/*
+ errno = __v0;
+ return -1;
+ */
+}
+
+void __start(void)
+{
+ write (1, "Hello, World!\n", 14);
+ exit1 (42);
+}
diff --git a/src/tests/tcg/linux-test.c b/src/tests/tcg/linux-test.c
new file mode 100644
index 0000000..1c6c013
--- /dev/null
+++ b/src/tests/tcg/linux-test.c
@@ -0,0 +1,538 @@
+/*
+ * linux and CPU test
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#define _GNU_SOURCE
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <utime.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sched.h>
+#include <dirent.h>
+#include <setjmp.h>
+#include <sys/shm.h>
+
+#define TESTPATH "/tmp/linux-test.tmp"
+#define TESTPORT 7654
+#define STACK_SIZE 16384
+
+void error1(const char *filename, int line, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s:%d: ", filename, line);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ exit(1);
+}
+
+int __chk_error(const char *filename, int line, int ret)
+{
+ if (ret < 0) {
+ error1(filename, line, "%m (ret=%d, errno=%d)",
+ ret, errno);
+ }
+ return ret;
+}
+
+#define error(fmt, ...) error1(__FILE__, __LINE__, fmt, ## __VA_ARGS__)
+
+#define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret))
+
+/*******************************************************/
+
+#define FILE_BUF_SIZE 300
+
+void test_file(void)
+{
+ int fd, i, len, ret;
+ uint8_t buf[FILE_BUF_SIZE];
+ uint8_t buf2[FILE_BUF_SIZE];
+ uint8_t buf3[FILE_BUF_SIZE];
+ char cur_dir[1024];
+ struct stat st;
+ struct utimbuf tbuf;
+ struct iovec vecs[2];
+ DIR *dir;
+ struct dirent *de;
+
+ /* clean up, just in case */
+ unlink(TESTPATH "/file1");
+ unlink(TESTPATH "/file2");
+ unlink(TESTPATH "/file3");
+ rmdir(TESTPATH);
+
+ if (getcwd(cur_dir, sizeof(cur_dir)) == NULL)
+ error("getcwd");
+
+ chk_error(mkdir(TESTPATH, 0755));
+
+ chk_error(chdir(TESTPATH));
+
+ /* open/read/write/close/readv/writev/lseek */
+
+ fd = chk_error(open("file1", O_WRONLY | O_TRUNC | O_CREAT, 0644));
+ for(i=0;i < FILE_BUF_SIZE; i++)
+ buf[i] = i;
+ len = chk_error(write(fd, buf, FILE_BUF_SIZE / 2));
+ if (len != (FILE_BUF_SIZE / 2))
+ error("write");
+ vecs[0].iov_base = buf + (FILE_BUF_SIZE / 2);
+ vecs[0].iov_len = 16;
+ vecs[1].iov_base = buf + (FILE_BUF_SIZE / 2) + 16;
+ vecs[1].iov_len = (FILE_BUF_SIZE / 2) - 16;
+ len = chk_error(writev(fd, vecs, 2));
+ if (len != (FILE_BUF_SIZE / 2))
+ error("writev");
+ chk_error(close(fd));
+
+ chk_error(rename("file1", "file2"));
+
+ fd = chk_error(open("file2", O_RDONLY));
+
+ len = chk_error(read(fd, buf2, FILE_BUF_SIZE));
+ if (len != FILE_BUF_SIZE)
+ error("read");
+ if (memcmp(buf, buf2, FILE_BUF_SIZE) != 0)
+ error("memcmp");
+
+#define FOFFSET 16
+ ret = chk_error(lseek(fd, FOFFSET, SEEK_SET));
+ if (ret != 16)
+ error("lseek");
+ vecs[0].iov_base = buf3;
+ vecs[0].iov_len = 32;
+ vecs[1].iov_base = buf3 + 32;
+ vecs[1].iov_len = FILE_BUF_SIZE - FOFFSET - 32;
+ len = chk_error(readv(fd, vecs, 2));
+ if (len != FILE_BUF_SIZE - FOFFSET)
+ error("readv");
+ if (memcmp(buf + FOFFSET, buf3, FILE_BUF_SIZE - FOFFSET) != 0)
+ error("memcmp");
+
+ chk_error(close(fd));
+
+ /* access */
+ chk_error(access("file2", R_OK));
+
+ /* stat/chmod/utime/truncate */
+
+ chk_error(chmod("file2", 0600));
+ tbuf.actime = 1001;
+ tbuf.modtime = 1000;
+ chk_error(truncate("file2", 100));
+ chk_error(utime("file2", &tbuf));
+ chk_error(stat("file2", &st));
+ if (st.st_size != 100)
+ error("stat size");
+ if (!S_ISREG(st.st_mode))
+ error("stat mode");
+ if ((st.st_mode & 0777) != 0600)
+ error("stat mode2");
+ if (st.st_atime != 1001 ||
+ st.st_mtime != 1000)
+ error("stat time");
+
+ chk_error(stat(TESTPATH, &st));
+ if (!S_ISDIR(st.st_mode))
+ error("stat mode");
+
+ /* fstat */
+ fd = chk_error(open("file2", O_RDWR));
+ chk_error(ftruncate(fd, 50));
+ chk_error(fstat(fd, &st));
+ chk_error(close(fd));
+
+ if (st.st_size != 50)
+ error("stat size");
+ if (!S_ISREG(st.st_mode))
+ error("stat mode");
+
+ /* symlink/lstat */
+ chk_error(symlink("file2", "file3"));
+ chk_error(lstat("file3", &st));
+ if (!S_ISLNK(st.st_mode))
+ error("stat mode");
+
+ /* getdents */
+ dir = opendir(TESTPATH);
+ if (!dir)
+ error("opendir");
+ len = 0;
+ for(;;) {
+ de = readdir(dir);
+ if (!de)
+ break;
+ if (strcmp(de->d_name, ".") != 0 &&
+ strcmp(de->d_name, "..") != 0 &&
+ strcmp(de->d_name, "file2") != 0 &&
+ strcmp(de->d_name, "file3") != 0)
+ error("readdir");
+ len++;
+ }
+ closedir(dir);
+ if (len != 4)
+ error("readdir");
+
+ chk_error(unlink("file3"));
+ chk_error(unlink("file2"));
+ chk_error(chdir(cur_dir));
+ chk_error(rmdir(TESTPATH));
+}
+
+void test_fork(void)
+{
+ int pid, status;
+
+ pid = chk_error(fork());
+ if (pid == 0) {
+ /* child */
+ exit(2);
+ }
+ chk_error(waitpid(pid, &status, 0));
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 2)
+ error("waitpid status=0x%x", status);
+}
+
+void test_time(void)
+{
+ struct timeval tv, tv2;
+ struct timespec ts, rem;
+ struct rusage rusg1, rusg2;
+ int ti, i;
+
+ chk_error(gettimeofday(&tv, NULL));
+ rem.tv_sec = 1;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 20 * 1000000;
+ chk_error(nanosleep(&ts, &rem));
+ if (rem.tv_sec != 1)
+ error("nanosleep");
+ chk_error(gettimeofday(&tv2, NULL));
+ ti = tv2.tv_sec - tv.tv_sec;
+ if (ti >= 2)
+ error("gettimeofday");
+
+ chk_error(getrusage(RUSAGE_SELF, &rusg1));
+ for(i = 0;i < 10000; i++);
+ chk_error(getrusage(RUSAGE_SELF, &rusg2));
+ if ((rusg2.ru_utime.tv_sec - rusg1.ru_utime.tv_sec) < 0 ||
+ (rusg2.ru_stime.tv_sec - rusg1.ru_stime.tv_sec) < 0)
+ error("getrusage");
+}
+
+void pstrcpy(char *buf, int buf_size, const char *str)
+{
+ int c;
+ char *q = buf;
+
+ if (buf_size <= 0)
+ return;
+
+ for(;;) {
+ c = *str++;
+ if (c == 0 || q >= buf + buf_size - 1)
+ break;
+ *q++ = c;
+ }
+ *q = '\0';
+}
+
+/* strcat and truncate. */
+char *pstrcat(char *buf, int buf_size, const char *s)
+{
+ int len;
+ len = strlen(buf);
+ if (len < buf_size)
+ pstrcpy(buf + len, buf_size - len, s);
+ return buf;
+}
+
+int server_socket(void)
+{
+ int val, fd;
+ struct sockaddr_in sockaddr;
+
+ /* server socket */
+ fd = chk_error(socket(PF_INET, SOCK_STREAM, 0));
+
+ val = 1;
+ chk_error(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)));
+
+ sockaddr.sin_family = AF_INET;
+ sockaddr.sin_port = htons(TESTPORT);
+ sockaddr.sin_addr.s_addr = 0;
+ chk_error(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)));
+ chk_error(listen(fd, 0));
+ return fd;
+
+}
+
+int client_socket(void)
+{
+ int fd;
+ struct sockaddr_in sockaddr;
+
+ /* server socket */
+ fd = chk_error(socket(PF_INET, SOCK_STREAM, 0));
+ sockaddr.sin_family = AF_INET;
+ sockaddr.sin_port = htons(TESTPORT);
+ inet_aton("127.0.0.1", &sockaddr.sin_addr);
+ chk_error(connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)));
+ return fd;
+}
+
+const char socket_msg[] = "hello socket\n";
+
+void test_socket(void)
+{
+ int server_fd, client_fd, fd, pid, ret, val;
+ struct sockaddr_in sockaddr;
+ socklen_t len;
+ char buf[512];
+
+ server_fd = server_socket();
+
+ /* test a few socket options */
+ len = sizeof(val);
+ chk_error(getsockopt(server_fd, SOL_SOCKET, SO_TYPE, &val, &len));
+ if (val != SOCK_STREAM)
+ error("getsockopt");
+
+ pid = chk_error(fork());
+ if (pid == 0) {
+ client_fd = client_socket();
+ send(client_fd, socket_msg, sizeof(socket_msg), 0);
+ close(client_fd);
+ exit(0);
+ }
+ len = sizeof(sockaddr);
+ fd = chk_error(accept(server_fd, (struct sockaddr *)&sockaddr, &len));
+
+ ret = chk_error(recv(fd, buf, sizeof(buf), 0));
+ if (ret != sizeof(socket_msg))
+ error("recv");
+ if (memcmp(buf, socket_msg, sizeof(socket_msg)) != 0)
+ error("socket_msg");
+ chk_error(close(fd));
+ chk_error(close(server_fd));
+}
+
+#define WCOUNT_MAX 512
+
+void test_pipe(void)
+{
+ fd_set rfds, wfds;
+ int fds[2], fd_max, ret;
+ uint8_t ch;
+ int wcount, rcount;
+
+ chk_error(pipe(fds));
+ chk_error(fcntl(fds[0], F_SETFL, O_NONBLOCK));
+ chk_error(fcntl(fds[1], F_SETFL, O_NONBLOCK));
+ wcount = 0;
+ rcount = 0;
+ for(;;) {
+ FD_ZERO(&rfds);
+ fd_max = fds[0];
+ FD_SET(fds[0], &rfds);
+
+ FD_ZERO(&wfds);
+ FD_SET(fds[1], &wfds);
+ if (fds[1] > fd_max)
+ fd_max = fds[1];
+
+ ret = chk_error(select(fd_max + 1, &rfds, &wfds, NULL, NULL));
+ if (ret > 0) {
+ if (FD_ISSET(fds[0], &rfds)) {
+ chk_error(read(fds[0], &ch, 1));
+ rcount++;
+ if (rcount >= WCOUNT_MAX)
+ break;
+ }
+ if (FD_ISSET(fds[1], &wfds)) {
+ ch = 'a';
+ chk_error(write(fds[0], &ch, 1));
+ wcount++;
+ }
+ }
+ }
+ chk_error(close(fds[0]));
+ chk_error(close(fds[1]));
+}
+
+int thread1_res;
+int thread2_res;
+
+int thread1_func(void *arg)
+{
+ int i;
+ for(i=0;i<5;i++) {
+ thread1_res++;
+ usleep(10 * 1000);
+ }
+ return 0;
+}
+
+int thread2_func(void *arg)
+{
+ int i;
+ for(i=0;i<6;i++) {
+ thread2_res++;
+ usleep(10 * 1000);
+ }
+ return 0;
+}
+
+void test_clone(void)
+{
+ uint8_t *stack1, *stack2;
+ int pid1, pid2, status1, status2;
+
+ stack1 = malloc(STACK_SIZE);
+ pid1 = chk_error(clone(thread1_func, stack1 + STACK_SIZE,
+ CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello1"));
+
+ stack2 = malloc(STACK_SIZE);
+ pid2 = chk_error(clone(thread2_func, stack2 + STACK_SIZE,
+ CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello2"));
+
+ while (waitpid(pid1, &status1, 0) != pid1);
+ free(stack1);
+ while (waitpid(pid2, &status2, 0) != pid2);
+ free(stack2);
+ if (thread1_res != 5 ||
+ thread2_res != 6)
+ error("clone");
+}
+
+/***********************************/
+
+volatile int alarm_count;
+jmp_buf jmp_env;
+
+void sig_alarm(int sig)
+{
+ if (sig != SIGALRM)
+ error("signal");
+ alarm_count++;
+}
+
+void sig_segv(int sig, siginfo_t *info, void *puc)
+{
+ if (sig != SIGSEGV)
+ error("signal");
+ longjmp(jmp_env, 1);
+}
+
+void test_signal(void)
+{
+ struct sigaction act;
+ struct itimerval it, oit;
+
+ /* timer test */
+
+ alarm_count = 0;
+
+ act.sa_handler = sig_alarm;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ chk_error(sigaction(SIGALRM, &act, NULL));
+
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 10 * 1000;
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = 10 * 1000;
+ chk_error(setitimer(ITIMER_REAL, &it, NULL));
+ chk_error(getitimer(ITIMER_REAL, &oit));
+ if (oit.it_value.tv_sec != it.it_value.tv_sec ||
+ oit.it_value.tv_usec != it.it_value.tv_usec)
+ error("itimer");
+
+ while (alarm_count < 5) {
+ usleep(10 * 1000);
+ }
+
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = 0;
+ memset(&oit, 0xff, sizeof(oit));
+ chk_error(setitimer(ITIMER_REAL, &it, &oit));
+ if (oit.it_value.tv_sec != 0 ||
+ oit.it_value.tv_usec != 10 * 1000)
+ error("setitimer");
+
+ /* SIGSEGV test */
+ act.sa_sigaction = sig_segv;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+ chk_error(sigaction(SIGSEGV, &act, NULL));
+ if (setjmp(jmp_env) == 0) {
+ *(uint8_t *)0 = 0;
+ }
+
+ act.sa_handler = SIG_DFL;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ chk_error(sigaction(SIGSEGV, &act, NULL));
+}
+
+#define SHM_SIZE 32768
+
+void test_shm(void)
+{
+ void *ptr;
+ int shmid;
+
+ shmid = chk_error(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0777));
+ ptr = shmat(shmid, NULL, 0);
+ if (!ptr)
+ error("shmat");
+
+ memset(ptr, 0, SHM_SIZE);
+
+ chk_error(shmctl(shmid, IPC_RMID, 0));
+ chk_error(shmdt(ptr));
+}
+
+int main(int argc, char **argv)
+{
+ test_file();
+ test_fork();
+ test_time();
+ test_socket();
+ // test_clone();
+ test_signal();
+ test_shm();
+ return 0;
+}
diff --git a/src/tests/tcg/lm32/Makefile b/src/tests/tcg/lm32/Makefile
new file mode 100644
index 0000000..57e7363
--- /dev/null
+++ b/src/tests/tcg/lm32/Makefile
@@ -0,0 +1,106 @@
+-include ../../../config-host.mak
+
+CROSS=lm32-elf-
+
+SIM = qemu-system-lm32
+SIMFLAGS = -M lm32-evr -nographic -semihosting -net none -kernel
+
+CC = $(CROSS)gcc
+AS = $(CROSS)as
+AS = $(CC) -x assembler
+SIZE = $(CROSS)size
+LD = $(CC)
+OBJCOPY = $(CROSS)objcopy
+
+TSRC_PATH = $(SRC_PATH)/tests/tcg/lm32
+
+LDFLAGS = -T$(TSRC_PATH)/linker.ld
+ASFLAGS += -Wa,-I,$(TSRC_PATH)/
+
+CRT = crt.o
+HELPER = helper.o
+TESTCASES += test_add.tst
+TESTCASES += test_addi.tst
+TESTCASES += test_and.tst
+TESTCASES += test_andhi.tst
+TESTCASES += test_andi.tst
+TESTCASES += test_b.tst
+TESTCASES += test_be.tst
+TESTCASES += test_bg.tst
+TESTCASES += test_bge.tst
+TESTCASES += test_bgeu.tst
+TESTCASES += test_bgu.tst
+TESTCASES += test_bi.tst
+TESTCASES += test_bne.tst
+TESTCASES += test_break.tst
+TESTCASES += test_bret.tst
+TESTCASES += test_call.tst
+TESTCASES += test_calli.tst
+TESTCASES += test_cmpe.tst
+TESTCASES += test_cmpei.tst
+TESTCASES += test_cmpg.tst
+TESTCASES += test_cmpgi.tst
+TESTCASES += test_cmpge.tst
+TESTCASES += test_cmpgei.tst
+TESTCASES += test_cmpgeu.tst
+TESTCASES += test_cmpgeui.tst
+TESTCASES += test_cmpgu.tst
+TESTCASES += test_cmpgui.tst
+TESTCASES += test_cmpne.tst
+TESTCASES += test_cmpnei.tst
+TESTCASES += test_divu.tst
+TESTCASES += test_eret.tst
+TESTCASES += test_lb.tst
+TESTCASES += test_lbu.tst
+TESTCASES += test_lh.tst
+TESTCASES += test_lhu.tst
+TESTCASES += test_lw.tst
+TESTCASES += test_modu.tst
+TESTCASES += test_mul.tst
+TESTCASES += test_muli.tst
+TESTCASES += test_nor.tst
+TESTCASES += test_nori.tst
+TESTCASES += test_or.tst
+TESTCASES += test_ori.tst
+TESTCASES += test_orhi.tst
+#TESTCASES += test_rcsr.tst
+TESTCASES += test_ret.tst
+TESTCASES += test_sb.tst
+TESTCASES += test_scall.tst
+TESTCASES += test_sextb.tst
+TESTCASES += test_sexth.tst
+TESTCASES += test_sh.tst
+TESTCASES += test_sl.tst
+TESTCASES += test_sli.tst
+TESTCASES += test_sr.tst
+TESTCASES += test_sri.tst
+TESTCASES += test_sru.tst
+TESTCASES += test_srui.tst
+TESTCASES += test_sub.tst
+TESTCASES += test_sw.tst
+#TESTCASES += test_wcsr.tst
+TESTCASES += test_xnor.tst
+TESTCASES += test_xnori.tst
+TESTCASES += test_xor.tst
+TESTCASES += test_xori.tst
+
+all: build
+
+%.o: $(TSRC_PATH)/%.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+%.o: $(TSRC_PATH)/%.S
+ $(AS) $(ASFLAGS) -c $< -o $@
+
+%.tst: %.o $(TSRC_PATH)/macros.inc $(CRT) $(HELPER)
+ $(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $(HELPER) $< -o $@
+
+build: $(TESTCASES)
+
+check: $(TESTCASES:test_%.tst=check_%)
+
+check_%: test_%.tst
+ @$(SIM) $(SIMFLAGS) $<
+
+clean:
+ $(RM) -fr $(TESTCASES) $(CRT) $(HELPER)
diff --git a/src/tests/tcg/lm32/crt.S b/src/tests/tcg/lm32/crt.S
new file mode 100644
index 0000000..fc437a3
--- /dev/null
+++ b/src/tests/tcg/lm32/crt.S
@@ -0,0 +1,84 @@
+.text
+.global _start
+
+_start:
+_reset_handler:
+ xor r0, r0, r0
+ mvhi r1, hi(_start)
+ ori r1, r1, lo(_start)
+ wcsr eba, r1
+ wcsr deba, r1
+ mvhi sp, hi(_fstack)
+ ori sp, sp, lo(_fstack)
+ bi _main
+
+_breakpoint_handler:
+ ori r25, r25, 1
+ addi ra, ba, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
+_instruction_bus_error_handler:
+ ori r25, r25, 2
+ addi ra, ea, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
+_watchpoint_handler:
+ ori r25, r25, 4
+ addi ra, ba, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
+_data_bus_error_handler:
+ ori r25, r25, 8
+ addi ra, ea, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
+_divide_by_zero_handler:
+ ori r25, r25, 16
+ addi ra, ea, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
+_interrupt_handler:
+ ori r25, r25, 32
+ addi ra, ea, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
+_system_call_handler:
+ ori r25, r25, 64
+ addi ra, ea, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
diff --git a/src/tests/tcg/lm32/helper.S b/src/tests/tcg/lm32/helper.S
new file mode 100644
index 0000000..3351d41
--- /dev/null
+++ b/src/tests/tcg/lm32/helper.S
@@ -0,0 +1,65 @@
+.text
+.global _start, _write, _exit
+.global _tc_fail, _tc_pass
+
+_write:
+ addi sp, sp, -4
+ sw (sp+4), r8
+ mvi r8, 5
+ scall
+ lw r8, (sp+4)
+ addi sp, sp, 4
+ ret
+
+_exit:
+ mvi r8, 1
+ scall
+1:
+ bi 1b
+
+_tc_pass:
+.data
+1:
+ .ascii "OK\n"
+2:
+.text
+ addi sp, sp, -16
+ sw (sp+4), ra
+ sw (sp+8), r1
+ sw (sp+12), r2
+ sw (sp+16), r3
+ mvi r1, 1
+ mvhi r2, hi(1b)
+ ori r2, r2, lo(1b)
+ mvi r3, (2b - 1b)
+ calli _write
+ lw r3, (sp+16)
+ lw r2, (sp+12)
+ lw r1, (sp+8)
+ lw ra, (sp+4)
+ addi sp, sp, 16
+ ret
+
+_tc_fail:
+.data
+1:
+ .ascii "FAILED\n"
+2:
+.text
+ addi sp, sp, -16
+ sw (sp+4), ra
+ sw (sp+8), r1
+ sw (sp+12), r2
+ sw (sp+16), r3
+ sw (sp+4), ra
+ mvi r1, 1
+ mvhi r2, hi(1b)
+ ori r2, r2, lo(1b)
+ mvi r3, (2b - 1b)
+ calli _write
+ lw r3, (sp+16)
+ lw r2, (sp+12)
+ lw r1, (sp+8)
+ lw ra, (sp+4)
+ addi sp, sp, 16
+ ret
diff --git a/src/tests/tcg/lm32/linker.ld b/src/tests/tcg/lm32/linker.ld
new file mode 100644
index 0000000..52d43a4
--- /dev/null
+++ b/src/tests/tcg/lm32/linker.ld
@@ -0,0 +1,55 @@
+OUTPUT_FORMAT("elf32-lm32")
+ENTRY(_start)
+
+__DYNAMIC = 0;
+
+MEMORY {
+ ram : ORIGIN = 0x08000000, LENGTH = 0x04000000 /* 64M */
+}
+
+SECTIONS
+{
+ .text :
+ {
+ _ftext = .;
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ _etext = .;
+ } > ram
+
+ .rodata :
+ {
+ . = ALIGN(4);
+ _frodata = .;
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.rodata1)
+ _erodata = .;
+ } > ram
+
+ .data :
+ {
+ . = ALIGN(4);
+ _fdata = .;
+ *(.data .data.* .gnu.linkonce.d.*)
+ *(.data1)
+ _gp = ALIGN(16);
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ _edata = .;
+ } > ram
+
+ .bss :
+ {
+ . = ALIGN(4);
+ _fbss = .;
+ *(.dynsbss)
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ _ebss = .;
+ _end = .;
+ } > ram
+}
+
+PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4);
+
diff --git a/src/tests/tcg/lm32/macros.inc b/src/tests/tcg/lm32/macros.inc
new file mode 100644
index 0000000..360ad53
--- /dev/null
+++ b/src/tests/tcg/lm32/macros.inc
@@ -0,0 +1,90 @@
+
+.equ MAX_TESTNAME_LEN, 32
+.macro test_name name
+ .data
+tn_\name:
+ .ascii "\name"
+ .space MAX_TESTNAME_LEN - (. - tn_\name), ' '
+ .text
+ .global \name
+\name:
+ addi sp, sp, -12
+ sw (sp+4), r1
+ sw (sp+8), r2
+ sw (sp+12), r3
+ mvi r1, 1
+ mvhi r2, hi(tn_\name)
+ ori r2, r2, lo(tn_\name)
+ mvi r3, MAX_TESTNAME_LEN
+ calli _write
+ lw r3, (sp+12)
+ lw r2, (sp+8)
+ lw r1, (sp+4)
+ addi sp, sp, 12
+.endm
+
+.macro load reg val
+ mvhi \reg, hi(\val)
+ ori \reg, \reg, lo(\val)
+.endm
+
+.macro tc_pass
+ calli _tc_pass
+.endm
+
+.macro tc_fail
+ addi r12, r12, 1
+ calli _tc_fail
+.endm
+
+.macro check_r3 val
+ mvhi r13, hi(\val)
+ ori r13, r13, lo(\val)
+ be r3, r13, 1f
+ tc_fail
+ bi 2f
+1:
+ tc_pass
+2:
+.endm
+
+.macro check_mem adr val
+ mvhi r13, hi(\adr)
+ ori r13, r13, lo(\adr)
+ mvhi r14, hi(\val)
+ ori r14, r14, lo(\val)
+ lw r13, (r13+0)
+ be r13, r14, 1f
+ tc_fail
+ bi 2f
+1:
+ tc_pass
+2:
+.endm
+
+.macro check_excp excp
+ andi r13, r25, \excp
+ bne r13, r0, 1f
+ tc_fail
+ bi 2f
+1:
+ tc_pass
+2:
+.endm
+
+.macro start
+ .global _main
+ .text
+_main:
+ mvi r12, 0
+.endm
+
+.macro end
+ mv r1, r12
+ calli _exit
+.endm
+
+# base +
+# 0 ctrl
+# 4 pass/fail
+# 8 ptr to test name
diff --git a/src/tests/tcg/lm32/test_add.S b/src/tests/tcg/lm32/test_add.S
new file mode 100644
index 0000000..030ad19
--- /dev/null
+++ b/src/tests/tcg/lm32/test_add.S
@@ -0,0 +1,75 @@
+.include "macros.inc"
+
+start
+
+test_name ADD_1
+mvi r1, 0
+mvi r2, 0
+add r3, r1, r2
+check_r3 0
+
+test_name ADD_2
+mvi r1, 0
+mvi r2, 1
+add r3, r1, r2
+check_r3 1
+
+test_name ADD_3
+mvi r1, 1
+mvi r2, 0
+add r3, r1, r2
+check_r3 1
+
+test_name ADD_4
+mvi r1, 1
+mvi r2, -1
+add r3, r1, r2
+check_r3 0
+
+test_name ADD_5
+mvi r1, -1
+mvi r2, 1
+add r3, r1, r2
+check_r3 0
+
+test_name ADD_6
+mvi r1, -1
+mvi r2, 0
+add r3, r1, r2
+check_r3 -1
+
+test_name ADD_7
+mvi r1, 0
+mvi r2, -1
+add r3, r1, r2
+check_r3 -1
+
+test_name ADD_8
+mvi r3, 2
+add r3, r3, r3
+check_r3 4
+
+test_name ADD_9
+mvi r1, 4
+mvi r3, 2
+add r3, r1, r3
+check_r3 6
+
+test_name ADD_10
+mvi r1, 4
+mvi r3, 2
+add r3, r3, r1
+check_r3 6
+
+test_name ADD_11
+mvi r1, 4
+add r3, r1, r1
+check_r3 8
+
+test_name ADD_12
+load r1 0x12345678
+load r2 0xabcdef97
+add r3, r1, r2
+check_r3 0xbe02460f
+
+end
diff --git a/src/tests/tcg/lm32/test_addi.S b/src/tests/tcg/lm32/test_addi.S
new file mode 100644
index 0000000..68e766d
--- /dev/null
+++ b/src/tests/tcg/lm32/test_addi.S
@@ -0,0 +1,56 @@
+.include "macros.inc"
+
+start
+
+test_name ADDI_1
+mvi r1, 0
+addi r3, r1, 0
+check_r3 0
+
+test_name ADDI_2
+mvi r1, 0
+addi r3, r1, 1
+check_r3 1
+
+test_name ADDI_3
+mvi r1, 1
+addi r3, r1, 0
+check_r3 1
+
+test_name ADDI_4
+mvi r1, 1
+addi r3, r1, -1
+check_r3 0
+
+test_name ADDI_5
+mvi r1, -1
+addi r3, r1, 1
+check_r3 0
+
+test_name ADDI_6
+mvi r1, -1
+addi r3, r1, 0
+check_r3 -1
+
+test_name ADDI_7
+mvi r1, 0
+addi r3, r1, -1
+check_r3 -1
+
+test_name ADDI_8
+mvi r3, 4
+addi r3, r3, 4
+check_r3 8
+
+test_name ADDI_9
+mvi r3, 4
+addi r3, r3, -4
+check_r3 0
+
+test_name ADDI_10
+mvi r3, 4
+addi r3, r3, -5
+check_r3 -1
+
+end
+
diff --git a/src/tests/tcg/lm32/test_and.S b/src/tests/tcg/lm32/test_and.S
new file mode 100644
index 0000000..80962ce
--- /dev/null
+++ b/src/tests/tcg/lm32/test_and.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name AND_1
+mvi r1, 0
+mvi r2, 0
+and r3, r1, r2
+check_r3 0
+
+test_name AND_2
+mvi r1, 0
+mvi r2, 1
+and r3, r1, r2
+check_r3 0
+
+test_name AND_3
+mvi r1, 1
+mvi r2, 1
+and r3, r1, r2
+check_r3 1
+
+test_name AND_4
+mvi r3, 7
+and r3, r3, r3
+check_r3 7
+
+test_name AND_5
+mvi r1, 7
+and r3, r1, r1
+check_r3 7
+
+test_name AND_6
+mvi r1, 7
+mvi r3, 0
+and r3, r1, r3
+check_r3 0
+
+test_name AND_7
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+and r3, r1, r2
+check_r3 0
+
+end
diff --git a/src/tests/tcg/lm32/test_andhi.S b/src/tests/tcg/lm32/test_andhi.S
new file mode 100644
index 0000000..4f73af5
--- /dev/null
+++ b/src/tests/tcg/lm32/test_andhi.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ANDHI_1
+mvi r1, 0
+andhi r3, r1, 0
+check_r3 0
+
+test_name ANDHI_2
+mvi r1, 1
+andhi r3, r1, 1
+check_r3 0
+
+test_name ANDHI_3
+load r1 0x000f0000
+andhi r3, r1, 1
+check_r3 0x00010000
+
+test_name ANDHI_4
+load r1 0xffffffff
+andhi r3, r1, 0xffff
+check_r3 0xffff0000
+
+test_name ANDHI_5
+load r1 0xffffffff
+andhi r3, r1, 0
+check_r3 0
+
+test_name ANDHI_6
+load r3 0x55aaffff
+andhi r3, r3, 0xaaaa
+check_r3 0x00aa0000
+
+end
diff --git a/src/tests/tcg/lm32/test_andi.S b/src/tests/tcg/lm32/test_andi.S
new file mode 100644
index 0000000..da1b0a3
--- /dev/null
+++ b/src/tests/tcg/lm32/test_andi.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ANDI_1
+mvi r1, 0
+andi r3, r1, 0
+check_r3 0
+
+test_name ANDI_2
+mvi r1, 1
+andi r3, r1, 1
+check_r3 1
+
+test_name ANDI_3
+load r1 0x000f0000
+andi r3, r1, 1
+check_r3 0
+
+test_name ANDI_4
+load r1 0xffffffff
+andi r3, r1, 0xffff
+check_r3 0xffff
+
+test_name ANDI_5
+load r1 0xffffffff
+andi r3, r1, 0
+check_r3 0
+
+test_name ANDI_6
+load r3 0xffff55aa
+andi r3, r3, 0xaaaa
+check_r3 0x000000aa
+
+end
diff --git a/src/tests/tcg/lm32/test_b.S b/src/tests/tcg/lm32/test_b.S
new file mode 100644
index 0000000..98172d8
--- /dev/null
+++ b/src/tests/tcg/lm32/test_b.S
@@ -0,0 +1,13 @@
+.include "macros.inc"
+
+start
+
+test_name B_1
+load r1 jump
+b r1
+tc_fail
+end
+
+jump:
+tc_pass
+end
diff --git a/src/tests/tcg/lm32/test_be.S b/src/tests/tcg/lm32/test_be.S
new file mode 100644
index 0000000..635caba
--- /dev/null
+++ b/src/tests/tcg/lm32/test_be.S
@@ -0,0 +1,48 @@
+.include "macros.inc"
+
+start
+
+test_name BE_1
+mvi r1, 0
+mvi r2, 0
+be r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BE_2
+mvi r1, 1
+mvi r2, 0
+be r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BE_3
+mvi r1, 0
+mvi r2, 1
+be r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BE_4
+mvi r1, 1
+mvi r2, 1
+be r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/src/tests/tcg/lm32/test_bg.S b/src/tests/tcg/lm32/test_bg.S
new file mode 100644
index 0000000..81823c2
--- /dev/null
+++ b/src/tests/tcg/lm32/test_bg.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BG_1
+mvi r1, 0
+mvi r2, 0
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BG_2
+mvi r1, 1
+mvi r2, 0
+bg r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BG_3
+mvi r1, 0
+mvi r2, 1
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BG_4
+mvi r1, 0
+mvi r2, -1
+bg r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BG_5
+mvi r1, -1
+mvi r2, 0
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BG_6
+mvi r1, -1
+mvi r2, -1
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BG_7
+mvi r1, 1
+mvi r2, 0
+bg r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/src/tests/tcg/lm32/test_bge.S b/src/tests/tcg/lm32/test_bge.S
new file mode 100644
index 0000000..6684d15
--- /dev/null
+++ b/src/tests/tcg/lm32/test_bge.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BGE_1
+mvi r1, 0
+mvi r2, 0
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGE_2
+mvi r1, 1
+mvi r2, 0
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGE_3
+mvi r1, 0
+mvi r2, 1
+bge r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGE_4
+mvi r1, 0
+mvi r2, -1
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGE_5
+mvi r1, -1
+mvi r2, 0
+bge r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGE_6
+mvi r1, -1
+mvi r2, -1
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BGE_7
+mvi r1, 1
+mvi r2, 0
+bge r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/src/tests/tcg/lm32/test_bgeu.S b/src/tests/tcg/lm32/test_bgeu.S
new file mode 100644
index 0000000..be44030
--- /dev/null
+++ b/src/tests/tcg/lm32/test_bgeu.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BGEU_1
+mvi r1, 0
+mvi r2, 0
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGEU_2
+mvi r1, 1
+mvi r2, 0
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGEU_3
+mvi r1, 0
+mvi r2, 1
+bgeu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGEU_4
+mvi r1, 0
+mvi r2, -1
+bgeu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGEU_5
+mvi r1, -1
+mvi r2, 0
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGEU_6
+mvi r1, -1
+mvi r2, -1
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BGEU_7
+mvi r1, 1
+mvi r2, 0
+bgeu r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/src/tests/tcg/lm32/test_bgu.S b/src/tests/tcg/lm32/test_bgu.S
new file mode 100644
index 0000000..8cc695b
--- /dev/null
+++ b/src/tests/tcg/lm32/test_bgu.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BGU_1
+mvi r1, 0
+mvi r2, 0
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGU_2
+mvi r1, 1
+mvi r2, 0
+bgu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGU_3
+mvi r1, 0
+mvi r2, 1
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGU_4
+mvi r1, 0
+mvi r2, -1
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGU_5
+mvi r1, -1
+mvi r2, 0
+bgu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGU_6
+mvi r1, -1
+mvi r2, -1
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BGU_7
+mvi r1, 1
+mvi r2, 0
+bgu r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/src/tests/tcg/lm32/test_bi.S b/src/tests/tcg/lm32/test_bi.S
new file mode 100644
index 0000000..a1fbd6f
--- /dev/null
+++ b/src/tests/tcg/lm32/test_bi.S
@@ -0,0 +1,23 @@
+.include "macros.inc"
+
+start
+
+test_name BI_1
+bi jump
+tc_fail
+end
+
+jump_back:
+tc_pass
+end
+
+jump:
+tc_pass
+
+test_name BI_2
+bi jump_back
+tc_fail
+
+end
+
+
diff --git a/src/tests/tcg/lm32/test_bne.S b/src/tests/tcg/lm32/test_bne.S
new file mode 100644
index 0000000..871a006
--- /dev/null
+++ b/src/tests/tcg/lm32/test_bne.S
@@ -0,0 +1,48 @@
+.include "macros.inc"
+
+start
+
+test_name BNE_1
+mvi r1, 0
+mvi r2, 0
+bne r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BNE_2
+mvi r1, 1
+mvi r2, 0
+bne r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BNE_3
+mvi r1, 0
+mvi r2, 1
+bne r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+bi 2f
+1:
+tc_fail
+bi 3f
+2:
+test_name BNE_4
+mvi r1, 1
+mvi r2, 1
+bne r1, r2, 1b
+tc_pass
+3:
+
+end
+
diff --git a/src/tests/tcg/lm32/test_break.S b/src/tests/tcg/lm32/test_break.S
new file mode 100644
index 0000000..0384fc6
--- /dev/null
+++ b/src/tests/tcg/lm32/test_break.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name BREAK_1
+mvi r1, 1
+wcsr IE, r1
+insn:
+break
+check_excp 1
+
+test_name BREAK_2
+mv r3, ba
+check_r3 insn
+
+test_name BREAK_3
+rcsr r3, IE
+check_r3 4
+
+end
diff --git a/src/tests/tcg/lm32/test_bret.S b/src/tests/tcg/lm32/test_bret.S
new file mode 100644
index 0000000..645210e
--- /dev/null
+++ b/src/tests/tcg/lm32/test_bret.S
@@ -0,0 +1,38 @@
+.include "macros.inc"
+
+start
+
+test_name BRET_1
+mvi r1, 4
+wcsr IE, r1
+load ba mark
+bret
+tc_fail
+bi 1f
+
+mark:
+tc_pass
+
+1:
+test_name BRET_2
+rcsr r3, IE
+check_r3 5
+
+test_name BRET_3
+mvi r1, 0
+wcsr IE, r1
+load ba mark2
+bret
+tc_fail
+bi 1f
+
+mark2:
+tc_pass
+
+1:
+test_name BRET_4
+rcsr r3, IE
+check_r3 0
+
+end
+
diff --git a/src/tests/tcg/lm32/test_call.S b/src/tests/tcg/lm32/test_call.S
new file mode 100644
index 0000000..1b91a5f
--- /dev/null
+++ b/src/tests/tcg/lm32/test_call.S
@@ -0,0 +1,16 @@
+.include "macros.inc"
+
+start
+
+test_name CALL_1
+load r1 mark
+call r1
+return:
+
+tc_fail
+end
+
+mark:
+mv r3, ra
+check_r3 return
+end
diff --git a/src/tests/tcg/lm32/test_calli.S b/src/tests/tcg/lm32/test_calli.S
new file mode 100644
index 0000000..1d87ae6
--- /dev/null
+++ b/src/tests/tcg/lm32/test_calli.S
@@ -0,0 +1,15 @@
+.include "macros.inc"
+
+start
+
+test_name CALLI_1
+calli mark
+return:
+
+tc_fail
+end
+
+mark:
+mv r3, ra
+check_r3 return
+end
diff --git a/src/tests/tcg/lm32/test_cmpe.S b/src/tests/tcg/lm32/test_cmpe.S
new file mode 100644
index 0000000..60a8855
--- /dev/null
+++ b/src/tests/tcg/lm32/test_cmpe.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name CMPE_1
+mvi r1, 0
+mvi r2, 0
+cmpe r3, r1, r2
+check_r3 1
+
+test_name CMPE_2
+mvi r1, 0
+mvi r2, 1
+cmpe r3, r1, r2
+check_r3 0
+
+test_name CMPE_3
+mvi r1, 1
+mvi r2, 0
+cmpe r3, r1, r2
+check_r3 0
+
+test_name CMPE_4
+mvi r3, 0
+mvi r2, 1
+cmpe r3, r3, r2
+check_r3 0
+
+test_name CMPE_5
+mvi r3, 0
+mvi r2, 0
+cmpe r3, r3, r2
+check_r3 1
+
+test_name CMPE_6
+mvi r3, 0
+cmpe r3, r3, r3
+check_r3 1
+
+end
diff --git a/src/tests/tcg/lm32/test_cmpei.S b/src/tests/tcg/lm32/test_cmpei.S
new file mode 100644
index 0000000..c3d3566
--- /dev/null
+++ b/src/tests/tcg/lm32/test_cmpei.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name CMPEI_1
+mvi r1, 0
+cmpei r3, r1, 0
+check_r3 1
+
+test_name CMPEI_2
+mvi r1, 0
+cmpei r3, r1, 1
+check_r3 0
+
+test_name CMPEI_3
+mvi r1, 1
+cmpei r3, r1, 0
+check_r3 0
+
+test_name CMPEI_4
+load r1 0xffffffff
+cmpei r3, r1, -1
+check_r3 1
+
+test_name CMPEI_5
+mvi r3, 0
+cmpei r3, r3, 0
+check_r3 1
+
+test_name CMPEI_6
+mvi r3, 0
+cmpei r3, r3, 1
+check_r3 0
+
+end
diff --git a/src/tests/tcg/lm32/test_cmpg.S b/src/tests/tcg/lm32/test_cmpg.S
new file mode 100644
index 0000000..0124078
--- /dev/null
+++ b/src/tests/tcg/lm32/test_cmpg.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPG_1
+mvi r1, 0
+mvi r2, 0
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_2
+mvi r1, 0
+mvi r2, 1
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_3
+mvi r1, 1
+mvi r2, 0
+cmpg r3, r1, r2
+check_r3 1
+
+test_name CMPG_4
+mvi r1, 1
+mvi r2, 1
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_5
+mvi r1, 0
+mvi r2, -1
+cmpg r3, r1, r2
+check_r3 1
+
+test_name CMPG_6
+mvi r1, -1
+mvi r2, 0
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_7
+mvi r1, -1
+mvi r2, -1
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_8
+mvi r3, 0
+mvi r2, 1
+cmpg r3, r3, r2
+check_r3 0
+
+test_name CMPG_9
+mvi r3, 1
+mvi r2, 0
+cmpg r3, r3, r2
+check_r3 1
+
+test_name CMPG_10
+mvi r3, 0
+cmpg r3, r3, r3
+check_r3 0
+
+end
diff --git a/src/tests/tcg/lm32/test_cmpge.S b/src/tests/tcg/lm32/test_cmpge.S
new file mode 100644
index 0000000..84620a0
--- /dev/null
+++ b/src/tests/tcg/lm32/test_cmpge.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGE_1
+mvi r1, 0
+mvi r2, 0
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_2
+mvi r1, 0
+mvi r2, 1
+cmpge r3, r1, r2
+check_r3 0
+
+test_name CMPGE_3
+mvi r1, 1
+mvi r2, 0
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_4
+mvi r1, 1
+mvi r2, 1
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_5
+mvi r1, 0
+mvi r2, -1
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_6
+mvi r1, -1
+mvi r2, 0
+cmpge r3, r1, r2
+check_r3 0
+
+test_name CMPGE_7
+mvi r1, -1
+mvi r2, -1
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_8
+mvi r3, 0
+mvi r2, 1
+cmpge r3, r3, r2
+check_r3 0
+
+test_name CMPGE_9
+mvi r3, 1
+mvi r2, 0
+cmpge r3, r3, r2
+check_r3 1
+
+test_name CMPGE_10
+mvi r3, 0
+cmpge r3, r3, r3
+check_r3 1
+
+end
diff --git a/src/tests/tcg/lm32/test_cmpgei.S b/src/tests/tcg/lm32/test_cmpgei.S
new file mode 100644
index 0000000..6e388a2
--- /dev/null
+++ b/src/tests/tcg/lm32/test_cmpgei.S
@@ -0,0 +1,70 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGEI_1
+mvi r1, 0
+cmpgei r3, r1, 0
+check_r3 1
+
+test_name CMPGEI_2
+mvi r1, 0
+cmpgei r3, r1, 1
+check_r3 0
+
+test_name CMPGEI_3
+mvi r1, 1
+cmpgei r3, r1, 0
+check_r3 1
+
+test_name CMPGEI_4
+mvi r1, 1
+cmpgei r3, r1, 1
+check_r3 1
+
+test_name CMPGEI_5
+mvi r1, 0
+cmpgei r3, r1, -1
+check_r3 1
+
+test_name CMPGEI_6
+mvi r1, -1
+cmpgei r3, r1, 0
+check_r3 0
+
+test_name CMPGEI_7
+mvi r1, -1
+cmpgei r3, r1, -1
+check_r3 1
+
+test_name CMPGEI_8
+mvi r3, 0
+cmpgei r3, r3, 1
+check_r3 0
+
+test_name CMPGEI_9
+mvi r3, 1
+cmpgei r3, r3, 0
+check_r3 1
+
+test_name CMPGEI_10
+mvi r3, 0
+cmpgei r3, r3, 0
+check_r3 1
+
+test_name CMPGEI_11
+mvi r1, 0
+cmpgei r3, r1, -32768
+check_r3 1
+
+test_name CMPGEI_12
+mvi r1, -1
+cmpgei r3, r1, -32768
+check_r3 1
+
+test_name CMPGEI_13
+mvi r1, -32768
+cmpgei r3, r1, -32768
+check_r3 1
+
+end
diff --git a/src/tests/tcg/lm32/test_cmpgeu.S b/src/tests/tcg/lm32/test_cmpgeu.S
new file mode 100644
index 0000000..2110ccb
--- /dev/null
+++ b/src/tests/tcg/lm32/test_cmpgeu.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGEU_1
+mvi r1, 0
+mvi r2, 0
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_2
+mvi r1, 0
+mvi r2, 1
+cmpgeu r3, r1, r2
+check_r3 0
+
+test_name CMPGEU_3
+mvi r1, 1
+mvi r2, 0
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_4
+mvi r1, 1
+mvi r2, 1
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_5
+mvi r1, 0
+mvi r2, -1
+cmpgeu r3, r1, r2
+check_r3 0
+
+test_name CMPGEU_6
+mvi r1, -1
+mvi r2, 0
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_7
+mvi r1, -1
+mvi r2, -1
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_8
+mvi r3, 0
+mvi r2, 1
+cmpgeu r3, r3, r2
+check_r3 0
+
+test_name CMPGEU_9
+mvi r3, 1
+mvi r2, 0
+cmpgeu r3, r3, r2
+check_r3 1
+
+test_name CMPGEU_10
+mvi r3, 0
+cmpgeu r3, r3, r3
+check_r3 1
+
+end
diff --git a/src/tests/tcg/lm32/test_cmpgeui.S b/src/tests/tcg/lm32/test_cmpgeui.S
new file mode 100644
index 0000000..3866d96
--- /dev/null
+++ b/src/tests/tcg/lm32/test_cmpgeui.S
@@ -0,0 +1,70 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGEUI_1
+mvi r1, 0
+cmpgeui r3, r1, 0
+check_r3 1
+
+test_name CMPGEUI_2
+mvi r1, 0
+cmpgeui r3, r1, 1
+check_r3 0
+
+test_name CMPGEUI_3
+mvi r1, 1
+cmpgeui r3, r1, 0
+check_r3 1
+
+test_name CMPGEUI_4
+mvi r1, 1
+cmpgeui r3, r1, 1
+check_r3 1
+
+test_name CMPGEUI_5
+mvi r1, 0
+cmpgeui r3, r1, 0xffff
+check_r3 0
+
+test_name CMPGEUI_6
+mvi r1, -1
+cmpgeui r3, r1, 0
+check_r3 1
+
+test_name CMPGEUI_7
+mvi r1, -1
+cmpgeui r3, r1, 0xffff
+check_r3 1
+
+test_name CMPGEUI_8
+mvi r3, 0
+cmpgeui r3, r3, 1
+check_r3 0
+
+test_name CMPGEUI_9
+mvi r3, 1
+cmpgeui r3, r3, 0
+check_r3 1
+
+test_name CMPGEUI_10
+mvi r3, 0
+cmpgeui r3, r3, 0
+check_r3 1
+
+test_name CMPGEUI_11
+mvi r1, 0
+cmpgeui r3, r1, 0x8000
+check_r3 0
+
+test_name CMPGEUI_12
+mvi r1, -1
+cmpgeui r3, r1, 0x8000
+check_r3 1
+
+test_name CMPGEUI_13
+ori r1, r0, 0x8000
+cmpgeui r3, r1, 0x8000
+check_r3 1
+
+end
diff --git a/src/tests/tcg/lm32/test_cmpgi.S b/src/tests/tcg/lm32/test_cmpgi.S
new file mode 100644
index 0000000..21695f9
--- /dev/null
+++ b/src/tests/tcg/lm32/test_cmpgi.S
@@ -0,0 +1,70 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGI_1
+mvi r1, 0
+cmpgi r3, r1, 0
+check_r3 0
+
+test_name CMPGI_2
+mvi r1, 0
+cmpgi r3, r1, 1
+check_r3 0
+
+test_name CMPGI_3
+mvi r1, 1
+cmpgi r3, r1, 0
+check_r3 1
+
+test_name CMPGI_4
+mvi r1, 1
+cmpgi r3, r1, 1
+check_r3 0
+
+test_name CMPGI_5
+mvi r1, 0
+cmpgi r3, r1, -1
+check_r3 1
+
+test_name CMPGI_6
+mvi r1, -1
+cmpgi r3, r1, 0
+check_r3 0
+
+test_name CMPGI_7
+mvi r1, -1
+cmpgi r3, r1, -1
+check_r3 0
+
+test_name CMPGI_8
+mvi r3, 0
+cmpgi r3, r3, 1
+check_r3 0
+
+test_name CMPGI_9
+mvi r3, 1
+cmpgi r3, r3, 0
+check_r3 1
+
+test_name CMPGI_10
+mvi r3, 0
+cmpgi r3, r3, 0
+check_r3 0
+
+test_name CMPGI_11
+mvi r1, 0
+cmpgi r3, r1, -32768
+check_r3 1
+
+test_name CMPGI_12
+mvi r1, -1
+cmpgi r3, r1, -32768
+check_r3 1
+
+test_name CMPGI_13
+mvi r1, -32768
+cmpgi r3, r1, -32768
+check_r3 0
+
+end
diff --git a/src/tests/tcg/lm32/test_cmpgu.S b/src/tests/tcg/lm32/test_cmpgu.S
new file mode 100644
index 0000000..dd46547
--- /dev/null
+++ b/src/tests/tcg/lm32/test_cmpgu.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGU_1
+mvi r1, 0
+mvi r2, 0
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_2
+mvi r1, 0
+mvi r2, 1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_3
+mvi r1, 1
+mvi r2, 0
+cmpgu r3, r1, r2
+check_r3 1
+
+test_name CMPGU_4
+mvi r1, 1
+mvi r2, 1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_5
+mvi r1, 0
+mvi r2, -1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_6
+mvi r1, -1
+mvi r2, 0
+cmpgu r3, r1, r2
+check_r3 1
+
+test_name CMPGU_7
+mvi r1, -1
+mvi r2, -1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_8
+mvi r3, 0
+mvi r2, 1
+cmpgu r3, r3, r2
+check_r3 0
+
+test_name CMPGU_9
+mvi r3, 1
+mvi r2, 0
+cmpgu r3, r3, r2
+check_r3 1
+
+test_name CMPGU_10
+mvi r3, 0
+cmpgu r3, r3, r3
+check_r3 0
+
+end
diff --git a/src/tests/tcg/lm32/test_cmpgui.S b/src/tests/tcg/lm32/test_cmpgui.S
new file mode 100644
index 0000000..dd94001
--- /dev/null
+++ b/src/tests/tcg/lm32/test_cmpgui.S
@@ -0,0 +1,70 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGUI_1
+mvi r1, 0
+cmpgui r3, r1, 0
+check_r3 0
+
+test_name CMPGUI_2
+mvi r1, 0
+cmpgui r3, r1, 1
+check_r3 0
+
+test_name CMPGUI_3
+mvi r1, 1
+cmpgui r3, r1, 0
+check_r3 1
+
+test_name CMPGUI_4
+mvi r1, 1
+cmpgui r3, r1, 1
+check_r3 0
+
+test_name CMPGUI_5
+mvi r1, 0
+cmpgui r3, r1, 0xffff
+check_r3 0
+
+test_name CMPGUI_6
+mvi r1, -1
+cmpgui r3, r1, 0
+check_r3 1
+
+test_name CMPGUI_7
+mvi r1, -1
+cmpgui r3, r1, 0xffff
+check_r3 1
+
+test_name CMPGUI_8
+mvi r3, 0
+cmpgui r3, r3, 1
+check_r3 0
+
+test_name CMPGUI_9
+mvi r3, 1
+cmpgui r3, r3, 0
+check_r3 1
+
+test_name CMPGUI_10
+mvi r3, 0
+cmpgui r3, r3, 0
+check_r3 0
+
+test_name CMPGUI_11
+mvi r1, 0
+cmpgui r3, r1, 0x8000
+check_r3 0
+
+test_name CMPGUI_12
+mvi r1, -1
+cmpgui r3, r1, 0x8000
+check_r3 1
+
+test_name CMPGUI_13
+ori r1, r0, 0x8000
+cmpgui r3, r1, 0x8000
+check_r3 0
+
+end
diff --git a/src/tests/tcg/lm32/test_cmpne.S b/src/tests/tcg/lm32/test_cmpne.S
new file mode 100644
index 0000000..0f10781
--- /dev/null
+++ b/src/tests/tcg/lm32/test_cmpne.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name CMPNE_1
+mvi r1, 0
+mvi r2, 0
+cmpne r3, r1, r2
+check_r3 0
+
+test_name CMPNE_2
+mvi r1, 0
+mvi r2, 1
+cmpne r3, r1, r2
+check_r3 1
+
+test_name CMPNE_3
+mvi r1, 1
+mvi r2, 0
+cmpne r3, r1, r2
+check_r3 1
+
+test_name CMPNE_4
+mvi r3, 0
+mvi r2, 1
+cmpne r3, r3, r2
+check_r3 1
+
+test_name CMPNE_5
+mvi r3, 0
+mvi r2, 0
+cmpne r3, r3, r2
+check_r3 0
+
+test_name CMPNE_6
+mvi r3, 0
+cmpne r3, r3, r3
+check_r3 0
+
+end
diff --git a/src/tests/tcg/lm32/test_cmpnei.S b/src/tests/tcg/lm32/test_cmpnei.S
new file mode 100644
index 0000000..060dd9d
--- /dev/null
+++ b/src/tests/tcg/lm32/test_cmpnei.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name CMPNEI_1
+mvi r1, 0
+cmpnei r3, r1, 0
+check_r3 0
+
+test_name CMPNEI_2
+mvi r1, 0
+cmpnei r3, r1, 1
+check_r3 1
+
+test_name CMPNEI_3
+mvi r1, 1
+cmpnei r3, r1, 0
+check_r3 1
+
+test_name CMPNEI_4
+load r1 0xffffffff
+cmpnei r3, r1, -1
+check_r3 0
+
+test_name CMPNEI_5
+mvi r3, 0
+cmpnei r3, r3, 0
+check_r3 0
+
+test_name CMPNEI_6
+mvi r3, 0
+cmpnei r3, r3, 1
+check_r3 1
+
+end
diff --git a/src/tests/tcg/lm32/test_divu.S b/src/tests/tcg/lm32/test_divu.S
new file mode 100644
index 0000000..f381d09
--- /dev/null
+++ b/src/tests/tcg/lm32/test_divu.S
@@ -0,0 +1,29 @@
+.include "macros.inc"
+
+start
+
+test_name DIVU_1
+mvi r1, 0
+mvi r2, 1
+divu r3, r1, r2
+check_r3 0
+
+test_name DIVU_2
+mvi r1, 1
+mvi r2, 1
+divu r3, r1, r2
+check_r3 1
+
+test_name DIVU_3
+mvi r1, 0
+mvi r2, 0
+divu r3, r1, r2
+check_excp 16
+
+test_name DIVU_4
+load r1 0xabcdef12
+load r2 0x12345
+divu r3, r1, r2
+check_r3 0x9700
+
+end
diff --git a/src/tests/tcg/lm32/test_eret.S b/src/tests/tcg/lm32/test_eret.S
new file mode 100644
index 0000000..6830bd1
--- /dev/null
+++ b/src/tests/tcg/lm32/test_eret.S
@@ -0,0 +1,38 @@
+.include "macros.inc"
+
+start
+
+test_name ERET_1
+mvi r1, 2
+wcsr IE, r1
+load ea mark
+eret
+tc_fail
+bi 1f
+
+mark:
+tc_pass
+
+1:
+test_name ERET_2
+rcsr r3, IE
+check_r3 3
+
+test_name ERET_3
+mvi r1, 0
+wcsr IE, r1
+load ea mark2
+eret
+tc_fail
+bi 1f
+
+mark2:
+tc_pass
+
+1:
+test_name ERET_4
+rcsr r3, IE
+check_r3 0
+
+end
+
diff --git a/src/tests/tcg/lm32/test_lb.S b/src/tests/tcg/lm32/test_lb.S
new file mode 100644
index 0000000..d677eea
--- /dev/null
+++ b/src/tests/tcg/lm32/test_lb.S
@@ -0,0 +1,49 @@
+.include "macros.inc"
+
+start
+
+test_name LB_1
+load r1 data
+lb r3, (r1+0)
+check_r3 0x7e
+
+test_name LB_2
+load r1 data
+lb r3, (r1+1)
+check_r3 0x7f
+
+test_name LB_3
+load r1 data
+lb r3, (r1+-1)
+check_r3 0x7d
+
+test_name LB_4
+load r1 data_msb
+lb r3, (r1+0)
+check_r3 0xfffffffe
+
+test_name LB_5
+load r1 data_msb
+lb r3, (r1+1)
+check_r3 0xffffffff
+
+test_name LB_6
+load r1 data_msb
+lb r3, (r1+-1)
+check_r3 0xfffffffd
+
+test_name LB_7
+load r3 data
+lb r3, (r3+0)
+check_r3 0x7e
+
+end
+
+.data
+ .align 4
+ .byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+ .byte 0x7e, 0x7f, 0x70, 0x71
+ .byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+ .byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/src/tests/tcg/lm32/test_lbu.S b/src/tests/tcg/lm32/test_lbu.S
new file mode 100644
index 0000000..dc5d5f6
--- /dev/null
+++ b/src/tests/tcg/lm32/test_lbu.S
@@ -0,0 +1,49 @@
+.include "macros.inc"
+
+start
+
+test_name LBU_1
+load r1 data
+lbu r3, (r1+0)
+check_r3 0x7e
+
+test_name LBU_2
+load r1 data
+lbu r3, (r1+1)
+check_r3 0x7f
+
+test_name LBU_3
+load r1 data
+lbu r3, (r1+-1)
+check_r3 0x7d
+
+test_name LBU_4
+load r1 data_msb
+lbu r3, (r1+0)
+check_r3 0xfe
+
+test_name LBU_5
+load r1 data_msb
+lbu r3, (r1+1)
+check_r3 0xff
+
+test_name LBU_6
+load r1 data_msb
+lbu r3, (r1+-1)
+check_r3 0xfd
+
+test_name LBU_7
+load r3 data
+lbu r3, (r3+0)
+check_r3 0x7e
+
+end
+
+.data
+ .align 4
+ .byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+ .byte 0x7e, 0x7f, 0x70, 0x71
+ .byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+ .byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/src/tests/tcg/lm32/test_lh.S b/src/tests/tcg/lm32/test_lh.S
new file mode 100644
index 0000000..397996b
--- /dev/null
+++ b/src/tests/tcg/lm32/test_lh.S
@@ -0,0 +1,49 @@
+.include "macros.inc"
+
+start
+
+test_name LH_1
+load r1 data
+lh r3, (r1+0)
+check_r3 0x7e7f
+
+test_name LH_2
+load r1 data
+lh r3, (r1+2)
+check_r3 0x7071
+
+test_name LH_3
+load r1 data
+lh r3, (r1+-2)
+check_r3 0x7c7d
+
+test_name LH_4
+load r1 data_msb
+lh r3, (r1+0)
+check_r3 0xfffffeff
+
+test_name LH_5
+load r1 data_msb
+lh r3, (r1+2)
+check_r3 0xfffff0f1
+
+test_name LH_6
+load r1 data_msb
+lh r3, (r1+-2)
+check_r3 0xfffffcfd
+
+test_name LH_7
+load r3 data
+lh r3, (r3+0)
+check_r3 0x7e7f
+
+end
+
+.data
+ .align 4
+ .byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+ .byte 0x7e, 0x7f, 0x70, 0x71
+ .byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+ .byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/src/tests/tcg/lm32/test_lhu.S b/src/tests/tcg/lm32/test_lhu.S
new file mode 100644
index 0000000..8de7c52
--- /dev/null
+++ b/src/tests/tcg/lm32/test_lhu.S
@@ -0,0 +1,49 @@
+.include "macros.inc"
+
+start
+
+test_name LHU_1
+load r1 data
+lhu r3, (r1+0)
+check_r3 0x7e7f
+
+test_name LHU_2
+load r1 data
+lhu r3, (r1+2)
+check_r3 0x7071
+
+test_name LHU_3
+load r1 data
+lhu r3, (r1+-2)
+check_r3 0x7c7d
+
+test_name LHU_4
+load r1 data_msb
+lhu r3, (r1+0)
+check_r3 0xfeff
+
+test_name LHU_5
+load r1 data_msb
+lhu r3, (r1+2)
+check_r3 0xf0f1
+
+test_name LHU_6
+load r1 data_msb
+lhu r3, (r1+-2)
+check_r3 0xfcfd
+
+test_name LHU_7
+load r3 data
+lhu r3, (r3+0)
+check_r3 0x7e7f
+
+end
+
+.data
+ .align 4
+ .byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+ .byte 0x7e, 0x7f, 0x70, 0x71
+ .byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+ .byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/src/tests/tcg/lm32/test_lw.S b/src/tests/tcg/lm32/test_lw.S
new file mode 100644
index 0000000..996e5f8
--- /dev/null
+++ b/src/tests/tcg/lm32/test_lw.S
@@ -0,0 +1,32 @@
+.include "macros.inc"
+
+start
+
+test_name LW_1
+load r1 data
+lw r3, (r1+0)
+check_r3 0x7e7f7071
+
+test_name LW_2
+load r1 data
+lw r3, (r1+4)
+check_r3 0x72737475
+
+test_name LW_3
+load r1 data
+lw r3, (r1+-4)
+check_r3 0x7a7b7c7d
+
+test_name LW_4
+load r3 data
+lw r3, (r3+0)
+check_r3 0x7e7f7071
+
+end
+
+.data
+ .align 4
+ .byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+ .byte 0x7e, 0x7f, 0x70, 0x71
+ .byte 0x72, 0x73, 0x74, 0x75
diff --git a/src/tests/tcg/lm32/test_modu.S b/src/tests/tcg/lm32/test_modu.S
new file mode 100644
index 0000000..4248690
--- /dev/null
+++ b/src/tests/tcg/lm32/test_modu.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name MODU_1
+mvi r1, 0
+mvi r2, 1
+modu r3, r1, r2
+check_r3 0
+
+test_name MODU_2
+mvi r1, 1
+mvi r2, 1
+modu r3, r1, r2
+check_r3 0
+
+test_name MODU_3
+mvi r1, 3
+mvi r2, 2
+modu r3, r1, r2
+check_r3 1
+
+test_name MODU_4
+mvi r1, 0
+mvi r2, 0
+modu r3, r1, r2
+check_excp 16
+
+test_name MODU_5
+load r1 0xabcdef12
+load r2 0x12345
+modu r3, r1, r2
+check_r3 0x3c12
+
+end
diff --git a/src/tests/tcg/lm32/test_mul.S b/src/tests/tcg/lm32/test_mul.S
new file mode 100644
index 0000000..e9b937e
--- /dev/null
+++ b/src/tests/tcg/lm32/test_mul.S
@@ -0,0 +1,70 @@
+.include "macros.inc"
+
+start
+
+test_name MUL_1
+mvi r1, 0
+mvi r2, 0
+mul r3, r1, r2
+check_r3 0
+
+test_name MUL_2
+mvi r1, 1
+mvi r2, 0
+mul r3, r1, r2
+check_r3 0
+
+test_name MUL_3
+mvi r1, 0
+mvi r2, 1
+mul r3, r1, r2
+check_r3 0
+
+test_name MUL_4
+mvi r1, 1
+mvi r2, 1
+mul r3, r1, r2
+check_r3 1
+
+test_name MUL_5
+mvi r1, 2
+mvi r2, -1
+mul r3, r1, r2
+check_r3 -2
+
+test_name MUL_6
+mvi r1, -2
+mvi r2, -1
+mul r3, r1, r2
+check_r3 2
+
+test_name MUL_7
+mvi r1, 0x1234
+mvi r2, 0x789
+mul r3, r1, r2
+check_r3 0x8929d4
+
+test_name MUL_8
+mvi r3, 4
+mul r3, r3, r3
+check_r3 16
+
+test_name MUL_9
+mvi r2, 2
+mvi r3, 4
+mul r3, r3, r2
+check_r3 8
+
+test_name MUL_10
+load r1 0x12345678
+load r2 0x7bcdef12
+mul r3, r1, r2
+check_r3 0xa801c70
+
+test_name MUL_11
+load r1 0x12345678
+load r2 0xabcdef12
+mul r3, r1, r2
+check_r3 0x8a801c70
+
+end
diff --git a/src/tests/tcg/lm32/test_muli.S b/src/tests/tcg/lm32/test_muli.S
new file mode 100644
index 0000000..d6dd4a0
--- /dev/null
+++ b/src/tests/tcg/lm32/test_muli.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name MULI_1
+mvi r1, 0
+muli r3, r1, 0
+check_r3 0
+
+test_name MULI_2
+mvi r1, 1
+muli r3, r1, 0
+check_r3 0
+
+test_name MULI_3
+mvi r1, 0
+muli r3, r1, 1
+check_r3 0
+
+test_name MULI_4
+mvi r1, 1
+muli r3, r1, 1
+check_r3 1
+
+test_name MULI_5
+mvi r1, 2
+muli r3, r1, -1
+check_r3 -2
+
+test_name MULI_6
+mvi r1, -2
+muli r3, r1, -1
+check_r3 2
+
+test_name MULI_7
+mvi r1, 0x1234
+muli r3, r1, 0x789
+check_r3 0x8929d4
+
+test_name MULI_8
+mvi r3, 4
+muli r3, r3, 4
+check_r3 16
+
+end
diff --git a/src/tests/tcg/lm32/test_nor.S b/src/tests/tcg/lm32/test_nor.S
new file mode 100644
index 0000000..74d7592
--- /dev/null
+++ b/src/tests/tcg/lm32/test_nor.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name NOR_1
+mvi r1, 0
+mvi r2, 0
+nor r3, r1, r2
+check_r3 0xffffffff
+
+test_name NOR_2
+mvi r1, 0
+mvi r2, 1
+nor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name NOR_3
+mvi r1, 1
+mvi r2, 1
+nor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name NOR_4
+mvi r1, 1
+mvi r2, 0
+nor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name NOR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+nor r3, r1, r2
+check_r3 0
+
+test_name NOR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+nor r3, r1, r2
+check_r3 0x55aa55aa
+
+test_name NOR_7
+load r1 0xaa55aa55
+nor r3, r1, r1
+check_r3 0x55aa55aa
+
+test_name NOR_8
+load r3 0xaa55aa55
+nor r3, r3, r3
+check_r3 0x55aa55aa
+
+end
diff --git a/src/tests/tcg/lm32/test_nori.S b/src/tests/tcg/lm32/test_nori.S
new file mode 100644
index 0000000..d00309c
--- /dev/null
+++ b/src/tests/tcg/lm32/test_nori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name NORI_1
+mvi r1, 0
+nori r3, r1, 0
+check_r3 0xffffffff
+
+test_name NORI_2
+mvi r1, 0
+nori r3, r1, 1
+check_r3 0xfffffffe
+
+test_name NORI_3
+mvi r1, 1
+nori r3, r1, 1
+check_r3 0xfffffffe
+
+test_name NORI_4
+mvi r1, 1
+nori r3, r1, 0
+check_r3 0xfffffffe
+
+test_name NORI_5
+load r1 0xaa55aa55
+nori r3, r1, 0x55aa
+check_r3 0x55aa0000
+
+test_name NORI_6
+load r3 0xaa55aa55
+nori r3, r3, 0x55aa
+check_r3 0x55aa0000
+
+end
diff --git a/src/tests/tcg/lm32/test_or.S b/src/tests/tcg/lm32/test_or.S
new file mode 100644
index 0000000..4ed2923
--- /dev/null
+++ b/src/tests/tcg/lm32/test_or.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name OR_1
+mvi r1, 0
+mvi r2, 0
+or r3, r1, r2
+check_r3 0
+
+test_name OR_2
+mvi r1, 0
+mvi r2, 1
+or r3, r1, r2
+check_r3 1
+
+test_name OR_3
+mvi r1, 1
+mvi r2, 1
+or r3, r1, r2
+check_r3 1
+
+test_name OR_4
+mvi r1, 1
+mvi r2, 0
+or r3, r1, r2
+check_r3 1
+
+test_name OR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+or r3, r1, r2
+check_r3 0xffffffff
+
+test_name OR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+or r3, r1, r2
+check_r3 0xaa55aa55
+
+test_name OR_7
+load r1 0xaa55aa55
+or r3, r1, r1
+check_r3 0xaa55aa55
+
+test_name OR_8
+load r3 0xaa55aa55
+or r3, r3, r3
+check_r3 0xaa55aa55
+
+end
diff --git a/src/tests/tcg/lm32/test_orhi.S b/src/tests/tcg/lm32/test_orhi.S
new file mode 100644
index 0000000..78b7600
--- /dev/null
+++ b/src/tests/tcg/lm32/test_orhi.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ORHI_1
+mvi r1, 0
+orhi r3, r1, 0
+check_r3 0
+
+test_name ORHI_2
+mvi r1, 0
+orhi r3, r1, 1
+check_r3 0x00010000
+
+test_name ORHI_3
+load r1 0x00010000
+orhi r3, r1, 1
+check_r3 0x00010000
+
+test_name ORHI_4
+mvi r1, 1
+orhi r3, r1, 0
+check_r3 1
+
+test_name ORHI_5
+load r1 0xaa55aa55
+orhi r3, r1, 0x55aa
+check_r3 0xffffaa55
+
+test_name ORHI_6
+load r3 0xaa55aa55
+orhi r3, r3, 0x55aa
+check_r3 0xffffaa55
+
+end
diff --git a/src/tests/tcg/lm32/test_ori.S b/src/tests/tcg/lm32/test_ori.S
new file mode 100644
index 0000000..3d576cd
--- /dev/null
+++ b/src/tests/tcg/lm32/test_ori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ORI_1
+mvi r1, 0
+ori r3, r1, 0
+check_r3 0
+
+test_name ORI_2
+mvi r1, 0
+ori r3, r1, 1
+check_r3 1
+
+test_name ORI_3
+mvi r1, 1
+ori r3, r1, 1
+check_r3 1
+
+test_name ORI_4
+mvi r1, 1
+ori r3, r1, 0
+check_r3 1
+
+test_name ORI_5
+load r1 0xaa55aa55
+ori r3, r1, 0x55aa
+check_r3 0xaa55ffff
+
+test_name ORI_6
+load r3 0xaa55aa55
+ori r3, r3, 0x55aa
+check_r3 0xaa55ffff
+
+end
diff --git a/src/tests/tcg/lm32/test_ret.S b/src/tests/tcg/lm32/test_ret.S
new file mode 100644
index 0000000..320264f
--- /dev/null
+++ b/src/tests/tcg/lm32/test_ret.S
@@ -0,0 +1,14 @@
+.include "macros.inc"
+
+start
+
+test_name RET_1
+load ra mark
+ret
+
+tc_fail
+end
+
+mark:
+tc_pass
+end
diff --git a/src/tests/tcg/lm32/test_sb.S b/src/tests/tcg/lm32/test_sb.S
new file mode 100644
index 0000000..b15a89d
--- /dev/null
+++ b/src/tests/tcg/lm32/test_sb.S
@@ -0,0 +1,32 @@
+.include "macros.inc"
+
+start
+
+test_name SB_1
+load r1 data
+load r2 0xf0f1f2aa
+sb (r1+0), r2
+check_mem data 0xaa000000
+
+test_name SB_2
+load r1 data
+load r2 0xf0f1f2bb
+sb (r1+1), r2
+check_mem data 0xaabb0000
+
+test_name SB_3
+load r1 data
+load r2 0xf0f1f2cc
+sb (r1+-1), r2
+check_mem data0 0x000000cc
+
+end
+
+.data
+ .align 4
+data0:
+ .byte 0, 0, 0, 0
+data:
+ .byte 0, 0, 0, 0
+data1:
+ .byte 0, 0, 0, 0
diff --git a/src/tests/tcg/lm32/test_scall.S b/src/tests/tcg/lm32/test_scall.S
new file mode 100644
index 0000000..46032f8
--- /dev/null
+++ b/src/tests/tcg/lm32/test_scall.S
@@ -0,0 +1,24 @@
+.include "macros.inc"
+
+start
+
+test_name SCALL_1
+mvi r1, 1
+wcsr IE, r1
+# we are running in a semi hosted environment
+# therefore we have to set r8 to some unused system
+# call
+mvi r8, 0
+insn:
+scall
+check_excp 64
+
+test_name SCALL_2
+mv r3, ea
+check_r3 insn
+
+test_name SCALL_3
+rcsr r3, IE
+check_r3 2
+
+end
diff --git a/src/tests/tcg/lm32/test_sextb.S b/src/tests/tcg/lm32/test_sextb.S
new file mode 100644
index 0000000..58db8ee
--- /dev/null
+++ b/src/tests/tcg/lm32/test_sextb.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name SEXTB_1
+mvi r1, 0
+sextb r3, r1
+check_r3 0
+
+test_name SEXTB_2
+mvi r1, 0x7f
+sextb r3, r1
+check_r3 0x0000007f
+
+test_name SEXTB_3
+mvi r1, 0x80
+sextb r3, r1
+check_r3 0xffffff80
+
+end
diff --git a/src/tests/tcg/lm32/test_sexth.S b/src/tests/tcg/lm32/test_sexth.S
new file mode 100644
index 0000000..a059ec3
--- /dev/null
+++ b/src/tests/tcg/lm32/test_sexth.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name SEXTH_1
+mvi r1, 0
+sexth r3, r1
+check_r3 0
+
+test_name SEXTH_2
+load r1 0x7fff
+sexth r3, r1
+check_r3 0x00007fff
+
+test_name SEXTH_3
+load r1 0x8000
+sexth r3, r1
+check_r3 0xffff8000
+
+end
diff --git a/src/tests/tcg/lm32/test_sh.S b/src/tests/tcg/lm32/test_sh.S
new file mode 100644
index 0000000..bba1022
--- /dev/null
+++ b/src/tests/tcg/lm32/test_sh.S
@@ -0,0 +1,32 @@
+.include "macros.inc"
+
+start
+
+test_name SH_1
+load r1 data
+load r2 0xf0f1aaaa
+sh (r1+0), r2
+check_mem data 0xaaaa0000
+
+test_name SH_2
+load r1 data
+load r2 0xf0f1bbbb
+sh (r1+2), r2
+check_mem data 0xaaaabbbb
+
+test_name SH_3
+load r1 data
+load r2 0xf0f1cccc
+sh (r1+-2), r2
+check_mem data0 0x0000cccc
+
+end
+
+.data
+ .align 4
+data0:
+ .byte 0, 0, 0, 0
+data:
+ .byte 0, 0, 0, 0
+data1:
+ .byte 0, 0, 0, 0
diff --git a/src/tests/tcg/lm32/test_sl.S b/src/tests/tcg/lm32/test_sl.S
new file mode 100644
index 0000000..0aee17f
--- /dev/null
+++ b/src/tests/tcg/lm32/test_sl.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name SL_1
+mvi r1, 1
+mvi r2, 0
+sl r3, r1, r2
+check_r3 1
+
+test_name SL_2
+mvi r1, 0
+mvi r2, 1
+sl r3, r1, r2
+check_r3 0
+
+test_name SL_3
+mvi r1, 1
+mvi r2, 31
+sl r3, r1, r2
+check_r3 0x80000000
+
+test_name SL_4
+mvi r1, 16
+mvi r2, 31
+sl r3, r1, r2
+check_r3 0
+
+test_name SL_5
+mvi r1, 1
+mvi r2, 34
+sl r3, r1, r2
+check_r3 4
+
+test_name SL_6
+mvi r1, 2
+sl r3, r1, r1
+check_r3 8
+
+test_name SL_7
+mvi r3, 2
+sl r3, r3, r3
+check_r3 8
+
+end
diff --git a/src/tests/tcg/lm32/test_sli.S b/src/tests/tcg/lm32/test_sli.S
new file mode 100644
index 0000000..a421de9
--- /dev/null
+++ b/src/tests/tcg/lm32/test_sli.S
@@ -0,0 +1,30 @@
+.include "macros.inc"
+
+start
+
+test_name SLI_1
+mvi r1, 1
+sli r3, r1, 0
+check_r3 1
+
+test_name SLI_2
+mvi r1, 0
+sli r3, r1, 1
+check_r3 0
+
+test_name SLI_3
+mvi r1, 1
+sli r3, r1, 31
+check_r3 0x80000000
+
+test_name SLI_4
+mvi r1, 16
+sli r3, r1, 31
+check_r3 0
+
+test_name SLI_7
+mvi r3, 2
+sli r3, r3, 2
+check_r3 8
+
+end
diff --git a/src/tests/tcg/lm32/test_sr.S b/src/tests/tcg/lm32/test_sr.S
new file mode 100644
index 0000000..62431a9
--- /dev/null
+++ b/src/tests/tcg/lm32/test_sr.S
@@ -0,0 +1,57 @@
+.include "macros.inc"
+
+start
+
+test_name SR_1
+mvi r1, 1
+mvi r2, 0
+sr r3, r1, r2
+check_r3 1
+
+test_name SR_2
+mvi r1, 0
+mvi r2, 1
+sr r3, r1, r2
+check_r3 0
+
+test_name SR_3
+load r1 0x40000000
+mvi r2, 30
+sr r3, r1, r2
+check_r3 1
+
+test_name SR_4
+load r1 0x40000000
+mvi r2, 31
+sr r3, r1, r2
+check_r3 0
+
+test_name SR_5
+mvi r1, 16
+mvi r2, 34
+sr r3, r1, r2
+check_r3 4
+
+test_name SR_6
+mvi r1, 2
+sr r3, r1, r1
+check_r3 0
+
+test_name SR_7
+mvi r3, 2
+sr r3, r3, r3
+check_r3 0
+
+test_name SR_8
+mvi r1, 0xfffffff0
+mvi r2, 2
+sr r3, r1, r2
+check_r3 0xfffffffc
+
+test_name SR_9
+mvi r1, 0xfffffff0
+mvi r2, 4
+sr r3, r1, r2
+check_r3 0xffffffff
+
+end
diff --git a/src/tests/tcg/lm32/test_sri.S b/src/tests/tcg/lm32/test_sri.S
new file mode 100644
index 0000000..c1be907
--- /dev/null
+++ b/src/tests/tcg/lm32/test_sri.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name SRI_1
+mvi r1, 1
+sri r3, r1, 0
+check_r3 1
+
+test_name SRI_2
+mvi r1, 0
+sri r3, r1, 1
+check_r3 0
+
+test_name SRI_3
+load r1 0x40000000
+sri r3, r1, 30
+check_r3 1
+
+test_name SRI_4
+load r1 0x40000000
+sri r3, r1, 31
+check_r3 0
+
+test_name SRI_5
+mvi r3, 2
+sri r3, r3, 2
+check_r3 0
+
+test_name SRI_6
+mvi r1, 0xfffffff0
+sri r3, r1, 2
+check_r3 0xfffffffc
+
+test_name SRI_7
+mvi r1, 0xfffffff0
+sri r3, r1, 4
+check_r3 0xffffffff
+
+end
diff --git a/src/tests/tcg/lm32/test_sru.S b/src/tests/tcg/lm32/test_sru.S
new file mode 100644
index 0000000..2ab0b54
--- /dev/null
+++ b/src/tests/tcg/lm32/test_sru.S
@@ -0,0 +1,57 @@
+.include "macros.inc"
+
+start
+
+test_name SRU_1
+mvi r1, 1
+mvi r2, 0
+sru r3, r1, r2
+check_r3 1
+
+test_name SRU_2
+mvi r1, 0
+mvi r2, 1
+sru r3, r1, r2
+check_r3 0
+
+test_name SRU_3
+load r1 0x40000000
+mvi r2, 30
+sru r3, r1, r2
+check_r3 1
+
+test_name SRU_4
+load r1 0x40000000
+mvi r2, 31
+sru r3, r1, r2
+check_r3 0
+
+test_name SRU_5
+mvi r1, 16
+mvi r2, 34
+sru r3, r1, r2
+check_r3 4
+
+test_name SRU_6
+mvi r1, 2
+sru r3, r1, r1
+check_r3 0
+
+test_name SRU_7
+mvi r3, 2
+sru r3, r3, r3
+check_r3 0
+
+test_name SRU_8
+mvi r1, 0xfffffff0
+mvi r2, 2
+sru r3, r1, r2
+check_r3 0x3ffffffc
+
+test_name SRU_9
+mvi r1, 0xfffffff0
+mvi r2, 4
+sru r3, r1, r2
+check_r3 0x0fffffff
+
+end
diff --git a/src/tests/tcg/lm32/test_srui.S b/src/tests/tcg/lm32/test_srui.S
new file mode 100644
index 0000000..872c374
--- /dev/null
+++ b/src/tests/tcg/lm32/test_srui.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name SRUI_1
+mvi r1, 1
+srui r3, r1, 0
+check_r3 1
+
+test_name SRUI_2
+mvi r1, 0
+srui r3, r1, 1
+check_r3 0
+
+test_name SRUI_3
+load r1 0x40000000
+srui r3, r1, 30
+check_r3 1
+
+test_name SRUI_4
+load r1 0x40000000
+srui r3, r1, 31
+check_r3 0
+
+test_name SRUI_5
+mvi r3, 2
+srui r3, r3, 2
+check_r3 0
+
+test_name SRUI_6
+mvi r1, 0xfffffff0
+srui r3, r1, 2
+check_r3 0x3ffffffc
+
+test_name SRUI_7
+mvi r1, 0xfffffff0
+srui r3, r1, 4
+check_r3 0x0fffffff
+
+end
diff --git a/src/tests/tcg/lm32/test_sub.S b/src/tests/tcg/lm32/test_sub.S
new file mode 100644
index 0000000..44b74a9
--- /dev/null
+++ b/src/tests/tcg/lm32/test_sub.S
@@ -0,0 +1,75 @@
+.include "macros.inc"
+
+start
+
+test_name SUB_1
+mvi r1, 0
+mvi r2, 0
+sub r3, r1, r2
+check_r3 0
+
+test_name SUB_2
+mvi r1, 0
+mvi r2, 1
+sub r3, r1, r2
+check_r3 -1
+
+test_name SUB_3
+mvi r1, 1
+mvi r2, 0
+sub r3, r1, r2
+check_r3 1
+
+test_name SUB_4
+mvi r1, 1
+mvi r2, -1
+sub r3, r1, r2
+check_r3 2
+
+test_name SUB_5
+mvi r1, -1
+mvi r2, 1
+sub r3, r1, r2
+check_r3 -2
+
+test_name SUB_6
+mvi r1, -1
+mvi r2, 0
+sub r3, r1, r2
+check_r3 -1
+
+test_name SUB_7
+mvi r1, 0
+mvi r2, -1
+sub r3, r1, r2
+check_r3 1
+
+test_name SUB_8
+mvi r3, 2
+sub r3, r3, r3
+check_r3 0
+
+test_name SUB_9
+mvi r1, 4
+mvi r3, 2
+sub r3, r1, r3
+check_r3 2
+
+test_name SUB_10
+mvi r1, 4
+mvi r3, 2
+sub r3, r3, r1
+check_r3 -2
+
+test_name SUB_11
+mvi r1, 4
+sub r3, r1, r1
+check_r3 0
+
+test_name SUB_12
+load r1 0x12345678
+load r2 0xabcdef97
+sub r3, r1, r2
+check_r3 0x666666e1
+
+end
diff --git a/src/tests/tcg/lm32/test_sw.S b/src/tests/tcg/lm32/test_sw.S
new file mode 100644
index 0000000..2b1c017
--- /dev/null
+++ b/src/tests/tcg/lm32/test_sw.S
@@ -0,0 +1,38 @@
+.include "macros.inc"
+
+start
+
+test_name SW_1
+load r1 data
+load r2 0xaabbccdd
+sw (r1+0), r2
+check_mem data 0xaabbccdd
+
+test_name SW_2
+load r1 data
+load r2 0x00112233
+sw (r1+4), r2
+check_mem data1 0x00112233
+
+test_name SW_3
+load r1 data
+load r2 0x44556677
+sw (r1+-4), r2
+check_mem data0 0x44556677
+
+test_name SW_4
+load r1 data
+sw (r1+0), r1
+lw r3, (r1+0)
+check_r3 data
+
+end
+
+.data
+ .align 4
+data0:
+ .byte 0, 0, 0, 0
+data:
+ .byte 0, 0, 0, 0
+data1:
+ .byte 0, 0, 0, 0
diff --git a/src/tests/tcg/lm32/test_xnor.S b/src/tests/tcg/lm32/test_xnor.S
new file mode 100644
index 0000000..14a6207
--- /dev/null
+++ b/src/tests/tcg/lm32/test_xnor.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name XNOR_1
+mvi r1, 0
+mvi r2, 0
+xnor r3, r1, r2
+check_r3 0xffffffff
+
+test_name XNOR_2
+mvi r1, 0
+mvi r2, 1
+xnor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name XNOR_3
+mvi r1, 1
+mvi r2, 1
+xnor r3, r1, r2
+check_r3 0xffffffff
+
+test_name XNOR_4
+mvi r1, 1
+mvi r2, 0
+xnor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name XNOR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+xnor r3, r1, r2
+check_r3 0
+
+test_name XNOR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+xnor r3, r1, r2
+check_r3 0x55aa55aa
+
+test_name XNOR_7
+load r1 0xaa55aa55
+xnor r3, r1, r1
+check_r3 0xffffffff
+
+test_name XNOR_8
+load r3 0xaa55aa55
+xnor r3, r3, r3
+check_r3 0xffffffff
+
+end
diff --git a/src/tests/tcg/lm32/test_xnori.S b/src/tests/tcg/lm32/test_xnori.S
new file mode 100644
index 0000000..9d9c3c6
--- /dev/null
+++ b/src/tests/tcg/lm32/test_xnori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name XNORI_1
+mvi r1, 0
+xnori r3, r1, 0
+check_r3 0xffffffff
+
+test_name XNORI_2
+mvi r1, 0
+xnori r3, r1, 1
+check_r3 0xfffffffe
+
+test_name XNORI_3
+mvi r1, 1
+xnori r3, r1, 1
+check_r3 0xffffffff
+
+test_name XNORI_4
+mvi r1, 1
+xnori r3, r1, 0
+check_r3 0xfffffffe
+
+test_name XNORI_5
+load r1 0xaa55aa55
+xnori r3, r1, 0x5555
+check_r3 0x55aa00ff
+
+test_name XNORI_6
+load r3 0xaa55aa55
+xnori r3, r3, 0x5555
+check_r3 0x55aa00ff
+
+end
diff --git a/src/tests/tcg/lm32/test_xor.S b/src/tests/tcg/lm32/test_xor.S
new file mode 100644
index 0000000..6c6e712
--- /dev/null
+++ b/src/tests/tcg/lm32/test_xor.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name XOR_1
+mvi r1, 0
+mvi r2, 0
+xor r3, r1, r2
+check_r3 0
+
+test_name XOR_2
+mvi r1, 0
+mvi r2, 1
+xor r3, r1, r2
+check_r3 1
+
+test_name XOR_3
+mvi r1, 1
+mvi r2, 1
+xor r3, r1, r2
+check_r3 0
+
+test_name XOR_4
+mvi r1, 1
+mvi r2, 0
+xor r3, r1, r2
+check_r3 1
+
+test_name XOR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+xor r3, r1, r2
+check_r3 0xffffffff
+
+test_name XOR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+xor r3, r1, r2
+check_r3 0xaa55aa55
+
+test_name XOR_7
+load r1 0xaa55aa55
+xor r3, r1, r1
+check_r3 0
+
+test_name XOR_8
+load r3 0xaa55aa55
+xor r3, r3, r3
+check_r3 0
+
+end
diff --git a/src/tests/tcg/lm32/test_xori.S b/src/tests/tcg/lm32/test_xori.S
new file mode 100644
index 0000000..2051699
--- /dev/null
+++ b/src/tests/tcg/lm32/test_xori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name XORI_1
+mvi r1, 0
+xori r3, r1, 0
+check_r3 0
+
+test_name XORI_2
+mvi r1, 0
+xori r3, r1, 1
+check_r3 1
+
+test_name XORI_3
+mvi r1, 1
+xori r3, r1, 1
+check_r3 0
+
+test_name XORI_4
+mvi r1, 1
+xori r3, r1, 0
+check_r3 1
+
+test_name XORI_5
+load r1 0xaa55aa55
+xori r3, r1, 0x5555
+check_r3 0xaa55ff00
+
+test_name XORI_6
+load r3 0xaa55aa55
+xori r3, r3, 0x5555
+check_r3 0xaa55ff00
+
+end
diff --git a/src/tests/tcg/mips/mips32-dsp/Makefile b/src/tests/tcg/mips/mips32-dsp/Makefile
new file mode 100644
index 0000000..c3a0a00
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/Makefile
@@ -0,0 +1,136 @@
+-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 += addq_s_w.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/src/tests/tcg/mips/mips32-dsp/absq_s_ph.c b/src/tests/tcg/mips/mips32-dsp/absq_s_ph.c
new file mode 100644
index 0000000..aa84112
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/absq_s_w.c b/src/tests/tcg/mips/mips32-dsp/absq_s_w.c
new file mode 100644
index 0000000..3f52a48
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/addq_ph.c b/src/tests/tcg/mips/mips32-dsp/addq_ph.c
new file mode 100644
index 0000000..96a5496
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/addq_ph.c
@@ -0,0 +1,46 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int dsp;
+ 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);
+
+ rs = 0x7fff847D;
+ rt = 0x0031AF2D;
+ result = 0x803033AA;
+ __asm
+ ("addq.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ __asm("rddsp %0\n\t"
+ : "=r"(dsp)
+ );
+ assert(((dsp >> 20) & 0x01) == 1);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/addq_s_ph.c b/src/tests/tcg/mips/mips32-dsp/addq_s_ph.c
new file mode 100644
index 0000000..5f865f6
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/addq_s_ph.c
@@ -0,0 +1,69 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int dsp;
+ 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);
+
+ __asm
+ ("rddsp %0\n\t"
+ : "=r"(dsp)
+ );
+ assert(((dsp >> 20) & 0x01) == 1);
+
+ rs = 0x7fff847D;
+ rt = 0x0031AF2D;
+ result = 0x7fff8000;
+ __asm
+ ("addq_s.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ __asm
+ ("rddsp %0\n\t"
+ : "=r"(dsp)
+ );
+ assert(((dsp >> 20) & 0x01) == 1);
+
+ rs = 0x8030847D;
+ rt = 0x8a00AF2D;
+ result = 0x80008000;
+ __asm
+ ("addq_s.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ __asm
+ ("rddsp %0\n\t"
+ : "=r"(dsp)
+ );
+ assert(((dsp >> 20) & 0x01) == 1);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/addq_s_w.c b/src/tests/tcg/mips/mips32-dsp/addq_s_w.c
new file mode 100644
index 0000000..1e13acf
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/addq_s_w.c
@@ -0,0 +1,44 @@
+#include<stdio.h>
+#include<assert.h>
+
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rt = 0x10017EFD;
+ rs = 0x11111111;
+ result = 0x2112900e;
+
+ __asm
+ ("addq_s.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rt = 0x80017EFD;
+ rs = 0x81111111;
+ result = 0x80000000;
+
+ __asm
+ ("addq_s.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rt = 0x7fffffff;
+ rs = 0x01111111;
+ result = 0x7fffffff;
+
+ __asm
+ ("addq_s.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/addsc.c b/src/tests/tcg/mips/mips32-dsp/addsc.c
new file mode 100644
index 0000000..ace749f
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/addsc.c
@@ -0,0 +1,33 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int dsp;
+ 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, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+ assert(((dsp >> 13) & 0x01) == 1);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/addu_qb.c b/src/tests/tcg/mips/mips32-dsp/addu_qb.c
new file mode 100644
index 0000000..23ba2e9
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/addu_qb.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int dsp;
+ int result;
+
+ rs = 0x00FF00FF;
+ rt = 0x00010001;
+ result = 0x00000000;
+ __asm
+ ("addu.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+ assert(((dsp >> 20) & 0x01) == 1);
+
+ rs = 0xFFFF1111;
+ rt = 0x00020001;
+ result = 0xFF011112;
+ __asm
+ ("addu.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+ assert(((dsp >> 20) & 0x01) == 1);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/addu_s_qb.c b/src/tests/tcg/mips/mips32-dsp/addu_s_qb.c
new file mode 100644
index 0000000..fe7fd3e
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/addu_s_qb.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int dsp;
+ int result;
+
+ rs = 0x10FF01FF;
+ rt = 0x10010001;
+ result = 0x20FF01FF;
+ __asm
+ ("addu_s.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+ assert(((dsp >> 20) & 0x1) == 1);
+
+ rs = 0xFFFF1111;
+ rt = 0x00020001;
+ result = 0xFFFF1112;
+ __asm
+ ("addu_s.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+ assert(((dsp >> 20) & 0x1) == 1);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/addwc.c b/src/tests/tcg/mips/mips32-dsp/addwc.c
new file mode 100644
index 0000000..8a8d81f
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/addwc.c
@@ -0,0 +1,49 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int dspi, dspo;
+ int result;
+
+ rs = 0x10FF01FF;
+ rt = 0x10010001;
+ dspi = 0x00002000;
+ result = 0x21000201;
+ __asm
+ ("wrdsp %3\n"
+ "addwc %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt), "r"(dspi)
+ );
+ assert(rd == result);
+
+ rs = 0xFFFF1111;
+ rt = 0x00020001;
+ dspi = 0x00;
+ result = 0x00011112;
+ __asm
+ ("wrdsp %3\n"
+ "addwc %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt), "r"(dspi)
+ );
+ assert(rd == result);
+
+ rs = 0x8FFF1111;
+ rt = 0x80020001;
+ dspi = 0x00;
+ result = 0x10011112;
+ __asm
+ ("wrdsp %4\n"
+ "addwc %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dspo)
+ : "r"(rs), "r"(rt), "r"(dspi)
+ );
+ assert(rd == result);
+ assert(((dspo >> 20) & 0x01) == 1);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/bitrev.c b/src/tests/tcg/mips/mips32-dsp/bitrev.c
new file mode 100644
index 0000000..04d8a38
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/bposge32.c b/src/tests/tcg/mips/mips32-dsp/bposge32.c
new file mode 100644
index 0000000..d25417e
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/cmp_eq_ph.c b/src/tests/tcg/mips/mips32-dsp/cmp_eq_ph.c
new file mode 100644
index 0000000..957bd88
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/cmp_le_ph.c b/src/tests/tcg/mips/mips32-dsp/cmp_le_ph.c
new file mode 100644
index 0000000..356f156
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/cmp_lt_ph.c b/src/tests/tcg/mips/mips32-dsp/cmp_lt_ph.c
new file mode 100644
index 0000000..3fb4827
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c b/src/tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c
new file mode 100644
index 0000000..2615c84
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c b/src/tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c
new file mode 100644
index 0000000..65d0813
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c b/src/tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c
new file mode 100644
index 0000000..7dddad9
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c b/src/tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c
new file mode 100644
index 0000000..680f2a1
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/cmpu_le_qb.c b/src/tests/tcg/mips/mips32-dsp/cmpu_le_qb.c
new file mode 100644
index 0000000..43cfa50
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c b/src/tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c
new file mode 100644
index 0000000..074ca5b
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c b/src/tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c
new file mode 100644
index 0000000..a6425b6
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c b/src/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c
new file mode 100644
index 0000000..cbf9007
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c
@@ -0,0 +1,125 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt, dsp;
+ int ach = 0, acl = 0;
+ int resulth, resultl, resultdsp;
+
+ rs = 0x80000000;
+ rt = 0x80000000;
+ resulth = 0x7FFFFFFF;
+ resultl = 0xFFFFFFFF;
+ resultdsp = 0x01;
+ __asm
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $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);
+
+ ach = 0x00000012;
+ acl = 0x00000048;
+ rs = 0x80000000;
+ rt = 0x80000000;
+
+ resulth = 0x7FFFFFFF;
+ resultl = 0xFFFFFFFF;
+ resultdsp = 0x01;
+ __asm
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $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);
+
+ ach = 0x741532A0;
+ acl = 0xFCEABB08;
+ rs = 0x80000000;
+ rt = 0x80000000;
+
+ resulth = 0x7FFFFFFF;
+ resultl = 0xFFFFFFFF;
+ resultdsp = 0x01;
+ __asm
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $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);
+
+ ach = 0;
+ acl = 0;
+ rs = 0xC0000000;
+ rt = 0x7FFFFFFF;
+
+ resulth = 0xC0000000;
+ resultl = 0x80000000;
+ resultdsp = 0;
+ __asm
+ ("wrdsp $0\n\t"
+ "mthi %0, $ac1\n\t"
+ "mtlo %1, $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);
+
+ ach = 0x20000000;
+ acl = 0;
+ rs = 0xE0000000;
+ rt = 0x7FFFFFFF;
+
+ resulth = 0;
+ resultl = 0x40000000;
+ resultdsp = 0;
+ __asm
+ ("wrdsp $0\n\t"
+ "mthi %0, $ac1\n\t"
+ "mtlo %1, $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/src/tests/tcg/mips/mips32-dsp/dpau_h_qbl.c b/src/tests/tcg/mips/mips32-dsp/dpau_h_qbl.c
new file mode 100644
index 0000000..6017b5e
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/dpau_h_qbr.c b/src/tests/tcg/mips/mips32-dsp/dpau_h_qbr.c
new file mode 100644
index 0000000..e4abb2e
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c b/src/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c
new file mode 100644
index 0000000..74058fe
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c
@@ -0,0 +1,45 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int ach = 5, acl = 5;
+ int resulth, resultl;
+
+ rs = 0xBC0123AD;
+ rt = 0x01643721;
+ resulth = 0x00000004;
+ resultl = 0xF15F94A3;
+ __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);
+
+ ach = 0x1424EF1F;
+ acl = 0x1035219A;
+ rs = 0x800083AD;
+ rt = 0x80003721;
+ resulth = 0x1424EF1E;
+ resultl = 0xC5C0D901;
+ __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/src/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c b/src/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c
new file mode 100644
index 0000000..eda3b14
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c
@@ -0,0 +1,55 @@
+#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 = 0x00BD3A22;
+ resultl = 0xD138776B;
+ resultdsp = 0x00;
+ __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);
+
+ ach = 0x54321123;
+ acl = 5;
+ rs = 0x80000000;
+ rt = 0x80000000;
+
+ resulth = 0xd4321123;
+ resultl = 0x06;
+ 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/src/tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c b/src/tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c
new file mode 100644
index 0000000..94e2bf6
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c b/src/tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c
new file mode 100644
index 0000000..a1e6635
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/extp.c b/src/tests/tcg/mips/mips32-dsp/extp.c
new file mode 100644
index 0000000..b18bdb3
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/extp.c
@@ -0,0 +1,62 @@
+#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);
+
+ ach = 0;
+ acl = 0x80000001;
+ dsp = 0x1F;
+ result = 0x80000001;
+
+ __asm
+ ("wrdsp %1\n\t"
+ "mthi %2, $ac2\n\t"
+ "mtlo %3, $ac2\n\t"
+ "extp %0, $ac2, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 14) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/extpdp.c b/src/tests/tcg/mips/mips32-dsp/extpdp.c
new file mode 100644
index 0000000..79ee16e
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/extpdp.c
@@ -0,0 +1,64 @@
+#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);
+
+
+ ach = 0;
+ acl = 0;
+ dsp = 0;
+ result = 0;
+
+ __asm
+ ("wrdsp %1\n\t"
+ "mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extpdp %0, $ac1, 0x00\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ assert(dsp == 0x3F);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/extpdpv.c b/src/tests/tcg/mips/mips32-dsp/extpdpv.c
new file mode 100644
index 0000000..f5774ee
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/extpv.c b/src/tests/tcg/mips/mips32-dsp/extpv.c
new file mode 100644
index 0000000..401b94a
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/extr_r_w.c b/src/tests/tcg/mips/mips32-dsp/extr_r_w.c
new file mode 100644
index 0000000..489c193
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/extr_r_w.c
@@ -0,0 +1,94 @@
+#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);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x01;
+ acl = 0xB4CB;
+ result = 0x10000B4D;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_r.w %0, $ac1, 0x04\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x3fffffff;
+ acl = 0x2bcdef01;
+ result = 0x7ffffffe;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_r.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0xFFFFFFFF;
+ acl = 0xFFFFFFFF;
+ result = 0;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_r.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/extr_rs_w.c b/src/tests/tcg/mips/mips32-dsp/extr_rs_w.c
new file mode 100644
index 0000000..f9d2ed6
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/extr_rs_w.c
@@ -0,0 +1,117 @@
+#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);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x01;
+ acl = 0xB4CB;
+ result = 0x10000B4D;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_rs.w %0, $ac1, 0x04\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x3fffffff;
+ acl = 0x2bcdef01;
+ result = 0x7ffffffe;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_rs.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x80000000;
+ acl = 0x00000000;
+ result = 0x80000000;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_rs.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 1);
+ assert(result == rt);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0xFFFFFFFF;
+ acl = 0xFFFFFFFF;
+ result = 0;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_rs.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/extr_s_h.c b/src/tests/tcg/mips/mips32-dsp/extr_s_h.c
new file mode 100644
index 0000000..9bc2a63
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/extr_s_h.c
@@ -0,0 +1,86 @@
+#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);
+
+ ach = 0xffffffff;
+ acl = 0x12344321;
+ result = 0xFFFF8000;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_s.h %0, $ac1, 0x08\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 1);
+ assert(result == rt);
+
+ /* Clear dsp */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x00;
+ acl = 0x4321;
+ result = 0x432;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_s.h %0, $ac1, 0x04\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ /* Clear dsp */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x123;
+ acl = 0x87654321;
+ result = 0x1238;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_s.h %0, $ac1, 28\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/extr_w.c b/src/tests/tcg/mips/mips32-dsp/extr_w.c
new file mode 100644
index 0000000..cf92614
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/extr_w.c
@@ -0,0 +1,94 @@
+#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);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x01;
+ acl = 0xB4CB;
+ result = 0x10000B4C;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr.w %0, $ac1, 0x04\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x3fffffff;
+ acl = 0x2bcdef01;
+ result = 0x7ffffffe;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0xFFFFFFFF;
+ acl = 0xFFFFFFFF;
+ result = 0xFFFFFFFF;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr.w %0, $ac1, 0x1F\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/extrv_r_w.c b/src/tests/tcg/mips/mips32-dsp/extrv_r_w.c
new file mode 100644
index 0000000..2403b3a
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/extrv_r_w.c
@@ -0,0 +1,79 @@
+#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);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 4;
+ ach = 0x01;
+ acl = 0xB4CB;
+ result = 0x10000B4D;
+ __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 == 0);
+ assert(result == rt);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 31;
+ ach = 0x3fffffff;
+ acl = 0x2bcdef01;
+ result = 0x7ffffffe;
+ __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 == 0);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/extrv_rs_w.c b/src/tests/tcg/mips/mips32-dsp/extrv_rs_w.c
new file mode 100644
index 0000000..ccceeb9
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/extrv_rs_w.c
@@ -0,0 +1,77 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs, ach, acl, dsp;
+ int result;
+
+ rs = 0x03;
+ ach = 0x05;
+ acl = 0xB4CB;
+ 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);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 0x04;
+ ach = 0x01;
+ acl = 0xB4CB;
+ result = 0x10000B4D;
+ __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 == 0);
+ assert(result == rt);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 0x1F;
+ ach = 0x3fffffff;
+ acl = 0x2bcdef01;
+ result = 0x7ffffffe;
+ __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 == 0);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/extrv_s_h.c b/src/tests/tcg/mips/mips32-dsp/extrv_s_h.c
new file mode 100644
index 0000000..feac3e2
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/extrv_s_h.c
@@ -0,0 +1,88 @@
+#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);
+
+ rs = 0x08;
+ ach = 0xffffffff;
+ acl = 0x12344321;
+ result = 0xFFFF8000;
+ __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);
+
+ /* Clear dsp */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 0x04;
+ ach = 0x00;
+ acl = 0x4321;
+ result = 0x432;
+ __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 == 0);
+ assert(result == rt);
+
+ rs = 0x1C;
+ ach = 0x123;
+ acl = 0x87654321;
+ result = 0x1238;
+ __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 == 0);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/extrv_w.c b/src/tests/tcg/mips/mips32-dsp/extrv_w.c
new file mode 100644
index 0000000..9e8b238
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/extrv_w.c
@@ -0,0 +1,80 @@
+#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);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 4;
+ ach = 0x01;
+ acl = 0xB4CB;
+ result = 0x10000B4C;
+ __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 == 0);
+ assert(result == rt);
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 31;
+ ach = 0x3fffffff;
+ acl = 0x2bcdef01;
+ result = 0x7ffffffe;
+ __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 == 0);
+ assert(result == rt);
+
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/insv.c b/src/tests/tcg/mips/mips32-dsp/insv.c
new file mode 100644
index 0000000..9d67469
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/insv.c
@@ -0,0 +1,36 @@
+#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 = 0x12345438;
+ __asm
+ ("wrdsp %2, 0x03\n\t"
+ "insv %0, %1\n\t"
+ : "+r"(rt)
+ : "r"(rs), "r"(dsp)
+ );
+ assert(rt == result);
+
+ dsp = 0x1000;
+ rt = 0xF0F0F0F0;
+ rs = 0xA5A5A5A5;
+ result = 0xA5A5A5A5;
+
+ __asm
+ ("wrdsp %2\n\t"
+ "insv %0, %1\n\t"
+ : "+r"(rt)
+ : "r"(rs), "r"(dsp)
+ );
+ assert(rt == result);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/lbux.c b/src/tests/tcg/mips/mips32-dsp/lbux.c
new file mode 100644
index 0000000..2337abe
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/lhx.c b/src/tests/tcg/mips/mips32-dsp/lhx.c
new file mode 100644
index 0000000..10be3b3
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/lwx.c b/src/tests/tcg/mips/mips32-dsp/lwx.c
new file mode 100644
index 0000000..e6543c9
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/madd.c b/src/tests/tcg/mips/mips32-dsp/madd.c
new file mode 100644
index 0000000..af4bfcf
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/maddu.c b/src/tests/tcg/mips/mips32-dsp/maddu.c
new file mode 100644
index 0000000..af4bfcf
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/main.c b/src/tests/tcg/mips/mips32-dsp/main.c
new file mode 100644
index 0000000..b296b20
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/main.c
@@ -0,0 +1,6 @@
+#include<stdio.h>
+
+int main()
+{
+ printf("hello world\n");
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c b/src/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c
new file mode 100644
index 0000000..0f7c070
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c
@@ -0,0 +1,55 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs;
+ int achi, acli;
+ int dsp;
+ int acho, aclo;
+ int resulth, resultl;
+ int resdsp;
+
+ achi = 0x00000005;
+ acli = 0x0000B4CB;
+ rs = 0xFF060000;
+ rt = 0xCB000000;
+ resulth = 0x00000005;
+ resultl = 0x006838CB;
+
+ __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);
+
+ achi = 0x00000006;
+ acli = 0x0000B4CB;
+ rs = 0x80000000;
+ rt = 0x80000000;
+ resulth = 0x00000006;
+ resultl = 0x8000B4CA;
+ resdsp = 1;
+
+ __asm
+ ("mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "maq_s.w.phl $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)
+ );
+ assert(resulth == acho);
+ assert(resultl == aclo);
+ assert(((dsp >> 17) & 0x01) == resdsp);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c b/src/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c
new file mode 100644
index 0000000..942722a
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c
@@ -0,0 +1,55 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs;
+ int achi, acli;
+ int dsp;
+ int acho, aclo;
+ int resulth, resultl;
+ int resdsp;
+
+ achi = 0x00000005;
+ acli = 0x0000B4CB;
+ rs = 0x0000FF06;
+ rt = 0x0000CB00;
+ resulth = 0x00000005;
+ resultl = 0x006838CB;
+
+ __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);
+
+ achi = 0x00000006;
+ acli = 0x0000B4CB;
+ rs = 0x00008000;
+ rt = 0x00008000;
+ resulth = 0x00000006;
+ resultl = 0x8000B4CA;
+ resdsp = 1;
+
+ __asm
+ ("mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "maq_s.w.phr $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)
+ );
+ assert(resulth == acho);
+ assert(resultl == aclo);
+ assert(((dsp >> 17) & 0x01) == resdsp);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c b/src/tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c
new file mode 100644
index 0000000..d83dce6
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c
@@ -0,0 +1,55 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs;
+ int achi, acli;
+ int dsp;
+ int acho, aclo;
+ int resulth, resultl;
+ int resdsp;
+
+ achi = 0x00000000;
+ acli = 0x0000B4CB;
+ rs = 0xFF060000;
+ rt = 0xCB000000;
+ resulth = 0x00000000;
+ resultl = 0x006838CB;
+
+ __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);
+
+ achi = 0x00000000;
+ acli = 0x0000B4CB;
+ rs = 0x80000000;
+ rt = 0x80000000;
+ resulth = 0x00;
+ resultl = 0x7fffffff;
+ resdsp = 0x01;
+
+ __asm
+ ("mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "maq_sa.w.phl $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)
+ );
+ assert(resulth == acho);
+ assert(resultl == aclo);
+ assert(((dsp >> 17) & 0x01) == 0x01);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c b/src/tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c
new file mode 100644
index 0000000..d233111
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c
@@ -0,0 +1,55 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs;
+ int achi, acli;
+ int dsp;
+ int acho, aclo;
+ int resulth, resultl;
+ int resdsp;
+
+ achi = 0x00000000;
+ acli = 0x0000B4CB;
+ rs = 0x0000FF06;
+ rt = 0x0000CB00;
+ resulth = 0x00000000;
+ resultl = 0x006838CB;
+
+ __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);
+
+ achi = 0x00000000;
+ acli = 0x0000B4CB;
+ rs = 0x00008000;
+ rt = 0x00008000;
+ resulth = 0x00000000;
+ resultl = 0x7FFFFFFF;
+ resdsp = 0x01;
+
+ __asm
+ ("mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "maq_sa.w.phr $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)
+ );
+ assert(resulth == acho);
+ assert(resultl == aclo);
+ assert(((dsp >> 17) & 0x01) == 0x01);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/mfhi.c b/src/tests/tcg/mips/mips32-dsp/mfhi.c
new file mode 100644
index 0000000..43a8066
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/mflo.c b/src/tests/tcg/mips/mips32-dsp/mflo.c
new file mode 100644
index 0000000..caeafdb
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/modsub.c b/src/tests/tcg/mips/mips32-dsp/modsub.c
new file mode 100644
index 0000000..c294eeb
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/msub.c b/src/tests/tcg/mips/mips32-dsp/msub.c
new file mode 100644
index 0000000..5779e6f
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/msubu.c b/src/tests/tcg/mips/mips32-dsp/msubu.c
new file mode 100644
index 0000000..e0f9b5a
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/mthi.c b/src/tests/tcg/mips/mips32-dsp/mthi.c
new file mode 100644
index 0000000..43a8066
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/mthlip.c b/src/tests/tcg/mips/mips32-dsp/mthlip.c
new file mode 100644
index 0000000..85f94d8
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/mthlip.c
@@ -0,0 +1,58 @@
+#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);
+
+ dsp = 0x1f;
+ ach = 0x05;
+ acl = 0xB4CB;
+ rs = 0x00FFBBAA;
+ resulth = 0xB4CB;
+ resultl = 0x00FFBBAA;
+ result = 0x3f;
+
+ __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/src/tests/tcg/mips/mips32-dsp/mtlo.c b/src/tests/tcg/mips/mips32-dsp/mtlo.c
new file mode 100644
index 0000000..caeafdb
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/muleq_s_w_phl.c b/src/tests/tcg/mips/mips32-dsp/muleq_s_w_phl.c
new file mode 100644
index 0000000..b3a5370
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c b/src/tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c
new file mode 100644
index 0000000..8066d7d
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c b/src/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c
new file mode 100644
index 0000000..66a3828
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c b/src/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c
new file mode 100644
index 0000000..4cc6c8f
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c b/src/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c
new file mode 100644
index 0000000..370c2a8
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c
@@ -0,0 +1,42 @@
+#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
+ ("wrdsp $0\n\t"
+ "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);
+
+ rs = 0x80011234;
+ rt = 0x80024321;
+ result = 0x7FFD098C;
+ resultdsp = 0;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "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/src/tests/tcg/mips/mips32-dsp/mult.c b/src/tests/tcg/mips/mips32-dsp/mult.c
new file mode 100644
index 0000000..15e6fde
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/multu.c b/src/tests/tcg/mips/mips32-dsp/multu.c
new file mode 100644
index 0000000..85d36c1
--- /dev/null
+++ b/src/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
+ ("multu $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/src/tests/tcg/mips/mips32-dsp/packrl_ph.c b/src/tests/tcg/mips/mips32-dsp/packrl_ph.c
new file mode 100644
index 0000000..1f8e699
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/pick_ph.c b/src/tests/tcg/mips/mips32-dsp/pick_ph.c
new file mode 100644
index 0000000..929a002
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/pick_ph.c
@@ -0,0 +1,49 @@
+#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);
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ dsp = 0x03000000;
+ result = 0x12345678;
+
+ __asm
+ ("wrdsp %3, 0x10\n\t"
+ "pick.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt), "r"(dsp)
+ );
+ assert(rd == result);
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ dsp = 0x00000000;
+ result = 0x87654321;
+
+ __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/src/tests/tcg/mips/mips32-dsp/pick_qb.c b/src/tests/tcg/mips/mips32-dsp/pick_qb.c
new file mode 100644
index 0000000..a790475
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/pick_qb.c
@@ -0,0 +1,36 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ dsp = 0x0f000000;
+ result = 0x12345678;
+
+ __asm
+ ("wrdsp %3, 0x10\n\t"
+ "pick.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt), "r"(dsp)
+ );
+ assert(rd == result);
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ dsp = 0x00000000;
+ result = 0x87654321;
+
+ __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/src/tests/tcg/mips/mips32-dsp/preceq_w_phl.c b/src/tests/tcg/mips/mips32-dsp/preceq_w_phl.c
new file mode 100644
index 0000000..bf70bf7
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/preceq_w_phr.c b/src/tests/tcg/mips/mips32-dsp/preceq_w_phr.c
new file mode 100644
index 0000000..3f885ef
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c b/src/tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c
new file mode 100644
index 0000000..63b7a95
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c b/src/tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c
new file mode 100644
index 0000000..31627f0
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c b/src/tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c
new file mode 100644
index 0000000..b6f72d3
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c b/src/tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c
new file mode 100644
index 0000000..4764fd0
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c b/src/tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c
new file mode 100644
index 0000000..fa95c26
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c b/src/tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c
new file mode 100644
index 0000000..021f21a
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c b/src/tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c
new file mode 100644
index 0000000..03df18c
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c b/src/tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c
new file mode 100644
index 0000000..6343276
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/precrq_ph_w.c b/src/tests/tcg/mips/mips32-dsp/precrq_ph_w.c
new file mode 100644
index 0000000..25d45f1
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/precrq_qb_ph.c b/src/tests/tcg/mips/mips32-dsp/precrq_qb_ph.c
new file mode 100644
index 0000000..fe23acc
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c b/src/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c
new file mode 100644
index 0000000..da6845b
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c
@@ -0,0 +1,51 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int dsp;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x12348765;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "precrq_rs.ph.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ rs = 0x7FFFC678;
+ rt = 0x865432A0;
+ result = 0x7FFF8654;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "precrq_rs.ph.w %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ assert(((dsp >> 22) & 0x01) == 1);
+ assert(result == rd);
+
+ rs = 0xBEEFFEED;
+ rt = 0x7FFF8000;
+ result = 0xBEF07FFF;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "precrq_rs.ph.w %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ assert(((dsp >> 22) & 0x01) == 1);
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c b/src/tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c
new file mode 100644
index 0000000..7481d5a
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int dsp;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87657FFF;
+ result = 0x24AC00FF;
+
+ __asm
+ ("precrqu_s.qb.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+ assert(((dsp >> 22) & 0x01) == 0x01);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/raddu_w_qb.c b/src/tests/tcg/mips/mips32-dsp/raddu_w_qb.c
new file mode 100644
index 0000000..77a983c
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/rddsp.c b/src/tests/tcg/mips/mips32-dsp/rddsp.c
new file mode 100644
index 0000000..2f30285
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/rddsp.c
@@ -0,0 +1,46 @@
+#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;
+
+ ccond_i = 0x0000000C; /* 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;
+
+ __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_i);
+ assert(outflag_o == outflag_i);
+ assert(efi_o == efi_i);
+ assert(c_o == c_i);
+ assert(scount_o == scount_i);
+ assert(pos_o == pos_i);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/repl_ph.c b/src/tests/tcg/mips/mips32-dsp/repl_ph.c
new file mode 100644
index 0000000..2107495
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/repl_qb.c b/src/tests/tcg/mips/mips32-dsp/repl_qb.c
new file mode 100644
index 0000000..6631393
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/replv_ph.c b/src/tests/tcg/mips/mips32-dsp/replv_ph.c
new file mode 100644
index 0000000..07fb15f
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/replv_qb.c b/src/tests/tcg/mips/mips32-dsp/replv_qb.c
new file mode 100644
index 0000000..dd1271f
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/shilo.c b/src/tests/tcg/mips/mips32-dsp/shilo.c
new file mode 100644
index 0000000..ce8ebc6
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shilo.c
@@ -0,0 +1,45 @@
+#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);
+
+
+ ach = 0x1;
+ acl = 0x80000000;
+
+ resulth = 0x3;
+ resultl = 0x0;
+
+ __asm
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "shilo $ac1, -1\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/src/tests/tcg/mips/mips32-dsp/shilov.c b/src/tests/tcg/mips/mips32-dsp/shilov.c
new file mode 100644
index 0000000..e1d6cea
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shilov.c
@@ -0,0 +1,49 @@
+#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);
+
+
+ rs = 0xffffffff;
+ ach = 0x1;
+ acl = 0x80000000;
+
+ resulth = 0x3;
+ resultl = 0x0;
+
+ __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/src/tests/tcg/mips/mips32-dsp/shll_ph.c b/src/tests/tcg/mips/mips32-dsp/shll_ph.c
new file mode 100644
index 0000000..5fa58cc
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shll_ph.c
@@ -0,0 +1,55 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt, dsp;
+ int result, resultdsp;
+
+ rt = 0x12345678;
+ result = 0xA000C000;
+ resultdsp = 1;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "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);
+
+ rt = 0x7fff8000;
+ result = 0xfffe0000;
+ resultdsp = 1;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "shll.ph %0, %2, 0x01\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rt)
+ );
+ dsp = (dsp >> 22) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ rt = 0x00000001;
+ result = 0x00008000;
+ resultdsp = 1;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "shll.ph %0, %2, 0x0F\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/src/tests/tcg/mips/mips32-dsp/shll_qb.c b/src/tests/tcg/mips/mips32-dsp/shll_qb.c
new file mode 100644
index 0000000..729716d
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shll_qb.c
@@ -0,0 +1,55 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt, dsp;
+ int result, resultdsp;
+
+ rt = 0x87654321;
+ result = 0x87654321;
+ resultdsp = 0x00;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "shll.qb %0, %2, 0x00\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rt)
+ );
+ dsp = (dsp >> 22) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ rt = 0x87654321;
+ result = 0x38281808;
+ resultdsp = 0x01;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "shll.qb %0, %2, 0x03\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rt)
+ );
+ dsp = (dsp >> 22) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ rt = 0x00000001;
+ result = 0x00000080;
+ resultdsp = 0x00;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "shll.qb %0, %2, 0x07\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/src/tests/tcg/mips/mips32-dsp/shll_s_ph.c b/src/tests/tcg/mips/mips32-dsp/shll_s_ph.c
new file mode 100644
index 0000000..910fea3
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/shll_s_w.c b/src/tests/tcg/mips/mips32-dsp/shll_s_w.c
new file mode 100644
index 0000000..628c752
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shll_s_w.c
@@ -0,0 +1,52 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt, dsp;
+ int result, resultdsp;
+
+ rt = 0x82345678;
+ result = 0x82345678;
+ resultdsp = 0x00;
+
+ __asm
+ ("shll_s.w %0, %2, 0x0\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rt)
+ );
+ dsp = (dsp >> 22) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ rt = 0x82345678;
+ result = 0x80000000;
+ 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);
+
+ 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/src/tests/tcg/mips/mips32-dsp/shllv_ph.c b/src/tests/tcg/mips/mips32-dsp/shllv_ph.c
new file mode 100644
index 0000000..f98a632
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shllv_ph.c
@@ -0,0 +1,40 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x0;
+ rt = 0x12345678;
+ result = 0x12345678;
+ resultdsp = 0;
+
+ __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);
+
+ 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/src/tests/tcg/mips/mips32-dsp/shllv_qb.c b/src/tests/tcg/mips/mips32-dsp/shllv_qb.c
new file mode 100644
index 0000000..6d8ff4a
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shllv_qb.c
@@ -0,0 +1,38 @@
+#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);
+
+ rs = 0x00;
+ rt = 0x87654321;
+ result = 0x87654321;
+ 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/src/tests/tcg/mips/mips32-dsp/shllv_s_ph.c b/src/tests/tcg/mips/mips32-dsp/shllv_s_ph.c
new file mode 100644
index 0000000..fc9bd32
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shllv_s_ph.c
@@ -0,0 +1,40 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x0;
+ rt = 0x12345678;
+ result = 0x12345678;
+ resultdsp = 0x0;
+
+ __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);
+
+ 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/src/tests/tcg/mips/mips32-dsp/shllv_s_w.c b/src/tests/tcg/mips/mips32-dsp/shllv_s_w.c
new file mode 100644
index 0000000..350c256
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shllv_s_w.c
@@ -0,0 +1,40 @@
+#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);
+
+ rs = 0x0;
+ rt = 0x12345678;
+ result = 0x12345678;
+ 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/src/tests/tcg/mips/mips32-dsp/shra_ph.c b/src/tests/tcg/mips/mips32-dsp/shra_ph.c
new file mode 100644
index 0000000..5b2d840
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shra_ph.c
@@ -0,0 +1,30 @@
+#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);
+
+ rt = 0x87654321;
+ result = 0x87654321;
+
+ __asm
+ ("shra.ph %0, %1, 0x00\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/shra_r_ph.c b/src/tests/tcg/mips/mips32-dsp/shra_r_ph.c
new file mode 100644
index 0000000..adc4ae6
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shra_r_ph.c
@@ -0,0 +1,30 @@
+#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);
+
+ rt = 0x87654321;
+ result = 0x87654321;
+
+ __asm
+ ("shra_r.ph %0, %1, 0x00\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/shra_r_w.c b/src/tests/tcg/mips/mips32-dsp/shra_r_w.c
new file mode 100644
index 0000000..ec0cf2c
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shra_r_w.c
@@ -0,0 +1,30 @@
+#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);
+
+ rt = 0x87654321;
+ result = 0x87654321;
+
+ __asm
+ ("shra_r.w %0, %1, 0x0\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/shrav_ph.c b/src/tests/tcg/mips/mips32-dsp/shrav_ph.c
new file mode 100644
index 0000000..6e42aaf
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shrav_ph.c
@@ -0,0 +1,32 @@
+#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);
+
+ rs = 0x00;
+ rt = 0x87654321;
+ result = 0x87654321;
+
+ __asm
+ ("shrav.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/shrav_r_ph.c b/src/tests/tcg/mips/mips32-dsp/shrav_r_ph.c
new file mode 100644
index 0000000..f03b978
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shrav_r_ph.c
@@ -0,0 +1,32 @@
+#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);
+
+ rs = 0x00;
+ rt = 0x87654321;
+ result = 0x87654321;
+
+ __asm
+ ("shrav_r.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/shrav_r_w.c b/src/tests/tcg/mips/mips32-dsp/shrav_r_w.c
new file mode 100644
index 0000000..2ab03bb
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shrav_r_w.c
@@ -0,0 +1,32 @@
+#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);
+
+ rs = 0x00;
+ rt = 0x40000000;
+ result = 0x40000000;
+
+ __asm
+ ("shrav_r.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+
+ assert(rd == result);
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/shrl_qb.c b/src/tests/tcg/mips/mips32-dsp/shrl_qb.c
new file mode 100644
index 0000000..a7e4e6a
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shrl_qb.c
@@ -0,0 +1,31 @@
+#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);
+
+ rt = 0x12345678;
+ result = 0x12345678;
+
+ __asm
+ ("shrl.qb %0, %1, 0x0\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/shrlv_qb.c b/src/tests/tcg/mips/mips32-dsp/shrlv_qb.c
new file mode 100644
index 0000000..db77f6d
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/shrlv_qb.c
@@ -0,0 +1,32 @@
+#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);
+
+ rs = 0x00;
+ rt = 0x12345678;
+ result = 0x12345678;
+
+ __asm
+ ("shrlv.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dsp/subq_ph.c b/src/tests/tcg/mips/mips32-dsp/subq_ph.c
new file mode 100644
index 0000000..fdd7b38
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/subq_ph.c
@@ -0,0 +1,40 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x77777777;
+ rt = 0x67654321;
+ result = 0x10123456;
+ resultdsp = 0x0;
+
+ __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);
+
+ 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/src/tests/tcg/mips/mips32-dsp/subq_s_ph.c b/src/tests/tcg/mips/mips32-dsp/subq_s_ph.c
new file mode 100644
index 0000000..64c89eb
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/subq_s_ph.c
@@ -0,0 +1,58 @@
+#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
+ ("wrdsp $0\n\t"
+ "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);
+
+ rs = 0x12348000;
+ rt = 0x87657000;
+ result = 0x7FFF8000;
+ resultdsp = 0x01;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "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);
+
+ rs = 0x12340000;
+ rt = 0x87658000;
+ result = 0x7FFF7FFF;
+ resultdsp = 0x01;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "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/src/tests/tcg/mips/mips32-dsp/subq_s_w.c b/src/tests/tcg/mips/mips32-dsp/subq_s_w.c
new file mode 100644
index 0000000..9d456a9
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/subq_s_w.c
@@ -0,0 +1,74 @@
+#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
+ ("wrdsp $0\n\t"
+ "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);
+
+ rs = 0x66666;
+ rt = 0x55555;
+ result = 0x11111;
+ resultdsp = 0x0;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "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);
+
+ rs = 0x0;
+ rt = 0x80000000;
+ result = 0x7FFFFFFF;
+ resultdsp = 0x01;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "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);
+
+ rs = 0x80000000;
+ rt = 0x80000000;
+ result = 0;
+ resultdsp = 0x00;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "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/src/tests/tcg/mips/mips32-dsp/subu_qb.c b/src/tests/tcg/mips/mips32-dsp/subu_qb.c
new file mode 100644
index 0000000..4209096
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/subu_s_qb.c b/src/tests/tcg/mips/mips32-dsp/subu_s_qb.c
new file mode 100644
index 0000000..3d65053
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dsp/wrdsp.c b/src/tests/tcg/mips/mips32-dsp/wrdsp.c
new file mode 100644
index 0000000..dc54943
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dsp/wrdsp.c
@@ -0,0 +1,46 @@
+#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;
+
+ 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;
+
+ __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_i & 0x0F));
+ assert(outflag_o == outflag_i);
+ assert(efi_o == efi_i);
+ assert(c_o == c_i);
+ assert(scount_o == scount_i);
+ assert(pos_o == pos_i);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dspr2/Makefile b/src/tests/tcg/mips/mips32-dspr2/Makefile
new file mode 100644
index 0000000..ed19581
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/Makefile
@@ -0,0 +1,71 @@
+-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 += 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/src/tests/tcg/mips/mips32-dspr2/absq_s_qb.c b/src/tests/tcg/mips/mips32-dspr2/absq_s_qb.c
new file mode 100644
index 0000000..af4683f
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/addqh_ph.c b/src/tests/tcg/mips/mips32-dspr2/addqh_ph.c
new file mode 100644
index 0000000..921f0ea
--- /dev/null
+++ b/src/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 = 0x81000100;
+ rt = 0xc2000100;
+ result = 0xa1800100;
+ __asm
+ ("addqh.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dspr2/addqh_r_ph.c b/src/tests/tcg/mips/mips32-dspr2/addqh_r_ph.c
new file mode 100644
index 0000000..213ba37
--- /dev/null
+++ b/src/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 = 0x81010100;
+ rt = 0xc2000100;
+ result = 0xa1810100;
+ __asm
+ ("addqh_r.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dspr2/addqh_r_w.c b/src/tests/tcg/mips/mips32-dspr2/addqh_r_w.c
new file mode 100644
index 0000000..75a75c5
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/addqh_w.c b/src/tests/tcg/mips/mips32-dspr2/addqh_w.c
new file mode 100644
index 0000000..de6926e
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/addu_ph.c b/src/tests/tcg/mips/mips32-dspr2/addu_ph.c
new file mode 100644
index 0000000..1d7a25a
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/addu_ph.c
@@ -0,0 +1,33 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int dsp;
+ 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, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+ assert(((dsp >> 20) & 0x01) == 1);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dspr2/addu_s_ph.c b/src/tests/tcg/mips/mips32-dspr2/addu_s_ph.c
new file mode 100644
index 0000000..979651b
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/addu_s_ph.c
@@ -0,0 +1,33 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int dsp;
+ 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, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+ assert(((dsp >> 20) & 0x01) == 1);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips32-dspr2/adduh_qb.c b/src/tests/tcg/mips/mips32-dspr2/adduh_qb.c
new file mode 100644
index 0000000..a1f5d63
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/adduh_r_qb.c b/src/tests/tcg/mips/mips32-dspr2/adduh_r_qb.c
new file mode 100644
index 0000000..81e98c1
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/append.c b/src/tests/tcg/mips/mips32-dspr2/append.c
new file mode 100644
index 0000000..9a91e16
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/balign.c b/src/tests/tcg/mips/mips32-dspr2/balign.c
new file mode 100644
index 0000000..537cf04
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c b/src/tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c
new file mode 100644
index 0000000..2d6340d
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c b/src/tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c
new file mode 100644
index 0000000..a0ecdca
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c b/src/tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c
new file mode 100644
index 0000000..dba99e3
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c b/src/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c
new file mode 100644
index 0000000..fae49f1
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c
@@ -0,0 +1,44 @@
+#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);
+
+ ach = 6, acl = 7;
+ rs = 0xFFFF00FF;
+ rt = 0xFFFF0002;
+ resulth = 0x06;
+ resultl = 0x206;
+ __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/src/tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c b/src/tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c
new file mode 100644
index 0000000..ce87830
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c
@@ -0,0 +1,79 @@
+#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);
+
+ ach = 5;
+ acl = 5;
+ rs = 0x800000FF;
+ rt = 0x00028000;
+ resulth = 0x05;
+ resultl = 0x80000400;
+ 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/src/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c b/src/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c
new file mode 100644
index 0000000..d551d64
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c
@@ -0,0 +1,57 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt, dsp;
+ int ach, acl;
+ int resulth, resultl, resultdsp;
+
+ ach = 0x00000005;
+ acl = 0x00000005;
+ rs = 0x00FF00FF;
+ rt = 0x00010002;
+ resulth = 0x00;
+ resultl = 0x7FFFFFFF;
+ resultdsp = 0x01;
+ dsp = 0;
+ __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);
+
+ ach = 0x00000009;
+ acl = 0x0000000B;
+ rs = 0x800000FF;
+ rt = 0x00018000;
+ resulth = 0x00;
+ resultl = 0x7FFFFFFF;
+ resultdsp = 0x01;
+ dsp = 0;
+ __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/src/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c b/src/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c
new file mode 100644
index 0000000..514797c
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c
@@ -0,0 +1,44 @@
+#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);
+
+ ach = 6, acl = 7;
+ rs = 0xFFFF00FF;
+ rt = 0xFFFF0002;
+ resulth = 0x05;
+ resultl = 0xFFFFFF06;
+ __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/src/tests/tcg/mips/mips32-dspr2/dps_w_ph.c b/src/tests/tcg/mips/mips32-dspr2/dps_w_ph.c
new file mode 100644
index 0000000..f51f9b9
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/dps_w_ph.c
@@ -0,0 +1,44 @@
+#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);
+
+ ach = 6, acl = 7;
+ rs = 0xFFFF00FF;
+ rt = 0xFFFF0002;
+ resulth = 0x05;
+ resultl = 0xFFFFFE08;
+ __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/src/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c b/src/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c
new file mode 100644
index 0000000..e40543f
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c
@@ -0,0 +1,54 @@
+#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 = 0x00000005;
+ resultl = 0x1CE5E09B;
+ 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);
+
+ ach = 0x99F13005;
+ acl = 0x51730062;
+ rs = 0x80008000;
+ rt = 0x80008000;
+
+ resulth = 0x99F13004;
+ resultl = 0x51730064;
+ resultdsp = 0x01;
+ __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/src/tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c b/src/tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c
new file mode 100644
index 0000000..7da278e
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c
@@ -0,0 +1,53 @@
+#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);
+
+ ach = 0x8c0b354A;
+ acl = 0xbbc02249;
+ rs = 0x800023AD;
+ rt = 0x01648000;
+ resulth = 0xffffffff;
+ resultl = 0x80000000;
+ 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/src/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c b/src/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c
new file mode 100644
index 0000000..bb49a40
--- /dev/null
+++ b/src/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 = 0x05;
+ resultl = 0xE72F050;
+ __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/src/tests/tcg/mips/mips32-dspr2/mul_ph.c b/src/tests/tcg/mips/mips32-dspr2/mul_ph.c
new file mode 100644
index 0000000..c7e9d60
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/mul_ph.c
@@ -0,0 +1,47 @@
+#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);
+
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 0x00210010;
+ rt = 0x00110005;
+ result = 0x2310050;
+ resultdsp = 0;
+
+ __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/src/tests/tcg/mips/mips32-dspr2/mul_s_ph.c b/src/tests/tcg/mips/mips32-dspr2/mul_s_ph.c
new file mode 100644
index 0000000..33da110
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/mul_s_ph.c
@@ -0,0 +1,62 @@
+#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);
+
+ rs = 0x7fffff00;
+ rt = 0xff007fff;
+ result = 0x80008000;
+ 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);
+
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 0x00320001;
+ rt = 0x00210002;
+ result = 0x06720002;
+ resultdsp = 0;
+
+ __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/src/tests/tcg/mips/mips32-dspr2/mulq_rs_w.c b/src/tests/tcg/mips/mips32-dspr2/mulq_rs_w.c
new file mode 100644
index 0000000..7ba633b
--- /dev/null
+++ b/src/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 = 0x7FFFAAAB;
+
+ __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/src/tests/tcg/mips/mips32-dspr2/mulq_s_ph.c b/src/tests/tcg/mips/mips32-dspr2/mulq_s_ph.c
new file mode 100644
index 0000000..00e0155
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/mulq_s_ph.c
@@ -0,0 +1,40 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x80000000;
+ rt = 0x0ffc0000;
+ result = 0xF0040000;
+ resultdsp = 0;
+
+ __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);
+
+ 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/src/tests/tcg/mips/mips32-dspr2/mulq_s_w.c b/src/tests/tcg/mips/mips32-dspr2/mulq_s_w.c
new file mode 100644
index 0000000..9c2be06
--- /dev/null
+++ b/src/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 = 0x7FFFAAAB;
+
+ __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/src/tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c b/src/tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c
new file mode 100644
index 0000000..a694093
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c b/src/tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c
new file mode 100644
index 0000000..06c91a4
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/precr_qb_ph.c b/src/tests/tcg/mips/mips32-dspr2/precr_qb_ph.c
new file mode 100644
index 0000000..3a2b3fd
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c b/src/tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c
new file mode 100644
index 0000000..5c9baab
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c b/src/tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c
new file mode 100644
index 0000000..6474a10
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/prepend.c b/src/tests/tcg/mips/mips32-dspr2/prepend.c
new file mode 100644
index 0000000..f6bcd47
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/shra_qb.c b/src/tests/tcg/mips/mips32-dspr2/shra_qb.c
new file mode 100644
index 0000000..48193de
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/shra_r_qb.c b/src/tests/tcg/mips/mips32-dspr2/shra_r_qb.c
new file mode 100644
index 0000000..29afa0e
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/shrav_qb.c b/src/tests/tcg/mips/mips32-dspr2/shrav_qb.c
new file mode 100644
index 0000000..b21e1b7
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/shrav_r_qb.c b/src/tests/tcg/mips/mips32-dspr2/shrav_r_qb.c
new file mode 100644
index 0000000..9ea8aa0
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/shrl_ph.c b/src/tests/tcg/mips/mips32-dspr2/shrl_ph.c
new file mode 100644
index 0000000..724b9a7
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/shrlv_ph.c b/src/tests/tcg/mips/mips32-dspr2/shrlv_ph.c
new file mode 100644
index 0000000..ac79aa6
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/subqh_ph.c b/src/tests/tcg/mips/mips32-dspr2/subqh_ph.c
new file mode 100644
index 0000000..dbc0967
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/subqh_r_ph.c b/src/tests/tcg/mips/mips32-dspr2/subqh_r_ph.c
new file mode 100644
index 0000000..24ef0f1
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/subqh_r_w.c b/src/tests/tcg/mips/mips32-dspr2/subqh_r_w.c
new file mode 100644
index 0000000..d460f86
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/subqh_w.c b/src/tests/tcg/mips/mips32-dspr2/subqh_w.c
new file mode 100644
index 0000000..42be3de
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/subu_ph.c b/src/tests/tcg/mips/mips32-dspr2/subu_ph.c
new file mode 100644
index 0000000..0d39a01
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/subu_ph.c
@@ -0,0 +1,40 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x87654321;
+ rt = 0x11111111;
+ result = 0x76543210;
+ resultdsp = 0x00;
+
+ __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);
+
+ 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/src/tests/tcg/mips/mips32-dspr2/subu_s_ph.c b/src/tests/tcg/mips/mips32-dspr2/subu_s_ph.c
new file mode 100644
index 0000000..8e4da4f
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/subuh_qb.c b/src/tests/tcg/mips/mips32-dspr2/subuh_qb.c
new file mode 100644
index 0000000..92cfc76
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips32-dspr2/subuh_r_qb.c b/src/tests/tcg/mips/mips32-dspr2/subuh_r_qb.c
new file mode 100644
index 0000000..dac81d4
--- /dev/null
+++ b/src/tests/tcg/mips/mips32-dspr2/subuh_r_qb.c
@@ -0,0 +1,32 @@
+#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);
+
+ rs = 0xBEFC292A;
+ rt = 0x9205C1B4;
+ result = 0x167cb4bb;
+
+ __asm
+ ("subuh_r.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/Makefile b/src/tests/tcg/mips/mips64-dsp/Makefile
new file mode 100644
index 0000000..b2ac6b3
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/Makefile
@@ -0,0 +1,306 @@
+
+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 += addq_s_w.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/src/tests/tcg/mips/mips64-dsp/absq_s_ob.c b/src/tests/tcg/mips/mips64-dsp/absq_s_ob.c
new file mode 100644
index 0000000..6214031
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/absq_s_ph.c b/src/tests/tcg/mips/mips64-dsp/absq_s_ph.c
new file mode 100644
index 0000000..238416d
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/absq_s_pw.c b/src/tests/tcg/mips/mips64-dsp/absq_s_pw.c
new file mode 100644
index 0000000..48fc763
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/absq_s_qh.c b/src/tests/tcg/mips/mips64-dsp/absq_s_qh.c
new file mode 100644
index 0000000..9001a9e
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/absq_s_w.c b/src/tests/tcg/mips/mips64-dsp/absq_s_w.c
new file mode 100644
index 0000000..414c8bd
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/addq_ph.c b/src/tests/tcg/mips/mips64-dsp/addq_ph.c
new file mode 100644
index 0000000..22a36d9
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/addq_ph.c
@@ -0,0 +1,57 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long dsp;
+ 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("1 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("2 addq.ph wrong\n");
+
+ return -1;
+ }
+
+ rs = 0x7fff847D;
+ rt = 0x0031AF2D;
+ result = 0xffffffff803033AA;
+ __asm
+ ("addq.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ __asm("rddsp %0\n\t"
+ : "=r"(dsp)
+ );
+
+ if (rd != result || (((dsp >> 20) & 0x01) != 1)) {
+ printf("3 addq.ph wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/addq_pw.c b/src/tests/tcg/mips/mips64-dsp/addq_pw.c
new file mode 100644
index 0000000..99a7668
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/addq_pw.c
@@ -0,0 +1,46 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt, result, dspreg, dspresult;
+
+ rs = 0x123456787FFFFFFF;
+ rt = 0x1111111100000101;
+ result = 0x2345678980000100;
+ 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;
+ }
+
+ rs = 0x1234567880FFFFFF;
+ rt = 0x1111111180000001;
+ result = 0x2345678901000000;
+ 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/src/tests/tcg/mips/mips64-dsp/addq_qh.c b/src/tests/tcg/mips/mips64-dsp/addq_qh.c
new file mode 100644
index 0000000..4b874af
--- /dev/null
+++ b/src/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 = 0x123456787FFF8010;
+ rt = 0x1111111100018000;
+ result = 0x2345678980000010;
+ 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/src/tests/tcg/mips/mips64-dsp/addq_s_ph.c b/src/tests/tcg/mips/mips64-dsp/addq_s_ph.c
new file mode 100644
index 0000000..ad84cdc
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/addq_s_ph.c
@@ -0,0 +1,84 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long dsp;
+ 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("1 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)
+ );
+
+ __asm
+ ("rddsp %0\n\t"
+ : "=r"(dsp)
+ );
+
+ if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) {
+ printf("2 addq_s.ph wrong\n");
+
+ return -1;
+ }
+
+ rs = 0x7fff847D;
+ rt = 0x0031AF2D;
+ result = 0x7fff8000;
+ __asm
+ ("addq_s.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ __asm
+ ("rddsp %0\n\t"
+ : "=r"(dsp)
+ );
+
+ if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) {
+ printf("3 addq_s.ph wrong\n");
+
+ return -1;
+ }
+
+ rs = 0x8030847D;
+ rt = 0x8a00AF2D;
+ result = 0xffffffff80008000;
+ __asm
+ ("addq_s.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ __asm
+ ("rddsp %0\n\t"
+ : "=r"(dsp)
+ );
+
+ if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) {
+ printf("4 addq_s.ph wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/addq_s_pw.c b/src/tests/tcg/mips/mips64-dsp/addq_s_pw.c
new file mode 100644
index 0000000..2e380bb
--- /dev/null
+++ b/src/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 = 0x80FFFFFFE00000FF;
+ rt = 0x80000001200000DD;
+ result = 0x80000000000001DC;
+ 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/src/tests/tcg/mips/mips64-dsp/addq_s_qh.c b/src/tests/tcg/mips/mips64-dsp/addq_s_qh.c
new file mode 100644
index 0000000..b638a2b
--- /dev/null
+++ b/src/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 = 0x123456787FFF8000;
+ rt = 0x1111111100028000;
+ result = 0x234567897FFF8000;
+ 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/src/tests/tcg/mips/mips64-dsp/addq_s_w.c b/src/tests/tcg/mips/mips64-dsp/addq_s_w.c
new file mode 100644
index 0000000..3e08f5d
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/addq_s_w.c
@@ -0,0 +1,48 @@
+#include "io.h"
+
+int main()
+{
+ long long rd, rs, rt;
+ long long result;
+
+ rt = 0x10017EFD;
+ rs = 0x11111111;
+ result = 0x2112900e;
+
+ __asm
+ ("addq_s.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ if (rd != result) {
+ printf("addq_s.w error\n");
+ }
+
+ rt = 0x80017EFD;
+ rs = 0x81111111;
+ result = 0xffffffff80000000;
+
+ __asm
+ ("addq_s.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ if (rd != result) {
+ printf("addq_s.w error\n");
+ }
+
+ rt = 0x7fffffff;
+ rs = 0x01111111;
+ result = 0x7fffffff;
+
+ __asm
+ ("addq_s.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ if (rd != result) {
+ printf("addq_s.w error\n");
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/addsc.c b/src/tests/tcg/mips/mips64-dsp/addsc.c
new file mode 100644
index 0000000..4b684b9
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/addsc.c
@@ -0,0 +1,39 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long dsp;
+ 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("1 addsc wrong\n");
+
+ return -1;
+ }
+
+ rs = 0xFFFF0FFF;
+ rt = 0x00010111;
+ result = 0x00001110;
+ __asm
+ ("addsc %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ if ((rd != result) || (((dsp >> 13) & 0x01) != 1)) {
+ printf("2 addsc wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/addu_ob.c b/src/tests/tcg/mips/mips64-dsp/addu_ob.c
new file mode 100644
index 0000000..17f9c66
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/addu_ob.c
@@ -0,0 +1,28 @@
+#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/src/tests/tcg/mips/mips64-dsp/addu_qb.c b/src/tests/tcg/mips/mips64-dsp/addu_qb.c
new file mode 100644
index 0000000..3b9b5fc
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/addu_qb.c
@@ -0,0 +1,40 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long dsp;
+ long long result;
+
+ rs = 0x00FF00FF;
+ rt = 0x00010001;
+ result = 0x00000000;
+ __asm
+ ("addu.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) {
+ printf("1 addu.qb wrong\n");
+
+ return -1;
+ }
+
+ rs = 0xFFFF1111;
+ rt = 0x00020001;
+ result = 0xFFFFFFFFFF011112;
+ __asm
+ ("addu.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) {
+ printf("2 addu.qb wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/addu_s_ob.c b/src/tests/tcg/mips/mips64-dsp/addu_s_ob.c
new file mode 100644
index 0000000..e89a463
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/addu_s_qb.c b/src/tests/tcg/mips/mips64-dsp/addu_s_qb.c
new file mode 100644
index 0000000..cb84293
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/addu_s_qb.c
@@ -0,0 +1,40 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long dsp;
+ long long result;
+
+ rs = 0x10FF01FF;
+ rt = 0x10010001;
+ result = 0x20FF01FF;
+ __asm
+ ("addu_s.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ if ((rd != result) || (((dsp >> 20) & 0x1) != 1)) {
+ printf("1 addu_s.qb error 1\n");
+
+ return -1;
+ }
+
+ rs = 0xFFFFFFFFFFFF1111;
+ rt = 0x00020001;
+ result = 0xFFFFFFFFFFFF1112;
+ __asm
+ ("addu_s.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ if ((rd != result) || (((dsp >> 20) & 0x1) != 1)) {
+ printf("2 addu_s.qb error 2\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/addwc.c b/src/tests/tcg/mips/mips64-dsp/addwc.c
new file mode 100644
index 0000000..5929cd2
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/addwc.c
@@ -0,0 +1,59 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long dspi, dspo;
+ long long result;
+
+ rs = 0x10FF01FF;
+ rt = 0x10010001;
+ dspi = 0x00002000;
+ result = 0x21000201;
+ __asm
+ ("wrdsp %3\n"
+ "addwc %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt), "r"(dspi)
+ );
+ if (rd != result) {
+ printf("1 addwc wrong\n");
+
+ return -1;
+ }
+
+ rs = 0xFFFF1111;
+ rt = 0x00020001;
+ dspi = 0x00;
+ result = 0x00011112;
+ __asm
+ ("wrdsp %3\n"
+ "addwc %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt), "r"(dspi)
+ );
+ if (rd != result) {
+ printf("2 addwc wrong\n");
+
+ return -1;
+ }
+
+ rs = 0x8FFF1111;
+ rt = 0x80020001;
+ dspi = 0x00;
+ result = 0x10011112;
+ __asm
+ ("wrdsp %4\n"
+ "addwc %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dspo)
+ : "r"(rs), "r"(rt), "r"(dspi)
+ );
+ if ((rd != result) || (((dspo >> 20) & 0x01) != 1)) {
+ printf("3 addwc wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/bitrev.c b/src/tests/tcg/mips/mips64-dsp/bitrev.c
new file mode 100644
index 0000000..ac24ef3
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/bposge32.c b/src/tests/tcg/mips/mips64-dsp/bposge32.c
new file mode 100644
index 0000000..97bce44
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/bposge64.c b/src/tests/tcg/mips/mips64-dsp/bposge64.c
new file mode 100644
index 0000000..36161ad
--- /dev/null
+++ b/src/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"
+ "bposge64 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("bposge64 wrong\n");
+
+ return -1;
+ }
+
+ dsp = 0x10;
+ sum = 0x01;
+ result = 0xA4;
+
+ __asm
+ ("wrdsp %1\n\t"
+ "bposge64 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("bposge64 wrong\n");
+
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/cmp_eq_ph.c b/src/tests/tcg/mips/mips64-dsp/cmp_eq_ph.c
new file mode 100644
index 0000000..63069d0
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/cmp_eq_pw.c b/src/tests/tcg/mips/mips64-dsp/cmp_eq_pw.c
new file mode 100644
index 0000000..bae4c06
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/cmp_eq_pw.c
@@ -0,0 +1,46 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rs, rt, dspreg, dspresult;
+
+ rs = 0x123456789ABCDEFF;
+ rt = 0x123456789ABCDEFF;
+ dspresult = 0x03;
+
+ __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("1 cmp.eq.pw error\n");
+
+ return -1;
+ }
+
+ rs = 0x123456799ABCDEFe;
+ rt = 0x123456789ABCDEFF;
+ dspresult = 0x00;
+
+ __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("2 cmp.eq.pw error\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/cmp_eq_qh.c b/src/tests/tcg/mips/mips64-dsp/cmp_eq_qh.c
new file mode 100644
index 0000000..49ea271
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/cmp_eq_qh.c
@@ -0,0 +1,46 @@
+#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;
+ }
+
+ rs = 0x12355a789A4CD3F0;
+ rt = 0x123456789ABCDEFF;
+ dspresult = 0x00;
+
+ __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/src/tests/tcg/mips/mips64-dsp/cmp_le_ph.c b/src/tests/tcg/mips/mips64-dsp/cmp_le_ph.c
new file mode 100644
index 0000000..12d24f1
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/cmp_le_pw.c b/src/tests/tcg/mips/mips64-dsp/cmp_le_pw.c
new file mode 100644
index 0000000..6acc43c
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/cmp_le_pw.c
@@ -0,0 +1,46 @@
+#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("1 cmp.le.pw error\n");
+
+ return -1;
+ }
+
+ rs = 0x123456799ABCEEFF;
+ rt = 0x123456789ABCDEFF;
+ dspresult = 0x00;
+
+ __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("2 cmp.le.pw error\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/cmp_le_qh.c b/src/tests/tcg/mips/mips64-dsp/cmp_le_qh.c
new file mode 100644
index 0000000..c9ce216
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/cmp_le_qh.c
@@ -0,0 +1,46 @@
+#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;
+ }
+
+ rs = 0x823456789ABCDEF0;
+ 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/src/tests/tcg/mips/mips64-dsp/cmp_lt_ph.c b/src/tests/tcg/mips/mips64-dsp/cmp_lt_ph.c
new file mode 100644
index 0000000..1d91228
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/cmp_lt_pw.c b/src/tests/tcg/mips/mips64-dsp/cmp_lt_pw.c
new file mode 100644
index 0000000..87e74ca
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/cmp_lt_pw.c
@@ -0,0 +1,46 @@
+#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;
+ }
+
+ rs = 0x123456779ABCDEFf;
+ rt = 0x123456789ABCDEFF;
+ dspresult = 0x02;
+
+ __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/src/tests/tcg/mips/mips64-dsp/cmp_lt_qh.c b/src/tests/tcg/mips/mips64-dsp/cmp_lt_qh.c
new file mode 100644
index 0000000..0a13a5e
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/cmp_lt_qh.c
@@ -0,0 +1,46 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rs, rt, dspreg, dspresult;
+
+ rs = 0x123558789ABCDEF0;
+ 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;
+ }
+
+ rs = 0x123356779ABbDEF0;
+ rt = 0x123456789ABCDEFF;
+ dspresult = 0x0f;
+
+ __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/src/tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c b/src/tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c
new file mode 100644
index 0000000..697d73d
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/cmpgu_eq_ob.c
@@ -0,0 +1,40 @@
+#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;
+ }
+
+ rs = 0x133456789ABCDEF0;
+ rt = 0x123556789ABCDEFF;
+ result = 0x3E;
+
+ __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/src/tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c b/src/tests/tcg/mips/mips64-dsp/cmpgu_eq_qb.c
new file mode 100644
index 0000000..b41c443
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c b/src/tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c
new file mode 100644
index 0000000..8b65f18
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/cmpgu_le_ob.c
@@ -0,0 +1,40 @@
+#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;
+ }
+
+ rs = 0x823556789ABCDEF0;
+ rt = 0x123456789ABCDEFF;
+ result = 0x3F;
+
+ __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/src/tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c b/src/tests/tcg/mips/mips64-dsp/cmpgu_le_qb.c
new file mode 100644
index 0000000..dd2b091
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c b/src/tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c
new file mode 100644
index 0000000..3e5c9dd
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/cmpgu_lt_ob.c
@@ -0,0 +1,40 @@
+#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;
+ }
+
+ rs = 0x823455789ABCDEF0;
+ rt = 0x123356789ABCDEFF;
+ result = 0x21;
+
+ __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/src/tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c b/src/tests/tcg/mips/mips64-dsp/cmpgu_lt_qb.c
new file mode 100644
index 0000000..a467cb7
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c b/src/tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c
new file mode 100644
index 0000000..4d1983e
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/cmpu_eq_ob.c
@@ -0,0 +1,46 @@
+#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;
+ }
+
+ rs = 0x133516713A0CD1F0;
+ rt = 0x123456789ABCDEFF;
+ dspresult = 0x00;
+
+ __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/src/tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c b/src/tests/tcg/mips/mips64-dsp/cmpu_eq_qb.c
new file mode 100644
index 0000000..28f3bec
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/cmpu_le_ob.c b/src/tests/tcg/mips/mips64-dsp/cmpu_le_ob.c
new file mode 100644
index 0000000..8acbd1c
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/cmpu_le_ob.c
@@ -0,0 +1,44 @@
+#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;
+ }
+
+ rs = 0x823656789ABCDEF0;
+ rt = 0x123456789ABCDEFF;
+ dspresult = 0x3F;
+
+ __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/src/tests/tcg/mips/mips64-dsp/cmpu_le_qb.c b/src/tests/tcg/mips/mips64-dsp/cmpu_le_qb.c
new file mode 100644
index 0000000..8a17a08
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c b/src/tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c
new file mode 100644
index 0000000..34e312d
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/cmpu_lt_ob.c
@@ -0,0 +1,44 @@
+#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;
+ }
+
+ rs = 0x823156789ABCDEF0;
+ rt = 0x123456789ABCDEFF;
+ dspresult = 0x41;
+
+ __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/src/tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c b/src/tests/tcg/mips/mips64-dsp/cmpu_lt_qb.c
new file mode 100644
index 0000000..adb75ee
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dappend.c b/src/tests/tcg/mips/mips64-dsp/dappend.c
new file mode 100644
index 0000000..ba8e121
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dextp.c b/src/tests/tcg/mips/mips64-dsp/dextp.c
new file mode 100644
index 0000000..a469cc0
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextp.c
@@ -0,0 +1,54 @@
+#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\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;
+ }
+
+ rs = 0xabcd1200;
+
+ achi = 0x12345678;
+ acli = 0x87654321;
+ resdsp = 0x1;
+
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\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) {
+ printf("dextp error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dextpdp.c b/src/tests/tcg/mips/mips64-dsp/dextpdp.c
new file mode 100644
index 0000000..a2361e2
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextpdp.c
@@ -0,0 +1,59 @@
+#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\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;
+ }
+
+ rs = 0xabcd1200;
+
+ achi = 0x12345678;
+ acli = 0x87654321;
+ resdsp = 0x1;
+
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\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;
+
+ if (tmp1 != resdsp) {
+ printf("dextpdp error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dextpdpv.c b/src/tests/tcg/mips/mips64-dsp/dextpdpv.c
new file mode 100644
index 0000000..09c0b5b
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextpdpv.c
@@ -0,0 +1,63 @@
+#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;
+ }
+
+ rsdsp = 0xabcd1200;
+ rs = 0x7;
+ achi = 0x12345678;
+ acli = 0x87654321;
+ resdsp = 0x1;
+
+ __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;
+
+ if (tmp1 != resdsp) {
+ printf("dextpdpv error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dextpv.c b/src/tests/tcg/mips/mips64-dsp/dextpv.c
new file mode 100644
index 0000000..2626f3d
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextpv.c
@@ -0,0 +1,58 @@
+#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;
+ }
+
+ rsdsp = 0xabcd1200;
+ rs = 0x7;
+
+ achi = 0x12345678;
+ acli = 0x87654321;
+ resdsp = 0x1;
+
+ __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) {
+ printf("dextpv error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dextr_l.c b/src/tests/tcg/mips/mips64-dsp/dextr_l.c
new file mode 100644
index 0000000..538846d
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextr_l.c
@@ -0,0 +1,44 @@
+#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;
+ }
+
+ achi = 0x87654321;
+ acli = 0x12345678;
+
+ res = 0x12345678;
+
+ __asm
+ ("mthi %1, $ac1\n\t"
+ "mtlo %2, $ac1\n\t"
+ "dextr.l %0, $ac1, 0x0\n\t"
+ : "=r"(rt)
+ : "r"(achi), "r"(acli)
+ );
+ if (rt != res) {
+ printf("dextr.l error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dextr_r_l.c b/src/tests/tcg/mips/mips64-dsp/dextr_r_l.c
new file mode 100644
index 0000000..a10a9ab
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextr_r_l.c
@@ -0,0 +1,54 @@
+#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;
+ }
+
+ achi = 0x87654321;
+ acli = 0x12345678;
+
+ res = 0x12345678;
+ resdsp = 0x01;
+
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "dextr_r.l %0, $ac1, 0x0\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/src/tests/tcg/mips/mips64-dsp/dextr_r_w.c b/src/tests/tcg/mips/mips64-dsp/dextr_r_w.c
new file mode 100644
index 0000000..2774e9b
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextr_r_w.c
@@ -0,0 +1,54 @@
+#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;
+ }
+
+ achi = 0x87654321;
+ acli = 0x12345678;
+
+ res = 0x12345678;
+ resdsp = 0x01;
+
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "dextr_r.w %0, $ac1, 0x0\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/src/tests/tcg/mips/mips64-dsp/dextr_rs_l.c b/src/tests/tcg/mips/mips64-dsp/dextr_rs_l.c
new file mode 100644
index 0000000..1a202fe
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextr_rs_l.c
@@ -0,0 +1,52 @@
+#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;
+ }
+
+ achi = 0x00;
+ acli = 0x12345678;
+
+ res = 0x12345678;
+ resdsp = 0x1;
+
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "dextr_rs.l %0, $ac1, 0x0\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/src/tests/tcg/mips/mips64-dsp/dextr_rs_w.c b/src/tests/tcg/mips/mips64-dsp/dextr_rs_w.c
new file mode 100644
index 0000000..ebe5f99
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextr_rs_w.c
@@ -0,0 +1,52 @@
+#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;
+ }
+
+ achi = 0x00;
+ acli = 0x12345678;
+
+ res = 0x123456;
+ 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/src/tests/tcg/mips/mips64-dsp/dextr_s_h.c b/src/tests/tcg/mips/mips64-dsp/dextr_s_h.c
new file mode 100644
index 0000000..1adb554
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextr_s_h.c
@@ -0,0 +1,73 @@
+#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("1 dextr_s.h error\n");
+ return -1;
+ }
+
+ achi = 0x77654321;
+ acli = 0x12345678;
+
+ res = 0x7fff;
+ 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("2 dextr_s.h error\n");
+ return -1;
+ }
+
+ achi = 0x00;
+ acli = 0x78;
+
+ res = 0x7;
+ resdsp = 0x1;
+
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "dextr_s.h %0, $ac1, 0x4\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(achi), "r"(acli)
+ );
+ dsp = (dsp >> 23) & 0x1;
+
+ if ((dsp != resdsp) || (rt != res)) {
+ printf("3 dextr_s.h error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dextr_w.c b/src/tests/tcg/mips/mips64-dsp/dextr_w.c
new file mode 100644
index 0000000..79bed5d
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextr_w.c
@@ -0,0 +1,44 @@
+#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;
+ }
+
+ achi = 0x87654321;
+ acli = 0x12345678;
+
+ res = 0x12345678;
+
+ __asm
+ ("mthi %1, $ac1\n\t"
+ "mtlo %2, $ac1\n\t"
+ "dextr.w %0, $ac1, 0x0\n\t"
+ : "=r"(rt)
+ : "r"(achi), "r"(acli)
+ );
+ if (rt != res) {
+ printf("dextr.w error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dextrv_l.c b/src/tests/tcg/mips/mips64-dsp/dextrv_l.c
new file mode 100644
index 0000000..2e6187f
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextrv_l.c
@@ -0,0 +1,46 @@
+#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;
+ }
+
+ achi = 0x87654321;
+ acli = 0x12345678;
+ rs = 0x0;
+
+ res = 0x12345678;
+
+ __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/src/tests/tcg/mips/mips64-dsp/dextrv_r_l.c b/src/tests/tcg/mips/mips64-dsp/dextrv_r_l.c
new file mode 100644
index 0000000..b47a017
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextrv_r_l.c
@@ -0,0 +1,56 @@
+#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;
+ }
+
+ achi = 0x87654321;
+ acli = 0x12345678;
+ rs = 0x0;
+
+ res = 0x12345678;
+ 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/src/tests/tcg/mips/mips64-dsp/dextrv_r_w.c b/src/tests/tcg/mips/mips64-dsp/dextrv_r_w.c
new file mode 100644
index 0000000..cd201de
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextrv_r_w.c
@@ -0,0 +1,56 @@
+#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;
+ }
+
+ achi = 0x87654321;
+ acli = 0x12345678;
+ rs = 0x0;
+
+ res = 0x12345678;
+ 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/src/tests/tcg/mips/mips64-dsp/dextrv_rs_l.c b/src/tests/tcg/mips/mips64-dsp/dextrv_rs_l.c
new file mode 100644
index 0000000..6ce4185
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextrv_rs_l.c
@@ -0,0 +1,54 @@
+#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;
+ }
+
+ achi = 0x00;
+ acli = 0x12345678;
+ rs = 0x0;
+
+ res = 0x12345678;
+ 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/src/tests/tcg/mips/mips64-dsp/dextrv_rs_w.c b/src/tests/tcg/mips/mips64-dsp/dextrv_rs_w.c
new file mode 100644
index 0000000..a65183c
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextrv_rs_w.c
@@ -0,0 +1,54 @@
+#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;
+ }
+
+ achi = 0x00;
+ acli = 0x12345678;
+ rs = 0x8;
+
+ res = 0x123456;
+ 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/src/tests/tcg/mips/mips64-dsp/dextrv_s_h.c b/src/tests/tcg/mips/mips64-dsp/dextrv_s_h.c
new file mode 100644
index 0000000..87d3aee
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dextrv_w.c b/src/tests/tcg/mips/mips64-dsp/dextrv_w.c
new file mode 100644
index 0000000..973765c
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dextrv_w.c
@@ -0,0 +1,46 @@
+#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;
+ }
+
+ achi = 0x87654321;
+ acli = 0x12345678;
+ rs = 0x0;
+
+ res = 0x12345678;
+
+ __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/src/tests/tcg/mips/mips64-dsp/dinsv.c b/src/tests/tcg/mips/mips64-dsp/dinsv.c
new file mode 100644
index 0000000..f619218
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dinsv.c
@@ -0,0 +1,26 @@
+#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/src/tests/tcg/mips/mips64-dsp/dmadd.c b/src/tests/tcg/mips/mips64-dsp/dmadd.c
new file mode 100644
index 0000000..fb22614
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dmaddu.c b/src/tests/tcg/mips/mips64-dsp/dmaddu.c
new file mode 100644
index 0000000..39ab0c1
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dmsub.c b/src/tests/tcg/mips/mips64-dsp/dmsub.c
new file mode 100644
index 0000000..16be617
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dmsubu.c b/src/tests/tcg/mips/mips64-dsp/dmsubu.c
new file mode 100644
index 0000000..cc4838a
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dmthlip.c b/src/tests/tcg/mips/mips64-dsp/dmthlip.c
new file mode 100644
index 0000000..027555f
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dmthlip.c
@@ -0,0 +1,41 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rs, dsp;
+ long long achi, acli;
+
+ long long rsdsp;
+ long long acho, aclo;
+
+ long long res;
+ long long reshi, reslo;
+
+
+ rs = 0xaaaabbbbccccdddd;
+ achi = 0x87654321;
+ acli = 0x12345678;
+ dsp = 0x22;
+
+ res = 0x62;
+ reshi = 0x12345678;
+ reslo = 0xffffffffccccdddd;
+
+ __asm
+ ("mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "wrdsp %5\n\t"
+ "dmthlip %6, $ac1\n\t"
+ "rddsp %0\n\t"
+ "mfhi %1, $ac1\n\t"
+ "mflo %2, $ac1\n\t"
+ : "=r"(rsdsp), "=r"(acho), "=r"(aclo)
+ : "r"(achi), "r"(acli), "r"(dsp), "r"(rs)
+ );
+ if ((rsdsp != res) || (acho != reshi) || (aclo != reslo)) {
+ printf("dmthlip error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c b/src/tests/tcg/mips/mips64-dsp/dpaq_s_w_ph.c
new file mode 100644
index 0000000..1bca935
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c b/src/tests/tcg/mips/mips64-dsp/dpaq_s_w_qh.c
new file mode 100644
index 0000000..844a347
--- /dev/null
+++ b/src/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 = 0x00;
+ 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/src/tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c b/src/tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c
new file mode 100644
index 0000000..1bb2ec2
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dpaq_sa_l_pw.c
@@ -0,0 +1,88 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rs, rt;
+ long long achi, acli;
+ long long acho, aclo;
+ long long dsp;
+ long long resh, resl;
+ long long resdsp;
+
+ rs = 0x0000000100000001;
+ rt = 0x0000000200000002;
+ achi = 0x1;
+ acli = 0x1;
+ resh = 0xffffffffffffffff;
+ resl = 0x0;
+ resdsp = 0x01;
+
+ __asm
+ ("mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "dpaq_sa.l.pw $ac1, %5, %6\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ "rddsp %2\n\t"
+ : "=r"(acho), "=r"(aclo), "=r"(dsp)
+ : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+ );
+
+ if ((acho != resh) || (aclo != resl) || ((dsp >> (16 + 1)) != resdsp)) {
+ printf("1 dpaq_sa_l_pw error\n");
+
+ return -1;
+ }
+
+ rs = 0xaaaabbbbccccdddd;
+ rt = 0x3333444455556666;
+ achi = 0x88888888;
+ acli = 0x66666666;
+
+ resh = 0xffffffff88888887;
+ resl = 0xffffffff9e2661da;
+
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "dpaq_sa.l.pw $ac1, %4, %5\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ : "=r"(acho), "=r"(aclo)
+ : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+ );
+
+ if ((acho != resh) || (aclo != resl)) {
+ printf("2 dpaq_sa_l_pw error\n");
+
+ return -1;
+ }
+
+ rs = 0x8000000080000000;
+ rt = 0x8000000080000000;
+ achi = 0x88888888;
+ acli = 0x66666666;
+
+ resh = 0xffffffffffffffff;
+ resl = 0x00;
+ resdsp = 0x01;
+
+ __asm
+ ("mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "dpaq_sa.l.pw $ac1, %5, %6\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ "rddsp %2\n\t"
+ : "=r"(acho), "=r"(aclo), "=r"(dsp)
+ : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+ );
+
+ if ((acho != resh) || (aclo != resl) || ((dsp >> (16 + 1)) != resdsp)) {
+ printf("2 dpaq_sa_l_pw error\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c b/src/tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c
new file mode 100644
index 0000000..f840cdd
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dpaq_sa_l_w.c
@@ -0,0 +1,82 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rs, rt, dsp;
+ long long ach = 0, acl = 0;
+ long long resulth, resultl, resultdsp;
+
+ rs = 0x80000000;
+ rt = 0x80000000;
+ 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 error\n");
+
+ return -1;
+ }
+
+ ach = 0x12;
+ acl = 0x48;
+ rs = 0x80000000;
+ rt = 0x80000000;
+
+ 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 error\n");
+
+ return -1;
+ }
+
+ ach = 0x741532A0;
+ acl = 0xfceabb08;
+ rs = 0x80000000;
+ rt = 0x80000000;
+
+ 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 error\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dpau_h_obl.c b/src/tests/tcg/mips/mips64-dsp/dpau_h_obl.c
new file mode 100644
index 0000000..54905e8
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dpau_h_obr.c b/src/tests/tcg/mips/mips64-dsp/dpau_h_obr.c
new file mode 100644
index 0000000..d7aa60b
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dpau_h_qbl.c b/src/tests/tcg/mips/mips64-dsp/dpau_h_qbl.c
new file mode 100644
index 0000000..fcfd764
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dpau_h_qbr.c b/src/tests/tcg/mips/mips64-dsp/dpau_h_qbr.c
new file mode 100644
index 0000000..3282461
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c b/src/tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c
new file mode 100644
index 0000000..7660f03
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dpsq_s_w_ph.c
@@ -0,0 +1,51 @@
+#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("1 dpsq_s.w.ph wrong\n");
+
+ return -1;
+ }
+
+ ach = 0x1424Ef1f;
+ acl = 0x1035219A;
+ rs = 0x800083AD;
+ rt = 0x80003721;
+ resulth = 0x1424ef1e;
+ resultl = 0x577ed901;
+
+ __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("2 dpsq_s.w.ph wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c b/src/tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c
new file mode 100644
index 0000000..2cc50c5
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dpsq_s_w_qh.c
@@ -0,0 +1,56 @@
+#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("1 dpsq_s.w.qh wrong\n");
+
+ return -1;
+ }
+
+ rs = 0x8000800080008000;
+ rt = 0x8000800080008000;
+ achi = 0x67576;
+ acli = 0x98878;
+
+ resh = 0x67575;
+ resl = 0x0009887c;
+
+ __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("2 dpsq_s.w.qh wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c b/src/tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c
new file mode 100644
index 0000000..7fc2503
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dpsq_sa_l_pw.c
@@ -0,0 +1,76 @@
+#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("1 dpsq_sa.l.pw wrong\n");
+
+ return -1;
+ }
+
+ /* clear dspcontrol reg for next test use. */
+ dsp = 0;
+ __asm
+ ("wrdsp %0"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 0x8B78980000000;
+ rt = 0x5867580000000;
+
+ achi = 0x98765437;
+ acli = 0x65489709;
+
+ resh = 0xffffffff98765436;
+ resl = 0x11d367d0;
+
+ 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("2 dpsq_sa.l.pw wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c b/src/tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c
new file mode 100644
index 0000000..f55afc9
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dpsq_sa_l_w.c
@@ -0,0 +1,59 @@
+#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 = 0xfffffffffdf4cbe0;
+ resultl = 0xFFFFFFFFd138776b;
+ resultdsp = 0x00;
+ __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("1 dpsq_sa.l.w wrong\n");
+
+ return -1;
+ }
+
+ ach = 0x54321123;
+ acl = 5;
+ rs = 0x80000000;
+ rt = 0x80000000;
+
+ resulth = 0xffffffffd4321123;
+ resultl = 0x06;
+ 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("2 dpsq_sa.l.w wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dpsu_h_obl.c b/src/tests/tcg/mips/mips64-dsp/dpsu_h_obl.c
new file mode 100644
index 0000000..c0a8f4d
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dpsu_h_obr.c b/src/tests/tcg/mips/mips64-dsp/dpsu_h_obr.c
new file mode 100644
index 0000000..aa0d47a
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c b/src/tests/tcg/mips/mips64-dsp/dpsu_h_qbl.c
new file mode 100644
index 0000000..da6dbb6
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c b/src/tests/tcg/mips/mips64-dsp/dpsu_h_qbr.c
new file mode 100644
index 0000000..bf00b70
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/dshilo.c b/src/tests/tcg/mips/mips64-dsp/dshilo.c
new file mode 100644
index 0000000..f50584b
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dshilo.c
@@ -0,0 +1,52 @@
+#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("1 dshilo error\n");
+ return -1;
+ }
+
+ achi = 0x87654321;
+ acli = 0x12345678;
+
+ reshi = 0x1234567;
+ reslo = 0x00;
+
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "dshilo $ac1, -60\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("2 dshilo error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/dshilov.c b/src/tests/tcg/mips/mips64-dsp/dshilov.c
new file mode 100644
index 0000000..792bd23
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/dshilov.c
@@ -0,0 +1,54 @@
+#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;
+ }
+
+ rs = 0x44;
+ achi = 0x87654321;
+ acli = 0x12345678;
+
+ reshi = 0x1234567;
+ reslo = 0x00;
+
+ __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/src/tests/tcg/mips/mips64-dsp/extp.c b/src/tests/tcg/mips/mips64-dsp/extp.c
new file mode 100644
index 0000000..c72f54b
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/extpdp.c b/src/tests/tcg/mips/mips64-dsp/extpdp.c
new file mode 100644
index 0000000..f430193
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/extpdpv.c b/src/tests/tcg/mips/mips64-dsp/extpdpv.c
new file mode 100644
index 0000000..ba57426
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/extpv.c b/src/tests/tcg/mips/mips64-dsp/extpv.c
new file mode 100644
index 0000000..158472b
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/extr_r_w.c b/src/tests/tcg/mips/mips64-dsp/extr_r_w.c
new file mode 100644
index 0000000..94572ad
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/extr_r_w.c
@@ -0,0 +1,53 @@
+#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("1 extr_r.w wrong\n");
+
+ return -1;
+ }
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x01;
+ acl = 0xB4CB;
+ result = 0x10000B4D;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_r.w %0, $ac1, 0x04\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ if ((dsp != 0) || (result != rt)) {
+ printf("2 extr_r.w wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/extr_rs_w.c b/src/tests/tcg/mips/mips64-dsp/extr_rs_w.c
new file mode 100644
index 0000000..73551f9
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/extr_rs_w.c
@@ -0,0 +1,53 @@
+#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("1 extr_rs.w wrong\n");
+
+ return -1;
+ }
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x01;
+ acl = 0xB4CB;
+ result = 0x10000B4D;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_rs.w %0, $ac1, 0x04\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ if ((dsp != 0) || (result != rt)) {
+ printf("2 extr_rs.w wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/extr_s_h.c b/src/tests/tcg/mips/mips64-dsp/extr_s_h.c
new file mode 100644
index 0000000..de10cb5
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/extr_s_h.c
@@ -0,0 +1,71 @@
+#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;
+ }
+
+ ach = 0xffffffff;
+ acl = 0x12344321;
+ result = 0xffffffffFFFF8000;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_s.h %0, $ac1, 0x08\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;
+ }
+
+ /* Clear dsp */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x00;
+ acl = 0x4321;
+ result = 0x432;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_s.h %0, $ac1, 0x04\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ if ((dsp != 0) || (result != rt)) {
+ printf("extr_s.h wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/extr_w.c b/src/tests/tcg/mips/mips64-dsp/extr_w.c
new file mode 100644
index 0000000..bd69576
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/extr_w.c
@@ -0,0 +1,53 @@
+#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;
+ }
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ ach = 0x01;
+ acl = 0xB4CB;
+ result = 0x10000B4C;
+ __asm
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr.w %0, $ac1, 0x04\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ if ((dsp != 0) || (result != rt)) {
+ printf("extr.w wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/extrv_r_w.c b/src/tests/tcg/mips/mips64-dsp/extrv_r_w.c
new file mode 100644
index 0000000..8379729
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/extrv_r_w.c
@@ -0,0 +1,59 @@
+#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;
+ }
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 4;
+ ach = 0x01;
+ acl = 0xB4CB;
+ result = 0x10000B4D;
+ __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 != 0) || (result != rt)) {
+ printf("extrv_r.w wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/extrv_rs_w.c b/src/tests/tcg/mips/mips64-dsp/extrv_rs_w.c
new file mode 100644
index 0000000..8707cd1
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/extrv_rs_w.c
@@ -0,0 +1,59 @@
+#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("1 extrv_rs.w wrong\n");
+
+ return -1;
+ }
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 4;
+ ach = 0x01;
+ acl = 0xB4CB;
+ result = 0x10000B4D;
+ __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 != 0) || (result != rt)) {
+ printf("2 extrv_rs.w wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/extrv_s_h.c b/src/tests/tcg/mips/mips64-dsp/extrv_s_h.c
new file mode 100644
index 0000000..b6dcaeb
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/extrv_s_h.c
@@ -0,0 +1,79 @@
+#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;
+ }
+
+ rs = 0x08;
+ ach = 0xffffffff;
+ acl = 0x12344321;
+ result = 0xffffffffFFFF8000;
+ __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;
+ }
+
+ /* Clear dsp */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 0x04;
+ ach = 0x00;
+ acl = 0x4321;
+ result = 0x432;
+ __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 != 0) || (result != rt)) {
+ printf("extrv_s.h wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/extrv_w.c b/src/tests/tcg/mips/mips64-dsp/extrv_w.c
new file mode 100644
index 0000000..8adffb3
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/extrv_w.c
@@ -0,0 +1,59 @@
+#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;
+ }
+
+ /* Clear dspcontrol */
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 4;
+ ach = 0x01;
+ acl = 0xB4CB;
+ result = 0x10000B4C;
+ __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 != 0) || (result != rt)) {
+ printf("extrv.w wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/head.S b/src/tests/tcg/mips/mips64-dsp/head.S
new file mode 100644
index 0000000..9a099ae
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/insv.c b/src/tests/tcg/mips/mips64-dsp/insv.c
new file mode 100644
index 0000000..fc5696f
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/io.h b/src/tests/tcg/mips/mips64-dsp/io.h
new file mode 100644
index 0000000..b7db61d
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/lbux.c b/src/tests/tcg/mips/mips64-dsp/lbux.c
new file mode 100644
index 0000000..dbdc87b
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/ldx.c b/src/tests/tcg/mips/mips64-dsp/ldx.c
new file mode 100644
index 0000000..787d9f0
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/lhx.c b/src/tests/tcg/mips/mips64-dsp/lhx.c
new file mode 100644
index 0000000..2020e56
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/lwx.c b/src/tests/tcg/mips/mips64-dsp/lwx.c
new file mode 100644
index 0000000..6a81414
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/madd.c b/src/tests/tcg/mips/mips64-dsp/madd.c
new file mode 100644
index 0000000..de6e44f
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/maddu.c b/src/tests/tcg/mips/mips64-dsp/maddu.c
new file mode 100644
index 0000000..e9f426a
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c b/src/tests/tcg/mips/mips64-dsp/maq_s_l_pwl.c
new file mode 100644
index 0000000..c196b43
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c b/src/tests/tcg/mips/mips64-dsp/maq_s_l_pwr.c
new file mode 100644
index 0000000..e2af69f
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/maq_s_w_phl.c b/src/tests/tcg/mips/mips64-dsp/maq_s_w_phl.c
new file mode 100644
index 0000000..7dba874
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/maq_s_w_phl.c
@@ -0,0 +1,60 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rt, rs;
+ long long achi, acli;
+ long long dsp;
+ long long acho, aclo;
+ long long resulth, resultl;
+ long long resdsp;
+
+ 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("1 maq_s.w.phl error\n");
+
+ return -1;
+ }
+
+ achi = 0x06;
+ acli = 0xB4CB;
+ rs = 0x80000000;
+ rt = 0x80000000;
+ resulth = 0x6;
+ resultl = 0xffffffff8000b4ca;
+ resdsp = 1;
+
+ __asm
+ ("mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "maq_s.w.phl $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 ((resulth != acho) || (resultl != aclo) ||
+ (((dsp >> 17) & 0x01) != resdsp)) {
+ printf("2 maq_s.w.phl error\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/maq_s_w_phr.c b/src/tests/tcg/mips/mips64-dsp/maq_s_w_phr.c
new file mode 100644
index 0000000..138ee2a
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/maq_s_w_phr.c
@@ -0,0 +1,60 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rt, rs;
+ long long achi, acli;
+ long long dsp;
+ long long acho, aclo;
+ long long resulth, resultl;
+ long long resdsp;
+
+ 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("1 maq_s.w.phr error\n");
+
+ return -1;
+ }
+
+ achi = 0x06;
+ acli = 0xB4CB;
+ rs = 0x8000;
+ rt = 0x8000;
+ resulth = 0x6;
+ resultl = 0xffffffff8000b4ca;
+ resdsp = 1;
+
+ __asm
+ ("mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "maq_s.w.phr $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 ((resulth != acho) || (resultl != aclo) ||
+ (((dsp >> 17) & 0x01) != resdsp)) {
+ printf("2 maq_s.w.phr error\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c b/src/tests/tcg/mips/mips64-dsp/maq_s_w_qhll.c
new file mode 100644
index 0000000..234a0af
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c b/src/tests/tcg/mips/mips64-dsp/maq_s_w_qhlr.c
new file mode 100644
index 0000000..8768cba
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c b/src/tests/tcg/mips/mips64-dsp/maq_s_w_qhrl.c
new file mode 100644
index 0000000..5006e2b
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c b/src/tests/tcg/mips/mips64-dsp/maq_s_w_qhrr.c
new file mode 100644
index 0000000..1d213a5
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c b/src/tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c
new file mode 100644
index 0000000..5530ffb
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/maq_sa_w_phl.c
@@ -0,0 +1,60 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rt, rs;
+ long long achi, acli;
+ long long dsp;
+ long long acho, aclo;
+ long long resulth, resultl;
+ long long resdsp;
+
+ 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("1 maq_sa.w.phl error\n");
+
+ return -1;
+ }
+
+ achi = 0x06;
+ acli = 0xB4CB;
+ rs = 0x80000000;
+ rt = 0x80000000;
+ resulth = 0x00;
+ resultl = 0x7fffffff;
+ resdsp = 0x01;
+
+ __asm
+ ("mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "maq_sa.w.phl $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 ((resulth != acho) || (resultl != aclo) ||
+ (((dsp >> 17) & 0x01) != 0x01)) {
+ printf("2 maq_sa.w.phl error\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c b/src/tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c
new file mode 100644
index 0000000..b611cfa
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/maq_sa_w_phr.c
@@ -0,0 +1,60 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rt, rs;
+ long long achi, acli;
+ long long dsp;
+ long long acho, aclo;
+ long long resulth, resultl;
+ long long resdsp;
+
+ 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("1 maq_sa.w.phr error\n");
+
+ return -1;
+ }
+
+ achi = 0x06;
+ acli = 0xB4CB;
+ rs = 0x8000;
+ rt = 0x8000;
+ resulth = 0x00;
+ resultl = 0x7fffffff;
+ resdsp = 0x01;
+
+ __asm
+ ("mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "maq_sa.w.phr $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 ((resulth != acho) || (resultl != aclo) ||
+ (((dsp >> 17) & 0x01) != 0x01)) {
+ printf("2 maq_sa.w.phr error\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c b/src/tests/tcg/mips/mips64-dsp/maq_sa_w_qhll.c
new file mode 100644
index 0000000..136ff2d
--- /dev/null
+++ b/src/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 = 0x00;
+ resultl = 0x7fffffff;
+
+ __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/src/tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c b/src/tests/tcg/mips/mips64-dsp/maq_sa_w_qhlr.c
new file mode 100644
index 0000000..dd0ae1c
--- /dev/null
+++ b/src/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 = 0x00;
+ resultl = 0x7fffffff;
+
+ __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/src/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c b/src/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrl.c
new file mode 100644
index 0000000..a3de6f8
--- /dev/null
+++ b/src/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 = 0x00;
+ resultl = 0x7fffffff;
+
+ __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/src/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c b/src/tests/tcg/mips/mips64-dsp/maq_sa_w_qhrr.c
new file mode 100644
index 0000000..f021737
--- /dev/null
+++ b/src/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 = 0x00;
+ resultl = 0x7fffffff;
+
+ __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/src/tests/tcg/mips/mips64-dsp/mfhi.c b/src/tests/tcg/mips/mips64-dsp/mfhi.c
new file mode 100644
index 0000000..ee915f7
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/mflo.c b/src/tests/tcg/mips/mips64-dsp/mflo.c
new file mode 100644
index 0000000..cdc646b
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/mips_boot.lds b/src/tests/tcg/mips/mips64-dsp/mips_boot.lds
new file mode 100644
index 0000000..bd7c0c0
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/modsub.c b/src/tests/tcg/mips/mips64-dsp/modsub.c
new file mode 100644
index 0000000..2c91cb4
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/msub.c b/src/tests/tcg/mips/mips64-dsp/msub.c
new file mode 100644
index 0000000..75066b5
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/msubu.c b/src/tests/tcg/mips/mips64-dsp/msubu.c
new file mode 100644
index 0000000..55f8ae0
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/mthi.c b/src/tests/tcg/mips/mips64-dsp/mthi.c
new file mode 100644
index 0000000..8570051
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/mthlip.c b/src/tests/tcg/mips/mips64-dsp/mthlip.c
new file mode 100644
index 0000000..957cd42
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/mthlip.c
@@ -0,0 +1,61 @@
+#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;
+ }
+
+ dsp = 0x3f;
+ ach = 0x05;
+ acl = 0xB4CB;
+ rs = 0x00FFBBAA;
+ resulth = 0xB4CB;
+ resultl = 0x00FFBBAA;
+ result = 0x3f;
+
+ __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/src/tests/tcg/mips/mips64-dsp/mtlo.c b/src/tests/tcg/mips/mips64-dsp/mtlo.c
new file mode 100644
index 0000000..304fffb
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c b/src/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c
new file mode 100644
index 0000000..6c68d45
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhl.c
@@ -0,0 +1,56 @@
+#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("1 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("2 muleq_s.pw.qhl error\n");
+
+ return -1;
+ }
+
+ rd = 0;
+ __asm
+ ("rddsp %0\n\t"
+ : "=r"(rd)
+ );
+ rd = rd >> 21;
+ rd = rd & 0x1;
+
+ if (rd != 1) {
+ printf("3 muleq_s.pw.qhl error\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c b/src/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c
new file mode 100644
index 0000000..fa8b41f
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/muleq_s_pw_qhr.c
@@ -0,0 +1,57 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long 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("1 muleq_s.pw.qhr error\n");
+
+ return -1;
+ }
+
+ rd = 0;
+ rs = 0x1234567845BC8000;
+ rt = 0x8765432198528000;
+ result = 0x52fbec707FFFFFFF;
+
+ __asm
+ ("muleq_s.pw.qhr %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ if (result != rd) {
+ printf("2 muleq_s.pw.qhr error\n");
+
+ return -1;
+ }
+
+ rd = 0;
+ __asm
+ ("rddsp %0\n\t"
+ : "=r"(rd)
+ );
+ rd = rd >> 21;
+ rd = rd & 0x1;
+
+ if (rd != 1) {
+ printf("3 muleq_s.pw.qhr error\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/muleq_s_w_phl.c b/src/tests/tcg/mips/mips64-dsp/muleq_s_w_phl.c
new file mode 100644
index 0000000..997a9f6
--- /dev/null
+++ b/src/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.phl 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.phl wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c b/src/tests/tcg/mips/mips64-dsp/muleq_s_w_phr.c
new file mode 100644
index 0000000..0e59479
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c b/src/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbl.c
new file mode 100644
index 0000000..2f444c9
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c b/src/tests/tcg/mips/mips64-dsp/muleu_s_ph_qbr.c
new file mode 100644
index 0000000..8bd0e99
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c b/src/tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c
new file mode 100644
index 0000000..db0d386
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/muleu_s_qh_obl.c
@@ -0,0 +1,30 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long dsp;
+ long long resdsp, result;
+
+ rd = 0;
+ rs = 0x1234567802020202;
+ rt = 0x0034432112344321;
+ result = 0x03A8FFFFFFFFFFFF;
+ resdsp = 0x01;
+
+ __asm
+ ("muleu_s.qh.obl %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+
+ dsp = (dsp >> 21) & 0x01;
+ if ((rd != result) || (resdsp != dsp)) {
+ printf("muleu_s.qh.obl error\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c b/src/tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c
new file mode 100644
index 0000000..52ed9c0
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/muleu_s_qh_obr.c
@@ -0,0 +1,31 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long dsp;
+ long long resdsp, result;
+
+ rd = 0;
+ rs = 0x0202020212345678;
+
+ rt = 0x0034432112344321;
+ result = 0x03A8FFFFFFFFFFFF;
+ resdsp = 0x01;
+
+ __asm
+ ("muleu_s.qh.obr %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+
+ dsp = (dsp >> 21) & 0x01;
+ if ((rd != result) || (resdsp != dsp)) {
+ printf("muleu_s.qh.obr error\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/mulq_rs_ph.c b/src/tests/tcg/mips/mips64-dsp/mulq_rs_ph.c
new file mode 100644
index 0000000..fd6233d
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/mulq_rs_qh.c b/src/tests/tcg/mips/mips64-dsp/mulq_rs_qh.c
new file mode 100644
index 0000000..7863c05
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c b/src/tests/tcg/mips/mips64-dsp/mulsaq_s_l_pw.c
new file mode 100644
index 0000000..02548f8
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c b/src/tests/tcg/mips/mips64-dsp/mulsaq_s_w_qh.c
new file mode 100644
index 0000000..92d7a0b
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/mult.c b/src/tests/tcg/mips/mips64-dsp/mult.c
new file mode 100644
index 0000000..4a294d1
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/multu.c b/src/tests/tcg/mips/mips64-dsp/multu.c
new file mode 100644
index 0000000..21a8a7c
--- /dev/null
+++ b/src/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
+ ("multu $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/src/tests/tcg/mips/mips64-dsp/packrl_ph.c b/src/tests/tcg/mips/mips64-dsp/packrl_ph.c
new file mode 100644
index 0000000..3722b0a
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/packrl_pw.c b/src/tests/tcg/mips/mips64-dsp/packrl_pw.c
new file mode 100644
index 0000000..7807418
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/pick_ob.c b/src/tests/tcg/mips/mips64-dsp/pick_ob.c
new file mode 100644
index 0000000..160049f
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/pick_ob.c
@@ -0,0 +1,66 @@
+#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("1 pick.ob error\n");
+ return -1;
+ }
+
+ dsp = 0x00000000;
+
+ rs = 0x1234567812345678;
+ rt = 0x8765432187654321;
+
+ res = 0x8765432187654321;
+
+ __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("2 pick.ob error\n");
+ return -1;
+ }
+
+ dsp = 0x34000000;
+
+ rs = 0x1234567812345678;
+ rt = 0x8765432187654321;
+
+ res = 0x8765567887344321;
+
+ __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("3 pick.ob error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/pick_ph.c b/src/tests/tcg/mips/mips64-dsp/pick_ph.c
new file mode 100644
index 0000000..8800c14
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/pick_ph.c
@@ -0,0 +1,60 @@
+#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("1 pick.ph wrong\n");
+
+ return -1;
+ }
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ dsp = 0x03000000;
+ result = 0x12345678;
+
+ __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("2 pick.ph wrong\n");
+
+ return -1;
+ }
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ dsp = 0x00000000;
+ result = 0xffffffff87654321;
+
+ __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("3 pick.ph wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/pick_pw.c b/src/tests/tcg/mips/mips64-dsp/pick_pw.c
new file mode 100644
index 0000000..24d80f5
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/pick_pw.c
@@ -0,0 +1,48 @@
+#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;
+ }
+
+ dsp = 0x00000000;
+
+ rs = 0x1234567812345678;
+ rt = 0x8765432187654321;
+
+ res = 0x8765432187654321;
+
+ __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/src/tests/tcg/mips/mips64-dsp/pick_qb.c b/src/tests/tcg/mips/mips64-dsp/pick_qb.c
new file mode 100644
index 0000000..0d5de9d
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/pick_qb.c
@@ -0,0 +1,43 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt, dsp;
+ long long result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ dsp = 0x0f000000;
+ result = 0x12345678;
+
+ __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;
+ }
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ dsp = 0x00000000;
+ result = 0xffffffff87654321;
+
+ __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/src/tests/tcg/mips/mips64-dsp/pick_qh.c b/src/tests/tcg/mips/mips64-dsp/pick_qh.c
new file mode 100644
index 0000000..aa2e293
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/pick_qh.c
@@ -0,0 +1,48 @@
+#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;
+ }
+
+ dsp = 0x00000000;
+
+ rs = 0x1234567812345678;
+ rt = 0x8765432187654321;
+
+ res = 0x8765432187654321;
+
+ __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/src/tests/tcg/mips/mips64-dsp/preceq_l_pwl.c b/src/tests/tcg/mips/mips64-dsp/preceq_l_pwl.c
new file mode 100644
index 0000000..6455100
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceq_l_pwr.c b/src/tests/tcg/mips/mips64-dsp/preceq_l_pwr.c
new file mode 100644
index 0000000..1e05339
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c b/src/tests/tcg/mips/mips64-dsp/preceq_pw_qhl.c
new file mode 100644
index 0000000..f44b940
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c b/src/tests/tcg/mips/mips64-dsp/preceq_pw_qhla.c
new file mode 100644
index 0000000..f0f78f4
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c b/src/tests/tcg/mips/mips64-dsp/preceq_pw_qhr.c
new file mode 100644
index 0000000..709d4f9
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c b/src/tests/tcg/mips/mips64-dsp/preceq_pw_qhra.c
new file mode 100644
index 0000000..4d071ec
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceq_w_phl.c b/src/tests/tcg/mips/mips64-dsp/preceq_w_phl.c
new file mode 100644
index 0000000..4ed3fc0
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceq_w_phr.c b/src/tests/tcg/mips/mips64-dsp/preceq_w_phr.c
new file mode 100644
index 0000000..e2ea093
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c b/src/tests/tcg/mips/mips64-dsp/precequ_ph_qbl.c
new file mode 100644
index 0000000..17b7331
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c b/src/tests/tcg/mips/mips64-dsp/precequ_ph_qbla.c
new file mode 100644
index 0000000..15e9494
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c b/src/tests/tcg/mips/mips64-dsp/precequ_ph_qbr.c
new file mode 100644
index 0000000..495368c
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c b/src/tests/tcg/mips/mips64-dsp/precequ_ph_qbra.c
new file mode 100644
index 0000000..7c66369
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precequ_qh_obl.c b/src/tests/tcg/mips/mips64-dsp/precequ_qh_obl.c
new file mode 100644
index 0000000..176d236
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precequ_qh_obla.c b/src/tests/tcg/mips/mips64-dsp/precequ_qh_obla.c
new file mode 100644
index 0000000..93a36a4
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precequ_qh_obr.c b/src/tests/tcg/mips/mips64-dsp/precequ_qh_obr.c
new file mode 100644
index 0000000..1214730
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precequ_qh_obra.c b/src/tests/tcg/mips/mips64-dsp/precequ_qh_obra.c
new file mode 100644
index 0000000..3aa0e09
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c b/src/tests/tcg/mips/mips64-dsp/preceu_ph_qbl.c
new file mode 100644
index 0000000..81f7917
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c b/src/tests/tcg/mips/mips64-dsp/preceu_ph_qbla.c
new file mode 100644
index 0000000..38cf6a6
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c b/src/tests/tcg/mips/mips64-dsp/preceu_ph_qbr.c
new file mode 100644
index 0000000..70c32b6
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c b/src/tests/tcg/mips/mips64-dsp/preceu_ph_qbra.c
new file mode 100644
index 0000000..c6638aa
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceu_qh_obl.c b/src/tests/tcg/mips/mips64-dsp/preceu_qh_obl.c
new file mode 100644
index 0000000..63f9373
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceu_qh_obla.c b/src/tests/tcg/mips/mips64-dsp/preceu_qh_obla.c
new file mode 100644
index 0000000..5fb65e4
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceu_qh_obr.c b/src/tests/tcg/mips/mips64-dsp/preceu_qh_obr.c
new file mode 100644
index 0000000..9af3b63
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/preceu_qh_obra.c b/src/tests/tcg/mips/mips64-dsp/preceu_qh_obra.c
new file mode 100644
index 0000000..fd04083
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precr_ob_qh.c b/src/tests/tcg/mips/mips64-dsp/precr_ob_qh.c
new file mode 100644
index 0000000..ce2da79
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c b/src/tests/tcg/mips/mips64-dsp/precr_sra_qh_pw.c
new file mode 100644
index 0000000..8bb16de
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c b/src/tests/tcg/mips/mips64-dsp/precr_sra_r_qh_pw.c
new file mode 100644
index 0000000..734ac32
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precrq_ob_qh.c b/src/tests/tcg/mips/mips64-dsp/precrq_ob_qh.c
new file mode 100644
index 0000000..4f61b17
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precrq_ph_w.c b/src/tests/tcg/mips/mips64-dsp/precrq_ph_w.c
new file mode 100644
index 0000000..f0946ab
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precrq_pw_l.c b/src/tests/tcg/mips/mips64-dsp/precrq_pw_l.c
new file mode 100644
index 0000000..da957c0
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precrq_qb_ph.c b/src/tests/tcg/mips/mips64-dsp/precrq_qb_ph.c
new file mode 100644
index 0000000..f417c9f
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precrq_qh_pw.c b/src/tests/tcg/mips/mips64-dsp/precrq_qh_pw.c
new file mode 100644
index 0000000..4a4ffef
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c b/src/tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c
new file mode 100644
index 0000000..61da333
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/precrq_rs_ph_w.c
@@ -0,0 +1,41 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long dsp;
+ 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("1 precrq_rs.ph.w wrong\n");
+
+ return -1;
+ }
+
+ rs = 0x7fffC678;
+ rt = 0x865432A0;
+ result = 0x7fff8654;
+
+ __asm
+ ("precrq_rs.ph.w %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ if ((result != rd) || (((dsp >> 22) & 0x01) != 1)) {
+ printf("2 precrq_rs.ph.w wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c b/src/tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c
new file mode 100644
index 0000000..ac78728
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/precrq_rs_qh_pw.c
@@ -0,0 +1,43 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long dsp;
+ 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;
+ }
+
+ rs = 0x7fffC67812345678;
+ rt = 0x8765432187654321;
+
+ res = 0x7fff123487658765;
+
+ __asm
+ ("precrq_rs.qh.pw %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+
+ if (rd != res) {
+ printf("precrq_rs.qh.pw error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c b/src/tests/tcg/mips/mips64-dsp/precrqu_s_ob_qh.c
new file mode 100644
index 0000000..e27c36b
--- /dev/null
+++ b/src/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 = 0x7fff567812345678;
+ rt = 0x8765432187654321;
+
+ res = 0xffac24ac00860086;
+ 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/src/tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c b/src/tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c
new file mode 100644
index 0000000..cb1fee4
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/precrqu_s_qb_ph.c
@@ -0,0 +1,26 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long dsp;
+ long long result;
+
+ rs = 0x12345678;
+ rt = 0x87657fff;
+ result = 0x24AC00FF;
+
+ __asm
+ ("precrqu_s.qb.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ if ((result != rd) || (((dsp >> 22) & 0x01) != 0x01)) {
+ printf("precrqu_s.qb.ph wrong\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/prependd.c b/src/tests/tcg/mips/mips64-dsp/prependd.c
new file mode 100644
index 0000000..b4208c2
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/prependw.c b/src/tests/tcg/mips/mips64-dsp/prependw.c
new file mode 100644
index 0000000..d91bd20
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/printf.c b/src/tests/tcg/mips/mips64-dsp/printf.c
new file mode 100644
index 0000000..cf8676d
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/raddu_l_ob.c b/src/tests/tcg/mips/mips64-dsp/raddu_l_ob.c
new file mode 100644
index 0000000..76ddf25
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/raddu_w_qb.c b/src/tests/tcg/mips/mips64-dsp/raddu_w_qb.c
new file mode 100644
index 0000000..c9d6535
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/rddsp.c b/src/tests/tcg/mips/mips64-dsp/rddsp.c
new file mode 100644
index 0000000..7165572
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/repl_ob.c b/src/tests/tcg/mips/mips64-dsp/repl_ob.c
new file mode 100644
index 0000000..20cb780
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/repl_ph.c b/src/tests/tcg/mips/mips64-dsp/repl_ph.c
new file mode 100644
index 0000000..11d29bd
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/repl_pw.c b/src/tests/tcg/mips/mips64-dsp/repl_pw.c
new file mode 100644
index 0000000..d35376a
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/repl_qb.c b/src/tests/tcg/mips/mips64-dsp/repl_qb.c
new file mode 100644
index 0000000..592feae
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/repl_qh.c b/src/tests/tcg/mips/mips64-dsp/repl_qh.c
new file mode 100644
index 0000000..82afc37
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/replv_ob.c b/src/tests/tcg/mips/mips64-dsp/replv_ob.c
new file mode 100644
index 0000000..31ff318
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/replv_ph.c b/src/tests/tcg/mips/mips64-dsp/replv_ph.c
new file mode 100644
index 0000000..0af7a36
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/replv_pw.c b/src/tests/tcg/mips/mips64-dsp/replv_pw.c
new file mode 100644
index 0000000..e1789af
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/replv_qb.c b/src/tests/tcg/mips/mips64-dsp/replv_qb.c
new file mode 100644
index 0000000..d99298c
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shilo.c b/src/tests/tcg/mips/mips64-dsp/shilo.c
new file mode 100644
index 0000000..5f454f6
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shilov.c b/src/tests/tcg/mips/mips64-dsp/shilov.c
new file mode 100644
index 0000000..e82615a
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shll_ob.c b/src/tests/tcg/mips/mips64-dsp/shll_ob.c
new file mode 100644
index 0000000..7dcb58f
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shll_ob.c
@@ -0,0 +1,43 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rt, dsp;
+ long long res, resdsp;
+
+ rt = 0x9ba8765433456789;
+ res = 0x9ba8765433456789;
+ resdsp = 0x0;
+ __asm
+ ("shll.ob %0, %2, 0x0\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;
+ }
+
+ 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/src/tests/tcg/mips/mips64-dsp/shll_ph.c b/src/tests/tcg/mips/mips64-dsp/shll_ph.c
new file mode 100644
index 0000000..42b462d
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shll_ph.c
@@ -0,0 +1,43 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rt, dsp;
+ long long result, resultdsp;
+
+ rt = 0x12345678;
+ result = 0x12345678;
+ resultdsp = 0;
+
+ __asm
+ ("shll.ph %0, %2, 0x0\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;
+ }
+
+ 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 wrong1\n");
+
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/shll_pw.c b/src/tests/tcg/mips/mips64-dsp/shll_pw.c
new file mode 100644
index 0000000..d7878b2
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shll_pw.c
@@ -0,0 +1,43 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rt, dsp;
+ long long result, resultdsp;
+
+ rt = 0x8765432112345678;
+ result = 0x8765432112345678;
+ resultdsp = 0;
+
+ __asm
+ ("shll.pw %0, %2, 0x0\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;
+ }
+
+ 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/src/tests/tcg/mips/mips64-dsp/shll_qb.c b/src/tests/tcg/mips/mips64-dsp/shll_qb.c
new file mode 100644
index 0000000..c21ab66
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shll_qh.c b/src/tests/tcg/mips/mips64-dsp/shll_qh.c
new file mode 100644
index 0000000..1380825
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shll_qh.c
@@ -0,0 +1,42 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rt, dsp;
+ long long res, resdsp;
+
+ rt = 0x9ba8765433456789;
+ res = 0x9ba8765433456789;
+ resdsp = 0x0;
+ __asm
+ ("shll.qh %0, %2, 0x0\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;
+ }
+
+ 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 error1\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/shll_s_ph.c b/src/tests/tcg/mips/mips64-dsp/shll_s_ph.c
new file mode 100644
index 0000000..1cf5d6d
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shll_s_ph.c
@@ -0,0 +1,43 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rt, dsp;
+ long long result, resultdsp;
+
+ rt = 0x12345678;
+ result = 0x12345678;
+ resultdsp = 0x0;
+
+ __asm
+ ("shll_s.ph %0, %2, 0x0\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;
+ }
+
+ 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/src/tests/tcg/mips/mips64-dsp/shll_s_pw.c b/src/tests/tcg/mips/mips64-dsp/shll_s_pw.c
new file mode 100644
index 0000000..e38f686
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shll_s_pw.c
@@ -0,0 +1,43 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rt, dsp;
+ long long result, resultdsp;
+
+ rt = 0x8765432112345678;
+ result = 0x8765432112345678;
+ resultdsp = 0;
+
+ __asm
+ ("shll_s.pw %0, %2, 0x0\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;
+ }
+
+ 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/src/tests/tcg/mips/mips64-dsp/shll_s_qh.c b/src/tests/tcg/mips/mips64-dsp/shll_s_qh.c
new file mode 100644
index 0000000..f2f57fa
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shll_s_qh.c
@@ -0,0 +1,43 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rt, dsp;
+ long long res, resdsp;
+
+ rt = 0x9ba8765433456789;
+ res = 0x9ba8765433456789;
+ resdsp = 0x0;
+ __asm
+ ("shll_s.qh %0, %2, 0x0\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;
+ }
+
+ 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/src/tests/tcg/mips/mips64-dsp/shll_s_w.c b/src/tests/tcg/mips/mips64-dsp/shll_s_w.c
new file mode 100644
index 0000000..5780061
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shllv_ob.c b/src/tests/tcg/mips/mips64-dsp/shllv_ob.c
new file mode 100644
index 0000000..96a2e6f
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shllv_ob.c
@@ -0,0 +1,45 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rt, rs, dsp;
+ long long result, resultdsp;
+
+ rt = 0x8765432112345678;
+ rs = 0x0;
+ result = 0x8765432112345678;
+ resultdsp = 0;
+
+ __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;
+ }
+
+ 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/src/tests/tcg/mips/mips64-dsp/shllv_ph.c b/src/tests/tcg/mips/mips64-dsp/shllv_ph.c
new file mode 100644
index 0000000..532291f
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shllv_pw.c b/src/tests/tcg/mips/mips64-dsp/shllv_pw.c
new file mode 100644
index 0000000..8d4ec29
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shllv_pw.c
@@ -0,0 +1,45 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rt, rs, dsp;
+ long long result, resultdsp;
+ rt = 0x8765432112345678;
+ rs = 0x0;
+ result = 0x8765432112345678;
+ resultdsp = 0;
+
+ __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;
+ }
+
+
+ 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/src/tests/tcg/mips/mips64-dsp/shllv_qb.c b/src/tests/tcg/mips/mips64-dsp/shllv_qb.c
new file mode 100644
index 0000000..e49356b
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shllv_qh.c b/src/tests/tcg/mips/mips64-dsp/shllv_qh.c
new file mode 100644
index 0000000..0de4077
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shllv_qh.c
@@ -0,0 +1,45 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rt, rs, dsp;
+ long long result, resultdsp;
+
+ rt = 0x8765432112345678;
+ rs = 0x0;
+ result = 0x8765432112345678;
+ resultdsp = 0;
+
+ __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;
+ }
+
+ 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/src/tests/tcg/mips/mips64-dsp/shllv_s_ph.c b/src/tests/tcg/mips/mips64-dsp/shllv_s_ph.c
new file mode 100644
index 0000000..7e69f94
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shllv_s_pw.c b/src/tests/tcg/mips/mips64-dsp/shllv_s_pw.c
new file mode 100644
index 0000000..f8dc8d2
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shllv_s_pw.c
@@ -0,0 +1,45 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rt, rs, dsp;
+ long long result, resultdsp;
+
+ rt = 0x8765432112345678;
+ rs = 0x0;
+ result = 0x8765432112345678;
+ resultdsp = 0;
+
+ __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;
+ }
+
+ 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/src/tests/tcg/mips/mips64-dsp/shllv_s_qh.c b/src/tests/tcg/mips/mips64-dsp/shllv_s_qh.c
new file mode 100644
index 0000000..db3832d
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shllv_s_qh.c
@@ -0,0 +1,45 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rt, rs, dsp;
+ long long result, resultdsp;
+
+ rt = 0x8765432112345678;
+ rs = 0x0;
+ result = 0x8765432112345678;
+ resultdsp = 0;
+
+ __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;
+ }
+
+ 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/src/tests/tcg/mips/mips64-dsp/shllv_s_w.c b/src/tests/tcg/mips/mips64-dsp/shllv_s_w.c
new file mode 100644
index 0000000..5f6af8b
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shra_ob.c b/src/tests/tcg/mips/mips64-dsp/shra_ob.c
new file mode 100644
index 0000000..d7fcfa8
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shra_ob.c
@@ -0,0 +1,23 @@
+#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/src/tests/tcg/mips/mips64-dsp/shra_ph.c b/src/tests/tcg/mips/mips64-dsp/shra_ph.c
new file mode 100644
index 0000000..a2dc014
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shra_pw.c b/src/tests/tcg/mips/mips64-dsp/shra_pw.c
new file mode 100644
index 0000000..33b1b8f
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shra_pw.c
@@ -0,0 +1,36 @@
+#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;
+ }
+
+ rt = 0x1234567887654321;
+ res = 0x1234567887654321;
+
+ __asm
+ ("shra.pw %0, %1, 0x0"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+
+ if (rd != res) {
+ printf("shra.pw error\n");
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/shra_qh.c b/src/tests/tcg/mips/mips64-dsp/shra_qh.c
new file mode 100644
index 0000000..85dbfef
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shra_qh.c
@@ -0,0 +1,37 @@
+#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;
+ }
+
+ rt = 0x8512345654323454;
+ res = 0x8512345654323454;
+
+ __asm
+ ("shra.qh %0, %1, 0x0\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+
+ if (rd != res) {
+ printf("shra.qh error1\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/shra_r_ob.c b/src/tests/tcg/mips/mips64-dsp/shra_r_ob.c
new file mode 100644
index 0000000..1847094
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shra_r_ph.c b/src/tests/tcg/mips/mips64-dsp/shra_r_ph.c
new file mode 100644
index 0000000..e0943ad
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shra_r_pw.c b/src/tests/tcg/mips/mips64-dsp/shra_r_pw.c
new file mode 100644
index 0000000..6a86e68
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shra_r_pw.c
@@ -0,0 +1,36 @@
+#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;
+ }
+
+ rt = 0x1234567887654321;
+ res = 0x1234567887654321;
+
+ __asm
+ ("shra_r.pw %0, %1, 0x0"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+
+ if (rd != res) {
+ printf("shra_r.pw error\n");
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/shra_r_qh.c b/src/tests/tcg/mips/mips64-dsp/shra_r_qh.c
new file mode 100644
index 0000000..d5c2110
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shra_r_qh.c
@@ -0,0 +1,37 @@
+#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;
+ }
+
+ rt = 0x8512345654323454;
+ res = 0x8512345654323454;
+
+ __asm
+ ("shra_r.qh %0, %1, 0x0\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+
+ if (rd != res) {
+ printf("shra_r.qh error1\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/shra_r_w.c b/src/tests/tcg/mips/mips64-dsp/shra_r_w.c
new file mode 100644
index 0000000..36d2c9c
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shrav_ph.c b/src/tests/tcg/mips/mips64-dsp/shrav_ph.c
new file mode 100644
index 0000000..1b4e983
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shrav_pw.c b/src/tests/tcg/mips/mips64-dsp/shrav_pw.c
new file mode 100644
index 0000000..e19d515
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shrav_pw.c
@@ -0,0 +1,38 @@
+#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;
+ }
+
+ rt = 0x1234567887654321;
+ rs = 0x0;
+ res = 0x1234567887654321;
+
+ __asm
+ ("shrav.pw %0, %1, %2"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+
+ if (rd != res) {
+ printf("shrav.pw error1\n");
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/shrav_qh.c b/src/tests/tcg/mips/mips64-dsp/shrav_qh.c
new file mode 100644
index 0000000..dc92e09
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shrav_qh.c
@@ -0,0 +1,39 @@
+#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;
+ }
+
+ rt = 0x8512345654323454;
+ rs = 0x0;
+ res = 0x8512345654323454;
+
+ __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/src/tests/tcg/mips/mips64-dsp/shrav_r_ph.c b/src/tests/tcg/mips/mips64-dsp/shrav_r_ph.c
new file mode 100644
index 0000000..350d529
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shrav_r_pw.c b/src/tests/tcg/mips/mips64-dsp/shrav_r_pw.c
new file mode 100644
index 0000000..25b0545
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shrav_r_pw.c
@@ -0,0 +1,37 @@
+#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;
+ }
+
+ rt = 0x1234567887654321;
+ rs = 0x0;
+ res = 0x1234567887654321;
+
+ __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/src/tests/tcg/mips/mips64-dsp/shrav_r_qh.c b/src/tests/tcg/mips/mips64-dsp/shrav_r_qh.c
new file mode 100644
index 0000000..fd187a1
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shrav_r_qh.c
@@ -0,0 +1,39 @@
+#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;
+ }
+
+ rt = 0x400000000000000;
+ rs = 0x0;
+ res = 0x400000000000000;
+
+ __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/src/tests/tcg/mips/mips64-dsp/shrav_r_w.c b/src/tests/tcg/mips/mips64-dsp/shrav_r_w.c
new file mode 100644
index 0000000..3766c72
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shrl_ob.c b/src/tests/tcg/mips/mips64-dsp/shrl_ob.c
new file mode 100644
index 0000000..a114571
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shrl_ob.c
@@ -0,0 +1,38 @@
+#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;
+ }
+
+ rt = 0xab76543212345678;
+ res = 0xab76543212345678;
+
+ __asm
+ ("shrl.ob %0, %1, 0x0\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+
+ if (rd != res) {
+ printf("shrl.ob error\n");
+ return -1;
+ }
+
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dsp/shrl_qb.c b/src/tests/tcg/mips/mips64-dsp/shrl_qb.c
new file mode 100644
index 0000000..c0e36db
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shrl_qh.c b/src/tests/tcg/mips/mips64-dsp/shrl_qh.c
new file mode 100644
index 0000000..c156246
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shrlv_ob.c b/src/tests/tcg/mips/mips64-dsp/shrlv_ob.c
new file mode 100644
index 0000000..cb39c46
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/shrlv_ob.c
@@ -0,0 +1,39 @@
+#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;
+ }
+
+ rt = 0xab76543212345678;
+ rs = 0x0;
+ res = 0xab76543212345678;
+
+ __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/src/tests/tcg/mips/mips64-dsp/shrlv_qb.c b/src/tests/tcg/mips/mips64-dsp/shrlv_qb.c
new file mode 100644
index 0000000..5616aa9
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/shrlv_qh.c b/src/tests/tcg/mips/mips64-dsp/shrlv_qh.c
new file mode 100644
index 0000000..05de2fd
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/subq_ph.c b/src/tests/tcg/mips/mips64-dsp/subq_ph.c
new file mode 100644
index 0000000..6a1b186
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/subq_pw.c b/src/tests/tcg/mips/mips64-dsp/subq_pw.c
new file mode 100644
index 0000000..32f96ba
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/subq_qh.c b/src/tests/tcg/mips/mips64-dsp/subq_qh.c
new file mode 100644
index 0000000..76d5f0a
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/subq_s_ph.c b/src/tests/tcg/mips/mips64-dsp/subq_s_ph.c
new file mode 100644
index 0000000..0b162f0
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/subq_s_pw.c b/src/tests/tcg/mips/mips64-dsp/subq_s_pw.c
new file mode 100644
index 0000000..e8e0b05
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/subq_s_pw.c
@@ -0,0 +1,63 @@
+#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;
+ }
+
+ rt = 0x8000000080000000;
+ rs = 0x7000000070000000;
+ 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 ((dspreg != dspresult)) {
+ printf("subq_s.pw error3\n");
+
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/tests/tcg/mips/mips64-dsp/subq_s_qh.c b/src/tests/tcg/mips/mips64-dsp/subq_s_qh.c
new file mode 100644
index 0000000..4053b6b
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dsp/subq_s_qh.c
@@ -0,0 +1,61 @@
+#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;
+ }
+
+ rs = 0x8000000000000000;
+ rt = 0x7000000000000000;
+ result = 0x8000000000000000;
+ 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 error3\n");
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/tests/tcg/mips/mips64-dsp/subq_s_w.c b/src/tests/tcg/mips/mips64-dsp/subq_s_w.c
new file mode 100644
index 0000000..91d32da
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/subu_ob.c b/src/tests/tcg/mips/mips64-dsp/subu_ob.c
new file mode 100644
index 0000000..f670967
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/subu_qb.c b/src/tests/tcg/mips/mips64-dsp/subu_qb.c
new file mode 100644
index 0000000..9eb80df
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/subu_s_ob.c b/src/tests/tcg/mips/mips64-dsp/subu_s_ob.c
new file mode 100644
index 0000000..5df64e5
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/subu_s_qb.c b/src/tests/tcg/mips/mips64-dsp/subu_s_qb.c
new file mode 100644
index 0000000..9de76f4
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dsp/wrdsp.c b/src/tests/tcg/mips/mips64-dsp/wrdsp.c
new file mode 100644
index 0000000..3033fd8
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/.directory b/src/tests/tcg/mips/mips64-dspr2/.directory
new file mode 100644
index 0000000..c75a914
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/.directory
@@ -0,0 +1,2 @@
+[Dolphin]
+Timestamp=2012,8,3,16,41,52
diff --git a/src/tests/tcg/mips/mips64-dspr2/Makefile b/src/tests/tcg/mips/mips64-dspr2/Makefile
new file mode 100644
index 0000000..ba44bb9
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/Makefile
@@ -0,0 +1,116 @@
+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 += 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/src/tests/tcg/mips/mips64-dspr2/absq_s_qb.c b/src/tests/tcg/mips/mips64-dspr2/absq_s_qb.c
new file mode 100644
index 0000000..f7aec3e
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/addqh_ph.c b/src/tests/tcg/mips/mips64-dspr2/addqh_ph.c
new file mode 100644
index 0000000..6b43cb8
--- /dev/null
+++ b/src/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 = 0x81000100;
+ rt = 0xc2000100;
+ result = 0xffffffffa1800100;
+ __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/src/tests/tcg/mips/mips64-dspr2/addqh_r_ph.c b/src/tests/tcg/mips/mips64-dspr2/addqh_r_ph.c
new file mode 100644
index 0000000..890ec98
--- /dev/null
+++ b/src/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 = 0x81010100;
+ rt = 0xc2000100;
+ result = 0xffffffffa1810100;
+ __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/src/tests/tcg/mips/mips64-dspr2/addqh_r_w.c b/src/tests/tcg/mips/mips64-dspr2/addqh_r_w.c
new file mode 100644
index 0000000..d324dec
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/addqh_w.c b/src/tests/tcg/mips/mips64-dspr2/addqh_w.c
new file mode 100644
index 0000000..78559e6
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/addu_ph.c b/src/tests/tcg/mips/mips64-dspr2/addu_ph.c
new file mode 100644
index 0000000..d64c8cd
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/addu_ph.c
@@ -0,0 +1,37 @@
+#include"io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long dsp;
+ 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("1 addu.ph error\n");
+ return -1;
+ }
+
+ rs = 0xFFFF1111;
+ rt = 0x00020001;
+ result = 0x00011112;
+ __asm
+ ("addu.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) {
+ printf("2 addu.ph error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dspr2/addu_qh.c b/src/tests/tcg/mips/mips64-dspr2/addu_qh.c
new file mode 100644
index 0000000..edcbf34
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/addu_qh.c
@@ -0,0 +1,43 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt, dspreg;
+ long long result, 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/src/tests/tcg/mips/mips64-dspr2/addu_s_ph.c b/src/tests/tcg/mips/mips64-dspr2/addu_s_ph.c
new file mode 100644
index 0000000..9250edb
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/addu_s_ph.c
@@ -0,0 +1,37 @@
+#include"io.h"
+
+int main(void)
+{
+ long long rd, rs, rt;
+ long long dsp;
+ 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, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ if ((rd != result) || (((dsp >> 20) & 0x01) != 1)) {
+ printf("addu_s.ph error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dspr2/addu_s_qh.c b/src/tests/tcg/mips/mips64-dspr2/addu_s_qh.c
new file mode 100644
index 0000000..b0c1626
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/addu_s_qh.c
@@ -0,0 +1,43 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt, dspreg;
+ long long result, 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("1 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("2 addu_s.qh error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dspr2/adduh_ob.c b/src/tests/tcg/mips/mips64-dspr2/adduh_ob.c
new file mode 100644
index 0000000..9b309f6
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/adduh_ob.c
@@ -0,0 +1,35 @@
+#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;
+ }
+
+ rs = 0xac50691729945316;
+ rt = 0xb9234ca3f5573162;
+ result = 0xb2395a5d8f75423c;
+
+ __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/src/tests/tcg/mips/mips64-dspr2/adduh_qb.c b/src/tests/tcg/mips/mips64-dspr2/adduh_qb.c
new file mode 100644
index 0000000..796b409
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/adduh_r_ob.c b/src/tests/tcg/mips/mips64-dspr2/adduh_r_ob.c
new file mode 100644
index 0000000..832de83
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/adduh_r_ob.c
@@ -0,0 +1,35 @@
+#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("1 adduh_r.ob error\n\t");
+ return -1;
+ }
+
+ rs = 0xac50691729945316;
+ rt = 0xb9234ca3f5573162;
+ result = 0xb33a5b5d8f76423c;
+
+ __asm("adduh_r.ob %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ if (rd != result) {
+ printf("2 adduh_r.ob error\n\t");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dspr2/adduh_r_qb.c b/src/tests/tcg/mips/mips64-dspr2/adduh_r_qb.c
new file mode 100644
index 0000000..ae65fa5
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/append.c b/src/tests/tcg/mips/mips64-dspr2/append.c
new file mode 100644
index 0000000..68a7cec
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/balign.c b/src/tests/tcg/mips/mips64-dspr2/balign.c
new file mode 100644
index 0000000..7fbe815
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c b/src/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c
new file mode 100644
index 0000000..61217f3
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_ob.c
@@ -0,0 +1,44 @@
+#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("1 cmpgdu.eq.ob error\n");
+ return -1;
+ }
+
+ rs = 0x133256789ABCDEF0;
+ rt = 0x123456789ABCDEFF;
+ result = 0x3E;
+ dspresult = 0x3E;
+
+ __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("2 cmpgdu.eq.ob error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c b/src/tests/tcg/mips/mips64-dspr2/cmpgdu_eq_qb.c
new file mode 100644
index 0000000..c63f648
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c b/src/tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c
new file mode 100644
index 0000000..b3da098
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/cmpgdu_le_ob.c
@@ -0,0 +1,44 @@
+#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;
+ }
+
+ rs = 0x113556789ABCDEF0;
+ rt = 0x123456789ABCDEFF;
+ result = 0xBE;
+ 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/src/tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c b/src/tests/tcg/mips/mips64-dspr2/cmpgdu_le_qb.c
new file mode 100644
index 0000000..f0a60ea
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c b/src/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c
new file mode 100644
index 0000000..d80b4e6
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_ob.c
@@ -0,0 +1,44 @@
+#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;
+ }
+
+ rs = 0x143356789ABCDEF0;
+ rt = 0x123456789ABCDEFF;
+ dspresult = 0x41;
+ result = 0x41;
+
+ __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/src/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c b/src/tests/tcg/mips/mips64-dspr2/cmpgdu_lt_qb.c
new file mode 100644
index 0000000..a71e4e3
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/dbalign.c b/src/tests/tcg/mips/mips64-dspr2/dbalign.c
new file mode 100644
index 0000000..c7431b1
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/dbalign.c
@@ -0,0 +1,39 @@
+#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;
+ }
+
+ rt = 0x1234567887654321;
+ rs = 0xabcd1234abcd1234;
+
+ res = 0x7887654321abcd12;
+
+ asm ("dbalign %0, %1, 0x3\n"
+ : "=r"(rt)
+ : "r"(rs)
+ );
+
+ if (rt != res) {
+ printf("dbalign error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dspr2/dpa_w_ph.c b/src/tests/tcg/mips/mips64-dspr2/dpa_w_ph.c
new file mode 100644
index 0000000..39dc99a
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/dpa_w_ph.c
@@ -0,0 +1,47 @@
+#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) || (acl != resultl)) {
+ printf("1 dpa.w.ph error\n");
+ return -1;
+ }
+
+ ach = 6, acl = 7;
+ rs = 0xFFFF00FF;
+ rt = 0xFFFF0002;
+ resulth = 0x05;
+ resultl = 0xfffffffffffe0206;
+ __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) || (acl != resultl)) {
+ printf("2 dpa.w.ph error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dspr2/dpa_w_qh.c b/src/tests/tcg/mips/mips64-dspr2/dpa_w_qh.c
new file mode 100644
index 0000000..1411e44
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c b/src/tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c
new file mode 100644
index 0000000..51252fb
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/dpaqx_s_w_ph.c
@@ -0,0 +1,97 @@
+#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;
+ }
+
+ ach = 5;
+ acl = 5;
+ rs = 0x800000FF;
+ rt = 0x00028000;
+ resulth = 0x05;
+ resultl = 0xffffffff80000400;
+ 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) || (ach != resulth) || (acl != resultl)) {
+ printf("dpaqx_s.w.ph error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c b/src/tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c
new file mode 100644
index 0000000..18d6b3a
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/dpaqx_sa_w_ph.c
@@ -0,0 +1,54 @@
+#include "io.h"
+
+int main()
+{
+ 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
+ ("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)
+ );
+ if ((dsp >> (16 + 1) != resultdsp) || (ach != resulth) ||
+ (acl != resultl)) {
+ printf("dpaqx_sa.w.ph errror\n");
+ }
+
+ ach = 9;
+ acl = 0xb;
+ rs = 0x800000FF;
+ rt = 0x00018000;
+ 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)
+ );
+ if ((dsp >> (16 + 1) != resultdsp) || (ach != resulth) ||
+ (acl != resultl)) {
+ printf("dpaqx_sa.w.ph errror\n");
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dspr2/dpax_w_ph.c b/src/tests/tcg/mips/mips64-dspr2/dpax_w_ph.c
new file mode 100644
index 0000000..9d595fc
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/dps_w_ph.c b/src/tests/tcg/mips/mips64-dspr2/dps_w_ph.c
new file mode 100644
index 0000000..99f292e
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/dps_w_qh.c b/src/tests/tcg/mips/mips64-dspr2/dps_w_qh.c
new file mode 100644
index 0000000..61277eb
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c b/src/tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c
new file mode 100644
index 0000000..ba46a92
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/dpsqx_s_w_ph.c
@@ -0,0 +1,55 @@
+#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;
+ }
+
+ ach = 0x99f13005;
+ acl = 0x51730062;
+ rs = 0x80008000;
+ rt = 0x80008000;
+
+ resulth = 0xffffffff99f13004;
+ resultl = 0x51730064;
+ resultdsp = 0x01;
+ __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/src/tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c b/src/tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c
new file mode 100644
index 0000000..24c8881
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/dpsqx_sa_w_ph.c
@@ -0,0 +1,53 @@
+#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;
+ }
+
+ ach = 0x8c0b354A;
+ acl = 0xbbc02249;
+ rs = 0x800023AD;
+ rt = 0x01648000;
+ resulth = 0xffffffffffffffff;
+ resultl = 0xffffffff80000000;
+ 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/src/tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c b/src/tests/tcg/mips/mips64-dspr2/dpsx_w_ph.c
new file mode 100644
index 0000000..b6291b5
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/head.S b/src/tests/tcg/mips/mips64-dspr2/head.S
new file mode 100644
index 0000000..9a099ae
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/io.h b/src/tests/tcg/mips/mips64-dspr2/io.h
new file mode 100644
index 0000000..b7db61d
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/mips_boot.lds b/src/tests/tcg/mips/mips64-dspr2/mips_boot.lds
new file mode 100644
index 0000000..bd7c0c0
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/mul_ph.c b/src/tests/tcg/mips/mips64-dspr2/mul_ph.c
new file mode 100644
index 0000000..5a3d05c
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/mul_ph.c
@@ -0,0 +1,50 @@
+#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;
+ }
+
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 0x00210010;
+ rt = 0x00110005;
+ result = 0x2310050;
+ resultdsp = 0;
+
+ __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/src/tests/tcg/mips/mips64-dspr2/mul_s_ph.c b/src/tests/tcg/mips/mips64-dspr2/mul_s_ph.c
new file mode 100644
index 0000000..7c8b2c7
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/mul_s_ph.c
@@ -0,0 +1,67 @@
+#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("1 mul_s.ph error\n");
+ return -1;
+ }
+
+ rs = 0x7fffff00;
+ rt = 0xff007fff;
+ result = 0xffffffff80008000;
+ 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("2 mul_s.ph error\n");
+ return -1;
+ }
+
+ dsp = 0;
+ __asm
+ ("wrdsp %0\n\t"
+ :
+ : "r"(dsp)
+ );
+
+ rs = 0x00320001;
+ rt = 0x00210002;
+ result = 0x06720002;
+ resultdsp = 0;
+
+ __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("3 mul_s.ph error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/mips/mips64-dspr2/mulq_rs_w.c b/src/tests/tcg/mips/mips64-dspr2/mulq_rs_w.c
new file mode 100644
index 0000000..ffdc66d
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/mulq_s_ph.c b/src/tests/tcg/mips/mips64-dspr2/mulq_s_ph.c
new file mode 100644
index 0000000..b8c20c6
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/mulq_s_w.c b/src/tests/tcg/mips/mips64-dspr2/mulq_s_w.c
new file mode 100644
index 0000000..db74b71
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c b/src/tests/tcg/mips/mips64-dspr2/mulsa_w_ph.c
new file mode 100644
index 0000000..5b22a60
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c b/src/tests/tcg/mips/mips64-dspr2/mulsaq_s_w_ph.c
new file mode 100644
index 0000000..835a73d
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/precr_qb_ph.c b/src/tests/tcg/mips/mips64-dspr2/precr_qb_ph.c
new file mode 100644
index 0000000..80d5e8d
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c b/src/tests/tcg/mips/mips64-dspr2/precr_sra_ph_w.c
new file mode 100644
index 0000000..b1d7bcd
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c b/src/tests/tcg/mips/mips64-dspr2/precr_sra_r_ph_w.c
new file mode 100644
index 0000000..62d220d
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/prepend.c b/src/tests/tcg/mips/mips64-dspr2/prepend.c
new file mode 100644
index 0000000..4ab083e
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/printf.c b/src/tests/tcg/mips/mips64-dspr2/printf.c
new file mode 100644
index 0000000..cf8676d
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/shra_qb.c b/src/tests/tcg/mips/mips64-dspr2/shra_qb.c
new file mode 100644
index 0000000..cac3102
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/shra_r_qb.c b/src/tests/tcg/mips/mips64-dspr2/shra_r_qb.c
new file mode 100644
index 0000000..9c64f75
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/shrav_ob.c b/src/tests/tcg/mips/mips64-dspr2/shrav_ob.c
new file mode 100644
index 0000000..fbdfbab
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/shrav_qb.c b/src/tests/tcg/mips/mips64-dspr2/shrav_qb.c
new file mode 100644
index 0000000..a716203
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/shrav_r_ob.c b/src/tests/tcg/mips/mips64-dspr2/shrav_r_ob.c
new file mode 100644
index 0000000..b80100a
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/shrav_r_qb.c b/src/tests/tcg/mips/mips64-dspr2/shrav_r_qb.c
new file mode 100644
index 0000000..009080b
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/shrl_ph.c b/src/tests/tcg/mips/mips64-dspr2/shrl_ph.c
new file mode 100644
index 0000000..e32d976
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/shrlv_ph.c b/src/tests/tcg/mips/mips64-dspr2/shrlv_ph.c
new file mode 100644
index 0000000..58c5488
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/subqh_ph.c b/src/tests/tcg/mips/mips64-dspr2/subqh_ph.c
new file mode 100644
index 0000000..9037401
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/subqh_r_ph.c b/src/tests/tcg/mips/mips64-dspr2/subqh_r_ph.c
new file mode 100644
index 0000000..b8f9d2f
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/subqh_r_w.c b/src/tests/tcg/mips/mips64-dspr2/subqh_r_w.c
new file mode 100644
index 0000000..b025e40
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/subqh_w.c b/src/tests/tcg/mips/mips64-dspr2/subqh_w.c
new file mode 100644
index 0000000..65f1760
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/subu_ph.c b/src/tests/tcg/mips/mips64-dspr2/subu_ph.c
new file mode 100644
index 0000000..60a6b1b
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/subu_qh.c b/src/tests/tcg/mips/mips64-dspr2/subu_qh.c
new file mode 100644
index 0000000..911cb34
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/subu_s_ph.c b/src/tests/tcg/mips/mips64-dspr2/subu_s_ph.c
new file mode 100644
index 0000000..ae32cc0
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/subu_s_qh.c b/src/tests/tcg/mips/mips64-dspr2/subu_s_qh.c
new file mode 100644
index 0000000..de7a29e
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/subu_s_qh.c
@@ -0,0 +1,42 @@
+#include "io.h"
+
+int main(void)
+{
+ long long rd, rs, rt, dspreg, result, dspresult;
+ rs = 0x1111111111111111;
+ rt = 0x2222222222222222;
+ result = 0x1111111111111111;
+ dspresult = 0x00;
+
+ __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;
+ }
+
+
+ rs = 0x8888888888888888;
+ rt = 0xa888a888a888a888;
+ 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/src/tests/tcg/mips/mips64-dspr2/subuh_ob.c b/src/tests/tcg/mips/mips64-dspr2/subuh_ob.c
new file mode 100644
index 0000000..3fc452b
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/subuh_ob.c
@@ -0,0 +1,36 @@
+#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;
+ }
+
+ rs = 0x246856789ABCDEF0;
+ rt = 0x1131517191B1D1F1;
+ result = 0x1b4f2d2d51637577;
+
+ __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/src/tests/tcg/mips/mips64-dspr2/subuh_qb.c b/src/tests/tcg/mips/mips64-dspr2/subuh_qb.c
new file mode 100644
index 0000000..aac7a83
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/subuh_r_ob.c b/src/tests/tcg/mips/mips64-dspr2/subuh_r_ob.c
new file mode 100644
index 0000000..fc20ffd
--- /dev/null
+++ b/src/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/src/tests/tcg/mips/mips64-dspr2/subuh_r_qb.c b/src/tests/tcg/mips/mips64-dspr2/subuh_r_qb.c
new file mode 100644
index 0000000..66d4680
--- /dev/null
+++ b/src/tests/tcg/mips/mips64-dspr2/subuh_r_qb.c
@@ -0,0 +1,37 @@
+#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("1 subuh_r.qb wrong\n");
+ return -1;
+ }
+
+ rs = 0xBEFC292A;
+ rt = 0x9205C1B4;
+ result = 0x167cb4bb;
+
+ __asm
+ ("subuh_r.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ if (rd != result) {
+ printf("2 subuh_r.qb wrong\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/Makefile b/src/tests/tcg/openrisc/Makefile
new file mode 100644
index 0000000..7e65888
--- /dev/null
+++ b/src/tests/tcg/openrisc/Makefile
@@ -0,0 +1,71 @@
+-include ../../config-host.mak
+
+CROSS = or32-linux-
+
+SIM = qemu-or32
+
+CC = $(CROSS)gcc
+
+TESTCASES = test_add.tst
+TESTCASES += test_sub.tst
+TESTCASES += test_addc.tst
+TESTCASES += test_addi.tst
+TESTCASES += test_addic.tst
+TESTCASES += test_and_or.tst
+TESTCASES += test_bf.tst
+TESTCASES += test_bnf.tst
+TESTCASES += test_div.tst
+TESTCASES += test_divu.tst
+TESTCASES += test_extx.tst
+TESTCASES += test_fx.tst
+TESTCASES += test_jal.tst
+TESTCASES += test_j.tst
+TESTCASES += test_lf_div.tst
+TESTCASES += test_lf_eqs.tst
+TESTCASES += test_lf_ges.tst
+TESTCASES += test_lf_gts.tst
+TESTCASES += test_lf_les.tst
+TESTCASES += test_lf_lts.tst
+TESTCASES += test_lf_mul.tst
+TESTCASES += test_lf_nes.tst
+TESTCASES += test_lf_rem.tst
+TESTCASES += test_lf_sub.tst
+TESTCASES += test_lf_add.tst
+TESTCASES += test_logic.tst
+TESTCASES += test_lx.tst
+TESTCASES += test_movhi.tst
+TESTCASES += test_mul.tst
+TESTCASES += test_mulu.tst
+TESTCASES += test_muli.tst
+TESTCASES += test_sfeq.tst
+TESTCASES += test_sfeqi.tst
+TESTCASES += test_sfges.tst
+TESTCASES += test_sfgesi.tst
+TESTCASES += test_sfgeu.tst
+TESTCASES += test_sfgeui.tst
+TESTCASES += test_sfgts.tst
+TESTCASES += test_sfgtsi.tst
+TESTCASES += test_sfgtu.tst
+TESTCASES += test_sfgtui.tst
+TESTCASES += test_sfles.tst
+TESTCASES += test_sflesi.tst
+TESTCASES += test_sfleu.tst
+TESTCASES += test_sfleui.tst
+TESTCASES += test_sflts.tst
+TESTCASES += test_sfltsi.tst
+TESTCASES += test_sfltu.tst
+TESTCASES += test_sfltui.tst
+TESTCASES += test_sfne.tst
+TESTCASES += test_sfnei.tst
+
+all: $(TESTCASES)
+
+%.tst: %.c
+ $(CC) -static $< -o $@
+
+
+check: $(TESTCASES)
+ @for case in $(TESTCASES); do $(SIM) $$case; echo $$case pass!; sleep 0.2; done
+
+clean:
+ $(RM) -rf $(TESTCASES)
diff --git a/src/tests/tcg/openrisc/test_add.c b/src/tests/tcg/openrisc/test_add.c
new file mode 100644
index 0000000..3d23592
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_add.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, d;
+ int result;
+
+ a = 0x100;
+ b = 0x100;
+ result = 0x200;
+ __asm
+ ("l.add %0, %0, %1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("add error\n");
+ return -1;
+ }
+
+ a = 0xffff;
+ b = 0x1;
+ result = 0x10000;
+ __asm
+ ("l.add %0, %0, %1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("add error\n");
+ return -1;
+ }
+
+ a = 0x7fffffff;
+ b = 0x1;
+ __asm
+ ("l.add %0, %1, %2\n\t"
+ : "=r"(d)
+ : "r"(b), "r"(a)
+ );
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_addc.c b/src/tests/tcg/openrisc/test_addc.c
new file mode 100644
index 0000000..a8f756a
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_addc.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x01;
+ c = 0xffffffff;
+ result = 0;
+ __asm
+ ("l.add r1, r1, r0\n\t" /* clear carry */
+ "l.addc %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("first addc error\n");
+ return -1;
+ }
+
+ b = 0x01;
+ c = 0xffffffff;
+ result = 0x80000001;
+ __asm
+ ("l.add r1, r1, r0\n\t" /* clear carry */
+ "l.addc %0, %1, %2\n\t"
+ "l.movhi %2, 0x7fff\n\t"
+ "l.ori %2, %2, 0xffff\n\t"
+ "l.addc %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("addc error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_addi.c b/src/tests/tcg/openrisc/test_addi.c
new file mode 100644
index 0000000..bbf5a5f
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_addi.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ b = 0x01;
+ result = 0x00;
+ __asm
+ ("l.addi %0, %1, 0xffff\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("addi error\n\t");
+ return -1;
+ }
+
+ b = 0x010000;
+ result = 0xffff;
+ __asm
+ ("l.addi %0, %1, 0xffff\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("addi error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_addic.c b/src/tests/tcg/openrisc/test_addic.c
new file mode 100644
index 0000000..857aaa1
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_addic.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 1;
+ result = 0x0;
+ __asm
+ ("l.add r1, r1, r0\n\t" /* clear carry */
+ "l.addic %0, %0, 0xffff\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("first addic error\n");
+ return -1;
+ }
+
+ a = -1;
+ result = 0x201;
+ __asm
+ ("l.add r1, r1, r0\n\t" /* clear carry */
+ "l.addic %0, %0, 0x1\n\t"
+ "l.ori %0, r0, 0x100\n\t"
+ "l.addic %0, %0, 0x100\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("second addic error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_and_or.c b/src/tests/tcg/openrisc/test_and_or.c
new file mode 100644
index 0000000..810d868
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_and_or.c
@@ -0,0 +1,65 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x2;
+ c = 0x1;
+ result = 0;
+ __asm
+ ("l.and %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("and error\n");
+ return -1;
+ }
+
+ result = 0x2;
+ __asm
+ ("l.andi %0, %1, 0x3\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("andi error %x\n", a);
+ return -1;
+ }
+
+ result = 0x3;
+ __asm
+ ("l.or %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("or error\n");
+ return -1;
+ }
+
+ result = 0x3;
+ __asm
+ ("l.xor %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("xor error\n");
+ return -1;
+ }
+
+ __asm
+ ("l.xori %0, %1, 0x1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("xori error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_bf.c b/src/tests/tcg/openrisc/test_bf.c
new file mode 100644
index 0000000..79f3fb9
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_bf.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 10;
+ c = 11;
+ result = 0x2;
+ __asm
+ ("1:\n\t"
+ "l.addi %1, %1, 0x01\n\t"
+ "l.addi %0, %0, 0x01\n\t"
+ "l.sfeq %1, %2\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sfeq error\n");
+ return -1;
+ }
+
+ a = 0x00;
+ b = 0x11;
+ c = 0x11;
+ result = 0x01;
+ __asm
+ ("1:\n\t"
+ "l.addi %1, %1, 0x01\n\t"
+ "l.addi %0, %0, 0x01\n\t"
+ "l.sfeq %1, %2\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sfeq error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_bnf.c b/src/tests/tcg/openrisc/test_bnf.c
new file mode 100644
index 0000000..f716215
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_bnf.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ b = 0;
+ result = 0x3;
+ __asm
+ ("l.sfeqi %1, 0x0\n\t"
+ "l.bnf 1f\n\t"
+ "l.nop\n\t"
+ "\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "\n\t"
+ "1:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("l.bnf error\n");
+ return -1;
+ }
+
+ a = 0;
+ b = 0;
+ result = 1;
+ __asm
+ ("l.sfeqi %1, 0x1\n\t"
+ "l.bnf 1f\n\t"
+ "l.nop\n\t"
+ "\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "\n\t"
+ "1:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("l.bnf error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_div.c b/src/tests/tcg/openrisc/test_div.c
new file mode 100644
index 0000000..9b65f6e
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_div.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x120;
+ c = 0x4;
+ result = 0x48;
+ __asm
+ ("l.div %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("div error\n");
+ return -1;
+ }
+
+ result = 0x4;
+ __asm
+ ("l.div %0, %1, %0\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("div error\n");
+ return -1;
+ }
+
+ b = 0xffffffff;
+ c = 0x80000000;
+ result = 0;
+ __asm
+ ("l.div %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("div error\n");
+ return -1;
+ }
+
+ b = 0x80000000;
+ c = 0xffffffff;
+ __asm
+ ("l.div %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_divu.c b/src/tests/tcg/openrisc/test_divu.c
new file mode 100644
index 0000000..bff9e3e
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_divu.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x120;
+ c = 0x4;
+ result = 0x48;
+
+ __asm
+ ("l.divu %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("divu error\n");
+ return -1;
+ }
+
+ result = 0x4;
+ __asm
+ ("l.divu %0, %1, %0\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("divu error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_extx.c b/src/tests/tcg/openrisc/test_extx.c
new file mode 100644
index 0000000..0922148
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_extx.c
@@ -0,0 +1,78 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ b = 0x83;
+ result = 0xffffff83;
+ __asm
+ ("l.extbs %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("extbs error\n");
+ return -1;
+ }
+
+ result = 0x83;
+ __asm
+ ("l.extbz %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("extbz error\n");
+ return -1;
+ }
+
+ b = 0x8083;
+ result = 0xffff8083;
+ __asm
+ ("l.exths %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("exths error\n");
+ return -1;
+ }
+
+ result = 0x8083;
+ __asm
+ ("l.exthz %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("exthz error\n");
+ return -1;
+ }
+
+ b = 0x11;
+ result = 0x11;
+ __asm
+ ("l.extws %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+
+ if (a != result) {
+ printf("extws error\n");
+ return -1;
+ }
+
+ __asm
+ ("l.extwz %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("extwz error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_fx.c b/src/tests/tcg/openrisc/test_fx.c
new file mode 100644
index 0000000..df86000
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_fx.c
@@ -0,0 +1,57 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ b = 0x123;
+ result = 1;
+ __asm
+ ("l.ff1 %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("ff1 error\n");
+ return -1;
+ }
+
+ b = 0x0;
+ result = 0;
+ __asm
+ ("l.ff1 %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("ff1 error\n");
+ return -1;
+ }
+
+ b = 0x123;
+ result = 9;
+ __asm
+ ("l.fl1 %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("fl1 error\n");
+ return -1;
+ }
+
+ b = 0x0;
+ result = 0;
+ __asm
+ ("l.fl1 %0, %1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("fl1 error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_j.c b/src/tests/tcg/openrisc/test_j.c
new file mode 100644
index 0000000..9ddf8bf
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_j.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 2;
+ __asm
+ ("l.addi %0, %0, 1\n\t"
+ "l.j j\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.nop\n\t"
+ "j:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("j error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_jal.c b/src/tests/tcg/openrisc/test_jal.c
new file mode 100644
index 0000000..7e2da40
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_jal.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 2;
+ __asm
+ ("l.addi %0, %0, 1\n\t"
+ "l.jal jal\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.nop\n\t"
+ "jal:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("jal error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_lf_add.c b/src/tests/tcg/openrisc/test_lf_add.c
new file mode 100644
index 0000000..e00212d
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_lf_add.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+ float a, b;
+ float res2;
+
+ a = 1.5;
+ b = 2.5;
+ res2 = 4.0;
+ __asm
+ ("lf.add.s %0, %0, %1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != res2) {
+ printf("lf.add.s error, %f\n", a);
+ return -1;
+ }
+
+/* double c, d;
+ double res1;
+
+ c = 1.5;
+ d = 1.5;
+ res1 = 3.00;
+ __asm
+ ("lf.add.d %0, %1, %2\n\t"
+ : "+r"(c)
+ : "r"(d)
+ );
+
+ if ((e - res1) > 0.002) {
+ printf("lf.add.d error, %f\n", e - res1);
+ return -1;
+ }*/
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_lf_div.c b/src/tests/tcg/openrisc/test_lf_div.c
new file mode 100644
index 0000000..70b5d1c
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_lf_div.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+
+int main(void)
+{
+ float a, b, c;
+ float result;
+
+ b = 1.5;
+ c = 0.5;
+ result = 3.0;
+ __asm
+ ("lf.div.s %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.div.s error\n");
+ return -1;
+ }
+
+/* double a, b, c, res;
+
+ b = 0x80000000;
+ c = 0x40;
+ result = 0x2000000;
+ __asm
+ ("lf.div.d %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.div.d error\n");
+ return -1;
+ }*/
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_lf_eqs.c b/src/tests/tcg/openrisc/test_lf_eqs.c
new file mode 100644
index 0000000..a176bd6
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_lf_eqs.c
@@ -0,0 +1,88 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, result;
+ float b, c;
+
+ a = 0x1;
+ b = 122.5;
+ c = 123.5;
+ result = 0x3;
+ __asm
+ ("lfeqd:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfeq.s %1, %2\n\t"
+ "l.bf lfeqd\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfeq.s error\n");
+ return -1;
+ }
+
+ b = 13.5;
+ c = 13.5;
+ result = 0x3;
+ __asm
+ ("lf.sfeq.s %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi r4, r4, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfeq.s error\n");
+ return -1;
+ }
+
+/* double b, c;
+ double result;
+ int a;
+
+ a = 0x1;
+ b = 122.5;
+ c = 133.5;
+ result = 0x3;
+
+ __asm
+ ("lfeqd:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfeq.d %1, %2\n\t"
+ "l.bf lfeqd\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfeq.d error\n");
+ return -1;
+ }
+
+ double c, d, res;
+ int e = 0;
+ c = 11.5;
+ d = 11.5;
+ res = 1;
+ __asm
+ ("lf.sfeq.d %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(e)
+ : "r"(c), "r"(d)
+ );
+ if (e != res) {
+ printf("lf.sfeq.d error\n");
+ return -1;
+ }*/
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_lf_ges.c b/src/tests/tcg/openrisc/test_lf_ges.c
new file mode 100644
index 0000000..98e7f50
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_lf_ges.c
@@ -0,0 +1,88 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, result;
+ float b, c;
+
+ a = 0;
+ b = 122.5;
+ c = 123.5;
+ result = 0x1;
+ __asm
+ ("lfges:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfge.s %1, %2\n\t"
+ "l.bf lfges\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfge.s error\n");
+ return -1;
+ }
+
+ b = 133.5;
+ c = 13.5;
+ result = 0x3;
+ __asm
+ ("l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfge.s %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfge.s error\n");
+ return -1;
+ }
+
+/* int a, result;
+ double b, c;
+
+ a = 0x1;
+ b = 122.5;
+ c = 123.5;
+ result = 0x2;
+ __asm
+ ("lfged:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfge.d %1, %2\n\t"
+ "l.bf lfged\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfge.d error\n");
+ return -1;
+ }
+
+ b = 133.5;
+ c = 13.5;
+ result = 0x4;
+ __asm
+ ("lf.sfge.d %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfge.d error\n");
+ return -1;
+ }*/
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_lf_gts.c b/src/tests/tcg/openrisc/test_lf_gts.c
new file mode 100644
index 0000000..f3df279
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_lf_gts.c
@@ -0,0 +1,86 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, result;
+ float b, c;
+
+ a = 0;
+ b = 122.5;
+ c = 123.5;
+ result = 0x1;
+ __asm
+ ("lfgts:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfgt.s %1, %2\n\t"
+ "l.bf lfgts\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfgt.s error\n");
+ return -1;
+ }
+
+ b = 133.5;
+ c = 13.5;
+ result = 0x1;
+ __asm
+ ("lf.sfgt.s %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfgt.s error\n");
+ return -1;
+ }
+
+/* int a, result;
+ double b, c;
+
+ a = 0;
+ b = 122.5;
+ c = 123.5;
+ result = 0x1;
+ __asm
+ ("lfgtd:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfgt.d %1, %2\n\t"
+ "l.bf lfgtd\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfgt.d error\n");
+ return -1;
+ }
+
+ b = 133.5;
+ c = 13.5;
+ result = 0x3;
+ __asm
+ ("l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfgt.d %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfgt.d error, %x\n", a);
+ return -1;
+ }*/
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_lf_les.c b/src/tests/tcg/openrisc/test_lf_les.c
new file mode 100644
index 0000000..046c511
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_lf_les.c
@@ -0,0 +1,88 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ float b, c;
+ int result;
+
+ a = 0;
+ b = 1234.2;
+ c = 12.4;
+ result = 0x1;
+ __asm
+ ("lfles:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfle.s %1, %2\n\t"
+ "l.bf lfles\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfle.s error\n");
+ return -1;
+ }
+
+ b = 1.1;
+ c = 19.4;
+ result = 0x3;
+ __asm
+ ("l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfle.s %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfle.s error\n");
+ return -1;
+ }
+
+/* int a;
+ double b, c;
+ int result;
+
+ a = 0;
+ b = 1212.5;
+ c = 123.5;
+ result = 0x1;
+ __asm
+ ("lfled:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfle.d %1, %2\n\t"
+ "l.bf lfled\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfle.d error\n");
+ return -1;
+ }
+
+ b = 13.5;
+ c = 113.5;
+ result = 0x2;
+ __asm
+ ("l.addi %0, %0, 0x1\n\t"
+ "lf.sfle.d %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfle.d error\n");
+ return -1;
+ }*/
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_lf_lts.c b/src/tests/tcg/openrisc/test_lf_lts.c
new file mode 100644
index 0000000..fa56721
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_lf_lts.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ float b, c, d;
+ int result;
+
+ a = 0;
+ b = 124.5;
+ c = 1.4;
+ result = 1;
+ __asm
+ ("lfltd:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sflt.s %1, %2\n\t"
+ "l.bf lfltd\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sflt.s error\n");
+ return -1;
+ }
+
+ a = 0;
+ b = 11.1;
+ c = 13.1;
+ d = 1.0;
+ result = 2;
+ __asm
+ ("1:\n\t"
+ "lf.add.s %1, %1, %3\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "lf.sflt.s %1, %2\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c), "r"(d)
+ );
+ if (a != result) {
+ printf("lf.sflt.s error\n");
+ return -1;
+ }
+
+/* int a;
+ double b, c;
+ int result;
+
+ a = 0;
+ b = 1432.1;
+ c = 2.4;
+ result = 0x1;
+ __asm
+ ("lfltd:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sflt.d %1, %2\n\t"
+ "l.bf lfltd\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sflt.d error\n");
+ return -1;
+ }
+
+ a = 0;
+ b = 1.1;
+ c = 19.7;
+ result = 2;
+ __asm
+ ("lf.sflt.d %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.addi %0, %0, 1\n\t"
+ : "+r"(a), "+r"(b)
+ : "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sflt.d error\n");
+ return -1;
+ }*/
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_lf_mul.c b/src/tests/tcg/openrisc/test_lf_mul.c
new file mode 100644
index 0000000..bc8ad80
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_lf_mul.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+int main(void)
+{
+ float a, b, c;
+ float result;
+
+ b = 1.5;
+ c = 4.0;
+ result = 6.0;
+ __asm
+ ("lf.mul.s %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.mul.s error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_lf_nes.c b/src/tests/tcg/openrisc/test_lf_nes.c
new file mode 100644
index 0000000..6136310
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_lf_nes.c
@@ -0,0 +1,89 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ float b, c;
+ int result;
+
+ a = 0;
+ b = 23.1;
+ c = 23.1;
+ result = 0x1;
+ __asm
+ ("lfnes:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfne.s %1, %2\n\t"
+ "l.bf lfnes\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfne.s error");
+ return -1;
+ }
+
+ b = 12.4;
+ c = 7.8;
+ result = 0x3;
+ __asm
+ ("l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfne.s %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfne.s error\n");
+ return -1;
+ }
+/* int a;
+ double b, c;
+ int result;
+
+ a = 0;
+ b = 124.3;
+ c = 124.3;
+ result = 0x1;
+ __asm
+ ("lfned:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfne.d %1, %2\n\t"
+ "l.bf lfned\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfne.d error\n");
+ return -1;
+ }
+
+ b = 11.5;
+ c = 16.7;
+ result = 0x3;
+ __asm
+ ("l.addi %0, %0, 0x1\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "lf.sfne.d %1, %2\n\t"
+ "l.bf 1f\n\t"
+ "l.nop\n\t"
+ "l.addi r4, r4, 0x1\n\t"
+ "l.addi r4, r4, 0x1\n\t"
+ "1:\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sfne.d error\n");
+ return -1;
+ }*/
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_lf_rem.c b/src/tests/tcg/openrisc/test_lf_rem.c
new file mode 100644
index 0000000..bd6090d
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_lf_rem.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+
+int main(void)
+{
+ float a, b, c;
+ float result;
+
+ b = 101.5;
+ c = 10;
+ result = 1.5;
+/* __asm
+ ("lf.rem.d %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.rem.d error\n");
+ return -1;
+ }*/
+
+ __asm
+ ("lf.rem.s %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.rem.s error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_lf_sub.c b/src/tests/tcg/openrisc/test_lf_sub.c
new file mode 100644
index 0000000..5ee9b03
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_lf_sub.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+
+int main(void)
+{
+ float a, b, c;
+ float result;
+
+ b = 10.5;
+ c = 1.5;
+ result = 9.0;
+ __asm
+ ("lf.sub.s %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sub.s error\n");
+ return -1;
+ }
+
+/* b = 0x999;
+ c = 0x654;
+ result = 0x345;
+ __asm
+ ("lf.sub.d %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("lf.sub.d error\n");
+ return -1;
+ }*/
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_logic.c b/src/tests/tcg/openrisc/test_logic.c
new file mode 100644
index 0000000..46d173f
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_logic.c
@@ -0,0 +1,105 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x9743;
+ c = 0x2;
+ result = 0x25d0c;
+ __asm
+ ("l.sll %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sll error\n");
+ return -1;
+ }
+
+ b = 0x9743;
+ result = 0x25d0c;
+ __asm
+ ("l.slli %0, %1, 0x2\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("slli error\n");
+ return -1;
+ }
+
+ b = 0x7654;
+ c = 0x03;
+ result = 0xeca;
+ __asm
+ ("l.srl %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+
+ b = 0x7654;
+ result = 0xeca;
+ __asm
+ ("l.srli %0, %1, 0x3\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("srli error\n");
+ return -1;
+ }
+
+ b = 0x80000001;
+ c = 0x4;
+ result = 0x18000000;
+ __asm
+ ("l.ror %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("ror error\n");
+ return -1;
+ }
+
+ b = 0x80000001;
+ result = 0x18000000;
+ __asm
+ ("l.rori %0, %1, 0x4\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("rori error\n");
+ return -1;
+ }
+
+ b = 0x80000001;
+ c = 0x03;
+ result = 0xf0000000;
+ __asm
+ ("l.sra %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sra error\n");
+ return -1;
+ }
+
+ b = 0x80000001;
+ result = 0xf0000000;
+ __asm
+ ("l.srai %0, %1, 0x3\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("srai error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_lx.c b/src/tests/tcg/openrisc/test_lx.c
new file mode 100644
index 0000000..792e3d5
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_lx.c
@@ -0,0 +1,84 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int p[50];
+ int result;
+
+ result = 0x23;
+ __asm
+ ("l.ori r8, r0, 0x123\n\t"
+ "l.sb 0x4 + %1, r8\n\t"
+ "\n\t"
+ "l.lbz %0, 0x4 + %1\n\t"
+ : "=r"(a), "+m"(*p)
+ );
+ if (a != result) {
+ printf("lbz error, %x\n", a);
+ return -1;
+ }
+
+ result = 0x23;
+ __asm
+ ("l.lbs %0, 0x4 + %1\n\t"
+ : "=r"(a)
+ : "m"(*p)
+ );
+ if (a != result) {
+ printf("lbs error\n");
+ return -1;
+ }
+
+ result = 0x1111;
+ __asm
+ ("l.ori r8, r0, 0x1111\n\t"
+ "l.sh 0x20 + %1, r8\n\t"
+ "\n\t"
+ "l.lhs %0, 0x20 + %1\n\t"
+ : "=r"(a), "=m"(*p)
+ );
+ if (a != result) {
+ printf("lhs error, %x\n", a);
+ return -1;
+ }
+
+ result = 0x1111;
+ __asm
+ ("l.lhz %0, 0x20 + %1\n\t"
+ : "=r"(a)
+ : "m"(*p)
+ );
+ if (a != result) {
+ printf("lhz error\n");
+ return -1;
+ }
+
+ result = 0x1111233;
+ __asm
+ ("l.ori r8, r0, 0x1233\n\t"
+ "l.movhi r1, 0x111\n\t"
+ "l.or r8, r8, r1\n\t"
+ "l.sw 0x123 + %1, r8\n\t"
+ "\n\t"
+ "l.lws %0, 0x123 + %1\n\t"
+ : "=r"(a), "+m"(*p)
+ );
+ if (a != result) {
+ printf("lws error, %x\n", a);
+ return -1;
+ }
+
+ result = 0x1111233;
+ __asm
+ ("l.lwz %0, 0x123 + %1\n\t"
+ : "=r"(a)
+ : "m"(*p)
+ );
+ if (a != result) {
+ printf("lwz error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_movhi.c b/src/tests/tcg/openrisc/test_movhi.c
new file mode 100644
index 0000000..737f75b
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_movhi.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ result = 0x1222;
+ __asm
+ ("l.movhi r3, 0x1222\n\t"
+ "l.srli %0, r3, 16\n\t"
+ : "=r"(a)
+ );
+ if (a != result) {
+ printf("movhi error\n");
+ return -1;
+ }
+
+ result = 0x1111;
+ __asm
+ ("l.movhi r8, 0x1111\n\t"
+ "l.srli %0, r8, 16\n\t"
+ : "=r"(a)
+ );
+ if (a != result) {
+ printf("movhi error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_mul.c b/src/tests/tcg/openrisc/test_mul.c
new file mode 100644
index 0000000..130101f
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_mul.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x4;
+ c = 0x1;
+ result = 0x4;
+ __asm
+ ("l.mul %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("mul error\n");
+ return -1;
+ }
+
+ b = 0x1;
+ c = 0x0;
+ result = 0x0;
+ __asm
+ ("l.mul %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("mul error\n");
+ return -1;
+ }
+
+ b = 0x1;
+ c = 0xff;
+ result = 0xff;
+ __asm
+ ("l.mul %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("mul error\n");
+ return -1;
+ }
+
+ b = 0x7fffffff;
+ c = 0x2;
+ result = 0xfffffffe;
+ __asm
+ ("l.mul %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("mul error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_muli.c b/src/tests/tcg/openrisc/test_muli.c
new file mode 100644
index 0000000..f1042e9
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_muli.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x4;
+ c = 0x1;
+ result = 0x4;
+ __asm
+ ("l.muli %0, %1, 0x1\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("muli error\n");
+ return -1;
+ }
+
+ b = 0x1;
+ c = 0x0;
+ result = 0x0;
+ __asm
+ ("l.muli %0, %1, 0x0\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("muli error\n");
+ return -1;
+ }
+
+ b = 0x1;
+ c = 0xff;
+ result = 0xff;
+ __asm
+ ("l.muli %0, %1, 0xff\n\t"
+ : "=r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("muli error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_mulu.c b/src/tests/tcg/openrisc/test_mulu.c
new file mode 100644
index 0000000..2d1e97d
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_mulu.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ b = 0x4;
+ c = 0x1;
+ result = 0x4;
+ __asm
+ ("l.mulu %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("mulu error\n");
+ return -1;
+ }
+
+ b = 0x1;
+ c = 0x0;
+ result = 0x0;
+ __asm
+ ("l.mulu %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("mulu error\n");
+ return -1;
+ }
+
+ b = 0x1;
+ c = 0xff;
+ result = 0xff;
+ __asm
+ ("l.mulu %0, %1, %2\n\t"
+ : "=r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("mulu error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfeq.c b/src/tests/tcg/openrisc/test_sfeq.c
new file mode 100644
index 0000000..bd7f875
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfeq.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0x1;
+ b = 0x80;
+ result = 0x2;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.sfeq %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfeq error\n");
+ return -1;
+ }
+
+ a = 0x7f;
+ b = 0x80;
+ result = 0x81;
+ __asm
+ ("2:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.sfeq %0, %1\n\t"
+ "l.bf 2b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfeq error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfeqi.c b/src/tests/tcg/openrisc/test_sfeqi.c
new file mode 100644
index 0000000..5742613
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfeqi.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 1;
+ result = 2;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.sfeqi %0, 0x80\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfeqi error\n");
+ return -1;
+ }
+
+ a = 0x7f;
+ result = 0x81;
+ __asm
+ ("2:\n\t"
+ "l.addi %0, %0, 0x1\n\t"
+ "l.sfeqi %0, 0x80\n\t"
+ "l.bf 2b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfeqi error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfges.c b/src/tests/tcg/openrisc/test_sfges.c
new file mode 100644
index 0000000..23761d7
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfges.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 1;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfges %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfges error\n");
+ return -1;
+ }
+
+ a = 0xff;
+ b = 3;
+ c = 0x1;
+ result = 2;
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %2\n\t"
+ "l.sfges %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sfges error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfgesi.c b/src/tests/tcg/openrisc/test_sfgesi.c
new file mode 100644
index 0000000..54a2d51
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfgesi.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ result = 1;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfgesi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfgesi error\n");
+ return -1;
+ }
+
+ a = 0xff;
+ b = 1;
+ result = 2;
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %1\n\t"
+ "l.sfgesi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgesi error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfgeu.c b/src/tests/tcg/openrisc/test_sfgeu.c
new file mode 100644
index 0000000..2a491d9
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfgeu.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 1;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfgeu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgeu error\n");
+ return -1;
+ }
+
+ a = 0xff;
+ b = 3;
+ c = 1;
+ result = 2;
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %2\n\t"
+ "l.sfgeu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sfgeu error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfgeui.c b/src/tests/tcg/openrisc/test_sfgeui.c
new file mode 100644
index 0000000..40af35c
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfgeui.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ result = 1;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfgeui %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfgeui error\n");
+ return -1;
+ }
+
+ a = 0xff;
+ b = 1;
+ result = 2;
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %1\n\t"
+ "l.sfgeui %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgeui error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfgts.c b/src/tests/tcg/openrisc/test_sfgts.c
new file mode 100644
index 0000000..4481a9c
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfgts.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 1;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfgts %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgts error\n");
+ return -1;
+ }
+
+
+ a = 0xff;
+ b = 3;
+ c = 1;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %2\n\t"
+ "l.sfgts %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sfgts error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfgtsi.c b/src/tests/tcg/openrisc/test_sfgtsi.c
new file mode 100644
index 0000000..7366e12
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfgtsi.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ result = 1;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfgtsi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfgtsi error\n");
+ return -1;
+ }
+
+ a = 0xff;
+ b = 1;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %1\n\t"
+ "l.sfgtsi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgtsi error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfgtu.c b/src/tests/tcg/openrisc/test_sfgtu.c
new file mode 100644
index 0000000..da28689
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfgtu.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+int main(void)
+{
+ int a, b, c;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 1;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfgtu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgtu error\n");
+ return -1;
+ }
+
+ a = 0xff;
+ b = 3;
+ c = 1;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %2\n\t"
+ "l.sfgtu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b), "r"(c)
+ );
+ if (a != result) {
+ printf("sfgtu error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfgtui.c b/src/tests/tcg/openrisc/test_sfgtui.c
new file mode 100644
index 0000000..565d44f
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfgtui.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ result = 1;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfgtui %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfgtui error\n");
+ return -1;
+ }
+
+
+ a = 0xff;
+ b = 1;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.sub %0, %0, %1\n\t"
+ "l.sfgtui %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfgtui error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfles.c b/src/tests/tcg/openrisc/test_sfles.c
new file mode 100644
index 0000000..f573522
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfles.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 4;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sfles %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfles error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sflesi.c b/src/tests/tcg/openrisc/test_sflesi.c
new file mode 100644
index 0000000..16fe605
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sflesi.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 4;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sflesi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sflesi error\n");
+ return -1;
+ }
+
+ a = 0;
+ result = 4;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sflesi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sflesi error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfleu.c b/src/tests/tcg/openrisc/test_sfleu.c
new file mode 100644
index 0000000..be0a3c3
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfleu.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 4;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sfleu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfleu error\n");
+ return -1;
+ }
+
+ a = 0;
+ b = 3;
+ result = 4;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfleu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfleu error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfleui.c b/src/tests/tcg/openrisc/test_sfleui.c
new file mode 100644
index 0000000..38d3c89
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfleui.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 4;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sfleui %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfleui error\n");
+ return -1;
+ }
+
+ a = 0;
+ result = 4;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfleui %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfleui error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sflts.c b/src/tests/tcg/openrisc/test_sflts.c
new file mode 100644
index 0000000..7deeb48
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sflts.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 4;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sflts %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sflts error\n");
+ return -1;
+ }
+
+ a = 0;
+ b = 3;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sflts %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sflts error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfltsi.c b/src/tests/tcg/openrisc/test_sfltsi.c
new file mode 100644
index 0000000..3cb1f02
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfltsi.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 4;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sfltsi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfltsi error\n");
+ return -1;
+ }
+
+ a = 0;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfltsi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfltsi error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfltu.c b/src/tests/tcg/openrisc/test_sfltu.c
new file mode 100644
index 0000000..7ed3b26
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfltu.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 4;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sfltu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfltu error\n");
+ return -1;
+ }
+
+ a = 0;
+ b = 3;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfltu %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfltu error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfltui.c b/src/tests/tcg/openrisc/test_sfltui.c
new file mode 100644
index 0000000..a5cb9f6
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfltui.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 4;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 4\n\t"
+ "l.sfltsi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfltui error\n");
+ return -1;
+ }
+
+ a = 0;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfltsi %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfltui error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfne.c b/src/tests/tcg/openrisc/test_sfne.c
new file mode 100644
index 0000000..b33a35c
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfne.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0;
+ b = 3;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 3\n\t"
+ "l.sfne %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfne error\n");
+ return -1;
+ }
+
+ a = 0;
+ b = 3;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfne %0, %1\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sfne error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sfnei.c b/src/tests/tcg/openrisc/test_sfnei.c
new file mode 100644
index 0000000..d311c9e
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sfnei.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a;
+ int result;
+
+ a = 0;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 3\n\t"
+ "l.sfnei %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfnei error\n");
+ return -1;
+ }
+
+ a = 0;
+ result = 3;
+ __asm
+ ("1:\n\t"
+ "l.addi %0, %0, 1\n\t"
+ "l.sfnei %0, 0x3\n\t"
+ "l.bf 1b\n\t"
+ "l.nop\n\t"
+ : "+r"(a)
+ );
+ if (a != result) {
+ printf("sfnei error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/openrisc/test_sub.c b/src/tests/tcg/openrisc/test_sub.c
new file mode 100644
index 0000000..474ec60
--- /dev/null
+++ b/src/tests/tcg/openrisc/test_sub.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+
+int main(void)
+{
+ int a, b;
+ int result;
+
+ a = 0x100;
+ b = 0x100;
+ result = 0x0;
+ __asm
+ ("l.sub %0, %0, %1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sub error\n");
+ return -1;
+ }
+
+ a = 0xffff;
+ b = 0x1;
+ result = 0xfffe;
+ __asm
+ ("l.sub %0, %0, %1\n\t"
+ : "+r"(a)
+ : "r"(b)
+ );
+ if (a != result) {
+ printf("sub error\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/tests/tcg/pi_10.com b/src/tests/tcg/pi_10.com
new file mode 100644
index 0000000..8993ba1
--- /dev/null
+++ b/src/tests/tcg/pi_10.com
Binary files differ
diff --git a/src/tests/tcg/runcom.c b/src/tests/tcg/runcom.c
new file mode 100644
index 0000000..d60342b
--- /dev/null
+++ b/src/tests/tcg/runcom.c
@@ -0,0 +1,192 @@
+/*
+ * Simple example of use of vm86: launch a basic .com DOS executable
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <signal.h>
+
+#include <linux/unistd.h>
+#include <asm/vm86.h>
+
+extern int vm86 (unsigned long int subfunction,
+ struct vm86plus_struct *info);
+
+#define VIF_MASK 0x00080000
+
+//#define SIGTEST
+
+#define COM_BASE_ADDR 0x10100
+
+static void usage(void)
+{
+ printf("runcom version 0.1 (c) 2003 Fabrice Bellard\n"
+ "usage: runcom file.com\n"
+ "VM86 Run simple .com DOS executables (linux vm86 test mode)\n");
+ exit(1);
+}
+
+static inline void set_bit(uint8_t *a, unsigned int bit)
+{
+ a[bit / 8] |= (1 << (bit % 8));
+}
+
+static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
+{
+ return (uint8_t *)((seg << 4) + (reg & 0xffff));
+}
+
+static inline void pushw(struct vm86_regs *r, int val)
+{
+ r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
+ *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
+}
+
+void dump_regs(struct vm86_regs *r)
+{
+ fprintf(stderr,
+ "EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
+ "ESI=%08lx EDI=%08lx EBP=%08lx ESP=%08lx\n"
+ "EIP=%08lx EFL=%08lx\n"
+ "CS=%04x DS=%04x ES=%04x SS=%04x FS=%04x GS=%04x\n",
+ r->eax, r->ebx, r->ecx, r->edx, r->esi, r->edi, r->ebp, r->esp,
+ r->eip, r->eflags,
+ r->cs, r->ds, r->es, r->ss, r->fs, r->gs);
+}
+
+#ifdef SIGTEST
+void alarm_handler(int sig)
+{
+ fprintf(stderr, "alarm signal=%d\n", sig);
+ alarm(1);
+}
+#endif
+
+int main(int argc, char **argv)
+{
+ uint8_t *vm86_mem;
+ const char *filename;
+ int fd, ret, seg;
+ struct vm86plus_struct ctx;
+ struct vm86_regs *r;
+
+ if (argc != 2)
+ usage();
+ filename = argv[1];
+
+ vm86_mem = mmap((void *)0x00000000, 0x110000,
+ PROT_WRITE | PROT_READ | PROT_EXEC,
+ MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (vm86_mem == MAP_FAILED) {
+ perror("mmap");
+ exit(1);
+ }
+#ifdef SIGTEST
+ {
+ struct sigaction act;
+
+ act.sa_handler = alarm_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGALRM, &act, NULL);
+ alarm(1);
+ }
+#endif
+
+ /* load the MSDOS .com executable */
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror(filename);
+ exit(1);
+ }
+ ret = read(fd, vm86_mem + COM_BASE_ADDR, 65536 - 256);
+ if (ret < 0) {
+ perror("read");
+ exit(1);
+ }
+ close(fd);
+
+ memset(&ctx, 0, sizeof(ctx));
+ /* init basic registers */
+ r = &ctx.regs;
+ r->eip = 0x100;
+ r->esp = 0xfffe;
+ seg = (COM_BASE_ADDR - 0x100) >> 4;
+ r->cs = seg;
+ r->ss = seg;
+ r->ds = seg;
+ r->es = seg;
+ r->fs = seg;
+ r->gs = seg;
+ r->eflags = VIF_MASK;
+
+ /* put return code */
+ set_bit((uint8_t *)&ctx.int_revectored, 0x21);
+ *seg_to_linear(r->cs, 0) = 0xb4; /* mov ah, $0 */
+ *seg_to_linear(r->cs, 1) = 0x00;
+ *seg_to_linear(r->cs, 2) = 0xcd; /* int $0x21 */
+ *seg_to_linear(r->cs, 3) = 0x21;
+ pushw(&ctx.regs, 0x0000);
+
+ /* the value of these registers seem to be assumed by pi_10.com */
+ r->esi = 0x100;
+ r->ecx = 0xff;
+ r->ebp = 0x0900;
+ r->edi = 0xfffe;
+
+ for(;;) {
+ ret = vm86(VM86_ENTER, &ctx);
+ switch(VM86_TYPE(ret)) {
+ case VM86_INTx:
+ {
+ int int_num, ah;
+
+ int_num = VM86_ARG(ret);
+ if (int_num != 0x21)
+ goto unknown_int;
+ ah = (r->eax >> 8) & 0xff;
+ switch(ah) {
+ case 0x00: /* exit */
+ exit(0);
+ case 0x02: /* write char */
+ {
+ uint8_t c = r->edx;
+ write(1, &c, 1);
+ }
+ break;
+ case 0x09: /* write string */
+ {
+ uint8_t c;
+ for(;;) {
+ c = *seg_to_linear(r->ds, r->edx);
+ if (c == '$')
+ break;
+ write(1, &c, 1);
+ }
+ r->eax = (r->eax & ~0xff) | '$';
+ }
+ break;
+ default:
+ unknown_int:
+ fprintf(stderr, "unsupported int 0x%02x\n", int_num);
+ dump_regs(&ctx.regs);
+ // exit(1);
+ }
+ }
+ break;
+ case VM86_SIGNAL:
+ /* a signal came, we just ignore that */
+ break;
+ case VM86_STI:
+ break;
+ default:
+ fprintf(stderr, "unhandled vm86 return code (0x%x)\n", ret);
+ dump_regs(&ctx.regs);
+ exit(1);
+ }
+ }
+}
diff --git a/src/tests/tcg/sha1.c b/src/tests/tcg/sha1.c
new file mode 100644
index 0000000..93b7c8e
--- /dev/null
+++ b/src/tests/tcg/sha1.c
@@ -0,0 +1,240 @@
+
+/* from valgrind tests */
+
+/* ================ sha1.c ================ */
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
+
+#define SHA1HANDSOFF
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+/* ================ sha1.h ================ */
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+*/
+
+typedef struct {
+ uint32_t state[5];
+ uint32_t count[2];
+ unsigned char buffer[64];
+} SHA1_CTX;
+
+void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]);
+void SHA1Init(SHA1_CTX* context);
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len);
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
+/* ================ end of sha1.h ================ */
+#include <endian.h>
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#elif BYTE_ORDER == BIG_ENDIAN
+#define blk0(i) block->l[i]
+#else
+#error "Endianness not defined!"
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
+{
+uint32_t a, b, c, d, e;
+typedef union {
+ unsigned char c[64];
+ uint32_t l[16];
+} CHAR64LONG16;
+#ifdef SHA1HANDSOFF
+CHAR64LONG16 block[1]; /* use array to appear as a pointer */
+ memcpy(block, buffer, 64);
+#else
+ /* The following had better never be used because it causes the
+ * pointer-to-const buffer to be cast into a pointer to non-const.
+ * And the result is written through. I threw a "const" in, hoping
+ * this will cause a diagnostic.
+ */
+CHAR64LONG16* block = (const CHAR64LONG16*)buffer;
+#endif
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+#ifdef SHA1HANDSOFF
+ memset(block, '\0', sizeof(block));
+#endif
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len)
+{
+uint32_t i;
+uint32_t j;
+
+ j = context->count[0];
+ if ((context->count[0] += len << 3) < j)
+ context->count[1]++;
+ context->count[1] += (len>>29);
+ j = (j >> 3) & 63;
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+unsigned i;
+unsigned char finalcount[8];
+unsigned char c;
+
+#if 0 /* untested "improvement" by DHR */
+ /* Convert context->count to a sequence of bytes
+ * in finalcount. Second element first, but
+ * big-endian order within element.
+ * But we do it all backwards.
+ */
+ unsigned char *fcp = &finalcount[8];
+
+ for (i = 0; i < 2; i++)
+ {
+ uint32_t t = context->count[i];
+ int j;
+
+ for (j = 0; j < 4; t >>= 8, j++)
+ *--fcp = (unsigned char) t;
+ }
+#else
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+#endif
+ c = 0200;
+ SHA1Update(context, &c, 1);
+ while ((context->count[0] & 504) != 448) {
+ c = 0000;
+ SHA1Update(context, &c, 1);
+ }
+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 20; i++) {
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ memset(context, '\0', sizeof(*context));
+ memset(&finalcount, '\0', sizeof(finalcount));
+}
+/* ================ end of sha1.c ================ */
+
+#define BUFSIZE 4096
+
+int
+main(int argc, char **argv)
+{
+ SHA1_CTX ctx;
+ unsigned char hash[20], buf[BUFSIZE];
+ int i;
+
+ for(i=0;i<BUFSIZE;i++)
+ buf[i] = i;
+
+ SHA1Init(&ctx);
+ for(i=0;i<1000;i++)
+ SHA1Update(&ctx, buf, BUFSIZE);
+ SHA1Final(hash, &ctx);
+
+ printf("SHA1=");
+ for(i=0;i<20;i++)
+ printf("%02x", hash[i]);
+ printf("\n");
+ return 0;
+}
diff --git a/src/tests/tcg/test-arm-iwmmxt.s b/src/tests/tcg/test-arm-iwmmxt.s
new file mode 100644
index 0000000..d647f94
--- /dev/null
+++ b/src/tests/tcg/test-arm-iwmmxt.s
@@ -0,0 +1,49 @@
+@ Checks whether iwMMXt is functional.
+.code 32
+.globl main
+
+main:
+ldr r0, =data0
+ldr r1, =data1
+ldr r2, =data2
+#ifndef FPA
+wldrd wr0, [r0, #0]
+wldrd wr1, [r0, #8]
+wldrd wr2, [r1, #0]
+wldrd wr3, [r1, #8]
+wsubb wr2, wr2, wr0
+wsubb wr3, wr3, wr1
+wldrd wr0, [r2, #0]
+wldrd wr1, [r2, #8]
+waddb wr0, wr0, wr2
+waddb wr1, wr1, wr3
+wstrd wr0, [r2, #0]
+wstrd wr1, [r2, #8]
+#else
+ldfe f0, [r0, #0]
+ldfe f1, [r0, #8]
+ldfe f2, [r1, #0]
+ldfe f3, [r1, #8]
+adfdp f2, f2, f0
+adfdp f3, f3, f1
+ldfe f0, [r2, #0]
+ldfe f1, [r2, #8]
+adfd f0, f0, f2
+adfd f1, f1, f3
+stfe f0, [r2, #0]
+stfe f1, [r2, #8]
+#endif
+mov r0, #1
+mov r1, r2
+mov r2, #0x11
+swi #0x900004
+mov r0, #0
+swi #0x900001
+
+.data
+data0:
+.string "aaaabbbbccccdddd"
+data1:
+.string "bbbbccccddddeeee"
+data2:
+.string "hvLLWs\x1fsdrs9\x1fNJ-\n"
diff --git a/src/tests/tcg/test-i386-code16.S b/src/tests/tcg/test-i386-code16.S
new file mode 100644
index 0000000..816c24b
--- /dev/null
+++ b/src/tests/tcg/test-i386-code16.S
@@ -0,0 +1,79 @@
+ .code16
+ .globl code16_start
+ .globl code16_end
+
+CS_SEG = 0xf
+
+code16_start:
+
+ .globl code16_func1
+
+ /* basic test */
+code16_func1 = . - code16_start
+ mov $1, %eax
+ data32 lret
+
+/* test push/pop in 16 bit mode */
+ .globl code16_func2
+code16_func2 = . - code16_start
+ xor %eax, %eax
+ mov $0x12345678, %ebx
+ movl %esp, %ecx
+ push %bx
+ subl %esp, %ecx
+ pop %ax
+ data32 lret
+
+/* test various jmp opcodes */
+ .globl code16_func3
+code16_func3 = . - code16_start
+ jmp 1f
+ nop
+1:
+ mov $4, %eax
+ mov $0x12345678, %ebx
+ xor %bx, %bx
+ jz 2f
+ add $2, %ax
+2:
+
+ call myfunc
+
+ lcall $CS_SEG, $(myfunc2 - code16_start)
+
+ ljmp $CS_SEG, $(myjmp1 - code16_start)
+myjmp1_next:
+
+ cs lcall *myfunc2_addr - code16_start
+
+ cs ljmp *myjmp2_addr - code16_start
+myjmp2_next:
+
+ data32 lret
+
+myfunc2_addr:
+ .short myfunc2 - code16_start
+ .short CS_SEG
+
+myjmp2_addr:
+ .short myjmp2 - code16_start
+ .short CS_SEG
+
+myjmp1:
+ add $8, %ax
+ jmp myjmp1_next
+
+myjmp2:
+ add $16, %ax
+ jmp myjmp2_next
+
+myfunc:
+ add $1, %ax
+ ret
+
+myfunc2:
+ add $4, %ax
+ lret
+
+
+code16_end:
diff --git a/src/tests/tcg/test-i386-fprem.c b/src/tests/tcg/test-i386-fprem.c
new file mode 100644
index 0000000..e91fb1a
--- /dev/null
+++ b/src/tests/tcg/test-i386-fprem.c
@@ -0,0 +1,353 @@
+/*
+ * x86 FPREM test - executes the FPREM and FPREM1 instructions with corner case
+ * operands and prints the operands, result and FPU status word.
+ *
+ * Run this on real hardware, then under QEMU, and diff the outputs, to compare
+ * QEMU's implementation to your hardware. The 'run-test-i386-fprem' make
+ * target does this.
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ * Copyright (c) 2012 Catalin Patulea
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "qemu/compiler.h"
+#include "qemu/osdep.h"
+#include <stdio.h>
+#include <inttypes.h>
+
+/*
+ * Inspired by <ieee754.h>'s union ieee854_long_double, but with single
+ * long long mantissa fields and assuming little-endianness for simplicity.
+ */
+union float80u {
+ long double d;
+
+ /* This is the IEEE 854 double-extended-precision format. */
+ struct {
+ unsigned long long mantissa:63;
+ unsigned int one:1;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+ } QEMU_PACKED ieee;
+
+ /* This is for NaNs in the IEEE 854 double-extended-precision format. */
+ struct {
+ unsigned long long mantissa:62;
+ unsigned int quiet_nan:1;
+ unsigned int one:1;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+ } QEMU_PACKED ieee_nan;
+};
+
+#define IEEE854_LONG_DOUBLE_BIAS 0x3fff
+
+static const union float80u q_nan = {
+ .ieee_nan.negative = 0, /* X */
+ .ieee_nan.exponent = 0x7fff,
+ .ieee_nan.one = 1,
+ .ieee_nan.quiet_nan = 1,
+ .ieee_nan.mantissa = 0,
+};
+
+static const union float80u s_nan = {
+ .ieee_nan.negative = 0, /* X */
+ .ieee_nan.exponent = 0x7fff,
+ .ieee_nan.one = 1,
+ .ieee_nan.quiet_nan = 0,
+ .ieee_nan.mantissa = 1, /* nonzero */
+};
+
+static const union float80u pos_inf = {
+ .ieee.negative = 0,
+ .ieee.exponent = 0x7fff,
+ .ieee.one = 1,
+ .ieee.mantissa = 0,
+};
+
+static const union float80u pseudo_pos_inf = { /* "unsupported" */
+ .ieee.negative = 0,
+ .ieee.exponent = 0x7fff,
+ .ieee.one = 0,
+ .ieee.mantissa = 0,
+};
+
+static const union float80u pos_denorm = {
+ .ieee.negative = 0,
+ .ieee.exponent = 0,
+ .ieee.one = 0,
+ .ieee.mantissa = 1,
+};
+
+static const union float80u smallest_positive_norm = {
+ .ieee.negative = 0,
+ .ieee.exponent = 1,
+ .ieee.one = 1,
+ .ieee.mantissa = 0,
+};
+
+static void fninit()
+{
+ asm volatile ("fninit\n");
+}
+
+static long double fprem(long double a, long double b, uint16_t *sw)
+{
+ long double result;
+ asm volatile ("fprem\n"
+ "fnstsw %1\n"
+ : "=t" (result), "=m" (*sw)
+ : "0" (a), "u" (b)
+ : "st(1)");
+ return result;
+}
+
+static long double fprem1(long double a, long double b, uint16_t *sw)
+{
+ long double result;
+ asm volatile ("fprem1\n"
+ "fnstsw %1\n"
+ : "=t" (result), "=m" (*sw)
+ : "0" (a), "u" (b)
+ : "st(1)");
+ return result;
+}
+
+#define FPUS_IE (1 << 0)
+#define FPUS_DE (1 << 1)
+#define FPUS_ZE (1 << 2)
+#define FPUS_OE (1 << 3)
+#define FPUS_UE (1 << 4)
+#define FPUS_PE (1 << 5)
+#define FPUS_SF (1 << 6)
+#define FPUS_SE (1 << 7)
+#define FPUS_C0 (1 << 8)
+#define FPUS_C1 (1 << 9)
+#define FPUS_C2 (1 << 10)
+#define FPUS_TOP 0x3800
+#define FPUS_C3 (1 << 14)
+#define FPUS_B (1 << 15)
+
+#define FPUS_EMASK 0x007f
+
+#define FPUC_EM 0x3f
+
+static void psw(uint16_t sw)
+{
+ printf("SW: C3 TopC2C1C0\n");
+ printf("SW: %c %d %3d %d %d %d %c %c %c %c %c %c %c %c\n",
+ sw & FPUS_B ? 'B' : 'b',
+ !!(sw & FPUS_C3),
+ (sw & FPUS_TOP) >> 11,
+ !!(sw & FPUS_C2),
+ !!(sw & FPUS_C1),
+ !!(sw & FPUS_C0),
+ (sw & FPUS_SE) ? 'S' : 's',
+ (sw & FPUS_SF) ? 'F' : 'f',
+ (sw & FPUS_PE) ? 'P' : 'p',
+ (sw & FPUS_UE) ? 'U' : 'u',
+ (sw & FPUS_OE) ? 'O' : 'o',
+ (sw & FPUS_ZE) ? 'Z' : 'z',
+ (sw & FPUS_DE) ? 'D' : 'd',
+ (sw & FPUS_IE) ? 'I' : 'i');
+}
+
+static void do_fprem(long double a, long double b)
+{
+ const union float80u au = {.d = a};
+ const union float80u bu = {.d = b};
+ union float80u ru;
+ uint16_t sw;
+
+ printf("A: S=%d Exp=%04x Int=%d (QNaN=%d) Sig=%016llx (%.06Le)\n",
+ au.ieee.negative, au.ieee.exponent, au.ieee.one,
+ au.ieee_nan.quiet_nan, (unsigned long long)au.ieee.mantissa,
+ a);
+ printf("B: S=%d Exp=%04x Int=%d (QNaN=%d) Sig=%016llx (%.06Le)\n",
+ bu.ieee.negative, bu.ieee.exponent, bu.ieee.one,
+ bu.ieee_nan.quiet_nan, (unsigned long long)bu.ieee.mantissa,
+ b);
+ fflush(stdout);
+
+ fninit();
+ ru.d = fprem(a, b, &sw);
+ psw(sw);
+
+ printf("R : S=%d Exp=%04x Int=%d (QNaN=%d) Sig=%016llx (%.06Le)\n",
+ ru.ieee.negative, ru.ieee.exponent, ru.ieee.one,
+ ru.ieee_nan.quiet_nan, (unsigned long long)ru.ieee.mantissa,
+ ru.d);
+
+ fninit();
+ ru.d = fprem1(a, b, &sw);
+ psw(sw);
+
+ printf("R1: S=%d Exp=%04x Int=%d (QNaN=%d) Sig=%016llx (%.06Le)\n",
+ ru.ieee.negative, ru.ieee.exponent, ru.ieee.one,
+ ru.ieee_nan.quiet_nan, (unsigned long long)ru.ieee.mantissa,
+ ru.d);
+
+ printf("\n");
+}
+
+static void do_fprem_stack_underflow(void)
+{
+ const long double a = 1.0;
+ union float80u ru;
+ uint16_t sw;
+
+ fninit();
+ asm volatile ("fprem\n"
+ "fnstsw %1\n"
+ : "=t" (ru.d), "=m" (sw)
+ : "0" (a)
+ : "st(1)");
+ psw(sw);
+
+ printf("R: S=%d Exp=%04x Int=%d (QNaN=%d) Sig=%016llx (%.06Le)\n",
+ ru.ieee.negative, ru.ieee.exponent, ru.ieee.one,
+ ru.ieee_nan.quiet_nan, (unsigned long long)ru.ieee.mantissa,
+ ru.d);
+ printf("\n");
+}
+
+static void test_fprem_cases(void)
+{
+ printf("= stack underflow =\n");
+ do_fprem_stack_underflow();
+
+ printf("= invalid operation =\n");
+ do_fprem(s_nan.d, 1.0);
+ do_fprem(1.0, 0.0);
+ do_fprem(pos_inf.d, 1.0);
+ do_fprem(pseudo_pos_inf.d, 1.0);
+
+ printf("= denormal =\n");
+ do_fprem(pos_denorm.d, 1.0);
+ do_fprem(1.0, pos_denorm.d);
+
+ /* printf("= underflow =\n"); */
+ /* TODO: Is there a case where FPREM raises underflow? */
+}
+
+static void test_fprem_pairs(void)
+{
+ unsigned long long count;
+
+ unsigned int negative_index_a = 0;
+ unsigned int negative_index_b = 0;
+ static const unsigned int negative_values[] = {
+ 0,
+ 1,
+ };
+
+ unsigned int exponent_index_a = 0;
+ unsigned int exponent_index_b = 0;
+ static const unsigned int exponent_values[] = {
+ 0,
+ 1,
+ 2,
+ IEEE854_LONG_DOUBLE_BIAS - 1,
+ IEEE854_LONG_DOUBLE_BIAS,
+ IEEE854_LONG_DOUBLE_BIAS + 1,
+ 0x7ffd,
+ 0x7ffe,
+ 0x7fff,
+ };
+
+ unsigned int one_index_a = 0;
+ unsigned int one_index_b = 0;
+ static const unsigned int one_values[] = {
+ 0,
+ 1,
+ };
+
+ unsigned int quiet_nan_index_a = 0;
+ unsigned int quiet_nan_index_b = 0;
+ static const unsigned int quiet_nan_values[] = {
+ 0,
+ 1,
+ };
+
+ unsigned int mantissa_index_a = 0;
+ unsigned int mantissa_index_b = 0;
+ static const unsigned long long mantissa_values[] = {
+ 0,
+ 1,
+ 2,
+ 0x3ffffffffffffffdULL,
+ 0x3ffffffffffffffeULL,
+ 0x3fffffffffffffffULL,
+ };
+
+ for (count = 0; ; ++count) {
+#define INIT_FIELD(var, field) \
+ .ieee_nan.field = field##_values[field##_index_##var]
+ const union float80u a = {
+ INIT_FIELD(a, negative),
+ INIT_FIELD(a, exponent),
+ INIT_FIELD(a, one),
+ INIT_FIELD(a, quiet_nan),
+ INIT_FIELD(a, mantissa),
+ };
+ const union float80u b = {
+ INIT_FIELD(b, negative),
+ INIT_FIELD(b, exponent),
+ INIT_FIELD(b, one),
+ INIT_FIELD(b, quiet_nan),
+ INIT_FIELD(b, mantissa),
+ };
+#undef INIT_FIELD
+
+ do_fprem(a.d, b.d);
+
+ int carry = 1;
+#define CARRY_INTO(var, field) do { \
+ if (carry) { \
+ if (++field##_index_##var == ARRAY_SIZE(field##_values)) { \
+ field##_index_##var = 0; \
+ } else { \
+ carry = 0; \
+ } \
+ } \
+ } while (0)
+ CARRY_INTO(b, mantissa);
+ CARRY_INTO(b, quiet_nan);
+ CARRY_INTO(b, one);
+ CARRY_INTO(b, exponent);
+ CARRY_INTO(b, negative);
+ CARRY_INTO(a, mantissa);
+ CARRY_INTO(a, quiet_nan);
+ CARRY_INTO(a, one);
+ CARRY_INTO(a, exponent);
+ CARRY_INTO(a, negative);
+#undef CARRY_INTO
+
+ if (carry) {
+ break;
+ }
+ }
+
+ fprintf(stderr, "test-i386-fprem: tested %llu cases\n", count);
+}
+
+int main(int argc, char **argv)
+{
+ test_fprem_cases();
+ test_fprem_pairs();
+ return 0;
+}
diff --git a/src/tests/tcg/test-i386-muldiv.h b/src/tests/tcg/test-i386-muldiv.h
new file mode 100644
index 0000000..015f59e
--- /dev/null
+++ b/src/tests/tcg/test-i386-muldiv.h
@@ -0,0 +1,76 @@
+
+void glue(glue(test_, OP), b)(long op0, long op1)
+{
+ long res, s1, s0, flags;
+ s0 = op0;
+ s1 = op1;
+ res = s0;
+ flags = 0;
+ asm ("push %4\n\t"
+ "popf\n\t"
+ stringify(OP)"b %b2\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=a" (res), "=g" (flags)
+ : "q" (s1), "0" (res), "1" (flags));
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
+ stringify(OP) "b", s0, s1, res, flags & CC_MASK);
+}
+
+void glue(glue(test_, OP), w)(long op0h, long op0, long op1)
+{
+ long res, s1, flags, resh;
+ s1 = op1;
+ resh = op0h;
+ res = op0;
+ flags = 0;
+ asm ("push %5\n\t"
+ "popf\n\t"
+ stringify(OP) "w %w3\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=a" (res), "=g" (flags), "=d" (resh)
+ : "q" (s1), "0" (res), "1" (flags), "2" (resh));
+ printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
+ stringify(OP) "w", op0h, op0, s1, resh, res, flags & CC_MASK);
+}
+
+void glue(glue(test_, OP), l)(long op0h, long op0, long op1)
+{
+ long res, s1, flags, resh;
+ s1 = op1;
+ resh = op0h;
+ res = op0;
+ flags = 0;
+ asm ("push %5\n\t"
+ "popf\n\t"
+ stringify(OP) "l %k3\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=a" (res), "=g" (flags), "=d" (resh)
+ : "q" (s1), "0" (res), "1" (flags), "2" (resh));
+ printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
+ stringify(OP) "l", op0h, op0, s1, resh, res, flags & CC_MASK);
+}
+
+#if defined(__x86_64__)
+void glue(glue(test_, OP), q)(long op0h, long op0, long op1)
+{
+ long res, s1, flags, resh;
+ s1 = op1;
+ resh = op0h;
+ res = op0;
+ flags = 0;
+ asm ("push %5\n\t"
+ "popf\n\t"
+ stringify(OP) "q %3\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=a" (res), "=g" (flags), "=d" (resh)
+ : "q" (s1), "0" (res), "1" (flags), "2" (resh));
+ printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
+ stringify(OP) "q", op0h, op0, s1, resh, res, flags & CC_MASK);
+}
+#endif
+
+#undef OP
diff --git a/src/tests/tcg/test-i386-shift.h b/src/tests/tcg/test-i386-shift.h
new file mode 100644
index 0000000..3d8f84b
--- /dev/null
+++ b/src/tests/tcg/test-i386-shift.h
@@ -0,0 +1,185 @@
+
+#define exec_op glue(exec_, OP)
+#define exec_opq glue(glue(exec_, OP), q)
+#define exec_opl glue(glue(exec_, OP), l)
+#define exec_opw glue(glue(exec_, OP), w)
+#define exec_opb glue(glue(exec_, OP), b)
+
+#ifndef OP_SHIFTD
+
+#ifdef OP_NOBYTE
+#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
+ asm ("push %4\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %" rsize "2, %" rsize "0\n\t" \
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=g" (res), "=g" (flags)\
+ : "r" (s1), "0" (res), "1" (flags));
+#else
+#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
+ asm ("push %4\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %%cl, %" rsize "0\n\t" \
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=q" (res), "=g" (flags)\
+ : "c" (s1), "0" (res), "1" (flags));
+#endif
+
+#if defined(__x86_64__)
+void exec_opq(long s2, long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("q", "", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "q", s0, s1, res, iflags, flags & CC_MASK);
+}
+#endif
+
+void exec_opl(long s2, long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("l", "k", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "l", s0, s1, res, iflags, flags & CC_MASK);
+}
+
+void exec_opw(long s2, long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("w", "w", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "w", s0, s1, res, iflags, flags & CC_MASK);
+}
+
+#else
+#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
+ asm ("push %4\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %%cl, %" rsize "5, %" rsize "0\n\t" \
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=g" (res), "=g" (flags)\
+ : "c" (s1), "0" (res), "1" (flags), "r" (s2));
+
+#if defined(__x86_64__)
+void exec_opq(long s2, long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("q", "", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "q", s0, s2, s1, res, iflags, flags & CC_MASK);
+}
+#endif
+
+void exec_opl(long s2, long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("l", "k", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "l", s0, s2, s1, res, iflags, flags & CC_MASK);
+}
+
+void exec_opw(long s2, long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("w", "w", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "w", s0, s2, s1, res, iflags, flags & CC_MASK);
+}
+
+#endif
+
+#ifndef OP_NOBYTE
+void exec_opb(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("b", "b", res, s1, 0, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "b", s0, s1, res, iflags, flags & CC_MASK);
+}
+#endif
+
+void exec_op(long s2, long s0, long s1)
+{
+ s2 = i2l(s2);
+ s0 = i2l(s0);
+#if defined(__x86_64__)
+ exec_opq(s2, s0, s1, 0);
+#endif
+ exec_opl(s2, s0, s1, 0);
+#ifdef OP_SHIFTD
+ exec_opw(s2, s0, s1, 0);
+#else
+ exec_opw(s2, s0, s1, 0);
+#endif
+#ifndef OP_NOBYTE
+ exec_opb(s0, s1, 0);
+#endif
+#ifdef OP_CC
+#if defined(__x86_64__)
+ exec_opq(s2, s0, s1, CC_C);
+#endif
+ exec_opl(s2, s0, s1, CC_C);
+ exec_opw(s2, s0, s1, CC_C);
+ exec_opb(s0, s1, CC_C);
+#endif
+}
+
+void glue(test_, OP)(void)
+{
+ int i, n;
+#if defined(__x86_64__)
+ n = 64;
+#else
+ n = 32;
+#endif
+ for(i = 0; i < n; i++)
+ exec_op(0x21ad3d34, 0x12345678, i);
+ for(i = 0; i < n; i++)
+ exec_op(0x813f3421, 0x82345679, i);
+}
+
+void *glue(_test_, OP) __init_call = glue(test_, OP);
+
+#undef OP
+#undef OP_CC
+#undef OP_SHIFTD
+#undef OP_NOBYTE
+#undef EXECSHIFT
diff --git a/src/tests/tcg/test-i386-ssse3.c b/src/tests/tcg/test-i386-ssse3.c
new file mode 100644
index 0000000..0a42bd0
--- /dev/null
+++ b/src/tests/tcg/test-i386-ssse3.c
@@ -0,0 +1,57 @@
+/* See if various MMX/SSE SSSE3 instructions give expected results */
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+int main(int argc, char *argv[]) {
+ char hello[16];
+ const char ehlo[8] = "EHLO ";
+ uint64_t mask = 0x8080800302020001;
+
+ uint64_t a = 0x0000000000090007;
+ uint64_t b = 0x0000000000000000;
+ uint32_t c;
+ uint16_t d;
+
+ const char e[16] = "LLOaaaaaaaaaaaaa";
+ const char f[16] = "aaaaaaaaaaaaaaHE";
+
+ /* pshufb mm1/xmm1, mm2/xmm2 */
+ asm volatile ("movq (%0), %%mm0" : : "r" (ehlo) : "mm0", "mm1");
+ asm volatile ("movq %0, %%mm1" : : "m" (mask));
+ asm volatile ("pshufb %mm1, %mm0");
+ asm volatile ("movq %%mm0, %0" : "=m" (hello));
+ printf("%s\n", hello);
+
+ /* pshufb mm1/xmm1, m64/m128 */
+ asm volatile ("movq (%0), %%mm0" : : "r" (ehlo) : "mm0");
+ asm volatile ("pshufb %0, %%mm0" : : "m" (mask));
+ asm volatile ("movq %%mm0, %0" : "=m" (hello));
+ printf("%s\n", hello);
+
+ /* psubsw mm1/xmm1, m64/m128 */
+ asm volatile ("movq %0, %%mm0" : : "r" (a) : "mm0");
+ asm volatile ("phsubsw %0, %%mm0" : : "m" (b));
+ asm volatile ("movq %%mm0, %0" : "=m" (a));
+ printf("%i - %i = %i\n", 9, 7, -(int16_t) a);
+
+ /* palignr mm1/xmm1, m64/m128, imm8 */
+ asm volatile ("movdqa (%0), %%xmm0" : : "r" (e) : "xmm0");
+ asm volatile ("palignr $14, (%0), %%xmm0" : : "r" (f));
+ asm volatile ("movdqa %%xmm0, (%0)" : : "r" (hello));
+ printf("%5.5s\n", hello);
+
+#if 1 /* SSE4 */
+ /* popcnt r64, r/m64 */
+ asm volatile ("movq $0x8421000010009c63, %%rax" : : : "rax");
+ asm volatile ("popcnt %%ax, %%dx" : : : "dx");
+ asm volatile ("popcnt %%eax, %%ecx" : : : "ecx");
+ asm volatile ("popcnt %rax, %rax");
+ asm volatile ("movq %%rax, %0" : "=m" (a));
+ asm volatile ("movl %%ecx, %0" : "=m" (c));
+ asm volatile ("movw %%dx, %0" : "=m" (d));
+ printf("%i = %i\n%i = %i = %i\n", 13, (int) a, 9, c, d + 1);
+#endif
+
+ return 0;
+}
diff --git a/src/tests/tcg/test-i386-vm86.S b/src/tests/tcg/test-i386-vm86.S
new file mode 100644
index 0000000..3bb96c9
--- /dev/null
+++ b/src/tests/tcg/test-i386-vm86.S
@@ -0,0 +1,103 @@
+ .code16
+ .globl vm86_code_start
+ .globl vm86_code_end
+
+#define GET_OFFSET(x) ((x) - vm86_code_start + 0x100)
+
+vm86_code_start:
+ movw $GET_OFFSET(hello_world), %dx
+ movb $0x09, %ah
+ int $0x21
+
+ /* prepare int 0x90 vector */
+ xorw %ax, %ax
+ movw %ax, %es
+ es movw $GET_OFFSET(int90_test), 0x90 * 4
+ es movw %cs, 0x90 * 4 + 2
+
+ /* launch int 0x90 */
+
+ int $0x90
+
+ /* test IF support */
+ movw $GET_OFFSET(IF_msg), %dx
+ movb $0x09, %ah
+ int $0x21
+
+ pushf
+ popw %dx
+ movb $0xff, %ah
+ int $0x21
+
+ cli
+ pushf
+ popw %dx
+ movb $0xff, %ah
+ int $0x21
+
+ sti
+ pushfl
+ popl %edx
+ movb $0xff, %ah
+ int $0x21
+
+#if 0
+ movw $GET_OFFSET(IF_msg1), %dx
+ movb $0x09, %ah
+ int $0x21
+
+ pushf
+ movw %sp, %bx
+ andw $~0x200, (%bx)
+ popf
+#else
+ cli
+#endif
+
+ pushf
+ popw %dx
+ movb $0xff, %ah
+ int $0x21
+
+ pushfl
+ movw %sp, %bx
+ orw $0x200, (%bx)
+ popfl
+
+ pushfl
+ popl %edx
+ movb $0xff, %ah
+ int $0x21
+
+ movb $0x00, %ah
+ int $0x21
+
+int90_test:
+ pushf
+ pop %dx
+ movb $0xff, %ah
+ int $0x21
+
+ movw %sp, %bx
+ movw 4(%bx), %dx
+ movb $0xff, %ah
+ int $0x21
+
+ movw $GET_OFFSET(int90_msg), %dx
+ movb $0x09, %ah
+ int $0x21
+ iret
+
+int90_msg:
+ .string "INT90 started\n$"
+
+hello_world:
+ .string "Hello VM86 world\n$"
+
+IF_msg:
+ .string "VM86 IF test\n$"
+
+IF_msg1:
+ .string "If you see a diff here, your Linux kernel is buggy, please update to 2.4.20 kernel\n$"
+
+vm86_code_end:
diff --git a/src/tests/tcg/test-i386.c b/src/tests/tcg/test-i386.c
new file mode 100644
index 0000000..b05572b
--- /dev/null
+++ b/src/tests/tcg/test-i386.c
@@ -0,0 +1,2765 @@
+/*
+ * x86 CPU test
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#define _GNU_SOURCE
+#include "qemu/compiler.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+#include <sys/ucontext.h>
+#include <sys/mman.h>
+
+#if !defined(__x86_64__)
+//#define TEST_VM86
+#define TEST_SEGS
+#endif
+//#define LINUX_VM86_IOPL_FIX
+//#define TEST_P4_FLAGS
+#ifdef __SSE__
+#define TEST_SSE
+#define TEST_CMOV 1
+#define TEST_FCOMI 1
+#else
+#undef TEST_SSE
+#define TEST_CMOV 1
+#define TEST_FCOMI 1
+#endif
+
+#if defined(__x86_64__)
+#define FMT64X "%016lx"
+#define FMTLX "%016lx"
+#define X86_64_ONLY(x) x
+#else
+#define FMT64X "%016" PRIx64
+#define FMTLX "%08lx"
+#define X86_64_ONLY(x)
+#endif
+
+#ifdef TEST_VM86
+#include <asm/vm86.h>
+#endif
+
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+#define stringify(s) tostring(s)
+#define tostring(s) #s
+
+#define CC_C 0x0001
+#define CC_P 0x0004
+#define CC_A 0x0010
+#define CC_Z 0x0040
+#define CC_S 0x0080
+#define CC_O 0x0800
+
+#define __init_call __attribute__ ((unused,__section__ ("initcall")))
+
+#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
+
+#if defined(__x86_64__)
+static inline long i2l(long v)
+{
+ return v | ((v ^ 0xabcd) << 32);
+}
+#else
+static inline long i2l(long v)
+{
+ return v;
+}
+#endif
+
+#define OP add
+#include "test-i386.h"
+
+#define OP sub
+#include "test-i386.h"
+
+#define OP xor
+#include "test-i386.h"
+
+#define OP and
+#include "test-i386.h"
+
+#define OP or
+#include "test-i386.h"
+
+#define OP cmp
+#include "test-i386.h"
+
+#define OP adc
+#define OP_CC
+#include "test-i386.h"
+
+#define OP sbb
+#define OP_CC
+#include "test-i386.h"
+
+#define OP inc
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#define OP dec
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#define OP neg
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#define OP not
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#undef CC_MASK
+#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
+
+#define OP shl
+#include "test-i386-shift.h"
+
+#define OP shr
+#include "test-i386-shift.h"
+
+#define OP sar
+#include "test-i386-shift.h"
+
+#define OP rol
+#include "test-i386-shift.h"
+
+#define OP ror
+#include "test-i386-shift.h"
+
+#define OP rcr
+#define OP_CC
+#include "test-i386-shift.h"
+
+#define OP rcl
+#define OP_CC
+#include "test-i386-shift.h"
+
+#define OP shld
+#define OP_SHIFTD
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP shrd
+#define OP_SHIFTD
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+/* XXX: should be more precise ? */
+#undef CC_MASK
+#define CC_MASK (CC_C)
+
+#define OP bt
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP bts
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP btr
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP btc
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+/* lea test (modrm support) */
+#define TEST_LEAQ(STR)\
+{\
+ asm("lea " STR ", %0"\
+ : "=r" (res)\
+ : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
+ printf("lea %s = " FMTLX "\n", STR, res);\
+}
+
+#define TEST_LEA(STR)\
+{\
+ asm("lea " STR ", %0"\
+ : "=r" (res)\
+ : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
+ printf("lea %s = " FMTLX "\n", STR, res);\
+}
+
+#define TEST_LEA16(STR)\
+{\
+ asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
+ : "=r" (res)\
+ : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
+ printf("lea %s = %08lx\n", STR, res);\
+}
+
+
+void test_lea(void)
+{
+ long eax, ebx, ecx, edx, esi, edi, res;
+ eax = i2l(0x0001);
+ ebx = i2l(0x0002);
+ ecx = i2l(0x0004);
+ edx = i2l(0x0008);
+ esi = i2l(0x0010);
+ edi = i2l(0x0020);
+
+ TEST_LEA("0x4000");
+
+ TEST_LEA("(%%eax)");
+ TEST_LEA("(%%ebx)");
+ TEST_LEA("(%%ecx)");
+ TEST_LEA("(%%edx)");
+ TEST_LEA("(%%esi)");
+ TEST_LEA("(%%edi)");
+
+ TEST_LEA("0x40(%%eax)");
+ TEST_LEA("0x40(%%ebx)");
+ TEST_LEA("0x40(%%ecx)");
+ TEST_LEA("0x40(%%edx)");
+ TEST_LEA("0x40(%%esi)");
+ TEST_LEA("0x40(%%edi)");
+
+ TEST_LEA("0x4000(%%eax)");
+ TEST_LEA("0x4000(%%ebx)");
+ TEST_LEA("0x4000(%%ecx)");
+ TEST_LEA("0x4000(%%edx)");
+ TEST_LEA("0x4000(%%esi)");
+ TEST_LEA("0x4000(%%edi)");
+
+ TEST_LEA("(%%eax, %%ecx)");
+ TEST_LEA("(%%ebx, %%edx)");
+ TEST_LEA("(%%ecx, %%ecx)");
+ TEST_LEA("(%%edx, %%ecx)");
+ TEST_LEA("(%%esi, %%ecx)");
+ TEST_LEA("(%%edi, %%ecx)");
+
+ TEST_LEA("0x40(%%eax, %%ecx)");
+ TEST_LEA("0x4000(%%ebx, %%edx)");
+
+ TEST_LEA("(%%ecx, %%ecx, 2)");
+ TEST_LEA("(%%edx, %%ecx, 4)");
+ TEST_LEA("(%%esi, %%ecx, 8)");
+
+ TEST_LEA("(,%%eax, 2)");
+ TEST_LEA("(,%%ebx, 4)");
+ TEST_LEA("(,%%ecx, 8)");
+
+ TEST_LEA("0x40(,%%eax, 2)");
+ TEST_LEA("0x40(,%%ebx, 4)");
+ TEST_LEA("0x40(,%%ecx, 8)");
+
+
+ TEST_LEA("-10(%%ecx, %%ecx, 2)");
+ TEST_LEA("-10(%%edx, %%ecx, 4)");
+ TEST_LEA("-10(%%esi, %%ecx, 8)");
+
+ TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
+ TEST_LEA("0x4000(%%edx, %%ecx, 4)");
+ TEST_LEA("0x4000(%%esi, %%ecx, 8)");
+
+#if defined(__x86_64__)
+ TEST_LEAQ("0x4000");
+ TEST_LEAQ("0x4000(%%rip)");
+
+ TEST_LEAQ("(%%rax)");
+ TEST_LEAQ("(%%rbx)");
+ TEST_LEAQ("(%%rcx)");
+ TEST_LEAQ("(%%rdx)");
+ TEST_LEAQ("(%%rsi)");
+ TEST_LEAQ("(%%rdi)");
+
+ TEST_LEAQ("0x40(%%rax)");
+ TEST_LEAQ("0x40(%%rbx)");
+ TEST_LEAQ("0x40(%%rcx)");
+ TEST_LEAQ("0x40(%%rdx)");
+ TEST_LEAQ("0x40(%%rsi)");
+ TEST_LEAQ("0x40(%%rdi)");
+
+ TEST_LEAQ("0x4000(%%rax)");
+ TEST_LEAQ("0x4000(%%rbx)");
+ TEST_LEAQ("0x4000(%%rcx)");
+ TEST_LEAQ("0x4000(%%rdx)");
+ TEST_LEAQ("0x4000(%%rsi)");
+ TEST_LEAQ("0x4000(%%rdi)");
+
+ TEST_LEAQ("(%%rax, %%rcx)");
+ TEST_LEAQ("(%%rbx, %%rdx)");
+ TEST_LEAQ("(%%rcx, %%rcx)");
+ TEST_LEAQ("(%%rdx, %%rcx)");
+ TEST_LEAQ("(%%rsi, %%rcx)");
+ TEST_LEAQ("(%%rdi, %%rcx)");
+
+ TEST_LEAQ("0x40(%%rax, %%rcx)");
+ TEST_LEAQ("0x4000(%%rbx, %%rdx)");
+
+ TEST_LEAQ("(%%rcx, %%rcx, 2)");
+ TEST_LEAQ("(%%rdx, %%rcx, 4)");
+ TEST_LEAQ("(%%rsi, %%rcx, 8)");
+
+ TEST_LEAQ("(,%%rax, 2)");
+ TEST_LEAQ("(,%%rbx, 4)");
+ TEST_LEAQ("(,%%rcx, 8)");
+
+ TEST_LEAQ("0x40(,%%rax, 2)");
+ TEST_LEAQ("0x40(,%%rbx, 4)");
+ TEST_LEAQ("0x40(,%%rcx, 8)");
+
+
+ TEST_LEAQ("-10(%%rcx, %%rcx, 2)");
+ TEST_LEAQ("-10(%%rdx, %%rcx, 4)");
+ TEST_LEAQ("-10(%%rsi, %%rcx, 8)");
+
+ TEST_LEAQ("0x4000(%%rcx, %%rcx, 2)");
+ TEST_LEAQ("0x4000(%%rdx, %%rcx, 4)");
+ TEST_LEAQ("0x4000(%%rsi, %%rcx, 8)");
+#else
+ /* limited 16 bit addressing test */
+ TEST_LEA16("0x4000");
+ TEST_LEA16("(%%bx)");
+ TEST_LEA16("(%%si)");
+ TEST_LEA16("(%%di)");
+ TEST_LEA16("0x40(%%bx)");
+ TEST_LEA16("0x40(%%si)");
+ TEST_LEA16("0x40(%%di)");
+ TEST_LEA16("0x4000(%%bx)");
+ TEST_LEA16("0x4000(%%si)");
+ TEST_LEA16("(%%bx,%%si)");
+ TEST_LEA16("(%%bx,%%di)");
+ TEST_LEA16("0x40(%%bx,%%si)");
+ TEST_LEA16("0x40(%%bx,%%di)");
+ TEST_LEA16("0x4000(%%bx,%%si)");
+ TEST_LEA16("0x4000(%%bx,%%di)");
+#endif
+}
+
+#define TEST_JCC(JCC, v1, v2)\
+{\
+ int res;\
+ asm("movl $1, %0\n\t"\
+ "cmpl %2, %1\n\t"\
+ "j" JCC " 1f\n\t"\
+ "movl $0, %0\n\t"\
+ "1:\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2));\
+ printf("%-10s %d\n", "j" JCC, res);\
+\
+ asm("movl $0, %0\n\t"\
+ "cmpl %2, %1\n\t"\
+ "set" JCC " %b0\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2));\
+ printf("%-10s %d\n", "set" JCC, res);\
+ if (TEST_CMOV) {\
+ long val = i2l(1);\
+ long res = i2l(0x12345678);\
+X86_64_ONLY(\
+ asm("cmpl %2, %1\n\t"\
+ "cmov" JCC "q %3, %0\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2), "m" (val), "0" (res));\
+ printf("%-10s R=" FMTLX "\n", "cmov" JCC "q", res);)\
+ asm("cmpl %2, %1\n\t"\
+ "cmov" JCC "l %k3, %k0\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2), "m" (val), "0" (res));\
+ printf("%-10s R=" FMTLX "\n", "cmov" JCC "l", res);\
+ asm("cmpl %2, %1\n\t"\
+ "cmov" JCC "w %w3, %w0\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2), "r" (1), "0" (res));\
+ printf("%-10s R=" FMTLX "\n", "cmov" JCC "w", res);\
+ } \
+}
+
+/* various jump tests */
+void test_jcc(void)
+{
+ TEST_JCC("ne", 1, 1);
+ TEST_JCC("ne", 1, 0);
+
+ TEST_JCC("e", 1, 1);
+ TEST_JCC("e", 1, 0);
+
+ TEST_JCC("l", 1, 1);
+ TEST_JCC("l", 1, 0);
+ TEST_JCC("l", 1, -1);
+
+ TEST_JCC("le", 1, 1);
+ TEST_JCC("le", 1, 0);
+ TEST_JCC("le", 1, -1);
+
+ TEST_JCC("ge", 1, 1);
+ TEST_JCC("ge", 1, 0);
+ TEST_JCC("ge", -1, 1);
+
+ TEST_JCC("g", 1, 1);
+ TEST_JCC("g", 1, 0);
+ TEST_JCC("g", 1, -1);
+
+ TEST_JCC("b", 1, 1);
+ TEST_JCC("b", 1, 0);
+ TEST_JCC("b", 1, -1);
+
+ TEST_JCC("be", 1, 1);
+ TEST_JCC("be", 1, 0);
+ TEST_JCC("be", 1, -1);
+
+ TEST_JCC("ae", 1, 1);
+ TEST_JCC("ae", 1, 0);
+ TEST_JCC("ae", 1, -1);
+
+ TEST_JCC("a", 1, 1);
+ TEST_JCC("a", 1, 0);
+ TEST_JCC("a", 1, -1);
+
+
+ TEST_JCC("p", 1, 1);
+ TEST_JCC("p", 1, 0);
+
+ TEST_JCC("np", 1, 1);
+ TEST_JCC("np", 1, 0);
+
+ TEST_JCC("o", 0x7fffffff, 0);
+ TEST_JCC("o", 0x7fffffff, -1);
+
+ TEST_JCC("no", 0x7fffffff, 0);
+ TEST_JCC("no", 0x7fffffff, -1);
+
+ TEST_JCC("s", 0, 1);
+ TEST_JCC("s", 0, -1);
+ TEST_JCC("s", 0, 0);
+
+ TEST_JCC("ns", 0, 1);
+ TEST_JCC("ns", 0, -1);
+ TEST_JCC("ns", 0, 0);
+}
+
+#define TEST_LOOP(insn) \
+{\
+ for(i = 0; i < sizeof(ecx_vals) / sizeof(long); i++) {\
+ ecx = ecx_vals[i];\
+ for(zf = 0; zf < 2; zf++) {\
+ asm("test %2, %2\n\t"\
+ "movl $1, %0\n\t"\
+ insn " 1f\n\t" \
+ "movl $0, %0\n\t"\
+ "1:\n\t"\
+ : "=a" (res)\
+ : "c" (ecx), "b" (!zf)); \
+ printf("%-10s ECX=" FMTLX " ZF=%ld r=%d\n", insn, ecx, zf, res); \
+ }\
+ }\
+}
+
+void test_loop(void)
+{
+ long ecx, zf;
+ const long ecx_vals[] = {
+ 0,
+ 1,
+ 0x10000,
+ 0x10001,
+#if defined(__x86_64__)
+ 0x100000000L,
+ 0x100000001L,
+#endif
+ };
+ int i, res;
+
+#if !defined(__x86_64__)
+ TEST_LOOP("jcxz");
+ TEST_LOOP("loopw");
+ TEST_LOOP("loopzw");
+ TEST_LOOP("loopnzw");
+#endif
+
+ TEST_LOOP("jecxz");
+ TEST_LOOP("loopl");
+ TEST_LOOP("loopzl");
+ TEST_LOOP("loopnzl");
+}
+
+#undef CC_MASK
+#ifdef TEST_P4_FLAGS
+#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
+#else
+#define CC_MASK (CC_O | CC_C)
+#endif
+
+#define OP mul
+#include "test-i386-muldiv.h"
+
+#define OP imul
+#include "test-i386-muldiv.h"
+
+void test_imulw2(long op0, long op1)
+{
+ long res, s1, s0, flags;
+ s0 = op0;
+ s1 = op1;
+ res = s0;
+ flags = 0;
+ asm volatile ("push %4\n\t"
+ "popf\n\t"
+ "imulw %w2, %w0\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=q" (res), "=g" (flags)
+ : "q" (s1), "0" (res), "1" (flags));
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
+ "imulw", s0, s1, res, flags & CC_MASK);
+}
+
+void test_imull2(long op0, long op1)
+{
+ long res, s1, s0, flags;
+ s0 = op0;
+ s1 = op1;
+ res = s0;
+ flags = 0;
+ asm volatile ("push %4\n\t"
+ "popf\n\t"
+ "imull %k2, %k0\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=q" (res), "=g" (flags)
+ : "q" (s1), "0" (res), "1" (flags));
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
+ "imull", s0, s1, res, flags & CC_MASK);
+}
+
+#if defined(__x86_64__)
+void test_imulq2(long op0, long op1)
+{
+ long res, s1, s0, flags;
+ s0 = op0;
+ s1 = op1;
+ res = s0;
+ flags = 0;
+ asm volatile ("push %4\n\t"
+ "popf\n\t"
+ "imulq %2, %0\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=q" (res), "=g" (flags)
+ : "q" (s1), "0" (res), "1" (flags));
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
+ "imulq", s0, s1, res, flags & CC_MASK);
+}
+#endif
+
+#define TEST_IMUL_IM(size, rsize, op0, op1)\
+{\
+ long res, flags, s1;\
+ flags = 0;\
+ res = 0;\
+ s1 = op1;\
+ asm volatile ("push %3\n\t"\
+ "popf\n\t"\
+ "imul" size " $" #op0 ", %" rsize "2, %" rsize "0\n\t" \
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=r" (res), "=g" (flags)\
+ : "r" (s1), "1" (flags), "0" (res));\
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",\
+ "imul" size " im", (long)op0, (long)op1, res, flags & CC_MASK);\
+}
+
+
+#undef CC_MASK
+#define CC_MASK (0)
+
+#define OP div
+#include "test-i386-muldiv.h"
+
+#define OP idiv
+#include "test-i386-muldiv.h"
+
+void test_mul(void)
+{
+ test_imulb(0x1234561d, 4);
+ test_imulb(3, -4);
+ test_imulb(0x80, 0x80);
+ test_imulb(0x10, 0x10);
+
+ test_imulw(0, 0x1234001d, 45);
+ test_imulw(0, 23, -45);
+ test_imulw(0, 0x8000, 0x8000);
+ test_imulw(0, 0x100, 0x100);
+
+ test_imull(0, 0x1234001d, 45);
+ test_imull(0, 23, -45);
+ test_imull(0, 0x80000000, 0x80000000);
+ test_imull(0, 0x10000, 0x10000);
+
+ test_mulb(0x1234561d, 4);
+ test_mulb(3, -4);
+ test_mulb(0x80, 0x80);
+ test_mulb(0x10, 0x10);
+
+ test_mulw(0, 0x1234001d, 45);
+ test_mulw(0, 23, -45);
+ test_mulw(0, 0x8000, 0x8000);
+ test_mulw(0, 0x100, 0x100);
+
+ test_mull(0, 0x1234001d, 45);
+ test_mull(0, 23, -45);
+ test_mull(0, 0x80000000, 0x80000000);
+ test_mull(0, 0x10000, 0x10000);
+
+ test_imulw2(0x1234001d, 45);
+ test_imulw2(23, -45);
+ test_imulw2(0x8000, 0x8000);
+ test_imulw2(0x100, 0x100);
+
+ test_imull2(0x1234001d, 45);
+ test_imull2(23, -45);
+ test_imull2(0x80000000, 0x80000000);
+ test_imull2(0x10000, 0x10000);
+
+ TEST_IMUL_IM("w", "w", 45, 0x1234);
+ TEST_IMUL_IM("w", "w", -45, 23);
+ TEST_IMUL_IM("w", "w", 0x8000, 0x80000000);
+ TEST_IMUL_IM("w", "w", 0x7fff, 0x1000);
+
+ TEST_IMUL_IM("l", "k", 45, 0x1234);
+ TEST_IMUL_IM("l", "k", -45, 23);
+ TEST_IMUL_IM("l", "k", 0x8000, 0x80000000);
+ TEST_IMUL_IM("l", "k", 0x7fff, 0x1000);
+
+ test_idivb(0x12341678, 0x127e);
+ test_idivb(0x43210123, -5);
+ test_idivb(0x12340004, -1);
+
+ test_idivw(0, 0x12345678, 12347);
+ test_idivw(0, -23223, -45);
+ test_idivw(0, 0x12348000, -1);
+ test_idivw(0x12343, 0x12345678, 0x81238567);
+
+ test_idivl(0, 0x12345678, 12347);
+ test_idivl(0, -233223, -45);
+ test_idivl(0, 0x80000000, -1);
+ test_idivl(0x12343, 0x12345678, 0x81234567);
+
+ test_divb(0x12341678, 0x127e);
+ test_divb(0x43210123, -5);
+ test_divb(0x12340004, -1);
+
+ test_divw(0, 0x12345678, 12347);
+ test_divw(0, -23223, -45);
+ test_divw(0, 0x12348000, -1);
+ test_divw(0x12343, 0x12345678, 0x81238567);
+
+ test_divl(0, 0x12345678, 12347);
+ test_divl(0, -233223, -45);
+ test_divl(0, 0x80000000, -1);
+ test_divl(0x12343, 0x12345678, 0x81234567);
+
+#if defined(__x86_64__)
+ test_imulq(0, 0x1234001d1234001d, 45);
+ test_imulq(0, 23, -45);
+ test_imulq(0, 0x8000000000000000, 0x8000000000000000);
+ test_imulq(0, 0x100000000, 0x100000000);
+
+ test_mulq(0, 0x1234001d1234001d, 45);
+ test_mulq(0, 23, -45);
+ test_mulq(0, 0x8000000000000000, 0x8000000000000000);
+ test_mulq(0, 0x100000000, 0x100000000);
+
+ test_imulq2(0x1234001d1234001d, 45);
+ test_imulq2(23, -45);
+ test_imulq2(0x8000000000000000, 0x8000000000000000);
+ test_imulq2(0x100000000, 0x100000000);
+
+ TEST_IMUL_IM("q", "", 45, 0x12341234);
+ TEST_IMUL_IM("q", "", -45, 23);
+ TEST_IMUL_IM("q", "", 0x8000, 0x8000000000000000);
+ TEST_IMUL_IM("q", "", 0x7fff, 0x10000000);
+
+ test_idivq(0, 0x12345678abcdef, 12347);
+ test_idivq(0, -233223, -45);
+ test_idivq(0, 0x8000000000000000, -1);
+ test_idivq(0x12343, 0x12345678, 0x81234567);
+
+ test_divq(0, 0x12345678abcdef, 12347);
+ test_divq(0, -233223, -45);
+ test_divq(0, 0x8000000000000000, -1);
+ test_divq(0x12343, 0x12345678, 0x81234567);
+#endif
+}
+
+#define TEST_BSX(op, size, op0)\
+{\
+ long res, val, resz;\
+ val = op0;\
+ asm("xor %1, %1\n"\
+ "mov $0x12345678, %0\n"\
+ #op " %" size "2, %" size "0 ; setz %b1" \
+ : "=&r" (res), "=&q" (resz)\
+ : "r" (val));\
+ printf("%-10s A=" FMTLX " R=" FMTLX " %ld\n", #op, val, res, resz);\
+}
+
+void test_bsx(void)
+{
+ TEST_BSX(bsrw, "w", 0);
+ TEST_BSX(bsrw, "w", 0x12340128);
+ TEST_BSX(bsfw, "w", 0);
+ TEST_BSX(bsfw, "w", 0x12340128);
+ TEST_BSX(bsrl, "k", 0);
+ TEST_BSX(bsrl, "k", 0x00340128);
+ TEST_BSX(bsfl, "k", 0);
+ TEST_BSX(bsfl, "k", 0x00340128);
+#if defined(__x86_64__)
+ TEST_BSX(bsrq, "", 0);
+ TEST_BSX(bsrq, "", 0x003401281234);
+ TEST_BSX(bsfq, "", 0);
+ TEST_BSX(bsfq, "", 0x003401281234);
+#endif
+}
+
+/**********************************************/
+
+union float64u {
+ double d;
+ uint64_t l;
+};
+
+union float64u q_nan = { .l = 0xFFF8000000000000LL };
+union float64u s_nan = { .l = 0xFFF0000000000000LL };
+
+void test_fops(double a, double b)
+{
+ printf("a=%f b=%f a+b=%f\n", a, b, a + b);
+ printf("a=%f b=%f a-b=%f\n", a, b, a - b);
+ printf("a=%f b=%f a*b=%f\n", a, b, a * b);
+ printf("a=%f b=%f a/b=%f\n", a, b, a / b);
+ printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
+ printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
+ printf("a=%f sin(a)=%f\n", a, sin(a));
+ printf("a=%f cos(a)=%f\n", a, cos(a));
+ printf("a=%f tan(a)=%f\n", a, tan(a));
+ printf("a=%f log(a)=%f\n", a, log(a));
+ printf("a=%f exp(a)=%f\n", a, exp(a));
+ printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
+ /* just to test some op combining */
+ printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
+ printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
+ printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
+
+}
+
+void fpu_clear_exceptions(void)
+{
+ struct QEMU_PACKED {
+ uint16_t fpuc;
+ uint16_t dummy1;
+ uint16_t fpus;
+ uint16_t dummy2;
+ uint16_t fptag;
+ uint16_t dummy3;
+ uint32_t ignored[4];
+ long double fpregs[8];
+ } float_env32;
+
+ asm volatile ("fnstenv %0\n" : "=m" (float_env32));
+ float_env32.fpus &= ~0x7f;
+ asm volatile ("fldenv %0\n" : : "m" (float_env32));
+}
+
+/* XXX: display exception bits when supported */
+#define FPUS_EMASK 0x0000
+//#define FPUS_EMASK 0x007f
+
+void test_fcmp(double a, double b)
+{
+ long eflags, fpus;
+
+ fpu_clear_exceptions();
+ asm("fcom %2\n"
+ "fstsw %%ax\n"
+ : "=a" (fpus)
+ : "t" (a), "u" (b));
+ printf("fcom(%f %f)=%04lx\n",
+ a, b, fpus & (0x4500 | FPUS_EMASK));
+ fpu_clear_exceptions();
+ asm("fucom %2\n"
+ "fstsw %%ax\n"
+ : "=a" (fpus)
+ : "t" (a), "u" (b));
+ printf("fucom(%f %f)=%04lx\n",
+ a, b, fpus & (0x4500 | FPUS_EMASK));
+ if (TEST_FCOMI) {
+ /* test f(u)comi instruction */
+ fpu_clear_exceptions();
+ asm("fcomi %3, %2\n"
+ "fstsw %%ax\n"
+ "pushf\n"
+ "pop %0\n"
+ : "=r" (eflags), "=a" (fpus)
+ : "t" (a), "u" (b));
+ printf("fcomi(%f %f)=%04lx %02lx\n",
+ a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
+ fpu_clear_exceptions();
+ asm("fucomi %3, %2\n"
+ "fstsw %%ax\n"
+ "pushf\n"
+ "pop %0\n"
+ : "=r" (eflags), "=a" (fpus)
+ : "t" (a), "u" (b));
+ printf("fucomi(%f %f)=%04lx %02lx\n",
+ a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
+ }
+ fpu_clear_exceptions();
+ asm volatile("fxam\n"
+ "fstsw %%ax\n"
+ : "=a" (fpus)
+ : "t" (a));
+ printf("fxam(%f)=%04lx\n", a, fpus & 0x4700);
+ fpu_clear_exceptions();
+}
+
+void test_fcvt(double a)
+{
+ float fa;
+ long double la;
+ int16_t fpuc;
+ int i;
+ int64_t lla;
+ int ia;
+ int16_t wa;
+ double ra;
+
+ fa = a;
+ la = a;
+ printf("(float)%f = %f\n", a, fa);
+ printf("(long double)%f = %Lf\n", a, la);
+ printf("a=" FMT64X "\n", *(uint64_t *)&a);
+ printf("la=" FMT64X " %04x\n", *(uint64_t *)&la,
+ *(unsigned short *)((char *)(&la) + 8));
+
+ /* test all roundings */
+ asm volatile ("fstcw %0" : "=m" (fpuc));
+ for(i=0;i<4;i++) {
+ uint16_t val16;
+ val16 = (fpuc & ~0x0c00) | (i << 10);
+ asm volatile ("fldcw %0" : : "m" (val16));
+ asm volatile ("fist %0" : "=m" (wa) : "t" (a));
+ asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
+ asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
+ asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
+ asm volatile ("fldcw %0" : : "m" (fpuc));
+ printf("(short)a = %d\n", wa);
+ printf("(int)a = %d\n", ia);
+ printf("(int64_t)a = " FMT64X "\n", lla);
+ printf("rint(a) = %f\n", ra);
+ }
+}
+
+#define TEST(N) \
+ asm("fld" #N : "=t" (a)); \
+ printf("fld" #N "= %f\n", a);
+
+void test_fconst(void)
+{
+ double a;
+ TEST(1);
+ TEST(l2t);
+ TEST(l2e);
+ TEST(pi);
+ TEST(lg2);
+ TEST(ln2);
+ TEST(z);
+}
+
+void test_fbcd(double a)
+{
+ unsigned short bcd[5];
+ double b;
+
+ asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
+ asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
+ printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
+ a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
+}
+
+#define TEST_ENV(env, save, restore)\
+{\
+ memset((env), 0xaa, sizeof(*(env)));\
+ for(i=0;i<5;i++)\
+ asm volatile ("fldl %0" : : "m" (dtab[i]));\
+ asm volatile (save " %0\n" : : "m" (*(env)));\
+ asm volatile (restore " %0\n": : "m" (*(env)));\
+ for(i=0;i<5;i++)\
+ asm volatile ("fstpl %0" : "=m" (rtab[i]));\
+ for(i=0;i<5;i++)\
+ printf("res[%d]=%f\n", i, rtab[i]);\
+ printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
+ (env)->fpuc,\
+ (env)->fpus & 0xff00,\
+ (env)->fptag);\
+}
+
+void test_fenv(void)
+{
+ struct __attribute__((__packed__)) {
+ uint16_t fpuc;
+ uint16_t dummy1;
+ uint16_t fpus;
+ uint16_t dummy2;
+ uint16_t fptag;
+ uint16_t dummy3;
+ uint32_t ignored[4];
+ long double fpregs[8];
+ } float_env32;
+ struct __attribute__((__packed__)) {
+ uint16_t fpuc;
+ uint16_t fpus;
+ uint16_t fptag;
+ uint16_t ignored[4];
+ long double fpregs[8];
+ } float_env16;
+ double dtab[8];
+ double rtab[8];
+ int i;
+
+ for(i=0;i<8;i++)
+ dtab[i] = i + 1;
+
+ TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv");
+ TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor");
+ TEST_ENV(&float_env32, "fnstenv", "fldenv");
+ TEST_ENV(&float_env32, "fnsave", "frstor");
+
+ /* test for ffree */
+ for(i=0;i<5;i++)
+ asm volatile ("fldl %0" : : "m" (dtab[i]));
+ asm volatile("ffree %st(2)");
+ asm volatile ("fnstenv %0\n" : : "m" (float_env32));
+ asm volatile ("fninit");
+ printf("fptag=%04x\n", float_env32.fptag);
+}
+
+
+#define TEST_FCMOV(a, b, eflags, CC)\
+{\
+ double res;\
+ asm("push %3\n"\
+ "popf\n"\
+ "fcmov" CC " %2, %0\n"\
+ : "=t" (res)\
+ : "0" (a), "u" (b), "g" (eflags));\
+ printf("fcmov%s eflags=0x%04lx-> %f\n", \
+ CC, (long)eflags, res);\
+}
+
+void test_fcmov(void)
+{
+ double a, b;
+ long eflags, i;
+
+ a = 1.0;
+ b = 2.0;
+ for(i = 0; i < 4; i++) {
+ eflags = 0;
+ if (i & 1)
+ eflags |= CC_C;
+ if (i & 2)
+ eflags |= CC_Z;
+ TEST_FCMOV(a, b, eflags, "b");
+ TEST_FCMOV(a, b, eflags, "e");
+ TEST_FCMOV(a, b, eflags, "be");
+ TEST_FCMOV(a, b, eflags, "nb");
+ TEST_FCMOV(a, b, eflags, "ne");
+ TEST_FCMOV(a, b, eflags, "nbe");
+ }
+ TEST_FCMOV(a, b, 0, "u");
+ TEST_FCMOV(a, b, CC_P, "u");
+ TEST_FCMOV(a, b, 0, "nu");
+ TEST_FCMOV(a, b, CC_P, "nu");
+}
+
+void test_floats(void)
+{
+ test_fops(2, 3);
+ test_fops(1.4, -5);
+ test_fcmp(2, -1);
+ test_fcmp(2, 2);
+ test_fcmp(2, 3);
+ test_fcmp(2, q_nan.d);
+ test_fcmp(q_nan.d, -1);
+ test_fcmp(-1.0/0.0, -1);
+ test_fcmp(1.0/0.0, -1);
+ test_fcvt(0.5);
+ test_fcvt(-0.5);
+ test_fcvt(1.0/7.0);
+ test_fcvt(-1.0/9.0);
+ test_fcvt(32768);
+ test_fcvt(-1e20);
+ test_fcvt(-1.0/0.0);
+ test_fcvt(1.0/0.0);
+ test_fcvt(q_nan.d);
+ test_fconst();
+ test_fbcd(1234567890123456.0);
+ test_fbcd(-123451234567890.0);
+ test_fenv();
+ if (TEST_CMOV) {
+ test_fcmov();
+ }
+}
+
+/**********************************************/
+#if !defined(__x86_64__)
+
+#define TEST_BCD(op, op0, cc_in, cc_mask)\
+{\
+ int res, flags;\
+ res = op0;\
+ flags = cc_in;\
+ asm ("push %3\n\t"\
+ "popf\n\t"\
+ #op "\n\t"\
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=a" (res), "=g" (flags)\
+ : "0" (res), "1" (flags));\
+ printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
+ #op, op0, res, cc_in, flags & cc_mask);\
+}
+
+void test_bcd(void)
+{
+ TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+
+ TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+
+ TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A));
+
+ TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
+ TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
+ TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
+ TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
+ TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A));
+ TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A));
+ TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A));
+ TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A));
+
+ TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
+ TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
+}
+#endif
+
+#define TEST_XCHG(op, size, opconst)\
+{\
+ long op0, op1;\
+ op0 = i2l(0x12345678);\
+ op1 = i2l(0xfbca7654);\
+ asm(#op " %" size "0, %" size "1" \
+ : "=q" (op0), opconst (op1) \
+ : "0" (op0));\
+ printf("%-10s A=" FMTLX " B=" FMTLX "\n",\
+ #op, op0, op1);\
+}
+
+#define TEST_CMPXCHG(op, size, opconst, eax)\
+{\
+ long op0, op1, op2;\
+ op0 = i2l(0x12345678);\
+ op1 = i2l(0xfbca7654);\
+ op2 = i2l(eax);\
+ asm(#op " %" size "0, %" size "1" \
+ : "=q" (op0), opconst (op1) \
+ : "0" (op0), "a" (op2));\
+ printf("%-10s EAX=" FMTLX " A=" FMTLX " C=" FMTLX "\n",\
+ #op, op2, op0, op1);\
+}
+
+void test_xchg(void)
+{
+#if defined(__x86_64__)
+ TEST_XCHG(xchgq, "", "+q");
+#endif
+ TEST_XCHG(xchgl, "k", "+q");
+ TEST_XCHG(xchgw, "w", "+q");
+ TEST_XCHG(xchgb, "b", "+q");
+
+#if defined(__x86_64__)
+ TEST_XCHG(xchgq, "", "=m");
+#endif
+ TEST_XCHG(xchgl, "k", "+m");
+ TEST_XCHG(xchgw, "w", "+m");
+ TEST_XCHG(xchgb, "b", "+m");
+
+#if defined(__x86_64__)
+ TEST_XCHG(xaddq, "", "+q");
+#endif
+ TEST_XCHG(xaddl, "k", "+q");
+ TEST_XCHG(xaddw, "w", "+q");
+ TEST_XCHG(xaddb, "b", "+q");
+
+ {
+ int res;
+ res = 0x12345678;
+ asm("xaddl %1, %0" : "=r" (res) : "0" (res));
+ printf("xaddl same res=%08x\n", res);
+ }
+
+#if defined(__x86_64__)
+ TEST_XCHG(xaddq, "", "+m");
+#endif
+ TEST_XCHG(xaddl, "k", "+m");
+ TEST_XCHG(xaddw, "w", "+m");
+ TEST_XCHG(xaddb, "b", "+m");
+
+#if defined(__x86_64__)
+ TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfbca7654);
+#endif
+ TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfbca7654);
+ TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfbca7654);
+ TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfbca7654);
+
+#if defined(__x86_64__)
+ TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfffefdfc);
+#endif
+ TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfffefdfc);
+ TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfffefdfc);
+ TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfffefdfc);
+
+#if defined(__x86_64__)
+ TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfbca7654);
+#endif
+ TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfbca7654);
+ TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfbca7654);
+ TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfbca7654);
+
+#if defined(__x86_64__)
+ TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfffefdfc);
+#endif
+ TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfffefdfc);
+ TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfffefdfc);
+ TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfffefdfc);
+
+ {
+ uint64_t op0, op1, op2;
+ long eax, edx;
+ long i, eflags;
+
+ for(i = 0; i < 2; i++) {
+ op0 = 0x123456789abcdLL;
+ eax = i2l(op0 & 0xffffffff);
+ edx = i2l(op0 >> 32);
+ if (i == 0)
+ op1 = 0xfbca765423456LL;
+ else
+ op1 = op0;
+ op2 = 0x6532432432434LL;
+ asm("cmpxchg8b %2\n"
+ "pushf\n"
+ "pop %3\n"
+ : "=a" (eax), "=d" (edx), "=m" (op1), "=g" (eflags)
+ : "0" (eax), "1" (edx), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32)));
+ printf("cmpxchg8b: eax=" FMTLX " edx=" FMTLX " op1=" FMT64X " CC=%02lx\n",
+ eax, edx, op1, eflags & CC_Z);
+ }
+ }
+}
+
+#ifdef TEST_SEGS
+/**********************************************/
+/* segmentation tests */
+
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <asm/ldt.h>
+#include <linux/version.h>
+
+static inline int modify_ldt(int func, void * ptr, unsigned long bytecount)
+{
+ return syscall(__NR_modify_ldt, func, ptr, bytecount);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
+#define modify_ldt_ldt_s user_desc
+#endif
+
+#define MK_SEL(n) (((n) << 3) | 7)
+
+uint8_t seg_data1[4096];
+uint8_t seg_data2[4096];
+
+#define TEST_LR(op, size, seg, mask)\
+{\
+ int res, res2;\
+ uint16_t mseg = seg;\
+ res = 0x12345678;\
+ asm (op " %" size "2, %" size "0\n" \
+ "movl $0, %1\n"\
+ "jnz 1f\n"\
+ "movl $1, %1\n"\
+ "1:\n"\
+ : "=r" (res), "=r" (res2) : "m" (mseg), "0" (res));\
+ printf(op ": Z=%d %08x\n", res2, res & ~(mask));\
+}
+
+#define TEST_ARPL(op, size, op1, op2)\
+{\
+ long a, b, c; \
+ a = (op1); \
+ b = (op2); \
+ asm volatile(op " %" size "3, %" size "0\n"\
+ "movl $0,%1\n"\
+ "jnz 1f\n"\
+ "movl $1,%1\n"\
+ "1:\n"\
+ : "=r" (a), "=r" (c) : "0" (a), "r" (b)); \
+ printf(op size " A=" FMTLX " B=" FMTLX " R=" FMTLX " z=%ld\n",\
+ (long)(op1), (long)(op2), a, c);\
+}
+
+/* NOTE: we use Linux modify_ldt syscall */
+void test_segs(void)
+{
+ struct modify_ldt_ldt_s ldt;
+ long long ldt_table[3];
+ int res, res2;
+ char tmp;
+ struct {
+ uint32_t offset;
+ uint16_t seg;
+ } __attribute__((__packed__)) segoff;
+
+ ldt.entry_number = 1;
+ ldt.base_addr = (unsigned long)&seg_data1;
+ ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
+ ldt.seg_32bit = 1;
+ ldt.contents = MODIFY_LDT_CONTENTS_DATA;
+ ldt.read_exec_only = 0;
+ ldt.limit_in_pages = 1;
+ ldt.seg_not_present = 0;
+ ldt.useable = 1;
+ modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+ ldt.entry_number = 2;
+ ldt.base_addr = (unsigned long)&seg_data2;
+ ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12;
+ ldt.seg_32bit = 1;
+ ldt.contents = MODIFY_LDT_CONTENTS_DATA;
+ ldt.read_exec_only = 0;
+ ldt.limit_in_pages = 1;
+ ldt.seg_not_present = 0;
+ ldt.useable = 1;
+ modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+ modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */
+#if 0
+ {
+ int i;
+ for(i=0;i<3;i++)
+ printf("%d: %016Lx\n", i, ldt_table[i]);
+ }
+#endif
+ /* do some tests with fs or gs */
+ asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
+
+ seg_data1[1] = 0xaa;
+ seg_data2[1] = 0x55;
+
+ asm volatile ("fs movzbl 0x1, %0" : "=r" (res));
+ printf("FS[1] = %02x\n", res);
+
+ asm volatile ("pushl %%gs\n"
+ "movl %1, %%gs\n"
+ "gs movzbl 0x1, %0\n"
+ "popl %%gs\n"
+ : "=r" (res)
+ : "r" (MK_SEL(2)));
+ printf("GS[1] = %02x\n", res);
+
+ /* tests with ds/ss (implicit segment case) */
+ tmp = 0xa5;
+ asm volatile ("pushl %%ebp\n\t"
+ "pushl %%ds\n\t"
+ "movl %2, %%ds\n\t"
+ "movl %3, %%ebp\n\t"
+ "movzbl 0x1, %0\n\t"
+ "movzbl (%%ebp), %1\n\t"
+ "popl %%ds\n\t"
+ "popl %%ebp\n\t"
+ : "=r" (res), "=r" (res2)
+ : "r" (MK_SEL(1)), "r" (&tmp));
+ printf("DS[1] = %02x\n", res);
+ printf("SS[tmp] = %02x\n", res2);
+
+ segoff.seg = MK_SEL(2);
+ segoff.offset = 0xabcdef12;
+ asm volatile("lfs %2, %0\n\t"
+ "movl %%fs, %1\n\t"
+ : "=r" (res), "=g" (res2)
+ : "m" (segoff));
+ printf("FS:reg = %04x:%08x\n", res2, res);
+
+ TEST_LR("larw", "w", MK_SEL(2), 0x0100);
+ TEST_LR("larl", "", MK_SEL(2), 0x0100);
+ TEST_LR("lslw", "w", MK_SEL(2), 0);
+ TEST_LR("lsll", "", MK_SEL(2), 0);
+
+ TEST_LR("larw", "w", 0xfff8, 0);
+ TEST_LR("larl", "", 0xfff8, 0);
+ TEST_LR("lslw", "w", 0xfff8, 0);
+ TEST_LR("lsll", "", 0xfff8, 0);
+
+ TEST_ARPL("arpl", "w", 0x12345678 | 3, 0x762123c | 1);
+ TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 3);
+ TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 1);
+}
+
+/* 16 bit code test */
+extern char code16_start, code16_end;
+extern char code16_func1;
+extern char code16_func2;
+extern char code16_func3;
+
+void test_code16(void)
+{
+ struct modify_ldt_ldt_s ldt;
+ int res, res2;
+
+ /* build a code segment */
+ ldt.entry_number = 1;
+ ldt.base_addr = (unsigned long)&code16_start;
+ ldt.limit = &code16_end - &code16_start;
+ ldt.seg_32bit = 0;
+ ldt.contents = MODIFY_LDT_CONTENTS_CODE;
+ ldt.read_exec_only = 0;
+ ldt.limit_in_pages = 0;
+ ldt.seg_not_present = 0;
+ ldt.useable = 1;
+ modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+ /* call the first function */
+ asm volatile ("lcall %1, %2"
+ : "=a" (res)
+ : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc");
+ printf("func1() = 0x%08x\n", res);
+ asm volatile ("lcall %2, %3"
+ : "=a" (res), "=c" (res2)
+ : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc");
+ printf("func2() = 0x%08x spdec=%d\n", res, res2);
+ asm volatile ("lcall %1, %2"
+ : "=a" (res)
+ : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc");
+ printf("func3() = 0x%08x\n", res);
+}
+#endif
+
+#if defined(__x86_64__)
+asm(".globl func_lret\n"
+ "func_lret:\n"
+ "movl $0x87654641, %eax\n"
+ "lretq\n");
+#else
+asm(".globl func_lret\n"
+ "func_lret:\n"
+ "movl $0x87654321, %eax\n"
+ "lret\n"
+
+ ".globl func_iret\n"
+ "func_iret:\n"
+ "movl $0xabcd4321, %eax\n"
+ "iret\n");
+#endif
+
+extern char func_lret;
+extern char func_iret;
+
+void test_misc(void)
+{
+ char table[256];
+ long res, i;
+
+ for(i=0;i<256;i++) table[i] = 256 - i;
+ res = 0x12345678;
+ asm ("xlat" : "=a" (res) : "b" (table), "0" (res));
+ printf("xlat: EAX=" FMTLX "\n", res);
+
+#if defined(__x86_64__)
+#if 0
+ {
+ /* XXX: see if Intel Core2 and AMD64 behavior really
+ differ. Here we implemented the Intel way which is not
+ compatible yet with QEMU. */
+ static struct QEMU_PACKED {
+ uint64_t offset;
+ uint16_t seg;
+ } desc;
+ long cs_sel;
+
+ asm volatile ("mov %%cs, %0" : "=r" (cs_sel));
+
+ asm volatile ("push %1\n"
+ "call func_lret\n"
+ : "=a" (res)
+ : "r" (cs_sel) : "memory", "cc");
+ printf("func_lret=" FMTLX "\n", res);
+
+ desc.offset = (long)&func_lret;
+ desc.seg = cs_sel;
+
+ asm volatile ("xor %%rax, %%rax\n"
+ "rex64 lcall *(%%rcx)\n"
+ : "=a" (res)
+ : "c" (&desc)
+ : "memory", "cc");
+ printf("func_lret2=" FMTLX "\n", res);
+
+ asm volatile ("push %2\n"
+ "mov $ 1f, %%rax\n"
+ "push %%rax\n"
+ "rex64 ljmp *(%%rcx)\n"
+ "1:\n"
+ : "=a" (res)
+ : "c" (&desc), "b" (cs_sel)
+ : "memory", "cc");
+ printf("func_lret3=" FMTLX "\n", res);
+ }
+#endif
+#else
+ asm volatile ("push %%cs ; call %1"
+ : "=a" (res)
+ : "m" (func_lret): "memory", "cc");
+ printf("func_lret=" FMTLX "\n", res);
+
+ asm volatile ("pushf ; push %%cs ; call %1"
+ : "=a" (res)
+ : "m" (func_iret): "memory", "cc");
+ printf("func_iret=" FMTLX "\n", res);
+#endif
+
+#if defined(__x86_64__)
+ /* specific popl test */
+ asm volatile ("push $12345432 ; push $0x9abcdef ; pop (%%rsp) ; pop %0"
+ : "=g" (res));
+ printf("popl esp=" FMTLX "\n", res);
+#else
+ /* specific popl test */
+ asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0"
+ : "=g" (res));
+ printf("popl esp=" FMTLX "\n", res);
+
+ /* specific popw test */
+ asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0"
+ : "=g" (res));
+ printf("popw esp=" FMTLX "\n", res);
+#endif
+}
+
+uint8_t str_buffer[4096];
+
+#define TEST_STRING1(OP, size, DF, REP)\
+{\
+ long esi, edi, eax, ecx, eflags;\
+\
+ esi = (long)(str_buffer + sizeof(str_buffer) / 2);\
+ edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\
+ eax = i2l(0x12345678);\
+ ecx = 17;\
+\
+ asm volatile ("push $0\n\t"\
+ "popf\n\t"\
+ DF "\n\t"\
+ REP #OP size "\n\t"\
+ "cld\n\t"\
+ "pushf\n\t"\
+ "pop %4\n\t"\
+ : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\
+ : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\
+ printf("%-10s ESI=" FMTLX " EDI=" FMTLX " EAX=" FMTLX " ECX=" FMTLX " EFL=%04x\n",\
+ REP #OP size, esi, edi, eax, ecx,\
+ (int)(eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)));\
+}
+
+#define TEST_STRING(OP, REP)\
+ TEST_STRING1(OP, "b", "", REP);\
+ TEST_STRING1(OP, "w", "", REP);\
+ TEST_STRING1(OP, "l", "", REP);\
+ X86_64_ONLY(TEST_STRING1(OP, "q", "", REP));\
+ TEST_STRING1(OP, "b", "std", REP);\
+ TEST_STRING1(OP, "w", "std", REP);\
+ TEST_STRING1(OP, "l", "std", REP);\
+ X86_64_ONLY(TEST_STRING1(OP, "q", "std", REP))
+
+void test_string(void)
+{
+ int i;
+ for(i = 0;i < sizeof(str_buffer); i++)
+ str_buffer[i] = i + 0x56;
+ TEST_STRING(stos, "");
+ TEST_STRING(stos, "rep ");
+ TEST_STRING(lods, ""); /* to verify stos */
+ TEST_STRING(lods, "rep ");
+ TEST_STRING(movs, "");
+ TEST_STRING(movs, "rep ");
+ TEST_STRING(lods, ""); /* to verify stos */
+
+ /* XXX: better tests */
+ TEST_STRING(scas, "");
+ TEST_STRING(scas, "repz ");
+ TEST_STRING(scas, "repnz ");
+ TEST_STRING(cmps, "");
+ TEST_STRING(cmps, "repz ");
+ TEST_STRING(cmps, "repnz ");
+}
+
+#ifdef TEST_VM86
+/* VM86 test */
+
+static inline void set_bit(uint8_t *a, unsigned int bit)
+{
+ a[bit / 8] |= (1 << (bit % 8));
+}
+
+static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
+{
+ return (uint8_t *)((seg << 4) + (reg & 0xffff));
+}
+
+static inline void pushw(struct vm86_regs *r, int val)
+{
+ r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
+ *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
+}
+
+static inline int vm86(int func, struct vm86plus_struct *v86)
+{
+ return syscall(__NR_vm86, func, v86);
+}
+
+extern char vm86_code_start;
+extern char vm86_code_end;
+
+#define VM86_CODE_CS 0x100
+#define VM86_CODE_IP 0x100
+
+void test_vm86(void)
+{
+ struct vm86plus_struct ctx;
+ struct vm86_regs *r;
+ uint8_t *vm86_mem;
+ int seg, ret;
+
+ vm86_mem = mmap((void *)0x00000000, 0x110000,
+ PROT_WRITE | PROT_READ | PROT_EXEC,
+ MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (vm86_mem == MAP_FAILED) {
+ printf("ERROR: could not map vm86 memory");
+ return;
+ }
+ memset(&ctx, 0, sizeof(ctx));
+
+ /* init basic registers */
+ r = &ctx.regs;
+ r->eip = VM86_CODE_IP;
+ r->esp = 0xfffe;
+ seg = VM86_CODE_CS;
+ r->cs = seg;
+ r->ss = seg;
+ r->ds = seg;
+ r->es = seg;
+ r->fs = seg;
+ r->gs = seg;
+ r->eflags = VIF_MASK;
+
+ /* move code to proper address. We use the same layout as a .com
+ dos program. */
+ memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP,
+ &vm86_code_start, &vm86_code_end - &vm86_code_start);
+
+ /* mark int 0x21 as being emulated */
+ set_bit((uint8_t *)&ctx.int_revectored, 0x21);
+
+ for(;;) {
+ ret = vm86(VM86_ENTER, &ctx);
+ switch(VM86_TYPE(ret)) {
+ case VM86_INTx:
+ {
+ int int_num, ah, v;
+
+ int_num = VM86_ARG(ret);
+ if (int_num != 0x21)
+ goto unknown_int;
+ ah = (r->eax >> 8) & 0xff;
+ switch(ah) {
+ case 0x00: /* exit */
+ goto the_end;
+ case 0x02: /* write char */
+ {
+ uint8_t c = r->edx;
+ putchar(c);
+ }
+ break;
+ case 0x09: /* write string */
+ {
+ uint8_t c, *ptr;
+ ptr = seg_to_linear(r->ds, r->edx);
+ for(;;) {
+ c = *ptr++;
+ if (c == '$')
+ break;
+ putchar(c);
+ }
+ r->eax = (r->eax & ~0xff) | '$';
+ }
+ break;
+ case 0xff: /* extension: write eflags number in edx */
+ v = (int)r->edx;
+#ifndef LINUX_VM86_IOPL_FIX
+ v &= ~0x3000;
+#endif
+ printf("%08x\n", v);
+ break;
+ default:
+ unknown_int:
+ printf("unsupported int 0x%02x\n", int_num);
+ goto the_end;
+ }
+ }
+ break;
+ case VM86_SIGNAL:
+ /* a signal came, we just ignore that */
+ break;
+ case VM86_STI:
+ break;
+ default:
+ printf("ERROR: unhandled vm86 return code (0x%x)\n", ret);
+ goto the_end;
+ }
+ }
+ the_end:
+ printf("VM86 end\n");
+ munmap(vm86_mem, 0x110000);
+}
+#endif
+
+/* exception tests */
+#if defined(__i386__) && !defined(REG_EAX)
+#define REG_EAX EAX
+#define REG_EBX EBX
+#define REG_ECX ECX
+#define REG_EDX EDX
+#define REG_ESI ESI
+#define REG_EDI EDI
+#define REG_EBP EBP
+#define REG_ESP ESP
+#define REG_EIP EIP
+#define REG_EFL EFL
+#define REG_TRAPNO TRAPNO
+#define REG_ERR ERR
+#endif
+
+#if defined(__x86_64__)
+#define REG_EIP REG_RIP
+#endif
+
+jmp_buf jmp_env;
+int v1;
+int tab[2];
+
+void sig_handler(int sig, siginfo_t *info, void *puc)
+{
+ struct ucontext *uc = puc;
+
+ printf("si_signo=%d si_errno=%d si_code=%d",
+ info->si_signo, info->si_errno, info->si_code);
+ printf(" si_addr=0x%08lx",
+ (unsigned long)info->si_addr);
+ printf("\n");
+
+ printf("trapno=" FMTLX " err=" FMTLX,
+ (long)uc->uc_mcontext.gregs[REG_TRAPNO],
+ (long)uc->uc_mcontext.gregs[REG_ERR]);
+ printf(" EIP=" FMTLX, (long)uc->uc_mcontext.gregs[REG_EIP]);
+ printf("\n");
+ longjmp(jmp_env, 1);
+}
+
+void test_exceptions(void)
+{
+ struct sigaction act;
+ volatile int val;
+
+ act.sa_sigaction = sig_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO | SA_NODEFER;
+ sigaction(SIGFPE, &act, NULL);
+ sigaction(SIGILL, &act, NULL);
+ sigaction(SIGSEGV, &act, NULL);
+ sigaction(SIGBUS, &act, NULL);
+ sigaction(SIGTRAP, &act, NULL);
+
+ /* test division by zero reporting */
+ printf("DIVZ exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* now divide by zero */
+ v1 = 0;
+ v1 = 2 / v1;
+ }
+
+#if !defined(__x86_64__)
+ printf("BOUND exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* bound exception */
+ tab[0] = 1;
+ tab[1] = 10;
+ asm volatile ("bound %0, %1" : : "r" (11), "m" (tab[0]));
+ }
+#endif
+
+#ifdef TEST_SEGS
+ printf("segment exceptions:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* load an invalid segment */
+ asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1));
+ }
+ if (setjmp(jmp_env) == 0) {
+ /* null data segment is valid */
+ asm volatile ("movl %0, %%fs" : : "r" (3));
+ /* null stack segment */
+ asm volatile ("movl %0, %%ss" : : "r" (3));
+ }
+
+ {
+ struct modify_ldt_ldt_s ldt;
+ ldt.entry_number = 1;
+ ldt.base_addr = (unsigned long)&seg_data1;
+ ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
+ ldt.seg_32bit = 1;
+ ldt.contents = MODIFY_LDT_CONTENTS_DATA;
+ ldt.read_exec_only = 0;
+ ldt.limit_in_pages = 1;
+ ldt.seg_not_present = 1;
+ ldt.useable = 1;
+ modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+ if (setjmp(jmp_env) == 0) {
+ /* segment not present */
+ asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
+ }
+ }
+#endif
+
+ /* test SEGV reporting */
+ printf("PF exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ val = 1;
+ /* we add a nop to test a weird PC retrieval case */
+ asm volatile ("nop");
+ /* now store in an invalid address */
+ *(char *)0x1234 = 1;
+ }
+
+ /* test SEGV reporting */
+ printf("PF exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ val = 1;
+ /* read from an invalid address */
+ v1 = *(char *)0x1234;
+ }
+
+ /* test illegal instruction reporting */
+ printf("UD2 exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* now execute an invalid instruction */
+ asm volatile("ud2");
+ }
+ printf("lock nop exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* now execute an invalid instruction */
+ asm volatile(".byte 0xf0, 0x90");
+ }
+
+ printf("INT exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int $0xfd");
+ }
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int $0x01");
+ }
+ if (setjmp(jmp_env) == 0) {
+ asm volatile (".byte 0xcd, 0x03");
+ }
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int $0x04");
+ }
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int $0x05");
+ }
+
+ printf("INT3 exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int3");
+ }
+
+ printf("CLI exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("cli");
+ }
+
+ printf("STI exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("cli");
+ }
+
+#if !defined(__x86_64__)
+ printf("INTO exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* overflow exception */
+ asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
+ }
+#endif
+
+ printf("OUTB exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
+ }
+
+ printf("INB exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
+ }
+
+ printf("REP OUTSB exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
+ }
+
+ printf("REP INSB exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
+ }
+
+ printf("HLT exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("hlt");
+ }
+
+ printf("single step exception:\n");
+ val = 0;
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("pushf\n"
+ "orl $0x00100, (%%esp)\n"
+ "popf\n"
+ "movl $0xabcd, %0\n"
+ "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
+ }
+ printf("val=0x%x\n", val);
+}
+
+#if !defined(__x86_64__)
+/* specific precise single step test */
+void sig_trap_handler(int sig, siginfo_t *info, void *puc)
+{
+ struct ucontext *uc = puc;
+ printf("EIP=" FMTLX "\n", (long)uc->uc_mcontext.gregs[REG_EIP]);
+}
+
+const uint8_t sstep_buf1[4] = { 1, 2, 3, 4};
+uint8_t sstep_buf2[4];
+
+void test_single_step(void)
+{
+ struct sigaction act;
+ volatile int val;
+ int i;
+
+ val = 0;
+ act.sa_sigaction = sig_trap_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+ sigaction(SIGTRAP, &act, NULL);
+ asm volatile ("pushf\n"
+ "orl $0x00100, (%%esp)\n"
+ "popf\n"
+ "movl $0xabcd, %0\n"
+
+ /* jmp test */
+ "movl $3, %%ecx\n"
+ "1:\n"
+ "addl $1, %0\n"
+ "decl %%ecx\n"
+ "jnz 1b\n"
+
+ /* movsb: the single step should stop at each movsb iteration */
+ "movl $sstep_buf1, %%esi\n"
+ "movl $sstep_buf2, %%edi\n"
+ "movl $0, %%ecx\n"
+ "rep movsb\n"
+ "movl $3, %%ecx\n"
+ "rep movsb\n"
+ "movl $1, %%ecx\n"
+ "rep movsb\n"
+
+ /* cmpsb: the single step should stop at each cmpsb iteration */
+ "movl $sstep_buf1, %%esi\n"
+ "movl $sstep_buf2, %%edi\n"
+ "movl $0, %%ecx\n"
+ "rep cmpsb\n"
+ "movl $4, %%ecx\n"
+ "rep cmpsb\n"
+
+ /* getpid() syscall: single step should skip one
+ instruction */
+ "movl $20, %%eax\n"
+ "int $0x80\n"
+ "movl $0, %%eax\n"
+
+ /* when modifying SS, trace is not done on the next
+ instruction */
+ "movl %%ss, %%ecx\n"
+ "movl %%ecx, %%ss\n"
+ "addl $1, %0\n"
+ "movl $1, %%eax\n"
+ "movl %%ecx, %%ss\n"
+ "jmp 1f\n"
+ "addl $1, %0\n"
+ "1:\n"
+ "movl $1, %%eax\n"
+ "pushl %%ecx\n"
+ "popl %%ss\n"
+ "addl $1, %0\n"
+ "movl $1, %%eax\n"
+
+ "pushf\n"
+ "andl $~0x00100, (%%esp)\n"
+ "popf\n"
+ : "=m" (val)
+ :
+ : "cc", "memory", "eax", "ecx", "esi", "edi");
+ printf("val=%d\n", val);
+ for(i = 0; i < 4; i++)
+ printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]);
+}
+
+/* self modifying code test */
+uint8_t code[] = {
+ 0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
+ 0xc3, /* ret */
+};
+
+asm(".section \".data\"\n"
+ "smc_code2:\n"
+ "movl 4(%esp), %eax\n"
+ "movl %eax, smc_patch_addr2 + 1\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "smc_patch_addr2:\n"
+ "movl $1, %eax\n"
+ "ret\n"
+ ".previous\n"
+ );
+
+typedef int FuncType(void);
+extern int smc_code2(int);
+void test_self_modifying_code(void)
+{
+ int i;
+ printf("self modifying code:\n");
+ printf("func1 = 0x%x\n", ((FuncType *)code)());
+ for(i = 2; i <= 4; i++) {
+ code[1] = i;
+ printf("func%d = 0x%x\n", i, ((FuncType *)code)());
+ }
+
+ /* more difficult test : the modified code is just after the
+ modifying instruction. It is forbidden in Intel specs, but it
+ is used by old DOS programs */
+ for(i = 2; i <= 4; i++) {
+ printf("smc_code2(%d) = %d\n", i, smc_code2(i));
+ }
+}
+#endif
+
+long enter_stack[4096];
+
+#if defined(__x86_64__)
+#define RSP "%%rsp"
+#define RBP "%%rbp"
+#else
+#define RSP "%%esp"
+#define RBP "%%ebp"
+#endif
+
+#if !defined(__x86_64__)
+/* causes an infinite loop, disable it for now. */
+#define TEST_ENTER(size, stack_type, level)
+#else
+#define TEST_ENTER(size, stack_type, level)\
+{\
+ long esp_save, esp_val, ebp_val, ebp_save, i;\
+ stack_type *ptr, *stack_end, *stack_ptr;\
+ memset(enter_stack, 0, sizeof(enter_stack));\
+ stack_end = stack_ptr = (stack_type *)(enter_stack + 4096);\
+ ebp_val = (long)stack_ptr;\
+ for(i=1;i<=32;i++)\
+ *--stack_ptr = i;\
+ esp_val = (long)stack_ptr;\
+ asm("mov " RSP ", %[esp_save]\n"\
+ "mov " RBP ", %[ebp_save]\n"\
+ "mov %[esp_val], " RSP "\n"\
+ "mov %[ebp_val], " RBP "\n"\
+ "enter" size " $8, $" #level "\n"\
+ "mov " RSP ", %[esp_val]\n"\
+ "mov " RBP ", %[ebp_val]\n"\
+ "mov %[esp_save], " RSP "\n"\
+ "mov %[ebp_save], " RBP "\n"\
+ : [esp_save] "=r" (esp_save),\
+ [ebp_save] "=r" (ebp_save),\
+ [esp_val] "=r" (esp_val),\
+ [ebp_val] "=r" (ebp_val)\
+ : "[esp_val]" (esp_val),\
+ "[ebp_val]" (ebp_val));\
+ printf("level=%d:\n", level);\
+ printf("esp_val=" FMTLX "\n", esp_val - (long)stack_end);\
+ printf("ebp_val=" FMTLX "\n", ebp_val - (long)stack_end);\
+ for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\
+ printf(FMTLX "\n", (long)ptr[0]);\
+}
+#endif
+
+static void test_enter(void)
+{
+#if defined(__x86_64__)
+ TEST_ENTER("q", uint64_t, 0);
+ TEST_ENTER("q", uint64_t, 1);
+ TEST_ENTER("q", uint64_t, 2);
+ TEST_ENTER("q", uint64_t, 31);
+#else
+ TEST_ENTER("l", uint32_t, 0);
+ TEST_ENTER("l", uint32_t, 1);
+ TEST_ENTER("l", uint32_t, 2);
+ TEST_ENTER("l", uint32_t, 31);
+#endif
+
+ TEST_ENTER("w", uint16_t, 0);
+ TEST_ENTER("w", uint16_t, 1);
+ TEST_ENTER("w", uint16_t, 2);
+ TEST_ENTER("w", uint16_t, 31);
+}
+
+#ifdef TEST_SSE
+
+typedef int __m64 __attribute__ ((__mode__ (__V2SI__)));
+typedef float __m128 __attribute__ ((__mode__(__V4SF__)));
+
+typedef union {
+ double d[2];
+ float s[4];
+ uint32_t l[4];
+ uint64_t q[2];
+ __m128 dq;
+} XMMReg;
+
+static uint64_t __attribute__((aligned(16))) test_values[4][2] = {
+ { 0x456723c698694873, 0xdc515cff944a58ec },
+ { 0x1f297ccd58bad7ab, 0x41f21efba9e3e146 },
+ { 0x007c62c2085427f8, 0x231be9e8cde7438d },
+ { 0x0f76255a085427f8, 0xc233e9e8c4c9439a },
+};
+
+#define SSE_OP(op)\
+{\
+ asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ b.q[1], b.q[0],\
+ r.q[1], r.q[0]);\
+}
+
+#define SSE_OP2(op)\
+{\
+ int i;\
+ for(i=0;i<2;i++) {\
+ a.q[0] = test_values[2*i][0];\
+ a.q[1] = test_values[2*i][1];\
+ b.q[0] = test_values[2*i+1][0];\
+ b.q[1] = test_values[2*i+1][1];\
+ SSE_OP(op);\
+ }\
+}
+
+#define MMX_OP2(op)\
+{\
+ int i;\
+ for(i=0;i<2;i++) {\
+ a.q[0] = test_values[2*i][0];\
+ b.q[0] = test_values[2*i+1][0];\
+ asm volatile (#op " %2, %0" : "=y" (r.q[0]) : "0" (a.q[0]), "y" (b.q[0]));\
+ printf("%-9s: a=" FMT64X " b=" FMT64X " r=" FMT64X "\n",\
+ #op,\
+ a.q[0],\
+ b.q[0],\
+ r.q[0]);\
+ }\
+ SSE_OP2(op);\
+}
+
+#define SHUF_OP(op, ib)\
+{\
+ a.q[0] = test_values[0][0];\
+ a.q[1] = test_values[0][1];\
+ b.q[0] = test_values[1][0];\
+ b.q[1] = test_values[1][1];\
+ asm volatile (#op " $" #ib ", %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ b.q[1], b.q[0],\
+ ib,\
+ r.q[1], r.q[0]);\
+}
+
+#define PSHUF_OP(op, ib)\
+{\
+ int i;\
+ for(i=0;i<2;i++) {\
+ a.q[0] = test_values[2*i][0];\
+ a.q[1] = test_values[2*i][1];\
+ asm volatile (#op " $" #ib ", %1, %0" : "=x" (r.dq) : "x" (a.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ ib,\
+ r.q[1], r.q[0]);\
+ }\
+}
+
+#define SHIFT_IM(op, ib)\
+{\
+ int i;\
+ for(i=0;i<2;i++) {\
+ a.q[0] = test_values[2*i][0];\
+ a.q[1] = test_values[2*i][1];\
+ asm volatile (#op " $" #ib ", %0" : "=x" (r.dq) : "0" (a.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ ib,\
+ r.q[1], r.q[0]);\
+ }\
+}
+
+#define SHIFT_OP(op, ib)\
+{\
+ int i;\
+ SHIFT_IM(op, ib);\
+ for(i=0;i<2;i++) {\
+ a.q[0] = test_values[2*i][0];\
+ a.q[1] = test_values[2*i][1];\
+ b.q[0] = ib;\
+ b.q[1] = 0;\
+ asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ b.q[1], b.q[0],\
+ r.q[1], r.q[0]);\
+ }\
+}
+
+#define MOVMSK(op)\
+{\
+ int i, reg;\
+ for(i=0;i<2;i++) {\
+ a.q[0] = test_values[2*i][0];\
+ a.q[1] = test_values[2*i][1];\
+ asm volatile (#op " %1, %0" : "=r" (reg) : "x" (a.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ reg);\
+ }\
+}
+
+#define SSE_OPS(a) \
+SSE_OP(a ## ps);\
+SSE_OP(a ## ss);
+
+#define SSE_OPD(a) \
+SSE_OP(a ## pd);\
+SSE_OP(a ## sd);
+
+#define SSE_COMI(op, field)\
+{\
+ unsigned int eflags;\
+ XMMReg a, b;\
+ a.field[0] = a1;\
+ b.field[0] = b1;\
+ asm volatile (#op " %2, %1\n"\
+ "pushf\n"\
+ "pop %0\n"\
+ : "=m" (eflags)\
+ : "x" (a.dq), "x" (b.dq));\
+ printf("%-9s: a=%f b=%f cc=%04x\n",\
+ #op, a1, b1,\
+ eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
+}
+
+void test_sse_comi(double a1, double b1)
+{
+ SSE_COMI(ucomiss, s);
+ SSE_COMI(ucomisd, d);
+ SSE_COMI(comiss, s);
+ SSE_COMI(comisd, d);
+}
+
+#define CVT_OP_XMM(op)\
+{\
+ asm volatile (#op " %1, %0" : "=x" (r.dq) : "x" (a.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ r.q[1], r.q[0]);\
+}
+
+/* Force %xmm0 usage to avoid the case where both register index are 0
+ to test instruction decoding more extensively */
+#define CVT_OP_XMM2MMX(op)\
+{\
+ asm volatile (#op " %1, %0" : "=y" (r.q[0]) : "x" (a.dq) \
+ : "%xmm0"); \
+ asm volatile("emms\n"); \
+ printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ r.q[0]);\
+}
+
+#define CVT_OP_MMX2XMM(op)\
+{\
+ asm volatile (#op " %1, %0" : "=x" (r.dq) : "y" (a.q[0]));\
+ asm volatile("emms\n"); \
+ printf("%-9s: a=" FMT64X " r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[0],\
+ r.q[1], r.q[0]);\
+}
+
+#define CVT_OP_REG2XMM(op)\
+{\
+ asm volatile (#op " %1, %0" : "=x" (r.dq) : "r" (a.l[0]));\
+ printf("%-9s: a=%08x r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.l[0],\
+ r.q[1], r.q[0]);\
+}
+
+#define CVT_OP_XMM2REG(op)\
+{\
+ asm volatile (#op " %1, %0" : "=r" (r.l[0]) : "x" (a.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ r.l[0]);\
+}
+
+struct fpxstate {
+ uint16_t fpuc;
+ uint16_t fpus;
+ uint16_t fptag;
+ uint16_t fop;
+ uint32_t fpuip;
+ uint16_t cs_sel;
+ uint16_t dummy0;
+ uint32_t fpudp;
+ uint16_t ds_sel;
+ uint16_t dummy1;
+ uint32_t mxcsr;
+ uint32_t mxcsr_mask;
+ uint8_t fpregs1[8 * 16];
+ uint8_t xmm_regs[8 * 16];
+ uint8_t dummy2[224];
+};
+
+static struct fpxstate fpx_state __attribute__((aligned(16)));
+static struct fpxstate fpx_state2 __attribute__((aligned(16)));
+
+void test_fxsave(void)
+{
+ struct fpxstate *fp = &fpx_state;
+ struct fpxstate *fp2 = &fpx_state2;
+ int i, nb_xmm;
+ XMMReg a, b;
+ a.q[0] = test_values[0][0];
+ a.q[1] = test_values[0][1];
+ b.q[0] = test_values[1][0];
+ b.q[1] = test_values[1][1];
+
+ asm("movdqa %2, %%xmm0\n"
+ "movdqa %3, %%xmm7\n"
+#if defined(__x86_64__)
+ "movdqa %2, %%xmm15\n"
+#endif
+ " fld1\n"
+ " fldpi\n"
+ " fldln2\n"
+ " fxsave %0\n"
+ " fxrstor %0\n"
+ " fxsave %1\n"
+ " fninit\n"
+ : "=m" (*(uint32_t *)fp2), "=m" (*(uint32_t *)fp)
+ : "m" (a), "m" (b));
+ printf("fpuc=%04x\n", fp->fpuc);
+ printf("fpus=%04x\n", fp->fpus);
+ printf("fptag=%04x\n", fp->fptag);
+ for(i = 0; i < 3; i++) {
+ printf("ST%d: " FMT64X " %04x\n",
+ i,
+ *(uint64_t *)&fp->fpregs1[i * 16],
+ *(uint16_t *)&fp->fpregs1[i * 16 + 8]);
+ }
+ printf("mxcsr=%08x\n", fp->mxcsr & 0x1f80);
+#if defined(__x86_64__)
+ nb_xmm = 16;
+#else
+ nb_xmm = 8;
+#endif
+ for(i = 0; i < nb_xmm; i++) {
+ printf("xmm%d: " FMT64X "" FMT64X "\n",
+ i,
+ *(uint64_t *)&fp->xmm_regs[i * 16],
+ *(uint64_t *)&fp->xmm_regs[i * 16 + 8]);
+ }
+}
+
+void test_sse(void)
+{
+ XMMReg r, a, b;
+ int i;
+
+ MMX_OP2(punpcklbw);
+ MMX_OP2(punpcklwd);
+ MMX_OP2(punpckldq);
+ MMX_OP2(packsswb);
+ MMX_OP2(pcmpgtb);
+ MMX_OP2(pcmpgtw);
+ MMX_OP2(pcmpgtd);
+ MMX_OP2(packuswb);
+ MMX_OP2(punpckhbw);
+ MMX_OP2(punpckhwd);
+ MMX_OP2(punpckhdq);
+ MMX_OP2(packssdw);
+ MMX_OP2(pcmpeqb);
+ MMX_OP2(pcmpeqw);
+ MMX_OP2(pcmpeqd);
+
+ MMX_OP2(paddq);
+ MMX_OP2(pmullw);
+ MMX_OP2(psubusb);
+ MMX_OP2(psubusw);
+ MMX_OP2(pminub);
+ MMX_OP2(pand);
+ MMX_OP2(paddusb);
+ MMX_OP2(paddusw);
+ MMX_OP2(pmaxub);
+ MMX_OP2(pandn);
+
+ MMX_OP2(pmulhuw);
+ MMX_OP2(pmulhw);
+
+ MMX_OP2(psubsb);
+ MMX_OP2(psubsw);
+ MMX_OP2(pminsw);
+ MMX_OP2(por);
+ MMX_OP2(paddsb);
+ MMX_OP2(paddsw);
+ MMX_OP2(pmaxsw);
+ MMX_OP2(pxor);
+ MMX_OP2(pmuludq);
+ MMX_OP2(pmaddwd);
+ MMX_OP2(psadbw);
+ MMX_OP2(psubb);
+ MMX_OP2(psubw);
+ MMX_OP2(psubd);
+ MMX_OP2(psubq);
+ MMX_OP2(paddb);
+ MMX_OP2(paddw);
+ MMX_OP2(paddd);
+
+ MMX_OP2(pavgb);
+ MMX_OP2(pavgw);
+
+ asm volatile ("pinsrw $1, %1, %0" : "=y" (r.q[0]) : "r" (0x12345678));
+ printf("%-9s: r=" FMT64X "\n", "pinsrw", r.q[0]);
+
+ asm volatile ("pinsrw $5, %1, %0" : "=x" (r.dq) : "r" (0x12345678));
+ printf("%-9s: r=" FMT64X "" FMT64X "\n", "pinsrw", r.q[1], r.q[0]);
+
+ a.q[0] = test_values[0][0];
+ a.q[1] = test_values[0][1];
+ asm volatile ("pextrw $1, %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
+ printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
+
+ asm volatile ("pextrw $5, %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
+ printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
+
+ asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
+ printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
+
+ asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
+ printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
+
+ {
+ r.q[0] = -1;
+ r.q[1] = -1;
+
+ a.q[0] = test_values[0][0];
+ a.q[1] = test_values[0][1];
+ b.q[0] = test_values[1][0];
+ b.q[1] = test_values[1][1];
+ asm volatile("maskmovq %1, %0" :
+ : "y" (a.q[0]), "y" (b.q[0]), "D" (&r)
+ : "memory");
+ printf("%-9s: r=" FMT64X " a=" FMT64X " b=" FMT64X "\n",
+ "maskmov",
+ r.q[0],
+ a.q[0],
+ b.q[0]);
+ asm volatile("maskmovdqu %1, %0" :
+ : "x" (a.dq), "x" (b.dq), "D" (&r)
+ : "memory");
+ printf("%-9s: r=" FMT64X "" FMT64X " a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X "\n",
+ "maskmov",
+ r.q[1], r.q[0],
+ a.q[1], a.q[0],
+ b.q[1], b.q[0]);
+ }
+
+ asm volatile ("emms");
+
+ SSE_OP2(punpcklqdq);
+ SSE_OP2(punpckhqdq);
+ SSE_OP2(andps);
+ SSE_OP2(andpd);
+ SSE_OP2(andnps);
+ SSE_OP2(andnpd);
+ SSE_OP2(orps);
+ SSE_OP2(orpd);
+ SSE_OP2(xorps);
+ SSE_OP2(xorpd);
+
+ SSE_OP2(unpcklps);
+ SSE_OP2(unpcklpd);
+ SSE_OP2(unpckhps);
+ SSE_OP2(unpckhpd);
+
+ SHUF_OP(shufps, 0x78);
+ SHUF_OP(shufpd, 0x02);
+
+ PSHUF_OP(pshufd, 0x78);
+ PSHUF_OP(pshuflw, 0x78);
+ PSHUF_OP(pshufhw, 0x78);
+
+ SHIFT_OP(psrlw, 7);
+ SHIFT_OP(psrlw, 16);
+ SHIFT_OP(psraw, 7);
+ SHIFT_OP(psraw, 16);
+ SHIFT_OP(psllw, 7);
+ SHIFT_OP(psllw, 16);
+
+ SHIFT_OP(psrld, 7);
+ SHIFT_OP(psrld, 32);
+ SHIFT_OP(psrad, 7);
+ SHIFT_OP(psrad, 32);
+ SHIFT_OP(pslld, 7);
+ SHIFT_OP(pslld, 32);
+
+ SHIFT_OP(psrlq, 7);
+ SHIFT_OP(psrlq, 32);
+ SHIFT_OP(psllq, 7);
+ SHIFT_OP(psllq, 32);
+
+ SHIFT_IM(psrldq, 16);
+ SHIFT_IM(psrldq, 7);
+ SHIFT_IM(pslldq, 16);
+ SHIFT_IM(pslldq, 7);
+
+ MOVMSK(movmskps);
+ MOVMSK(movmskpd);
+
+ /* FPU specific ops */
+
+ {
+ uint32_t mxcsr;
+ asm volatile("stmxcsr %0" : "=m" (mxcsr));
+ printf("mxcsr=%08x\n", mxcsr & 0x1f80);
+ asm volatile("ldmxcsr %0" : : "m" (mxcsr));
+ }
+
+ test_sse_comi(2, -1);
+ test_sse_comi(2, 2);
+ test_sse_comi(2, 3);
+ test_sse_comi(2, q_nan.d);
+ test_sse_comi(q_nan.d, -1);
+
+ for(i = 0; i < 2; i++) {
+ a.s[0] = 2.7;
+ a.s[1] = 3.4;
+ a.s[2] = 4;
+ a.s[3] = -6.3;
+ b.s[0] = 45.7;
+ b.s[1] = 353.4;
+ b.s[2] = 4;
+ b.s[3] = 56.3;
+ if (i == 1) {
+ a.s[0] = q_nan.d;
+ b.s[3] = q_nan.d;
+ }
+
+ SSE_OPS(add);
+ SSE_OPS(mul);
+ SSE_OPS(sub);
+ SSE_OPS(min);
+ SSE_OPS(div);
+ SSE_OPS(max);
+ SSE_OPS(sqrt);
+ SSE_OPS(cmpeq);
+ SSE_OPS(cmplt);
+ SSE_OPS(cmple);
+ SSE_OPS(cmpunord);
+ SSE_OPS(cmpneq);
+ SSE_OPS(cmpnlt);
+ SSE_OPS(cmpnle);
+ SSE_OPS(cmpord);
+
+
+ a.d[0] = 2.7;
+ a.d[1] = -3.4;
+ b.d[0] = 45.7;
+ b.d[1] = -53.4;
+ if (i == 1) {
+ a.d[0] = q_nan.d;
+ b.d[1] = q_nan.d;
+ }
+ SSE_OPD(add);
+ SSE_OPD(mul);
+ SSE_OPD(sub);
+ SSE_OPD(min);
+ SSE_OPD(div);
+ SSE_OPD(max);
+ SSE_OPD(sqrt);
+ SSE_OPD(cmpeq);
+ SSE_OPD(cmplt);
+ SSE_OPD(cmple);
+ SSE_OPD(cmpunord);
+ SSE_OPD(cmpneq);
+ SSE_OPD(cmpnlt);
+ SSE_OPD(cmpnle);
+ SSE_OPD(cmpord);
+ }
+
+ /* float to float/int */
+ a.s[0] = 2.7;
+ a.s[1] = 3.4;
+ a.s[2] = 4;
+ a.s[3] = -6.3;
+ CVT_OP_XMM(cvtps2pd);
+ CVT_OP_XMM(cvtss2sd);
+ CVT_OP_XMM2MMX(cvtps2pi);
+ CVT_OP_XMM2MMX(cvttps2pi);
+ CVT_OP_XMM2REG(cvtss2si);
+ CVT_OP_XMM2REG(cvttss2si);
+ CVT_OP_XMM(cvtps2dq);
+ CVT_OP_XMM(cvttps2dq);
+
+ a.d[0] = 2.6;
+ a.d[1] = -3.4;
+ CVT_OP_XMM(cvtpd2ps);
+ CVT_OP_XMM(cvtsd2ss);
+ CVT_OP_XMM2MMX(cvtpd2pi);
+ CVT_OP_XMM2MMX(cvttpd2pi);
+ CVT_OP_XMM2REG(cvtsd2si);
+ CVT_OP_XMM2REG(cvttsd2si);
+ CVT_OP_XMM(cvtpd2dq);
+ CVT_OP_XMM(cvttpd2dq);
+
+ /* sse/mmx moves */
+ CVT_OP_XMM2MMX(movdq2q);
+ CVT_OP_MMX2XMM(movq2dq);
+
+ /* int to float */
+ a.l[0] = -6;
+ a.l[1] = 2;
+ a.l[2] = 100;
+ a.l[3] = -60000;
+ CVT_OP_MMX2XMM(cvtpi2ps);
+ CVT_OP_MMX2XMM(cvtpi2pd);
+ CVT_OP_REG2XMM(cvtsi2ss);
+ CVT_OP_REG2XMM(cvtsi2sd);
+ CVT_OP_XMM(cvtdq2ps);
+ CVT_OP_XMM(cvtdq2pd);
+
+ /* XXX: test PNI insns */
+#if 0
+ SSE_OP2(movshdup);
+#endif
+ asm volatile ("emms");
+}
+
+#endif
+
+#define TEST_CONV_RAX(op)\
+{\
+ unsigned long a, r;\
+ a = i2l(0x8234a6f8);\
+ r = a;\
+ asm volatile(#op : "=a" (r) : "0" (r));\
+ printf("%-10s A=" FMTLX " R=" FMTLX "\n", #op, a, r);\
+}
+
+#define TEST_CONV_RAX_RDX(op)\
+{\
+ unsigned long a, d, r, rh; \
+ a = i2l(0x8234a6f8);\
+ d = i2l(0x8345a1f2);\
+ r = a;\
+ rh = d;\
+ asm volatile(#op : "=a" (r), "=d" (rh) : "0" (r), "1" (rh)); \
+ printf("%-10s A=" FMTLX " R=" FMTLX ":" FMTLX "\n", #op, a, r, rh); \
+}
+
+void test_conv(void)
+{
+ TEST_CONV_RAX(cbw);
+ TEST_CONV_RAX(cwde);
+#if defined(__x86_64__)
+ TEST_CONV_RAX(cdqe);
+#endif
+
+ TEST_CONV_RAX_RDX(cwd);
+ TEST_CONV_RAX_RDX(cdq);
+#if defined(__x86_64__)
+ TEST_CONV_RAX_RDX(cqo);
+#endif
+
+ {
+ unsigned long a, r;
+ a = i2l(0x12345678);
+ asm volatile("bswapl %k0" : "=r" (r) : "0" (a));
+ printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapl", a, r);
+ }
+#if defined(__x86_64__)
+ {
+ unsigned long a, r;
+ a = i2l(0x12345678);
+ asm volatile("bswapq %0" : "=r" (r) : "0" (a));
+ printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapq", a, r);
+ }
+#endif
+}
+
+extern void *__start_initcall;
+extern void *__stop_initcall;
+
+
+int main(int argc, char **argv)
+{
+ void **ptr;
+ void (*func)(void);
+
+ ptr = &__start_initcall;
+ while (ptr != &__stop_initcall) {
+ func = *ptr++;
+ func();
+ }
+ test_bsx();
+ test_mul();
+ test_jcc();
+ test_loop();
+ test_floats();
+#if !defined(__x86_64__)
+ test_bcd();
+#endif
+ test_xchg();
+ test_string();
+ test_misc();
+ test_lea();
+#ifdef TEST_SEGS
+ test_segs();
+ test_code16();
+#endif
+#ifdef TEST_VM86
+ test_vm86();
+#endif
+#if !defined(__x86_64__)
+ test_exceptions();
+ test_self_modifying_code();
+ test_single_step();
+#endif
+ test_enter();
+ test_conv();
+#ifdef TEST_SSE
+ test_sse();
+ test_fxsave();
+#endif
+ return 0;
+}
diff --git a/src/tests/tcg/test-i386.h b/src/tests/tcg/test-i386.h
new file mode 100644
index 0000000..75106b8
--- /dev/null
+++ b/src/tests/tcg/test-i386.h
@@ -0,0 +1,152 @@
+
+#define exec_op glue(exec_, OP)
+#define exec_opq glue(glue(exec_, OP), q)
+#define exec_opl glue(glue(exec_, OP), l)
+#define exec_opw glue(glue(exec_, OP), w)
+#define exec_opb glue(glue(exec_, OP), b)
+
+#define EXECOP2(size, rsize, res, s1, flags) \
+ asm ("push %4\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %" rsize "2, %" rsize "0\n\t" \
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=q" (res), "=g" (flags)\
+ : "q" (s1), "0" (res), "1" (flags)); \
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n", \
+ stringify(OP) size, s0, s1, res, iflags, flags & CC_MASK);
+
+#define EXECOP1(size, rsize, res, flags) \
+ asm ("push %3\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %" rsize "0\n\t" \
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=q" (res), "=g" (flags)\
+ : "0" (res), "1" (flags)); \
+ printf("%-10s A=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n", \
+ stringify(OP) size, s0, res, iflags, flags & CC_MASK);
+
+#ifdef OP1
+#if defined(__x86_64__)
+void exec_opq(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP1("q", "", res, flags);
+}
+#endif
+
+void exec_opl(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP1("l", "k", res, flags);
+}
+
+void exec_opw(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP1("w", "w", res, flags);
+}
+
+void exec_opb(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP1("b", "b", res, flags);
+}
+#else
+#if defined(__x86_64__)
+void exec_opq(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP2("q", "", res, s1, flags);
+}
+#endif
+
+void exec_opl(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP2("l", "k", res, s1, flags);
+}
+
+void exec_opw(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP2("w", "w", res, s1, flags);
+}
+
+void exec_opb(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP2("b", "b", res, s1, flags);
+}
+#endif
+
+void exec_op(long s0, long s1)
+{
+ s0 = i2l(s0);
+ s1 = i2l(s1);
+#if defined(__x86_64__)
+ exec_opq(s0, s1, 0);
+#endif
+ exec_opl(s0, s1, 0);
+ exec_opw(s0, s1, 0);
+ exec_opb(s0, s1, 0);
+#ifdef OP_CC
+#if defined(__x86_64__)
+ exec_opq(s0, s1, CC_C);
+#endif
+ exec_opl(s0, s1, CC_C);
+ exec_opw(s0, s1, CC_C);
+ exec_opb(s0, s1, CC_C);
+#endif
+}
+
+void glue(test_, OP)(void)
+{
+ exec_op(0x12345678, 0x812FADA);
+ exec_op(0x12341, 0x12341);
+ exec_op(0x12341, -0x12341);
+ exec_op(0xffffffff, 0);
+ exec_op(0xffffffff, -1);
+ exec_op(0xffffffff, 1);
+ exec_op(0xffffffff, 2);
+ exec_op(0x7fffffff, 0);
+ exec_op(0x7fffffff, 1);
+ exec_op(0x7fffffff, -1);
+ exec_op(0x80000000, -1);
+ exec_op(0x80000000, 1);
+ exec_op(0x80000000, -2);
+ exec_op(0x12347fff, 0);
+ exec_op(0x12347fff, 1);
+ exec_op(0x12347fff, -1);
+ exec_op(0x12348000, -1);
+ exec_op(0x12348000, 1);
+ exec_op(0x12348000, -2);
+ exec_op(0x12347f7f, 0);
+ exec_op(0x12347f7f, 1);
+ exec_op(0x12347f7f, -1);
+ exec_op(0x12348080, -1);
+ exec_op(0x12348080, 1);
+ exec_op(0x12348080, -2);
+}
+
+void *glue(_test_, OP) __init_call = glue(test_, OP);
+
+#undef OP
+#undef OP_CC
diff --git a/src/tests/tcg/test-mmap.c b/src/tests/tcg/test-mmap.c
new file mode 100644
index 0000000..3982fa2
--- /dev/null
+++ b/src/tests/tcg/test-mmap.c
@@ -0,0 +1,484 @@
+/*
+ * Small test program to verify simulated mmap behaviour.
+ *
+ * When running qemu-linux-user with the -p flag, you may need to tell
+ * this test program about the pagesize because getpagesize() will not reflect
+ * the -p choice. Simply pass one argument being the pagesize.
+ *
+ * Copyright (c) 2007 AXIS Communications AB
+ * Written by Edgar E. Iglesias.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#define D(x)
+
+#define fail_unless(x) \
+do \
+{ \
+ if (!(x)) { \
+ fprintf (stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \
+ exit (EXIT_FAILURE); \
+ } \
+} while (0);
+
+unsigned char *dummybuf;
+static unsigned int pagesize;
+static unsigned int pagemask;
+int test_fd;
+size_t test_fsize;
+
+void check_aligned_anonymous_unfixed_mmaps(void)
+{
+ void *p1;
+ void *p2;
+ void *p3;
+ void *p4;
+ void *p5;
+ uintptr_t p;
+ int i;
+
+ fprintf (stderr, "%s", __func__);
+ for (i = 0; i < 0x1fff; i++)
+ {
+ size_t len;
+
+ len = pagesize + (pagesize * i & 7);
+ p1 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ p2 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ p3 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ p4 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ p5 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ /* Make sure we get pages aligned with the pagesize. The
+ target expects this. */
+ fail_unless (p1 != MAP_FAILED);
+ fail_unless (p2 != MAP_FAILED);
+ fail_unless (p3 != MAP_FAILED);
+ fail_unless (p4 != MAP_FAILED);
+ fail_unless (p5 != MAP_FAILED);
+ p = (uintptr_t) p1;
+ D(printf ("p=%x\n", p));
+ fail_unless ((p & pagemask) == 0);
+ p = (uintptr_t) p2;
+ fail_unless ((p & pagemask) == 0);
+ p = (uintptr_t) p3;
+ fail_unless ((p & pagemask) == 0);
+ p = (uintptr_t) p4;
+ fail_unless ((p & pagemask) == 0);
+ p = (uintptr_t) p5;
+ fail_unless ((p & pagemask) == 0);
+
+ /* Make sure we can read from the entire area. */
+ memcpy (dummybuf, p1, pagesize);
+ memcpy (dummybuf, p2, pagesize);
+ memcpy (dummybuf, p3, pagesize);
+ memcpy (dummybuf, p4, pagesize);
+ memcpy (dummybuf, p5, pagesize);
+
+ munmap (p1, len);
+ munmap (p2, len);
+ munmap (p3, len);
+ munmap (p4, len);
+ munmap (p5, len);
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_large_anonymous_unfixed_mmap(void)
+{
+ void *p1;
+ uintptr_t p;
+ size_t len;
+
+ fprintf (stderr, "%s", __func__);
+
+ len = 0x02000000;
+ p1 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ /* Make sure we get pages aligned with the pagesize. The
+ target expects this. */
+ fail_unless (p1 != MAP_FAILED);
+ p = (uintptr_t) p1;
+ fail_unless ((p & pagemask) == 0);
+
+ /* Make sure we can read from the entire area. */
+ memcpy (dummybuf, p1, pagesize);
+ munmap (p1, len);
+ fprintf (stderr, " passed\n");
+}
+
+void check_aligned_anonymous_unfixed_colliding_mmaps(void)
+{
+ char *p1;
+ char *p2;
+ char *p3;
+ uintptr_t p;
+ int i;
+
+ fprintf (stderr, "%s", __func__);
+ for (i = 0; i < 0x2fff; i++)
+ {
+ int nlen;
+ p1 = mmap(NULL, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ fail_unless (p1 != MAP_FAILED);
+ p = (uintptr_t) p1;
+ fail_unless ((p & pagemask) == 0);
+ memcpy (dummybuf, p1, pagesize);
+
+ p2 = mmap(NULL, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ fail_unless (p2 != MAP_FAILED);
+ p = (uintptr_t) p2;
+ fail_unless ((p & pagemask) == 0);
+ memcpy (dummybuf, p2, pagesize);
+
+
+ munmap (p1, pagesize);
+ nlen = pagesize * 8;
+ p3 = mmap(NULL, nlen, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ fail_unless (p3 != MAP_FAILED);
+
+ /* Check if the mmaped areas collide. */
+ if (p3 < p2
+ && (p3 + nlen) > p2)
+ fail_unless (0);
+
+ memcpy (dummybuf, p3, pagesize);
+
+ /* Make sure we get pages aligned with the pagesize. The
+ target expects this. */
+ p = (uintptr_t) p3;
+ fail_unless ((p & pagemask) == 0);
+ munmap (p2, pagesize);
+ munmap (p3, nlen);
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_aligned_anonymous_fixed_mmaps(void)
+{
+ char *addr;
+ void *p1;
+ uintptr_t p;
+ int i;
+
+ /* Find a suitable address to start with. */
+ addr = mmap(NULL, pagesize * 40, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+ fprintf (stderr, "%s addr=%p", __func__, addr);
+ fail_unless (addr != MAP_FAILED);
+
+ for (i = 0; i < 40; i++)
+ {
+ /* Create submaps within our unfixed map. */
+ p1 = mmap(addr, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+ -1, 0);
+ /* Make sure we get pages aligned with the pagesize.
+ The target expects this. */
+ p = (uintptr_t) p1;
+ fail_unless (p1 == addr);
+ fail_unless ((p & pagemask) == 0);
+ memcpy (dummybuf, p1, pagesize);
+ munmap (p1, pagesize);
+ addr += pagesize;
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_aligned_anonymous_fixed_mmaps_collide_with_host(void)
+{
+ char *addr;
+ void *p1;
+ uintptr_t p;
+ int i;
+
+ /* Find a suitable address to start with. Right were the x86 hosts
+ stack is. */
+ addr = ((void *)0x80000000);
+ fprintf (stderr, "%s addr=%p", __func__, addr);
+ fprintf (stderr, "FIXME: QEMU fails to track pages used by the host.");
+
+ for (i = 0; i < 20; i++)
+ {
+ /* Create submaps within our unfixed map. */
+ p1 = mmap(addr, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+ -1, 0);
+ /* Make sure we get pages aligned with the pagesize.
+ The target expects this. */
+ p = (uintptr_t) p1;
+ fail_unless (p1 == addr);
+ fail_unless ((p & pagemask) == 0);
+ memcpy (p1, dummybuf, pagesize);
+ munmap (p1, pagesize);
+ addr += pagesize;
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_file_unfixed_mmaps(void)
+{
+ unsigned int *p1, *p2, *p3;
+ uintptr_t p;
+ int i;
+
+ fprintf (stderr, "%s", __func__);
+ for (i = 0; i < 0x10; i++)
+ {
+ size_t len;
+
+ len = pagesize;
+ p1 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE,
+ test_fd, 0);
+ p2 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE,
+ test_fd, pagesize);
+ p3 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE,
+ test_fd, pagesize * 2);
+
+ fail_unless (p1 != MAP_FAILED);
+ fail_unless (p2 != MAP_FAILED);
+ fail_unless (p3 != MAP_FAILED);
+
+ /* Make sure we get pages aligned with the pagesize. The
+ target expects this. */
+ p = (uintptr_t) p1;
+ fail_unless ((p & pagemask) == 0);
+ p = (uintptr_t) p2;
+ fail_unless ((p & pagemask) == 0);
+ p = (uintptr_t) p3;
+ fail_unless ((p & pagemask) == 0);
+
+ /* Verify that the file maps was made correctly. */
+ D(printf ("p1=%d p2=%d p3=%d\n", *p1, *p2, *p3));
+ fail_unless (*p1 == 0);
+ fail_unless (*p2 == (pagesize / sizeof *p2));
+ fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
+
+ memcpy (dummybuf, p1, pagesize);
+ memcpy (dummybuf, p2, pagesize);
+ memcpy (dummybuf, p3, pagesize);
+ munmap (p1, len);
+ munmap (p2, len);
+ munmap (p3, len);
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_file_unfixed_eof_mmaps(void)
+{
+ char *cp;
+ unsigned int *p1;
+ uintptr_t p;
+ int i;
+
+ fprintf (stderr, "%s", __func__);
+ for (i = 0; i < 0x10; i++)
+ {
+ p1 = mmap(NULL, pagesize, PROT_READ,
+ MAP_PRIVATE,
+ test_fd,
+ (test_fsize - sizeof *p1) & ~pagemask);
+
+ fail_unless (p1 != MAP_FAILED);
+
+ /* Make sure we get pages aligned with the pagesize. The
+ target expects this. */
+ p = (uintptr_t) p1;
+ fail_unless ((p & pagemask) == 0);
+ /* Verify that the file maps was made correctly. */
+ fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
+ == ((test_fsize - sizeof *p1) / sizeof *p1));
+
+ /* Verify that the end of page is accessible and zeroed. */
+ cp = (void *) p1;
+ fail_unless (cp[pagesize - 4] == 0);
+ munmap (p1, pagesize);
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_file_fixed_eof_mmaps(void)
+{
+ char *addr;
+ char *cp;
+ unsigned int *p1;
+ uintptr_t p;
+ int i;
+
+ /* Find a suitable address to start with. */
+ addr = mmap(NULL, pagesize * 44, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+
+ fprintf (stderr, "%s addr=%p", __func__, (void *)addr);
+ fail_unless (addr != MAP_FAILED);
+
+ for (i = 0; i < 0x10; i++)
+ {
+ /* Create submaps within our unfixed map. */
+ p1 = mmap(addr, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_FIXED,
+ test_fd,
+ (test_fsize - sizeof *p1) & ~pagemask);
+
+ fail_unless (p1 != MAP_FAILED);
+
+ /* Make sure we get pages aligned with the pagesize. The
+ target expects this. */
+ p = (uintptr_t) p1;
+ fail_unless ((p & pagemask) == 0);
+
+ /* Verify that the file maps was made correctly. */
+ fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
+ == ((test_fsize - sizeof *p1) / sizeof *p1));
+
+ /* Verify that the end of page is accessible and zeroed. */
+ cp = (void *)p1;
+ fail_unless (cp[pagesize - 4] == 0);
+ munmap (p1, pagesize);
+ addr += pagesize;
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_file_fixed_mmaps(void)
+{
+ unsigned char *addr;
+ unsigned int *p1, *p2, *p3, *p4;
+ int i;
+
+ /* Find a suitable address to start with. */
+ addr = mmap(NULL, pagesize * 40 * 4, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+ fprintf (stderr, "%s addr=%p", __func__, (void *)addr);
+ fail_unless (addr != MAP_FAILED);
+
+ for (i = 0; i < 40; i++)
+ {
+ p1 = mmap(addr, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_FIXED,
+ test_fd, 0);
+ p2 = mmap(addr + pagesize, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_FIXED,
+ test_fd, pagesize);
+ p3 = mmap(addr + pagesize * 2, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_FIXED,
+ test_fd, pagesize * 2);
+ p4 = mmap(addr + pagesize * 3, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_FIXED,
+ test_fd, pagesize * 3);
+
+ /* Make sure we get pages aligned with the pagesize.
+ The target expects this. */
+ fail_unless (p1 == (void *)addr);
+ fail_unless (p2 == (void *)addr + pagesize);
+ fail_unless (p3 == (void *)addr + pagesize * 2);
+ fail_unless (p4 == (void *)addr + pagesize * 3);
+
+ /* Verify that the file maps was made correctly. */
+ fail_unless (*p1 == 0);
+ fail_unless (*p2 == (pagesize / sizeof *p2));
+ fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
+ fail_unless (*p4 == ((pagesize * 3) / sizeof *p4));
+
+ memcpy (dummybuf, p1, pagesize);
+ memcpy (dummybuf, p2, pagesize);
+ memcpy (dummybuf, p3, pagesize);
+ memcpy (dummybuf, p4, pagesize);
+
+ munmap (p1, pagesize);
+ munmap (p2, pagesize);
+ munmap (p3, pagesize);
+ munmap (p4, pagesize);
+ addr += pagesize * 4;
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void checked_write(int fd, const void *buf, size_t count)
+{
+ ssize_t rc = write(fd, buf, count);
+ fail_unless(rc == count);
+}
+
+int main(int argc, char **argv)
+{
+ char tempname[] = "/tmp/.cmmapXXXXXX";
+ unsigned int i;
+
+ /* Trust the first argument, otherwise probe the system for our
+ pagesize. */
+ if (argc > 1)
+ pagesize = strtoul(argv[1], NULL, 0);
+ else
+ pagesize = sysconf(_SC_PAGESIZE);
+
+ /* Assume pagesize is a power of two. */
+ pagemask = pagesize - 1;
+ dummybuf = malloc (pagesize);
+ printf ("pagesize=%u pagemask=%x\n", pagesize, pagemask);
+
+ test_fd = mkstemp(tempname);
+ unlink(tempname);
+
+ /* Fill the file with int's counting from zero and up. */
+ for (i = 0; i < (pagesize * 4) / sizeof i; i++) {
+ checked_write(test_fd, &i, sizeof i);
+ }
+
+ /* Append a few extra writes to make the file end at non
+ page boundary. */
+ checked_write(test_fd, &i, sizeof i); i++;
+ checked_write(test_fd, &i, sizeof i); i++;
+ checked_write(test_fd, &i, sizeof i); i++;
+
+ test_fsize = lseek(test_fd, 0, SEEK_CUR);
+
+ /* Run the tests. */
+ check_aligned_anonymous_unfixed_mmaps();
+ check_aligned_anonymous_unfixed_colliding_mmaps();
+ check_aligned_anonymous_fixed_mmaps();
+ check_file_unfixed_mmaps();
+ check_file_fixed_mmaps();
+ check_file_fixed_eof_mmaps();
+ check_file_unfixed_eof_mmaps();
+
+ /* Fails at the moment. */
+ /* check_aligned_anonymous_fixed_mmaps_collide_with_host(); */
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/tests/tcg/test_path.c b/src/tests/tcg/test_path.c
new file mode 100644
index 0000000..1c29bce
--- /dev/null
+++ b/src/tests/tcg/test_path.c
@@ -0,0 +1,157 @@
+/* Test path override code */
+#include "config-host.h"
+#include "util/cutils.c"
+#include "util/hexdump.c"
+#include "util/iov.c"
+#include "util/path.c"
+#include "util/qemu-timer-common.c"
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+void qemu_log(const char *fmt, ...);
+
+/* Any log message kills the test. */
+void qemu_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "FATAL: ");
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ exit(1);
+}
+
+#define NO_CHANGE(_path) \
+ do { \
+ if (strcmp(path(_path), _path) != 0) return __LINE__; \
+ } while(0)
+
+#define CHANGE_TO(_path, _newpath) \
+ do { \
+ if (strcmp(path(_path), _newpath) != 0) return __LINE__; \
+ } while(0)
+
+static void cleanup(void)
+{
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE2");
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE3");
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE4");
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE5");
+ rmdir("/tmp/qemu-test_path/DIR1/DIR2");
+ rmdir("/tmp/qemu-test_path/DIR1/DIR3");
+ rmdir("/tmp/qemu-test_path/DIR1");
+ rmdir("/tmp/qemu-test_path");
+}
+
+static unsigned int do_test(void)
+{
+ if (mkdir("/tmp/qemu-test_path", 0700) != 0)
+ return __LINE__;
+
+ if (mkdir("/tmp/qemu-test_path/DIR1", 0700) != 0)
+ return __LINE__;
+
+ if (mkdir("/tmp/qemu-test_path/DIR1/DIR2", 0700) != 0)
+ return __LINE__;
+
+ if (mkdir("/tmp/qemu-test_path/DIR1/DIR3", 0700) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE", 0600)) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE2", 0600)) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE3", 0600)) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE4", 0600)) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE5", 0600)) != 0)
+ return __LINE__;
+
+ init_paths("/tmp/qemu-test_path");
+
+ NO_CHANGE("/tmp");
+ NO_CHANGE("/tmp/");
+ NO_CHANGE("/tmp/qemu-test_path");
+ NO_CHANGE("/tmp/qemu-test_path/");
+ NO_CHANGE("/tmp/qemu-test_path/D");
+ NO_CHANGE("/tmp/qemu-test_path/DI");
+ NO_CHANGE("/tmp/qemu-test_path/DIR");
+ NO_CHANGE("/tmp/qemu-test_path/DIR1");
+ NO_CHANGE("/tmp/qemu-test_path/DIR1/");
+
+ NO_CHANGE("/D");
+ NO_CHANGE("/DI");
+ NO_CHANGE("/DIR");
+ NO_CHANGE("/DIR2");
+ NO_CHANGE("/DIR1.");
+
+ CHANGE_TO("/DIR1", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/DIR1/", "/tmp/qemu-test_path/DIR1");
+
+ NO_CHANGE("/DIR1/D");
+ NO_CHANGE("/DIR1/DI");
+ NO_CHANGE("/DIR1/DIR");
+ NO_CHANGE("/DIR1/DIR1");
+
+ CHANGE_TO("/DIR1/DIR2", "/tmp/qemu-test_path/DIR1/DIR2");
+ CHANGE_TO("/DIR1/DIR2/", "/tmp/qemu-test_path/DIR1/DIR2");
+
+ CHANGE_TO("/DIR1/DIR3", "/tmp/qemu-test_path/DIR1/DIR3");
+ CHANGE_TO("/DIR1/DIR3/", "/tmp/qemu-test_path/DIR1/DIR3");
+
+ NO_CHANGE("/DIR1/DIR2/F");
+ NO_CHANGE("/DIR1/DIR2/FI");
+ NO_CHANGE("/DIR1/DIR2/FIL");
+ NO_CHANGE("/DIR1/DIR2/FIL.");
+
+ CHANGE_TO("/DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/DIR2/FILE2", "/tmp/qemu-test_path/DIR1/DIR2/FILE2");
+ CHANGE_TO("/DIR1/DIR2/FILE3", "/tmp/qemu-test_path/DIR1/DIR2/FILE3");
+ CHANGE_TO("/DIR1/DIR2/FILE4", "/tmp/qemu-test_path/DIR1/DIR2/FILE4");
+ CHANGE_TO("/DIR1/DIR2/FILE5", "/tmp/qemu-test_path/DIR1/DIR2/FILE5");
+
+ NO_CHANGE("/DIR1/DIR2/FILE6");
+ NO_CHANGE("/DIR1/DIR2/FILE/X");
+
+ CHANGE_TO("/DIR1/../DIR1", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/DIR1/../DIR1/", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/../DIR1", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/../DIR1/", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/DIR1/DIR2/../DIR2", "/tmp/qemu-test_path/DIR1/DIR2");
+ CHANGE_TO("/DIR1/DIR2/../DIR2/../../DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/DIR2/../DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+
+ NO_CHANGE("/DIR1/DIR2/../DIR1");
+ NO_CHANGE("/DIR1/DIR2/../FILE");
+
+ CHANGE_TO("/./DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/././DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/./DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/././DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/DIR2/./FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/DIR2/././FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/./DIR1/./DIR2/./FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+
+ ret = do_test();
+ cleanup();
+ if (ret) {
+ fprintf(stderr, "test_path: failed on line %i\n", ret);
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/tests/tcg/testthread.c b/src/tests/tcg/testthread.c
new file mode 100644
index 0000000..810ba5d
--- /dev/null
+++ b/src/tests/tcg/testthread.c
@@ -0,0 +1,57 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <sys/wait.h>
+#include <sched.h>
+
+void checked_write(int fd, const void *buf, size_t count)
+{
+ ssize_t rc = write(fd, buf, count);
+ assert(rc == count);
+}
+
+void *thread1_func(void *arg)
+{
+ int i;
+ char buf[512];
+
+ for(i=0;i<10;i++) {
+ snprintf(buf, sizeof(buf), "thread1: %d %s\n", i, (char *)arg);
+ checked_write(1, buf, strlen(buf));
+ usleep(100 * 1000);
+ }
+ return NULL;
+}
+
+void *thread2_func(void *arg)
+{
+ int i;
+ char buf[512];
+ for(i=0;i<20;i++) {
+ snprintf(buf, sizeof(buf), "thread2: %d %s\n", i, (char *)arg);
+ checked_write(1, buf, strlen(buf));
+ usleep(150 * 1000);
+ }
+ return NULL;
+}
+
+void test_pthread(void)
+{
+ pthread_t tid1, tid2;
+
+ pthread_create(&tid1, NULL, thread1_func, "hello1");
+ pthread_create(&tid2, NULL, thread2_func, "hello2");
+ pthread_join(tid1, NULL);
+ pthread_join(tid2, NULL);
+ printf("End of pthread test.\n");
+}
+
+int main(int argc, char **argv)
+{
+ test_pthread();
+ return 0;
+}
diff --git a/src/tests/tcg/xtensa/Makefile b/src/tests/tcg/xtensa/Makefile
new file mode 100644
index 0000000..522a63e
--- /dev/null
+++ b/src/tests/tcg/xtensa/Makefile
@@ -0,0 +1,92 @@
+-include ../../../config-host.mak
+
+CORE=dc232b
+CROSS=xtensa-$(CORE)-elf-
+
+ifndef XT
+SIM = ../../../xtensa-softmmu/qemu-system-xtensa
+SIMFLAGS = -M sim -cpu $(CORE) -nographic -semihosting $(EXTFLAGS) -kernel
+SIMDEBUG = -s -S
+else
+SIM = xt-run
+SIMFLAGS = --xtensa-core=DC_B_232L --exit_with_target_code $(EXTFLAGS)
+SIMDEBUG = --gdbserve=0
+endif
+
+HOST_CC = gcc
+CC = $(CROSS)gcc
+AS = $(CROSS)gcc -x assembler-with-cpp
+LD = $(CROSS)ld
+
+XTENSA_SRC_PATH = $(SRC_PATH)/tests/tcg/xtensa
+INCLUDE_DIRS = $(XTENSA_SRC_PATH) $(SRC_PATH)/target-xtensa/core-$(CORE)
+XTENSA_INC = $(addprefix -I,$(INCLUDE_DIRS))
+
+LDFLAGS = -Tlinker.ld
+
+CRT = crt.o vectors.o
+
+TESTCASES += test_b.tst
+TESTCASES += test_bi.tst
+#TESTCASES += test_boolean.tst
+TESTCASES += test_break.tst
+TESTCASES += test_bz.tst
+TESTCASES += test_cache.tst
+TESTCASES += test_clamps.tst
+TESTCASES += test_extui.tst
+TESTCASES += test_fail.tst
+TESTCASES += test_interrupt.tst
+TESTCASES += test_loop.tst
+TESTCASES += test_mac16.tst
+TESTCASES += test_max.tst
+TESTCASES += test_min.tst
+TESTCASES += test_mmu.tst
+TESTCASES += test_mul16.tst
+TESTCASES += test_mul32.tst
+TESTCASES += test_nsa.tst
+ifdef XT
+TESTCASES += test_pipeline.tst
+endif
+TESTCASES += test_quo.tst
+TESTCASES += test_rem.tst
+TESTCASES += test_rst0.tst
+TESTCASES += test_s32c1i.tst
+TESTCASES += test_sar.tst
+TESTCASES += test_sext.tst
+TESTCASES += test_shift.tst
+TESTCASES += test_sr.tst
+TESTCASES += test_timer.tst
+TESTCASES += test_windowed.tst
+
+all: build
+
+linker.ld: $(XTENSA_SRC_PATH)/linker.ld.S
+ $(HOST_CC) $(XTENSA_INC) -E -P $< -o $@
+
+%.o: $(XTENSA_SRC_PATH)/%.c
+ $(CC) $(XTENSA_INC) $(CFLAGS) -c $< -o $@
+
+%.o: $(XTENSA_SRC_PATH)/%.S
+ $(CC) $(XTENSA_INC) $(ASFLAGS) -c $< -o $@
+
+%.tst: %.o linker.ld $(XTENSA_SRC_PATH)/macros.inc $(CRT) Makefile
+ $(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
+
+build: $(TESTCASES)
+
+check: $(addprefix run-, $(TESTCASES))
+
+run-%.tst: %.tst
+ $(SIM) $(SIMFLAGS) ./$<
+
+run-test_fail.tst: test_fail.tst
+ ! $(SIM) $(SIMFLAGS) ./$<
+
+debug-%.tst: %.tst
+ $(SIM) $(SIMDEBUG) $(SIMFLAGS) ./$<
+
+host-debug-%.tst: %.tst
+ gdb --args $(SIM) $(SIMFLAGS) ./$<
+
+clean:
+ $(RM) -fr $(TESTCASES) $(CRT) linker.ld
diff --git a/src/tests/tcg/xtensa/crt.S b/src/tests/tcg/xtensa/crt.S
new file mode 100644
index 0000000..d9846ac
--- /dev/null
+++ b/src/tests/tcg/xtensa/crt.S
@@ -0,0 +1,24 @@
+.section .init
+ j 1f
+.section .init.text
+1:
+ movi a2, _start
+ jx a2
+
+.text
+.global _start
+_start:
+ movi a2, 1
+ wsr a2, windowstart
+ movi a2, 0
+ wsr a2, windowbase
+ movi a1, _fstack
+ movi a2, 0x4000f
+ wsr a2, ps
+ isync
+
+ call0 main
+
+ mov a3, a2
+ movi a2, 1
+ simcall
diff --git a/src/tests/tcg/xtensa/linker.ld.S b/src/tests/tcg/xtensa/linker.ld.S
new file mode 100644
index 0000000..f1e7fa9
--- /dev/null
+++ b/src/tests/tcg/xtensa/linker.ld.S
@@ -0,0 +1,130 @@
+#include <core-isa.h>
+
+#if XTENSA_HAVE_BE
+OUTPUT_FORMAT("elf32-xtensa-be")
+#else
+OUTPUT_FORMAT("elf32-xtensa-le")
+#endif
+ENTRY(_start)
+
+__DYNAMIC = 0;
+
+MEMORY {
+ ram : ORIGIN = XCHAL_VECBASE_RESET_VADDR, LENGTH = 0x08000000 /* 128M */
+ rom : ORIGIN = XCHAL_RESET_VECTOR_VADDR, LENGTH = 0x00001000 /* 4k */
+}
+
+SECTIONS
+{
+ .init :
+ {
+ *(.init)
+ *(.init.*)
+ } > rom
+
+ .vector :
+ {
+ . = XCHAL_WINDOW_OF4_VECOFS;
+ *(.vector.window_overflow_4)
+ *(.vector.window_overflow_4.*)
+ . = XCHAL_WINDOW_UF4_VECOFS;
+ *(.vector.window_underflow_4)
+ *(.vector.window_underflow_4.*)
+ . = XCHAL_WINDOW_OF8_VECOFS;
+ *(.vector.window_overflow_8)
+ *(.vector.window_overflow_8.*)
+ . = XCHAL_WINDOW_UF8_VECOFS;
+ *(.vector.window_underflow_8)
+ *(.vector.window_underflow_8.*)
+ . = XCHAL_WINDOW_OF12_VECOFS;
+ *(.vector.window_overflow_12)
+ *(.vector.window_overflow_12.*)
+ . = XCHAL_WINDOW_UF12_VECOFS;
+ *(.vector.window_underflow_12)
+ *(.vector.window_underflow_12.*)
+
+#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 2
+ . = XCHAL_INTLEVEL2_VECOFS;
+ *(.vector.level2)
+ *(.vector.level2.*)
+#endif
+#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 3
+ . = XCHAL_INTLEVEL3_VECOFS;
+ *(.vector.level3)
+ *(.vector.level3.*)
+#endif
+#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 4
+ . = XCHAL_INTLEVEL4_VECOFS;
+ *(.vector.level4)
+ *(.vector.level4.*)
+#endif
+#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 5
+ . = XCHAL_INTLEVEL5_VECOFS;
+ *(.vector.level5)
+ *(.vector.level5.*)
+#endif
+#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 6
+ . = XCHAL_INTLEVEL6_VECOFS;
+ *(.vector.level6)
+ *(.vector.level6.*)
+#endif
+#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 7
+ . = XCHAL_INTLEVEL7_VECOFS;
+ *(.vector.level7)
+ *(.vector.level7.*)
+#endif
+
+ . = XCHAL_KERNEL_VECOFS;
+ *(.vector.kernel)
+ *(.vector.kernel.*)
+ . = XCHAL_USER_VECOFS;
+ *(.vector.user)
+ *(.vector.user.*)
+ . = XCHAL_DOUBLEEXC_VECOFS;
+ *(.vector.double)
+ *(.vector.double.*)
+ } > ram
+
+ .text :
+ {
+ _ftext = .;
+ *(.text .stub .text.* .gnu.linkonce.t.* .literal .literal.*)
+ _etext = .;
+ } > ram
+
+ .rodata :
+ {
+ . = ALIGN(4);
+ _frodata = .;
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.rodata1)
+ _erodata = .;
+ } > ram
+
+ .data :
+ {
+ . = ALIGN(4);
+ _fdata = .;
+ *(.data .data.* .gnu.linkonce.d.*)
+ *(.data1)
+ _gp = ALIGN(16);
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ _edata = .;
+ } > ram
+
+ .bss :
+ {
+ . = ALIGN(4);
+ _fbss = .;
+ *(.dynsbss)
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ _ebss = .;
+ _end = .;
+ } > ram
+}
+
+PROVIDE(_fstack = (ORIGIN(ram) & 0xf0000000) + LENGTH(ram) - 16);
diff --git a/src/tests/tcg/xtensa/macros.inc b/src/tests/tcg/xtensa/macros.inc
new file mode 100644
index 0000000..4ebd30a
--- /dev/null
+++ b/src/tests/tcg/xtensa/macros.inc
@@ -0,0 +1,91 @@
+#include "core-isa.h"
+
+.macro test_suite name
+.data
+status: .word result
+result: .space 256
+.text
+.global main
+.align 4
+main:
+.endm
+
+.macro reset_ps
+ movi a2, 0x4000f
+ wsr a2, ps
+ isync
+.endm
+
+.macro test_suite_end
+ reset_ps
+ movi a0, status
+ l32i a2, a0, 0
+ movi a0, result
+ sub a2, a2, a0
+ movi a3, 0
+ loopnez a2, 1f
+ l8ui a2, a0, 0
+ or a3, a3, a2
+ addi a0, a0, 1
+1:
+ exit
+.endm
+
+.macro print text
+.data
+97: .ascii "\text\n"
+98:
+ .align 4
+.text
+ movi a2, 4
+ movi a3, 2
+ movi a4, 97b
+ movi a5, 98b
+ sub a5, a5, a4
+ simcall
+.endm
+
+.macro test_init
+.endm
+
+.macro test name
+ //print test_\name
+ test_init
+test_\name:
+.global test_\name
+.endm
+
+.macro test_end
+99:
+ reset_ps
+ movi a2, status
+ l32i a3, a2, 0
+ addi a3, a3, 1
+ s32i a3, a2, 0
+.endm
+
+.macro exit
+ movi a2, 1
+ simcall
+.endm
+
+.macro test_fail
+ movi a2, status
+ l32i a2, a2, 0
+ movi a3, 1
+ s8i a3, a2, 0
+ j 99f
+.endm
+
+.macro assert cond, arg1, arg2
+ b\cond \arg1, \arg2, 90f
+ test_fail
+90:
+ nop
+.endm
+
+.macro set_vector vector, addr
+ movi a2, handler_\vector
+ movi a3, \addr
+ s32i a3, a2, 0
+.endm
diff --git a/src/tests/tcg/xtensa/test_b.S b/src/tests/tcg/xtensa/test_b.S
new file mode 100644
index 0000000..8e81f95
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_b.S
@@ -0,0 +1,221 @@
+#include "macros.inc"
+
+test_suite b
+
+test bnone
+ movi a2, 0xa5a5ff00
+ movi a3, 0x5a5a00ff
+ bnone a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xa5a5ff01
+ bnone a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test beq
+ movi a2, 0
+ movi a3, 0
+ beq a2, a3, 1f
+ test_fail
+1:
+ movi a2, 1
+ beq a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test blt
+ movi a2, 6
+ movi a3, 7
+ blt a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xffffffff
+ blt a2, a3, 1f
+ test_fail
+1:
+ movi a2, 7
+ blt a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bltu
+ movi a2, 6
+ movi a3, 7
+ bltu a2, a3, 1f
+ test_fail
+1:
+ movi a2, 7
+ bltu a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+ movi a2, 0xffffffff
+ bltu a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test ball
+ movi a2, 0xa5a5ffa5
+ movi a3, 0xa5a5ff00
+ ball a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xa5a5a5a5
+ ball a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bbc
+ movi a2, 0xfffffffd
+ movi a3, 0xffffff01
+ bbc a2, a3, 1f
+ test_fail
+1:
+ movi a2, 8
+ movi a3, 0xffffff03
+ bbc a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bbci
+ movi a2, 0xfffdffff
+ bbci a2, 17, 1f
+ test_fail
+1:
+ movi a2, 0x00020000
+ bbci a2, 17, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bany
+ movi a2, 0xa5a5ff01
+ movi a3, 0x5a5a00ff
+ bany a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xa5a5ff00
+ bany a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bne
+ movi a2, 1
+ movi a3, 0
+ bne a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0
+ bne a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bge
+ movi a2, 7
+ movi a3, 7
+ bge a2, a3, 1f
+ test_fail
+1:
+ movi a2, 6
+ bge a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+ movi a2, 0xffffffff
+ bge a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bgeu
+ movi a2, 7
+ movi a3, 7
+ bgeu a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xffffffff
+ bgeu a2, a3, 1f
+ test_fail
+1:
+ movi a2, 6
+ bgeu a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bnall
+ movi a2, 0xa5a5a5a5
+ movi a3, 0xa5a5ff00
+ bnall a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xa5a5ffa5
+ bnall a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bbs
+ movi a2, 8
+ movi a3, 0xffffff03
+ bbs a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xfffffffd
+ movi a3, 0xffffff01
+ bbs a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bbsi
+ movi a2, 0x00020000
+ bbsi a2, 17, 1f
+ test_fail
+1:
+ movi a2, 0xfffdffff
+ bbsi a2, 17, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_bi.S b/src/tests/tcg/xtensa/test_bi.S
new file mode 100644
index 0000000..4f94c0c
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_bi.S
@@ -0,0 +1,103 @@
+#include "macros.inc"
+
+test_suite bi
+
+test beqi
+ movi a2, 7
+ beqi a2, 7, 1f
+ test_fail
+1:
+ movi a2, 1
+ beqi a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bnei
+ movi a2, 1
+ bnei a2, 7, 1f
+ test_fail
+1:
+ movi a2, 7
+ bnei a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test blti
+ movi a2, 6
+ blti a2, 7, 1f
+ test_fail
+1:
+ movi a2, 0xffffffff
+ blti a2, 7, 1f
+ test_fail
+1:
+ movi a2, 7
+ blti a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bgei
+ movi a2, 7
+ bgei a2, 7, 1f
+ test_fail
+1:
+ movi a2, 6
+ bgei a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+ movi a2, 0xffffffff
+ bgei a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bltui
+ movi a2, 6
+ bltui a2, 7, 1f
+ test_fail
+1:
+ movi a2, 7
+ bltui a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+ movi a2, 0xffffffff
+ bltui a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bgeui
+ movi a2, 7
+ bgeui a2, 7, 1f
+ test_fail
+1:
+ movi a2, 0xffffffff
+ bgeui a2, 7, 1f
+ test_fail
+1:
+ movi a2, 6
+ bgeui a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_boolean.S b/src/tests/tcg/xtensa/test_boolean.S
new file mode 100644
index 0000000..eac40e0
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_boolean.S
@@ -0,0 +1,23 @@
+#include "macros.inc"
+
+test_suite boolean
+
+test all4
+ movi a2, 0xfec0
+ wsr a2, br
+ all4 b0, b0
+ rsr a3, br
+ assert eq, a2, a3
+ all4 b0, b4
+ rsr a3, br
+ assert eq, a2, a3
+ all4 b0, b8
+ rsr a3, br
+ assert eq, a2, a3
+ all4 b0, b12
+ rsr a3, br
+ addi a2, a2, 1
+ assert eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_break.S b/src/tests/tcg/xtensa/test_break.S
new file mode 100644
index 0000000..775cd7c
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_break.S
@@ -0,0 +1,257 @@
+#include "macros.inc"
+
+#define debug_level 6
+#define debug_vector level6
+
+test_suite break
+
+test break
+ set_vector debug_vector, 0
+ rsil a2, debug_level
+ _break 0, 0
+
+ set_vector debug_vector, 2f
+ rsil a2, debug_level - 1
+1:
+ _break 0, 0
+ test_fail
+2:
+ rsr a2, ps
+ movi a3, 0x1f
+ and a2, a2, a3
+ movi a3, 0x10 | debug_level
+ assert eq, a2, a3
+ rsr a2, epc6
+ movi a3, 1b
+ assert eq, a2, a3
+ rsr a2, debugcause
+ movi a3, 0x8
+ assert eq, a2, a3
+test_end
+
+test breakn
+ set_vector debug_vector, 0
+ rsil a2, debug_level
+ _break.n 0
+
+ set_vector debug_vector, 2f
+ rsil a2, debug_level - 1
+1:
+ _break.n 0
+ test_fail
+2:
+ rsr a2, ps
+ movi a3, 0x1f
+ and a2, a2, a3
+ movi a3, 0x10 | debug_level
+ assert eq, a2, a3
+ rsr a2, epc6
+ movi a3, 1b
+ assert eq, a2, a3
+ rsr a2, debugcause
+ movi a3, 0x10
+ assert eq, a2, a3
+test_end
+
+test ibreak
+ set_vector debug_vector, 0
+ rsil a2, debug_level
+ movi a2, 1f
+ wsr a2, ibreaka0
+ movi a2, 1
+ wsr a2, ibreakenable
+ isync
+1:
+ rsil a2, debug_level - 1
+ movi a2, 1f
+ wsr a2, ibreaka0
+ movi a2, 0
+ wsr a2, ibreakenable
+ isync
+1:
+ set_vector debug_vector, 2f
+ movi a2, 1f
+ wsr a2, ibreaka0
+ movi a2, 1
+ wsr a2, ibreakenable
+ isync
+1:
+ test_fail
+2:
+ rsr a2, ps
+ movi a3, 0x1f
+ and a2, a2, a3
+ movi a3, 0x10 | debug_level
+ assert eq, a2, a3
+ rsr a2, epc6
+ movi a3, 1b
+ assert eq, a2, a3
+ rsr a2, debugcause
+ movi a3, 0x2
+ assert eq, a2, a3
+test_end
+
+test ibreak_remove
+ set_vector debug_vector, 3f
+ rsil a2, debug_level - 1
+ movi a2, 2f
+ wsr a2, ibreaka0
+ movi a3, 1
+1:
+ wsr a3, ibreakenable
+ isync
+2:
+ beqz a3, 4f
+ test_fail
+3:
+ assert eqi, a3, 1
+ rsr a2, ps
+ movi a3, 0x1f
+ and a2, a2, a3
+ movi a3, 0x10 | debug_level
+ assert eq, a2, a3
+ rsr a2, epc6
+ movi a3, 2b
+ assert eq, a2, a3
+ rsr a2, debugcause
+ movi a3, 0x2
+ assert eq, a2, a3
+
+ movi a2, 0x40000
+ wsr a2, ps
+ isync
+ movi a3, 0
+ j 1b
+4:
+test_end
+
+test ibreak_priority
+ set_vector debug_vector, 2f
+ rsil a2, debug_level - 1
+ movi a2, 1f
+ wsr a2, ibreaka0
+ movi a2, 1
+ wsr a2, ibreakenable
+ isync
+1:
+ break 0, 0
+ test_fail
+2:
+ rsr a2, debugcause
+ movi a3, 0x2
+ assert eq, a2, a3
+test_end
+
+test icount
+ set_vector debug_vector, 2f
+ rsil a2, debug_level - 1
+ movi a2, -2
+ wsr a2, icount
+ movi a2, 1
+ wsr a2, icountlevel
+ isync
+ rsil a2, 0
+ nop
+1:
+ break 0, 0
+ test_fail
+2:
+ movi a2, 0
+ wsr a2, icountlevel
+ rsr a2, epc6
+ movi a3, 1b
+ assert eq, a2, a3
+ rsr a2, debugcause
+ movi a3, 0x1
+ assert eq, a2, a3
+test_end
+
+.macro check_dbreak dr
+ rsr a2, epc6
+ movi a3, 1b
+ assert eq, a2, a3
+ rsr a2, debugcause
+ movi a3, 0x4 | (\dr << 8)
+ assert eq, a2, a3
+ movi a2, 0
+ wsr a2, dbreakc\dr
+.endm
+
+.macro dbreak_test dr, ctl, break, access, op
+ set_vector debug_vector, 2f
+ rsil a2, debug_level - 1
+ movi a2, \ctl
+ wsr a2, dbreakc\dr
+ movi a2, \break
+ wsr a2, dbreaka\dr
+ movi a2, \access
+ isync
+1:
+ \op a3, a2, 0
+ test_fail
+2:
+ check_dbreak \dr
+ reset_ps
+.endm
+
+test dbreak_exact
+ dbreak_test 0, 0x4000003f, 0xd000007f, 0xd000007f, l8ui
+ dbreak_test 1, 0x4000003e, 0xd000007e, 0xd000007e, l16ui
+ dbreak_test 0, 0x4000003c, 0xd000007c, 0xd000007c, l32i
+
+ dbreak_test 1, 0x8000003f, 0xd000007f, 0xd000007f, s8i
+ dbreak_test 0, 0x8000003e, 0xd000007e, 0xd000007e, s16i
+ dbreak_test 1, 0x8000003c, 0xd000007c, 0xd000007c, s32i
+test_end
+
+test dbreak_overlap
+ dbreak_test 0, 0x4000003f, 0xd000007d, 0xd000007c, l16ui
+ dbreak_test 1, 0x4000003f, 0xd000007d, 0xd000007c, l32i
+
+ dbreak_test 0, 0x4000003e, 0xd000007e, 0xd000007f, l8ui
+ dbreak_test 1, 0x4000003e, 0xd000007e, 0xd000007c, l32i
+
+ dbreak_test 0, 0x4000003c, 0xd000007c, 0xd000007d, l8ui
+ dbreak_test 1, 0x4000003c, 0xd000007c, 0xd000007c, l16ui
+
+ dbreak_test 0, 0x40000038, 0xd0000078, 0xd000007b, l8ui
+ dbreak_test 1, 0x40000038, 0xd0000078, 0xd000007a, l16ui
+ dbreak_test 0, 0x40000038, 0xd0000078, 0xd000007c, l32i
+
+ dbreak_test 1, 0x40000030, 0xd0000070, 0xd0000075, l8ui
+ dbreak_test 0, 0x40000030, 0xd0000070, 0xd0000076, l16ui
+ dbreak_test 1, 0x40000030, 0xd0000070, 0xd0000078, l32i
+
+ dbreak_test 0, 0x40000020, 0xd0000060, 0xd000006f, l8ui
+ dbreak_test 1, 0x40000020, 0xd0000060, 0xd0000070, l16ui
+ dbreak_test 0, 0x40000020, 0xd0000060, 0xd0000074, l32i
+
+
+ dbreak_test 0, 0x8000003f, 0xd000007d, 0xd000007c, s16i
+ dbreak_test 1, 0x8000003f, 0xd000007d, 0xd000007c, s32i
+
+ dbreak_test 0, 0x8000003e, 0xd000007e, 0xd000007f, s8i
+ dbreak_test 1, 0x8000003e, 0xd000007e, 0xd000007c, s32i
+
+ dbreak_test 0, 0x8000003c, 0xd000007c, 0xd000007d, s8i
+ dbreak_test 1, 0x8000003c, 0xd000007c, 0xd000007c, s16i
+
+ dbreak_test 0, 0x80000038, 0xd0000078, 0xd000007b, s8i
+ dbreak_test 1, 0x80000038, 0xd0000078, 0xd000007a, s16i
+ dbreak_test 0, 0x80000038, 0xd0000078, 0xd000007c, s32i
+
+ dbreak_test 1, 0x80000030, 0xd0000070, 0xd0000075, s8i
+ dbreak_test 0, 0x80000030, 0xd0000070, 0xd0000076, s16i
+ dbreak_test 1, 0x80000030, 0xd0000070, 0xd0000078, s32i
+
+ dbreak_test 0, 0x80000020, 0xd0000060, 0xd000006f, s8i
+ dbreak_test 1, 0x80000020, 0xd0000060, 0xd0000070, s16i
+ dbreak_test 0, 0x80000020, 0xd0000060, 0xd0000074, s32i
+test_end
+
+test dbreak_invalid
+ dbreak_test 0, 0x40000030, 0xd0000071, 0xd0000070, l16ui
+ dbreak_test 1, 0x40000035, 0xd0000072, 0xd0000070, l32i
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_bz.S b/src/tests/tcg/xtensa/test_bz.S
new file mode 100644
index 0000000..b681350
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_bz.S
@@ -0,0 +1,57 @@
+#include "macros.inc"
+
+test_suite bz
+
+test beqz
+ movi a2, 0
+ _beqz a2, 1f
+ test_fail
+1:
+ movi a2, 1
+ _beqz a2, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bnez
+ movi a2, 1
+ _bnez a2, 1f
+ test_fail
+1:
+ movi a2, 0
+ _bnez a2, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bltz
+ movi a2, 0xffffffff
+ bltz a2, 1f
+ test_fail
+1:
+ movi a2, 0
+ bltz a2, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bgez
+ movi a2, 0
+ bgez a2, 1f
+ test_fail
+1:
+ movi a2, 0xffffffff
+ bgez a2, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_cache.S b/src/tests/tcg/xtensa/test_cache.S
new file mode 100644
index 0000000..6b2df97
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_cache.S
@@ -0,0 +1,97 @@
+#include "macros.inc"
+
+.purgem test_init
+.macro test_init
+ call0 cache_unlock_invalidate
+.endm
+
+test_suite cache
+
+.macro pf_op op
+ \op a2, 0
+ \op a3, 0
+ \op a4, 0
+.endm
+
+test prefetch
+ movi a2, 0xd0000000 /* cacheable */
+ movi a3, 0xd8000000 /* non-cacheable */
+ movi a4, 0x00001235 /* unmapped */
+
+ pf_op dpfr
+ pf_op dpfro
+ pf_op dpfw
+ pf_op dpfwo
+ pf_op ipf
+
+ dpfl a2, 0
+ ipfl a2, 0
+test_end
+
+.macro cache_fault op, addr, exc_code
+ set_vector kernel, 2f
+
+ movi a4, \addr
+1:
+ \op a4, 0
+ test_fail
+2:
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+ rsr a2, excvaddr
+ assert eq, a2, a4
+ rsr a2, exccause
+ movi a3, \exc_code
+ assert eq, a2, a3
+.endm
+
+test dpfl_tlb_miss
+ cache_fault dpfl, 0x00002345, 24
+test_end
+
+test dhwb_tlb_miss
+ cache_fault dhwb, 0x00002345, 24
+test_end
+
+test dhwbi_tlb_miss
+ cache_fault dhwbi, 0x00002345, 24
+test_end
+
+test dhi_tlb_miss
+ cache_fault dhi, 0x00002345, 24
+test_end
+
+test dhu_tlb_miss
+ cache_fault dhu, 0x00002345, 24
+test_end
+
+
+test ipfl_tlb_miss
+ cache_fault ipfl, 0x00002345, 16
+test_end
+
+test ihu_tlb_miss
+ cache_fault ihu, 0x00002345, 16
+test_end
+
+test ihi_tlb_miss
+ cache_fault ihi, 0x00002345, 16
+test_end
+
+test_suite_end
+
+.macro cache_all op1, op2, size, linesize
+ movi a2, 0
+ movi a3, \size
+1:
+ \op1 a2, 0
+ \op2 a2, 0
+ addi a2, a2, \linesize
+ bltu a2, a3, 1b
+.endm
+
+cache_unlock_invalidate:
+ cache_all diu, dii, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE
+ cache_all iiu, iii, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE
+ ret
diff --git a/src/tests/tcg/xtensa/test_clamps.S b/src/tests/tcg/xtensa/test_clamps.S
new file mode 100644
index 0000000..3efabfd
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_clamps.S
@@ -0,0 +1,42 @@
+#include "macros.inc"
+
+test_suite clamps
+
+test clamps
+ movi a2, 0
+ movi a3, 0
+ clamps a4, a2, 7
+ assert eq, a3, a4
+
+ movi a2, 0x7f
+ movi a3, 0x7f
+ clamps a4, a2, 7
+ assert eq, a3, a4
+
+ movi a2, 0xffffff80
+ movi a3, 0xffffff80
+ clamps a4, a2, 7
+ assert eq, a3, a4
+
+ movi a2, 0x80
+ movi a3, 0x7f
+ clamps a2, a2, 7
+ assert eq, a3, a2
+
+ movi a2, 0xffffff7f
+ movi a3, 0xffffff80
+ clamps a2, a2, 7
+ assert eq, a3, a2
+
+ movi a2, 0x7fffffff
+ movi a3, 0x7f
+ clamps a2, a2, 7
+ assert eq, a3, a2
+
+ movi a2, 0x80000000
+ movi a3, 0xffffff80
+ clamps a2, a2, 7
+ assert eq, a3, a2
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_extui.S b/src/tests/tcg/xtensa/test_extui.S
new file mode 100644
index 0000000..c32bb82
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_extui.S
@@ -0,0 +1,26 @@
+#include "macros.inc"
+
+test_suite extui
+
+.macro test_extui v, shiftimm, maskimm
+ .if \shiftimm + \maskimm <= 32
+ movi a2, \v
+ extui a3, a2, \shiftimm, \maskimm
+ movi a4, ((\v) >> (\shiftimm)) & ((1 << (\maskimm)) - 1)
+ assert eq, a3, a4
+ .endif
+.endm
+
+test extui
+ .set shiftimm, 0
+ .rept 32
+ .set maskimm, 1
+ .rept 16
+ test_extui 0xc8df1370, shiftimm, maskimm
+ .set maskimm, maskimm + 1
+ .endr
+ .set shiftimm, shiftimm + 1
+ .endr
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_fail.S b/src/tests/tcg/xtensa/test_fail.S
new file mode 100644
index 0000000..1c26d50
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_fail.S
@@ -0,0 +1,9 @@
+#include "macros.inc"
+
+test_suite fail
+
+test fail
+ test_fail
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_interrupt.S b/src/tests/tcg/xtensa/test_interrupt.S
new file mode 100644
index 0000000..334ddab
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_interrupt.S
@@ -0,0 +1,194 @@
+#include "macros.inc"
+
+test_suite interrupt
+
+.macro clear_interrupts
+ movi a2, 0
+ wsr a2, intenable
+ wsr a2, ccompare0
+ wsr a2, ccompare1
+ wsr a2, ccompare2
+ esync
+ rsr a2, interrupt
+ wsr a2, intclear
+
+ esync
+ rsr a2, interrupt
+ assert eqi, a2, 0
+.endm
+
+.macro check_l1
+ rsr a2, ps
+ movi a3, 0x1f /* EXCM | INTMASK */
+ and a2, a2, a3
+ assert eqi, a2, 0x10 /* only EXCM is set for level-1 interrupt */
+ rsr a2, exccause
+ assert eqi, a2, 4
+.endm
+
+test rsil
+ clear_interrupts
+
+ rsr a2, ps
+ rsil a3, 7
+ rsr a4, ps
+ assert eq, a2, a3
+ movi a2, 0xf
+ and a2, a4, a2
+ assert eqi, a2, 7
+ xor a3, a3, a4
+ movi a2, 0xfffffff0
+ and a2, a3, a2
+ assert eqi, a2, 0
+test_end
+
+test soft_disabled
+ set_vector kernel, 1f
+ clear_interrupts
+
+ movi a2, 0x80
+ wsr a2, intset
+ esync
+ rsr a3, interrupt
+ assert eq, a2, a3
+ wsr a2, intclear
+ esync
+ rsr a3, interrupt
+ assert eqi, a3, 0
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test soft_intenable
+ set_vector kernel, 1f
+ clear_interrupts
+
+ movi a2, 0x80
+ wsr a2, intset
+ esync
+ rsr a3, interrupt
+ assert eq, a2, a3
+ rsil a3, 0
+ wsr a2, intenable
+ esync
+ test_fail
+1:
+ check_l1
+test_end
+
+test soft_rsil
+ set_vector kernel, 1f
+ clear_interrupts
+
+ movi a2, 0x80
+ wsr a2, intset
+ esync
+ rsr a3, interrupt
+ assert eq, a2, a3
+ wsr a2, intenable
+ rsil a3, 0
+ esync
+ test_fail
+1:
+ check_l1
+test_end
+
+test soft_waiti
+ set_vector kernel, 1f
+ clear_interrupts
+
+ movi a2, 0x80
+ wsr a2, intset
+ esync
+ rsr a3, interrupt
+ assert eq, a2, a3
+ wsr a2, intenable
+ waiti 0
+ test_fail
+1:
+ check_l1
+test_end
+
+test soft_user
+ set_vector kernel, 1f
+ set_vector user, 2f
+ clear_interrupts
+
+ movi a2, 0x80
+ wsr a2, intset
+ esync
+ rsr a3, interrupt
+ assert eq, a2, a3
+ wsr a2, intenable
+
+ rsr a2, ps
+ movi a3, 0x20
+ or a2, a2, a3
+ wsr a2, ps
+ waiti 0
+1:
+ test_fail
+2:
+ check_l1
+test_end
+
+test soft_priority
+ set_vector kernel, 1f
+ set_vector level3, 2f
+ clear_interrupts
+
+ movi a2, 0x880
+ wsr a2, intenable
+ rsil a3, 0
+ esync
+ wsr a2, intset
+ esync
+1:
+ test_fail
+2:
+ rsr a2, ps
+ movi a3, 0x1f /* EXCM | INTMASK */
+ and a2, a2, a3
+ movi a3, 0x13
+ assert eq, a2, a3 /* EXCM and INTMASK are set
+ for high-priority interrupt */
+test_end
+
+test eps_epc_rfi
+ set_vector level3, 3f
+ clear_interrupts
+ reset_ps
+
+ movi a2, 0x880
+ wsr a2, intenable
+ rsil a3, 0
+ rsr a3, ps
+ esync
+ wsr a2, intset
+1:
+ esync
+2:
+ test_fail
+3:
+ rsr a2, eps3
+ assert eq, a2, a3
+ rsr a2, epc3
+ movi a3, 1b
+ assert ge, a2, a3
+ movi a3, 2b
+ assert ge, a3, a2
+ movi a2, 4f
+ wsr a2, epc3
+ movi a2, 0x40003
+ wsr a2, eps3
+ rfi 3
+ test_fail
+4:
+ rsr a2, ps
+ movi a3, 0x40003
+ assert eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_loop.S b/src/tests/tcg/xtensa/test_loop.S
new file mode 100644
index 0000000..5755578
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_loop.S
@@ -0,0 +1,163 @@
+#include "macros.inc"
+
+test_suite loop
+
+test loop
+ movi a2, 0
+ movi a3, 5
+ loop a3, 1f
+ addi a2, a2, 1
+1:
+ assert eqi, a2, 5
+test_end
+
+test loop0
+ movi a2, 0
+ loop a2, 1f
+ rsr a2, lcount
+ assert eqi, a2, -1
+ j 1f
+1:
+test_end
+
+test loop_jump
+ movi a2, 0
+ movi a3, 5
+ loop a3, 1f
+ addi a2, a2, 1
+ j 1f
+1:
+ assert eqi, a2, 1
+test_end
+
+test loop_branch
+ movi a2, 0
+ movi a3, 5
+ loop a3, 1f
+ addi a2, a2, 1
+ beqi a2, 3, 1f
+1:
+ assert eqi, a2, 3
+test_end
+
+test loop_manual
+ movi a2, 0
+ movi a3, 5
+ movi a4, 1f
+ movi a5, 2f
+ wsr a3, lcount
+ wsr a4, lbeg
+ wsr a5, lend
+ isync
+ j 1f
+.align 4
+1:
+ addi a2, a2, 1
+2:
+ assert eqi, a2, 6
+test_end
+
+test loop_excm
+ movi a2, 0
+ movi a3, 5
+ rsr a4, ps
+ movi a5, 0x10
+ or a4, a4, a5
+ wsr a4, ps
+ isync
+ loop a3, 1f
+ addi a2, a2, 1
+1:
+ xor a4, a4, a5
+ isync
+ wsr a4, ps
+ assert eqi, a2, 1
+test_end
+
+test lbeg_invalidation
+ movi a2, 0
+ movi a3, 1
+ movi a4, 1f
+ movi a5, 3f
+ wsr a3, lcount
+ wsr a4, lbeg
+ wsr a5, lend
+ isync
+ j 1f
+.align 4
+1:
+ addi a2, a2, 1
+ j 2f
+.align 4
+2:
+ addi a2, a2, 2
+ movi a3, 2b
+ wsr a3, lbeg
+ isync
+ nop
+3:
+ assert eqi, a2, 5
+test_end
+
+test lend_invalidation
+ movi a2, 0
+ movi a3, 5
+ movi a4, 1f
+ movi a5, 2f
+ wsr a3, lcount
+ wsr a4, lbeg
+ wsr a5, lend
+ isync
+ j 1f
+.align 4
+1:
+ addi a2, a2, 1
+2:
+ beqi a3, 3, 1f
+ assert eqi, a2, 6
+ movi a3, 3
+ wsr a3, lcount
+ wsr a4, lend
+ isync
+ j 1b
+1:
+ assert eqi, a2, 7
+test_end
+
+test loopnez
+ movi a2, 0
+ movi a3, 5
+ loopnez a3, 1f
+ addi a2, a2, 1
+1:
+ assert eqi, a2, 5
+
+ movi a2, 0
+ movi a3, 0
+ loopnez a3, 1f
+ test_fail
+1:
+test_end
+
+test loopgtz
+ movi a2, 0
+ movi a3, 5
+ loopgtz a3, 1f
+ addi a2, a2, 1
+1:
+ assert eqi, a2, 5
+
+ movi a2, 0
+ movi a3, 0
+ loopgtz a3, 1f
+ test_fail
+1:
+
+ movi a2, 0
+ movi a3, 0x80000000
+ loopgtz a3, 1f
+ test_fail
+1:
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_mac16.S b/src/tests/tcg/xtensa/test_mac16.S
new file mode 100644
index 0000000..512025d
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_mac16.S
@@ -0,0 +1,243 @@
+#include "macros.inc"
+
+test_suite mac16
+
+#define ext16(v) (((v) & 0xffff) | (((v) & 0x8000) * 0x1ffffffe))
+#define mul16(a, b) ((ext16(a) * ext16(b)))
+
+.macro assert_acc_value v
+ rsr a4, ACCLO
+ movi a5, (\v) & 0xffffffff
+ assert eq, a4, a5
+ rsr a4, ACCHI
+ movi a5, (\v) >> 32
+ sext a5, a5, 7
+ assert eq, a4, a5
+.endm
+
+.macro init_reg sr, reg, val
+ .if (\sr)
+ movi a4, \val
+ wsr a4, \reg
+ .else
+ movi \reg, \val
+ .endif
+.endm
+
+.macro test_mulxx mulop, comb, s, t, a, b
+ init_reg \comb & 2, \s, \a
+ init_reg \comb & 1, \t, \b
+
+ \mulop\().ll \s, \t
+ assert_acc_value mul16(\a, \b)
+
+ \mulop\().lh \s, \t
+ assert_acc_value mul16(\a, (\b >> 16))
+
+ \mulop\().hl \s, \t
+ assert_acc_value mul16((\a >> 16), \b)
+
+ \mulop\().hh \s, \t
+ assert_acc_value mul16((\a >> 16), (\b >> 16))
+.endm
+
+test mul_aa
+ test_mulxx mul.aa, 0, a2, a3, 0xf7315a5a, 0xa5a5137f
+test_end
+
+test mul_ad
+ test_mulxx mul.ad, 1, a2, m2, 0xf7315a5a, 0xa5a5137f
+test_end
+
+test mul_da
+ test_mulxx mul.da, 2, m1, a3, 0xf7315a5a, 0xa5a5137f
+test_end
+
+test mul_dd
+ test_mulxx mul.dd, 3, m0, m3, 0xf7315a5a, 0xa5a5137f
+test_end
+
+
+.macro init_acc iv
+ movi a4, (\iv) & 0xffffffff
+ wsr a4, ACCLO
+ movi a4, (\iv) >> 32
+ wsr a4, ACCHI
+.endm
+
+.macro test_mulxxx mulop, comb, s, t, a, b, iv, op
+ init_reg \comb & 2, \s, \a
+ init_reg \comb & 1, \t, \b
+
+ init_acc \iv
+ \mulop\().ll \s, \t
+ assert_acc_value (\iv \op mul16(\a, \b))
+
+ init_acc \iv
+ \mulop\().lh \s, \t
+ assert_acc_value (\iv \op mul16(\a, (\b >> 16)))
+
+ init_acc \iv
+ \mulop\().hl \s, \t
+ assert_acc_value (\iv \op mul16((\a >> 16), \b))
+
+ init_acc \iv
+ \mulop\().hh \s, \t
+ assert_acc_value (\iv \op mul16((\a >> 16), (\b >> 16)))
+.endm
+
+
+test mula_aa
+ test_mulxxx mula.aa, 0, a2, a3, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, +
+test_end
+
+test mula_ad
+ test_mulxxx mula.ad, 1, a2, m2, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, +
+test_end
+
+test mula_da
+ test_mulxxx mula.da, 2, m1, a3, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+test_end
+
+test mula_dd
+ test_mulxxx mula.dd, 3, m0, m3, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+test_end
+
+
+test muls_aa
+ test_mulxxx muls.aa, 0, a2, a3, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, -
+test_end
+
+test muls_ad
+ test_mulxxx muls.ad, 1, a2, m2, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, -
+test_end
+
+test muls_da
+ test_mulxxx muls.da, 2, m1, a3, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, -
+test_end
+
+test muls_dd
+ test_mulxxx muls.dd, 3, m0, m3, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, -
+test_end
+
+test ldinc
+ movi a2, 1f - 4
+ ldinc m0, a2
+ movi a3, 1f
+ assert eq, a2, a3
+ rsr a3, m0
+ movi a4, 0x55aa137f
+ assert eq, a3, a4
+ ldinc m1, a2
+ movi a3, 1f + 4
+ assert eq, a2, a3
+ rsr a3, m1
+ movi a4, 0x12345678
+ assert eq, a3, a4
+
+.data
+1: .word 0x55aa137f, 0x12345678, 0x137fa5a5
+.text
+test_end
+
+test lddec
+ movi a2, 1f
+ lddec m2, a2
+ movi a3, 1f - 4
+ assert eq, a2, a3
+ rsr a3, m2
+ movi a4, 0x12345678
+ assert eq, a3, a4
+ lddec m3, a2
+ movi a3, 1f - 8
+ assert eq, a2, a3
+ rsr a3, m3
+ movi a4, 0x55aa137f
+ assert eq, a3, a4
+.data
+ .word 0x55aa137f, 0x12345678
+1:
+.text
+test_end
+
+
+.macro test_mulxxx_ld mulop, ldop, comb, w, x, s, t, a, b, iv, op
+ init_reg \comb & 2, \s, \a
+ init_reg \comb & 1, \t, \b
+
+ init_acc \iv
+ \mulop\().ll.\ldop \w, \x, \s, \t
+ assert_acc_value (\iv \op mul16(\a, \b))
+
+ init_acc \iv
+ \mulop\().lh.\ldop \w, \x, \s, \t
+ assert_acc_value (\iv \op mul16(\a, (\b >> 16)))
+
+ init_acc \iv
+ \mulop\().hl.\ldop \w, \x, \s, \t
+ assert_acc_value (\iv \op mul16((\a >> 16), \b))
+
+ init_acc \iv
+ \mulop\().hh.\ldop \w, \x, \s, \t
+ assert_acc_value (\iv \op mul16((\a >> 16), (\b >> 16)))
+.endm
+
+test mula_da_ldinc
+ movi a2, 1f - 4
+ test_mulxxx_ld mula.da, ldinc, 2, m1, a2, m1, a3, \
+ 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+ movi a3, 1f + 12
+ assert eq, a2, a3
+ rsr a2, m1
+ movi a3, 0x12345678
+ assert eq, a2, a3
+.data
+1: .word 0xf7315a5a, 0xf7315a5a, 0xf7315a5a, 0x12345678
+.text
+test_end
+
+test mula_dd_ldinc
+ movi a2, 1f - 4
+ test_mulxxx_ld mula.dd, ldinc, 3, m2, a2, m1, m2, \
+ 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+ movi a3, 1f + 12
+ assert eq, a2, a3
+ rsr a2, m2
+ movi a3, 0x12345678
+ assert eq, a2, a3
+.data
+1: .word 0xa5a5137f, 0xa5a5137f, 0xa5a5137f, 0x12345678
+.text
+test_end
+
+test mula_da_lddec
+ movi a2, 1f
+ test_mulxxx_ld mula.da, lddec, 2, m1, a2, m1, a3, \
+ 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+ movi a3, 1f - 16
+ assert eq, a2, a3
+ rsr a2, m1
+ movi a3, 0x12345678
+ assert eq, a2, a3
+.data
+ .word 0x12345678, 0xf7315a5a, 0xf7315a5a, 0xf7315a5a
+1:
+.text
+test_end
+
+test mula_dd_lddec
+ movi a2, 1f
+ test_mulxxx_ld mula.dd, lddec, 3, m2, a2, m1, m2, \
+ 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+ movi a3, 1f - 16
+ assert eq, a2, a3
+ rsr a2, m2
+ movi a3, 0x12345678
+ assert eq, a2, a3
+.data
+ .word 0x12345678, 0xa5a5137f, 0xa5a5137f, 0xa5a5137f
+1:
+.text
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_max.S b/src/tests/tcg/xtensa/test_max.S
new file mode 100644
index 0000000..3caa207
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_max.S
@@ -0,0 +1,81 @@
+#include "macros.inc"
+
+test_suite max
+
+test max
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 1
+ max a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 1
+ max a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 1
+ max a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 1
+ max a3, a2, a3
+ assert eq, a3, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 1
+ max a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 1
+ max a3, a2, a3
+ assert eq, a3, a4
+test_end
+
+test maxu
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 0xffffffff
+ maxu a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 0xffffffff
+ maxu a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 0xffffffff
+ maxu a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 0xffffffff
+ maxu a3, a2, a3
+ assert eq, a3, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 0xffffffff
+ maxu a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 0xffffffff
+ maxu a3, a2, a3
+ assert eq, a3, a4
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_min.S b/src/tests/tcg/xtensa/test_min.S
new file mode 100644
index 0000000..551cf59
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_min.S
@@ -0,0 +1,81 @@
+#include "macros.inc"
+
+test_suite min
+
+test min
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 0xffffffff
+ min a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 0xffffffff
+ min a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 0xffffffff
+ min a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 0xffffffff
+ min a3, a2, a3
+ assert eq, a3, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 0xffffffff
+ min a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 0xffffffff
+ min a3, a2, a3
+ assert eq, a3, a4
+test_end
+
+test minu
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 1
+ minu a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 1
+ minu a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 1
+ minu a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 1
+ minu a3, a2, a3
+ assert eq, a3, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 1
+ minu a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 1
+ minu a3, a2, a3
+ assert eq, a3, a4
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_mmu.S b/src/tests/tcg/xtensa/test_mmu.S
new file mode 100644
index 0000000..a15316f
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_mmu.S
@@ -0,0 +1,743 @@
+#include "macros.inc"
+
+test_suite mmu
+
+.purgem test_init
+
+.macro clean_tlb_way way, page_size, n_entries
+ movi a2, \way
+ movi a3, \page_size
+ movi a4, \n_entries
+ loop a4, 1f
+ idtlb a2
+ iitlb a2
+ add a2, a2, a3
+1:
+.endm
+
+.macro test_init
+ clean_tlb_way 0, 0x00001000, 4
+ clean_tlb_way 1, 0x00001000, 4
+ clean_tlb_way 2, 0x00001000, 4
+ clean_tlb_way 3, 0x00001000, 4
+ clean_tlb_way 4, 0x00100000, 4
+ movi a2, 0x00000007
+ idtlb a2
+ movi a2, 0x00000008
+ idtlb a2
+ movi a2, 0x00000009
+ idtlb a2
+.endm
+
+test tlb_group
+ movi a2, 0x04000002 /* PPN */
+ movi a3, 0x01200004 /* VPN */
+ wdtlb a2, a3
+ witlb a2, a3
+ movi a3, 0x00200004
+ rdtlb0 a1, a3
+ ritlb0 a2, a3
+ movi a3, 0x01000001
+ assert eq, a1, a3
+ assert eq, a2, a3
+ movi a3, 0x00200004
+ rdtlb1 a1, a3
+ ritlb1 a2, a3
+ movi a3, 0x04000002
+ assert eq, a1, a3
+ assert eq, a2, a3
+ movi a3, 0x01234567
+ pdtlb a1, a3
+ pitlb a2, a3
+ movi a3, 0x01234014
+ assert eq, a1, a3
+ movi a3, 0x0123400c
+ assert eq, a2, a3
+ movi a3, 0x00200004
+ idtlb a3
+ iitlb a3
+ movi a3, 0x01234567
+ pdtlb a1, a3
+ pitlb a2, a3
+ movi a3, 0x00000010
+ and a1, a1, a3
+ assert eqi, a1, 0
+ movi a3, 0x00000008
+ and a2, a2, a3
+ assert eqi, a2, 0
+test_end
+
+test itlb_miss
+ set_vector kernel, 1f
+
+ movi a3, 0x00100000
+ jx a3
+ test_fail
+1:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+ rsr a2, exccause
+ movi a3, 16
+ assert eq, a2, a3
+test_end
+
+test dtlb_miss
+ set_vector kernel, 1f
+
+ movi a3, 0x00100000
+ l8ui a2, a3, 0
+ test_fail
+1:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+ rsr a2, exccause
+ movi a3, 24
+ assert eq, a2, a3
+test_end
+
+test itlb_multi_hit
+ set_vector kernel, 1f
+
+ movi a2, 0x04000002 /* PPN */
+ movi a3, 0xf0000004 /* VPN */
+ witlb a2, a3
+ movi a3, 0xf0000000
+ pitlb a2, a3
+ test_fail
+1:
+ rsr a2, exccause
+ movi a3, 17
+ assert eq, a2, a3
+test_end
+
+test dtlb_multi_hit
+ set_vector kernel, 1f
+
+ movi a2, 0x04000002 /* PPN */
+ movi a3, 0x01200004 /* VPN */
+ wdtlb a2, a3
+ movi a3, 0x01200007 /* VPN */
+ wdtlb a2, a3
+ movi a3, 0x01200000
+ pdtlb a2, a3
+ test_fail
+1:
+ rsr a2, exccause
+ movi a3, 25
+ assert eq, a2, a3
+test_end
+
+test inst_fetch_privilege
+ set_vector kernel, 3f
+
+ movi a2, 0x4004f
+ wsr a2, ps
+1:
+ isync
+ nop
+2:
+ test_fail
+3:
+ movi a1, 1b
+ rsr a2, excvaddr
+ rsr a3, epc1
+ assert ge, a2, a1
+ assert ge, a3, a1
+ movi a1, 2b
+ assert lt, a2, a1
+ assert lt, a3, a1
+ rsr a2, exccause
+ movi a3, 18
+ assert eq, a2, a3
+ rsr a2, ps
+ movi a3, 0x4005f
+ assert eq, a2, a3
+test_end
+
+test load_store_privilege
+ set_vector kernel, 2f
+
+ movi a3, 10f
+ pitlb a3, a3
+ ritlb1 a2, a3
+ movi a1, 0x10
+ or a2, a2, a1
+ movi a1, 0x000ff000
+ and a3, a3, a1
+ movi a1, 4
+ or a3, a3, a1
+ witlb a2, a3
+ movi a3, 10f
+ movi a1, 0x000fffff
+ and a1, a3, a1
+
+ movi a2, 0x04000003 /* PPN */
+ movi a3, 0x01200004 /* VPN */
+ wdtlb a2, a3
+ movi a3, 0x01200001
+ movi a2, 0x4004f
+ jx a1
+10:
+ wsr a2, ps
+ isync
+1:
+ l8ui a2, a3, 0
+ test_fail
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 1b
+ movi a1, 0x000fffff
+ and a3, a3, a1
+ assert eq, a2, a3
+ rsr a2, exccause
+ movi a3, 26
+ assert eq, a2, a3
+ rsr a2, ps
+ movi a3, 0x4005f
+ assert eq, a2, a3
+test_end
+
+test cring_load_store_privilege
+ set_vector kernel, 0
+ set_vector double, 2f
+
+ movi a2, 0x04000003 /* PPN */
+ movi a3, 0x01200004 /* VPN */
+ wdtlb a2, a3
+ movi a3, 0x01200004
+ movi a2, 0x4005f /* ring 1 + excm => cring == 0 */
+ wsr a2, ps
+ isync
+ l8ui a2, a3, 0 /* cring used */
+1:
+ l32e a2, a3, -4 /* ring used */
+ test_fail
+2:
+ rsr a2, excvaddr
+ addi a2, a2, 4
+ assert eq, a2, a3
+ rsr a2, depc
+ movi a3, 1b
+ assert eq, a2, a3
+ rsr a2, exccause
+ movi a3, 26
+ assert eq, a2, a3
+ rsr a2, ps
+ movi a3, 0x4005f
+ assert eq, a2, a3
+test_end
+
+test inst_fetch_prohibited
+ set_vector kernel, 2f
+
+ movi a3, 10f
+ pitlb a3, a3
+ ritlb1 a2, a3
+ movi a1, 0xfffff000
+ and a2, a2, a1
+ movi a1, 0x4
+ or a2, a2, a1
+ movi a1, 0x000ff000
+ and a3, a3, a1
+ movi a1, 4
+ or a3, a3, a1
+ witlb a2, a3
+ movi a3, 10f
+ movi a1, 0x000fffff
+ and a1, a3, a1
+ jx a1
+ .align 4
+10:
+ nop
+ test_fail
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a1
+ rsr a2, epc1
+ assert eq, a2, a1
+ rsr a2, exccause
+ movi a3, 20
+ assert eq, a2, a3
+test_end
+
+test load_prohibited
+ set_vector kernel, 2f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x01200004 /* VPN */
+ wdtlb a2, a3
+ movi a3, 0x01200002
+1:
+ l8ui a2, a3, 0
+ test_fail
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+ rsr a2, exccause
+ movi a3, 28
+ assert eq, a2, a3
+test_end
+
+test store_prohibited
+ set_vector kernel, 2f
+
+ movi a2, 0x04000001 /* PPN */
+ movi a3, 0x01200004 /* VPN */
+ wdtlb a2, a3
+ movi a3, 0x01200003
+ l8ui a2, a3, 0
+1:
+ s8i a2, a3, 0
+ test_fail
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+ rsr a2, exccause
+ movi a3, 29
+ assert eq, a2, a3
+test_end
+
+/* Set up page table entry vaddr->paddr, ring=pte_ring, attr=pte_attr
+ * and DTLB way 7 to cover this PTE, ring=pt_ring, attr=pt_attr
+ */
+.macro pt_setup pt_ring, pt_attr, pte_ring, vaddr, paddr, pte_attr
+ movi a2, 0x80000000
+ wsr a2, ptevaddr
+
+ movi a3, 0x80000007 | (((\vaddr) >> 10) & 0xfffff000) /* way 7 */
+ movi a4, 0x04000003 | ((\pt_ring) << 4) /* PADDR 64M */
+ wdtlb a4, a3
+ isync
+
+ movi a3, ((\paddr) & 0xfffff000) | ((\pte_ring) << 4) | (\pte_attr)
+ movi a1, ((\vaddr) >> 12) << 2
+ add a2, a1, a2
+ s32i a3, a2, 0
+
+ movi a3, 0x80000007 | (((\vaddr) >> 10) & 0xfffff000) /* way 7 */
+ movi a4, 0x04000000 | ((\pt_ring) << 4) | (\pt_attr) /* PADDR 64M */
+ wdtlb a4, a3
+ isync
+
+ movi a3, (\vaddr)
+.endm
+
+/* out: PS.RING=ring, PS.EXCM=excm, a3=vaddr */
+.macro go_ring ring, excm, vaddr
+ movi a3, 10f
+ pitlb a3, a3
+ ritlb1 a2, a3
+ movi a1, 0x10
+ or a2, a2, a1
+ movi a1, 0x000ff000
+ and a3, a3, a1
+ movi a1, 4
+ or a3, a3, a1
+ witlb a2, a3
+ movi a3, 10f
+ movi a1, 0x000fffff
+ and a1, a3, a1
+
+ movi a2, 0
+ wsr a2, excvaddr
+
+ movi a3, \vaddr
+ movi a2, 0x4000f | ((\ring) << 6) | ((\excm) << 4)
+ jx a1
+10:
+ wsr a2, ps
+ isync
+.endm
+
+/* in: a3 -- virtual address to test */
+.macro assert_auto_tlb
+ movi a2, 0x4000f
+ wsr a2, ps
+ isync
+ pdtlb a2, a3
+ movi a1, 0xfffff01f
+ and a2, a2, a1
+ movi a1, 0xfffff000
+ and a1, a1, a3
+ xor a1, a1, a2
+ assert gei, a1, 0x10
+ movi a2, 0x14
+ assert lt, a1, a2
+.endm
+
+/* in: a3 -- virtual address to test */
+.macro assert_no_auto_tlb
+ movi a2, 0x4000f
+ wsr a2, ps
+ isync
+ pdtlb a2, a3
+ movi a1, 0x10
+ and a1, a1, a2
+ assert eqi, a1, 0
+.endm
+
+.macro assert_sr sr, v
+ rsr a2, \sr
+ movi a1, (\v)
+ assert eq, a1, a2
+.endm
+
+.macro assert_epc1_1m vaddr
+ movi a2, (\vaddr)
+ movi a1, 0xfffff
+ and a1, a1, a2
+ rsr a2, epc1
+ assert eq, a1, a2
+.endm
+
+test dtlb_autoload
+ set_vector kernel, 0
+
+ pt_setup 0, 3, 1, 0x1000, 0x1000, 3
+ assert_no_auto_tlb
+
+ l8ui a1, a3, 0
+
+ rsr a2, excvaddr
+ assert eq, a2, a3
+
+ assert_auto_tlb
+test_end
+
+test autoload_load_store_privilege
+ set_vector kernel, 0
+ set_vector double, 2f
+
+ pt_setup 0, 3, 0, 0x2000, 0x2000, 3
+ movi a3, 0x2004
+ assert_no_auto_tlb
+
+ movi a2, 0x4005f /* ring 1 + excm => cring == 0 */
+ wsr a2, ps
+ isync
+1:
+ l32e a2, a3, -4 /* ring used */
+ test_fail
+2:
+ rsr a2, excvaddr
+ addi a1, a3, -4
+ assert eq, a1, a2
+
+ assert_auto_tlb
+ assert_sr depc, 1b
+ assert_sr exccause, 26
+test_end
+
+test autoload_pte_load_prohibited
+ set_vector kernel, 2f
+
+ pt_setup 0, 3, 0, 0x3000, 0, 0xc
+ assert_no_auto_tlb
+1:
+ l32i a2, a3, 0
+ test_fail
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+
+ assert_auto_tlb
+ assert_sr epc1, 1b
+ assert_sr exccause, 28
+test_end
+
+test autoload_pt_load_prohibited
+ set_vector kernel, 2f
+
+ pt_setup 0, 0xc, 0, 0x4000, 0x4000, 3
+ assert_no_auto_tlb
+1:
+ l32i a2, a3, 0
+ test_fail
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+
+ assert_no_auto_tlb
+ assert_sr epc1, 1b
+ assert_sr exccause, 24
+test_end
+
+test autoload_pt_privilege
+ set_vector kernel, 2f
+ pt_setup 0, 3, 1, 0x5000, 0, 3
+ go_ring 1, 0, 0x5001
+
+ l8ui a2, a3, 0
+1:
+ syscall
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+
+ assert_auto_tlb
+ assert_epc1_1m 1b
+ assert_sr exccause, 1
+test_end
+
+test autoload_pte_privilege
+ set_vector kernel, 2f
+ pt_setup 0, 3, 0, 0x6000, 0, 3
+ go_ring 1, 0, 0x6001
+1:
+ l8ui a2, a3, 0
+ syscall
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+
+ assert_auto_tlb
+ assert_epc1_1m 1b
+ assert_sr exccause, 26
+test_end
+
+test autoload_3_level_pt
+ set_vector kernel, 2f
+ pt_setup 1, 3, 1, 0x00400000, 0, 3
+ pt_setup 1, 3, 1, 0x80001000, 0x2000000, 3
+ go_ring 1, 0, 0x00400001
+1:
+ l8ui a2, a3, 0
+ syscall
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+
+ assert_no_auto_tlb
+ assert_epc1_1m 1b
+ assert_sr exccause, 24
+test_end
+
+test cross_page_insn
+ set_vector kernel, 2f
+
+ movi a2, 0x04000003 /* PPN */
+ movi a3, 0x00007000 /* VPN */
+ witlb a2, a3
+ wdtlb a2, a3
+ movi a3, 0x00008000 /* VPN */
+ witlb a2, a3
+ wdtlb a2, a3
+
+ movi a2, 0x00007fff
+ movi a3, 20f
+ movi a4, 21f
+ sub a4, a4, a3
+ loop a4, 1f
+ l8ui a5, a3, 0
+ s8i a5, a2, 0
+ addi a2, a2, 1
+ addi a3, a3, 1
+1:
+ movi a2, 0x00007fff
+ movi a3, 0x00008000
+ /* DTLB: OK, ITLB: OK */
+ jx a2
+
+ .begin no-transform
+20:
+ l32i a2, a3, 0
+ syscall
+21:
+ .end no-transform
+
+2:
+ rsr a2, exccause
+ movi a3, 1
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x8002
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007fff
+ assert ne, a2, a3
+
+ reset_ps
+ set_vector kernel, 3f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x00008000 /* VPN */
+ wdtlb a2, a3
+ movi a2, 0x00007fff
+ movi a3, 0x00008000
+ /* DTLB: FAIL, ITLB: OK */
+ jx a2
+3:
+ rsr a2, exccause
+ movi a3, 28
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x7fff
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007fff
+ assert eq, a2, a3
+
+ reset_ps
+ set_vector kernel, 4f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x00008000 /* VPN */
+ witlb a2, a3
+ movi a2, 0x04000003 /* PPN */
+ wdtlb a2, a3
+ movi a2, 0x00007fff
+ movi a3, 0x00008000
+ /* DTLB: OK, ITLB: FAIL */
+ jx a2
+4:
+ rsr a2, exccause
+ movi a3, 20
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x7fff
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007fff
+ assert eq, a2, a3
+
+ reset_ps
+ set_vector kernel, 5f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x00008000 /* VPN */
+ wdtlb a2, a3
+ movi a2, 0x00007fff
+ movi a3, 0x00008000
+ /* DTLB: FAIL, ITLB: FAIL */
+ jx a2
+5:
+ rsr a2, exccause
+ movi a3, 20
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x7fff
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007fff
+ assert eq, a2, a3
+test_end
+
+test cross_page_tb
+ set_vector kernel, 2f
+
+ movi a2, 0x04000003 /* PPN */
+ movi a3, 0x00007000 /* VPN */
+ witlb a2, a3
+ wdtlb a2, a3
+ movi a3, 0x00008000 /* VPN */
+ witlb a2, a3
+ wdtlb a2, a3
+
+ movi a2, 0x00007ffc
+ movi a3, 20f
+ movi a4, 21f
+ sub a4, a4, a3
+ loop a4, 1f
+ l8ui a5, a3, 0
+ s8i a5, a2, 0
+ addi a2, a2, 1
+ addi a3, a3, 1
+1:
+ movi a2, 0x00007ffc
+ movi a3, 0x00008000
+ /* DTLB: OK, ITLB: OK */
+ jx a2
+
+ .begin no-transform
+20:
+ l32i a2, a3, 0
+ syscall
+21:
+ .end no-transform
+
+2:
+ rsr a2, exccause
+ movi a3, 1
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x7fff
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007ffc
+ assert ne, a2, a3
+
+ reset_ps
+ set_vector kernel, 3f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x00008000 /* VPN */
+ wdtlb a2, a3
+ movi a2, 0x00007ffc
+ movi a3, 0x00008000
+ /* DTLB: FAIL, ITLB: OK */
+ jx a2
+3:
+ rsr a2, exccause
+ movi a3, 28
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x7ffc
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007ffc
+ assert eq, a2, a3
+
+ reset_ps
+ set_vector kernel, 4f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x00008000 /* VPN */
+ witlb a2, a3
+ movi a2, 0x04000003 /* PPN */
+ wdtlb a2, a3
+ movi a2, 0x00007ffc
+ movi a3, 0x00008000
+ /* DTLB: OK, ITLB: FAIL */
+ jx a2
+4:
+ rsr a2, exccause
+ movi a3, 20
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x7fff
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007ffc
+ assert ne, a2, a3
+
+ reset_ps
+ set_vector kernel, 5f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x00008000 /* VPN */
+ wdtlb a2, a3
+ movi a2, 0x00007ffc
+ movi a3, 0x00008000
+ /* DTLB: FAIL, ITLB: FAIL */
+ jx a2
+5:
+ rsr a2, exccause
+ movi a3, 28
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x7ffc
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007ffc
+ assert eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_mul16.S b/src/tests/tcg/xtensa/test_mul16.S
new file mode 100644
index 0000000..98fa704
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_mul16.S
@@ -0,0 +1,83 @@
+#include "macros.inc"
+
+test_suite mul16
+
+test mul16u_pp
+ movi a2, 0x137f5a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x06e180a6
+ mul16u a5, a2, a4
+ assert eq, a5, a6
+ mul16u a2, a2, a4
+ assert eq, a2, a6
+ mul16u a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test mul16u_np
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x0c9d6bdb
+ mul16u a5, a2, a4
+ assert eq, a5, a6
+ mul16u a2, a2, a4
+ assert eq, a2, a6
+ mul16u a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test mul16u_nn
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5f731
+ movi a6, 0x9ff1e795
+ mul16u a5, a2, a4
+ assert eq, a5, a6
+ mul16u a2, a2, a4
+ assert eq, a2, a6
+ mul16u a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test mul16s_pp
+ movi a2, 0x137f5a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x06e180a6
+ mul16s a5, a2, a4
+ assert eq, a5, a6
+ mul16s a2, a2, a4
+ assert eq, a2, a6
+ mul16s a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test mul16s_np
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xf91e6bdb
+ mul16s a5, a2, a4
+ assert eq, a5, a6
+ mul16s a2, a2, a4
+ assert eq, a2, a6
+ mul16s a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test mul16s_nn
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5f731
+ movi a6, 0x031be795
+ mul16s a5, a2, a4
+ assert eq, a5, a6
+ mul16s a2, a2, a4
+ assert eq, a2, a6
+ mul16s a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_mul32.S b/src/tests/tcg/xtensa/test_mul32.S
new file mode 100644
index 0000000..b288ead
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_mul32.S
@@ -0,0 +1,20 @@
+#include "macros.inc"
+
+test_suite mul32
+
+test mull
+ movi a2, 0x137f5a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x5de480a6
+ mull a5, a2, a4
+ assert eq, a5, a6
+ mull a2, a2, a4
+ assert eq, a2, a6
+ mull a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+/* unfortunately dc232b doesn't have muluh/mulsh*/
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_nsa.S b/src/tests/tcg/xtensa/test_nsa.S
new file mode 100644
index 0000000..479b2e2
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_nsa.S
@@ -0,0 +1,59 @@
+#include "macros.inc"
+
+test_suite nsa
+
+test nsa
+ movi a2, 0
+ movi a3, 31
+ nsa a4, a2
+ assert eq, a3, a4
+
+ movi a2, 0xffffffff
+ movi a3, 31
+ nsa a4, a2
+ assert eq, a3, a4
+
+ movi a2, 1
+ movi a3, 30
+ nsa a2, a2
+ assert eq, a3, a2
+
+ movi a2, 0xfffffffe
+ movi a3, 30
+ nsa a2, a2
+ assert eq, a3, a2
+
+ movi a2, 0x5a5a5a5a
+ movi a3, 0
+ nsa a4, a2
+ assert eq, a3, a4
+
+ movi a2, 0xa5a5a5a5
+ movi a3, 0
+ nsa a4, a2
+ assert eq, a3, a4
+test_end
+
+test nsau
+ movi a2, 0
+ movi a3, 32
+ nsau a4, a2
+ assert eq, a3, a4
+
+ movi a2, 0xffffffff
+ movi a3, 0
+ nsau a4, a2
+ assert eq, a3, a4
+
+ movi a2, 1
+ movi a3, 31
+ nsau a2, a2
+ assert eq, a3, a2
+
+ movi a2, 0x5a5a5a5a
+ movi a3, 1
+ nsau a2, a2
+ assert eq, a3, a2
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_pipeline.S b/src/tests/tcg/xtensa/test_pipeline.S
new file mode 100644
index 0000000..f418c11
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_pipeline.S
@@ -0,0 +1,157 @@
+#include "macros.inc"
+
+.purgem test
+.macro test name
+ movi a2, 1f
+ movi a3, 99f
+0:
+ ipf a2, 0
+ ipf a2, 4
+ ipf a2, 8
+ ipf a2, 12
+ addi a2, a2, 16
+ blt a2, a3, 0b
+ j 1f
+ .align 4
+1:
+.endm
+
+test_suite pipeline
+
+test register_no_stall
+ rsr a3, ccount
+ add a5, a6, a6
+ add a6, a5, a5
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 3
+test_end
+
+test register_stall
+ l32i a5, a1, 0 /* data cache preload */
+ nop
+ rsr a3, ccount
+ l32i a5, a1, 0
+ add a6, a5, a5 /* M-to-E interlock */
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 4
+test_end
+
+test j0_stall
+ rsr a3, ccount
+ j 1f /* E + 2-cycle penalty */
+1:
+ rsr a4, ccount /* E */
+ sub a3, a4, a3
+ assert eqi, a3, 4
+test_end
+
+test j1_stall
+ rsr a3, ccount
+ j 1f
+ nop
+1:
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 4
+test_end
+
+test j5_stall
+ rsr a3, ccount
+ j 1f
+ nop
+ nop
+ nop
+ nop
+ nop
+1:
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 4
+test_end
+
+test b_no_stall
+ movi a5, 1
+ rsr a3, ccount
+ beqi a5, 2, 1f
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 2
+1:
+test_end
+
+test b1_stall
+ movi a5, 1
+ rsr a3, ccount
+ beqi a5, 1, 1f
+ nop
+1:
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 4
+test_end
+
+test b5_stall
+ movi a5, 1
+ rsr a3, ccount
+ beqi a5, 1, 1f
+ nop
+ nop
+ nop
+ nop
+ nop
+1:
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 4
+test_end
+
+/* PS *SYNC */
+
+test ps_dsync
+ rsr a5, ps
+ isync
+ rsr a3, ccount
+ wsr a5, ps
+ dsync
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 5
+test_end
+
+test ps_esync
+ rsr a5, ps
+ isync
+ rsr a3, ccount
+ wsr a5, ps
+ esync
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 5
+test_end
+
+test ps_rsync
+ rsr a5, ps
+ isync
+ rsr a3, ccount
+ wsr a5, ps
+ rsync
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 5
+test_end
+
+test ps_isync
+ rsr a5, ps
+ isync
+ rsr a3, ccount
+ wsr a5, ps
+ isync
+ rsr a4, ccount
+ sub a3, a4, a3
+ movi a4, 9
+ assert eq, a3, a4
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_quo.S b/src/tests/tcg/xtensa/test_quo.S
new file mode 100644
index 0000000..5b3ae38
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_quo.S
@@ -0,0 +1,147 @@
+#include "macros.inc"
+
+test_suite quo
+
+test quou_pp
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0x4
+ quou a5, a2, a4
+ assert eq, a5, a6
+ quou a2, a2, a4
+ assert eq, a2, a6
+ quou a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quou_np
+ movi a2, 0xa5a5137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0x8
+ quou a5, a2, a4
+ assert eq, a5, a6
+ quou a2, a2, a4
+ assert eq, a2, a6
+ quou a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quou_pn
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0xf7315a5a
+ movi a6, 0
+ quou a5, a2, a4
+ assert eq, a5, a6
+ quou a2, a2, a4
+ assert eq, a2, a6
+ quou a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quou_nn
+ movi a2, 0xf7315a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x1
+ quou a5, a2, a4
+ assert eq, a5, a6
+ quou a2, a2, a4
+ assert eq, a2, a6
+ quou a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quou_exc
+ set_vector kernel, 2f
+ movi a2, 0xf7315a5a
+ movi a4, 0x00000000
+1:
+ quou a5, a2, a4
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+test_end
+
+test quos_pp
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0x4
+ quos a5, a2, a4
+ assert eq, a5, a6
+ quos a2, a2, a4
+ assert eq, a2, a6
+ quos a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quos_np
+ movi a2, 0xa5a5137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0xfffffffc
+ quos a5, a2, a4
+ assert eq, a5, a6
+ quos a2, a2, a4
+ assert eq, a2, a6
+ quos a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quos_pn
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0xf7315a5a
+ movi a6, 0xfffffff6
+ quos a5, a2, a4
+ assert eq, a5, a6
+ quos a2, a2, a4
+ assert eq, a2, a6
+ quos a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quos_nn
+ movi a2, 0xf7315a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0
+ quos a5, a2, a4
+ assert eq, a5, a6
+ quos a2, a2, a4
+ assert eq, a2, a6
+ quos a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quos_over
+ movi a2, 0x80000000
+ movi a4, 0xffffffff
+ movi a6, 0x80000000
+ quos a5, a2, a4
+ assert eq, a5, a6
+test_end
+
+test quos_exc
+ set_vector kernel, 2f
+ movi a2, 0xf7315a5a
+ movi a4, 0x00000000
+1:
+ quos a5, a2, a4
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_rem.S b/src/tests/tcg/xtensa/test_rem.S
new file mode 100644
index 0000000..6357e52
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_rem.S
@@ -0,0 +1,147 @@
+#include "macros.inc"
+
+test_suite rem
+
+test remu_pp
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0x0c5caa17
+ remu a5, a2, a4
+ assert eq, a5, a6
+ remu a2, a2, a4
+ assert eq, a2, a6
+ remu a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test remu_np
+ movi a2, 0xa5a5137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0x9aa40af
+ remu a5, a2, a4
+ assert eq, a5, a6
+ remu a2, a2, a4
+ assert eq, a2, a6
+ remu a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test remu_pn
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0xf7315a5a
+ movi a6, 0x5a5a137f
+ remu a5, a2, a4
+ assert eq, a5, a6
+ remu a2, a2, a4
+ assert eq, a2, a6
+ remu a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test remu_nn
+ movi a2, 0xf7315a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x518c46db
+ remu a5, a2, a4
+ assert eq, a5, a6
+ remu a2, a2, a4
+ assert eq, a2, a6
+ remu a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test remu_exc
+ set_vector kernel, 2f
+ movi a2, 0xf7315a5a
+ movi a4, 0x00000000
+1:
+ remu a5, a2, a4
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+test_end
+
+test rems_pp
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0x0c5caa17
+ rems a5, a2, a4
+ assert eq, a5, a6
+ rems a2, a2, a4
+ assert eq, a2, a6
+ rems a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test rems_np
+ movi a2, 0xa5a5137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0xf3a27ce7
+ rems a5, a2, a4
+ assert eq, a5, a6
+ rems a2, a2, a4
+ assert eq, a2, a6
+ rems a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test rems_pn
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0xf7315a5a
+ movi a6, 0x02479b03
+ rems a5, a2, a4
+ assert eq, a5, a6
+ rems a2, a2, a4
+ assert eq, a2, a6
+ rems a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test rems_nn
+ movi a2, 0xf7315a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xf7315a5a
+ rems a5, a2, a4
+ assert eq, a5, a6
+ rems a2, a2, a4
+ assert eq, a2, a6
+ rems a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test rems_over
+ movi a2, 0x80000000
+ movi a4, 0xffffffff
+ movi a6, 0
+ rems a5, a2, a4
+ assert eq, a5, a6
+test_end
+
+test rems_exc
+ set_vector kernel, 2f
+ movi a2, 0xf7315a5a
+ movi a4, 0x00000000
+1:
+ rems a5, a2, a4
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_rst0.S b/src/tests/tcg/xtensa/test_rst0.S
new file mode 100644
index 0000000..a73366b
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_rst0.S
@@ -0,0 +1,148 @@
+#include "macros.inc"
+
+test_suite rst0
+
+test and
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x01250125
+ and a5, a2, a4
+ assert eq, a5, a6
+ and a2, a2, a4
+ assert eq, a2, a6
+ and a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test or
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xb7ffb7ff
+ or a5, a2, a4
+ assert eq, a5, a6
+ or a2, a2, a4
+ assert eq, a2, a6
+ or a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test xor
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xb6dab6da
+ xor a5, a2, a4
+ assert eq, a5, a6
+ xor a2, a2, a4
+ assert eq, a2, a6
+ xor a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test add
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xb924b924
+ add a5, a2, a4
+ assert eq, a5, a6
+ add a2, a2, a4
+ assert eq, a2, a6
+ add a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test addx2
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xcca45ec9
+ addx2 a5, a2, a4
+ assert eq, a5, a6
+ addx2 a2, a2, a4
+ assert eq, a2, a6
+ addx2 a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test addx4
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xf3a3aa13
+ addx4 a5, a2, a4
+ assert eq, a5, a6
+ addx4 a2, a2, a4
+ assert eq, a2, a6
+ addx4 a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test addx8
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x41a240a7
+ addx8 a5, a2, a4
+ assert eq, a5, a6
+ addx8 a2, a2, a4
+ assert eq, a2, a6
+ addx8 a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test sub
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x6dda9226
+ sub a5, a2, a4
+ assert eq, a5, a6
+ sub a2, a2, a4
+ assert eq, a2, a6
+ sub a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test subx2
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x815a37cb
+ subx2 a5, a2, a4
+ assert eq, a5, a6
+ subx2 a2, a2, a4
+ assert eq, a2, a6
+ subx2 a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test subx4
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xa8598315
+ subx4 a5, a2, a4
+ assert eq, a5, a6
+ subx4 a2, a2, a4
+ assert eq, a2, a6
+ subx4 a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test subx8
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xf65819a9
+ subx8 a5, a2, a4
+ assert eq, a5, a6
+ subx8 a2, a2, a4
+ assert eq, a2, a6
+ subx8 a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_s32c1i.S b/src/tests/tcg/xtensa/test_s32c1i.S
new file mode 100644
index 0000000..93b575d
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_s32c1i.S
@@ -0,0 +1,39 @@
+#include "macros.inc"
+
+test_suite s32c1i
+
+test s32c1i_nowrite
+ movi a2, 1f
+ movi a3, 1
+ wsr a3, scompare1
+ movi a1, 2
+ s32c1i a1, a2, 0
+ assert ne, a1, a3
+ l32i a1, a2, 0
+ assert eqi, a1, 3
+
+.data
+.align 4
+1:
+ .word 3
+.text
+test_end
+
+test s32c1i_write
+ movi a2, 1f
+ movi a3, 3
+ wsr a3, scompare1
+ movi a1, 2
+ s32c1i a1, a2, 0
+ assert eq, a1, a3
+ l32i a1, a2, 0
+ assert eqi, a1, 2
+
+.data
+.align 4
+1:
+ .word 3
+.text
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_sar.S b/src/tests/tcg/xtensa/test_sar.S
new file mode 100644
index 0000000..b615a55
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_sar.S
@@ -0,0 +1,111 @@
+#include "macros.inc"
+
+test_suite sar
+
+.macro test_sar prefix, imm
+ \prefix\()_set \imm
+ \prefix\()_ver \imm
+.endm
+
+.macro tests_sar prefix
+ test_sar \prefix, 0
+ test_sar \prefix, 1
+ test_sar \prefix, 2
+ test_sar \prefix, 3
+ test_sar \prefix, 0x1f
+ test_sar \prefix, 0x20
+ test_sar \prefix, 0x3f
+ test_sar \prefix, 0x40
+ test_sar \prefix, 0xfffffffe
+.endm
+
+.macro sar_set imm
+ movi a2, \imm
+ wsr a2, sar
+.endm
+
+.macro sar_ver imm
+ rsr a3, sar
+ movi a2, \imm & 0x3f
+ assert eq, a2, a3
+.endm
+
+test sar
+ tests_sar sar
+test_end
+
+.macro ssr_set imm
+ movi a2, \imm
+ ssr a2
+.endm
+
+.macro ssr_ver imm
+ rsr a3, sar
+ movi a2, \imm & 0x1f
+ assert eq, a2, a3
+.endm
+
+test ssr
+ tests_sar ssr
+test_end
+
+.macro ssl_set imm
+ movi a2, \imm
+ ssl a2
+.endm
+
+.macro ssl_ver imm
+ rsr a3, sar
+ movi a2, 32 - (\imm & 0x1f)
+ assert eq, a2, a3
+.endm
+
+test ssl
+ tests_sar ssl
+test_end
+
+.macro ssa8l_set imm
+ movi a2, \imm
+ ssa8l a2
+.endm
+
+.macro ssa8l_ver imm
+ rsr a3, sar
+ movi a2, (\imm & 0x3) << 3
+ assert eq, a2, a3
+.endm
+
+test ssa8l
+ tests_sar ssa8l
+test_end
+
+.macro ssa8b_set imm
+ movi a2, \imm
+ ssa8b a2
+.endm
+
+.macro ssa8b_ver imm
+ rsr a3, sar
+ movi a2, 32 - ((\imm & 0x3) << 3)
+ assert eq, a2, a3
+.endm
+
+test ssa8b
+ tests_sar ssa8b
+test_end
+
+.macro ssai_set imm
+ ssai \imm & 0x1f
+.endm
+
+.macro ssai_ver imm
+ rsr a3, sar
+ movi a2, \imm & 0x1f
+ assert eq, a2, a3
+.endm
+
+test ssai
+ tests_sar ssai
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_sext.S b/src/tests/tcg/xtensa/test_sext.S
new file mode 100644
index 0000000..087a633
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_sext.S
@@ -0,0 +1,69 @@
+#include "macros.inc"
+
+test_suite sext
+
+test sext
+ movi a2, 0xffffff5a
+ movi a3, 0x0000005a
+ sext a4, a2, 7
+ assert eq, a3, a4
+
+ movi a2, 0x000000a5
+ movi a3, 0xffffffa5
+ sext a4, a2, 7
+ assert eq, a3, a4
+
+ movi a2, 0xfffffaa5
+ movi a3, 0x000000a5
+ sext a4, a2, 8
+ assert eq, a3, a4
+
+ movi a2, 0x0000055a
+ movi a3, 0xffffff5a
+ sext a4, a2, 8
+ assert eq, a3, a4
+
+ movi a2, 0xffff5a5a
+ movi a3, 0x00005a5a
+ sext a4, a2, 15
+ assert eq, a3, a4
+
+ movi a2, 0x0000a5a5
+ movi a3, 0xffffa5a5
+ sext a4, a2, 15
+ assert eq, a3, a4
+
+ movi a2, 0x00055a5a
+ movi a3, 0xffff5a5a
+ sext a4, a2, 16
+ assert eq, a3, a4
+
+ movi a2, 0x000aa5a5
+ movi a3, 0x0000a5a5
+ sext a4, a2, 16
+ assert eq, a3, a4
+
+ movi a2, 0x005a5a5a
+ movi a3, 0xffda5a5a
+ sext a4, a2, 22
+ assert eq, a3, a4
+
+ movi a2, 0xffa5a5a5
+ movi a3, 0x0025a5a5
+ sext a4, a2, 22
+ assert eq, a3, a4
+test_end
+
+test sext_same_rs
+ movi a2, 0xffffff5a
+ movi a3, 0x0000005a
+ sext a2, a2, 7
+ assert eq, a3, a2
+
+ movi a2, 0x000000a5
+ movi a3, 0xffffffa5
+ sext a2, a2, 7
+ assert eq, a3, a2
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_shift.S b/src/tests/tcg/xtensa/test_shift.S
new file mode 100644
index 0000000..5df9ed4
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_shift.S
@@ -0,0 +1,206 @@
+#include "macros.inc"
+
+test_suite shift
+
+.macro test_shift prefix, dst, src, v, imm
+ \prefix\()_set \dst, \src, \v, \imm
+ \prefix\()_ver \dst, \v, \imm
+.endm
+
+.macro test_shift_sd prefix, v, imm
+ test_shift \prefix, a3, a2, \v, \imm
+ test_shift \prefix, a2, a2, \v, \imm
+.endm
+
+.macro tests_imm_shift prefix, v
+ test_shift_sd \prefix, \v, 1
+ test_shift_sd \prefix, \v, 2
+ test_shift_sd \prefix, \v, 7
+ test_shift_sd \prefix, \v, 8
+ test_shift_sd \prefix, \v, 15
+ test_shift_sd \prefix, \v, 16
+ test_shift_sd \prefix, \v, 31
+.endm
+
+.macro tests_shift prefix, v
+ test_shift_sd \prefix, \v, 0
+ tests_imm_shift \prefix, \v
+ test_shift_sd \prefix, \v, 32
+.endm
+
+
+.macro slli_set dst, src, v, imm
+ movi \src, \v
+ slli \dst, \src, \imm
+.endm
+
+.macro slli_ver dst, v, imm
+ mov a2, \dst
+ movi a3, ((\v) << (\imm)) & 0xffffffff
+ assert eq, a2, a3
+.endm
+
+test slli
+ tests_imm_shift slli, 0xa3c51249
+test_end
+
+
+.macro srai_set dst, src, v, imm
+ movi \src, \v
+ srai \dst, \src, \imm
+.endm
+
+.macro srai_ver dst, v, imm
+ mov a2, \dst
+ .if (\imm)
+ movi a3, (((\v) >> (\imm)) & 0xffffffff) | \
+ ~((((\v) & 0x80000000) >> ((\imm) - 1)) - 1)
+ .else
+ movi a3, \v
+ .endif
+ assert eq, a2, a3
+.endm
+
+test srai
+ tests_imm_shift srai, 0x49a3c512
+ tests_imm_shift srai, 0xa3c51249
+test_end
+
+
+.macro srli_set dst, src, v, imm
+ movi \src, \v
+ srli \dst, \src, \imm
+.endm
+
+.macro srli_ver dst, v, imm
+ mov a2, \dst
+ movi a3, (((\v) >> (\imm)) & 0xffffffff)
+ assert eq, a2, a3
+.endm
+
+test srli
+ tests_imm_shift srli, 0x49a3c512
+ tests_imm_shift srli, 0xa3c51249
+test_end
+
+
+.macro sll_set dst, src, v, imm
+ movi a2, \imm
+ ssl a2
+ movi \src, \v
+ sll \dst, \src
+.endm
+
+.macro sll_sar_set dst, src, v, imm
+ movi a2, 32 - \imm
+ wsr a2, sar
+ movi \src, \v
+ sll \dst, \src
+.endm
+
+.macro sll_ver dst, v, imm
+ slli_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro sll_sar_ver dst, v, imm
+ slli_ver \dst, \v, \imm
+.endm
+
+test sll
+ tests_shift sll, 0xa3c51249
+ tests_shift sll_sar, 0xa3c51249
+test_end
+
+
+.macro srl_set dst, src, v, imm
+ movi a2, \imm
+ ssr a2
+ movi \src, \v
+ srl \dst, \src
+.endm
+
+.macro srl_sar_set dst, src, v, imm
+ movi a2, \imm
+ wsr a2, sar
+ movi \src, \v
+ srl \dst, \src
+.endm
+
+.macro srl_ver dst, v, imm
+ srli_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro srl_sar_ver dst, v, imm
+ srli_ver \dst, \v, \imm
+.endm
+
+test srl
+ tests_shift srl, 0xa3c51249
+ tests_shift srl_sar, 0xa3c51249
+ tests_shift srl, 0x49a3c512
+ tests_shift srl_sar, 0x49a3c512
+test_end
+
+
+.macro sra_set dst, src, v, imm
+ movi a2, \imm
+ ssr a2
+ movi \src, \v
+ sra \dst, \src
+.endm
+
+.macro sra_sar_set dst, src, v, imm
+ movi a2, \imm
+ wsr a2, sar
+ movi \src, \v
+ sra \dst, \src
+.endm
+
+.macro sra_ver dst, v, imm
+ srai_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro sra_sar_ver dst, v, imm
+ srai_ver \dst, \v, \imm
+.endm
+
+test sra
+ tests_shift sra, 0xa3c51249
+ tests_shift sra_sar, 0xa3c51249
+ tests_shift sra, 0x49a3c512
+ tests_shift sra_sar, 0x49a3c512
+test_end
+
+
+.macro src_set dst, src, v, imm
+ movi a2, \imm
+ ssr a2
+ movi \src, (\v) & 0xffffffff
+ movi a4, (\v) >> 32
+ src \dst, a4, \src
+.endm
+
+.macro src_sar_set dst, src, v, imm
+ movi a2, \imm
+ wsr a2, sar
+ movi \src, (\v) & 0xffffffff
+ movi a4, (\v) >> 32
+ src \dst, a4, \src
+.endm
+
+.macro src_ver dst, v, imm
+ src_sar_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro src_sar_ver dst, v, imm
+ mov a2, \dst
+ movi a3, ((\v) >> (\imm)) & 0xffffffff
+ assert eq, a2, a3
+.endm
+
+test src
+ tests_shift src, 0xa3c51249215c3a94
+ tests_shift src_sar, 0xa3c51249215c3a94
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_sr.S b/src/tests/tcg/xtensa/test_sr.S
new file mode 100644
index 0000000..4fac46e
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_sr.S
@@ -0,0 +1,90 @@
+#include "macros.inc"
+
+test_suite sr
+
+.macro sr_op sym, op_sym, op_byte, sr
+ .if \sym
+ \op_sym a4, \sr
+ .else
+ .byte 0x40, \sr, \op_byte
+ .endif
+.endm
+
+.macro test_sr_op sym, mask, op, op_byte, sr
+ movi a4, 0
+ .if (\mask)
+ set_vector kernel, 0
+ sr_op \sym, \op, \op_byte, \sr
+ .else
+ set_vector kernel, 2f
+1:
+ sr_op \sym, \op, \op_byte, \sr
+ test_fail
+2:
+ reset_ps
+ rsr a2, exccause
+ assert eqi, a2, 0
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+ .endif
+.endm
+
+.macro test_sr_mask sr, sym, mask
+test \sr
+ test_sr_op \sym, \mask & 1, rsr, 0x03, \sr
+ test_sr_op \sym, \mask & 2, wsr, 0x13, \sr
+ test_sr_op \sym, \mask & 4, xsr, 0x61, \sr
+test_end
+.endm
+
+.macro test_sr sr, conf
+ test_sr_mask \sr, \conf, 7
+.endm
+
+test_sr acchi, 1
+test_sr acclo, 1
+test_sr_mask /*atomctl*/99, 0, 0
+test_sr_mask /*br*/4, 0, 0
+test_sr_mask /*cacheattr*/98, 0, 0
+test_sr ccompare0, 1
+test_sr ccount, 1
+test_sr cpenable, 1
+test_sr dbreaka0, 1
+test_sr dbreakc0, 1
+test_sr_mask debugcause, 1, 1
+test_sr depc, 1
+test_sr dtlbcfg, 1
+test_sr epc1, 1
+test_sr epc2, 1
+test_sr eps2, 1
+test_sr exccause, 1
+test_sr excsave1, 1
+test_sr excsave2, 1
+test_sr excvaddr, 1
+test_sr ibreaka0, 1
+test_sr ibreakenable, 1
+test_sr icount, 1
+test_sr icountlevel, 1
+test_sr_mask /*intclear*/227, 0, 2
+test_sr_mask /*interrupt*/226, 0, 3
+test_sr intenable, 1
+test_sr itlbcfg, 1
+test_sr lbeg, 1
+test_sr lcount, 1
+test_sr lend, 1
+test_sr litbase, 1
+test_sr m0, 1
+test_sr misc0, 1
+test_sr_mask /*prefctl*/40, 0, 0
+test_sr_mask /*prid*/235, 0, 1
+test_sr ps, 1
+test_sr ptevaddr, 1
+test_sr rasid, 1
+test_sr sar, 1
+test_sr scompare1, 1
+test_sr vecbase, 1
+test_sr windowbase, 1
+test_sr windowstart, 1
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_timer.S b/src/tests/tcg/xtensa/test_timer.S
new file mode 100644
index 0000000..f8c6f74
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_timer.S
@@ -0,0 +1,178 @@
+#include "macros.inc"
+
+test_suite timer
+
+test ccount
+ rsr a3, ccount
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 1
+test_end
+
+test ccompare
+ movi a2, 0
+ wsr a2, intenable
+ rsr a2, interrupt
+ wsr a2, intclear
+ movi a2, 0
+ wsr a2, ccompare1
+ wsr a2, ccompare2
+
+ movi a3, 20
+ rsr a2, ccount
+ addi a2, a2, 20
+ wsr a2, ccompare0
+ rsr a2, interrupt
+ assert eqi, a2, 0
+ loop a3, 1f
+ rsr a3, interrupt
+ bnez a3, 2f
+1:
+ test_fail
+2:
+test_end
+
+test ccompare0_interrupt
+ set_vector kernel, 2f
+ movi a2, 0
+ wsr a2, intenable
+ rsr a2, interrupt
+ wsr a2, intclear
+ movi a2, 0
+ wsr a2, ccompare1
+ wsr a2, ccompare2
+
+ movi a3, 20
+ rsr a2, ccount
+ addi a2, a2, 20
+ wsr a2, ccompare0
+ rsync
+ rsr a2, interrupt
+ assert eqi, a2, 0
+
+ movi a2, 0x40
+ wsr a2, intenable
+ rsil a2, 0
+ loop a3, 1f
+ nop
+1:
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
+test_end
+
+test ccompare1_interrupt
+ set_vector level3, 2f
+ movi a2, 0
+ wsr a2, intenable
+ rsr a2, interrupt
+ wsr a2, intclear
+ movi a2, 0
+ wsr a2, ccompare0
+ wsr a2, ccompare2
+
+ movi a3, 20
+ rsr a2, ccount
+ addi a2, a2, 20
+ wsr a2, ccompare1
+ rsync
+ rsr a2, interrupt
+ assert eqi, a2, 0
+ movi a2, 0x400
+ wsr a2, intenable
+ rsil a2, 2
+ loop a3, 1f
+ nop
+1:
+ test_fail
+2:
+test_end
+
+test ccompare2_interrupt
+ set_vector level5, 2f
+ movi a2, 0
+ wsr a2, intenable
+ rsr a2, interrupt
+ wsr a2, intclear
+ movi a2, 0
+ wsr a2, ccompare0
+ wsr a2, ccompare1
+
+ movi a3, 20
+ rsr a2, ccount
+ addi a2, a2, 20
+ wsr a2, ccompare2
+ rsync
+ rsr a2, interrupt
+ assert eqi, a2, 0
+ movi a2, 0x2000
+ wsr a2, intenable
+ rsil a2, 4
+ loop a3, 1f
+ nop
+1:
+ test_fail
+2:
+test_end
+
+test ccompare_interrupt_masked
+ set_vector kernel, 2f
+ movi a2, 0
+ wsr a2, intenable
+ rsr a2, interrupt
+ wsr a2, intclear
+ movi a2, 0
+ wsr a2, ccompare2
+
+ movi a3, 40
+ rsr a2, ccount
+ addi a2, a2, 20
+ wsr a2, ccompare1
+ addi a2, a2, 20
+ wsr a2, ccompare0
+ rsync
+ rsr a2, interrupt
+ assert eqi, a2, 0
+
+ movi a2, 0x40
+ wsr a2, intenable
+ rsil a2, 0
+ loop a3, 1f
+ nop
+1:
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
+test_end
+
+test ccompare_interrupt_masked_waiti
+ set_vector kernel, 2f
+ movi a2, 0
+ wsr a2, intenable
+ rsr a2, interrupt
+ wsr a2, intclear
+ movi a2, 0
+ wsr a2, ccompare2
+
+ movi a3, 40
+ rsr a2, ccount
+ addi a2, a2, 20
+ wsr a2, ccompare1
+ addi a2, a2, 20
+ wsr a2, ccompare0
+ rsync
+ rsr a2, interrupt
+ assert eqi, a2, 0
+
+ movi a2, 0x40
+ wsr a2, intenable
+ waiti 0
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/test_windowed.S b/src/tests/tcg/xtensa/test_windowed.S
new file mode 100644
index 0000000..d851e8f
--- /dev/null
+++ b/src/tests/tcg/xtensa/test_windowed.S
@@ -0,0 +1,353 @@
+#include "macros.inc"
+
+test_suite windowed
+
+.altmacro
+
+.macro reset_window start
+ movi a2, 0xff
+ wsr a2, windowstart
+ rsync
+ movi a2, 0
+ wsr a2, windowbase
+ rsync
+ movi a2, \start
+ wsr a2, windowstart
+ rsync
+.endm
+
+.macro overflow_test shift, window, probe_ok, probe_ex
+ set_vector window_overflow_4, 0
+ set_vector window_overflow_8, 0
+ set_vector window_overflow_12, 0
+
+ movi a2, 1 | (((1 << ((\window) / 4)) | 1) << ((\shift) / 4))
+ wsr a2, windowstart
+ reset_ps
+
+ mov a2, a\probe_ok
+ set_vector window_overflow_\window, 10f
+1:
+ mov a2, a\probe_ex
+ test_fail
+10:
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+ movi a2, 2f
+ wsr a2, epc1
+
+ rsr a2, windowbase
+ movi a3, (\shift) / 4
+ assert eq, a2, a3
+ rsr a2, ps
+ movi a3, 0x4001f
+ assert eq, a2, a3
+ rfwo
+ test_fail
+2:
+ rsr a2, windowbase
+ assert eqi, a2, 0
+ rsr a2, windowstart
+ movi a3, 1 | ((1 << ((\window) / 4)) << ((\shift) / 4))
+ assert eq, a2, a3
+ rsr a2, ps
+ movi a3, 0x4000f
+ assert eq, a2, a3
+.endm
+
+.macro overflow_tests shift, window, probe
+ .if \probe < 15
+ overflow_test \shift, \window, %((\shift) - 1), \probe
+ overflow_tests \shift, \window, %((\probe) + 1)
+ .endif
+.endm
+
+.macro all_overflow_tests
+ .irp shift, 4, 8, 12
+ .irp window, 4, 8, 12
+ overflow_tests \shift, \window, \shift
+ .endr
+ .endr
+.endm
+
+test overflow
+ all_overflow_tests
+test_end
+
+
+.macro underflow_test window
+ set_vector window_underflow_4, 0
+ set_vector window_underflow_8, 0
+ set_vector window_underflow_12, 0
+
+ set_vector window_underflow_\window, 10f
+
+ reset_window 1
+ reset_ps
+
+ ssai 2
+ movi a2, 2f
+ slli a2, a2, 2
+ movi a3, (\window) / 4
+ src a0, a3, a2
+1:
+ retw
+ test_fail
+10:
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+ movi a2, 2f
+ wsr a2, epc1
+
+ rsr a2, ps
+ movi a3, 0x4001f
+ assert eq, a2, a3
+ rsr a2, windowbase
+ assert eqi, a2, 8 - ((\window) / 4)
+ rsr a2, windowstart
+ assert eqi, a2, 1
+ rfwu
+2:
+ rsr a2, ps
+ movi a3, 0x4000f
+ assert eq, a2, a3
+ rsr a2, windowbase
+ assert eqi, a2, 0
+ rsr a2, windowstart
+ assert bsi, a2, 0
+ assert bsi, a2, 8 - ((\window) / 4)
+.endm
+
+test underflow
+ set_vector window_overflow_4, 0
+ set_vector window_overflow_8, 0
+ set_vector window_overflow_12, 0
+
+ underflow_test 4
+ underflow_test 8
+ underflow_test 12
+test_end
+
+
+.macro retw_test window
+ reset_window %(1 | (1 << (8 - (\window) / 4)))
+ reset_ps
+
+ ssai 2
+ movi a2, 1f
+ slli a2, a2, 2
+ movi a3, (\window) / 4
+ src a0, a3, a2
+ retw
+ test_fail
+1:
+ rsr a2, ps
+ movi a3, 0x4000f
+ assert eq, a2, a3
+ rsr a2, windowbase
+ assert eqi, a2, 8 - ((\window) / 4)
+ rsr a2, windowstart
+ assert bci, a2, 0
+ assert bsi, a2, 8 - ((\window) / 4)
+.endm
+
+test retw
+ set_vector window_underflow_4, 0
+ set_vector window_underflow_8, 0
+ set_vector window_underflow_12, 0
+
+ retw_test 4
+ retw_test 8
+ retw_test 12
+test_end
+
+test movsp
+ set_vector kernel, 2f
+
+ reset_window 1
+ reset_ps
+1:
+ movsp a2, a3
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 5
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+
+ set_vector kernel, 0
+
+ reset_window 0x81
+ reset_ps
+
+ movsp a2, a3
+test_end
+
+test rotw
+ reset_window 0x4b
+ reset_ps
+
+ movi a3, 0x10
+
+ rotw 1
+ rsr a2, windowbase
+ assert eqi, a2, 1
+ movi a3, 0x11
+ movi a7, 0x12
+
+ rotw 2
+ rsr a2, windowbase
+ assert eqi, a2, 3
+ movi a3, 0x13
+ movi a7, 0x14
+ movi a11, 0x15
+
+ rotw 3
+ rsr a2, windowbase
+ assert eqi, a2, 6
+ movi a3, 0x16
+ movi a7, 0x17
+
+ movi a2, 0x44
+ wsr a2, windowstart
+ rsync
+
+ movi a2, 0x10
+ assert eq, a2, a11
+ movi a11, 0x18
+ movi a2, 0x11
+ assert eq, a2, a15
+ movi a15, 0x19
+
+ rotw 4
+ movi a2, 0x12
+ assert eq, a2, a3
+ movi a2, 0x13
+ assert eq, a2, a7
+ movi a2, 0x14
+ assert eq, a2, a11
+ movi a2, 0x15
+ assert eq, a2, a15
+
+ movi a2, 0x5
+ wsr a2, windowstart
+ rsync
+
+ rotw -2
+ movi a2, 0x18
+ assert eq, a2, a3
+ movi a2, 0x19
+ assert eq, a2, a7
+test_end
+
+.macro callw_test window
+ call\window 2f
+1:
+ test_fail
+ .align 4
+2:
+ rsr a2, windowbase
+ assert eqi, a2, 0
+ rsr a2, ps
+ movi a3, 0x4000f | ((\window) << 14)
+ assert eq, a2, a3
+ movi a2, 1b
+ slli a2, a2, 2
+ ssai 2
+ movi a3, (\window) / 4
+ src a2, a3, a2
+ assert eq, a2, a\window
+.endm
+
+test callw
+ reset_window 0x1
+ reset_ps
+
+ callw_test 4
+ callw_test 8
+ callw_test 12
+test_end
+
+
+.macro entry_test window
+ reset_window 0x1
+ reset_ps
+ movi a2, 0x4000f | ((\window) << 14)
+ wsr a2, ps
+ isync
+ movi a3, 0x12345678
+ j 1f
+ .align 4
+1:
+ entry a3, 0x5678
+ movi a2, 0x12340000
+ assert eq, a2, a3
+ rsr a2, windowbase
+ assert eqi, a2, (\window) / 4
+ rsr a2, windowstart
+ movi a3, 1 | (1 << ((\window) / 4))
+ assert eq, a2, a3
+ rotw -(\window) / 4
+.endm
+
+test entry
+ entry_test 4
+ entry_test 8
+ entry_test 12
+test_end
+
+.macro entry_overflow_test window, free, next_window
+ set_vector window_overflow_4, 0
+ set_vector window_overflow_8, 0
+ set_vector window_overflow_12, 0
+ set_vector window_overflow_\next_window, 10f
+
+ movi a2, \window
+ movi a2, \free
+ movi a2, \next_window
+ reset_window %(1 | ((1 | (1 << ((\next_window) / 4))) << ((\free) / 4)))
+ reset_ps
+ movi a2, 0x4000f | ((\window) << 14)
+ wsr a2, ps
+ isync
+ movi a3, 0x12345678
+ j 1f
+ .align 4
+1:
+ entry a3, 0x5678
+ test_fail
+ .align 4
+10:
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+ movi a2, 2f
+ wsr a2, epc1
+
+ rsr a2, windowbase
+ movi a3, (\free) / 4
+ assert eq, a2, a3
+ rfwo
+2:
+.endm
+
+.macro all_entry_overflow_tests
+ .irp window, 4, 8, 12
+ .irp next_window, 4, 8, 12
+ .irp free, 4, 8, 12
+ .if \free <= \window
+ entry_overflow_test \window, \free, \next_window
+ .endif
+ .endr
+ .endr
+ .endr
+.endm
+
+test entry_overflow
+ all_entry_overflow_tests
+test_end
+
+test_suite_end
diff --git a/src/tests/tcg/xtensa/vectors.S b/src/tests/tcg/xtensa/vectors.S
new file mode 100644
index 0000000..265a181
--- /dev/null
+++ b/src/tests/tcg/xtensa/vectors.S
@@ -0,0 +1,39 @@
+.macro vector name
+
+.section .vector.\name
+ j 1f
+.section .vector.\name\().text
+1:
+ wsr a2, excsave1
+ movi a2, handler_\name
+ l32i a2, a2, 0
+ beqz a2, 1f
+ jx a2
+1:
+ movi a3, 1b
+ movi a2, 1
+ simcall
+
+.align 4
+.global handler_\name
+handler_\name\(): .word 0
+
+.endm
+
+vector window_overflow_4
+vector window_overflow_8
+vector window_overflow_12
+vector window_underflow_4
+vector window_underflow_8
+vector window_underflow_12
+
+vector level2
+vector level3
+vector level4
+vector level5
+vector level6
+vector level7
+
+vector kernel
+vector user
+vector double
OpenPOWER on IntegriCloud