diff options
author | Andrew Bennett <andrew.bennett@imgtec.com> | 2015-09-25 15:52:18 +0100 |
---|---|---|
committer | Andrew Bennett <andrew.bennett@imgtec.com> | 2015-09-25 15:52:18 +0100 |
commit | 8e394ffc7ab691eafcf276d7ae578454a8c5548f (patch) | |
tree | 309466c282f5b0adc8a27e5f8fa3b6a6f2e64ee0 /sim/mips | |
parent | 8a9e7a9121490a8c64d8c17f5be510e43104f6d9 (diff) | |
download | gdb-8e394ffc7ab691eafcf276d7ae578454a8c5548f.zip gdb-8e394ffc7ab691eafcf276d7ae578454a8c5548f.tar.gz gdb-8e394ffc7ab691eafcf276d7ae578454a8c5548f.tar.bz2 |
[PATCH] Add micromips support to the MIPS simulator
2015-09-25 Andrew Bennett <andrew.bennett@imgtec.com>
Ali Lown <ali.lown@imgtec.com>
sim/common/
* sim-bits.h (EXTEND6): New macro.
(EXTEND12): New macro.
(EXTEND25): New macro.
sim/mips/
* Makefile.in (tmp-micromips): New rule.
(tmp-mach-multi): Add support for micromips.
* configure.ac (mips*-sde-elf* | mips*-mti-elf*): Made a multi sim
that works for both mips64 and micromips64.
(mipsisa32r2*-*-*): Made a multi sim that works for mips32 and
micromips32.
Add build support for micromips.
* dsp.igen (do_ph_s_absq, do_w_s_absq, do_qb_s_absq, do_addsc,
do_addwc, do_bitrev, do_extpv, do_extrv, do_extrv_s_h, do_insv,
do_lxx do_modsub, do_mthlip, do_mulsaq_s_w_ph, do_ph_packrl, do_qb_pick
do_ph_pick, do_qb_ph_precequ, do_qb_ph_preceu, do_w_preceq
do_w_ph_precrq, do_ph_qb_precrq, do_w_ph_rs_precrq do_qb_w_raddu,
do_rddsp, do_repl, do_shilov, do_ph_shl, do_qb_shl do_w_s_shllv,
do_ph_shrlv, do_w_r_shrav, do_wrdsp, do_qb_shrav, do_append,
do_balign, do_ph_w_mulsa, do_ph_qb_precr, do_prepend): New functions.
Refactored instruction code to use these functions.
* dsp2.igen: Refactored instruction code to use the new functions.
* interp.c (decode_coproc): Refactored to work with any instruction
encoding.
(isa_mode): New variable
(RSVD_INSTRUCTION): Changed to 0x00000039.
* m16.igen (BREAK16): Refactored instruction to use do_break16.
(JALX32): Add mips32, mips64, mips32r2 and mips64r2 models.
* micromips.dc: New file.
* micromips.igen: New file.
* micromips16.dc: New file.
* micromipsdsp.igen: New file.
* micromipsrun.c: New file.
* mips.igen (do_swc1): Changed to work with any instruction encoding.
(do_add do_addi do_andi do_dadd do_daddi do_dsll32 do_dsra32
do_dsrl32, do_dsub, do_break, do_break16, do_clo, do_clz, do_dclo
do_dclz, do_lb, do_lh, do_lwr, do_lwl, do_lwc, do_lw, do_lwu, do_lhu
do_ldc, do_lbu, do_ll, do_lld, do_lui, do_madd, do_dsp_madd, do_maddu
do_dsp_maddu, do_dsp_mfhi, do_dsp_mflo, do_movn, do_movz, do_msub
do_dsp_msub, do_msubu, do_dsp_msubu, do_mthi, do_dsp_mthi, do_mtlo
do_dsp_mtlo, do_mul, do_dsp_mult, do_dsp_multu, do_pref, do_sc, do_scd
do_sub, do_sw, do_teq, do_teqi, do_tge, do_tgei, do_tgeiu, do_tgeu, do_tlt
do_tlti, do_tltiu, do_tltu, do_tne, do_tnei, do_abs_fmt, do_add_fmt
do_alnv_ps, do_c_cond_fmt, do_ceil_fmt, do_cfc1, do_ctc1, do_cvt_d_fmt
do_cvt_l_fmt, do_cvt_ps_s, do_cvt_s_fmt, do_cvt_s_pl, do_cvt_s_pu
do_cvt_w_fmt, do_div_fmt, do_dmfc1b, do_dmtc1b, do_floor_fmt, do_luxc1_32
do_luxc1_64, do_lwc1, do_lwxc1, do_madd_fmt, do_mfc1b, do_mov_fmt, do_movtf
do_movtf_fmt, do_movn_fmt, do_movz_fmt, do_msub_fmt, do_mtc1b, do_mul_fmt
do_neg_fmt, do_nmadd_fmt, do_nmsub_fmt, do_pll_ps, do_plu_ps, do_pul_ps
do_puu_ps, do_recip_fmt, do_round_fmt, do_rsqrt_fmt, do_prefx, do_sdc1
do_suxc1_32, do_suxc1_64, do_sqrt_fmt, do_sub_fmt, do_swc1, do_swxc1
do_trunc_fmt): New functions, refactored from existing instructions.
Refactored instruction code to use these functions.
(RSVD): Changed to use new reserved instruction.
(loadstore_ea, not_word_value, unpredictable, check_mt_hilo, check_mf_hilo,
check_mult_hilo, check_div_hilo, check_u64, do_luxc1_32, do_sdc1, do_suxc1_32,
check_fmt_p, check_fpu, do_load_double, do_store_double): Added micromips32
and micromips64 models.
Added include for micromips.igen and micromipsdsp.igen
Add micromips32 and micromips64 models.
(DecodeCoproc): Updated to use new macro definition.
* mips3264r2.igen (do_dsbh, do_dshd, do_dext, do_dextm, do_dextu, do_di,
do_dins, do_dinsm, do_ei, do_ext, do_mfhc1, do_mthc1, do_ins, do_dinsu,
do_seb, do_seh do_rdhwr, do_wsbh): New functions.
Refactored instruction code to use these functions.
* sim-main.h (CP0_operation): New enum.
(DecodeCoproc): Updated macro.
(IMEM32_MICROMIPS, IMEM16_MICROMIPS, MICROMIPS_MINOR_OPCODE,
MICROMIPS_DELAYSLOT_SIZE_ANY, MICROMIPS_DELAYSLOT_SIZE_16, MICROMIPS_DELAYSLOT_SIZE_32,
ISA_MODE_MIPS32 and ISA_MODE_MICROMIPS): New defines.
(sim_state): Add isa_mode field.
sim/testsuite/sim/mips/
* basic.exp (run_micromips_test, run_sim_tests): New functions
Add support for micromips tests.
* hilo-hazard-4.s: New file.
* testutils.inc (_dowrite): Changed reserved instruction encoding.
(writemsg): Moved the la and li instructions before the data they are
assigned to, which prevents a bug where MIPS32 relocations are used instead
of micromips relocations when building for micromips.
Diffstat (limited to 'sim/mips')
-rw-r--r-- | sim/mips/ChangeLog | 72 | ||||
-rw-r--r-- | sim/mips/Makefile.in | 324 | ||||
-rwxr-xr-x | sim/mips/configure | 61 | ||||
-rw-r--r-- | sim/mips/configure.ac | 59 | ||||
-rw-r--r-- | sim/mips/dsp.igen | 1041 | ||||
-rw-r--r-- | sim/mips/dsp2.igen | 84 | ||||
-rw-r--r-- | sim/mips/interp.c | 53 | ||||
-rw-r--r-- | sim/mips/m16.igen | 10 | ||||
-rw-r--r-- | sim/mips/micromips.dc | 15 | ||||
-rw-r--r-- | sim/mips/micromips.igen | 3091 | ||||
-rw-r--r-- | sim/mips/micromips16.dc | 11 | ||||
-rw-r--r-- | sim/mips/micromipsdsp.igen | 1137 | ||||
-rw-r--r-- | sim/mips/micromipsrun.c | 135 | ||||
-rw-r--r-- | sim/mips/mips.igen | 2235 | ||||
-rw-r--r-- | sim/mips/mips3264r2.igen | 290 | ||||
-rw-r--r-- | sim/mips/sim-main.h | 47 |
16 files changed, 7203 insertions, 1462 deletions
diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog index 012149d..2865266 100644 --- a/sim/mips/ChangeLog +++ b/sim/mips/ChangeLog @@ -1,3 +1,75 @@ +2015-09-25 Andrew Bennett <andrew.bennett@imgtec.com> + Ali Lown <ali.lown@imgtec.com> + + * Makefile.in (tmp-micromips): New rule. + (tmp-mach-multi): Add support for micromips. + * configure.ac (mips*-sde-elf* | mips*-mti-elf*): Made a multi sim + that works for both mips64 and micromips64. + (mipsisa32r2*-*-*): Made a multi sim that works for mips32 and + micromips32. + Add build support for micromips. + * dsp.igen (do_ph_s_absq, do_w_s_absq, do_qb_s_absq, do_addsc, + do_addwc, do_bitrev, do_extpv, do_extrv, do_extrv_s_h, do_insv, + do_lxx do_modsub, do_mthlip, do_mulsaq_s_w_ph, do_ph_packrl, do_qb_pick + do_ph_pick, do_qb_ph_precequ, do_qb_ph_preceu, do_w_preceq + do_w_ph_precrq, do_ph_qb_precrq, do_w_ph_rs_precrq do_qb_w_raddu, + do_rddsp, do_repl, do_shilov, do_ph_shl, do_qb_shl do_w_s_shllv, + do_ph_shrlv, do_w_r_shrav, do_wrdsp, do_qb_shrav, do_append, + do_balign, do_ph_w_mulsa, do_ph_qb_precr, do_prepend): New functions. + Refactored instruction code to use these functions. + * dsp2.igen: Refactored instruction code to use the new functions. + * interp.c (decode_coproc): Refactored to work with any instruction + encoding. + (isa_mode): New variable + (RSVD_INSTRUCTION): Changed to 0x00000039. + * m16.igen (BREAK16): Refactored instruction to use do_break16. + (JALX32): Add mips32, mips64, mips32r2 and mips64r2 models. + * micromips.dc: New file. + * micromips.igen: New file. + * micromips16.dc: New file. + * micromipsdsp.igen: New file. + * micromipsrun.c: New file. + * mips.igen (do_swc1): Changed to work with any instruction encoding. + (do_add do_addi do_andi do_dadd do_daddi do_dsll32 do_dsra32 + do_dsrl32, do_dsub, do_break, do_break16, do_clo, do_clz, do_dclo, + do_dclz, do_lb, do_lh, do_lwr, do_lwl, do_lwc, do_lw, do_lwu, do_lhu, + do_ldc, do_lbu, do_ll, do_lld, do_lui, do_madd, do_dsp_madd, do_maddu, + do_dsp_maddu, do_dsp_mfhi, do_dsp_mflo, do_movn, do_movz, do_msub, + do_dsp_msub, do_msubu, do_dsp_msubu, do_mthi, do_dsp_mthi, do_mtlo, + do_dsp_mtlo, do_mul, do_dsp_mult, do_dsp_multu, do_pref, do_sc, + do_scd, do_sub, do_sw, do_teq, do_teqi, do_tge, do_tgei, do_tgeiu, + do_tgeu, do_tlt do_tlti, do_tltiu, do_tltu, do_tne, do_tnei, do_abs_fmt, + do_add_fmt, do_alnv_ps, do_c_cond_fmt, do_ceil_fmt, do_cfc1, do_ctc1, + do_cvt_d_fmt, do_cvt_l_fmt, do_cvt_ps_s, do_cvt_s_fmt, do_cvt_s_pl, + do_cvt_s_pu, do_cvt_w_fmt, do_div_fmt, do_dmfc1b, do_dmtc1b, do_floor_fmt, + do_luxc1_32, do_luxc1_64, do_lwc1, do_lwxc1, do_madd_fmt, do_mfc1b, + do_mov_fmt, do_movtf, do_movtf_fmt, do_movn_fmt, do_movz_fmt, do_msub_fmt, + do_mtc1b, do_mul_fmt, do_neg_fmt, do_nmadd_fmt, do_nmsub_fmt, do_pll_ps, + do_plu_ps, do_pul_ps, do_puu_ps, do_recip_fmt, do_round_fmt, do_rsqrt_fmt, + do_prefx, do_sdc1, do_suxc1_32, do_suxc1_64, do_sqrt_fmt, do_sub_fmt, + do_swc1, do_swxc1, do_trunc_fmt): New functions, refactored from existing + instructions. + Refactored instruction code to use these functions. + (RSVD): Changed to use new reserved instruction. + (loadstore_ea, not_word_value, unpredictable, check_mt_hilo, + check_mf_hilo, check_mult_hilo, check_div_hilo, check_u64, do_luxc1_32, + do_sdc1, do_suxc1_32, check_fmt_p, check_fpu, do_load_double, + do_store_double): Added micromips32 and micromips64 models. + Added include for micromips.igen and micromipsdsp.igen + Add micromips32 and micromips64 models. + (DecodeCoproc): Updated to use new macro definition. + * mips3264r2.igen (do_dsbh, do_dshd, do_dext, do_dextm, do_dextu, do_di, + do_dins, do_dinsm, do_ei, do_ext, do_mfhc1, do_mthc1, do_ins, do_dinsu, + do_seb, do_seh do_rdhwr, do_wsbh): New functions. + Refactored instruction code to use these functions. + * sim-main.h (CP0_operation): New enum. + (DecodeCoproc): Updated macro. + (IMEM32_MICROMIPS, IMEM16_MICROMIPS, MICROMIPS_MINOR_OPCODE, + MICROMIPS_DELAYSLOT_SIZE_ANY, MICROMIPS_DELAYSLOT_SIZE_16, + MICROMIPS_DELAYSLOT_SIZE_32, ISA_MODE_MIPS32 and + ISA_MODE_MICROMIPS): New defines. + (sim_state): Add isa_mode field. + 2015-06-23 Mike Frysinger <vapier@gentoo.org> * configure: Regenerate. diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in index 17eeab6..f02e1bd 100644 --- a/sim/mips/Makefile.in +++ b/sim/mips/Makefile.in @@ -35,7 +35,29 @@ SIM_M16_OBJ = \ itable.o \ m16run.o \ -SIM_MULTI_OBJ = itable.o @sim_multi_obj@ +SIM_MICROMIPS_OBJ = \ + micromips16_support.o \ + micromips16_semantics.o \ + micromips16_idecode.o \ + micromips16_icache.o \ + \ + micromips32_support.o \ + micromips32_semantics.o \ + micromips32_idecode.o \ + micromips32_icache.o \ + \ + micromips_m32_support.o \ + micromips_m32_semantics.o \ + micromips_m32_idecode.o \ + micromips_m32_icache.o \ + \ + itable.o \ + micromipsrun.o \ + + +SIM_MULTI_OBJ = @sim_multi_obj@ \ + itable.o \ + multi-run.o \ MIPS_EXTRA_LIBS = @mips_extra_libs@ @@ -68,11 +90,11 @@ SIM_EXTRA_LIBS = $(MIPS_EXTRA_LIBS) ## COMMON_POST_CONFIG_FRAG interp.o: $(srcdir)/interp.c config.h sim-main.h itable.h -cp1.o: $(srcdir)/cp1.c config.h sim-main.h -mdmx.o: $(srcdir)/mdmx.c $(srcdir)/sim-main.h +m16run.o: sim-main.h m16_idecode.h m32_idecode.h m16run.c $(SIM_EXTRA_DEPS) -dsp.o: $(srcdir)/dsp.c $(srcdir)/sim-main.h +micromipsrun.o: sim-main.h micromips16_idecode.h micromips32_idecode.h \ + micromips_m32_idecode.h micromipsrun.c $(SIM_EXTRA_DEPS) multi-run.o: multi-include.h tmp-mach-multi @@ -83,7 +105,11 @@ IGEN_TRACE= # -G omit-line-numbers # -G trace-rule-selection -G trace-rule-rejec IGEN_INSN=$(srcdir)/mips.igen IGEN_DC=$(srcdir)/mips.dc M16_DC=$(srcdir)/m16.dc +MICROMIPS32_DC=$(srcdir)/micromips.dc +MICROMIPS16_DC=$(srcdir)/micromips16.dc IGEN_INCLUDE=\ + $(srcdir)/micromipsdsp.igen \ + $(srcdir)/micromips.igen \ $(srcdir)/m16.igen \ $(srcdir)/m16e.igen \ $(srcdir)/mdmx.igen \ @@ -104,6 +130,7 @@ BUILT_SRC_FROM_GEN = \ SIM_IGEN_ALL = tmp-igen SIM_M16_ALL = tmp-m16 +SIM_MICROMIPS_ALL = tmp-micromips SIM_MULTI_ALL = tmp-multi $(BUILT_SRC_FROM_GEN): $(SIM_@sim_gen@_ALL) @@ -174,25 +201,6 @@ tmp-igen: $(IGEN_INSN) $(IGEN_DC) ../igen/igen $(IGEN_INCLUDE) $(SHELL) $(srcdir)/../../move-if-change tmp-irun.c irun.c touch tmp-igen -semantics.o: sim-main.h semantics.c $(SIM_EXTRA_DEPS) -engine.o: sim-main.h engine.c $(SIM_EXTRA_DEPS) -support.o: sim-main.h support.c $(SIM_EXTRA_DEPS) -idecode.o: sim-main.h idecode.c $(SIM_EXTRA_DEPS) -itable.o: sim-main.h itable.c $(SIM_EXTRA_DEPS) -m16run.o: sim-main.h m16_idecode.h m32_idecode.h $(SIM_EXTRA_DEPS) - -m16_semantics.o: sim-main.h m16_semantics.c $(SIM_EXTRA_DEPS) -m16_support.o: sim-main.h m16_support.c $(SIM_EXTRA_DEPS) -m16_idecode.o: sim-main.h m16_idecode.c $(SIM_EXTRA_DEPS) -m16_icache.o: sim-main.h m16_icache.c $(SIM_EXTRA_DEPS) - -m32_semantics.o: sim-main.h m32_semantics.c $(SIM_EXTRA_DEPS) -m32_support.o: sim-main.h m32_support.c $(SIM_EXTRA_DEPS) -m32_idecode.o: sim-main.h m32_idecode.c $(SIM_EXTRA_DEPS) -m32_icache.o: sim-main.h m32_icache.c $(SIM_EXTRA_DEPS) - -$(SIM_MULTI_OBJ): sim-main.h $(SIM_EXTRA_DEPS) - BUILT_SRC_FROM_M16 = \ m16_icache.h \ m16_icache.c \ @@ -284,8 +292,10 @@ tmp-m16: $(IGEN_INSN) $(IGEN_DC) ../igen/igen $(IGEN_INCLUDE) $(SHELL) $(srcdir)/../../move-if-change tmp-icache.c m32_icache.c $(SHELL) $(srcdir)/../../move-if-change tmp-idecode.h m32_idecode.h $(SHELL) $(srcdir)/../../move-if-change tmp-idecode.c m32_idecode.c - $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.h m32_semantics.h - $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.c m32_semantics.c + $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.h \ + m32_semantics.h + $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.c \ + m32_semantics.c $(SHELL) $(srcdir)/../../move-if-change tmp-model.h m32_model.h $(SHELL) $(srcdir)/../../move-if-change tmp-model.c m32_model.c $(SHELL) $(srcdir)/../../move-if-change tmp-support.h m32_support.h @@ -307,6 +317,196 @@ tmp-m16: $(IGEN_INSN) $(IGEN_DC) ../igen/igen $(IGEN_INCLUDE) $(SHELL) $(srcdir)/../../move-if-change tmp-itable.c itable.c touch tmp-m16 +BUILT_SRC_FROM_MICROMIPS = \ + micromips16_icache.h \ + micromips16_icache.c \ + micromips16_idecode.h \ + micromips16_idecode.c \ + micromips16_semantics.h \ + micromips16_semantics.c \ + micromips16_model.h \ + micromips16_model.c \ + micromips16_support.h \ + micromips16_support.c \ + \ + micromips32_icache.h \ + micromips32_icache.c \ + micromips32_idecode.h \ + micromips32_idecode.c \ + micromips32_semantics.h \ + micromips32_semantics.c \ + micromips32_model.h \ + micromips32_model.c \ + micromips32_support.h \ + micromips32_support.c \ + \ + micromips_m32_icache.h \ + micromips_m32_icache.c \ + micromips_m32_idecode.h \ + micromips_m32_idecode.c \ + micromips_m32_semantics.h \ + micromips_m32_semantics.c \ + micromips_m32_model.h \ + micromips_m32_model.c \ + micromips_m32_support.h \ + micromips_m32_support.c \ + +$(BUILT_SRC_FROM_MICROMIPS): tmp-micromips + +tmp-micromips: $(IGEN_INSN) $(IGEN_DC) ../igen/igen $(IGEN_INCLUDE) + cd ../igen && $(MAKE) + ../igen/igen \ + $(IGEN_TRACE) \ + -I $(srcdir) \ + -Werror \ + -Wnodiscard \ + @sim_micromips16_flags@ \ + -G gen-direct-access \ + -G gen-zero-r0 \ + -B 16 \ + -H 15 \ + -i $(IGEN_INSN) \ + -o $(MICROMIPS16_DC) \ + -P micromips16_ \ + -x \ + -n micromips16_icache.h -hc tmp-icache.h \ + -n micromips16_icache.c -c tmp-icache.c \ + -n micromips16_semantics.h -hs tmp-semantics.h \ + -n micromips16_semantics.c -s tmp-semantics.c \ + -n micromips16_idecode.h -hd tmp-idecode.h \ + -n micromips16_idecode.c -d tmp-idecode.c \ + -n micromips16_model.h -hm tmp-model.h \ + -n micromips16_model.c -m tmp-model.c \ + -n micromips16_support.h -hf tmp-support.h \ + -n micromips16_support.c -f tmp-support.c \ + # + $(SHELL) $(srcdir)/../../move-if-change tmp-icache.h \ + micromips16_icache.h + $(SHELL) $(srcdir)/../../move-if-change tmp-icache.c \ + micromips16_icache.c + $(SHELL) $(srcdir)/../../move-if-change tmp-idecode.h \ + micromips16_idecode.h + $(SHELL) $(srcdir)/../../move-if-change tmp-idecode.c \ + micromips16_idecode.c + $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.h \ + micromips16_semantics.h + $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.c \ + micromips16_semantics.c + $(SHELL) $(srcdir)/../../move-if-change tmp-model.h \ + micromips16_model.h + $(SHELL) $(srcdir)/../../move-if-change tmp-model.c \ + micromips16_model.c + $(SHELL) $(srcdir)/../../move-if-change tmp-support.h \ + micromips16_support.h + $(SHELL) $(srcdir)/../../move-if-change tmp-support.c \ + micromips16_support.c + cd ../igen && $(MAKE) + ../igen/igen \ + $(IGEN_TRACE) \ + -I $(srcdir) \ + -Werror \ + -Wnodiscard \ + @sim_micromips_flags@ \ + -G gen-direct-access \ + -G gen-zero-r0 \ + -B 32 \ + -H 31 \ + -i $(IGEN_INSN) \ + -o $(MICROMIPS32_DC) \ + -P micromips32_ \ + -x \ + -n micromips32_icache.h -hc tmp-icache.h \ + -n micromips32_icache.c -c tmp-icache.c \ + -n micromips32_semantics.h -hs tmp-semantics.h \ + -n micromips32_semantics.c -s tmp-semantics.c \ + -n micromips32_idecode.h -hd tmp-idecode.h \ + -n micromips32_idecode.c -d tmp-idecode.c \ + -n micromips32_model.h -hm tmp-model.h \ + -n micromips32_model.c -m tmp-model.c \ + -n micromips32_support.h -hf tmp-support.h \ + -n micromips32_support.c -f tmp-support.c \ + # + $(SHELL) $(srcdir)/../../move-if-change tmp-icache.h \ + micromips32_icache.h + $(SHELL) $(srcdir)/../../move-if-change tmp-icache.c \ + micromips32_icache.c + $(SHELL) $(srcdir)/../../move-if-change tmp-idecode.h \ + micromips32_idecode.h + $(SHELL) $(srcdir)/../../move-if-change tmp-idecode.c \ + micromips32_idecode.c + $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.h \ + micromips32_semantics.h + $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.c \ + micromips32_semantics.c + $(SHELL) $(srcdir)/../../move-if-change tmp-model.h \ + micromips32_model.h + $(SHELL) $(srcdir)/../../move-if-change tmp-model.c \ + micromips32_model.c + $(SHELL) $(srcdir)/../../move-if-change tmp-support.h \ + micromips32_support.h + $(SHELL) $(srcdir)/../../move-if-change tmp-support.c \ + micromips32_support.c + ../igen/igen \ + $(IGEN_TRACE) \ + -I $(srcdir) \ + -Werror \ + -Wnodiscard \ + @sim_igen_flags@ \ + -G gen-direct-access \ + -G gen-zero-r0 \ + -B 32 \ + -H 31 \ + -i $(IGEN_INSN) \ + -o $(IGEN_DC) \ + -P micromips_m32_ \ + -x \ + -n micromips_m32_icache.h -hc tmp-icache.h \ + -n micromips_m32_icache.c -c tmp-icache.c \ + -n micromips_m32_semantics.h -hs tmp-semantics.h \ + -n micromips_m32_semantics.c -s tmp-semantics.c \ + -n micromips_m32_idecode.h -hd tmp-idecode.h \ + -n micromips_m32_idecode.c -d tmp-idecode.c \ + -n micromips_m32_model.h -hm tmp-model.h \ + -n micromips_m32_model.c -m tmp-model.c \ + -n micromips_m32_support.h -hf tmp-support.h \ + -n micromips_m32_support.c -f tmp-support.c \ + # + $(SHELL) $(srcdir)/../../move-if-change tmp-icache.h \ + micromips_m32_icache.h + $(SHELL) $(srcdir)/../../move-if-change tmp-icache.c \ + micromips_m32_icache.c + $(SHELL) $(srcdir)/../../move-if-change tmp-idecode.h \ + micromips_m32_idecode.h + $(SHELL) $(srcdir)/../../move-if-change tmp-idecode.c \ + micromips_m32_idecode.c + $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.h \ + micromips_m32_semantics.h + $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.c \ + micromips_m32_semantics.c + $(SHELL) $(srcdir)/../../move-if-change tmp-model.h \ + micromips_m32_model.h + $(SHELL) $(srcdir)/../../move-if-change tmp-model.c \ + micromips_m32_model.c + $(SHELL) $(srcdir)/../../move-if-change tmp-support.h \ + micromips_m32_support.h + $(SHELL) $(srcdir)/../../move-if-change tmp-support.c \ + micromips_m32_support.c + ../igen/igen \ + $(IGEN_TRACE) \ + -I $(srcdir) \ + -Werror \ + -Wnodiscard \ + -Wnowidth \ + @sim_igen_flags@ @sim_micromips_flags@ @sim_micromips16_flags@\ + -G gen-direct-access \ + -G gen-zero-r0 \ + -i $(IGEN_INSN) \ + -n itable.h -ht tmp-itable.h \ + -n itable.c -t tmp-itable.c \ + # + $(SHELL) $(srcdir)/../../move-if-change tmp-itable.h itable.h + $(SHELL) $(srcdir)/../../move-if-change tmp-itable.c itable.c + touch tmp-micromips BUILT_SRC_FROM_MULTI = @sim_multi_src@ SIM_MULTI_IGEN_CONFIGS = @sim_multi_igen_configs@ @@ -319,6 +519,15 @@ tmp-mach-multi: $(IGEN_INSN) $(IGEN_DC) ../igen/igen $(IGEN_INCLUDE) m=`echo $${t} | sed -e 's/.*:\(.*\):.*/\1/'` ; \ f=`echo $${t} | sed -e 's/.*://'` ; \ case $${p} in \ + micromips16*) e="-B 16 -H 15 -o $(MICROMIPS16_DC) -F 16" ;; \ + micromips32* | micromips64*) \ + e="-B 32 -H 31 -o $(MICROMIPS32_DC) -F $${f}" ;; \ + micromips_m32*) \ + e="-B 32 -H 31 -o $(IGEN_DC) -F $${f}"; \ + m="mips32r2,mips3d,mdmx,dsp,dsp2,smartmips" ;; \ + micromips_m64*) \ + e="-B 32 -H 31 -o $(IGEN_DC) -F $${f}"; \ + m="mips64r2,mips3d,mdmx,dsp,dsp2,smartmips" ;; \ m16*) e="-B 16 -H 15 -o $(M16_DC) -F 16" ;; \ *) e="-B 32 -H 31 -o $(IGEN_DC) -F $${f}" ;; \ esac; \ @@ -348,18 +557,30 @@ tmp-mach-multi: $(IGEN_INSN) $(IGEN_DC) ../igen/igen $(IGEN_INCLUDE) -n $${p}_engine.h -he tmp-engine.h \ -n $${p}_engine.c -e tmp-engine.c \ || exit; \ - $(SHELL) $(srcdir)/../../move-if-change tmp-icache.h $${p}_icache.h ; \ - $(SHELL) $(srcdir)/../../move-if-change tmp-icache.c $${p}_icache.c ; \ - $(SHELL) $(srcdir)/../../move-if-change tmp-idecode.h $${p}_idecode.h ; \ - $(SHELL) $(srcdir)/../../move-if-change tmp-idecode.c $${p}_idecode.c ; \ - $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.h $${p}_semantics.h ; \ - $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.c $${p}_semantics.c ; \ - $(SHELL) $(srcdir)/../../move-if-change tmp-model.h $${p}_model.h ; \ - $(SHELL) $(srcdir)/../../move-if-change tmp-model.c $${p}_model.c ; \ - $(SHELL) $(srcdir)/../../move-if-change tmp-support.h $${p}_support.h ; \ - $(SHELL) $(srcdir)/../../move-if-change tmp-support.c $${p}_support.c ; \ - $(SHELL) $(srcdir)/../../move-if-change tmp-engine.h $${p}_engine.h ; \ - $(SHELL) $(srcdir)/../../move-if-change tmp-engine.c $${p}_engine.c ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-icache.h \ + $${p}_icache.h ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-icache.c \ + $${p}_icache.c ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-idecode.h \ + $${p}_idecode.h ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-idecode.c \ + $${p}_idecode.c ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.h \ + $${p}_semantics.h ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-semantics.c \ + $${p}_semantics.c ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-model.h \ + $${p}_model.h ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-model.c \ + $${p}_model.c ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-support.h \ + $${p}_support.h ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-support.c \ + $${p}_support.c ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-engine.h \ + $${p}_engine.h ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-engine.c \ + $${p}_engine.c ; \ done touch tmp-mach-multi tmp-itable-multi: $(IGEN_INSN) $(IGEN_DC) ../igen/igen $(IGEN_INCLUDE) @@ -380,7 +601,7 @@ tmp-itable-multi: $(IGEN_INSN) $(IGEN_DC) ../igen/igen $(IGEN_INCLUDE) $(SHELL) $(srcdir)/../../move-if-change tmp-itable.h itable.h $(SHELL) $(srcdir)/../../move-if-change tmp-itable.c itable.c touch tmp-itable-multi -tmp-run-multi: $(srcdir)/m16run.c +tmp-run-multi: $(srcdir)/m16run.c $(srcdir)/micromipsrun.c for t in $(SIM_MULTI_IGEN_CONFIGS); do \ case $${t} in \ m16*) \ @@ -389,7 +610,29 @@ tmp-run-multi: $(srcdir)/m16run.c -e "s/^sim_/m16$${m}_/" \ -e "s/m16_/m16$${m}_/" \ -e "s/m32_/m32$${m}_/" ; \ - $(SHELL) $(srcdir)/../../move-if-change tmp-run m16$${m}_run.c ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-run \ + m16$${m}_run.c ; \ + ;;\ + micromips32*) \ + m=`echo $${t} | sed -e 's/^micromips32//' -e 's/:.*//'`; \ + sed < $(srcdir)/micromipsrun.c > tmp-run \ + -e "s/^sim_/micromips32$${m}_/" \ + -e "s/micromips16_/micromips16$${m}_/" \ + -e "s/micromips32_/micromips32$${m}_/" \ + -e "s/m32_/m32$${m}_/" ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-run \ + micromips$${m}_run.c ; \ + ;;\ + micromips64*) \ + m=`echo $${t} | sed -e 's/^micromips64//' -e 's/:.*//'`; \ + sed < $(srcdir)/micromipsrun.c > tmp-run \ + -e "s/^sim_/micromips64$${m}_/" \ + -e "s/micromips16_/micromips16$${m}_/" \ + -e "s/micromips32_/micromips64$${m}_/" \ + -e "s/m32_/m64$${m}_/" ; \ + $(SHELL) $(srcdir)/../../move-if-change tmp-run \ + micromips$${m}_run.c ; \ + ;;\ esac \ done touch tmp-run-multi @@ -398,9 +641,10 @@ clean-extra: rm -f $(BUILT_SRC_FROM_GEN) rm -f $(BUILT_SRC_FROM_IGEN) rm -f $(BUILT_SRC_FROM_M16) + rm -f $(BUILT_SRC_FROM_MICROMIPS) rm -f $(BUILT_SRC_FROM_MULTI) rm -f tmp-* - rm -f m16*.o m32*.o itable*.o + rm -f micromips16*.o micromips32*.o m16*.o m32*.o itable*.o distclean-extra: rm -f multi-include.h multi-run.c diff --git a/sim/mips/configure b/sim/mips/configure index f073b2b..67f7e09 100755 --- a/sim/mips/configure +++ b/sim/mips/configure @@ -609,6 +609,8 @@ sim_multi_src sim_multi_igen_configs sim_multi_flags sim_gen +sim_micromips16_flags +sim_micromips_flags sim_m16_flags sim_igen_flags SIM_SUBTARGET @@ -12347,7 +12349,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12350 "configure" +#line 12352 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12453,7 +12455,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12456 "configure" +#line 12458 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -13674,11 +13676,11 @@ case "${target}" in sim_multi_default=mips5000 ;; mips*-sde-elf* | mips*-mti-elf*) - sim_gen=M16 - sim_igen_machine="-M mips64r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips" - sim_m16_machine="-M mips16,mips16e,mips64r2" - sim_igen_filter="32,64,f" - sim_mach_default="mipsisa64r2" + sim_gen=MULTI + sim_multi_configs="\ + micromips:micromips64,micromipsdsp:32,64,f:mips_micromips\ + mips64r2:mips64r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,64,f:mipsisa64r2" + sim_multi_default=mipsisa64r2 ;; mips64*-*-*) sim_igen_filter="32,64,f" sim_gen=IGEN @@ -13687,11 +13689,11 @@ case "${target}" in sim_igen_filter="32,64,f" sim_m16_filter="16" ;; - mipsisa32r2*-*-*) sim_gen=M16 - sim_igen_machine="-M mips32r2,mips16,mips16e,mdmx,dsp,dsp2,smartmips" - sim_m16_machine="-M mips16,mips16e,mips32r2" - sim_igen_filter="32,f" - sim_mach_default="mipsisa32r2" + mipsisa32r2*-*-*) sim_gen=MULTI + sim_multi_configs="\ + micromips:micromips32,micromipsdsp:32,f:mips_micromips\ + mips32r2:mips32r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,f:mipsisa32r2" + sim_multi_default=mipsisa32r2 ;; mipsisa32*-*-*) sim_gen=M16 sim_igen_machine="-M mips32,mips16,mips16e,smartmips" @@ -13763,7 +13765,7 @@ if test ${sim_gen} = MULTI; then rm -f multi-include.h multi-run.c sim_multi_flags= sim_multi_src= - sim_multi_obj=multi-run.o + sim_multi_obj= sim_multi_igen_configs= sim_seen_default=no @@ -13790,6 +13792,8 @@ if test ${sim_gen} = MULTI; then #include "sim-main.h" #include "multi-include.h" +#include "elf-bfd.h" +#include "elf/mips.h" #define SD sd #define CPU cpu @@ -13804,6 +13808,9 @@ sim_engine_run (SIM_DESC sd, if (STATE_ARCHITECTURE (sd) == NULL) mach = bfd_mach_${sim_multi_default}; + else if (elf_elfheader (sd->base.prog_bfd)->e_flags + & EF_MIPS_ARCH_ASE_MICROMIPS) + mach = bfd_mach_mips_micromips; else mach = STATE_ARCHITECTURE (SD)->mach; @@ -13833,7 +13840,7 @@ __EOF__ # the ${sim_multi_configs} entry. sim_multi_flags="${sim_multi_flags} -F ${filter} -M ${machine}" - # Check whether mips16 handling is needed. + # Check whether special handling is needed. case ${c} in *:*mips16*:*) # Run igen twice, once for normal mode and once for mips16. @@ -13846,6 +13853,30 @@ __EOF__ sim_multi_obj="${sim_multi_obj} m16${name}_run.o" sim_multi_flags="${sim_multi_flags} -F 16" ;; + *:*micromips32*:*) + # Run igen thrice, once for micromips32, once for micromips16, + # and once for m32. + ws="micromips_m32 micromips16 micromips32" + + # The top-level function for the micromips simulator is + # in a file micromips${name}_run.c, generated by the + # tmp-run-multi Makefile rule. + sim_multi_src="${sim_multi_src} micromips${name}_run.c" + sim_multi_obj="${sim_multi_obj} micromips${name}_run.o" + sim_multi_flags="${sim_multi_flags} -F 16,32" + ;; + *:*micromips64*:*) + # Run igen thrice, once for micromips64, once for micromips16, + # and once for m64. + ws="micromips_m64 micromips16 micromips64" + + # The top-level function for the micromips simulator is + # in a file micromips${name}_run.c, generated by the + # tmp-run-multi Makefile rule. + sim_multi_src="${sim_multi_src} micromips${name}_run.c" + sim_multi_obj="${sim_multi_obj} micromips${name}_run.o" + sim_multi_flags="${sim_multi_flags} -F 16,32,64" + ;; *) ws=m32 ;; @@ -13931,6 +13962,8 @@ else fi sim_igen_flags="-F ${sim_igen_filter} ${sim_igen_machine} ${sim_igen_smp}" sim_m16_flags=" -F ${sim_m16_filter} ${sim_m16_machine} ${sim_igen_smp}" +sim_micromips16_flags=" -F ${sim_micromips16_filter} ${sim_micromips16_machine} ${sim_igen_smp}" +sim_micromips_flags=" -F ${sim_micromips_filter} ${sim_micromips_machine} ${sim_igen_smp}" diff --git a/sim/mips/configure.ac b/sim/mips/configure.ac index d786351..a642326 100644 --- a/sim/mips/configure.ac +++ b/sim/mips/configure.ac @@ -139,11 +139,11 @@ case "${target}" in sim_multi_default=mips5000 ;; mips*-sde-elf* | mips*-mti-elf*) - sim_gen=M16 - sim_igen_machine="-M mips64r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips" - sim_m16_machine="-M mips16,mips16e,mips64r2" - sim_igen_filter="32,64,f" - sim_mach_default="mipsisa64r2" + sim_gen=MULTI + sim_multi_configs="\ + micromips:micromips64,micromipsdsp:32,64,f:mips_micromips\ + mips64r2:mips64r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,64,f:mipsisa64r2" + sim_multi_default=mipsisa64r2 ;; mips64*-*-*) sim_igen_filter="32,64,f" sim_gen=IGEN @@ -152,11 +152,11 @@ case "${target}" in sim_igen_filter="32,64,f" sim_m16_filter="16" ;; - mipsisa32r2*-*-*) sim_gen=M16 - sim_igen_machine="-M mips32r2,mips16,mips16e,mdmx,dsp,dsp2,smartmips" - sim_m16_machine="-M mips16,mips16e,mips32r2" - sim_igen_filter="32,f" - sim_mach_default="mipsisa32r2" + mipsisa32r2*-*-*) sim_gen=MULTI + sim_multi_configs="\ + micromips:micromips32,micromipsdsp:32,f:mips_micromips\ + mips32r2:mips32r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,f:mipsisa32r2" + sim_multi_default=mipsisa32r2 ;; mipsisa32*-*-*) sim_gen=M16 sim_igen_machine="-M mips32,mips16,mips16e,smartmips" @@ -228,7 +228,7 @@ if test ${sim_gen} = MULTI; then rm -f multi-include.h multi-run.c sim_multi_flags= sim_multi_src= - sim_multi_obj=multi-run.o + sim_multi_obj= sim_multi_igen_configs= sim_seen_default=no @@ -255,6 +255,8 @@ if test ${sim_gen} = MULTI; then #include "sim-main.h" #include "multi-include.h" +#include "elf-bfd.h" +#include "elf/mips.h" #define SD sd #define CPU cpu @@ -269,6 +271,9 @@ sim_engine_run (SIM_DESC sd, if (STATE_ARCHITECTURE (sd) == NULL) mach = bfd_mach_${sim_multi_default}; + else if (elf_elfheader (sd->base.prog_bfd)->e_flags + & EF_MIPS_ARCH_ASE_MICROMIPS) + mach = bfd_mach_mips_micromips; else mach = STATE_ARCHITECTURE (SD)->mach; @@ -298,7 +303,7 @@ __EOF__ # the ${sim_multi_configs} entry. sim_multi_flags="${sim_multi_flags} -F ${filter} -M ${machine}" - # Check whether mips16 handling is needed. + # Check whether special handling is needed. case ${c} in *:*mips16*:*) # Run igen twice, once for normal mode and once for mips16. @@ -311,6 +316,30 @@ __EOF__ sim_multi_obj="${sim_multi_obj} m16${name}_run.o" sim_multi_flags="${sim_multi_flags} -F 16" ;; + *:*micromips32*:*) + # Run igen thrice, once for micromips32, once for micromips16, + # and once for m32. + ws="micromips_m32 micromips16 micromips32" + + # The top-level function for the micromips simulator is + # in a file micromips${name}_run.c, generated by the + # tmp-run-multi Makefile rule. + sim_multi_src="${sim_multi_src} micromips${name}_run.c" + sim_multi_obj="${sim_multi_obj} micromips${name}_run.o" + sim_multi_flags="${sim_multi_flags} -F 16,32" + ;; + *:*micromips64*:*) + # Run igen thrice, once for micromips64, once for micromips16, + # and once for m64. + ws="micromips_m64 micromips16 micromips64" + + # The top-level function for the micromips simulator is + # in a file micromips${name}_run.c, generated by the + # tmp-run-multi Makefile rule. + sim_multi_src="${sim_multi_src} micromips${name}_run.c" + sim_multi_obj="${sim_multi_obj} micromips${name}_run.o" + sim_multi_flags="${sim_multi_flags} -F 16,32,64" + ;; *) ws=m32 ;; @@ -396,15 +425,17 @@ else fi sim_igen_flags="-F ${sim_igen_filter} ${sim_igen_machine} ${sim_igen_smp}" sim_m16_flags=" -F ${sim_m16_filter} ${sim_m16_machine} ${sim_igen_smp}" +sim_micromips16_flags=" -F ${sim_micromips16_filter} ${sim_micromips16_machine} ${sim_igen_smp}" +sim_micromips_flags=" -F ${sim_micromips_filter} ${sim_micromips_machine} ${sim_igen_smp}" AC_SUBST(sim_igen_flags) AC_SUBST(sim_m16_flags) +AC_SUBST(sim_micromips_flags) +AC_SUBST(sim_micromips16_flags) AC_SUBST(sim_gen) AC_SUBST(sim_multi_flags) AC_SUBST(sim_multi_igen_configs) AC_SUBST(sim_multi_src) AC_SUBST(sim_multi_obj) - - # # Add simulated hardware devices # diff --git a/sim/mips/dsp.igen b/sim/mips/dsp.igen index 96a25dc..b8d5a6c 100644 --- a/sim/mips/dsp.igen +++ b/sim/mips/dsp.igen @@ -4,7 +4,7 @@ // Copyright (C) 2005-2015 Free Software Foundation, Inc. // Contributed by MIPS Technologies, Inc. Written by Chao-ying Fu. // -// This file is part of GDB, the GNU debugger. +// This file is part of the MIPS sim // // 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 @@ -247,6 +247,622 @@ GPR[rd] = EXTEND32 (result); } +:function:::void:do_ph_s_absq:int rd, int rt +{ + int i; + signed16 h0; + unsigned32 v1 = GPR[rt]; + unsigned32 result = 0; + for (i = 0; i < 32; i += 16, v1 >>= 16) + { + h0 = (signed16)(v1 & 0xffff); + if (h0 == (signed16)0x8000) + { + DSPCR |= DSPCR_OUFLAG4; + h0 = 0x7fff; + } + else if (h0 & 0x8000) + h0 = -h0; + result |= ((unsigned32)((unsigned16)h0) << i); + } + GPR[rd] = EXTEND32 (result); +} + +:function:::void:do_w_s_absq:int rd, int rt +{ + unsigned32 v1 = GPR[rt]; + signed32 h0 = (signed32)v1; + if (h0 == (signed32)0x80000000) + { + DSPCR |= DSPCR_OUFLAG4; + h0 = 0x7fffffff; + } + else if (h0 & 0x80000000) + h0 = -h0; + GPR[rd] = EXTEND32 (h0); +} + +:function:::void:do_qb_s_absq:int rd, int rt +{ + int i; + signed8 q0; + unsigned32 v1 = GPR[rt]; + unsigned32 result = 0; + for (i = 0; i < 32; i += 8, v1 >>= 8) + { + q0 = (signed8)(v1 & 0xff); + if (q0 == (signed8)0x80) + { + DSPCR |= DSPCR_OUFLAG4; + q0 = 0x7f; + } + else if (q0 & 0x80) + q0 = -q0; + result |= ((unsigned32)((unsigned8)q0) << i); + } + GPR[rd] = EXTEND32 (result); +} + +:function:::void:do_addsc:int rd, int rs, int rt +{ + unsigned32 v1 = GPR[rs]; + unsigned32 v2 = GPR[rt]; + unsigned64 h0; + h0 = (unsigned64)v1 + (unsigned64)v2; + if (h0 & 0x100000000LL) + DSPCR |= DSPCR_CARRY; + GPR[rd] = EXTEND32 (h0); +} + +:function:::void:do_addwc:int rd, int rs, int rt +{ + unsigned32 v1 = GPR[rs]; + unsigned32 v2 = GPR[rt]; + unsigned64 h0; + signed32 h1 = (signed32) v1; + signed32 h2 = (signed32) v2; + h0 = (signed64)h1 + (signed64)h2 + + (signed64)((DSPCR >> DSPCR_CARRY_SHIFT) & DSPCR_CARRY_MASK); + if (((h0 & 0x100000000LL) >> 1) != (h0 & 0x80000000)) + DSPCR |= DSPCR_OUFLAG4; + GPR[rd] = EXTEND32 (h0); +} + +:function:::void:do_bitrev:int rd, int rt +{ + int i; + unsigned32 v1 = GPR[rt]; + unsigned32 h1 = 0; + for (i = 0; i < 16; i++) + { + if (v1 & (1 << i)) + h1 |= (1 << (15 - i)); + } + GPR[rd] = EXTEND32 (h1); +} + +// op: 0 = EXTPV, 1 = EXTPDPV +:function:::void:do_extpv:int rt, int ac, int rs, int op +{ + unsigned32 size = GPR[rs] & 0x1f; + do_extp (SD_, rt, ac, size, op); +} + +// op: 0 = EXTRV, 1 = EXTRV_R, 2 = EXTRV_RS +:function:::void:do_extrv:int rt, int ac, int rs, int op +{ + unsigned32 shift = GPR[rs] & 0x1f; + do_w_extr (SD_, rt, ac, shift, op); +} + +:function:::void:do_extrv_s_h:int rt, int ac, int rs +{ + unsigned32 shift = GPR[rs] & 0x1f; + do_h_extr (SD_, rt, ac, shift); +} + +:function:::void:do_insv:int rt, int rs +{ + unsigned32 v1 = GPR[rs]; + unsigned32 v2 = GPR[rt]; + unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK; + unsigned32 size = (DSPCR >> DSPCR_SCOUNT_SHIFT) & DSPCR_SCOUNT_MASK; + unsigned32 mask1, mask2, mask3, result; + if (size < 32) + mask1 = (1 << size) - 1; + else + mask1 = 0xffffffff; + mask2 = (1 << pos) - 1; + if (pos + size < 32) + mask3 = ~((1 << (pos + size)) - 1); + else + mask3 = 0; + result = (v2 & mask3) | ((v1 & mask1) << pos) | (v2 & mask2); + GPR[rt] = EXTEND32 (result); +} + +// op: 0 = NORMAL, 1 = EXTEND16, 2 = EXTEND32 +:function:::void:do_lxx:int rd, int base, int index, int op +{ + if (op == 0) + GPR[rd] = do_load (SD_, AccessLength_BYTE, GPR[base], GPR[index]); + else if (op == 1) + GPR[rd] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[base], GPR[index])); + else if (op == 2) + GPR[rd] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[base], GPR[index])); +} + +:function:::void:do_modsub:int rd, int rs, int rt +{ + unsigned32 result = 0; + unsigned32 v1 = GPR[rs]; + unsigned32 v2 = GPR[rt]; + unsigned32 decr = v2 & 0xff; + unsigned32 lastindex = (v2 & 0xffff00) >> 8; + if (v1 == 0) + result = lastindex; + else + result = v1 - decr; + GPR[rd] = EXTEND32 (result); +} + +:function:::void:do_mthlip:int rs, int ac +{ + unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK; + DSPHI(ac) = DSPLO(ac); + DSPLO(ac) = GPR[rs]; + if (pos >= 32) + Unpredictable (); + else + pos += 32; + DSPCR &= (~DSPCR_POS_SMASK); + DSPCR |= (pos & DSPCR_POS_MASK) << DSPCR_POS_SHIFT; +} + +:function:::void:do_mulsaq_s_w_ph:int ac, int rs, int rt +{ + int i; + unsigned32 v1 = GPR[rs]; + unsigned32 v2 = GPR[rt]; + signed16 h1, h2; + signed32 result; + unsigned32 lo = DSPLO(ac); + unsigned32 hi = DSPHI(ac); + signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo); + for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16) + { + h1 = (signed16)(v1 & 0xffff); + h2 = (signed16)(v2 & 0xffff); + if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000) + { + DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + ac)); + result = (signed32) 0x7fffffff; + } + else + result = ((signed32)h1 * (signed32)h2) << 1; + + if (i == 0) + prod -= (signed64) result; + else + prod += (signed64) result; + } + DSPLO(ac) = EXTEND32 (prod); + DSPHI(ac) = EXTEND32 (prod >> 32); +} + +:function:::void:do_ph_packrl:int rd, int rs, int rt +{ + + unsigned32 v1 = GPR[rs]; + unsigned32 v2 = GPR[rt]; + GPR[rd] = EXTEND32 ((v1 << 16) + (v2 >> 16)); +} + +:function:::void:do_qb_pick:int rd, int rs, int rt +{ + int i, j; + unsigned32 v1 = GPR[rs]; + unsigned32 v2 = GPR[rt]; + unsigned8 h1, h2; + unsigned32 result = 0; + for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8) + { + h1 = (unsigned8)(v1 & 0xff); + h2 = (unsigned8)(v2 & 0xff); + if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j))) + result |= (unsigned32)(h1 << i); + else + result |= (unsigned32)(h2 << i); + } + GPR[rd] = EXTEND32 (result); +} + +:function:::void:do_ph_pick:int rd, int rs, int rt +{ + int i, j; + unsigned32 v1 = GPR[rs]; + unsigned32 v2 = GPR[rt]; + unsigned16 h1, h2; + unsigned32 result = 0; + for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16) + { + h1 = (unsigned16)(v1 & 0xffff); + h2 = (unsigned16)(v2 & 0xffff); + if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j))) + result |= (unsigned32)(h1 << i); + else + result |= (unsigned32)(h2 << i); + } + GPR[rd] = EXTEND32 (result); +} + +// op: 0 = QBR, 1 = QBRA, 2 = QBL, 3 = QBLA +:function:::void:do_qb_ph_precequ:int rd, int rt, int op +{ + unsigned32 v1 = GPR[rt]; + if (op == 0) + GPR[rd] = EXTEND32 ((v1 & 0xff00) << 15) | ((v1 & 0xff) << 7); + else if (op == 1) + GPR[rd] = EXTEND32 ((v1 & 0xff0000) << 7) | ((v1 & 0xff) << 7); + else if (op == 2) + GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff0000) >> 9); + else if (op == 3) + GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff00) >> 1); +} + +// op: 0 = QBR, 1 = QBRA, 2 = QBL, 3 = QBLA +:function:::void:do_qb_ph_preceu:int rd, int rt, int op +{ + unsigned32 v1 = GPR[rt]; + if (op == 0) + GPR[rd] = EXTEND32 ((v1 & 0xff00) << 8) | (v1 & 0xff); + else if (op == 1) + GPR[rd] = EXTEND32 ((v1 & 0xff0000) | (v1 & 0xff)); + else if (op == 2) + GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff0000) >> 16); + else if (op == 3) + GPR[rd] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff00) >> 8); +} + +// op: 0 = .PHL, 1 = PHR +:function:::void:do_w_preceq:int rd, int rt, int op +{ + unsigned32 v1 = GPR[rt]; + if (op == 0) + GPR[rd] = EXTEND32 (v1 & 0xffff0000); + else if (op == 1) + GPR[rd] = EXTEND32 ((v1 & 0xffff) << 16); +} + +:function:::void:do_w_ph_precrq:int rd, int rs, int rt +{ + unsigned32 v1 = GPR[rs]; + unsigned32 v2 = GPR[rt]; + unsigned32 tempu = (v1 & 0xffff0000) >> 16; + unsigned32 tempv = (v2 & 0xffff0000) >> 16; + GPR[rd] = EXTEND32 ((tempu << 16) | tempv); +} + +// sat: 0 = PRECRQ.QB.PH, 1 = PRECRQU_S.QB.PH +:function:::void:do_ph_qb_precrq:int rd, int rs, int rt, int sat +{ + unsigned32 v1 = GPR[rs]; + unsigned32 v2 = GPR[rt]; + unsigned32 tempu = 0, tempv = 0, tempw = 0, tempx = 0; + if (sat == 0) + { + tempu = (v1 & 0xff000000) >> 24; + tempv = (v1 & 0xff00) >> 8; + tempw = (v2 & 0xff000000) >> 24; + tempx = (v2 & 0xff00) >> 8; + } + else if (sat == 1) + { + if (v1 & 0x80000000) + { + DSPCR |= DSPCR_OUFLAG6; + tempu = 0; + } + else if (!(v1 & 0x80000000) && ((v1 >> 16) > (unsigned32)0x7f80)) + { + DSPCR |= DSPCR_OUFLAG6; + tempu = 0xff; + } + else + tempu = (v1 & 0x7f800000) >> 23; + if (v1 & 0x8000) + { + DSPCR |= DSPCR_OUFLAG6; + tempv = 0; + } + else if (!(v1 & 0x8000) && ((v1 & 0xffff) > (unsigned32)0x7f80)) + { + DSPCR |= DSPCR_OUFLAG6; + tempv = 0xff; + } + else + tempv = (v1 & 0x7f80) >> 7; + if (v2 & 0x80000000) + { + DSPCR |= DSPCR_OUFLAG6; + tempw = 0; + } + else if (!(v2 & 0x80000000) && ((v2 >> 16) > (unsigned32)0x7f80)) + { + DSPCR |= DSPCR_OUFLAG6; + tempw = 0xff; + } + else + tempw = (v2 & 0x7f800000) >> 23; + if (v2 & 0x8000) + { + DSPCR |= DSPCR_OUFLAG6; + tempx = 0; + } + else if (!(v2 & 0x8000) && ((v2 & 0xffff) > (unsigned32)0x7f80)) + { + DSPCR |= DSPCR_OUFLAG6; + tempx = 0xff; + } + else + tempx = (v2 & 0x7f80) >> 7; + } + GPR[rd] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx); +} + +:function:::void:do_w_ph_rs_precrq:int rd, int rs, int rt +{ + unsigned32 v1 = GPR[rs]; + unsigned32 v2 = GPR[rt]; + signed32 h1 = (signed32)v1; + signed32 h2 = (signed32)v2; + signed64 temp1 = (signed64)h1 + (signed64)0x8000; + signed32 temp2; + signed64 temp3 = (signed64)h2 + (signed64)0x8000; + signed32 temp4; + if (((temp1 & 0x100000000LL) >> 1) != (temp1 & 0x80000000)) + { + DSPCR |= DSPCR_OUFLAG6; + temp2 = 0x7fff; + } + else + temp2 = (signed32)((temp1 & 0xffff0000) >> 16); + if (((temp3 & 0x100000000LL) >> 1) != (temp3 & 0x80000000)) + { + DSPCR |= DSPCR_OUFLAG6; + temp4 = 0x7fff; + } + else + temp4 = (signed32)((temp3 & 0xffff0000) >> 16); + GPR[rd] = EXTEND32 ((temp2 << 16) | temp4); +} + +:function:::void:do_qb_w_raddu:int rd, int rs +{ + int i; + unsigned8 h0; + unsigned32 v1 = GPR[rs]; + unsigned32 result = 0; + for (i = 0; i < 32; i += 8, v1 >>= 8) + { + h0 = (unsigned8)(v1 & 0xff); + result += (unsigned32)h0; + } + GPR[rd] = EXTEND32 (result); +} + +:function:::void:do_rddsp:int rd, int mask +{ + unsigned32 result = 0; + if (mask & 0x1) + { + result &= (~DSPCR_POS_SMASK); + result |= (DSPCR & DSPCR_POS_SMASK); + } + if (mask & 0x2) + { + result &= (~DSPCR_SCOUNT_SMASK); + result |= (DSPCR & DSPCR_SCOUNT_SMASK); + } + if (mask & 0x4) + { + result &= (~DSPCR_CARRY_SMASK); + result |= (DSPCR & DSPCR_CARRY_SMASK); + } + if (mask & 0x8) + { + result &= (~DSPCR_OUFLAG_SMASK); + result |= (DSPCR & DSPCR_OUFLAG_SMASK); + } + if (mask & 0x10) + { + result &= (~DSPCR_CCOND_SMASK); + result |= (DSPCR & DSPCR_CCOND_SMASK); + } + if (mask & 0x20) + { + result &= (~DSPCR_EFI_SMASK); + result |= (DSPCR & DSPCR_EFI_SMASK); + } + GPR[rd] = EXTEND32 (result); +} + +// op: 0 = REPL.QB, 1 = REPLV.QB, 2 = REPL.PH, 3 = REPLV.PH +:function:::void:do_repl:int rd, int p2, int op +{ + if (op == 0) + GPR[rd] = EXTEND32 ((p2 << 24) | (p2 << 16) | (p2 << 8) | p2); + else if (op == 1) + { + unsigned32 v1 = GPR[p2] & 0xff; + GPR[rd] = EXTEND32 ((v1 << 24) | (v1 << 16) | (v1 << 8) | v1); + } + else if (op == 2) + { + signed32 v1 = p2; + if (v1 & 0x200) + v1 |= 0xfffffc00; + GPR[rd] = EXTEND32 ((v1 << 16) | (v1 & 0xffff)); + } + else if (op == 3) + { + unsigned32 v1 = GPR[p2]; + v1 = v1 & 0xffff; + GPR[rd] = EXTEND32 ((v1 << 16) | v1); + } +} + +:function:::void:do_shilov:int ac, int rs +{ + signed32 shift = GPR[rs] & 0x3f; + do_shilo (SD_, ac, shift); +} + +// op: 0 = SHLLV, 1 = SHRAV +// sat: 0 = normal, 1 = saturate/rounding +:function:::void:do_ph_shl:int rd, int rt, int rs, int op, int sat +{ + unsigned32 shift = GPR[rs] & 0xf; + do_ph_shift (SD_, rd, rt, shift, op, sat); +} + +// op: 0 = SHLLV, 1 = SHRLV +:function:::void:do_qb_shl:int rd, int rt, int rs, int op +{ + unsigned32 shift = GPR[rs] & 0x7; + do_qb_shift (SD_, rd, rt, shift, op); +} + +:function:::void:do_w_s_shllv:int rd, int rt, int rs +{ + unsigned32 shift = GPR[rs] & 0x1f; + do_w_shll (SD_, rd, rt, shift); +} + +:function:::void:do_ph_shrlv:int rd, int rt, int rs +{ + unsigned32 shift = GPR[rs] & 0xf; + do_ph_shrl (SD_, rd, rt, shift); +} + +:function:::void:do_w_r_shrav:int rd, int rt, int rs +{ + unsigned32 shift = GPR[rs] & 0x1f; + do_w_shra (SD_, rd, rt, shift); +} + +:function:::void:do_wrdsp:int rs, int mask +{ + unsigned32 v1 = GPR[rs]; + if (mask & 0x1) + { + DSPCR &= (~DSPCR_POS_SMASK); + DSPCR |= (v1 & DSPCR_POS_SMASK); + } + if (mask & 0x2) + { + DSPCR &= (~DSPCR_SCOUNT_SMASK); + DSPCR |= (v1 & DSPCR_SCOUNT_SMASK); + } + if (mask & 0x4) + { + DSPCR &= (~DSPCR_CARRY_SMASK); + DSPCR |= (v1 & DSPCR_CARRY_SMASK); + } + if (mask & 0x8) + { + DSPCR &= (~DSPCR_OUFLAG_SMASK); + DSPCR |= (v1 & DSPCR_OUFLAG_SMASK); + } + if (mask & 0x10) + { + DSPCR &= (~DSPCR_CCOND_SMASK); + DSPCR |= (v1 & DSPCR_CCOND_SMASK); + } + if (mask & 0x20) + { + DSPCR &= (~DSPCR_EFI_SMASK); + DSPCR |= (v1 & DSPCR_EFI_SMASK); + } +} + +// round: 0 = no rounding, 1 = rounding +:function:::void:do_qb_shrav:int rd, int rt, int rs, int round +{ + unsigned32 shift = GPR[rs] & 0x7; + do_qb_shra (SD_, rd, rt, shift, round); +} + +:function:::void:do_append:int rt, int rs, int sa +{ + unsigned32 v0 = GPR[rs]; + unsigned32 v1 = GPR[rt]; + unsigned32 result; + unsigned32 mask = (1 << sa) - 1; + result = (v1 << sa) | (v0 & mask); + GPR[rt] = EXTEND32 (result); +} + +:function:::void:do_balign:int rt, int rs, int bp +{ + unsigned32 v0 = GPR[rs]; + unsigned32 v1 = GPR[rt]; + unsigned32 result; + if (bp == 0) + result = v1; + else + result = (v1 << 8 * bp) | (v0 >> 8 * (4 - bp)); + GPR[rt] = EXTEND32 (result); +} + +:function:::void:do_ph_w_mulsa:int ac, int rs, int rt +{ + int i; + unsigned32 v1 = GPR[rs]; + unsigned32 v2 = GPR[rt]; + signed16 h1, h2; + signed32 result; + unsigned32 lo = DSPLO(ac); + unsigned32 hi = DSPHI(ac); + signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo); + for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16) + { + h1 = (signed16)(v1 & 0xffff); + h2 = (signed16)(v2 & 0xffff); + result = (signed32)h1 * (signed32)h2; + + if (i == 0) + prod -= (signed64) result; + else + prod += (signed64) result; + } + DSPLO(ac) = EXTEND32 (prod); + DSPHI(ac) = EXTEND32 (prod >> 32); +} + +:function:::void:do_ph_qb_precr:int rd, int rs, int rt +{ + unsigned32 v1 = GPR[rs]; + unsigned32 v2 = GPR[rt]; + unsigned32 tempu = (v1 & 0xff0000) >> 16; + unsigned32 tempv = (v1 & 0xff); + unsigned32 tempw = (v2 & 0xff0000) >> 16; + unsigned32 tempx = (v2 & 0xff); + GPR[rd] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx); +} + +:function:::void:do_prepend:int rt, int rs, int sa +{ + unsigned32 v0 = GPR[rs]; + unsigned32 v1 = GPR[rt]; + unsigned32 result; + if (sa == 0) + result = v1; + else + result = (v0 << (32 - sa)) | (v1 >> sa); + GPR[rt] = EXTEND32 (result); +} + :function:::void:do_w_shra:int rd, int rt, int shift { unsigned32 result = GPR[rt]; @@ -332,291 +948,140 @@ "addsc r<RD>, r<RS>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - unsigned64 h0; - h0 = (unsigned64)v1 + (unsigned64)v2; - if (h0 & 0x100000000LL) - DSPCR |= DSPCR_CARRY; - GPR[RD] = EXTEND32 (h0); + do_addsc (SD_, RD, RS, RT); } 011111,5.RS,5.RT,5.RD,10001,010000:SPECIAL3:32::ADDWC "addwc r<RD>, r<RS>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - unsigned64 h0; - signed32 h1 = (signed32) v1; - signed32 h2 = (signed32) v2; - h0 = (signed64)h1 + (signed64)h2 - + (signed64)((DSPCR >> DSPCR_CARRY_SHIFT) & DSPCR_CARRY_MASK); - if (((h0 & 0x100000000LL) >> 1) != (h0 & 0x80000000)) - DSPCR |= DSPCR_OUFLAG4; - GPR[RD] = EXTEND32 (h0); + do_addwc (SD_, RD, RS, RT); } 011111,5.RS,5.RT,5.RD,10010,010000:SPECIAL3:32::MODSUB "modsub r<RD>, r<RS>, r<RT>" *dsp: { - unsigned32 result = 0; - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - unsigned32 decr = v2 & 0xff; - unsigned32 lastindex = (v2 & 0xffff00) >> 8; - if (v1 == 0) - result = lastindex; - else - result = v1 - decr; - GPR[RD] = EXTEND32 (result); + do_modsub (SD_, RD, RS, RT); } 011111,5.RS,00000,5.RD,10100,010000:SPECIAL3:32::RADDU.W.QB "raddu.w.qb r<RD>, r<RS>" *dsp: { - int i; - unsigned8 h0; - unsigned32 v1 = GPR[RS]; - unsigned32 result = 0; - for (i = 0; i < 32; i += 8, v1 >>= 8) - { - h0 = (unsigned8)(v1 & 0xff); - result += (unsigned32)h0; - } - GPR[RD] = EXTEND32 (result); + do_qb_w_raddu (SD_, RD, RS); } 011111,00000,5.RT,5.RD,01001,010010:SPECIAL3:32::ABSQ_S.PH "absq_s.ph r<RD>, r<RT>" *dsp: { - int i; - signed16 h0; - unsigned32 v1 = GPR[RT]; - unsigned32 result = 0; - for (i = 0; i < 32; i += 16, v1 >>= 16) - { - h0 = (signed16)(v1 & 0xffff); - if (h0 == (signed16)0x8000) - { - DSPCR |= DSPCR_OUFLAG4; - h0 = 0x7fff; - } - else if (h0 & 0x8000) - h0 = -h0; - result |= ((unsigned32)((unsigned16)h0) << i); - } - GPR[RD] = EXTEND32 (result); + do_ph_s_absq (SD_, RD, RT); } 011111,00000,5.RT,5.RD,10001,010010:SPECIAL3:32::ABSQ_S.W "absq_s.w r<RD>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RT]; - signed32 h0 = (signed32)v1; - if (h0 == (signed32)0x80000000) - { - DSPCR |= DSPCR_OUFLAG4; - h0 = 0x7fffffff; - } - else if (h0 & 0x80000000) - h0 = -h0; - GPR[RD] = EXTEND32 (h0); + do_w_s_absq (SD_, RD, RT); } 011111,5.RS,5.RT,5.RD,01100,010001:SPECIAL3:32::PRECRQ.QB.PH "precrq.qb.ph r<RD>, r<RS>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - unsigned32 tempu = (v1 & 0xff000000) >> 24; - unsigned32 tempv = (v1 & 0xff00) >> 8; - unsigned32 tempw = (v2 & 0xff000000) >> 24; - unsigned32 tempx = (v2 & 0xff00) >> 8; - GPR[RD] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx); + do_ph_qb_precrq (SD_, RD, RS, RT, 0); } 011111,5.RS,5.RT,5.RD,10100,010001:SPECIAL3:32::PRECRQ.PH.W "precrq.ph.w r<RD>, r<RS>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - unsigned32 tempu = (v1 & 0xffff0000) >> 16; - unsigned32 tempv = (v2 & 0xffff0000) >> 16; - GPR[RD] = EXTEND32 ((tempu << 16) | tempv); + do_w_ph_precrq (SD_, RD, RS, RT); } 011111,5.RS,5.RT,5.RD,10101,010001:SPECIAL3:32::PRECRQ_RS.PH.W "precrq_rs.ph.w r<RD>, r<RS>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - signed32 h1 = (signed32)v1; - signed32 h2 = (signed32)v2; - signed64 temp1 = (signed64)h1 + (signed64)0x8000; - signed32 temp2; - signed64 temp3 = (signed64)h2 + (signed64)0x8000; - signed32 temp4; - if (((temp1 & 0x100000000LL) >> 1) != (temp1 & 0x80000000)) - { - DSPCR |= DSPCR_OUFLAG6; - temp2 = 0x7fff; - } - else - temp2 = (signed32)((temp1 & 0xffff0000) >> 16); - if (((temp3 & 0x100000000LL) >> 1) != (temp3 & 0x80000000)) - { - DSPCR |= DSPCR_OUFLAG6; - temp4 = 0x7fff; - } - else - temp4 = (signed32)((temp3 & 0xffff0000) >> 16); - GPR[RD] = EXTEND32 ((temp2 << 16) | temp4); + do_w_ph_rs_precrq (SD_, RD, RS, RT); } 011111,5.RS,5.RT,5.RD,01111,010001:SPECIAL3:32::PRECRQU_S.QB.PH "precrqu_s.qb.ph r<RD>, r<RS>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - unsigned32 tempu, tempv, tempw, tempx; - if (v1 & 0x80000000) - { - DSPCR |= DSPCR_OUFLAG6; - tempu = 0; - } - else if (!(v1 & 0x80000000) && ((v1 >> 16) > (unsigned32)0x7f80)) - { - DSPCR |= DSPCR_OUFLAG6; - tempu = 0xff; - } - else - tempu = (v1 & 0x7f800000) >> 23; - if (v1 & 0x8000) - { - DSPCR |= DSPCR_OUFLAG6; - tempv = 0; - } - else if (!(v1 & 0x8000) && ((v1 & 0xffff) > (unsigned32)0x7f80)) - { - DSPCR |= DSPCR_OUFLAG6; - tempv = 0xff; - } - else - tempv = (v1 & 0x7f80) >> 7; - if (v2 & 0x80000000) - { - DSPCR |= DSPCR_OUFLAG6; - tempw = 0; - } - else if (!(v2 & 0x80000000) && ((v2 >> 16) > (unsigned32)0x7f80)) - { - DSPCR |= DSPCR_OUFLAG6; - tempw = 0xff; - } - else - tempw = (v2 & 0x7f800000) >> 23; - if (v2 & 0x8000) - { - DSPCR |= DSPCR_OUFLAG6; - tempx = 0; - } - else if (!(v2 & 0x8000) && ((v2 & 0xffff) > (unsigned32)0x7f80)) - { - DSPCR |= DSPCR_OUFLAG6; - tempx = 0xff; - } - else - tempx = (v2 & 0x7f80) >> 7; - GPR[RD] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx); + do_ph_qb_precrq (SD_, RD, RS, RT, 1); } 011111,00000,5.RT,5.RD,01100,010010:SPECIAL3:32::PRECEQ.W.PHL "preceq.w.phl r<RD>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RT]; - GPR[RD] = EXTEND32 (v1 & 0xffff0000); + do_w_preceq (SD_, RD, RT, 0); } 011111,00000,5.RT,5.RD,01101,010010:SPECIAL3:32::PRECEQ.W.PHR "preceq.w.phr r<RD>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RT]; - GPR[RD] = EXTEND32 ((v1 & 0xffff) << 16); + do_w_preceq (SD_, RD, RT, 1); } 011111,00000,5.RT,5.RD,00100,010010:SPECIAL3:32::PRECEQU.PH.QBL "precequ.ph.qbl r<RD>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RT]; - GPR[RD] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff0000) >> 9); + do_qb_ph_precequ (SD_, RD, RT, 2); } 011111,00000,5.RT,5.RD,00101,010010:SPECIAL3:32::PRECEQU.PH.QBR "precequ.ph.qbr r<RD>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RT]; - GPR[RD] = EXTEND32 ((v1 & 0xff00) << 15) | ((v1 & 0xff) << 7); + do_qb_ph_precequ (SD_, RD, RT, 0); } 011111,00000,5.RT,5.RD,00110,010010:SPECIAL3:32::PRECEQU.PH.QBLA "precequ.ph.qbla r<RD>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RT]; - GPR[RD] = EXTEND32 ((v1 & 0xff000000) >> 1) | ((v1 & 0xff00) >> 1); + do_qb_ph_precequ (SD_, RD, RT, 3); } 011111,00000,5.RT,5.RD,00111,010010:SPECIAL3:32::PRECEQU.PH.QBRA "precequ.ph.qbra r<RD>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RT]; - GPR[RD] = EXTEND32 ((v1 & 0xff0000) << 7) | ((v1 & 0xff) << 7); + do_qb_ph_precequ (SD_, RD, RT, 1); } 011111,00000,5.RT,5.RD,11100,010010:SPECIAL3:32::PRECEU.PH.QBL "preceu.ph.qbl r<RD>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RT]; - GPR[RD] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff0000) >> 16); + do_qb_ph_preceu (SD_, RD, RT, 2); } 011111,00000,5.RT,5.RD,11101,010010:SPECIAL3:32::PRECEU.PH.QBR "preceu.ph.qbr r<RD>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RT]; - GPR[RD] = EXTEND32 ((v1 & 0xff00) << 8) | (v1 & 0xff); + do_qb_ph_preceu (SD_, RD, RT, 0); } 011111,00000,5.RT,5.RD,11110,010010:SPECIAL3:32::PRECEU.PH.QBLA "preceu.ph.qbla r<RD>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RT]; - GPR[RD] = EXTEND32 ((v1 & 0xff000000) >> 8) | ((v1 & 0xff00) >> 8); + do_qb_ph_preceu (SD_, RD, RT, 3); } 011111,00000,5.RT,5.RD,11111,010010:SPECIAL3:32::PRECEU.PH.QBRA "preceu.ph.qbra r<RD>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RT]; - GPR[RD] = EXTEND32 ((v1 & 0xff0000) | (v1 & 0xff)); + do_qb_ph_preceu (SD_, RD, RT, 1); } 011111,00,3.SHIFT3,5.RT,5.RD,00000,010011:SPECIAL3:32::SHLL.QB @@ -630,8 +1095,7 @@ "shllv.qb r<RD>, r<RT>, r<RS>" *dsp: { - unsigned32 shift = GPR[RS] & 0x7; - do_qb_shift (SD_, RD, RT, shift, 0); + do_qb_shl (SD_, RD, RT, RS, 0); } 011111,0,4.SHIFT4,5.RT,5.RD,01000,010011:SPECIAL3:32::SHLL.PH @@ -645,8 +1109,7 @@ "shllv.ph r<RD>, r<RT>, r<RS>" *dsp: { - unsigned32 shift = GPR[RS] & 0xf; - do_ph_shift (SD_, RD, RT, shift, 0, 0); + do_ph_shl (SD_, RD, RT, RS, 0, 0); } 011111,0,4.SHIFT4,5.RT,5.RD,01100,010011:SPECIAL3:32::SHLL_S.PH @@ -660,8 +1123,7 @@ "shllv_s.ph r<RD>, r<RT>, r<RS>" *dsp: { - unsigned32 shift = GPR[RS] & 0xf; - do_ph_shift (SD_, RD, RT, shift, 0, 1); + do_ph_shl (SD_, RD, RT, RS, 0, 1); } 011111,5.SHIFT5,5.RT,5.RD,10100,010011:SPECIAL3:32::SHLL_S.W @@ -675,8 +1137,7 @@ "shllv_s.w r<RD>, r<RT>, r<RS>" *dsp: { - unsigned32 shift = GPR[RS] & 0x1f; - do_w_shll (SD_, RD, RT, shift); + do_w_s_shllv (SD_, RD, RT, RS); } 011111,00,3.SHIFT3,5.RT,5.RD,00001,010011:SPECIAL3:32::SHRL.QB @@ -690,8 +1151,7 @@ "shrlv.qb r<RD>, r<RT>, r<RS>" *dsp: { - unsigned32 shift = GPR[RS] & 0x7; - do_qb_shift (SD_, RD, RT, shift, 1); + do_qb_shl (SD_, RD, RT, RS, 1); } 011111,0,4.SHIFT4,5.RT,5.RD,01001,010011:SPECIAL3:32::SHRA.PH @@ -705,8 +1165,7 @@ "shrav.ph r<RD>, r<RT>, r<RS>" *dsp: { - unsigned32 shift = GPR[RS] & 0xf; - do_ph_shift (SD_, RD, RT, shift, 1, 0); + do_ph_shl (SD_, RD, RT, RS, 1, 0); } 011111,0,4.SHIFT4,5.RT,5.RD,01101,010011:SPECIAL3:32::SHRA_R.PH @@ -720,8 +1179,7 @@ "shrav_r.ph r<RD>, r<RT>, r<RS>" *dsp: { - unsigned32 shift = GPR[RS] & 0xf; - do_ph_shift (SD_, RD, RT, shift, 1, 1); + do_ph_shl (SD_, RD, RT, RS, 1, 1); } 011111,5.SHIFT5,5.RT,5.RD,10101,010011:SPECIAL3:32::SHRA_R.W @@ -735,8 +1193,7 @@ "shrav_r.w r<RD>, r<RT>, r<RS>" *dsp: { - unsigned32 shift = GPR[RS] & 0x1f; - do_w_shra (SD_, RD, RT, shift); + do_w_r_shrav (SD_, RD, RT, RS); } // loc: 0 = qhl, 1 = qhr @@ -963,33 +1420,7 @@ "mulsaq_s.w.ph ac<AC>, r<RS>, r<RT>" *dsp: { - int i; - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - signed16 h1, h2; - signed32 result; - unsigned32 lo = DSPLO(AC); - unsigned32 hi = DSPHI(AC); - signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo); - for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16) - { - h1 = (signed16)(v1 & 0xffff); - h2 = (signed16)(v2 & 0xffff); - if (h1 == (signed16)0x8000 && h2 == (signed16)0x8000) - { - DSPCR |= (1 << (DSPCR_OUFLAG_SHIFT + AC)); - result = (signed32) 0x7fffffff; - } - else - result = ((signed32)h1 * (signed32)h2) << 1; - - if (i == 0) - prod -= (signed64) result; - else - prod += (signed64) result; - } - DSPLO(AC) = EXTEND32 (prod); - DSPHI(AC) = EXTEND32 (prod >> 32); + do_mulsaq_s_w_ph (SD_, AC, RS, RT); } // op: 0 = DPAQ 1 = DPSQ @@ -1159,72 +1590,42 @@ "bitrev r<RD>, r<RT>" *dsp: { - int i; - unsigned32 v1 = GPR[RT]; - unsigned32 h1 = 0; - for (i = 0; i < 16; i++) - { - if (v1 & (1 << i)) - h1 |= (1 << (15 - i)); - } - GPR[RD] = EXTEND32 (h1); + do_bitrev (SD_, RD, RT); } 011111,5.RS,5.RT,00000,00000,001100:SPECIAL3:32::INSV "insv r<RT>, r<RS>" *dsp: { - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK; - unsigned32 size = (DSPCR >> DSPCR_SCOUNT_SHIFT) & DSPCR_SCOUNT_MASK; - unsigned32 mask1, mask2, mask3, result; - if (size < 32) - mask1 = (1 << size) - 1; - else - mask1 = 0xffffffff; - mask2 = (1 << pos) - 1; - if (pos + size < 32) - mask3 = ~((1 << (pos + size)) - 1); - else - mask3 = 0; - result = (v2 & mask3) | ((v1 & mask1) << pos) | (v2 & mask2); - GPR[RT] = EXTEND32 (result); + do_insv (SD_, RT, RS); } 011111,00,8.IMM8,5.RD,00010,010010:SPECIAL3:32::REPL.QB "repl.qb r<RD>, <IMM8>" *dsp: { - GPR[RD] = EXTEND32 ((IMM8 << 24) | (IMM8 << 16) | (IMM8 << 8) | IMM8); + do_repl (SD_, RD, IMM8, 0); } 011111,00000,5.RT,5.RD,00011,010010:SPECIAL3:32::REPLV.QB "replv.qb r<RD>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RT]; - v1 = v1 & 0xff; - GPR[RD] = EXTEND32 ((v1 << 24) | (v1 << 16) | (v1 << 8) | v1); + do_repl (SD_, RD, RT, 1); } 011111,10.IMM10,5.RD,01010,010010:SPECIAL3:32::REPL.PH "repl.ph r<RD>, <IMM10>" *dsp: { - signed32 v1 = IMM10; - if (v1 & 0x200) - v1 |= 0xfffffc00; - GPR[RD] = EXTEND32 ((v1 << 16) | (v1 & 0xffff)); + do_repl (SD_, RD, IMM10, 2); } 011111,00000,5.RT,5.RD,01011,010010:SPECIAL3:32::REPLV.PH "replv.ph r<RD>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RT]; - v1 = v1 & 0xffff; - GPR[RD] = EXTEND32 ((v1 << 16) | v1); + do_repl (SD_, RD, RT, 3); } // op: 0 = EQ, 1 = LT, 2 = LE @@ -1362,51 +1763,21 @@ "pick.qb r<RD>, r<RS>, r<RT>" *dsp: { - int i, j; - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - unsigned8 h1, h2; - unsigned32 result = 0; - for (i = 0, j = 0; i < 32; i += 8, j++, v1 >>= 8, v2 >>= 8) - { - h1 = (unsigned8)(v1 & 0xff); - h2 = (unsigned8)(v2 & 0xff); - if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j))) - result |= (unsigned32)(h1 << i); - else - result |= (unsigned32)(h2 << i); - } - GPR[RD] = EXTEND32 (result); + do_qb_pick (SD_, RD, RS, RT); } 011111,5.RS,5.RT,5.RD,01011,010001:SPECIAL3:32::PICK.PH "pick.ph r<RD>, r<RS>, r<RT>" *dsp: { - int i, j; - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - unsigned16 h1, h2; - unsigned32 result = 0; - for (i = 0, j = 0; i < 32; i += 16, j++, v1 >>= 16, v2 >>= 16) - { - h1 = (unsigned16)(v1 & 0xffff); - h2 = (unsigned16)(v2 & 0xffff); - if (DSPCR & (1 << (DSPCR_CCOND_SHIFT + j))) - result |= (unsigned32)(h1 << i); - else - result |= (unsigned32)(h2 << i); - } - GPR[RD] = EXTEND32 (result); + do_ph_pick (SD_, RD, RS, RT); } 011111,5.RS,5.RT,5.RD,01110,010001:SPECIAL3:32::PACKRL.PH "packrl.ph r<RD>, r<RS>, r<RT>" *dsp: { - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - GPR[RD] = EXTEND32 ((v1 << 16) + (v2 >> 16)); + do_ph_packrl (SD_, RD, RS, RT); } // op: 0 = EXTR, 1 = EXTR_R, 2 = EXTR_RS @@ -1484,8 +1855,7 @@ "extrv.w r<RT>, ac<AC>, r<RS>" *dsp: { - unsigned32 shift = GPR[RS] & 0x1f; - do_w_extr (SD_, RT, AC, shift, 0); + do_extrv (SD_, RT, AC, RS, 0); } 011111,5.SHIFT,5.RT,000,2.AC,00100,111000:SPECIAL3:32::EXTR_R.W @@ -1499,8 +1869,7 @@ "extrv_r.w r<RT>, ac<AC>, r<RS>" *dsp: { - unsigned32 shift = GPR[RS] & 0x1f; - do_w_extr (SD_, RT, AC, shift, 1); + do_extrv (SD_, RT, AC, RS, 1); } 011111,5.SHIFT,5.RT,000,2.AC,00110,111000:SPECIAL3:32::EXTR_RS.W @@ -1514,8 +1883,7 @@ "extrv_rs.w r<RT>, ac<AC>, r<RS>" *dsp: { - unsigned32 shift = GPR[RS] & 0x1f; - do_w_extr (SD_, RT, AC, shift, 2); + do_extrv (SD_, RT, AC, RS, 2); } :function:::void:do_h_extr:int rt, int ac, int shift @@ -1551,8 +1919,7 @@ "extrv_s.h r<RT>, ac<AC>, r<RS>" *dsp: { - unsigned32 shift = GPR[RS] & 0x1f; - do_h_extr (SD_, RT, AC, shift); + do_extrv_s_h (SD_, RT, AC, RS); } // op: 0 = EXTP, 1 = EXTPDP @@ -1600,8 +1967,7 @@ "extpv r<RT>, ac<AC>, r<RS>" *dsp: { - unsigned32 size = GPR[RS] & 0x1f; - do_extp (SD_, RT, AC, size, 0); + do_extpv (SD_, RT, AC, RS, 0); } 011111,5.SIZE,5.RT,000,2.AC,01010,111000:SPECIAL3:32::EXTPDP @@ -1615,8 +1981,7 @@ "extpdpv r<RT>, ac<AC>, r<RS>" *dsp: { - unsigned32 size = GPR[RS] & 0x1f; - do_extp (SD_, RT, AC, size, 1); + do_extpv (SD_, RT, AC, RS, 1); } :function:::void:do_shilo:int ac, int shift @@ -1645,23 +2010,14 @@ "shilov ac<AC>, r<RS>" *dsp: { - signed32 shift = GPR[RS] & 0x3f; - do_shilo (SD_, AC, shift); + do_shilov (SD_, AC, RS); } 011111,5.RS,00000,000,2.AC,11111,111000:SPECIAL3:32::MTHLIP "mthlip r<RS>, ac<AC>" *dsp: { - unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK; - DSPHI(AC) = DSPLO(AC); - DSPLO(AC) = GPR[RS]; - if (pos >= 32) - Unpredictable (); - else - pos += 32; - DSPCR &= (~DSPCR_POS_SMASK); - DSPCR |= (pos & DSPCR_POS_MASK) << DSPCR_POS_SHIFT; + do_mthlip (SD_, RS, AC); } 011111,5.RS,10.MASK10,10011,111000:SPECIAL3:32::WRDSP @@ -1669,37 +2025,7 @@ "wrdsp r<RS>, <MASK10>" *dsp: { - unsigned32 v1 = GPR[RS]; - if (MASK10 & 0x1) - { - DSPCR &= (~DSPCR_POS_SMASK); - DSPCR |= (v1 & DSPCR_POS_SMASK); - } - if (MASK10 & 0x2) - { - DSPCR &= (~DSPCR_SCOUNT_SMASK); - DSPCR |= (v1 & DSPCR_SCOUNT_SMASK); - } - if (MASK10 & 0x4) - { - DSPCR &= (~DSPCR_CARRY_SMASK); - DSPCR |= (v1 & DSPCR_CARRY_SMASK); - } - if (MASK10 & 0x8) - { - DSPCR &= (~DSPCR_OUFLAG_SMASK); - DSPCR |= (v1 & DSPCR_OUFLAG_SMASK); - } - if (MASK10 & 0x10) - { - DSPCR &= (~DSPCR_CCOND_SMASK); - DSPCR |= (v1 & DSPCR_CCOND_SMASK); - } - if (MASK10 & 0x20) - { - DSPCR &= (~DSPCR_EFI_SMASK); - DSPCR |= (v1 & DSPCR_EFI_SMASK); - } + do_wrdsp (SD_, RS, MASK10); } 011111,10.MASK10,5.RD,10010,111000:SPECIAL3:32::RDDSP @@ -1707,59 +2033,28 @@ "rddsp r<RD>, <MASK10>" *dsp: { - unsigned32 result = 0; - if (MASK10 & 0x1) - { - result &= (~DSPCR_POS_SMASK); - result |= (DSPCR & DSPCR_POS_SMASK); - } - if (MASK10 & 0x2) - { - result &= (~DSPCR_SCOUNT_SMASK); - result |= (DSPCR & DSPCR_SCOUNT_SMASK); - } - if (MASK10 & 0x4) - { - result &= (~DSPCR_CARRY_SMASK); - result |= (DSPCR & DSPCR_CARRY_SMASK); - } - if (MASK10 & 0x8) - { - result &= (~DSPCR_OUFLAG_SMASK); - result |= (DSPCR & DSPCR_OUFLAG_SMASK); - } - if (MASK10 & 0x10) - { - result &= (~DSPCR_CCOND_SMASK); - result |= (DSPCR & DSPCR_CCOND_SMASK); - } - if (MASK10 & 0x20) - { - result &= (~DSPCR_EFI_SMASK); - result |= (DSPCR & DSPCR_EFI_SMASK); - } - GPR[RD] = EXTEND32 (result); + do_rddsp (SD_, RD, MASK10); } 011111,5.BASE,5.INDEX,5.RD,00110,001010:SPECIAL3:32::LBUX "lbux r<RD>, r<INDEX>(r<BASE>)" *dsp: { - GPR[RD] = do_load (SD_, AccessLength_BYTE, GPR[BASE], GPR[INDEX]); + do_lxx (SD_, RD, BASE, INDEX, 0); } 011111,5.BASE,5.INDEX,5.RD,00100,001010:SPECIAL3:32::LHX "lhx r<RD>, r<INDEX>(r<BASE>)" *dsp: { - GPR[RD] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[BASE], GPR[INDEX])); + do_lxx (SD_, RD, BASE, INDEX, 1); } 011111,5.BASE,5.INDEX,5.RD,00000,001010:SPECIAL3:32::LWX "lwx r<RD>, r<INDEX>(r<BASE>)" *dsp: { - GPR[RD] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[BASE], GPR[INDEX])); + do_lxx (SD_, RD, BASE, INDEX, 2); } 000001,00000,11100,16.OFFSET:REGIMM:32::BPOSGE32 diff --git a/sim/mips/dsp2.igen b/sim/mips/dsp2.igen index 9cecd62..a871026 100644 --- a/sim/mips/dsp2.igen +++ b/sim/mips/dsp2.igen @@ -5,7 +5,7 @@ // Contributed by MIPS Technologies, Inc. // Written by Chao-ying Fu (fu@mips.com). // -// This file is part of GDB, the GNU debugger. +// This file is part of the MIPS sim // // 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 @@ -353,23 +353,7 @@ "absq_s.qb r<RD>, r<RT>" *dsp2: { - int i; - signed8 q0; - unsigned32 v1 = GPR[RT]; - unsigned32 result = 0; - for (i = 0; i < 32; i += 8, v1 >>= 8) - { - q0 = (signed8)(v1 & 0xff); - if (q0 == (signed8)0x80) - { - DSPCR |= DSPCR_OUFLAG4; - q0 = 0x7f; - } - else if (q0 & 0x80) - q0 = -q0; - result |= ((unsigned32)((unsigned8)q0) << i); - } - GPR[RD] = EXTEND32 (result); + do_qb_s_absq (SD_, RD, RT); } 011111,5.RS,5.RT,5.RD,01000,010000:SPECIAL3:32::ADDU.PH @@ -404,26 +388,14 @@ "append r<RT>, r<RS>, <SA>" *dsp2: { - unsigned32 v0 = GPR[RS]; - unsigned32 v1 = GPR[RT]; - unsigned32 result; - unsigned32 mask = (1 << SA) - 1; - result = (v1 << SA) | (v0 & mask); - GPR[RT] = EXTEND32 (result); + do_append (SD_, RT, RS, SA); } 011111,5.RS,5.RT,000,2.BP,10000,110001:SPECIAL3:32::BALIGN "balign r<RT>, r<RS>, <BP>" *dsp2: { - unsigned32 v0 = GPR[RS]; - unsigned32 v1 = GPR[RT]; - unsigned32 result; - if (BP == 0) - result = v1; - else - result = (v1 << 8 * BP) | (v0 >> 8 * (4 - BP)); - GPR[RT] = EXTEND32 (result); + do_balign (SD_, RT, RS, BP); } 011111,5.RS,5.RT,5.RD,11000,010001:SPECIAL3:32::CMPGDU.EQ.QB @@ -500,40 +472,14 @@ "mulsa.w.ph ac<AC>, r<RS>, r<RT>" *dsp2: { - int i; - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - signed16 h1, h2; - signed32 result; - unsigned32 lo = DSPLO(AC); - unsigned32 hi = DSPHI(AC); - signed64 prod = (signed64)((((unsigned64)hi) << 32) + (unsigned64)lo); - for (i = 0; i < 32; i += 16, v1 >>= 16, v2 >>= 16) - { - h1 = (signed16)(v1 & 0xffff); - h2 = (signed16)(v2 & 0xffff); - result = (signed32)h1 * (signed32)h2; - - if (i == 0) - prod -= (signed64) result; - else - prod += (signed64) result; - } - DSPLO(AC) = EXTEND32 (prod); - DSPHI(AC) = EXTEND32 (prod >> 32); + do_ph_w_mulsa (SD_, AC, RS, RT); } 011111,5.RS,5.RT,5.RD,01101,010001:SPECIAL3:32::PRECR.QB.PH "precr.qb.ph r<RD>, r<RS>, r<RT>" *dsp2: { - unsigned32 v1 = GPR[RS]; - unsigned32 v2 = GPR[RT]; - unsigned32 tempu = (v1 & 0xff0000) >> 16; - unsigned32 tempv = (v1 & 0xff); - unsigned32 tempw = (v2 & 0xff0000) >> 16; - unsigned32 tempx = (v2 & 0xff); - GPR[RD] = EXTEND32 ((tempu << 24) | (tempv << 16) | (tempw << 8) | tempx); + do_ph_qb_precr (SD_, RD, RS, RT); } 011111,5.RS,5.RT,5.SA,11110,010001:SPECIAL3:32::PRECR_SRA.PH.W @@ -554,14 +500,7 @@ "prepend r<RT>, r<RS>, <SA>" *dsp2: { - unsigned32 v0 = GPR[RS]; - unsigned32 v1 = GPR[RT]; - unsigned32 result; - if (SA == 0) - result = v1; - else - result = (v0 << (32 - SA)) | (v1 >> SA); - GPR[RT] = EXTEND32 (result); + do_prepend (SD_, RT, RS, SA); } 011111,00,3.SHIFT3,5.RT,5.RD,00100,010011:SPECIAL3:32::SHRA.QB @@ -582,16 +521,14 @@ "shrav.qb r<RD>, r<RT>, r<RS>" *dsp2: { - unsigned32 shift = GPR[RS] & 0x7; - do_qb_shra (SD_, RD, RT, shift, 0); + do_qb_shrav (SD_, RD, RT, RS, 0); } 011111,5.RS,5.RT,5.RD,00111,010011:SPECIAL3:32::SHRAV_R.QB "shrav_r.qb r<RD>, r<RT>, r<RS>" *dsp2: { - unsigned32 shift = GPR[RS] & 0x7; - do_qb_shra (SD_, RD, RT, shift, 1); + do_qb_shrav (SD_, RD, RT, RS, 1); } 011111,0,4.SHIFT4,5.RT,5.RD,11001,010011:SPECIAL3:32::SHRL.PH @@ -605,8 +542,7 @@ "shrlv.ph r<RD>, r<RT>, r<RS>" *dsp2: { - unsigned32 shift = GPR[RS] & 0xf; - do_ph_shrl (SD_, RD, RT, shift); + do_ph_shrlv (SD_, RD, RT, RS); } 011111,5.RS,5.RT,5.RD,01001,010000:SPECIAL3:32::SUBU.PH diff --git a/sim/mips/interp.c b/sim/mips/interp.c index ed44cd9..9dc8964 100644 --- a/sim/mips/interp.c +++ b/sim/mips/interp.c @@ -71,7 +71,7 @@ char* pr_uword64 (uword64 addr); trap is required. NOTE: Care must be taken, since this value may be used in later revisions of the MIPS ISA. */ -#define RSVD_INSTRUCTION (0x00000005) +#define RSVD_INSTRUCTION (0x00000039) #define RSVD_INSTRUCTION_MASK (0xFC00003F) #define RSVD_INSTRUCTION_ARG_SHIFT 6 @@ -146,7 +146,6 @@ static SIM_ADDR lsipmon_monitor_base = 0xBFC00200; static SIM_RC sim_firmware_command (SIM_DESC sd, char* arg); - #define MEM_SIZE (8 << 20) /* 8 MBytes */ @@ -2186,18 +2185,17 @@ void decode_coproc (SIM_DESC sd, sim_cpu *cpu, address_word cia, - unsigned int instruction) + unsigned int instruction, + int coprocnum, + CP0_operation op, + int rt, + int rd, + int sel) { - int coprocnum = ((instruction >> 26) & 3); - switch (coprocnum) { case 0: /* standard CPU control and cache registers */ { - int code = ((instruction >> 21) & 0x1F); - int rt = ((instruction >> 16) & 0x1F); - int rd = ((instruction >> 11) & 0x1F); - int tail = instruction & 0x3ff; /* R4000 Users Manual (second edition) lists the following CP0 instructions: CODE><-RT><RD-><--TAIL---> @@ -2212,15 +2210,10 @@ decode_coproc (SIM_DESC sd, CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii) ERET Exception return (VR4100 = 01000010000000000000000000011000) */ - if (((code == 0x00) || (code == 0x04) /* MFC0 / MTC0 */ - || (code == 0x01) || (code == 0x05)) /* DMFC0 / DMTC0 */ - && tail == 0) + if (((op == cp0_mfc0) || (op == cp0_mtc0) /* MFC0 / MTC0 */ + || (op == cp0_dmfc0) || (op == cp0_dmtc0)) /* DMFC0 / DMTC0 */ + && sel == 0) { - /* Clear double/single coprocessor move bit. */ - code &= ~1; - - /* M[TF]C0 (32 bits) | DM[TF]C0 (64 bits) */ - switch (rd) /* NOTEs: Standard CP0 registers */ { /* 0 = Index R4000 VR4100 VR4300 */ @@ -2248,7 +2241,7 @@ decode_coproc (SIM_DESC sd, case 8: /* 8 = BadVAddr R4000 VR4100 VR4300 */ - if (code == 0x00) + if (op == cp0_mfc0 || op == cp0_dmfc0) GPR[rt] = (signed_word) (signed_address) COP0_BADVADDR; else COP0_BADVADDR = GPR[rt]; @@ -2256,21 +2249,21 @@ decode_coproc (SIM_DESC sd, #endif /* SUBTARGET_R3900 */ case 12: - if (code == 0x00) + if (op == cp0_mfc0 || op == cp0_dmfc0) GPR[rt] = SR; else SR = GPR[rt]; break; /* 13 = Cause R4000 VR4100 VR4300 */ case 13: - if (code == 0x00) + if (op == cp0_mfc0 || op == cp0_dmfc0) GPR[rt] = CAUSE; else CAUSE = GPR[rt]; break; /* 14 = EPC R4000 VR4100 VR4300 */ case 14: - if (code == 0x00) + if (op == cp0_mfc0 || op == cp0_dmfc0) GPR[rt] = (signed_word) (signed_address) EPC; else EPC = GPR[rt]; @@ -2279,7 +2272,7 @@ decode_coproc (SIM_DESC sd, #ifdef SUBTARGET_R3900 /* 16 = Debug */ case 16: - if (code == 0x00) + if (op == cp0_mfc0 || op == cp0_dmfc0) GPR[rt] = Debug; else Debug = GPR[rt]; @@ -2287,7 +2280,7 @@ decode_coproc (SIM_DESC sd, #else /* 16 = Config R4000 VR4100 VR4300 */ case 16: - if (code == 0x00) + if (op == cp0_mfc0 || op == cp0_dmfc0) GPR[rt] = C0_CONFIG; else /* only bottom three bits are writable */ @@ -2297,7 +2290,7 @@ decode_coproc (SIM_DESC sd, #ifdef SUBTARGET_R3900 /* 17 = Debug */ case 17: - if (code == 0x00) + if (op == cp0_mfc0 || op == cp0_dmfc0) GPR[rt] = DEPC; else DEPC = GPR[rt]; @@ -2320,7 +2313,7 @@ decode_coproc (SIM_DESC sd, GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */ /* CPR[0,rd] = GPR[rt]; */ default: - if (code == 0x00) + if (op == cp0_mfc0 || op == cp0_dmfc0) GPR[rt] = (signed_word) (signed32) COP0_GPR[rd]; else COP0_GPR[rd] = GPR[rt]; @@ -2332,12 +2325,12 @@ decode_coproc (SIM_DESC sd, #endif } } - else if ((code == 0x00 || code == 0x01) + else if ((op == cp0_mfc0 || op == cp0_dmfc0) && rd == 16) { /* [D]MFC0 RT,C0_CONFIG,SEL */ signed32 cfg = 0; - switch (tail & 0x07) + switch (sel) { case 0: cfg = C0_CONFIG; @@ -2366,7 +2359,7 @@ decode_coproc (SIM_DESC sd, } GPR[rt] = cfg; } - else if (code == 0x10 && (tail & 0x3f) == 0x18) + else if (op == cp0_eret && sel == 0x18) { /* ERET */ if (SR & status_ERL) @@ -2382,7 +2375,7 @@ decode_coproc (SIM_DESC sd, SR &= ~status_EXL; } } - else if (code == 0x10 && (tail & 0x3f) == 0x10) + else if (op == cp0_rfe && sel == 0x10) { /* RFE */ #ifdef SUBTARGET_R3900 @@ -2394,7 +2387,7 @@ decode_coproc (SIM_DESC sd, /* TODO: CACHE register */ #endif /* SUBTARGET_R3900 */ } - else if (code == 0x10 && (tail & 0x3f) == 0x1F) + else if (op == cp0_deret && sel == 0x1F) { /* DERET */ Debug &= ~Debug_DM; diff --git a/sim/mips/m16.igen b/sim/mips/m16.igen index f87a863..74adacd 100644 --- a/sim/mips/m16.igen +++ b/sim/mips/m16.igen @@ -1075,6 +1075,10 @@ 011101,26.IMMED:JALX:32::JALX32 "jalx <IMMED>" +*mips32: +*mips64: +*mips32r2: +*mips64r2: *mips16: *vr4100: { @@ -1228,9 +1232,5 @@ *mips16: *vr4100: { - if (STATE & simDELAYSLOT) - PC = cia - 2; /* reference the branch instruction */ - else - PC = cia; - SignalException (BreakPoint, instruction_0); + do_break16 (SD_, instruction_0); } diff --git a/sim/mips/micromips.dc b/sim/mips/micromips.dc new file mode 100644 index 0000000..2593aba --- /dev/null +++ b/sim/mips/micromips.dc @@ -0,0 +1,15 @@ +# most instructions +# ------ options ------ : Fst : Lst : ff : fl : fe : word : fmt : model ... +# { : mask : value : word } + +# Top level - create a very big switch statement. + + padded-switch,combine : 31 : 26 : : : : : : + + switch,combine : 5 : 0 : : : : : : + + switch,combine : 10 : 0 : : : : : : + + switch,combine : 25 : 16 : : : : : : + switch,combine : 25 : 21 : : : : : : + switch,combine : 15 : 11 : : : : : : diff --git a/sim/mips/micromips.igen b/sim/mips/micromips.igen new file mode 100644 index 0000000..2c62376 --- /dev/null +++ b/sim/mips/micromips.igen @@ -0,0 +1,3091 @@ +// Simulator definition for the micromips ASE. +// Copyright (C) 2005-2015 Free Software Foundation, Inc. +// Contributed by Imagination Technologies, Ltd. +// Written by Andrew Bennett <andrew.bennett@imgtec.com> +// +// This file is part of the MIPS sim. +// +// 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 3 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/>. + +:compute:::int:TBASE:BASE:((BASE < 2) ? (16 + BASE) \: BASE) +:compute:::int:TRD:RD:((RD < 2) ? (16 + RD) \: RD) +:compute:::int:TRS:RS:((RS < 2) ? (16 + RS) \: RS) +:compute:::int:TRT:RT:((RT < 2) ? (16 + RT) \: RT) +:compute:::int:TRT_S:RT_S:((RT_S == 1 ) ? 17 \: RT_S) +:compute:::int:ERT:RT:(compute_movep_src_reg (SD_, RT)) +:compute:::int:ERS:RS:(compute_movep_src_reg (SD_, RS)) + +:compute:::int:IMM_DEC1:IMMEDIATE:((IMMEDIATE == 7) ? -1 \: ((IMMEDIATE == 0) ? 1 \: IMMEDIATE << 2)) +:compute:::int:IMM_DEC2:IMMEDIATE:((IMMEDIATE < 8) ? IMMEDIATE \: (IMMEDIATE - 16)) +:compute:::int:IMM_DEC3:IMMEDIATE:((IMMEDIATE < 2) ? IMMEDIATE + 256 \: ((IMMEDIATE < 256) ? IMMEDIATE \: ((IMMEDIATE < 510) ? IMMEDIATE - 512 \: IMMEDIATE - 768))) +:compute:::int:IMM_DEC4:IMMEDIATE:(compute_andi16_imm (SD_, IMMEDIATE)) +:compute:::int:IMM_DEC5:IMMEDIATE:((IMMEDIATE < 15) ? IMMEDIATE \: -1) +:compute:::int:IMM_DEC6:IMMEDIATE:((IMMEDIATE < 127) ? IMMEDIATE \: -1) + +:compute:::int:SHIFT_DEC:SHIFT:((SHIFT == 0) ? 8 \: SHIFT) + +:compute:::int:IMM_SHIFT_1BIT:IMMEDIATE:(IMMEDIATE << 1) +:compute:::int:IMM_SHIFT_2BIT:IMMEDIATE:(IMMEDIATE << 2) + +:function:::address_word:delayslot_micromips:address_word target, address_word nia, int delayslot_instruction_size +{ + instruction_word delay_insn; + sim_events_slip (SD, 1); + DSPC = CIA; + CIA = nia; + STATE |= simDELAYSLOT; + ENGINE_ISSUE_PREFIX_HOOK(); + micromips_instruction_decode (SD, CPU, CIA, delayslot_instruction_size); + STATE &= ~simDELAYSLOT; + return target; +} + +:function:::address_word:process_isa_mode:address_word target +{ + SD->isa_mode = target & 0x1; + return (target & (-1 << 1)); +} + +:function:::address_word:do_micromips_jalr:int rt, int rs, address_word nia, int delayslot_instruction_size +{ + GPR[rt] = (nia + delayslot_instruction_size) | ISA_MODE_MICROMIPS; + return (process_isa_mode (SD_, + delayslot_micromips (SD_, GPR[rs], nia, delayslot_instruction_size))); +} + +:function:::address_word:do_micromips_jal:address_word target, address_word nia, int delayslot_instruction_size +{ + RA = (nia + delayslot_instruction_size) | ISA_MODE_MICROMIPS; + return delayslot_micromips (SD_, target, nia, delayslot_instruction_size); +} + + +:function:::unsigned32:compute_movep_src_reg:int reg +{ + switch(reg) + { + case 0: return 0; + case 1: return 17; + case 2: return 2; + case 3: return 3; + case 4: return 16; + case 5: return 18; + case 6: return 19; + case 7: return 20; + default: return 0; + } +} + +:function:::unsigned32:compute_andi16_imm:int encoded_imm +{ + switch (encoded_imm) + { + case 0: return 128; + case 1: return 1; + case 2: return 2; + case 3: return 3; + case 4: return 4; + case 5: return 7; + case 6: return 8; + case 7: return 15; + case 8: return 16; + case 9: return 31; + case 10: return 32; + case 11: return 63; + case 12: return 64; + case 13: return 255; + case 14: return 32768; + case 15: return 65535; + default: return 0; + } +} + +:function:::FP_formats:convert_fmt_micromips:int fmt +{ + switch (fmt) + { + case 0: return fmt_single; + case 1: return fmt_double; + case 2: return fmt_ps; + default: return fmt_unknown; + } +} + +:function:::FP_formats:convert_fmt_micromips_cvt_d:int fmt +{ + switch (fmt) + { + case 0: return fmt_single; + case 1: return fmt_word; + case 2: return fmt_long; + default: return fmt_unknown; + } +} + + +:function:::FP_formats:convert_fmt_micromips_cvt_s:int fmt +{ + switch (fmt) + { + case 0: return fmt_double; + case 1: return fmt_word; + case 2: return fmt_long; + default: return fmt_unknown; + } +} + + +011011,3.RD,6.IMMEDIATE,1:POOL16E:16::ADDIUR1SP +"addiur1sp r<TRD>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_addiu (SD_, SPIDX, TRD, IMMEDIATE << 2); +} + + +011011,3.RD,3.RS,3.IMMEDIATE,0:POOL16E:16::ADDIUR2 +"addiur2 r<TRD>, r<TRS>, <IMM_DEC1>" +*micromips32: +*micromips64: +{ + do_addiu (SD_, TRS, TRD, IMM_DEC1); +} + + +010011,5.RD,4.IMMEDIATE,0:POOL16D:16::ADDIUS5 +"addius5 r<RD>, <IMM_DEC2>" +*micromips32: +*micromips64: +{ + do_addiu (SD_, RD, RD, IMM_DEC2); +} + + +010011,9.IMMEDIATE,1:POOL16D:16::ADDIUSP +"addiusp <IMM_DEC3>" +*micromips32: +*micromips64: +{ + do_addiu (SD_, SPIDX, SPIDX, IMM_DEC3 << 2); +} + + +000001,3.RD,3.RT,3.RS,0:POOL16A:16::ADDU16 +"addu16 r<TRD>, r<TRS>, r<TRT>" +*micromips32: +*micromips64: +{ + do_addu (SD_, TRS, TRT, TRD); +} + + +001011,3.RD,3.RS,4.IMMEDIATE:MICROMIPS:16::ANDI16 +"andi16 r<TRD>, r<TRS>, <IMM_DEC4>" +*micromips32: +*micromips64: +{ + do_andi (SD_, TRS, TRD, IMM_DEC4); +} + + +010001,0010,3.RT,3.RS:POOL16C:16::AND16 +"and16 r<TRT>, r<TRS>" +*micromips32: +*micromips64: +{ + do_and (SD_, TRS, TRT, TRT); +} + + +110011,10.IMMEDIATE:MICROMIPS:16::B16 +"b16 <IMMEDIATE>" +*micromips32: +*micromips64: +{ + NIA = delayslot_micromips (SD_, NIA + (EXTEND11 (IMMEDIATE << 1)), + NIA, MICROMIPS_DELAYSLOT_SIZE_ANY); +} + + +100011,3.RS,7.IMMEDIATE:MICROMIPS:16::BEQZ16 +"beqz16 r<TRS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + if (GPR[TRS] == 0) + NIA = delayslot_micromips (SD_, NIA + (EXTEND8 (IMMEDIATE << 1)), + NIA, MICROMIPS_DELAYSLOT_SIZE_ANY); +} + + +101011,3.RS,7.IMMEDIATE:MICROMIPS:16::BNEZ16 +"bnez16 r<TRS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + if (GPR[TRS] != 0) + NIA = delayslot_micromips (SD_, NIA + (EXTEND8 (IMMEDIATE << 1)), + NIA, MICROMIPS_DELAYSLOT_SIZE_ANY); +} + + +010001,101000,4.CODE:POOL16C:16::BREAK16 +"break16 %#lx<CODE>" +*micromips32: +*micromips64: +{ + do_break16 (SD_, instruction_0); +} + + +010001,01110,5.RS:POOL16C:16::JALR16 +"jalr16 r<RS>" +*micromips32: +*micromips64: +{ + NIA = do_micromips_jalr (SD_, RAIDX, RS, NIA, MICROMIPS_DELAYSLOT_SIZE_32); +} + + +010001,01111,5.RS:POOL16C:16::JALRS16 +"jalrs16 r<RS>" +*micromips32: +*micromips64: +{ + NIA = do_micromips_jalr (SD_, RAIDX, RS, NIA, MICROMIPS_DELAYSLOT_SIZE_16); +} + + +010001,01100,5.RS:POOL16C:16::JR16 +"jr16 r<RS>" +*micromips32: +*micromips64: +{ + NIA = process_isa_mode (SD_, + delayslot_micromips (SD_, GPR[RS], NIA, MICROMIPS_DELAYSLOT_SIZE_ANY)); +} + + +010001,11000,5.IMMEDIATE:POOL16C:16::JRADDIUSP +"jraddiusp <IMMEDIATE>" +*micromips32: +*micromips64: +{ + address_word temp = RA; + do_addiu (SD_, SPIDX, SPIDX, IMMEDIATE << 2); + NIA = process_isa_mode (SD_, temp); +} + + +010001,01101,5.RS:POOL16C:16::JRC +"jrc r<RS>" +*micromips32: +*micromips64: +{ + NIA = process_isa_mode (SD_, GPR[RS]); +} + + +000010,3.RT,3.BASE,4.IMMEDIATE:MICROMIPS:16::LBU16 +"lbu16 r<TRT>, <IMM_DEC5>(r<TBASE>)" +*micromips32: +*micromips64: +{ + /* LBU can have a negative offset. As the offset argument to do_load is + unsigned we need to do the address calcuation before the function call so + that the load address has been correctly calculated */ + + GPR[TRT] = do_load (SD_, AccessLength_BYTE, GPR[TBASE] + IMM_DEC5, 0); +} + + +001010,3.RT,3.BASE,4.IMMEDIATE:MICROMIPS:16::LHU16 +"lhu16 r<TRT>, <IMM_SHIFT_1BIT>(r<TBASE>)" +*micromips32: +*micromips64: +{ + GPR[TRT] = do_load (SD_, AccessLength_HALFWORD, GPR[TBASE], IMM_SHIFT_1BIT); +} + + +111011,3.RD,7.IMMEDIATE:MICROMIPS:16::LI16 +"li16 r<TRD>, <IMM_DEC6>" +*micromips32: +*micromips64: +{ + GPR[TRD] = IMM_DEC6; +} + + +011010,3.RT,3.BASE,4.IMMEDIATE:MICROMIPS:16::LW16 +"lw16 r<TRT>, <IMM_SHIFT_2BIT>(r<TBASE>)" +*micromips32: +*micromips64: +{ + GPR[TRT] = EXTEND32 ( + do_load (SD_, AccessLength_WORD, GPR[TBASE], IMM_SHIFT_2BIT)); +} + +:%s::::LWMREGS:int lwmregs +*micromips32: +*micromips64: +{ + if (lwmregs == 3) + return "s0, s1, s2, s3, ra"; + else if (lwmregs == 2) + return "s0, s1, s2, ra"; + else if (lwmregs == 1) + return "s0, s1, ra"; + else if (lwmregs == 0) + return "s0, ra"; + else + return ""; +} + +010001,0100,2.LWMREGS,4.IMMEDIATE:POOL16C:16::LWM16 +"lwm16 %s<LWMREGS>, <IMM_SHIFT_2BIT>(sp)" +*micromips32: +*micromips64: +{ + int address = GPR[SPIDX] + IMM_SHIFT_2BIT; + int reg_offset; + + for (reg_offset = 0; reg_offset <= LWMREGS; reg_offset++) + GPR[16 + reg_offset] = EXTEND32 ( + do_load (SD_, AccessLength_WORD, address, reg_offset * 4)); + + RA = EXTEND32 (do_load (SD_, AccessLength_WORD, address, reg_offset * 4)); +} + + +011001,3.RT,7.IMMEDIATE:MICROMIPS:16::LWGP +"lwgp r<TRT>, <IMM_SHIFT_2BIT>(gp)" +*micromips32: +*micromips64: +{ + GPR[TRT] = EXTEND32 ( + do_load (SD_, AccessLength_WORD, GPR[28], IMM_SHIFT_2BIT)); +} + + +010010,5.RT,5.IMMEDIATE:MICROMIPS:16::LWSP +"lwsp r<RT>, <IMM_SHIFT_2BIT>(sp)" +*micromips32: +*micromips64: +{ + GPR[RT] = EXTEND32 (do_load (SD_, AccessLength_WORD, SP, IMM_SHIFT_2BIT)); +} + + +010001,10000,5.RD:POOL16C:16::MFHI16 +"mfhi16 r<RD>" +*micromips32: +*micromips64: +{ + do_mfhi (SD_, RD); +} + + +010001,10010,5.RD:POOL16C:16::MFLO16 +"mflo16 r<RD>" +*micromips32: +*micromips64: +{ + do_mflo (SD_, RD); +} + + +000011,5.RD,5.RS:MICROMIPS:16::MOVE16 +"nop":RD==0&&RS==0 +"move16 r<RD>, r<RS>" +*micromips32: +*micromips64: +{ + GPR[RD] = GPR[RS]; +} + + +:%s::::DESTREGS:int regs +*micromips32: +*micromips64: +{ + switch (regs) + { + case 0: return "a1, a2,"; + case 1: return "a1, a3,"; + case 2: return "a2, a3,"; + case 3: return "a0, s5,"; + case 4: return "a0, s6,"; + case 5: return "a0, a1,"; + case 6: return "a0, a2,"; + case 7: return "a0, a3,"; + default: return ""; + } +} + +100001,3.DESTREGS,3.RT,3.RS,0:MICROMIPS:16::MOVEP +"movep %s<DESTREGS> r<ERS>, r<ERT>" +*micromips32: +*micromips64: +{ + int rd; + int re; + int dest = DESTREGS; + + if (dest == 0 || dest == 1) + rd = 5; + else if (dest == 2) + rd = 6; + else + rd = 4; + + if (dest == 0 || dest == 6) + re = 6; + else if (dest == 1 || dest == 2 || dest == 7) + re = 7; + else if (dest == 3) + re = 21; + else if (dest == 4) + re = 22; + /* assume dest is 5 */ + else + re = 5; + + GPR[rd] = GPR[ERS]; + GPR[re] = GPR[ERT]; +} + + +010001,0000,3.RT,3.RS:POOL16C:16::NOT16 +"not16 r<TRT>, r<TRS>" +*micromips32: +*micromips64: +{ + do_nor (SD_, 0, TRS, TRT); +} + + +010001,0011,3.RT,3.RS:POOL16C:16::OR16 +"or16 r<TRT>, r<TRS>" +*micromips32: +*micromips64: +{ + do_or (SD_, TRS, TRT, TRT); +} + + +100010,3.RT_S,3.BASE,4.IMMEDIATE:MICROMIPS:16::SB16 +"sb16 r<TRT_S>, <IMMEDIATE>(r<TBASE>)" +*micromips32: +*micromips64: +{ + do_store (SD_, AccessLength_BYTE, GPR[TBASE], IMMEDIATE, GPR[TRT_S]); +} + + +010001,101100,4.CODE:POOL16C:16::SDBBP16 +"sdbbp16 %#lx<CODE>" +*micromips32: +*micromips64: +{ + SignalException (DebugBreakPoint, instruction_0); +} + + +101010,3.RT_S,3.BASE,4.IMMEDIATE:MICROMIPS:16::SH16 +"sh16 r<TRT_S>, <IMM_SHIFT_1BIT>(r<TBASE>)" +*micromips32: +*micromips64: +{ + do_store (SD_, AccessLength_HALFWORD, GPR[TBASE], IMM_SHIFT_1BIT, GPR[TRT_S]); +} + + +001001,3.RD,3.RT,3.SHIFT,0:POOL16B:16::SLL16 +"sll16 r<TRD>, r<TRT>, <SHIFT_DEC>" +*micromips32: +*micromips64: +{ + do_sll (SD_, TRT, TRD, SHIFT_DEC); +} + + +001001,3.RD,3.RT,3.SHIFT,1:POOL16B:16::SRL16 +"srl16 r<TRD>, r<TRT>, <SHIFT_DEC>" +*micromips32: +*micromips64: +{ + do_srl (SD_, TRT, TRD, SHIFT_DEC); +} + + +000001,3.RD,3.RT,3.RS,1:POOL16A:16::SUBU16 +"subu16 r<TRD>, r<TRS>, r<TRT>" +*micromips32: +*micromips64: +{ + do_subu (SD_, TRS, TRT, TRD); +} + + +111010,3.RT_S,3.BASE,4.IMMEDIATE:MICROMIPS:16::SW16 +"sw16 r<TRT_S>, <IMM_SHIFT_2BIT>(r<TBASE>)" +*micromips32: +*micromips64: +{ + do_store (SD_, AccessLength_WORD, GPR[TBASE], IMM_SHIFT_2BIT, GPR[TRT_S]); +} + + +110010,5.RT,5.IMMEDIATE:MICROMIPS:16::SWSP +"swsp r<RT>, <IMM_SHIFT_2BIT>(sp)" +*micromips32: +*micromips64: +{ + do_store (SD_, AccessLength_WORD, SP, IMM_SHIFT_2BIT, GPR[RT]); +} + + +010001,0101,2.LWMREGS,4.IMMEDIATE:POOL16C:16::SWM16 +"swm16 %s<LWMREGS>, <IMM_SHIFT_2BIT>(sp)" +*micromips32: +*micromips64: +{ + int address = GPR[SPIDX] + IMM_SHIFT_2BIT; + int reg_offset; + + for (reg_offset = 0; reg_offset <= LWMREGS; reg_offset++) + do_store (SD_, AccessLength_WORD, address, reg_offset * 4, + GPR[16 + reg_offset]); + + do_store (SD_, AccessLength_WORD, address, reg_offset * 4, RA); +} + + +010001,0001,3.RT,3.RS:POOL16C:16::XOR16 +"xor16 r<TRT>, r<TRS>" +*micromips32: +*micromips64: +{ + do_xor (SD_, TRS, TRT, TRT); +} + + +000000,5.RT,5.RS,5.RD,00100,010000:POOL32A:32::ADD +"add r<RD>, r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_add (SD_, RS, RT, RD); +} + + +000100,5.RT,5.RS,16.IMMEDIATE:MICROMIPS:32::ADDI +"addi r<RT>, r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_addi (SD_, RS, RT, IMMEDIATE); +} + + +001100,5.RT,5.RS,16.IMMEDIATE:MICROMIPS:32::ADDIU +"li r<RT>, <IMMEDIATE>":RS==0 +"addiu r<RT>, r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_addiu (SD_, RS, RT, IMMEDIATE); +} + + +011110,3.RS,23.IMMEDIATE:MICROMIPS:32::ADDIUPC +"addiupc r<TRS>, <IMM_SHIFT_2BIT>" +*micromips32: +*micromips64: +{ + GPR[TRS] = EXTEND32 ((CIA & ~3) + EXTEND25 (IMM_SHIFT_2BIT)); +} + + +000000,5.RT,5.RS,5.RD,00101,010000:POOL32A:32::ADDU +"addu r<RD>, r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_addu (SD_, RS, RT, RD); +} + + +000000,5.RT,5.RS,5.RD,01001,010000:POOL32A:32::AND +"and r<RD>, r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_and (SD_, RS, RT, RD); +} + + +110100,5.RT,5.RS,16.IMMEDIATE:MICROMIPS:32::ANDI +"andi r<RT>, r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_andi (SD_, RS, RT, IMMEDIATE); +} + + +010000,1110,1.TF,3.CC,00,16.IMMEDIATE:POOL32I:32,f::BC1a +"bc1%s<TF> <IMMEDIATE>":CC == 0 +"bc1%s<TF> <CC>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + check_fpu (SD_); + if (GETFCC(CC) == TF) + { + address_word dest = NIA + (EXTEND16 (IMMEDIATE) << 1); + NIA = delayslot_micromips (SD_, dest, NIA, MICROMIPS_DELAYSLOT_SIZE_ANY); + } +} + + +010000,1010,1.TF,3.CC,00,16.IMMEDIATE:POOL32I:32::BC2a +"bc2%s<TF> <CC>, <IMMEDIATE>":CC == 0 +"bc2%s<TF> <CC>, <IMMEDIATE>" +*micromips32: +*micromips64: + + +100101,5.RT,5.RS,16.IMMEDIATE:MICROMIPS:32::BEQ +"b <IMMEDIATE>":RT == 0 && RS == 0 +"beq r<RS>, r<RT>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + address_word offset = EXTEND16 (IMMEDIATE) << 1; + if ((signed_word) GPR[RS] == (signed_word) GPR[RT]) + NIA = delayslot_micromips (SD_, NIA + offset, NIA, + MICROMIPS_DELAYSLOT_SIZE_ANY); +} + +010000,00010,5.RS,16.IMMEDIATE:POOL32I:32::BGEZ +"bgez r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + address_word offset = EXTEND16 (IMMEDIATE) << 1; + if ((signed_word) GPR[RS] >= 0) + NIA = delayslot_micromips (SD_, NIA + offset, NIA, + MICROMIPS_DELAYSLOT_SIZE_ANY); +} + + +010000,00111,5.RS,16.IMMEDIATE:POOL32I:32::BEQZC +"beqzc r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + address_word offset = EXTEND16 (IMMEDIATE) << 1; + if (GPR[RS] == 0) + NIA = NIA + offset; +} + + +010000,00011,5.RS,16.IMMEDIATE:POOL32I:32::BGEZAL +"bal <IMMEDIATE>":RS == 0 +"bgezal r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + address_word offset = EXTEND16 (IMMEDIATE) << 1; + if (RS == 31) + Unpredictable (); + RA = (NIA + MICROMIPS_DELAYSLOT_SIZE_32) | ISA_MODE_MICROMIPS; + if ((signed_word) GPR[RS] >= 0) + NIA = delayslot_micromips (SD_, NIA + offset, NIA, + MICROMIPS_DELAYSLOT_SIZE_32); +} + + +010000,00110,5.RS,16.IMMEDIATE:POOL32I:32::BGTZ +"bgtz r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + address_word offset = EXTEND16 (IMMEDIATE) << 1; + if ((signed_word) GPR[RS] > 0) + NIA = delayslot_micromips (SD_, NIA + offset, NIA, + MICROMIPS_DELAYSLOT_SIZE_ANY); +} + + +010000,10011,5.RS,16.IMMEDIATE:POOL32I:32::BGEZALS +"bal <IMMEDIATE>":RS == 0 +"bgezals r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + address_word offset = EXTEND16 (IMMEDIATE) << 1; + if (RS == 31) + Unpredictable (); + RA = (NIA + MICROMIPS_DELAYSLOT_SIZE_16) | ISA_MODE_MICROMIPS; + if ((signed_word) GPR[RS] >= 0) + NIA = delayslot_micromips (SD_, NIA + offset, NIA, + MICROMIPS_DELAYSLOT_SIZE_16); +} + + +010000,00100,5.RS,16.IMMEDIATE:POOL32I:32::BLEZ +"blez r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + address_word offset = EXTEND16 (IMMEDIATE) << 1; + /* NOTE: The branch occurs AFTER the next instruction has been + executed */ + if ((signed_word) GPR[RS] <= 0) + NIA = delayslot_micromips (SD_, NIA + offset, NIA, + MICROMIPS_DELAYSLOT_SIZE_ANY); +} + + +010000,00000,5.RS,16.IMMEDIATE:POOL32I:32::BLTZ +"bltz r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + address_word offset = EXTEND16 (IMMEDIATE) << 1; + if ((signed_word) GPR[RS] < 0) + NIA = delayslot_micromips (SD_, NIA + offset, NIA, + MICROMIPS_DELAYSLOT_SIZE_ANY); +} + + +010000,00001,5.RS,16.IMMEDIATE:POOL32I:32::BLTZAL +"bltzal r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + address_word offset = EXTEND16 (IMMEDIATE) << 1; + if (RS == 31) + Unpredictable (); + RA = (NIA + MICROMIPS_DELAYSLOT_SIZE_32) | ISA_MODE_MICROMIPS; + /* NOTE: The branch occurs AFTER the next instruction has been + executed */ + if ((signed_word) GPR[RS] < 0) + NIA = delayslot_micromips (SD_, NIA + offset, NIA, + MICROMIPS_DELAYSLOT_SIZE_32); +} + +010000,10001,5.RS,16.IMMEDIATE:POOL32I:32::BLTZALS +"bltzals r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + address_word offset = EXTEND16 (IMMEDIATE) << 1; + if (RS == 31) + Unpredictable (); + RA = (NIA + MICROMIPS_DELAYSLOT_SIZE_16) | ISA_MODE_MICROMIPS; + if ((signed_word) GPR[RS] < 0) + NIA = delayslot_micromips (SD_, NIA + offset, NIA, + MICROMIPS_DELAYSLOT_SIZE_16); +} + + +101101,5.RT,5.RS,16.IMMEDIATE:MICROMIPS:32::BNE +"bne r<RS>, r<RT>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + address_word offset = EXTEND16 (IMMEDIATE) << 1; + if ((signed_word) GPR[RS] != (signed_word) GPR[RT]) + NIA = delayslot_micromips (SD_, NIA + offset, NIA, + MICROMIPS_DELAYSLOT_SIZE_ANY); +} + + +010000,00101,5.RS,16.IMMEDIATE:POOL32I:32::BNEZC +"bnezc r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + address_word offset = EXTEND16 (IMMEDIATE) << 1; + if ((signed_word) GPR[RS] != 0) + NIA = NIA + offset; +} + + +000000,20.CODE,000111:POOL32A:32::BREAK +"break %#lx<CODE>" +*micromips32: +*micromips64: +{ + do_break (SD_, instruction_0); +} + + +001000,5.OP,5.BASE,0110,12.IMMEDIATE:POOL32B:32::CACHE +"cache <OP>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + address_word base = GPR[BASE]; + address_word offset = EXTEND12 (IMMEDIATE); + address_word vaddr = loadstore_ea (SD_, base, offset); + address_word paddr; + int uncached; + if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, + isTARGET, isREAL)) + CacheOp (OP, vaddr, paddr, instruction_0); +} + + +011000,5.OP,5.BASE,1010011,9.IMMEDIATE:POOL32C:32::CACHEE +"cachee <OP>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +010101,5.RT,5.FS,0001000000,111011:POOL32F:32,f::CFC1 +"cfc1 r<RT>, f<FS>" +*micromips32: +*micromips64: +{ + do_cfc1 (SD_, RT, FS); +} + + +000000,5.RT,5.IMPL,1100110100,111100:POOL32A:32::CFC2 +"cfc2 r<RT>, <IMPL>" +*micromips32: +*micromips64: + + +000000,5.RT,5.RS,0100101100,111100:POOL32A:32::CLO +"clo r<RT>, r<RS>" +*micromips32: +*micromips64: +{ + do_clo (SD_, RT, RS); +} + + +000000,5.RT,5.RS,0101101100,111100:POOL32A:32::CLZ +"clz r<RT>, r<RS>" +*micromips32: +*micromips64: +{ + do_clz (SD_, RT, RS); +} + + +000000,23.COFUN,010:POOL32A:32::COP2 +"cop2 <COFUN>" +*micromips32: +*micromips64: + + +010101,5.RT,5.FS,0001100000,111011:POOL32F:32,f::CTC1 +"ctc1 r<RT>, f<FS>" +*micromips32: +*micromips64: +{ + do_ctc1 (SD_, RT, FS); +} + + +000000,5.RT,5.IMPL,1101110100,111100:POOL32A:32::CTC2 +"ctc2 r<RT>, <IMPL>" +*micromips32: +*micromips64: + + +000000,00000000001110001101,111100:POOL32A:32::DERET +"deret" +*micromips32: +*micromips64: + + +000000,00000,5.RS,0100011101,111100:POOL32A:32::DI +"di":RS == 0 +"di r<RS>" +*micromips32: +*micromips64: +{ + do_di (SD_, RS); +} + +000000,5.RT,5.RS,1010101100,111100:POOL32A:32::DIV +"div r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_div (SD_, RS, RT); +} + + +000000,5.RT,5.RS,1011101100,111100:POOL32A:32::DIVU +"divu r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_divu (SD_, RS, RT); +} + + +000000,00000000000001100000,000000:POOL32A:32::EHB +"ehb" +*micromips32: +*micromips64: + + +000000,00000,5.RS,0101011101,111100:POOL32A:32::EI +"ei":RS == 0 +"ei r<RS>" +*micromips32: +*micromips64: +{ + do_ei (SD_, RS); +} + +000000,00000000001111001101,111100:POOL32A:32::ERET +"eret" +*micromips32: +*micromips64: +{ + if (SR & status_ERL) + { + /* Oops, not yet available */ + sim_io_printf (SD, "Warning: ERET when SR[ERL] set not supported"); + NIA = EPC; + SR &= ~status_ERL; + } + else + { + NIA = EPC; + SR &= ~status_EXL; + } +} + + +000000,5.RT,5.RS,5.MSBD,5.LSB,101100:POOL32A:32::EXT +"ext r<RT>, r<RS>, <LSB>, <MSBD+1>" +*micromips32: +*micromips64: +{ + do_ext (SD_, RT, RS, LSB, MSBD); +} + + +000000,5.RT,5.RS,5.MSBD,5.LSB,001100:POOL32A:32::INS +"ins r<RT>, r<RS>, <LSB>, <MSBD-LSB+1>" +*micromips32: +*micromips64: +{ + do_ins (SD_, RT, RS, LSB, MSBD); +} + + +110101,26.IMMEDIATE:MICROMIPS:32::J +"j <IMM_SHIFT_1BIT>" +*micromips32: +*micromips64: +{ + address_word region = (NIA & MASK (63, 27)); + NIA = delayslot_micromips (SD_, region | (IMM_SHIFT_1BIT), NIA, + MICROMIPS_DELAYSLOT_SIZE_ANY); +} + + +111101,26.IMMEDIATE:MICROMIPS:32::JAL +"jal <IMM_SHIFT_1BIT>" +*micromips32: +*micromips64: +{ + /* NOTE: The region used is that of the delay slot and NOT the + current instruction */ + address_word region = (NIA & MASK (63, 27)); + NIA = do_micromips_jal (SD_, (region | (IMM_SHIFT_1BIT)), NIA, + MICROMIPS_DELAYSLOT_SIZE_32); +} + + +011101,26.IMMEDIATE:MICROMIPS:32::JALS +"jals <IMM_SHIFT_1BIT>" +*micromips32: +*micromips64: +{ + address_word region = (NIA & MASK (63, 27)); + NIA = do_micromips_jal (SD_, (region | (IMM_SHIFT_1BIT)), NIA, + MICROMIPS_DELAYSLOT_SIZE_16); +} + +000000,5.RT!0,5.RS,0000111100,111100:POOL32A:32::JALR +"jalr r<RS>":RT == 31 +"jalr r<RT>, r<RS>" +*micromips32: +*micromips64: +{ + if (RS == RT) + Unpredictable (); + NIA = do_micromips_jalr (SD_, RT, RS, NIA, MICROMIPS_DELAYSLOT_SIZE_32); +} + +000000,5.RT,5.RS,0100111100,111100:POOL32A:32::JALRS +"jalrs r<RT>, r<RS>" +*micromips32: +*micromips64: +{ + if (RS == RT) + Unpredictable (); + NIA = do_micromips_jalr (SD_, RT, RS, NIA, MICROMIPS_DELAYSLOT_SIZE_16); +} + + +111100,26.IMMEDIATE:MICROMIPS:32::JALX +"jalx <IMM_SHIFT_2BIT>" +*micromips32: +*micromips64: +{ + address_word region = (NIA & MASK (63, 26)); + NIA = do_micromips_jal (SD_, (region | (IMM_SHIFT_2BIT)) | ISA_MODE_MIPS32, + NIA, MICROMIPS_DELAYSLOT_SIZE_32); + SD->isa_mode = ISA_MODE_MIPS32; +} + +000000,00000,5.RS,0000111100,111100:POOL32A:32::JR +"jr r<RS>" +*micromips32: +*micromips64: +{ + NIA = process_isa_mode (SD_, + delayslot_micromips (SD_, GPR[RS], NIA, + MICROMIPS_DELAYSLOT_SIZE_32)); +} + + +000000,5.RT,5.RS,0001111100,111100:POOL32A:32::JALR.HB +"jalr.hb r<RT>, r<RS>" +*micromips32: +*micromips64: +{ + if (RS == RT) + Unpredictable (); + NIA = do_micromips_jalr (SD_, RT, RS, NIA, MICROMIPS_DELAYSLOT_SIZE_32); +} + + +000000,5.RT,5.RS,0101111100,111100:POOL32A:32::JALRS.HB +"jalrs.hb r<RT>, r<RS>" +*micromips32: +*micromips64: +{ + if (RS == RT) + Unpredictable (); + NIA = do_micromips_jalr (SD_, RT, RS, NIA, MICROMIPS_DELAYSLOT_SIZE_16); +} + + +000000,00000,5.RS,0111111100,111100:POOL32A:32::JR.HB +"jr.hb r<RS>" +*micromips32: +*micromips64: +{ + NIA = process_isa_mode (SD_, + delayslot_micromips (SD_, GPR[RS], NIA, + MICROMIPS_DELAYSLOT_SIZE_32)); +} + + +000111,5.RT,5.BASE,16.IMMEDIATE:MICROMIPS:32::LB +"lb r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_lb (SD_, RT, IMMEDIATE, BASE); +} + + +011000,5.RT,5.BASE,0110100,9.IMMEDIATE:POOL32C:32::LBE +"lbe r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +000101,5.RT,5.BASE,16.IMMEDIATE:MICROMIPS:32::LBU +"lbu r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_lbu (SD_, RT, IMMEDIATE, BASE); +} + + +011000,5.RT,5.BASE,0110000,9.IMMEDIATE:POOL32C:32::LBUE +"lbue r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +101111,5.FT,5.BASE,16.IMMEDIATE:MICROMIPS:32,f::LDC1a +"ldc1 f<FT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +{ + check_fpu (SD_); + COP_LD (1, FT, do_load_double (SD_, GPR[BASE], EXTEND16 (IMMEDIATE))); +} + + +101111,5.FT,5.BASE,16.IMMEDIATE:MICROMIPS:32,f::LDC1b +"ldc1 f<FT>, <IMMEDIATE>(r<BASE>)" +*micromips64: +{ + check_fpu (SD_); + COP_LD (1, FT, do_load (SD_, AccessLength_DOUBLEWORD, GPR[BASE], + EXTEND16 (IMMEDIATE))); +} + + +001000,5.RT,5.BASE,0010,12.IMMEDIATE:POOL32B:32::LDC2 +"ldc2 r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +001111,5.RT,5.BASE,16.IMMEDIATE:MICROMIPS:32::LH +"lh r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_lh (SD_, RT, IMMEDIATE, BASE); +} + + +011000,5.RT,5.BASE,0110101,9.IMMEDIATE:POOL32C:32::LHE +"lhe r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +001101,5.RT,5.BASE,16.IMMEDIATE:MICROMIPS:32::LHU +"lhu r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_lhu (SD_, RT, IMMEDIATE, BASE); +} + + +011000,5.RT,5.BASE,0110001,9.IMMEDIATE:POOL32C:32::LHUE +"lhue r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +011000,5.RT,5.BASE,0011,12.IMMEDIATE:POOL32C:32::LL +"ll r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_ll (SD_, RT, EXTEND12 (IMMEDIATE), BASE); +} + + +011000,5.RT,5.BASE,0110110,9.IMMEDIATE:POOL32C:32::LLE +"lle r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +010000,01101,5.RS,16.IMMEDIATE:POOL32I:32::LUI +"lui r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_lui (SD_, RS, IMMEDIATE); +} + + +010101,5.INDEX,5.BASE,5.FD,00101,001000:POOL32F:32,f::LUXC1 +"luxc1 f<FD>, r<INDEX>(r<BASE>)" +*micromips32: +{ + do_luxc1_32 (SD_, FD, INDEX, BASE); +} + + +010101,5.INDEX,5.BASE,5.FD,00101,001000:POOL32F:64,f::LUXC1 +"luxc1 f<FD>, r<INDEX>(r<BASE>)" +*micromips64: +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + do_luxc1_64 (SD_, FD, INDEX, BASE); +} + + +111111,5.RT,5.BASE,16.IMMEDIATE:MICROMIPS:32::LW +"lw r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_lw (SD_, RT, IMMEDIATE, BASE); +} + + +100111,5.FT,5.BASE,16.IMMEDIATE:MICROMIPS:32,f::LWC1 +"lwc1 f<FT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_lwc1 (SD_, FT, IMMEDIATE, BASE); +} + + +001000,5.RT,5.BASE,0000,12.IMMEDIATE:POOL32B:32::LWC2 +"lwc2 r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +011000,5.RT,5.BASE,0110111,9.IMMEDIATE:POOL32C:32::LWE +"lwe r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +011000,5.RT,5.BASE,0110011,9.IMMEDIATE:POOL32C:32::LWEE +"lwee r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +011000,5.RT,5.BASE,0000,12.IMMEDIATE:POOL32C:32::LWL +"lwl r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_lwl (SD_, RT, EXTEND12 (IMMEDIATE), BASE); +} + + +011000,5.RT,5.BASE,0110010,9.IMMEDIATE:POOL32C:32::LWLE +"lwle r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + +:%s::::LWM32REGS:int lwmregs +*micromips32: +*micromips64: +{ + if (lwmregs & 0x10) + { + switch(lwmregs & 0xf) + { + case 0: + return "ra"; + case 1: + return "s0, ra"; + case 2: + return "s0, s1, ra"; + case 3: + return "s0, s1, s2, ra"; + case 4: + return "s0, s1, s2, s3, ra"; + case 5: + return "s0, s1, s2, s3, s4, ra"; + case 6: + return "s0, s1, s2, s3, s4, s5, ra"; + case 7: + return "s0, s1, s2, s3, s4, s5, s6, ra"; + case 8: + return "s0, s1, s2, s3, s4, s5, s6, s7, ra"; + case 9: + return "s0, s1, s2, s3, s4, s5, s6, s7, s8, ra"; + default: + return ""; + } + } + else + { + switch(lwmregs & 0xf) + { + case 1: + return "s0"; + case 2: + return "s0, s1"; + case 3: + return "s0, s1, s2"; + case 4: + return "s0, s1, s2, s3"; + case 5: + return "s0, s1, s2, s3, s4"; + case 6: + return "s0, s1, s2, s3, s4, s5"; + case 7: + return "s0, s1, s2, s3, s4, s5, s6"; + case 8: + return "s0, s1, s2, s3, s4, s5, s6, s7"; + case 9: + return "s0, s1, s2, s3, s4, s5, s6, s7, s8"; + default: + return ""; + } + } +} + +001000,5.LWM32REGS,5.BASE,0101,12.IMMEDIATE:POOL32B:32::LWM32 +"lwm32 %s<LWM32REGS>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + int address_base = GPR[BASE] + EXTEND12 (IMMEDIATE); + int reg_offset; + for (reg_offset = 0; reg_offset < (LWM32REGS & 0xf); reg_offset++) + { + int dst = (reg_offset == 8) ? 30 : 16 + reg_offset; + GPR[dst] = EXTEND32 (do_load (SD_, AccessLength_WORD, address_base, + 4 * reg_offset)); + } + + if (LWM32REGS & 0x10) + RA = EXTEND32 (do_load (SD_, AccessLength_WORD, address_base, + 4 * reg_offset)); +} + + +001000,5.RD,5.BASE,0001,12.IMMEDIATE:POOL32B:32::LWP +"lwp r<RD>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + if (BASE == RD || RD == 31) + Unpredictable (); + else + { + do_lw (SD_, RD, EXTEND12 (IMMEDIATE), BASE); + do_lw (SD_, RD + 1, EXTEND12 (IMMEDIATE) + 4, BASE); + } +} + + +011000,5.RT,5.BASE,0001,12.IMMEDIATE:POOL32C:32::LWR +"lwr r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_lwr (SD_, RT, EXTEND12 (IMMEDIATE), BASE); +} + + +011000,5.RT,5.BASE,1110,12.IMMEDIATE:POOL32C:32::LWU +"lwu r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_lwu (SD_, RT, IMMEDIATE, BASE, instruction_0); +} + + +010101,5.INDEX,5.BASE,5.FD,00001,001000:POOL32F:32,f::LWXC1 +"lwxc1 f<FD>, <INDEX>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_lwxc1 (SD_, FD, INDEX, BASE, instruction_0); +} + + +000000,5.INDEX,5.BASE,5.RD,00100,011000:POOL32A:32::LWXS +"lwxs r<RD>, r<INDEX>(r<BASE>)" +*micromips32: +*micromips64: +{ + GPR[RD] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[BASE], + GPR[INDEX] * 4)); +} + + +000000,5.RT,5.RS,1100101100,111100:POOL32A:32::MADD +"madd r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_madd (SD_, RS, RT); +} + + +000000,5.RT,5.RS,1101101100,111100:POOL32A:32::MADDU +"maddu r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_maddu (SD_, RS, RT); +} + + +000000,5.RT,5.RS,00,3.SEL,00011,111100:POOL32A:32::MFC0 +"mfc0 r<RS>, r<RT>": SEL == 0 +"mfc0 r<RS>, r<RT>, <SEL>" +*micromips32: +*micromips64: +{ + DecodeCoproc (instruction_0, 0, cp0_mfc0, RT, RS, SEL); +} + + +010101,5.RT,5.FS,0010000000,111011:POOL32F:32,f::MFC1 +"mfc1 r<RT>, f<FS>" +*micromips32: +*micromips64: +{ + do_mfc1b (SD_, RT, FS); +} + + +000000,5.RT,5.IMPL,0100110100,111100:POOL32A:32::MFC2 +"mfc2 r<RT>, <IMPL>" +*micromips32: +*micromips64: + + +010101,5.RT,5.FS,0011000000,111011:POOL32F:32,f::MFHC1 +"mfhc1 r<RT>, f<FS>" +*micromips32: +*micromips64: +{ + do_mfhc1 (SD_, RT, FS); +} + + +000000,5.RT,5.IMPL,1000110100,111100:POOL32A:32::MFHC2 +"mfhc2 r<RT>, <IMPL>" +*micromips32: +*micromips64: + + +000000,00000,5.RS,0000110101,111100:POOL32A:32::MFHI +"mfhi r<RS>" +*micromips32: +*micromips64: +{ + do_mfhi (SD_, RS); +} + + +000000,00000,5.RS,0001110101,111100:POOL32A:32::MFLO +"mflo r<RS>" +*micromips32: +*micromips64: +{ + do_mflo (SD_, RS); +} + + +// MOVF +// MOVT +010101,5.RT,5.RS,3.CC,0,1.TF,00101,111011:POOL32F:32::MOVtf +"mov%s<TF> r<RT>, r<RS>, CC" +*micromips32: +*micromips64: +{ + do_movtf (SD_, TF, RT, RS, CC); +} + + +000000,5.RT,5.RS,5.RD,00000,011000:POOL32A:32::MOVN +"movn r<RD>, r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_movn (SD_, RD, RS, RT); +} + + +000000,5.RT,5.RS,5.RD,00001,011000:POOL32A:32::MOVZ +"movz r<RD>, r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_movz (SD_, RD, RS, RT); +} + + +000000,5.RT,5.RS,1110101100,111100:POOL32A:32::MSUB +"msub r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_msub (SD_, RS, RT); +} + + +000000,5.RT,5.RS,1111101100,111100:POOL32A:32::MSUBU +"msubu r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_msubu (SD_, RS, RT); +} + + +000000,5.RT,5.RS,00,3.SEL,01011,111100:POOL32A:32::MTC0 +"mtc0 r<RS>, r<RT>": SEL == 0 +"mtc0 r<RS>, r<RT>, <SEL>" +*micromips32: +*micromips64: +{ + DecodeCoproc (instruction_0, 0, cp0_mtc0, RT, RS, SEL); +} + + +010101,5.RT,5.FS,0010100000,111011:POOL32F:32,f::MTC1 +"mtc1 r<RT>, f<FS>" +*micromips32: +*micromips64: +{ + do_mtc1b (SD_, RT, FS); +} + + +000000,5.RT,5.IMPL,0101110100,111100:POOL32A:32::MTC2 +"mtc2 r<RT>, <IMPL>" +*micromips32: +*micromips64: + + +010101,5.RT,5.FS,0011100000,111011:POOL32F:32,f::MTHC1 +"mthc1 r<RT>, f<FS>" +*micromips32: +*micromips64: +{ + do_mthc1 (SD_, RT, FS); +} + + +000000,5.RT,5.IMPL,1001110100,111100:POOL32A:32::MTHC2 +"mthc2 r<RT>, <IMPL>" +*micromips32: +*micromips64: + + +000000,00000,5.RS,0010110101,111100:POOL32A:32::MTHI +"mthi r<RS>" +*micromips32: +*micromips64: +{ + do_mthi (SD_, RS); +} + + +000000,00000,5.RS,0011110101,111100:POOL32A:32::MTLO +"mtlo r<RS>" +*micromips32: +*micromips64: +{ + do_mtlo (SD_, RS); +} + + +000000,5.RT,5.RS,5.RD,01000,010000:POOL32A:32::MUL +"mul r<RD>, r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_mul (SD_, RD, RS, RT); +} + + +000000,5.RT,5.RS,1000101100,111100:POOL32A:32::MULT +"mult r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_mult (SD_, RS, RT, 0); +} + + +000000,5.RT,5.RS,1001101100,111100:POOL32A:32::MULTU +"multu r<RS> r<RT>" +*micromips32: +*micromips64: +{ + do_multu (SD_, RS, RT, 0); +} + + +000000,00000000000000000000,000000:POOL32A:32::NOP +"nop" +*micromips32: +*micromips64: +{ +} + + +000000,5.RT,5.RS,5.RD,01011,010000:POOL32A:32::NOR +"nor r<RD>, r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_nor (SD_, RS, RT, RD); +} + + +000000,5.RT,5.RS,5.RD,01010,010000:POOL32A:32::OR +"or r<RD>, r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_or (SD_, RS, RT, RD); +} + + +010100,5.RT,5.RS,16.IMMEDIATE:MICROMIPS:32::ORI +"ori r<RT>, r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_ori (SD_, RS, RT, IMMEDIATE); +} + + +000000,00000000000010100000,000000:POOL32A:32::PAUSE +"pause" +*micromips32: +*micromips64: + + +011000,5.HINT,5.BASE,0010,12.IMMEDIATE:POOL32C:32::PREF +"pref <HINT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_pref (SD_, HINT, EXTEND12 (IMMEDIATE), BASE); +} + + +011000,5.HINT,5.BASE,1010010,9.IMMEDIATE:POOL32C:32::PREFE +"prefe <HINT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +010101,5.INDEX,5.BASE,5.HINT,00110,100000:POOL32F:32::PREFX +"prefx <HINT>, r<INDEX>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_prefx (SD_, HINT, INDEX, BASE); +} + +000000,5.RT,5.RS,0110101100,111100:POOL32A:32::RDHWR +"rdhwr r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_rdhwr (SD_, RT, RS); +} + +000000,5.RT,5.RS,1110000101,111100:POOL32A:32::RDPGPR +"rdpgpr r<RS>, r<RT>" +*micromips32: +*micromips64: + + +000000,5.RT,5.RS,5.SHIFT,00011,000000:POOL32A:32::ROTR +"rotr r<RT>, r<RS>, <SHIFT>" +*micromips32: +*micromips64: +{ + GPR[RT] = do_ror (SD_, GPR[RS], SHIFT); +} + + +000000,5.RT,5.RS,5.RD,00011,010000:POOL32A:32::ROTRV +"rotrv r<RD>, r<RT>, r<RS>" +*micromips32: +*micromips64: +{ + GPR[RD] = do_ror (SD_, GPR[RT], GPR[RS]); +} + + +000110,5.RT,5.BASE,16.IMMEDIATE:MICROMIPS:32::SB +"sb r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_store (SD_, AccessLength_BYTE, GPR[BASE], EXTEND16 (IMMEDIATE), GPR[RT]); +} + + +011000,5.RT,5.BASE,1010101,9.IMMEDIATE:POOL32C:32::SBE +"sbe r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +011000,5.RT,5.BASE,1011,12.IMMEDIATE:POOL32C:32::SC +"sc r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_sc (SD_, RT, EXTEND12 (IMMEDIATE), BASE, instruction_0); +} + + +011000,5.RT,5.BASE,1010110,9.IMMEDIATE:POOL32C:32::SCE +"sce r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +000000,10.CODE,1101101101,111100:POOL32A:32::SDBBP +"sdbbp %#lx<CODE>" +*micromips32: +*micromips64: +{ + SignalException (DebugBreakPoint, instruction_0); +} + + +101110,5.FT,5.BASE,16.IMMEDIATE:MICROMIPS:32,f::SDC1a +"sdc1 f<FT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +{ + do_sdc1 (SD_, FT, IMMEDIATE, BASE); +} + + +101110,5.FT,5.BASE,16.IMMEDIATE:MICROMIPS:32,f::SDC1b +"sdc1 f<FT>, <IMMEDIATE>(r<BASE>)" +*micromips64: +{ + check_fpu (SD_); + do_store (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (IMMEDIATE), + COP_SD (1, FT)); +} + + +001000,5.RT,5.BASE,1010,12.IMMEDIATE:MICROMIPS:32::SDC2 +"sdc2 r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +000000,5.RT,5.RS,0010101100,111100:POOL32A:32::SEB +"seb r<RT>, r<RS>" +*micromips32: +*micromips64: +{ + do_seb (SD_, RT, RS); +} + + +000000,5.RT,5.RS,0011101100,111100:POOL32A:32::SEH +"seh r<RT>, r<RS>" +*micromips32: +*micromips64: +{ + do_seh (SD_, RT, RS); +} + + +001110,5.RT,5.BASE,16.IMMEDIATE:MICROMIPS:32::SH +"sh r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_store (SD_, AccessLength_HALFWORD, GPR[BASE], EXTEND16 (IMMEDIATE), + GPR[RT]); +} + + +011000,5.RT,5.BASE,1010100,9.IMMEDIATE:POOL32C:32::SHE +"she r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +000000,5.RT!0,5.RS!0,5.SHIFT,00000,000000:POOL32A:32::SLL +"sll r<RT>, r<RS>, <SHIFT>" +*micromips32: +*micromips64: +{ + do_sll (SD_, RS, RT, SHIFT); +} + + +000000,5.RT,5.RS,5.RD,00000,010000:POOL32A:32::SLLV +"sllv r<RD>, r<RT>, r<RS>" +*micromips32: +*micromips64: +{ + do_sllv (SD_, RS, RT, RD); +} + + +000000,5.RT,5.RS,5.RD,01101,010000:POOL32A:32::SLT +"slt r<RD>, r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_slt (SD_, RS, RT, RD); +} + + +100100,5.RT,5.RS,16.IMMEDIATE:MICROMIPS:32::SLTI +"slti r<RT>, r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_slti (SD_, RS, RT, IMMEDIATE); +} + + +101100,5.RT,5.RS,16.IMMEDIATE:MICROMIPS:32::SLTIU +"sltiu r<RT>, r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_sltiu (SD_, RS, RT, IMMEDIATE); +} + + +000000,5.RT,5.RS,5.RD,01110,010000:POOL32A:32::SLTU +"sltu r<RD>, r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_sltu (SD_, RS, RT, RD); +} + + +000000,5.RT,5.RS,5.SHIFT,00010,000000:POOL32A:32::SRA +"sra r<RT>, r<RS>, <SHIFT>" +*micromips32: +*micromips64: +{ + do_sra (SD_, RS, RT, SHIFT); +} + + +000000,5.RT,5.RS,5.RD,00010,010000:POOL32A:32::SRAV +"srav r<RD>, r<RT>, r<RS>" +*micromips32: +*micromips64: +{ + do_srav (SD_, RS, RT, RD); +} + + +000000,5.RT,5.RS,5.SHIFT,00001,000000:POOL32A:32::SRL +"srl r<RT>, r<RS>, <SHIFT>" +*micromips32: +*micromips64: +{ + do_srl (SD_, RS, RT, SHIFT); +} + + +000000,5.RT,5.RS,5.RD,00001,010000:POOL32A:32::SRLV +"srlv r<RD>, r<RT>, r<RS>" +*micromips32: +*micromips64: +{ + do_srlv (SD_, RS, RT, RD); +} + + +000000,00000000000000100000,000000:POOL32A:32::SSNOP +"ssnop" +*micromips32: +*micromips64: +{ +} + + +000000,5.RT,5.RS,5.RD,00110,010000:POOL32A:32::SUB +"sub r<RD>, r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_sub (SD_, RD, RS, RT); +} + + +000000,5.RT,5.RS,5.RD,00111,010000:POOL32A:32::SUBU +"subu r<RD>, r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_subu (SD_, RS, RT, RD); +} + + +010101,5.INDEX,5.BASE,5.FD,00110,001000:POOL32F:32,f::SUXC1 +"suxc1 f<FD>, r<INDEX>(r<BASE>)" +*micromips32: +{ + do_suxc1_32 (SD_, FD, INDEX, BASE); +} + + +010101,5.INDEX,5.BASE,5.FD,00110,001000:POOL32F:64,f::SUXC1 +"suxc1 f<FD>, r<INDEX>(r<BASE>)" +*micromips64: +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + do_suxc1_64 (SD_, FD, INDEX, BASE); +} + +111110,5.RT,5.BASE,16.IMMEDIATE:MICROMIPS:32::SW +"sw r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_store (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (IMMEDIATE), GPR[RT]); +} + + +100110,5.FT,5.BASE,16.IMMEDIATE:MICROMIPS:32,f::SWC1 +"swc1 f<FT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_swc1 (SD_, FT, IMMEDIATE, BASE, instruction_0); +} + + +001000,5.RT,5.BASE,1000,12.IMMEDIATE:POOL32B:32::SWC2 +"swc2 r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +011000,5.RT,5.BASE,1010111,9.IMMEDIATE:POOL32C:32::SWE +"swe r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +011000,5.RT,5.BASE,1000,12.IMMEDIATE:POOL32C:32::SWL +"swl r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_store_left (SD_, AccessLength_WORD, GPR[BASE], EXTEND12 (IMMEDIATE), + GPR[RT]); +} + + +011000,5.RT,5.BASE,1010000,9.IMMEDIATE:POOL32C:32::SWLE +"swle r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +001000,5.LWM32REGS,5.BASE,1101,12.IMMEDIATE:POOL32B:32::SWM32 +"swm32 %s<LWM32REGS>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + int address_base = GPR[BASE] + EXTEND12 (IMMEDIATE); + int reg_offset; + for (reg_offset = 0; reg_offset < (LWM32REGS & 0xf); reg_offset++) + { + int src = (reg_offset == 8) ? 30 : 16 + reg_offset; + do_store (SD_, AccessLength_WORD, address_base, 4 * reg_offset, + GPR[src]); + } + + if (LWM32REGS & 0x10) + do_store (SD_, AccessLength_WORD, address_base, 4 * reg_offset, RA); +} + + +001000,5.RS1,5.BASE,1001,12.IMMEDIATE:POOL32B:32::SWP +"swp r<RS1>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + if (RS1 == 31) + Unpredictable (); + else + { + do_sw (SD_, RS1, EXTEND12 (IMMEDIATE), BASE); + do_sw (SD_, RS1 + 1, EXTEND12 (IMMEDIATE) + 4, BASE); + } +} + + +011000,5.RT,5.BASE,1001,12.IMMEDIATE:POOL32C:32::SWR +"swr r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_store_right (SD_, AccessLength_WORD, GPR[BASE], EXTEND12 (IMMEDIATE), + GPR[RT]); +} + + +011000,5.RT,5.BASE,1010001,9.IMMEDIATE:POOL32C:32::SWRE +"swre r<RT>, <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: + + +010101,5.INDEX,5.BASE,5.FD,00010,001000:POOL32F:32,f::SWXC1 +"swxc1 f<FD>, r<INDEX>(r<BASE>)" +*micromips32: +*micromips64: +{ + do_swxc1 (SD_, FD, INDEX, BASE, instruction_0); +} + + +000000,00000,5.STYPE,0110101101,111100:POOL32A:32::SYNC +"sync <STYPE>" +*micromips32: +*micromips64: +{ + SyncOperation (STYPE); +} + + +010000,10000,5.BASE,16.IMMEDIATE:POOL32I:32::SYNCI +"synci <IMMEDIATE>(r<BASE>)" +*micromips32: +*micromips64: +{ +} + +000000,10.CODE,1000101101,111100:POOL32A:32::SYSCALL +"syscall %#lx<CODE>" +*micromips32: +*micromips64: +{ + SignalException (SystemCall, instruction_0); +} + + +000000,5.RT,5.RS,4.CODE,000000,111100:POOL32A:32::TEQ +"teq r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_teq (SD_, RS, RT, instruction_0); +} + + +010000,01110,5.RS,16.IMMEDIATE:POOL32I:32::TEQI +"teqi r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_teqi (SD_, RS, IMMEDIATE, instruction_0); +} + + +000000,5.RT,5.RS,4.CODE,001000,111100:POOL32A:32::TGE +"tge r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_tge (SD_, RS, RT, instruction_0); +} + + +010000,01001,5.RS,16.IMMEDIATE:POOL32I:32::TGEI +"tgei r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_tgei (SD_, RS, IMMEDIATE, instruction_0); +} + + +010000,01011,5.RS,16.IMMEDIATE:POOL32I:32::TGEIU +"tgeiu r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_tgeiu (SD_, RS, IMMEDIATE, instruction_0); +} + + +000000,5.RT,5.RS,4.CODE,010000,111100:POOL32A:32::TGEU +"tgeu r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_tgeu (SD_, RS, RT, instruction_0); +} + + +000000,00000000000000001101,111100:POOL32A:32::TLBP +"tlbp" +*micromips32: +*micromips64: + + +000000,00000000000001001101,111100:POOL32A:32::TLBR +"tlbr" +*micromips32: +*micromips64: + + +000000,00000000000010001101,111100:POOL32A:32::TLBWI +"tlbwi" +*micromips32: +*micromips64: + + +000000,00000000000011001101,111100:POOL32A:32::TLBWR +"tlbwr" +*micromips32: +*micromips64: + + +000000,5.RT,5.RS,4.CODE,100000,111100:POOL32A:32::TLT +"tlt r<RS>, r<RT>, %#lx<CODE>" +*micromips32: +*micromips64: +{ + do_tlt (SD_, RS, RT, instruction_0); +} + + +010000,01000,5.RS,16.IMMEDIATE:POOL32I:32::TLTI +"tlti r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_tlti (SD_, RS, IMMEDIATE, instruction_0); +} + + +010000,01010,5.RS,16.IMMEDIATE:POOL32I:32::TLTIU +"tltiu r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_tltiu (SD_, RS, IMMEDIATE, instruction_0); +} + + +000000,5.RT,5.RS,4.CODE,101000,111100:POOL32A:32::TLTU +"tltu r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_tltu (SD_, RS, RT, instruction_0); +} + + +000000,5.RT,5.RS,4.CODE,110000,111100:POOL32A:32::TNE +"tne r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_tne (SD_, RS, RT, instruction_0); +} + + +010000,01100,5.RS,16.IMMEDIATE:POOL32I:32::TNEI +"tnei r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_tnei (SD_, RS, IMMEDIATE, instruction_0); +} + + +000000,10.CODE,1001001101,111100:POOL32A:32::WAIT +"wait" +*micromips32: +*micromips64: + + +000000,5.RT,5.RS,1111000101,111100:POOL32A:32::WRPGPR +"wrpgpr r<RS>, r<RT>" +*micromips32: +*micromips64: + + +000000,5.RT,5.RS,0111101100,111100:POOL32A:32::WSBH +"wsbh r<RT>, r<RS>" +*micromips32: +*micromips64: +{ + do_wsbh (SD_, RT, RS); +} + + +000000,5.RT,5.RS,5.RD,01100,010000:POOL32A:32::XOR +"xor r<RD>, r<RS>, r<RT>" +*micromips32: +*micromips64: +{ + do_xor (SD_, RS, RT, RD); +} + + +011100,5.RT,5.RS,16.IMMEDIATE:MICROMIPS:32::XORI +"xori r<RT>, r<RS>, <IMMEDIATE>" +*micromips32: +*micromips64: +{ + do_xori (SD_, RS, RT, IMMEDIATE); +} + + +:%s::::FMT_MICROMIPS:int fmt +{ + switch (fmt) + { + case 0: return "s"; + case 1: return "d"; + case 2: return "ps"; + default: return "?"; + } +} + + +:%s::::FMT_MICROMIPS_CVT_D:int fmt +{ + switch (fmt) + { + case 0: return "s"; + case 1: return "w"; + case 2: return "l"; + default: return "?"; + } +} + + +:%s::::FMT_MICROMIPS_CVT_S:int fmt +{ + switch (fmt) + { + case 0: return "d"; + case 1: return "w"; + case 2: return "l"; + default: return "?"; + } +} + + +010101,5.FT,5.FS,0,2.FMT_MICROMIPS!3,0001101,111011:POOL32F:32,f::ABS.fmt +"abs.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_abs_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FT, FS, + instruction_0); +} + + +010101,5.FT,5.FS,5.FD,0,2.FMT_MICROMIPS!3,00,110000:POOL32F:32,f::ADD.fmt +"add.%s<FMT_MICROMIPS> f<FD>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_add_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FD, FS, FT, + instruction_0); +} + + +010101,5.FT,5.FS,5.FD,5.RS,011001:POOL32F:32,f::ALNV.PS +"alnv.ps f<FD>, f<FS>, f<FT>, r<RS>" +*micromips32: +*micromips64: +{ + do_alnv_ps (SD_, FD, FS, FT, RS, instruction_0); +} + + +010101,5.FT,5.FS,3.CC,0,2.FMT_MICROMIPS!3,4.COND,111100:POOL32F:32,f::C.cond.fmt +"c.%s<COND>.%s<FMT_MICROMIPS> f<FS>, f<FT>":CC == 0 +"c.%s<COND>.%s<FMT_MICROMIPS> <CC>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_c_cond_fmt (SD_, COND, convert_fmt_micromips (SD_, FMT_MICROMIPS), CC, + FS, FT, instruction_0); +} + + +010101,5.FT,5.FS,0,1.FMT_MICROMIPS,01001100,111011:POOL32F:32,f::CEIL.L.fmt +"ceil.l.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_ceil_fmt (SD_, fmt_long, FMT_MICROMIPS, FT, FS, instruction_0); +} + + +010101,5.FT,5.FS,0,1.FMT_MICROMIPS,01101100,111011:POOL32F:32,f::CEIL.W.fmt +"ceil.w.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_ceil_fmt (SD_, fmt_word, FMT_MICROMIPS, FT, FS, instruction_0); +} + + +010101,5.FT,5.FS,0,2.FMT_MICROMIPS_CVT_D!3,1001101,111011:POOL32F:32,f::CVT.D.fmt +"cvt.d.%s<FMT_MICROMIPS_CVT_D> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_cvt_d_fmt (SD_, convert_fmt_micromips_cvt_d (SD_, FMT_MICROMIPS_CVT_D), + FT, FS, instruction_0); +} + + +010101,5.FT,5.FS,0,1.FMT_MICROMIPS,00000100,111011:POOL32F:32,f::CVT.L.fmt +"cvt.l.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_cvt_l_fmt (SD_, FMT_MICROMIPS, FT, FS, instruction_0); +} + + +010101,5.FT,5.FS,5.FD,00110,000000:POOL32F:32,f::CVT.PS.S +"cvt.ps.s f<FD>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_cvt_ps_s (SD_, FD, FS, FT, instruction_0); +} + + +010101,5.FT,5.FS,0,2.FMT_MICROMIPS_CVT_S!3,1101101,111011:POOL32F:32,f::CVT.S.fmt +"cvt.s.%s<FMT_MICROMIPS_CVT_S> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_cvt_s_fmt (SD_, convert_fmt_micromips_cvt_s (SD_, FMT_MICROMIPS_CVT_S), + FT, FS, instruction_0); +} + + +010101,5.FT,5.FS,00,10000100,111011:POOL32F:32,f::CVT.S.PL +"cvt.s.pl f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_cvt_s_pl (SD_, FT, FS, instruction_0); +} + + +010101,5.FT,5.FS,00,10100100,111011:POOL32F:32,f::CVT.S.PU +"cvt.s.pu f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_cvt_s_pu (SD_, FT, FS, instruction_0); +} + + +010101,5.FT,5.FS,0,1.FMT_MICROMIPS,00100100,111011:POOL32F:32,f::CVT.W.fmt +"cvt.w.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_cvt_w_fmt (SD_, FMT_MICROMIPS, FT, FS, instruction_0); +} + + +010101,5.FT,5.FS,5.FD,0,2.FMT_MICROMIPS!2!3,11,110000:POOL32F:32,f::DIV.fmt +"div.%s<FMT_MICROMIPS> f<FD>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_div_fmt (SD_, FMT_MICROMIPS, FD, FS, FT, instruction_0); +} + + +010101,5.FT,5.FS,0,1.FMT_MICROMIPS,00001100,111011:POOL32F:32,f::FLOOR.L.fmt +"floor.l.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_floor_fmt (SD_, fmt_long, FMT_MICROMIPS, FT, FS); +} + + +010101,5.FT,5.FS,0,1.FMT_MICROMIPS,00101100,111011:POOL32F:32,f::FLOOR.W.fmt +"floor.w.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_floor_fmt (SD_, fmt_word, FMT_MICROMIPS, FT, FS); +} + + +010101,5.FT,5.FS,5.FD,5.FR,0,2.FMT_MICROMIPS!3,001:POOL32F:32,f::MADD.fmt +"madd.%s<FMT_MICROMIPS> f<FD>, f<FR>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_madd_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FD, FR, FS, + FT, instruction_0); +} + +010101,5.FT,5.FS,0,2.FMT_MICROMIPS!3,0000001,111011:POOL32F:32,f::MOV.fmt +"mov.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_mov_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FT, FS, + instruction_0); +} + + +010101,5.FT,5.FS,3.CC,00,2.FMT_MICROMIPS!3,00,1.TF,100000:POOL32F:32,f::MOVtf.fmt +"mov%s<TF>.%s<FMT_MICROMIPS> f<FT>, f<FS>, <CC>" +*micromips32: +*micromips64: +{ + do_movtf_fmt (SD_, TF, convert_fmt_micromips (SD_, FMT_MICROMIPS), FT, + FS, CC); +} + + +010101,5.FT,5.FS,5.FD,0,2.FMT_MICROMIPS!3,00,111000:POOL32F:32,f::MOVN.fmt +"movn.%s<FMT_MICROMIPS> f<FD>, f<FS>, r<FT>" +*micromips32: +*micromips64: +{ + do_movn_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FD, FS, FT); +} + +010101,5.FT,5.FS,5.FD,0,2.FMT_MICROMIPS!3,01,111000:POOL32F:32,f::MOVZ.fmt +"movz.%s<FMT_MICROMIPS> f<FD>, f<FS>, r<FT>" +*micromips32: +*micromips64: +{ + do_movz_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FD, FS, FT); +} + + +010101,5.FT,5.FS,5.FD,5.FR,1,2.FMT_MICROMIPS!3,001:POOL32F:32,f::MSUB.fmt +"msub.%s<FMT_MICROMIPS> f<FD>, f<FR>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_msub_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FD, FR, FS, + FT, instruction_0); +} + +010101,5.FT,5.FS,5.FD,0,2.FMT_MICROMIPS!3,10,110000:POOL32F:32,f::MUL.fmt +"mul.%s<FMT_MICROMIPS> f<FD>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_mul_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FD, FS, FT, + instruction_0); +} + + +010101,5.FT,5.FS,0,2.FMT_MICROMIPS!3,0101101,111011:POOL32F:32,f::NEG.fmt +"neg.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_neg_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FT, FS, + instruction_0); +} + + +010101,5.FT,5.FS,5.FD,5.FR,0,2.FMT_MICROMIPS!3,010:POOL32F:32,f::NMADD.fmt +"nmadd.%s<FMT_MICROMIPS> f<FD>, f<FR>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_nmadd_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FD, FR, FS, + FT, instruction_0); +} + +010101,5.FT,5.FS,5.FD,5.FR,1,2.FMT_MICROMIPS!3,010:POOL32F:32,f::NMSUB.fmt +"nmsub.%s<FMT_MICROMIPS> f<FD>, f<FR>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_nmsub_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FD, FR, FS, + FT, instruction_0); +} + + +010101,5.FT,5.FS,5.FD,00010,000000:POOL32F:32,f::PLL.PS +"pll.ps f<FD>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_pll_ps (SD_, FD, FS, FT, instruction_0); +} + + +010101,5.FT,5.FS,5.FD,00011,000000:POOL32F:32,f::PLU.PS +"plu.ps f<FD>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_plu_ps (SD_, FD, FS, FT, instruction_0); +} + + +010101,5.FT,5.FS,5.FD,00100,000000:POOL32F:32,f::PUL.PS +"pul.ps f<FD>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_pul_ps (SD_, FD, FS, FT, instruction_0); +} + + +010101,5.FT,5.FS,5.FD,00101,000000:POOL32F:32,f::PUU.PS +"puu.ps f<FD>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_puu_ps (SD_, FD, FS, FT, instruction_0); +} + + +010101,5.FT,5.FS,0,1.FMT_MICROMIPS,01001000,111011:POOL32F:32,f::RECIP.fmt +"recip.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_recip_fmt (SD_, FMT_MICROMIPS, FT, FS); +} + + +010101,5.FT,5.FS,0,1.FMT_MICROMIPS,11001100,111011:POOL32F:32,f::ROUND.L.fmt +"round.l.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_round_fmt (SD_, fmt_long, FMT_MICROMIPS, FT, FS); +} + + +010101,5.FT,5.FS,0,1.FMT_MICROMIPS,11101100,111011:POOL32F:32,f::ROUND.W.fmt +"round.w.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_round_fmt (SD_, fmt_word, FMT_MICROMIPS, FT, FS); +} + + +010101,5.FT,5.FS,0,1.FMT_MICROMIPS,00001000,111011:POOL32F:32,f::RSQRT.fmt +"rsqrt.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_rsqrt_fmt (SD_, FMT_MICROMIPS, FT, FS); +} + + +010101,5.FT,5.FS,0,1.FMT_MICROMIPS,00101000,111011:POOL32F:32,f::SQRT.fmt +"sqrt.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_sqrt_fmt (SD_, FMT_MICROMIPS, FT, FS); +} + + +010101,5.FT,5.FS,5.FD,0,2.FMT_MICROMIPS!3,01,110000:POOL32F:32,f::SUB.fmt +"sub.%s<FMT_MICROMIPS> f<FD>, f<FS>, f<FT>" +*micromips32: +*micromips64: +{ + do_sub_fmt (SD_, convert_fmt_micromips (SD_, FMT_MICROMIPS), FD, FS, FT, + instruction_0); +} + + +010101,5.FT,5.FS,0,1.FMT_MICROMIPS,10001100,111011:POOL32F:32,f::TRUNC.L.fmt +"trunc.l.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_trunc_fmt (SD_, fmt_long, FMT_MICROMIPS, FT, FS); +} + + +010101,5.FT,5.FS,0,1.FMT_MICROMIPS,10101100,111011:POOL32F:32,f::TRUNC.W.fmt +"trunc.w.%s<FMT_MICROMIPS> f<FT>, f<FS>" +*micromips32: +*micromips64: +{ + do_trunc_fmt (SD_, fmt_word, FMT_MICROMIPS, FT, FS); +} + +001000,5.LWM32REGS,5.BASE,0111,12.OFFSET:POOL32B:64::LDM +"ldm %s<LWM32REGS>, <OFFSET>(r<BASE>)" +*micromips64: +{ + int address_base = GPR[BASE] + EXTEND12 (OFFSET); + int reg_offset; + for (reg_offset = 0; reg_offset < (LWM32REGS & 0xf); reg_offset++) + { + int dst = (reg_offset == 8) ? 30 : 16 + reg_offset; + GPR[dst] = EXTEND64 (do_load (SD_, AccessLength_DOUBLEWORD, address_base, + 8 * reg_offset)); + } + + if (LWM32REGS & 0x10) + RA = EXTEND64 (do_load (SD_, AccessLength_DOUBLEWORD, address_base, + 8 * reg_offset)); +} + +001000,5.RD,5.BASE,0100,12.OFFSET:POOL32B:64::LDP +"ldp r<RD>, <OFFSET>(r<BASE>)" +*micromips64: +{ + if (BASE == RD || RD == 31) + Unpredictable (); + else + { + check_u64 (SD_, instruction_0); + GPR[RD] = EXTEND64 (do_load (SD_, AccessLength_DOUBLEWORD, GPR[BASE], + EXTEND12 (OFFSET))); + GPR[RD + 1] = EXTEND64 (do_load (SD_, AccessLength_DOUBLEWORD, GPR[BASE], + EXTEND12 (OFFSET) + 8)); + } +} + +001000,5.LWM32REGS,5.BASE,1111,12.OFFSET:POOL32B:64::SDM +"sdm %s<LWM32REGS>, <OFFSET>(r<BASE>)" +*micromips64: +{ + int address_base = GPR[BASE] + EXTEND12 (OFFSET); + int reg_offset; + for (reg_offset = 0; reg_offset < (LWM32REGS & 0xf); reg_offset++) + { + int src = (reg_offset == 8) ? 30 : 16 + reg_offset; + do_store (SD_, AccessLength_DOUBLEWORD, address_base, 8 * reg_offset, + GPR[src]); + } + + if (LWM32REGS & 0x10) + do_store (SD_, AccessLength_DOUBLEWORD, address_base, 8 * reg_offset, RA); +} + +001000,5.RD,5.BASE,1100,12.OFFSET:POOL32B:64::SDP +"sdp r<RD>, <OFFSET>(r<BASE>)" +*micromips64: +{ + if (RD == 31) + Unpredictable (); + else + { + check_u64 (SD_, instruction_0); + do_store (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND12 (OFFSET), + GPR[RD]); + do_store (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND12 (OFFSET) + 8, + GPR[RD + 1]); + } +} + +010110,5.RT,5.RS,5.RD,00,100010000:POOL32S:64::DADD +"dadd r<RD>, r<RS>, r<RT>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dadd (SD_, RD, RS, RT); +} + +010110,5.RT,5.RS,10.IMMEDIATE,011100:POOL32S:64::DADDI +"daddi r<RT>, r<RS>, <IMMEDIATE>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_daddi (SD_, RT, RS, IMMEDIATE); +} + +010111,5.RT,5.RS,16.IMMEDIATE:MICROMIPS:64::DADDIU +"daddiu r<RT>, r<RS>, <IMMEDIATE>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_daddiu (SD_, RS, RT, IMMEDIATE); +} + +010110,5.RT,5.RS,5.RD,00,101010000:POOL32S:64::DADDU +"daddu r<RD>, r<RS>, r<RT>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_daddu (SD_, RS, RT, RD); +} + +010110,5.RT,5.RS,0100101100,111100:POOL32S:64::DCLO +"dclo r<RT>, r<RS>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dclo (SD_, RT, RS); +} + +010110,5.RT,5.RS,0101101100,111100:POOL32S:64::DCLZ +"dclz r<RT>, r<RS>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dclz (SD_, RT, RS); +} + +010110,5.RT,5.RS,1010101100,111100:POOL32S:64::DDIV +"ddiv r<RS>, r<RT>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_ddiv (SD_, RS, RT); +} + +010110,5.RT,5.RS,1011101100,111100:POOL32S:64::DDIVU +"ddivu r<RS>, r<RT>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_ddivu (SD_, RS, RT); +} + +010110,5.RT,5.RS,5.SIZE,5.LSB,101100:POOL32S:64::DEXT +"dext r<RT>, r<RS>, <LSB>, <SIZE+1>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dext (SD_, RT, RS, LSB, SIZE); +} + +010110,5.RT,5.RS,5.SIZE,5.LSB,100100:POOL32S:64::DEXTM +"dextm r<RT>, r<RS>, <LSB>, <SIZE+33>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dextm (SD_, RT, RS, LSB, SIZE); +} + +010110,5.RT,5.RS,5.SIZE,5.LSB,010100:POOL32S:64::DEXTU +"dextu r<RT>, r<RS>, <LSB+32>, <SIZE+1>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dextu (SD_, RT, RS, LSB, SIZE); +} + +010110,5.RT,5.RS,5.MSB,5.LSB,001100:POOL32S:64::DINS +"dins r<RT>, r<RS>, <LSB>, <MSB-LSB+1>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dins (SD_, RT, RS, LSB, MSB); +} + +010110,5.RT,5.RS,5.MSB,5.LSB,000100:POOL32S:64::DINSM +"dinsm r<RT>, r<RS>, <LSB>, <MSB+32-LSB+1>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dinsm (SD_, RT, RS, LSB, MSB); +} + +010110,5.RT,5.RS,5.MSB,5.LSB,110100:POOL32S:64::DINSU +"dinsu r<RT>, r<RS>, <LSB+32>, <MSB-LSB+1>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dinsu (SD_, RT, RS, LSB, MSB); +} + +010110,5.RT,5.RS,00,3.SEL,00011,111100:POOL32S:64::DMFC0 +"dmfc0 r<RT>, r<RS>": SEL == 0 +"dmfc0 r<RT>, r<RS>, <SEL>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + DecodeCoproc (instruction_0, 0, cp0_dmfc0, RT, RS, SEL); +} + +010101,5.RT,5.FS,00,10010000,111011:POOL32F:64::DMFC1 +"dmfc1 r<RT>, f<FS>" +*micromips64: +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + do_dmfc1b (SD_, RT, FS); +} + +010110,5.RT,5.RS,00,3.SEL,01011,111100:POOL32S:64::DMTC0 +"dmtc0 r<RT>, r<RS>": SEL == 0 +"dmtc0 r<RT>, r<RS>, <SEL>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + DecodeCoproc (instruction_0, 0, cp0_dmtc0, RT, RS, SEL); +} + +010101,5.RT,5.FS,00,10110000,111011:POOL32F:64::DMTC1 +"dmtc1 r<RT>, f<FS>" +*micromips64: +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + do_dmtc1b (SD_, RT, FS); +} + +010110,5.RT,5.RS,1000101100,111100:POOL32S:64::DMULT +"dmult r<RS>, r<RT>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dmult (SD_, RS, RT, 0); +} + +010110,5.RT,5.RS,1001101100,111100:POOL32S:64::DMULTU +"dmultu r<RS>, r<RT>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dmultu (SD_, RS, RT, 0); +} + +010110,5.RT,5.RS,5.SA,00,011000000:POOL32S:64::DROTR +"drotr r<RT>, r<RS>, <SA>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + GPR[RT] = do_dror (SD_, GPR[RS], SA); +} + +010110,5.RT,5.RS,5.SA,00,011001000:POOL32S:64::DROTR32 +"drotr32 r<RT>, r<RS>, <SA+32>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + GPR[RT] = do_dror (SD_, GPR[RS], SA + 32); +} + +010110,5.RT,5.RS,5.RD,00,011010000:POOL32S:64::DROTRV +"drotrv r<RD>, r<RT>, r<RS>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + GPR[RD] = do_dror (SD_, GPR[RT], GPR[RS]); +} + +010110,5.RT,5.RS,0111101100,111100:POOL32S:64::DSBH +"dsbh r<RT>, r<RS>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dsbh (SD_, RT, RS); +} + +010110,5.RT,5.RS,1111101100,111100:POOL32S:64::DSHD +"dshd r<RT>, r<RS>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dshd (SD_, RS, RT); +} + +010110,5.RT,5.RS,5.SA,00,000000000:POOL32S:64::DSLL +"dsll r<RT>, r<RS>, <SA>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dsll (SD_, RS, RT, SA); +} + +010110,5.RT,5.RS,5.SA,00,000001000:POOL32S:64::DSLL32 +"dsll32 r<RT>, r<RS>, <SA>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dsll32 (SD_, RT, RS, SA); +} + +010110,5.RT,5.RS,5.RD,00,000010000:POOL32S:64::DSLLV +"dsllv r<RD>, r<RT>, r<RS>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dsllv (SD_, RS, RT, RD); +} + +010110,5.RT,5.RS,5.SA,00,010000000:POOL32S:64::DSRA +"dsra r<RT>, r<RS>, <SA>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dsra (SD_, RS, RT, SA); +} + +010110,5.RT,5.RS,5.SA,00,010001000:POOL32S:64::DSRA32 +"dsra32 r<RT>, r<RS>, <SA>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dsra32 (SD_, RT, RS, SA); +} + +010110,5.RT,5.RS,5.RD,00,010010000:POOL32S:64::DSRAV +"dsrav r<RD>, r<RS>, r<RT>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dsrav (SD_, RS, RT, RD); +} + +010110,5.RT,5.RS,5.SA,00,001000000:POOL32S:64::DSRL +"dsrl r<RT>, r<RS>, <SA>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dsrl (SD_, RS, RT, SA); +} + +010110,5.RT,5.RS,5.SA,00,001001000:POOL32S:64::DSRL32 +"dsrl32 r<RT>, r<RS>, <SA>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dsrl32 (SD_, RT, RS, SA); +} + +010110,5.RT,5.RS,5.RD,00,001010000:POOL32S:64::DSRLV +"dsrlv r<RD>, r<RT>, r<RS>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dsrlv (SD_, RS, RT, RD); +} + +010110,5.RT,5.RS,5.RD,00,110001000:POOL32S:64::DSUB +"dsub r<RD>, r<RS>, r<RT>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dsub (SD_, RD, RS, RT); +} + +010110,5.RT,5.RS,5.RD,00,111001000:POOL32S:64::DSUBU +"dsubu r<RD>, r<RS>, r<RT>" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_dsubu (SD_, RS, RT, RD); +} + +110111,5.RT,5.BASE,16.OFFSET:MICROMIPS64:64::LD +"ld r<RT>, <OFFSET>(r<BASE>)" +*micromips64: +{ + check_u64 (SD_, instruction_0); + GPR[RT] = EXTEND64 (do_load (SD_, AccessLength_DOUBLEWORD, GPR[BASE], + EXTEND16 (OFFSET))); +} + +011000,5.RT,5.BASE,0100,12.OFFSET:POOL32C:64::LDL +"ldl r<RT>, <OFFSET>(r<BASE>)" +*micromips64: +{ + check_u64 (SD_, instruction_0); + GPR[RT] = do_load_left (SD_, AccessLength_DOUBLEWORD, GPR[BASE], + EXTEND12 (OFFSET), GPR[RT]); +} + +011000,5.RT,5.BASE,0101,12.OFFSET:POOL32C:64::LDR +"ldr r<RT>, <OFFSET>(r<BASE>)" +*micromips64: +{ + check_u64 (SD_, instruction_0); + GPR[RT] = do_load_right (SD_, AccessLength_DOUBLEWORD, GPR[BASE], + EXTEND12 (OFFSET), GPR[RT]); +} + +010101,5.INDEX,5.BASE,5.FD,00,011001000:POOL32F:64,f::LDXC1 +"ldxc1 f<FD>, r<INDEX>(r<BASE>)" +*micromips64: +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + COP_LD (1, FD, do_load (SD_, AccessLength_DOUBLEWORD, GPR[BASE], GPR[INDEX])); +} + +011000,5.RT,5.BASE,0111,12.OFFSET:POOL32C:64::LLD +"lld r<RT>, <OFFSET>(r<BASE>)" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_lld (SD_, RT, OFFSET, BASE); +} + +011000,5.RT,5.BASE,1111,12.OFFSET:POOL32C:64::SCD +"scd r<RT>, <OFFSET>(r<BASE>)" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_scd (SD_, RT, OFFSET, BASE); +} + +110110,5.RT,5.BASE,16.OFFSET:MICROMIPS64:64::SD +"sd r<RT>, <OFFSET>(r<BASE>)" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_store (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET), + GPR[RT]); +} + +011000,5.RT,5.BASE,1100,12.OFFSET:POOL32C:64::SDL +"sdl r<RT>, <OFFSET>(r<BASE>)" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_store_left (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND12 (OFFSET), + GPR[RT]); +} + +011000,5.RT,5.BASE,1101,12.OFFSET:POOL32C:64::SDR +"sdr r<RT>, <OFFSET>(r<BASE>)" +*micromips64: +{ + check_u64 (SD_, instruction_0); + do_store_right (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND12 (OFFSET), + GPR[RT]); +} + +010101,5.INDEX,5.BASE,5.FD,00,100001000:POOL32F:64,f::SDXC1 +"sdxc1 f<FD>, r<INDEX>(r<BASE>)" +*micromips64: +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + do_store (SD_, AccessLength_DOUBLEWORD, GPR[BASE], GPR[INDEX], + COP_SD (1, FD)); +} diff --git a/sim/mips/micromips16.dc b/sim/mips/micromips16.dc new file mode 100644 index 0000000..a1cd9a0 --- /dev/null +++ b/sim/mips/micromips16.dc @@ -0,0 +1,11 @@ +# most instructions +# ------ options ------ : Fst : Lst : ff : fl : fe : word : fmt : model ... +# { : mask : value : word } + +# Top level - create a very big switch statement. + + padded-switch,combine : 15 : 10 : : : : : : + + switch,combine : 9 : 6 : : : : : : + switch,combine : 9 : 5 : : : : : : + switch,combine : 0 : 0 : : : : : : diff --git a/sim/mips/micromipsdsp.igen b/sim/mips/micromipsdsp.igen new file mode 100644 index 0000000..daa9f83 --- /dev/null +++ b/sim/mips/micromipsdsp.igen @@ -0,0 +1,1137 @@ +// Simulator definition for the micromips DSP ASE. +// Copyright (C) 2005-2015 Free Software Foundation, Inc. +// Contributed by Imagination Technologies, Ltd. +// Written by Andrew Bennett <andrew.bennett@imgtec.com> +// +// This file is part of the MIPS sim. +// +// 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 3 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/>. + +000000,5.RT,5.RS,0001000100,111100:POOL32A:32::ABSQ_S.PH +"absq_s.ph r<RT>, r<RS>" +*micromipsdsp: +{ + do_ph_s_absq (SD_, RT, RS); +} + +000000,5.RT,5.RS,0000000100,111100:POOL32A:32::ABSQ_S.QB +"absq_s.qb r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_s_absq (SD_, RT, RS); +} + +000000,5.RT,5.RS,0010000100,111100:POOL32A:32::ABSQ_S.W +"absq_s.w r<RT>, r<RS>" +*micromipsdsp: +{ + do_w_s_absq (SD_, RT, RS); +} + +000000,5.RT,5.RS,5.RD,00000,001101:POOL32A:32::ADDQ.PH +"addq.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_op (SD_, RD, RS, RT, 0, 0); +} + +000000,5.RT,5.RS,5.RD,10000,001101:POOL32A:32::ADDQ_S.PH +"addq_s.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_op (SD_, RD, RS, RT, 0, 1); +} + +000000,5.RT,5.RS,5.RD,01100,000101:POOL32A:32::ADDQ_S.W +"addq_s.w r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_w_op (SD_, RD, RS, RT, 0); +} + +000000,5.RT,5.RS,5.RD,00001,001101:POOL32A:32::ADDQH.PH +"addqh.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qh_ph_op (SD_, RD, RS, RT, 0, 0); +} + +000000,5.RT,5.RS,5.RD,10001,001101:POOL32A:32::ADDQH_R.PH +"addqh_r.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qh_ph_op (SD_, RD, RS, RT, 0, 1); +} + +000000,5.RT,5.RS,5.RD,00010,001101:POOL32A:32::ADDQH.W +"addqh.w r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qh_w_op (SD_, RD, RS, RT, 0, 0); +} + +000000,5.RT,5.RS,5.RD,10010,001101:POOL32A:32::ADDQH_R.W +"addqh_r.w r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qh_w_op (SD_, RD, RS, RT, 0, 1); +} + +000000,5.RT,5.RS,5.RD,01110,000101:POOL32A:32::ADDSC +"addsc r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_addsc (SD_, RD, RS, RT); +} + +000000,5.RT,5.RS,5.RD,00100,001101:POOL32A:32::ADDU.PH +"addu.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_u_ph_op (SD_, RD, RS, RT, 0, 0); +} + +000000,5.RT,5.RS,5.RD,10100,001101:POOL32A:32::ADDU_S.PH +"addu_s.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_u_ph_op (SD_, RD, RS, RT, 0, 1); +} + +000000,5.RT,5.RS,5.RD,00011,001101:POOL32A:32::ADDU.QB +"addu.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_op (SD_, RD, RS, RT, 0, 0); +} + +000000,5.RT,5.RS,5.RD,10011,001101:POOL32A:32::ADDU_S.QB +"addu_s.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_op (SD_, RD, RS, RT, 0, 1); +} + +000000,5.RT,5.RS,5.RD,01111,000101:POOL32A:32::ADDWC +"addwc r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_addwc (SD_, RD, RS, RT); +} + +000000,5.RT,5.RS,5.RD,00101,001101:POOL32A:32::ADDUH.QB +"adduh.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_uh_qb_op (SD_, RD, RS, RT, 0, 0); +} + +000000,5.RT,5.RS,5.RD,10101,001101:POOL32A:32::ADDUH_R.QB +"adduh_r.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_uh_qb_op (SD_, RD, RS, RT, 0, 1); +} + +000000,5.RT,5.RS,5.SA,01000,010101:POOL32A:32::APPEND +"append r<RT>, r<RS>, <SA>" +*micromipsdsp: +{ + do_append (SD_, RT, RS, SA); +} + +000000,5.RT,5.RS,2.BP,00100010,111100:POOL32A:32::BALIGN +"balign r<RT>, r<RS>, <BP>" +*micromipsdsp: +{ + do_balign (SD_, RT, RS, BP); +} + +000000,5.RT,5.RS,0011000100,111100:POOL32A:32::BITREV +"bitrev r<RT>, r<RS>" +*micromipsdsp: +{ + do_bitrev (SD_, RT, RS); +} + +010000,1101100000,16.IMMEDIATE:POOL32I:32::BPOSGE32 +"bposge32 <IMMEDIATE>" +*micromipsdsp: +{ + unsigned32 pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK; + if (pos >= 32) + NIA = delayslot_micromips (SD_, NIA + (EXTEND12 (IMMEDIATE) << 1), NIA, + MICROMIPS_DELAYSLOT_SIZE_ANY); +} + +000000,5.RT,5.RS,0000000000,000101:POOL32A:32::CMP.EQ.PH +"cmp.eq.ph r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_cmpu (SD_, RS, RT, 0); +} + +000000,5.RT,5.RS,0000000001,000101:POOL32A:32::CMP.LT.PH +"cmp.lt.ph r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_cmpu (SD_, RS, RT, 1); +} + +000000,5.RT,5.RS,0000000010,000101:POOL32A:32::CMP.LE.PH +"cmp.le.ph r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_cmpu (SD_, RS, RT, 2); +} + +000000,5.RT,5.RS,5.RD,00110,000101:POOL32A:32::CMPGDU.EQ.QB +"cmpgdu.eq.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_cmpgdu (SD_, RD, RS, RT, 0); +} + +000000,5.RT,5.RS,5.RD,00111,000101:POOL32A:32::CMPGDU.LT.QB +"cmpgdu.lt.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_cmpgdu (SD_, RD, RS, RT, 1); +} + +000000,5.RT,5.RS,5.RD,01000,000101:POOL32A:32::CMPGDU.LE.QB +"cmpgdu.le.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_cmpgdu (SD_, RD, RS, RT, 2); +} + +000000,5.RT,5.RS,5.RD,00011,000101:POOL32A:32::CMPGU.EQ.QB +"cmpgu.eq.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_cmpgu (SD_, RD, RS, RT, 0); +} + +000000,5.RT,5.RS,5.RD,00100,000101:POOL32A:32::CMPGU.LT.QB +"cmpgu.lt.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_cmpgu (SD_, RD, RS, RT, 1); +} + +000000,5.RT,5.RS,5.RD,00101,000101:POOL32A:32::CMPGU.LE.QB +"cmpgu.le.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_cmpgu (SD_, RD, RS, RT, 2); +} + +000000,5.RT,5.RS,0000001001,000101:POOL32A:32::CMPU.EQ.QB +"cmpu.eq.qb r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_cmpu (SD_, RS, RT, 0); +} + +000000,5.RT,5.RS,0000001010,000101:POOL32A:32::CMPU.LT.QB +"cmpu.lt.qb r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_cmpu (SD_, RS, RT, 1); +} + +000000,5.RT,5.RS,0000001011,000101:POOL32A:32::CMPU.LE.QB +"cmpu.le.qb r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_cmpu (SD_, RS, RT, 2); +} + +000000,5.RT,5.RS,2.AC,00000010,111100:POOL32A:32::DPA.W.PH +"dpa.w.ph ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_w_ph_dot_product (SD_, AC, RS, RT, 0); +} + +000000,5.RT,5.RS,2.AC,00001010,111100:POOL32A:32::DPAQ_S.W.PH +"dpaq_s.w.ph ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_dot_product (SD_, AC, RS, RT, 0); +} + +000000,5.RT,5.RS,2.AC,01001010,111100:POOL32A:32::DPAQ_SA.L.W +"dpaq_sa.l.w ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_w_dot_product (SD_, AC, RS, RT, 0); +} + +000000,5.RT,5.RS,2.AC,10001010,111100:POOL32A:32::DPAQX_S.W.PH +"dpaqx_s.w.ph ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qx_w_ph_dot_product (SD_, AC, RS, RT, 0, 0); +} + +000000,5.RT,5.RS,2.AC,11001010,111100:POOL32A:32::DPAQX_SA.W.PH +"dpaqx_sa.w.ph ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qx_w_ph_dot_product (SD_, AC, RS, RT, 0, 1); +} + +000000,5.RT,5.RS,2.AC,10000010,111100:POOL32A:32::DPAU.H.QBL +"dpau.h.qbl ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_dot_product (SD_, AC, RS, RT, 0, 0); +} + +000000,5.RT,5.RS,2.AC,11000010,111100:POOL32A:32::DPAU.H.QBR +"dpau.h.qbr ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_dot_product (SD_, AC, RS, RT, 0, 1); +} + +000000,5.RT,5.RS,2.AC,01000010,111100:POOL32A:32::DPAX.W.PH +"dpax.w.ph ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_x_w_ph_dot_product (SD_, AC, RS, RT, 0); +} + +000000,5.RT,5.RS,2.AC,00010010,111100:POOL32A:32::DPS.W.PH +"dps.w.ph ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_w_ph_dot_product (SD_, AC, RS, RT, 1); +} + +000000,5.RT,5.RS,2.AC,00011010,111100:POOL32A:32::DPSQ_S.W.PH +"dpsq_s.w.ph ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_dot_product (SD_, AC, RS, RT, 1); +} + +000000,5.RT,5.RS,2.AC,01011010,111100:POOL32A:32::DPSQ_SA.L.W +"dpsq_sa.l.w ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_w_dot_product (SD_, AC, RS, RT, 1); +} + +000000,5.RT,5.RS,2.AC,10011010,111100:POOL32A:32::DPSQX_S.W.PH +"dpsqx_s.w.ph ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qx_w_ph_dot_product (SD_, AC, RS, RT, 1, 0); +} + +000000,5.RT,5.RS,2.AC,11011010,111100:POOL32A:32::DPSQX_SA.W.PH +"dpsqx_sa.w.ph ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qx_w_ph_dot_product (SD_, AC, RS, RT, 1, 1); +} + +000000,5.RT,5.RS,2.AC,10010010,111100:POOL32A:32::DPSU.H.QBL +"dpsu.h.qbl ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_dot_product (SD_, AC, RS, RT, 1, 0); +} + +000000,5.RT,5.RS,2.AC,11010010,111100:POOL32A:32::DPSU.H.QBR +"dpsu.h.qbr ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_dot_product (SD_, AC, RS, RT, 1, 1); +} + +000000,5.RT,5.RS,2.AC,01010010,111100:POOL32A:32::DPSX.W.PH +"dpsx.w.ph ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_x_w_ph_dot_product (SD_, AC, RS, RT, 1); +} + +000000,5.RT,5.SIZE,2.AC,10011001,111100:POOL32A:32::EXTP +"extp r<RT>, ac<AC>, <SIZE>" +*micromipsdsp: +{ + do_extp (SD_, RT, AC, SIZE, 0); +} + +000000,5.RT,5.SIZE,2.AC,11011001,111100:POOL32A:32::EXTPDP +"extpdp r<RT>, ac<AC>, <SIZE>" +*micromipsdsp: +{ + do_extp (SD_, RT, AC, SIZE, 1); +} + +000000,5.RT,5.RS,2.AC,11100010,111100:POOL32A:32::EXTPDPV +"extpdpv r<RT>, ac<AC>, r<RS>" +*micromipsdsp: +{ + do_extpv (SD_, RT, AC, RS, 1); +} + +000000,5.RT,5.RS,2.AC,10100010,111100:POOL32A:32::EXTPV +"extpv r<RT>, ac<AC>, r<RS>" +*micromipsdsp: +{ + do_extpv (SD_, RT, AC, RS, 0); +} + +000000,5.RT,5.SHIFT,2.AC,00111001,111100:POOL32A:32::EXTR.W +"extr.w r<RT>, ac<AC>, <SHIFT>" +*micromipsdsp: +{ + do_w_extr (SD_, RT, AC, SHIFT, 0); +} + +000000,5.RT,5.SHIFT,2.AC,01111001,111100:POOL32A:32::EXTR_R.W +"extr_r.w r<RT>, ac<AC>, <SHIFT>" +*micromipsdsp: +{ + do_w_extr (SD_, RT, AC, SHIFT, 1); +} + +000000,5.RT,5.SHIFT,2.AC,10111001,111100:POOL32A:32::EXTR_RS.W +"extr_rs.w r<RT>, ac<AC>, <SHIFT>" +*micromipsdsp: +{ + do_w_extr (SD_, RT, AC, SHIFT, 2); +} + +000000,5.RT,5.SHIFT,2.AC,11111001,111100:POOL32A:32::EXTR_S.H +"extr_s.h r<RT>, ac<AC>, <SHIFT>" +*micromipsdsp: +{ + do_h_extr (SD_, RT, AC, SHIFT); +} + +000000,5.RT,5.RS,2.AC,00111010,111100:POOL32A:32::EXTRV.W +"extrv.w r<RT>, ac<AC>, r<RS>" +*micromipsdsp: +{ + do_extrv (SD_, RT, AC, RS, 0); +} + +000000,5.RT,5.RS,2.AC,01111010,111100:POOL32A:32::EXTRV_R.W +"extrv_r.w r<RT>, ac<AC>, r<RS>" +*micromipsdsp: +{ + do_extrv (SD_, RT, AC, RS, 1); +} + +000000,5.RT,5.RS,2.AC,10111010,111100:POOL32A:32::EXTRV_RS.W +"extrv_rs.w r<RT>, ac<AC>, r<RS>" +*micromipsdsp: +{ + do_extrv (SD_, RT, AC, RS, 2); +} + +000000,5.RT,5.RS,2.AC,11111010,111100:POOL32A:32::EXTRV_S.H +"extrv_s.h r<RT>, ac<AC>, r<RS>" +*micromipsdsp: +{ + do_extrv_s_h (SD_, RT, AC, RS); +} + +000000,5.RT,5.RS,0100000100,111100:POOL32A:32::INSV +"insv r<RT>, r<RS>" +*micromipsdsp: +{ + do_insv (SD_, RT, RS); +} + +000000,5.INDEX,5.BASE,5.RD,01000,100101:POOL32A:32::LBUX +"lbux r<RD>, r<INDEX>(r<BASE>)" +*micromipsdsp: +{ + do_lxx (SD_, RD, BASE, INDEX, 0); +} + +000000,5.INDEX,5.BASE,5.RD,00101,100101:POOL32A:32::LHX +"lhx r<RD>, r<INDEX>(r<BASE>)" +*micromipsdsp: +{ + do_lxx (SD_, RD, BASE, INDEX, 1); +} + +000000,5.INDEX,5.BASE,5.RD,00110,100101:POOL32A:32::LWX +"lwx r<RD>, r<INDEX>(r<BASE>)" +*micromipsdsp: +{ + do_lxx (SD_, RD, BASE, INDEX, 2); +} + +000000,5.RT,5.RS,2.AC,00101010,111100:POOL32A:32::MADD_DSP +"madd ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_dsp_madd (SD_, AC, RS, RT); +} + +000000,5.RT,5.RS,2.AC,01101010,111100:POOL32A:32::MADDU_DSP +"maddu ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_dsp_maddu (SD_, AC, RS, RT); +} + +000000,5.RT,5.RS,2.AC,01101001,111100:POOL32A:32::MAQ_S.W.PHL +"maq_s.w.phl ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_maq (SD_, AC, RS, RT, 0, 0); +} + +000000,5.RT,5.RS,2.AC,11101001,111100:POOL32A:32::MAQ_SA.W.PHL +"maq_sa.w.phl ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_maq (SD_, AC, RS, RT, 1, 0); +} + +000000,5.RT,5.RS,2.AC,00101001,111100:POOL32A:32::MAQ_S.W.PHR +"maq_s.w.phr ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_maq (SD_, AC, RS, RT, 0, 1); +} + +000000,5.RT,5.RS,2.AC,10101001,111100:POOL32A:32::MAQ_SA.W.PHR +"maq_sa.w.phr ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_maq (SD_, AC, RS, RT, 1, 1); +} + +000000,00000,5.RS,2.AC,00000001,111100:POOL32A:32::MFHI_DSP +"mfhi r<RS>, ac<AC>" +*micromipsdsp: +{ + do_dsp_mfhi (SD_, AC, RS); +} + +000000,00000,5.RS,2.AC,01000001,111100:POOL32A:32::MFLO_DSP +"mflo r<RS>, ac<AC>" +*micromipsdsp: +{ + do_dsp_mflo (SD_, AC, RS); +} + +000000,5.RT,5.RS,5.RD,01010,010101:POOL32A:32::MODSUB +"modsub r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_modsub (SD_, RD, RS, RT); +} + +000000,5.RT,5.RS,2.AC,10101010,111100:POOL32A:32::MSUB_DSP +"msub ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_dsp_msub (SD_, AC, RS, RT); +} + +000000,5.RT,5.RS,2.AC,11101010,111100:POOL32A:32::MSUBU_DSP +"msubu ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_dsp_msubu (SD_, AC, RS, RT); +} + +000000,00000,5.RS,2.AC,10000001,111100:POOL32A:32::MTHI_DSP +"mthi r<RS>, ac<AC>" +*micromipsdsp: +{ + do_dsp_mthi (SD_, AC, RS); +} + +000000,00000,5.RS,2.AC,00001001,111100:POOL32A:32::MTHLIP +"mthlip r<RS>, ac<AC>" +*micromipsdsp: +{ + do_mthlip (SD_, RS, AC); +} + +000000,00000,5.RS,2.AC,11000001,111100:POOL32A:32::MTLO_DSP +"mtlo r<RS>, ac<AC>" +*micromipsdsp: +{ + do_dsp_mtlo (SD_, AC, RS); +} + +000000,5.RT,5.RS,5.RD,00000,101101:POOL32A:32::MUL.PH +"mul.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_op (SD_, RD, RS, RT, 2, 0); +} + +000000,5.RT,5.RS,5.RD,10000,101101:POOL32A:32::MUL_S.PH +"mul_s.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_op (SD_, RD, RS, RT, 2, 1); +} + +000000,5.RT,5.RS,5.RD,00000,100101:POOL32A:32::MULEQ_S.W.PHL +"muleq_s.w.phl r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_muleq (SD_, RD, RS, RT, 0); +} + +000000,5.RT,5.RS,5.RD,00001,100101:POOL32A:32::MULEQ_S.W.PHR +"muleq_s.w.phr r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_muleq (SD_, RD, RS, RT, 1); +} + +000000,5.RT,5.RS,5.RD,00010,010101:POOL32A:32::MULEU_S.PH.QBL +"muleu_s.ph.qbl r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_muleu (SD_, RD, RS, RT, 0); +} + +000000,5.RT,5.RS,5.RD,00011,010101:POOL32A:32::MULEU_S.PH.QBR +"muleu_s.ph.qbr r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_muleu (SD_, RD, RS, RT, 1); +} + +000000,5.RT,5.RS,5.RD,00100,010101:POOL32A:32::MULQ_RS.PH +"mulq_rs.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_mulq (SD_, RD, RS, RT, 1); +} + +000000,5.RT,5.RS,5.RD,00110,010101:POOL32A:32::MULQ_RS.W +"mulq_rs.w r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_w_mulq (SD_, RD, RS, RT, 1); +} + +000000,5.RT,5.RS,5.RD,00101,010101:POOL32A:32::MULQ_S.PH +"mulq_s.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_mulq (SD_, RD, RS, RT, 0); +} + +000000,5.RT,5.RS,5.RD,00111,010101:POOL32A:32::MULQ_S.W +"mulq_s.w r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_w_mulq (SD_, RD, RS, RT, 0); +} + +000000,5.RT,5.RS,2.AC,10110010,111100:POOL32A:32::MULSA.W.PH +"mulsa.w.ph ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_w_mulsa (SD_, AC, RS, RT); +} + +000000,5.RT,5.RS,2.AC,11110010,111100:POOL32A:32::MULSAQ_S.W.PH +"mulsaq_s.w.ph ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_mulsaq_s_w_ph (SD_, AC, RS, RT); +} + +000000,5.RT,5.RS,2.AC,00110010,111100:POOL32A:32::MULT_DSP +"mult ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_dsp_mult (SD_, AC, RS, RT); +} + +000000,5.RT,5.RS,2.AC,01110010,111100:POOL32A:32::MULTU_DSP +"multu ac<AC>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_dsp_multu (SD_, AC, RS, RT); +} + +000000,5.RT,5.RS,5.RD,00110,101101:POOL32A:32::PACKRL.PH +"packrl.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_packrl (SD_, RD, RS, RT); +} + +000000,5.RT,5.RS,5.RD,01000,101101:POOL32A:32::PICK.PH +"pick.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_pick (SD_, RD, RS, RT); +} + +000000,5.RT,5.RS,5.RD,00111,101101:POOL32A:32::PICK.QB +"pick.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_pick (SD_, RD, RS, RT); +} + +000000,5.RT,5.RS,0101000100,111100:POOL32A:32::PRECEQ.W.PHL +"preceq.w.phl r<RT>, r<RS>" +*micromipsdsp: +{ + do_w_preceq (SD_, RT, RS, 0); +} + +000000,5.RT,5.RS,0110000100,111100:POOL32A:32::PRECEQ.W.PHR +"preceq.w.phr r<RT>, r<RS>" +*micromipsdsp: +{ + do_w_preceq (SD_, RT, RS, 1); +} + +000000,5.RT,5.RS,0111000100,111100:POOL32A:32::PRECEQU.PH.QBL +"precequ.ph.qbl r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_ph_precequ (SD_, RT, RS, 2); +} + +000000,5.RT,5.RS,0111001100,111100:POOL32A:32::PRECEQU.PH.QBLA +"precequ.ph.qbla r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_ph_precequ (SD_, RT, RS, 3); +} + +000000,5.RT,5.RS,1001000100,111100:POOL32A:32::PRECEQU.PH.QBR +"precequ.ph.qbr r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_ph_precequ (SD_, RT, RS, 0); +} + +000000,5.RT,5.RS,1001001100,111100:POOL32A:32::PRECEQU.PH.QBRA +"precequ.ph.qbra r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_ph_precequ (SD_, RT, RS, 1); +} + +000000,5.RT,5.RS,1011000100,111100:POOL32A:32::PRECEU.PH.QBL +"preceu.ph.qbl r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_ph_preceu (SD_, RT, RS, 2); +} + +000000,5.RT,5.RS,1011001100,111100:POOL32A:32::PRECEU.PH.QBLA +"preceu.ph.qbla r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_ph_preceu (SD_, RT, RS, 3); +} + +000000,5.RT,5.RS,1101000100,111100:POOL32A:32::PRECEU.PH.QBR +"preceu.ph.qbr r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_ph_preceu (SD_, RT, RS, 0); +} + +000000,5.RT,5.RS,1101001100,111100:POOL32A:32::PRECEU.PH.QBRA +"preceu.ph.qbra r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_ph_preceu (SD_, RT, RS, 1); +} + +000000,5.RT,5.RS,5.RD,00001,101101:POOL32A:32::PRECR.QB.PH +"precr.qb.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_qb_precr (SD_, RD, RS, RT); +} + +000000,5.RT,5.RS,5.SA,01111,001101:POOL32A:32::PRECR_SRA.PH.W +"precr_sra.ph.w r<RT>, r<RS>, <SA>" +*micromipsdsp: +{ + do_precr_sra (SD_, RT, RS, SA, 0); +} + +000000,5.RT,5.RS,5.SA,11111,001101:POOL32A:32::PRECR_SRA_R.PH.W +"precr_sra_r.ph.w r<RT>, r<RS>, <SA>" +*micromipsdsp: +{ + do_precr_sra (SD_, RT, RS, SA, 1); +} + +000000,5.RT,5.RS,5.RD,00011,101101:POOL32A:32::PRECRQ.PH.W +"precrq.ph.w r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_w_ph_precrq (SD_, RD, RS, RT); +} + +000000,5.RT,5.RS,5.RD,00010,101101:POOL32A:32::PRECRQ.QB.PH +"precrq.qb.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_qb_precrq (SD_, RD, RS, RT, 0); +} + +000000,5.RT,5.RS,5.RD,00101,101101:POOL32A:32::PRECRQU_S.QB.PH +"precrqu_s.qb.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_qb_precrq (SD_, RD, RS, RT, 1); +} + +000000,5.RT,5.RS,5.RD,00100,101101:POOL32A:32::PRECRQ_RS.PH.W +"precrq_rs.ph.w r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_w_ph_rs_precrq (SD_, RD, RS, RT); +} + +000000,5.RT,5.RS,5.SA,01001,010101:POOL32A:32::PREPEND +"prepend r<RT>, r<RS>, <SA>" +*micromipsdsp: +{ + do_prepend (SD_, RT, RS, SA); +} + +000000,5.RT,5.RS,1111000100,111100:POOL32A:32::RADDU.W.QB +"raddu.w.qb r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_w_raddu (SD_, RT, RS); +} + +000000,5.RT,7.CONTROL_MASK,00011001,111100:POOL32A:32::RDDSP +"rddsp r<RT>":CONTROL_MASK == 1111111111 +"rddsp r<RT>, <CONTROL_MASK>" +*micromipsdsp: +{ + do_rddsp (SD_, RT, CONTROL_MASK); +} + +000000,10.IMMEDIATE,5.RD,00000,111101:POOL32A:32::REPL.PH +"repl.ph r<RD>, <IMMEDIATE>" +*micromipsdsp: +{ + do_repl (SD_, RD, IMMEDIATE, 2); +} + +000000,5.RT,8.IMMEDIATE,0010111,111100:POOL32A:32::REPL.QB +"repl.qb r<RT>, <IMMEDIATE>" +*micromipsdsp: +{ + do_repl (SD_, RT, IMMEDIATE, 0); +} + +000000,5.RT,5.RS,0000001100,111100:POOL32A:32::REPLV.PH +"replv.ph r<RT>, r<RS>" +*micromipsdsp: +{ + do_repl (SD_, RT, RS, 3); +} + +000000,5.RT,5.RS,0001001100,111100:POOL32A:32::REPLV.QB +"replv.qb r<RT>, r<RS>" +*micromipsdsp: +{ + do_repl (SD_, RT, RS, 1); +} + +000000,0000,6.IMMEDIATE,2.AC,00000000,011101:POOL32A:32::SHILO +"shilo ac<AC>, <IMMEDIATE>" +*micromipsdsp: +{ + do_shilo (SD_, AC, IMMEDIATE); +} + +000000,00000,5.RS,2.AC,01001001,111100:POOL32A:32::SHILOV +"shilov ac<AC>, r<RS>" +*micromipsdsp: +{ + do_shilov (SD_, AC, RS); +} + +000000,5.RT,5.RS,4.SHIFT,001110,110101:POOL32A:32::SHLL.PH +"shll.ph r<RT>, r<RS>, <SHIFT>" +*micromipsdsp: +{ + do_ph_shift (SD_, RT, RS, SHIFT, 0, 0); +} + +000000,5.RT,5.RS,4.SHIFT,101110,110101:POOL32A:32::SHLL_S.PH +"shll_s.ph r<RT>, r<RS>, <SHIFT>" +*micromipsdsp: +{ + do_ph_shift (SD_, RT, RS, SHIFT, 0, 1); +} + +000000,5.RT,5.RS,3.SHIFT,0100001,111100:POOL32A:32::SHLL.QB +"shll.qb r<RT>, r<RS>, <SHIFT>" +*micromipsdsp: +{ + do_qb_shift (SD_, RT, RS, SHIFT, 0); +} + +000000,5.RT,5.RS,5.RD,01110,001101:POOL32A:32::SHLLV.PH +"shllv.ph r<RD>, r<RT>, r<RS>" +*micromipsdsp: +{ + do_ph_shl (SD_, RD, RT, RS, 0, 0); +} + +000000,5.RT,5.RS,5.RD,11110,001101:POOL32A:32::SHLLV_S.PH +"shllv_s.ph r<RD>, r<RD>, r<RS>" +*micromipsdsp: +{ + do_ph_shl (SD_, RD, RT, RS, 0, 1); +} + +000000,5.RT,5.RS,5.RD,01110,010101:POOL32A:32::SHLLV.QB +"shllv.qb r<RD>, r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_shl (SD_, RD, RT, RS, 0); +} + +000000,5.RT,5.RS,5.RD,01111,010101:POOL32A:32::SHLLV_S.W +"shllv_s.w r<RD>, r<RT>, r<RS>" +*micromipsdsp: +{ + do_w_s_shllv (SD_, RD, RT, RS); +} + +000000,5.RT,5.RS,5.SHIFT,01111,110101:POOL32A:32::SHLL_S.W +"shll_s.w r<RT>, r<RS>, <SHIFT>" +*micromipsdsp: +{ + do_w_shll (SD_, RT, RS, SHIFT); +} + +000000,5.RT,5.RS,3.SHIFT,0000111,111100:POOL32A:32::SHRA.QB +"shra.qb r<RT>, r<RS>, <SHIFT>" +*micromipsdsp: +{ + do_qb_shra (SD_, RT, RS, SHIFT, 0); +} + +000000,5.RT,5.RS,3.SHIFT,1000111,111100:POOL32A:32::SHRA_R.QB +"shra_r.qb r<RT>, r<RS>, <SHIFT>" +*micromipsdsp: +{ + do_qb_shra (SD_, RT, RS, SHIFT, 1); +} + +000000,5.RT,5.RS,4.SHIFT,001100,110101:POOL32A:32::SHRA.PH +"shra.ph r<RT>, r<RS>, <SHIFT>" +*micromipsdsp: +{ + do_ph_shift (SD_, RT, RS, SHIFT, 1, 0); +} + +000000,5.RT,5.RS,4.SHIFT,011100,110101:POOL32A:32::SHRA_R.PH +"shra_r.ph r<RT>, r<RS>, <SHIFT>" +*micromipsdsp: +{ + do_ph_shift (SD_, RT, RS, SHIFT, 1, 1); +} + +000000,5.RT,5.RS,5.RD,00110,001101:POOL32A:32::SHRAV.PH +"shrav.ph r<RD>, r<RT>, r<RS>" +*micromipsdsp: +{ + do_ph_shl (SD_, RD, RT, RS, 1, 0); +} + +000000,5.RT,5.RS,5.RD,10110,001101:POOL32A:32::SHRAV_R.PH +"shrav_r.ph r<RD>, r<RT>, r<RS>" +*micromipsdsp: +{ + do_ph_shl (SD_, RD, RT, RS, 1, 1); +} + +000000,5.RT,5.RS,5.RD,00111,001101:POOL32A:32::SHRAV.QB +"shrav.qb r<RD>, r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_shrav (SD_, RD, RT, RS, 0); +} + +000000,5.RT,5.RS,5.RD,10111,001101:POOL32A:32::SHRAV_R.QB +"shrav_r.qb r<RD>, r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_shrav (SD_, RD, RT, RS, 1); +} + +000000,5.RT,5.RS,5.RD,01011,010101:POOL32A:32::SHRAV_R.W +"shrav_r.w r<RD>, r<RT>, r<RS>" +*micromipsdsp: +{ + do_w_r_shrav (SD_, RD, RT, RS); +} + +000000,5.RT,5.RS,5.SHIFT,01011,110101:POOL32A:32::SHRA_R.W +"shra_r.w r<RT>, r<RS>, <SHIFT>" +*micromipsdsp: +{ + do_w_shra (SD_, RT, RS, SHIFT); +} + +000000,5.RT,5.RS,4.SHIFT,001111,111100:POOL32A:32::SHRL.PH +"shrl.ph r<RT>, r<RS>, <SHIFT>" +*micromipsdsp: +{ + do_ph_shrl (SD_, RT, RS, SHIFT); +} + +000000,5.RT,5.RS,3.SHIFT,1100001,111100:POOL32A:32::SHRL.QB +"shrl.qb r<RT>, r<RS>, <SHIFT>" +*micromipsdsp: +{ + do_qb_shift (SD_, RT, RS, SHIFT, 1); +} + +000000,5.RT,5.RS,5.RD,01100,010101:POOL32A:32::SHRLV.PH +"shrlv.ph r<RD>, r<RT>, r<RS>" +*micromipsdsp: +{ + do_ph_shrlv (SD_, RD, RT, RS); +} + +000000,5.RT,5.RS,5.RD,01101,010101:POOL32A:32::SHRLV.QB +"shrlv.qb r<RD>, r<RT>, r<RS>" +*micromipsdsp: +{ + do_qb_shl (SD_, RD, RT, RS, 1); +} + +000000,5.RT,5.RS,5.RD,01000,001101:POOL32A:32::SUBQ.PH +"subq.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_op (SD_, RD, RS, RT, 1, 0); +} + +000000,5.RT,5.RS,5.RD,11000,001101:POOL32A:32::SUBQ_S.PH +"subq_s.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_ph_op (SD_, RD, RS, RT, 1, 1); +} + +000000,5.RT,5.RS,5.RD,01101,000101:POOL32A:32::SUBQ_S.W +"subq_s.w r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_w_op (SD_, RD, RS, RT, 1); +} + +000000,5.RT,5.RS,5.RD,01001,001101:POOL32A:32::SUBQH.PH +"subqh.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qh_ph_op (SD_, RD, RS, RT, 1, 0); +} + +000000,5.RT,5.RS,5.RD,11001,001101:POOL32A:32::SUBQH_R.PH +"subqh_r.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qh_ph_op (SD_, RD, RS, RT, 1, 1); +} + +000000,5.RT,5.RS,5.RD,01010,001101:POOL32A:32::SUBQH.W +"subqh.w r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qh_w_op (SD_, RD, RS, RT, 1, 0); +} + +000000,5.RT,5.RS,5.RD,11010,001101:POOL32A:32::SUBQH_R.W +"subqh_r.w r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qh_w_op (SD_, RD, RS, RT, 1, 1); +} + +000000,5.RT,5.RS,5.RD,01100,001101:POOL32A:32::SUBU.PH +"subu.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_u_ph_op (SD_, RD, RS, RT, 1, 0); +} + +000000,5.RT,5.RS,5.RD,11100,001101:POOL32A:32::SUBU_S.PH +"subu_s.ph r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_u_ph_op (SD_, RD, RS, RT, 1, 1); +} + +000000,5.RT,5.RS,5.RD,01011,001101:POOL32A:32::SUBU.QB +"subu.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_op (SD_, RD, RS, RT, 1, 0); +} + +000000,5.RT,5.RS,5.RD,11011,001101:POOL32A:32::SUBU_S.QB +"subu_s.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_qb_op (SD_, RD, RS, RT, 1, 1); +} + +000000,5.RT,5.RS,5.RD,01101,001101:POOL32A:32::SUBUH.QB +"subuh.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_uh_qb_op (SD_, RD, RS, RT, 1, 0); +} + +000000,5.RT,5.RS,5.RD,11101,001101:POOL32A:32::SUBUH_R.QB +"subuh_r.qb r<RD>, r<RS>, r<RT>" +*micromipsdsp: +{ + do_uh_qb_op (SD_, RD, RS, RT, 1, 1); +} + +000000,5.RT,7.CONTROL_MASK,01011001,111100:POOL32A:32::WRDSP +"wrdsp r<RT>":CONTROL_MASK == 1111111111 +"wrdsp r<RT>, <CONTROL_MASK>" +*micromipsdsp: +{ + do_wrdsp (SD_, RT, CONTROL_MASK); +} diff --git a/sim/mips/micromipsrun.c b/sim/mips/micromipsrun.c new file mode 100644 index 0000000..c39138b --- /dev/null +++ b/sim/mips/micromipsrun.c @@ -0,0 +1,135 @@ +/* Run function for the micromips simulator + + Copyright (C) 2005-2015 Free Software Foundation, Inc. + Contributed by Imagination Technologies, Ltd. + Written by Andrew Bennett <andrew.bennett@imgtec.com>. + + This file is part of the MIPS sim. + + 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 3 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 "sim-main.h" +#include "micromips16_idecode.h" +#include "micromips32_idecode.h" +#include "micromips_m32_idecode.h" +#include "bfd.h" +#include "sim-engine.h" + +/* These definitions come from the *_support.h files generated by igen and are + required because they are used in some of the macros in the code below. + Unfortunately we can not just blindly include the *_support.h files to get + these definitions because some of the defines in these files are specific + for a particular configuration of the simulator for example instruction word + size is 16 bits for micromips16 and 32 bits for micromips32. This means we + could break future code changes by doing this, so a safer approach is to just + extract the defines that we need to get this file to compile. */ +#define SD sd +#define CPU cpu + +address_word +micromips_instruction_decode (SIM_DESC sd, sim_cpu * cpu, + address_word cia, + int instruction_size) +{ + if (instruction_size == MICROMIPS_DELAYSLOT_SIZE_ANY) + { + micromips16_instruction_word instruction_0 = IMEM16_MICROMIPS (cia); + if (MICROMIPS_MINOR_OPCODE (instruction_0) > 0 + && MICROMIPS_MINOR_OPCODE (instruction_0) < 4) + return micromips16_idecode_issue (sd, instruction_0, cia); + else + { + micromips32_instruction_word instruction_0 = IMEM32_MICROMIPS (cia); + return micromips32_idecode_issue (sd, instruction_0, cia); + } + } + else if (instruction_size == MICROMIPS_DELAYSLOT_SIZE_16) + { + micromips16_instruction_word instruction_0 = IMEM16_MICROMIPS (cia); + if (MICROMIPS_MINOR_OPCODE (instruction_0) > 0 + && MICROMIPS_MINOR_OPCODE (instruction_0) < 4) + return micromips16_idecode_issue (sd, instruction_0, cia); + else + sim_engine_abort (sd, cpu, cia, + "Invalid 16 bit micromips instruction"); + } + else if (instruction_size == MICROMIPS_DELAYSLOT_SIZE_32) + { + micromips32_instruction_word instruction_0 = IMEM32_MICROMIPS (cia); + return micromips32_idecode_issue (sd, instruction_0, cia); + } + else + return NULL_CIA; +} + +void +sim_engine_run (SIM_DESC sd, int next_cpu_nr, int nr_cpus, + int signal) +{ + micromips_m32_instruction_word instruction_0; + sim_cpu *cpu = STATE_CPU (sd, next_cpu_nr); + micromips32_instruction_address cia = CPU_PC_GET (cpu); + sd->isa_mode = ISA_MODE_MIPS32; + + while (1) + { + micromips32_instruction_address nia; + + /* Allow us to switch back from MIPS32 to microMIPS + This covers two cases: + 1. Setting the correct isa mode based on the start address + from the elf header. + 2. Setting the correct isa mode after a MIPS32 jump or branch + instruction. */ + if ((sd->isa_mode == ISA_MODE_MIPS32) + && ((cia & 0x1) == ISA_MODE_MICROMIPS)) + { + sd->isa_mode = ISA_MODE_MICROMIPS; + cia = cia & ~0x1; + } + +#if defined (ENGINE_ISSUE_PREFIX_HOOK) + ENGINE_ISSUE_PREFIX_HOOK (); +#endif + switch (sd->isa_mode) + { + case ISA_MODE_MICROMIPS: + nia = + micromips_instruction_decode (sd, cpu, cia, + MICROMIPS_DELAYSLOT_SIZE_ANY); + break; + case ISA_MODE_MIPS32: + instruction_0 = IMEM32 (cia); + nia = micromips_m32_idecode_issue (sd, instruction_0, cia); + break; + default: + nia = NULL_CIA; + } + +#if defined (ENGINE_ISSUE_POSTFIX_HOOK) + ENGINE_ISSUE_POSTFIX_HOOK (); +#endif + + /* Update the instruction address */ + cia = nia; + + /* process any events */ + if (sim_events_tick (sd)) + { + CPU_PC_SET (cpu, cia); + sim_events_process (sd); + cia = CPU_PC_GET (cpu); + } + } +} diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen index 5a6326f..2862eeb 100644 --- a/sim/mips/mips.igen +++ b/sim/mips/mips.igen @@ -74,6 +74,9 @@ :model:::dsp:dsp: // dsp.igen :model:::dsp2:dsp2: // dsp2.igen :model:::smartmips:smartmips: // smartmips.igen +:model:::micromips32:micromips64: // micromips.igen +:model:::micromips64:micromips64: // micromips.igen +:model:::micromipsdsp:micromipsdsp: // micromipsdsp.igen // Vendor Extensions // @@ -91,7 +94,7 @@ // Pseudo instructions known by interp.c // For grep - RSVD_INSTRUCTION, RSVD_INSTRUCTION_MASK -000000,5.*,5.*,5.*,5.OP,000101:SPECIAL:32::RSVD +000000,5.*,5.*,5.*,5.OP,111001:SPECIAL:32::RSVD "rsvd <OP>" { SignalException (ReservedInstruction, instruction_0); @@ -142,6 +145,7 @@ *vr4100: *vr5000: *r3900: +*micromips32: { return base + offset; } @@ -149,6 +153,7 @@ :function:::address_word:loadstore_ea:address_word base, address_word offset *mips64: *mips64r2: +*micromips64: { #if 0 /* XXX FIXME: enable this only after some additional testing. */ /* If in user mode and UX is not set, use 32-bit compatibility effective @@ -181,6 +186,8 @@ *mips32r2: *mips64: *mips64r2: +*micromips32: +*micromips64: { #if WITH_TARGET_WORD_BITSIZE == 64 return value != (((value & 0xffffffff) ^ 0x80000000) - 0x80000000); @@ -214,6 +221,8 @@ *mips32r2: *mips64: *mips64r2: +*micromips32: +*micromips64: { unpredictable_action (CPU, CIA); } @@ -305,6 +314,8 @@ *mips64: *mips64r2: *r3900: +*micromips32: +*micromips64: { signed64 time = sim_events_time (SD); history->mt.timestamp = time; @@ -331,6 +342,8 @@ *vr4100: *vr5000: *r3900: +*micromips32: +*micromips64: { signed64 time = sim_events_time (SD); int ok = 1; @@ -401,6 +414,8 @@ *mips64: *mips64r2: *r3900: +*micromips32: +*micromips64: { /* FIXME: could record the fact that a stall occured if we want */ signed64 time = sim_events_time (SD); @@ -455,6 +470,8 @@ *mips32r2: *mips64: *mips64r2: +*micromips32: +*micromips64: { signed64 time = sim_events_time (SD); hi->op.timestamp = time; @@ -487,6 +504,10 @@ *mips16e: *mips64: *mips64r2: +*mips32: +*mips32r2: +*micromips64: +*micromips32: { #if 0 /* XXX FIXME: enable this only after some additional testing. */ if (UserMode && (SR & (status_UX|status_PX)) == 0) @@ -503,6 +524,1272 @@ // +:function:::void:do_add:int rs, int rt, int rd +{ + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + { + ALU32_BEGIN (GPR[rs]); + ALU32_ADD (GPR[rt]); + ALU32_END (GPR[rd]); /* This checks for overflow. */ + } + TRACE_ALU_RESULT (GPR[rd]); +} + +:function:::void:do_addi:int rs, int rt, unsigned16 immediate +{ + if (NotWordValue (GPR[rs])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], EXTEND16 (immediate)); + { + ALU32_BEGIN (GPR[rs]); + ALU32_ADD (EXTEND16 (immediate)); + ALU32_END (GPR[rt]); /* This checks for overflow. */ + } + TRACE_ALU_RESULT (GPR[rt]); +} + +:function:::void:do_andi:int rs, int rt, unsigned int immediate +{ + TRACE_ALU_INPUT2 (GPR[rs], immediate); + GPR[rt] = GPR[rs] & immediate; + TRACE_ALU_RESULT (GPR[rt]); +} + +:function:::void:do_dadd:int rd, int rs, int rt +{ + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + { + ALU64_BEGIN (GPR[rs]); + ALU64_ADD (GPR[rt]); + ALU64_END (GPR[rd]); /* This checks for overflow. */ + } + TRACE_ALU_RESULT (GPR[rd]); +} + +:function:::void:do_daddi:int rt, int rs, int immediate +{ + TRACE_ALU_INPUT2 (GPR[rs], EXTEND16 (immediate)); + { + ALU64_BEGIN (GPR[rs]); + ALU64_ADD (EXTEND16 (immediate)); + ALU64_END (GPR[rt]); /* This checks for overflow. */ + } + TRACE_ALU_RESULT (GPR[rt]); +} + +:function:::void:do_dsll32:int rd, int rt, int shift +{ + int s = 32 + shift; + TRACE_ALU_INPUT2 (GPR[rt], s); + GPR[rd] = GPR[rt] << s; + TRACE_ALU_RESULT (GPR[rd]); +} + +:function:::void:do_dsra32:int rd, int rt, int shift +{ + int s = 32 + shift; + TRACE_ALU_INPUT2 (GPR[rt], s); + GPR[rd] = ((signed64) GPR[rt]) >> s; + TRACE_ALU_RESULT (GPR[rd]); +} + +:function:::void:do_dsrl32:int rd, int rt, int shift +{ + int s = 32 + shift; + TRACE_ALU_INPUT2 (GPR[rt], s); + GPR[rd] = (unsigned64) GPR[rt] >> s; + TRACE_ALU_RESULT (GPR[rd]); +} + +:function:::void:do_dsub:int rd, int rs, int rt +{ + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + { + ALU64_BEGIN (GPR[rs]); + ALU64_SUB (GPR[rt]); + ALU64_END (GPR[rd]); /* This checks for overflow. */ + } + TRACE_ALU_RESULT (GPR[rd]); +} + +:function:::void:do_break:address_word instruction_0 +{ + /* Check for some break instruction which are reserved for use by the + simulator. */ + unsigned int break_code = instruction_0 & HALT_INSTRUCTION_MASK; + if (break_code == (HALT_INSTRUCTION & HALT_INSTRUCTION_MASK) || + break_code == (HALT_INSTRUCTION2 & HALT_INSTRUCTION_MASK)) + { + sim_engine_halt (SD, CPU, NULL, cia, + sim_exited, (unsigned int)(A0 & 0xFFFFFFFF)); + } + else if (break_code == (BREAKPOINT_INSTRUCTION & HALT_INSTRUCTION_MASK) || + break_code == (BREAKPOINT_INSTRUCTION2 & HALT_INSTRUCTION_MASK)) + { + if (STATE & simDELAYSLOT) + PC = cia - 4; /* reference the branch instruction */ + else + PC = cia; + SignalException (BreakPoint, instruction_0); + } + + else + { + /* If we get this far, we're not an instruction reserved by the sim. Raise + the exception. */ + SignalException (BreakPoint, instruction_0); + } +} + +:function:::void:do_break16:address_word instruction_0 +{ + if (STATE & simDELAYSLOT) + PC = cia - 2; /* reference the branch instruction */ + else + PC = cia; + SignalException (BreakPoint, instruction_0); +} + +:function:::void:do_clo:int rd, int rs +{ + unsigned32 temp = GPR[rs]; + unsigned32 i, mask; + if (NotWordValue (GPR[rs])) + Unpredictable (); + TRACE_ALU_INPUT1 (GPR[rs]); + for (mask = ((unsigned32)1<<31), i = 0; i < 32; ++i) + { + if ((temp & mask) == 0) + break; + mask >>= 1; + } + GPR[rd] = EXTEND32 (i); + TRACE_ALU_RESULT (GPR[rd]); +} + +:function:::void:do_clz:int rd, int rs +{ + unsigned32 temp = GPR[rs]; + unsigned32 i, mask; + if (NotWordValue (GPR[rs])) + Unpredictable (); + TRACE_ALU_INPUT1 (GPR[rs]); + for (mask = ((unsigned32)1<<31), i = 0; i < 32; ++i) + { + if ((temp & mask) != 0) + break; + mask >>= 1; + } + GPR[rd] = EXTEND32 (i); + TRACE_ALU_RESULT (GPR[rd]); +} + +:function:::void:do_dclo:int rd, int rs +{ + unsigned64 temp = GPR[rs]; + unsigned32 i; + unsigned64 mask; + TRACE_ALU_INPUT1 (GPR[rs]); + for (mask = ((unsigned64)1<<63), i = 0; i < 64; ++i) + { + if ((temp & mask) == 0) + break; + mask >>= 1; + } + GPR[rd] = EXTEND32 (i); + TRACE_ALU_RESULT (GPR[rd]); +} + +:function:::void:do_dclz:int rd, int rs +{ + unsigned64 temp = GPR[rs]; + unsigned32 i; + unsigned64 mask; + TRACE_ALU_INPUT1 (GPR[rs]); + for (mask = ((unsigned64)1<<63), i = 0; i < 64; ++i) + { + if ((temp & mask) != 0) + break; + mask >>= 1; + } + GPR[rd] = EXTEND32 (i); + TRACE_ALU_RESULT (GPR[rd]); +} + +:function:::void:do_lb:int rt, int offset, int base +{ + GPR[rt] = EXTEND8 (do_load (SD_, AccessLength_BYTE, GPR[base], + EXTEND16 (offset))); +} + +:function:::void:do_lh:int rt, int offset, int base +{ + GPR[rt] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[base], + EXTEND16 (offset))); +} + +:function:::void:do_lwr:int rt, int offset, int base +{ + GPR[rt] = EXTEND32 (do_load_right (SD_, AccessLength_WORD, GPR[base], + EXTEND16 (offset), GPR[rt])); +} + +:function:::void:do_lwl:int rt, int offset, int base +{ + GPR[rt] = EXTEND32 (do_load_left (SD_, AccessLength_WORD, GPR[base], + EXTEND16 (offset), GPR[rt])); +} + +:function:::void:do_lwc:int num, int rt, int offset, int base +{ + COP_LW (num, rt, do_load (SD_, AccessLength_WORD, GPR[base], + EXTEND16 (offset))); +} + +:function:::void:do_lw:int rt, int offset, int base +{ + GPR[rt] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[base], + EXTEND16 (offset))); +} + +:function:::void:do_lwu:int rt, int offset, int base, address_word instruction_0 +{ + check_u64 (SD_, instruction_0); + GPR[rt] = do_load (SD_, AccessLength_WORD, GPR[base], EXTEND16 (offset)); +} + +:function:::void:do_lhu:int rt, int offset, int base +{ + GPR[rt] = do_load (SD_, AccessLength_HALFWORD, GPR[base], EXTEND16 (offset)); +} + +:function:::void:do_ldc:int num, int rt, int offset, int base +{ + COP_LD (num, rt, do_load (SD_, AccessLength_DOUBLEWORD, GPR[base], + EXTEND16 (offset))); +} + +:function:::void:do_lbu:int rt, int offset, int base +{ + GPR[rt] = do_load (SD_, AccessLength_BYTE, GPR[base], EXTEND16 (offset)); +} + +:function:::void:do_ll:int rt, int insn_offset, int basereg +{ + address_word base = GPR[basereg]; + address_word offset = EXTEND16 (insn_offset); + { + address_word vaddr = loadstore_ea (SD_, base, offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + { + SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, read_transfer, + sim_core_unaligned_signal); + } + else + { + if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, + isTARGET, isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); + unsigned int shift = 2; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory (&memval, &memval1, uncached, AccessLength_WORD, paddr, + vaddr, isDATA, isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[rt] = EXTEND32 (memval >> (8 * byte)); + LLBIT = 1; + } + } + } +} + +:function:::void:do_lld:int rt, int roffset, int rbase +{ + address_word base = GPR[rbase]; + address_word offset = EXTEND16 (roffset); + { + address_word vaddr = loadstore_ea (SD_, base, offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + { + SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 8, vaddr, read_transfer, + sim_core_unaligned_signal); + } + else + { + if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, + isTARGET, isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + LoadMemory (&memval, &memval1, uncached, AccessLength_DOUBLEWORD, + paddr, vaddr, isDATA, isREAL); + GPR[rt] = memval; + LLBIT = 1; + } + } + } +} + +:function:::void:do_lui:int rt, int immediate +{ + TRACE_ALU_INPUT1 (immediate); + GPR[rt] = EXTEND32 (immediate << 16); + TRACE_ALU_RESULT (GPR[rt]); +} + +:function:::void:do_madd:int rs, int rt +{ + signed64 temp; + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + temp = (U8_4 (VL4_8 (HI), VL4_8 (LO)) + + ((signed64) EXTEND32 (GPR[rt]) * (signed64) EXTEND32 (GPR[rs]))); + LO = EXTEND32 (temp); + HI = EXTEND32 (VH4_8 (temp)); + TRACE_ALU_RESULT2 (HI, LO); +} + +:function:::void:do_dsp_madd:int ac, int rs, int rt +{ + signed64 temp; + if (ac == 0) + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + temp = (U8_4 (VL4_8 (DSPHI(ac)), VL4_8 (DSPLO(ac))) + + ((signed64) EXTEND32 (GPR[rt]) * (signed64) EXTEND32 (GPR[rs]))); + DSPLO(ac) = EXTEND32 (temp); + DSPHI(ac) = EXTEND32 (VH4_8 (temp)); + if (ac == 0) + TRACE_ALU_RESULT2 (HI, LO); +} + +:function:::void:do_maddu:int rs, int rt +{ + unsigned64 temp; + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + temp = (U8_4 (VL4_8 (HI), VL4_8 (LO)) + + ((unsigned64) VL4_8 (GPR[rs]) * (unsigned64) VL4_8 (GPR[rt]))); + ACX += U8_4 (VL4_8 (HI), VL4_8 (LO)) < temp; /* SmartMIPS */ + LO = EXTEND32 (temp); + HI = EXTEND32 (VH4_8 (temp)); + TRACE_ALU_RESULT2 (HI, LO); +} + +:function:::void:do_dsp_maddu:int ac, int rs, int rt +{ + unsigned64 temp; + if (ac == 0) + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + temp = (U8_4 (VL4_8 (DSPHI(ac)), VL4_8 (DSPLO(ac))) + + ((unsigned64) VL4_8 (GPR[rs]) * (unsigned64) VL4_8 (GPR[rt]))); + if (ac == 0) + ACX += U8_4 (VL4_8 (HI), VL4_8 (LO)) < temp; /* SmartMIPS */ + DSPLO(ac) = EXTEND32 (temp); + DSPHI(ac) = EXTEND32 (VH4_8 (temp)); + if (ac == 0) + TRACE_ALU_RESULT2 (HI, LO); +} + +:function:::void:do_dsp_mfhi:int ac, int rd +{ + if (ac == 0) + do_mfhi (SD_, rd); + else + GPR[rd] = DSPHI(ac); +} + +:function:::void:do_dsp_mflo:int ac, int rd +{ + if (ac == 0) + do_mflo (SD_, rd); + else + GPR[rd] = DSPLO(ac); +} + +:function:::void:do_movn:int rd, int rs, int rt +{ + if (GPR[rt] != 0) + { + GPR[rd] = GPR[rs]; + TRACE_ALU_RESULT (GPR[rd]); + } +} + +:function:::void:do_movz:int rd, int rs, int rt +{ + if (GPR[rt] == 0) + { + GPR[rd] = GPR[rs]; + TRACE_ALU_RESULT (GPR[rd]); + } +} + +:function:::void:do_msub:int rs, int rt +{ + signed64 temp; + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + temp = (U8_4 (VL4_8 (HI), VL4_8 (LO)) + - ((signed64) EXTEND32 (GPR[rt]) * (signed64) EXTEND32 (GPR[rs]))); + LO = EXTEND32 (temp); + HI = EXTEND32 (VH4_8 (temp)); + TRACE_ALU_RESULT2 (HI, LO); +} + +:function:::void:do_dsp_msub:int ac, int rs, int rt +{ + signed64 temp; + if (ac == 0) + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + temp = (U8_4 (VL4_8 (DSPHI(ac)), VL4_8 (DSPLO(ac))) + - ((signed64) EXTEND32 (GPR[rt]) * (signed64) EXTEND32 (GPR[rs]))); + DSPLO(ac) = EXTEND32 (temp); + DSPHI(ac) = EXTEND32 (VH4_8 (temp)); + if (ac == 0) + TRACE_ALU_RESULT2 (HI, LO); +} + +:function:::void:do_msubu:int rs, int rt +{ + unsigned64 temp; + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + temp = (U8_4 (VL4_8 (HI), VL4_8 (LO)) + - ((unsigned64) VL4_8 (GPR[rs]) * (unsigned64) VL4_8 (GPR[rt]))); + LO = EXTEND32 (temp); + HI = EXTEND32 (VH4_8 (temp)); + TRACE_ALU_RESULT2 (HI, LO); +} + +:function:::void:do_dsp_msubu:int ac, int rs, int rt +{ + unsigned64 temp; + if (ac == 0) + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + temp = (U8_4 (VL4_8 (DSPHI(ac)), VL4_8 (DSPLO(ac))) + - ((unsigned64) VL4_8 (GPR[rs]) * (unsigned64) VL4_8 (GPR[rt]))); + DSPLO(ac) = EXTEND32 (temp); + DSPHI(ac) = EXTEND32 (VH4_8 (temp)); + if (ac == 0) + TRACE_ALU_RESULT2 (HI, LO); +} + +:function:::void:do_mthi:int rs +{ + check_mt_hilo (SD_, HIHISTORY); + HI = GPR[rs]; +} + +:function:::void:do_dsp_mthi:int ac, int rs +{ + if (ac == 0) + check_mt_hilo (SD_, HIHISTORY); + DSPHI(ac) = GPR[rs]; +} + +:function:::void:do_mtlo:int rs +{ + check_mt_hilo (SD_, LOHISTORY); + LO = GPR[rs]; +} + +:function:::void:do_dsp_mtlo:int ac, int rs +{ + if (ac == 0) + check_mt_hilo (SD_, LOHISTORY); + DSPLO(ac) = GPR[rs]; +} + +:function:::void:do_mul:int rd, int rs, int rt +{ + signed64 prod; + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + prod = (((signed64)(signed32) GPR[rs]) + * ((signed64)(signed32) GPR[rt])); + GPR[rd] = EXTEND32 (VL4_8 (prod)); + TRACE_ALU_RESULT (GPR[rd]); +} + +:function:::void:do_dsp_mult:int ac, int rs, int rt +{ + signed64 prod; + if (ac == 0) + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + prod = ((signed64)(signed32) GPR[rs]) + * ((signed64)(signed32) GPR[rt]); + DSPLO(ac) = EXTEND32 (VL4_8 (prod)); + DSPHI(ac) = EXTEND32 (VH4_8 (prod)); + if (ac == 0) + { + ACX = 0; /* SmartMIPS */ + TRACE_ALU_RESULT2 (HI, LO); + } +} + +:function:::void:do_dsp_multu:int ac, int rs, int rt +{ + unsigned64 prod; + if (ac == 0) + check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + prod = ((unsigned64)(unsigned32) GPR[rs]) + * ((unsigned64)(unsigned32) GPR[rt]); + DSPLO(ac) = EXTEND32 (VL4_8 (prod)); + DSPHI(ac) = EXTEND32 (VH4_8 (prod)); + if (ac == 0) + TRACE_ALU_RESULT2 (HI, LO); +} + +:function:::void:do_pref:int hint, int insn_offset, int insn_base +{ + address_word base = GPR[insn_base]; + address_word offset = EXTEND16 (insn_offset); + { + address_word vaddr = loadstore_ea (SD_, base, offset); + address_word paddr; + int uncached; + { + if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, + isTARGET, isREAL)) + Prefetch (uncached, paddr, vaddr, isDATA, hint); + } + } +} + +:function:::void:do_sc:int rt, int offsetarg, int basereg, address_word instruction_0 +{ + unsigned32 instruction = instruction_0; + address_word base = GPR[basereg]; + address_word offset = EXTEND16 (offsetarg); + { + address_word vaddr = loadstore_ea (SD_, base, offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + { + SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, write_transfer, + sim_core_unaligned_signal); + } + else + { + if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, + isTARGET, isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); + address_word reverseendian = + (ReverseEndian ? (mask ^ AccessLength_WORD) : 0); + address_word bigendiancpu = + (BigEndianCPU ? (mask ^ AccessLength_WORD) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian)); + byte = ((vaddr & mask) ^ bigendiancpu); + memval = ((unsigned64) GPR[rt] << (8 * byte)); + if (LLBIT) + { + StoreMemory (uncached, AccessLength_WORD, memval, memval1, + paddr, vaddr, isREAL); + } + GPR[rt] = LLBIT; + } + } + } +} + +:function:::void:do_scd:int rt, int roffset, int rbase +{ + address_word base = GPR[rbase]; + address_word offset = EXTEND16 (roffset); + { + address_word vaddr = loadstore_ea (SD_, base, offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + { + SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 8, vaddr, write_transfer, + sim_core_unaligned_signal); + } + else + { + if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, + isTARGET, isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + memval = GPR[rt]; + if (LLBIT) + { + StoreMemory (uncached, AccessLength_DOUBLEWORD, memval, memval1, + paddr, vaddr, isREAL); + } + GPR[rt] = LLBIT; + } + } + } +} + +:function:::void:do_sub:int rs, int rt, int rd +{ + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); + { + ALU32_BEGIN (GPR[rs]); + ALU32_SUB (GPR[rt]); + ALU32_END (GPR[rd]); /* This checks for overflow. */ + } + TRACE_ALU_RESULT (GPR[rd]); +} + +:function:::void:do_sw:int rt, int offset, int base +{ + do_store (SD_, AccessLength_WORD, GPR[base], EXTEND16 (offset), GPR[rt]); +} + +:function:::void:do_teq:int rs, int rt, address_word instruction_0 +{ + if ((signed_word) GPR[rs] == (signed_word) GPR[rt]) + SignalException (Trap, instruction_0); +} + +:function:::void:do_teqi:int rs, int immediate, address_word instruction_0 +{ + if ((signed_word) GPR[rs] == (signed_word) EXTEND16 (immediate)) + SignalException (Trap, instruction_0); +} + +:function:::void:do_tge:int rs, int rt, address_word instruction_0 +{ + if ((signed_word) GPR[rs] >= (signed_word) GPR[rt]) + SignalException (Trap, instruction_0); +} + +:function:::void:do_tgei:int rs, int immediate, address_word instruction_0 +{ + if ((signed_word) GPR[rs] >= (signed_word) EXTEND16 (immediate)) + SignalException (Trap, instruction_0); +} + +:function:::void:do_tgeiu:int rs, int immediate, address_word instruction_0 +{ + if ((unsigned_word) GPR[rs] >= (unsigned_word) EXTEND16 (immediate)) + SignalException (Trap, instruction_0); +} + +:function:::void:do_tgeu:int rs ,int rt, address_word instruction_0 +{ + if ((unsigned_word) GPR[rs] >= (unsigned_word) GPR[rt]) + SignalException (Trap, instruction_0); +} + +:function:::void:do_tlt:int rs, int rt, address_word instruction_0 +{ + if ((signed_word) GPR[rs] < (signed_word) GPR[rt]) + SignalException (Trap, instruction_0); +} + +:function:::void:do_tlti:int rs, int immediate, address_word instruction_0 +{ + if ((signed_word) GPR[rs] < (signed_word) EXTEND16 (immediate)) + SignalException (Trap, instruction_0); +} + +:function:::void:do_tltiu:int rs, int immediate, address_word instruction_0 +{ + if ((unsigned_word) GPR[rs] < (unsigned_word) EXTEND16 (immediate)) + SignalException (Trap, instruction_0); +} + +:function:::void:do_tltu:int rs, int rt, address_word instruction_0 +{ + if ((unsigned_word) GPR[rs] < (unsigned_word) GPR[rt]) + SignalException (Trap, instruction_0); +} + +:function:::void:do_tne:int rs, int rt, address_word instruction_0 +{ + if ((signed_word) GPR[rs] != (signed_word) GPR[rt]) + SignalException (Trap, instruction_0); +} + +:function:::void:do_tnei:int rs, int immediate, address_word instruction_0 +{ + if ((signed_word) GPR[rs] != (signed_word) EXTEND16 (immediate)) + SignalException (Trap, instruction_0); +} + +:function:::void:do_abs_fmt:int fmt, int fd, int fs, address_word instruction_0 +{ + check_fpu (SD_); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (fd, fmt, AbsoluteValue (ValueFPR (fs, fmt), fmt)); +} + +:function:::void:do_add_fmt:int fmt, int fd, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (fd, fmt, Add (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt)); +} + +:function:::void:do_alnv_ps:int fd, int fs, int ft, int rs, address_word instruction_0 +{ + unsigned64 fsx; + unsigned64 ftx; + unsigned64 fdx; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + fsx = ValueFPR (fs, fmt_ps); + if ((GPR[rs] & 0x3) != 0) + Unpredictable (); + if ((GPR[rs] & 0x4) == 0) + fdx = fsx; + else + { + ftx = ValueFPR (ft, fmt_ps); + if (BigEndianCPU) + fdx = PackPS (PSLower (fsx), PSUpper (ftx)); + else + fdx = PackPS (PSLower (ftx), PSUpper (fsx)); + } + StoreFPR (fd, fmt_ps, fdx); +} + +:function:::void:do_c_cond_fmt:int cond, int fmt, int cc, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + check_fmt_p (SD_, fmt, instruction_0); + Compare (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt, cond, cc); + TRACE_ALU_RESULT (ValueFCR (31)); +} + +:function:::void:do_ceil_fmt:int type, int fmt, int fd, int fs, address_word instruction_0 +{ + check_fpu (SD_); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (fd, type, Convert (FP_RM_TOPINF, ValueFPR (fs, fmt), fmt, + type)); +} + +:function:::void:do_cfc1:int rt, int fs +{ + check_fpu (SD_); + if (fs == 0 || fs == 25 || fs == 26 || fs == 28 || fs == 31) + { + unsigned_word fcr = ValueFCR (fs); + TRACE_ALU_INPUT1 (fcr); + GPR[rt] = fcr; + } + /* else NOP */ + TRACE_ALU_RESULT (GPR[rt]); +} + +:function:::void:do_ctc1:int rt, int fs +{ + check_fpu (SD_); + TRACE_ALU_INPUT1 (GPR[rt]); + if (fs == 25 || fs == 26 || fs == 28 || fs == 31) + StoreFCR (fs, GPR[rt]); + /* else NOP */ +} + +:function:::void:do_cvt_d_fmt:int fmt, int fd, int fs, address_word instruction_0 +{ + check_fpu (SD_); + if ((fmt == fmt_double) | 0) + SignalException (ReservedInstruction, instruction_0); + StoreFPR (fd, fmt_double, Convert (GETRM (), ValueFPR (fs, fmt), fmt, + fmt_double)); +} + +:function:::void:do_cvt_l_fmt:int fmt, int fd, int fs, address_word instruction_0 +{ + check_fpu (SD_); + if ((fmt == fmt_long) | ((fmt == fmt_long) || (fmt == fmt_word))) + SignalException (ReservedInstruction, instruction_0); + StoreFPR (fd, fmt_long, Convert (GETRM (), ValueFPR (fs, fmt), fmt, + fmt_long)); +} + +:function:::void:do_cvt_ps_s:int fd, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + StoreFPR (fd, fmt_ps, PackPS (ValueFPR (fs, fmt_single), + ValueFPR (ft, fmt_single))); +} + +:function:::void:do_cvt_s_fmt:int fmt, int fd, int fs, address_word instruction_0 +{ + check_fpu (SD_); + if ((fmt == fmt_single) | 0) + SignalException (ReservedInstruction, instruction_0); + StoreFPR (fd, fmt_single, Convert (GETRM (), ValueFPR (fs, fmt), fmt, + fmt_single)); +} + +:function:::void:do_cvt_s_pl:int fd, int fs, address_word instruction_0 +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + StoreFPR (fd, fmt_single, PSLower (ValueFPR (fs, fmt_ps))); +} + +:function:::void:do_cvt_s_pu:int fd, int fs, address_word instruction_0 +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + StoreFPR (fd, fmt_single, PSUpper (ValueFPR (fs, fmt_ps))); +} + +:function:::void:do_cvt_w_fmt:int fmt, int fd, int fs, address_word instruction_0 +{ + check_fpu (SD_); + if ((fmt == fmt_word) | ((fmt == fmt_long) || (fmt == fmt_word))) + SignalException (ReservedInstruction, instruction_0); + StoreFPR (fd, fmt_word, Convert (GETRM (), ValueFPR (fs, fmt), fmt, + fmt_word)); +} + +:function:::void:do_div_fmt:int fmt, int fd, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + StoreFPR (fd, fmt, Divide (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt)); +} + +:function:::void:do_dmfc1b:int rt, int fs +*mipsIV: +*mipsV: +*mips64: +*mips64r2: +*vr4100: +*vr5000: +*r3900: +*micromips64: +{ + if (SizeFGR () == 64) + GPR[rt] = FGR[fs]; + else if ((fs & 0x1) == 0) + GPR[rt] = SET64HI (FGR[fs+1]) | FGR[fs]; + else + GPR[rt] = SET64HI (0xDEADC0DE) | 0xBAD0BAD0; + TRACE_ALU_RESULT (GPR[rt]); +} + +:function:::void:do_dmtc1b:int rt, int fs +{ + if (SizeFGR () == 64) + StoreFPR (fs, fmt_uninterpreted_64, GPR[rt]); + else if ((fs & 0x1) == 0) + StoreFPR (fs, fmt_uninterpreted_64, GPR[rt]); + else + Unpredictable (); +} + +:function:::void:do_floor_fmt:int type, int fmt, int fd, int fs +{ + check_fpu (SD_); + StoreFPR (fd, type, Convert (FP_RM_TOMINF, ValueFPR (fs, fmt), fmt, + type)); +} + +:function:::void:do_luxc1_32:int fd, int rindex, int rbase +*mips32r2: +*micromips32: +{ + address_word base = GPR[rbase]; + address_word index = GPR[rindex]; + address_word vaddr = base + index; + check_fpu (SD_); + if (SizeFGR () != 64) + Unpredictable (); + /* Arrange for the bottom 3 bits of (base + index) to be 0. */ + if ((vaddr & 0x7) != 0) + index -= (vaddr & 0x7); + COP_LD (1, fd, do_load_double (SD_, base, index)); +} + +:function:::void:do_luxc1_64:int fd, int rindex, int rbase +{ + address_word base = GPR[rbase]; + address_word index = GPR[rindex]; + address_word vaddr = base + index; + if (SizeFGR () != 64) + Unpredictable (); + /* Arrange for the bottom 3 bits of (base + index) to be 0. */ + if ((vaddr & 0x7) != 0) + index -= (vaddr & 0x7); + COP_LD (1, fd, do_load (SD_, AccessLength_DOUBLEWORD, base, index)); + +} + +:function:::void:do_lwc1:int ft, int offset, int base +{ + check_fpu (SD_); + COP_LW (1, ft, do_load (SD_, AccessLength_WORD, GPR[base], + EXTEND16 (offset))); +} + +:function:::void:do_lwxc1:int fd, int index, int base, address_word instruction_0 +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + COP_LW (1, fd, do_load (SD_, AccessLength_WORD, GPR[base], GPR[index])); +} + +:function:::void:do_madd_fmt:int fmt, int fd, int fr, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (fd, fmt, MultiplyAdd (ValueFPR (fs, fmt), ValueFPR (ft, fmt), + ValueFPR (fr, fmt), fmt)); +} + +:function:::void:do_mfc1b:int rt, int fs +{ + check_fpu (SD_); + GPR[rt] = EXTEND32 (FGR[fs]); + TRACE_ALU_RESULT (GPR[rt]); +} + +:function:::void:do_mov_fmt:int fmt, int fd, int fs, address_word instruction_0 +{ + check_fpu (SD_); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (fd, fmt, ValueFPR (fs, fmt)); +} + +:function:::void:do_movtf:int tf, int rd, int rs, int cc +{ + check_fpu (SD_); + if (GETFCC(cc) == tf) + GPR[rd] = GPR[rs]; +} + +:function:::void:do_movtf_fmt:int tf, int fmt, int fd, int fs, int cc +{ + check_fpu (SD_); + if (fmt != fmt_ps) + { + if (GETFCC(cc) == tf) + StoreFPR (fd, fmt, ValueFPR (fs, fmt)); + else + StoreFPR (fd, fmt, ValueFPR (fd, fmt)); /* set fmt */ + } + else + { + unsigned64 fdx; + fdx = PackPS (PSUpper (ValueFPR ((GETFCC (cc+1) == tf) ? fs : fd, + fmt_ps)), + PSLower (ValueFPR ((GETFCC (cc+0) == tf) ? fs : fd, + fmt_ps))); + StoreFPR (fd, fmt_ps, fdx); + } +} + +:function:::void:do_movn_fmt:int fmt, int fd, int fs, int rt +{ + check_fpu (SD_); + if (GPR[rt] != 0) + StoreFPR (fd, fmt, ValueFPR (fs, fmt)); + else + StoreFPR (fd, fmt, ValueFPR (fd, fmt)); +} + +:function:::void:do_movz_fmt:int fmt, int fd, int fs, int rt +{ + check_fpu (SD_); + if (GPR[rt] == 0) + StoreFPR (fd, fmt, ValueFPR (fs, fmt)); + else + StoreFPR (fd, fmt, ValueFPR (fd, fmt)); +} + +:function:::void:do_msub_fmt:int fmt, int fd, int fr, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (fd, fmt, MultiplySub (ValueFPR (fs, fmt), ValueFPR (ft, fmt), + ValueFPR (fr, fmt), fmt)); +} + +:function:::void:do_mtc1b:int rt, int fs +{ + check_fpu (SD_); + StoreFPR (fs, fmt_uninterpreted_32, VL4_8 (GPR[rt])); +} + +:function:::void:do_mul_fmt:int fmt, int fd, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (fd, fmt, Multiply (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt)); +} + +:function:::void:do_neg_fmt:int fmt, int fd, int fs, address_word instruction_0 +{ + check_fpu (SD_); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (fd, fmt, Negate (ValueFPR (fs, fmt), fmt)); +} + +:function:::void:do_nmadd_fmt:int fmt, int fd, int fr, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (fd, fmt, NegMultiplyAdd (ValueFPR (fs, fmt), ValueFPR (ft, fmt), + ValueFPR (fr, fmt), fmt)); +} + +:function:::void:do_nmsub_fmt:int fmt, int fd, int fr, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (fd, fmt, NegMultiplySub (ValueFPR (fs, fmt), ValueFPR (ft, fmt), + ValueFPR (fr, fmt), fmt)); +} + +:function:::void:do_pll_ps:int fd, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + StoreFPR (fd, fmt_ps, PackPS (PSLower (ValueFPR (fs, fmt_ps)), + PSLower (ValueFPR (ft, fmt_ps)))); +} + +:function:::void:do_plu_ps:int fd, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + StoreFPR (fd, fmt_ps, PackPS (PSLower (ValueFPR (fs, fmt_ps)), + PSUpper (ValueFPR (ft, fmt_ps)))); +} + +:function:::void:do_pul_ps:int fd, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + StoreFPR (fd, fmt_ps, PackPS (PSUpper (ValueFPR (fs, fmt_ps)), + PSLower (ValueFPR (ft, fmt_ps)))); +} + +:function:::void:do_puu_ps:int fd, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + StoreFPR (fd, fmt_ps, PackPS (PSUpper (ValueFPR (fs, fmt_ps)), + PSUpper (ValueFPR (ft, fmt_ps)))); +} + +:function:::void:do_recip_fmt:int fmt, int fd, int fs +{ + check_fpu (SD_); + StoreFPR (fd, fmt, Recip (ValueFPR (fs, fmt), fmt)); +} + +:function:::void:do_round_fmt:int type, int fmt, int fd, int fs +{ + check_fpu (SD_); + StoreFPR (fd, type, Convert (FP_RM_NEAREST, ValueFPR (fs, fmt), fmt, + type)); +} + +:function:::void:do_rsqrt_fmt:int fmt, int fd, int fs +{ + check_fpu (SD_); + StoreFPR (fd, fmt, RSquareRoot (ValueFPR (fs, fmt), fmt)); +} + +:function:::void:do_prefx:int hint, int rindex, int rbase +{ + address_word base = GPR[rbase]; + address_word index = GPR[rindex]; + { + address_word vaddr = loadstore_ea (SD_, base, index); + address_word paddr; + int uncached; + if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, isTARGET, + isREAL)) + Prefetch (uncached, paddr, vaddr, isDATA, hint); + } +} + +:function:::void:do_sdc1:int ft, int offset, int base +*mipsII: +*mips32: +*mips32r2: +*micromips32: +{ + check_fpu (SD_); + do_store_double (SD_, GPR[base], EXTEND16 (offset), COP_SD (1, ft)); +} + +:function:::void:do_suxc1_32:int fs, int rindex, int rbase +*mips32r2: +*micromips32: +{ + address_word base = GPR[rbase]; + address_word index = GPR[rindex]; + address_word vaddr = base + index; + check_fpu (SD_); + if (SizeFGR () != 64) + Unpredictable (); + /* Arrange for the bottom 3 bits of (base + index) to be 0. */ + if ((vaddr & 0x7) != 0) + index -= (vaddr & 0x7); + do_store_double (SD_, base, index, COP_SD (1, fs)); +} + +:function:::void:do_suxc1_64:int fs, int rindex, int rbase +{ + address_word base = GPR[rbase]; + address_word index = GPR[rindex]; + address_word vaddr = base + index; + if (SizeFGR () != 64) + Unpredictable (); + /* Arrange for the bottom 3 bits of (base + index) to be 0. */ + if ((vaddr & 0x7) != 0) + index -= (vaddr & 0x7); + do_store (SD_, AccessLength_DOUBLEWORD, base, index, COP_SD (1, fs)); +} + +:function:::void:do_sqrt_fmt:int fmt, int fd, int fs +{ + check_fpu (SD_); + StoreFPR (fd, fmt, (SquareRoot (ValueFPR (fs, fmt), fmt))); +} + +:function:::void:do_sub_fmt:int fmt, int fd, int fs, int ft, address_word instruction_0 +{ + check_fpu (SD_); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (fd, fmt, Sub (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt)); +} + +:function:::void:do_swc1:int ft, int roffset, int rbase, address_word instruction_0 +{ + address_word base = GPR[rbase]; + address_word offset = EXTEND16 (roffset); + check_fpu (SD_); + { + address_word vaddr = loadstore_ea (SD_, base, offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + { + SIM_CORE_SIGNAL (SD, CPU, cia, read_map, AccessLength_WORD+1, vaddr, + write_transfer, sim_core_unaligned_signal); + } + else + { + if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, + isTARGET, isREAL)) + { + uword64 memval = 0; + uword64 memval1 = 0; + uword64 mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); + address_word reverseendian = + (ReverseEndian ?(mask ^ AccessLength_WORD): 0); + address_word bigendiancpu = + (BigEndianCPU ?(mask ^ AccessLength_WORD): 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian)); + byte = ((vaddr & mask) ^ bigendiancpu); + memval = (((uword64)COP_SW(1, ft)) << (8 * byte)); + StoreMemory (uncached, AccessLength_WORD, memval, memval1, paddr, + vaddr, isREAL); + } + } + } +} + +:function:::void:do_swxc1:int fs, int rindex, int rbase, address_word instruction_0 +{ + address_word base = GPR[rbase]; + address_word index = GPR[rindex]; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + { + address_word vaddr = loadstore_ea (SD_, base, index); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + { + SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, write_transfer, + sim_core_unaligned_signal); + } + else + { + if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, + isTARGET, isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); + address_word reverseendian = + (ReverseEndian ? (mask ^ AccessLength_WORD) : 0); + address_word bigendiancpu = + (BigEndianCPU ? (mask ^ AccessLength_WORD) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian)); + byte = ((vaddr & mask) ^ bigendiancpu); + memval = (((unsigned64)COP_SW(1,fs)) << (8 * byte)); + StoreMemory (uncached, AccessLength_WORD, memval, memval1, paddr, + vaddr, isREAL); + } + } + } +} + +:function:::void:do_trunc_fmt:int type, int fmt, int fd, int fs +{ + check_fpu (SD_); + StoreFPR (fd, type, Convert (FP_RM_TOZERO, ValueFPR (fs, fmt), fmt, + type)); +} 000000,5.RS,5.RT,5.RD,00000,100000:SPECIAL:32::ADD "add r<RD>, r<RS>, r<RT>" @@ -519,15 +1806,7 @@ *vr5000: *r3900: { - if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - { - ALU32_BEGIN (GPR[RS]); - ALU32_ADD (GPR[RT]); - ALU32_END (GPR[RD]); /* This checks for overflow. */ - } - TRACE_ALU_RESULT (GPR[RD]); + do_add (SD_, RS, RT, RD); } @@ -547,15 +1826,7 @@ *vr5000: *r3900: { - if (NotWordValue (GPR[RS])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], EXTEND16 (IMMEDIATE)); - { - ALU32_BEGIN (GPR[RS]); - ALU32_ADD (EXTEND16 (IMMEDIATE)); - ALU32_END (GPR[RT]); /* This checks for overflow. */ - } - TRACE_ALU_RESULT (GPR[RT]); + do_addi (SD_, RS, RT, IMMEDIATE); } @@ -660,9 +1931,7 @@ *vr5000: *r3900: { - TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE); - GPR[RT] = GPR[RS] & IMMEDIATE; - TRACE_ALU_RESULT (GPR[RT]); + do_andi (SD_,RS, RT, IMMEDIATE); } @@ -1096,30 +2365,7 @@ *vr5000: *r3900: { - /* Check for some break instruction which are reserved for use by the simulator. */ - unsigned int break_code = instruction_0 & HALT_INSTRUCTION_MASK; - if (break_code == (HALT_INSTRUCTION & HALT_INSTRUCTION_MASK) || - break_code == (HALT_INSTRUCTION2 & HALT_INSTRUCTION_MASK)) - { - sim_engine_halt (SD, CPU, NULL, cia, - sim_exited, (unsigned int)(A0 & 0xFFFFFFFF)); - } - else if (break_code == (BREAKPOINT_INSTRUCTION & HALT_INSTRUCTION_MASK) || - break_code == (BREAKPOINT_INSTRUCTION2 & HALT_INSTRUCTION_MASK)) - { - if (STATE & simDELAYSLOT) - PC = cia - 4; /* reference the branch instruction */ - else - PC = cia; - SignalException (BreakPoint, instruction_0); - } - - else - { - /* If we get this far, we're not an instruction reserved by the sim. Raise - the exception. */ - SignalException (BreakPoint, instruction_0); - } + do_break (SD_, instruction_0); } @@ -1132,21 +2378,9 @@ *mips64r2: *vr5500: { - unsigned32 temp = GPR[RS]; - unsigned32 i, mask; if (RT != RD) Unpredictable (); - if (NotWordValue (GPR[RS])) - Unpredictable (); - TRACE_ALU_INPUT1 (GPR[RS]); - for (mask = ((unsigned32)1<<31), i = 0; i < 32; ++i) - { - if ((temp & mask) == 0) - break; - mask >>= 1; - } - GPR[RD] = EXTEND32 (i); - TRACE_ALU_RESULT (GPR[RD]); + do_clo (SD_, RD, RS); } @@ -1159,21 +2393,9 @@ *mips64r2: *vr5500: { - unsigned32 temp = GPR[RS]; - unsigned32 i, mask; if (RT != RD) Unpredictable (); - if (NotWordValue (GPR[RS])) - Unpredictable (); - TRACE_ALU_INPUT1 (GPR[RS]); - for (mask = ((unsigned32)1<<31), i = 0; i < 32; ++i) - { - if ((temp & mask) != 0) - break; - mask >>= 1; - } - GPR[RD] = EXTEND32 (i); - TRACE_ALU_RESULT (GPR[RD]); + do_clz (SD_, RD, RS); } @@ -1189,13 +2411,7 @@ *vr5000: { check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - { - ALU64_BEGIN (GPR[RS]); - ALU64_ADD (GPR[RT]); - ALU64_END (GPR[RD]); /* This checks for overflow. */ - } - TRACE_ALU_RESULT (GPR[RD]); + do_dadd (SD_, RD, RS, RT); } @@ -1211,13 +2427,7 @@ *vr5000: { check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT2 (GPR[RS], EXTEND16 (IMMEDIATE)); - { - ALU64_BEGIN (GPR[RS]); - ALU64_ADD (EXTEND16 (IMMEDIATE)); - ALU64_END (GPR[RT]); /* This checks for overflow. */ - } - TRACE_ALU_RESULT (GPR[RT]); + do_daddi (SD_, RT, RS, IMMEDIATE); } @@ -1274,21 +2484,10 @@ *mips64r2: *vr5500: { - unsigned64 temp = GPR[RS]; - unsigned32 i; - unsigned64 mask; - check_u64 (SD_, instruction_0); if (RT != RD) Unpredictable (); - TRACE_ALU_INPUT1 (GPR[RS]); - for (mask = ((unsigned64)1<<63), i = 0; i < 64; ++i) - { - if ((temp & mask) == 0) - break; - mask >>= 1; - } - GPR[RD] = EXTEND32 (i); - TRACE_ALU_RESULT (GPR[RD]); + check_u64 (SD_, instruction_0); + do_dclo (SD_, RD, RS); } @@ -1299,21 +2498,10 @@ *mips64r2: *vr5500: { - unsigned64 temp = GPR[RS]; - unsigned32 i; - unsigned64 mask; - check_u64 (SD_, instruction_0); if (RT != RD) Unpredictable (); - TRACE_ALU_INPUT1 (GPR[RS]); - for (mask = ((unsigned64)1<<63), i = 0; i < 64; ++i) - { - if ((temp & mask) != 0) - break; - mask >>= 1; - } - GPR[RD] = EXTEND32 (i); - TRACE_ALU_RESULT (GPR[RD]); + check_u64 (SD_, instruction_0); + do_dclz (SD_, RD, RS); } @@ -1680,11 +2868,8 @@ *vr4100: *vr5000: { - int s = 32 + SHIFT; check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT2 (GPR[RT], s); - GPR[RD] = GPR[RT] << s; - TRACE_ALU_RESULT (GPR[RD]); + do_dsll32 (SD_, RD, RT, SHIFT); } :function:::void:do_dsllv:int rs, int rt, int rd @@ -1742,11 +2927,8 @@ *vr4100: *vr5000: { - int s = 32 + SHIFT; check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT2 (GPR[RT], s); - GPR[RD] = ((signed64) GPR[RT]) >> s; - TRACE_ALU_RESULT (GPR[RD]); + do_dsra32 (SD_, RD, RT, SHIFT); } @@ -1805,11 +2987,8 @@ *vr4100: *vr5000: { - int s = 32 + SHIFT; check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT2 (GPR[RT], s); - GPR[RD] = (unsigned64) GPR[RT] >> s; - TRACE_ALU_RESULT (GPR[RD]); + do_dsrl32 (SD_, RD, RT, SHIFT); } @@ -1849,13 +3028,7 @@ *vr5000: { check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - { - ALU64_BEGIN (GPR[RS]); - ALU64_SUB (GPR[RT]); - ALU64_END (GPR[RD]); /* This checks for overflow. */ - } - TRACE_ALU_RESULT (GPR[RD]); + do_dsub (SD_, RD, RS, RT); } @@ -2108,7 +3281,7 @@ *vr5000: *r3900: { - GPR[RT] = EXTEND8 (do_load (SD_, AccessLength_BYTE, GPR[BASE], EXTEND16 (OFFSET))); + do_lb (SD_,RT,OFFSET,BASE); } @@ -2127,7 +3300,7 @@ *vr5000: *r3900: { - GPR[RT] = do_load (SD_, AccessLength_BYTE, GPR[BASE], EXTEND16 (OFFSET)); + do_lbu (SD_, RT,OFFSET,BASE); } @@ -2160,7 +3333,7 @@ *vr5000: *r3900: { - COP_LD (ZZ, RT, do_load (SD_, AccessLength_DOUBLEWORD, GPR[BASE], EXTEND16 (OFFSET))); + do_ldc (SD_, ZZ, RT, OFFSET, BASE); } @@ -2211,7 +3384,7 @@ *vr5000: *r3900: { - GPR[RT] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[BASE], EXTEND16 (OFFSET))); + do_lh (SD_,RT,OFFSET,BASE); } @@ -2230,7 +3403,7 @@ *vr5000: *r3900: { - GPR[RT] = do_load (SD_, AccessLength_HALFWORD, GPR[BASE], EXTEND16 (OFFSET)); + do_lhu (SD_,RT,OFFSET,BASE); } @@ -2247,35 +3420,7 @@ *vr4100: *vr5000: { - address_word base = GPR[BASE]; - address_word offset = EXTEND16 (OFFSET); - { - address_word vaddr = loadstore_ea (SD_, base, offset); - address_word paddr; - int uncached; - if ((vaddr & 3) != 0) - { - SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, read_transfer, sim_core_unaligned_signal); - } - else - { - if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) - { - unsigned64 memval = 0; - unsigned64 memval1 = 0; - unsigned64 mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); - unsigned int shift = 2; - unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); - unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); - unsigned int byte; - paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); - LoadMemory(&memval,&memval1,uncached,AccessLength_WORD,paddr,vaddr,isDATA,isREAL); - byte = ((vaddr & mask) ^ (bigend << shift)); - GPR[RT] = EXTEND32 (memval >> (8 * byte)); - LLBIT = 1; - } - } - } + do_ll (SD_, RT, OFFSET, BASE); } @@ -2289,29 +3434,8 @@ *vr4100: *vr5000: { - address_word base = GPR[BASE]; - address_word offset = EXTEND16 (OFFSET); check_u64 (SD_, instruction_0); - { - address_word vaddr = loadstore_ea (SD_, base, offset); - address_word paddr; - int uncached; - if ((vaddr & 7) != 0) - { - SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 8, vaddr, read_transfer, sim_core_unaligned_signal); - } - else - { - if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) - { - unsigned64 memval = 0; - unsigned64 memval1 = 0; - LoadMemory(&memval,&memval1,uncached,AccessLength_DOUBLEWORD,paddr,vaddr,isDATA,isREAL); - GPR[RT] = memval; - LLBIT = 1; - } - } - } + do_lld (SD_, RT, OFFSET, BASE); } @@ -2330,9 +3454,7 @@ *vr5000: *r3900: { - TRACE_ALU_INPUT1 (IMMEDIATE); - GPR[RT] = EXTEND32 (IMMEDIATE << 16); - TRACE_ALU_RESULT (GPR[RT]); + do_lui (SD_, RT, IMMEDIATE); } @@ -2351,7 +3473,7 @@ *vr5000: *r3900: { - GPR[RT] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET))); + do_lw (SD_,RT,OFFSET,BASE); } @@ -2370,7 +3492,7 @@ *vr5000: *r3900: { - COP_LW (ZZ, RT, do_load (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET))); + do_lwc (SD_, ZZ, RT, OFFSET, BASE); } @@ -2389,7 +3511,7 @@ *vr5000: *r3900: { - GPR[RT] = EXTEND32 (do_load_left (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET), GPR[RT])); + do_lwl (SD_, RT, OFFSET, BASE); } @@ -2408,7 +3530,7 @@ *vr5000: *r3900: { - GPR[RT] = EXTEND32 (do_load_right (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET), GPR[RT])); + do_lwr (SD_, RT, OFFSET, BASE); } @@ -2422,8 +3544,7 @@ *vr4100: *vr5000: { - check_u64 (SD_, instruction_0); - GPR[RT] = do_load (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET)); + do_lwu (SD_, RT, OFFSET, BASE, instruction_0); } @@ -2434,16 +3555,7 @@ *mips64: *vr5500: { - signed64 temp; - check_mult_hilo (SD_, HIHISTORY, LOHISTORY); - if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - temp = (U8_4 (VL4_8 (HI), VL4_8 (LO)) - + ((signed64) EXTEND32 (GPR[RT]) * (signed64) EXTEND32 (GPR[RS]))); - LO = EXTEND32 (temp); - HI = EXTEND32 (VH4_8 (temp)); - TRACE_ALU_RESULT2 (HI, LO); + do_madd (SD_, RS, RT); } @@ -2454,18 +3566,7 @@ *mips64r2: *dsp2: { - signed64 temp; - if (AC == 0) - check_mult_hilo (SD_, HIHISTORY, LOHISTORY); - if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - temp = (U8_4 (VL4_8 (DSPHI(AC)), VL4_8 (DSPLO(AC))) - + ((signed64) EXTEND32 (GPR[RT]) * (signed64) EXTEND32 (GPR[RS]))); - DSPLO(AC) = EXTEND32 (temp); - DSPHI(AC) = EXTEND32 (VH4_8 (temp)); - if (AC == 0) - TRACE_ALU_RESULT2 (HI, LO); + do_dsp_madd (SD_, AC, RS, RT); } @@ -2475,17 +3576,7 @@ *mips64: *vr5500: { - unsigned64 temp; - check_mult_hilo (SD_, HIHISTORY, LOHISTORY); - if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - temp = (U8_4 (VL4_8 (HI), VL4_8 (LO)) - + ((unsigned64) VL4_8 (GPR[RS]) * (unsigned64) VL4_8 (GPR[RT]))); - ACX += U8_4 (VL4_8 (HI), VL4_8 (LO)) < temp; /* SmartMIPS */ - LO = EXTEND32 (temp); - HI = EXTEND32 (VH4_8 (temp)); - TRACE_ALU_RESULT2 (HI, LO); + do_maddu (SD_, RS, RT); } @@ -2496,20 +3587,7 @@ *mips64r2: *dsp2: { - unsigned64 temp; - if (AC == 0) - check_mult_hilo (SD_, HIHISTORY, LOHISTORY); - if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - temp = (U8_4 (VL4_8 (DSPHI(AC)), VL4_8 (DSPLO(AC))) - + ((unsigned64) VL4_8 (GPR[RS]) * (unsigned64) VL4_8 (GPR[RT]))); - if (AC == 0) - ACX += U8_4 (VL4_8 (HI), VL4_8 (LO)) < temp; /* SmartMIPS */ - DSPLO(AC) = EXTEND32 (temp); - DSPHI(AC) = EXTEND32 (VH4_8 (temp)); - if (AC == 0) - TRACE_ALU_RESULT2 (HI, LO); + do_dsp_maddu (SD_, AC, RS, RT); } @@ -2545,10 +3623,7 @@ *mips64r2: *dsp: { - if (AC == 0) - do_mfhi (SD_, RD); - else - GPR[RD] = DSPHI(AC); + do_dsp_mfhi (SD_, AC, RD); } @@ -2584,10 +3659,7 @@ *mips64r2: *dsp: { - if (AC == 0) - do_mflo (SD_, RD); - else - GPR[RD] = DSPLO(AC); + do_dsp_mflo (SD_, AC, RD); } @@ -2601,11 +3673,7 @@ *mips64r2: *vr5000: { - if (GPR[RT] != 0) - { - GPR[RD] = GPR[RS]; - TRACE_ALU_RESULT (GPR[RD]); - } + do_movn (SD_, RD, RS, RT); } @@ -2620,11 +3688,7 @@ *mips64r2: *vr5000: { - if (GPR[RT] == 0) - { - GPR[RD] = GPR[RS]; - TRACE_ALU_RESULT (GPR[RD]); - } + do_movz (SD_, RD, RS, RT); } @@ -2635,16 +3699,7 @@ *mips64: *vr5500: { - signed64 temp; - check_mult_hilo (SD_, HIHISTORY, LOHISTORY); - if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - temp = (U8_4 (VL4_8 (HI), VL4_8 (LO)) - - ((signed64) EXTEND32 (GPR[RT]) * (signed64) EXTEND32 (GPR[RS]))); - LO = EXTEND32 (temp); - HI = EXTEND32 (VH4_8 (temp)); - TRACE_ALU_RESULT2 (HI, LO); + do_msub (SD_, RS, RT); } @@ -2655,18 +3710,7 @@ *mips64r2: *dsp2: { - signed64 temp; - if (AC == 0) - check_mult_hilo (SD_, HIHISTORY, LOHISTORY); - if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - temp = (U8_4 (VL4_8 (DSPHI(AC)), VL4_8 (DSPLO(AC))) - - ((signed64) EXTEND32 (GPR[RT]) * (signed64) EXTEND32 (GPR[RS]))); - DSPLO(AC) = EXTEND32 (temp); - DSPHI(AC) = EXTEND32 (VH4_8 (temp)); - if (AC == 0) - TRACE_ALU_RESULT2 (HI, LO); + do_dsp_msub (SD_, AC, RS, RT); } @@ -2676,16 +3720,7 @@ *mips64: *vr5500: { - unsigned64 temp; - check_mult_hilo (SD_, HIHISTORY, LOHISTORY); - if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - temp = (U8_4 (VL4_8 (HI), VL4_8 (LO)) - - ((unsigned64) VL4_8 (GPR[RS]) * (unsigned64) VL4_8 (GPR[RT]))); - LO = EXTEND32 (temp); - HI = EXTEND32 (VH4_8 (temp)); - TRACE_ALU_RESULT2 (HI, LO); + do_msubu (SD_, RS, RT); } @@ -2696,18 +3731,7 @@ *mips64r2: *dsp2: { - unsigned64 temp; - if (AC == 0) - check_mult_hilo (SD_, HIHISTORY, LOHISTORY); - if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - temp = (U8_4 (VL4_8 (DSPHI(AC)), VL4_8 (DSPLO(AC))) - - ((unsigned64) VL4_8 (GPR[RS]) * (unsigned64) VL4_8 (GPR[RT]))); - DSPLO(AC) = EXTEND32 (temp); - DSPHI(AC) = EXTEND32 (VH4_8 (temp)); - if (AC == 0) - TRACE_ALU_RESULT2 (HI, LO); + do_dsp_msubu (SD_, AC, RS, RT); } @@ -2724,8 +3748,7 @@ *mips32: *mips64: { - check_mt_hilo (SD_, HIHISTORY); - HI = GPR[RS]; + do_mthi (SD_, RS); } @@ -2736,9 +3759,7 @@ *mips64r2: *dsp: { - if (AC == 0) - check_mt_hilo (SD_, HIHISTORY); - DSPHI(AC) = GPR[RS]; + do_dsp_mthi (SD_, AC, RS); } @@ -2755,8 +3776,7 @@ *mips32: *mips64: { - check_mt_hilo (SD_, LOHISTORY); - LO = GPR[RS]; + do_mtlo (SD_, RS); } @@ -2767,9 +3787,7 @@ *mips64r2: *dsp: { - if (AC == 0) - check_mt_hilo (SD_, LOHISTORY); - DSPLO(AC) = GPR[RS]; + do_dsp_mtlo (SD_, AC, RS); } @@ -2781,14 +3799,7 @@ *mips64r2: *vr5500: { - signed64 prod; - if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - prod = (((signed64)(signed32) GPR[RS]) - * ((signed64)(signed32) GPR[RT])); - GPR[RD] = EXTEND32 (VL4_8 (prod)); - TRACE_ALU_RESULT (GPR[RD]); + do_mul (SD_, RD, RS, RT); } @@ -2832,21 +3843,7 @@ *mips64r2: *dsp2: { - signed64 prod; - if (AC == 0) - check_mult_hilo (SD_, HIHISTORY, LOHISTORY); - if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - prod = ((signed64)(signed32) GPR[RS]) - * ((signed64)(signed32) GPR[RT]); - DSPLO(AC) = EXTEND32 (VL4_8 (prod)); - DSPHI(AC) = EXTEND32 (VH4_8 (prod)); - if (AC == 0) - { - ACX = 0; /* SmartMIPS */ - TRACE_ALU_RESULT2 (HI, LO); - } + do_dsp_mult (SD_, AC, RS, RT); } @@ -2898,18 +3895,7 @@ *mips64r2: *dsp2: { - unsigned64 prod; - if (AC == 0) - check_mult_hilo (SD_, HIHISTORY, LOHISTORY); - if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - prod = ((unsigned64)(unsigned32) GPR[RS]) - * ((unsigned64)(unsigned32) GPR[RT]); - DSPLO(AC) = EXTEND32 (VL4_8 (prod)); - DSPHI(AC) = EXTEND32 (VH4_8 (prod)); - if (AC == 0) - TRACE_ALU_RESULT2 (HI, LO); + do_dsp_multu (SD_, AC, RS, RT); } @@ -3012,17 +3998,7 @@ *mips64r2: *vr5000: { - address_word base = GPR[BASE]; - address_word offset = EXTEND16 (OFFSET); - { - address_word vaddr = loadstore_ea (SD_, base, offset); - address_word paddr; - int uncached; - { - if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) - Prefetch(uncached,paddr,vaddr,isDATA,HINT); - } - } + do_pref (SD_, HINT, OFFSET, BASE); } @@ -3182,38 +4158,7 @@ *vr4100: *vr5000: { - unsigned32 instruction = instruction_0; - address_word base = GPR[BASE]; - address_word offset = EXTEND16 (OFFSET); - { - address_word vaddr = loadstore_ea (SD_, base, offset); - address_word paddr; - int uncached; - if ((vaddr & 3) != 0) - { - SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, write_transfer, sim_core_unaligned_signal); - } - else - { - if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) - { - unsigned64 memval = 0; - unsigned64 memval1 = 0; - unsigned64 mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); - address_word reverseendian = (ReverseEndian ? (mask ^ AccessLength_WORD) : 0); - address_word bigendiancpu = (BigEndianCPU ? (mask ^ AccessLength_WORD) : 0); - unsigned int byte; - paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian)); - byte = ((vaddr & mask) ^ bigendiancpu); - memval = ((unsigned64) GPR[RT] << (8 * byte)); - if (LLBIT) - { - StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); - } - GPR[RT] = LLBIT; - } - } - } + do_sc (SD_, RT, OFFSET, BASE, instruction_0); } @@ -3227,32 +4172,8 @@ *vr4100: *vr5000: { - address_word base = GPR[BASE]; - address_word offset = EXTEND16 (OFFSET); check_u64 (SD_, instruction_0); - { - address_word vaddr = loadstore_ea (SD_, base, offset); - address_word paddr; - int uncached; - if ((vaddr & 7) != 0) - { - SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 8, vaddr, write_transfer, sim_core_unaligned_signal); - } - else - { - if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) - { - unsigned64 memval = 0; - unsigned64 memval1 = 0; - memval = GPR[RT]; - if (LLBIT) - { - StoreMemory(uncached,AccessLength_DOUBLEWORD,memval,memval1,paddr,vaddr,isREAL); - } - GPR[RT] = LLBIT; - } - } - } + do_scd (SD_, RT, OFFSET, BASE); } @@ -3648,15 +4569,7 @@ *vr5000: *r3900: { - if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) - Unpredictable (); - TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); - { - ALU32_BEGIN (GPR[RS]); - ALU32_SUB (GPR[RT]); - ALU32_END (GPR[RD]); /* This checks for overflow. */ - } - TRACE_ALU_RESULT (GPR[RD]); + do_sub (SD_, RD, RS, RT); } @@ -3703,7 +4616,7 @@ *r3900: *vr5000: { - do_store (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET), GPR[RT]); + do_sw (SD_, RT, OFFSET, BASE); } @@ -3815,8 +4728,7 @@ *vr4100: *vr5000: { - if ((signed_word) GPR[RS] == (signed_word) GPR[RT]) - SignalException (Trap, instruction_0); + do_teq (SD_, RS, RT, instruction_0); } @@ -3833,8 +4745,7 @@ *vr4100: *vr5000: { - if ((signed_word) GPR[RS] == (signed_word) EXTEND16 (IMMEDIATE)) - SignalException (Trap, instruction_0); + do_teqi (SD_, RS, IMMEDIATE, instruction_0); } @@ -3851,8 +4762,7 @@ *vr4100: *vr5000: { - if ((signed_word) GPR[RS] >= (signed_word) GPR[RT]) - SignalException (Trap, instruction_0); + do_tge (SD_, RS, RT, instruction_0); } @@ -3869,8 +4779,7 @@ *vr4100: *vr5000: { - if ((signed_word) GPR[RS] >= (signed_word) EXTEND16 (IMMEDIATE)) - SignalException (Trap, instruction_0); + do_tgei (SD_, RS, IMMEDIATE, instruction_0); } @@ -3887,8 +4796,7 @@ *vr4100: *vr5000: { - if ((unsigned_word) GPR[RS] >= (unsigned_word) EXTEND16 (IMMEDIATE)) - SignalException (Trap, instruction_0); + do_tgeiu (SD_, RS, IMMEDIATE, instruction_0); } @@ -3905,8 +4813,7 @@ *vr4100: *vr5000: { - if ((unsigned_word) GPR[RS] >= (unsigned_word) GPR[RT]) - SignalException (Trap, instruction_0); + do_tgeu (SD_, RS, RT, instruction_0); } @@ -3923,8 +4830,7 @@ *vr4100: *vr5000: { - if ((signed_word) GPR[RS] < (signed_word) GPR[RT]) - SignalException (Trap, instruction_0); + do_tlt (SD_, RS, RT, instruction_0); } @@ -3941,8 +4847,7 @@ *vr4100: *vr5000: { - if ((signed_word) GPR[RS] < (signed_word) EXTEND16 (IMMEDIATE)) - SignalException (Trap, instruction_0); + do_tlti (SD_, RS, IMMEDIATE, instruction_0); } @@ -3959,8 +4864,7 @@ *vr4100: *vr5000: { - if ((unsigned_word) GPR[RS] < (unsigned_word) EXTEND16 (IMMEDIATE)) - SignalException (Trap, instruction_0); + do_tltiu (SD_, RS, IMMEDIATE, instruction_0); } @@ -3977,8 +4881,7 @@ *vr4100: *vr5000: { - if ((unsigned_word) GPR[RS] < (unsigned_word) GPR[RT]) - SignalException (Trap, instruction_0); + do_tltu (SD_, RS, RT, instruction_0); } @@ -3995,8 +4898,7 @@ *vr4100: *vr5000: { - if ((signed_word) GPR[RS] != (signed_word) GPR[RT]) - SignalException (Trap, instruction_0); + do_tne (SD_, RS, RT, instruction_0); } @@ -4013,8 +4915,7 @@ *vr4100: *vr5000: { - if ((signed_word) GPR[RS] != (signed_word) EXTEND16 (IMMEDIATE)) - SignalException (Trap, instruction_0); + do_tnei (SD_, RS, IMMEDIATE, instruction_0); } @@ -4156,6 +5057,7 @@ :function:::void:check_fmt_p:int fmt, instruction_word insn *mips32r2: +*micromips32: { if ((fmt != fmt_single) && (fmt != fmt_double) && (fmt != fmt_ps)) SignalException (ReservedInstruction, insn); @@ -4165,6 +5067,7 @@ *mipsV: *mips64: *mips64r2: +*micromips64: { if ((fmt != fmt_single) && (fmt != fmt_double) && (fmt != fmt_ps || (UserMode && (SR & (status_UX|status_PX)) == 0))) @@ -4191,6 +5094,8 @@ *vr4100: *vr5000: *r3900: +*micromips32: +*micromips64: { if (! COP_Usable (1)) SignalExceptionCoProcessorUnusable (1); @@ -4208,6 +5113,7 @@ *mipsII: *mips32: *mips32r2: +*micromips32: { int bigendian = (BigEndianCPU ? ! ReverseEndian : ReverseEndian); address_word vaddr; @@ -4245,6 +5151,7 @@ *mipsII: *mips32: *mips32r2: +*micromips32: { int bigendian = (BigEndianCPU ? ! ReverseEndian : ReverseEndian); address_word vaddr; @@ -4285,10 +5192,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - check_fmt_p (SD_, fmt, instruction_0); - StoreFPR (FD, fmt, AbsoluteValue (ValueFPR (FS, fmt), fmt)); + do_abs_fmt (SD_, FMT, FD, FS, instruction_0); } @@ -4308,10 +5212,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - check_fmt_p (SD_, fmt, instruction_0); - StoreFPR (FD, fmt, Add (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt)); + do_add_fmt (SD_, FMT, FD, FS, FT, instruction_0); } @@ -4322,25 +5223,7 @@ *mips64: *mips64r2: { - unsigned64 fs; - unsigned64 ft; - unsigned64 fd; - check_fpu (SD_); - check_u64 (SD_, instruction_0); - fs = ValueFPR (FS, fmt_ps); - if ((GPR[RS] & 0x3) != 0) - Unpredictable (); - if ((GPR[RS] & 0x4) == 0) - fd = fs; - else - { - ft = ValueFPR (FT, fmt_ps); - if (BigEndianCPU) - fd = PackPS (PSLower (fs), PSUpper (ft)); - else - fd = PackPS (PSLower (ft), PSUpper (fs)); - } - StoreFPR (FD, fmt_ps, fd); + do_alnv_ps (SD_, FD, FS, FT, RS, instruction_0); } @@ -4425,11 +5308,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - check_fmt_p (SD_, fmt, instruction_0); - Compare (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt, COND, CC); - TRACE_ALU_RESULT (ValueFCR (31)); + do_c_cond_fmt (SD_, COND, FMT, CC, FS, FT, instruction_0); } @@ -4445,10 +5324,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - StoreFPR (FD, fmt_long, Convert (FP_RM_TOPINF, ValueFPR (FS, fmt), fmt, - fmt_long)); + do_ceil_fmt (SD_, fmt_long, FMT, FD, FS, instruction_0); } @@ -4466,10 +5342,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - StoreFPR (FD, fmt_word, Convert (FP_RM_TOPINF, ValueFPR (FS, fmt), fmt, - fmt_word)); + do_ceil_fmt (SD_, fmt_word, FMT, FD, FS, instruction_0); } @@ -4513,15 +5386,7 @@ *mips64: *mips64r2: { - check_fpu (SD_); - if (FS == 0 || FS == 25 || FS == 26 || FS == 28 || FS == 31) - { - unsigned_word fcr = ValueFCR (FS); - TRACE_ALU_INPUT1 (fcr); - GPR[RT] = fcr; - } - /* else NOP */ - TRACE_ALU_RESULT (GPR[RT]); + do_cfc1 (SD_, RT, FS); } 010001,00110,5.RT,5.FS,00000000000:COP1:32,f::CTC1a @@ -4558,11 +5423,7 @@ *mips64: *mips64r2: { - check_fpu (SD_); - TRACE_ALU_INPUT1 (GPR[RT]); - if (FS == 25 || FS == 26 || FS == 28 || FS == 31) - StoreFCR (FS, GPR[RT]); - /* else NOP */ + do_ctc1 (SD_, RT, FS); } @@ -4584,12 +5445,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - if ((fmt == fmt_double) | 0) - SignalException (ReservedInstruction, instruction_0); - StoreFPR (FD, fmt_double, Convert (GETRM (), ValueFPR (FS, fmt), fmt, - fmt_double)); + do_cvt_d_fmt (SD_, FMT, FD, FS, instruction_0); } @@ -4605,12 +5461,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - if ((fmt == fmt_long) | ((fmt == fmt_long) || (fmt == fmt_word))) - SignalException (ReservedInstruction, instruction_0); - StoreFPR (FD, fmt_long, Convert (GETRM (), ValueFPR (FS, fmt), fmt, - fmt_long)); + do_cvt_l_fmt (SD_, FMT, FD, FS, instruction_0); } @@ -4621,10 +5472,7 @@ *mips64: *mips64r2: { - check_fpu (SD_); - check_u64 (SD_, instruction_0); - StoreFPR (FD, fmt_ps, PackPS (ValueFPR (FS, fmt_single), - ValueFPR (FT, fmt_single))); + do_cvt_ps_s (SD_, FD, FS, FT, instruction_0); } @@ -4646,12 +5494,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - if ((fmt == fmt_single) | 0) - SignalException (ReservedInstruction, instruction_0); - StoreFPR (FD, fmt_single, Convert (GETRM (), ValueFPR (FS, fmt), fmt, - fmt_single)); + do_cvt_s_fmt (SD_, FMT, FD, FS, instruction_0); } @@ -4662,9 +5505,7 @@ *mips64: *mips64r2: { - check_fpu (SD_); - check_u64 (SD_, instruction_0); - StoreFPR (FD, fmt_single, PSLower (ValueFPR (FS, fmt_ps))); + do_cvt_s_pl (SD_, FD, FS, instruction_0); } @@ -4675,9 +5516,7 @@ *mips64: *mips64r2: { - check_fpu (SD_); - check_u64 (SD_, instruction_0); - StoreFPR (FD, fmt_single, PSUpper (ValueFPR (FS, fmt_ps))); + do_cvt_s_pu (SD_, FD, FS, instruction_0); } @@ -4696,12 +5535,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - if ((fmt == fmt_word) | ((fmt == fmt_long) || (fmt == fmt_word))) - SignalException (ReservedInstruction, instruction_0); - StoreFPR (FD, fmt_word, Convert (GETRM (), ValueFPR (FS, fmt), fmt, - fmt_word)); + do_cvt_w_fmt (SD_, FMT, FD, FS, instruction_0); } @@ -4720,9 +5554,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - StoreFPR (FD, fmt, Divide (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt)); + do_div_fmt (SD_, FMT, FD, FS, FT, instruction_0); } @@ -4755,13 +5587,7 @@ { check_fpu (SD_); check_u64 (SD_, instruction_0); - if (SizeFGR () == 64) - GPR[RT] = FGR[FS]; - else if ((FS & 0x1) == 0) - GPR[RT] = SET64HI (FGR[FS+1]) | FGR[FS]; - else - GPR[RT] = SET64HI (0xDEADC0DE) | 0xBAD0BAD0; - TRACE_ALU_RESULT (GPR[RT]); + do_dmfc1b (SD_, RT, FS); } @@ -4796,12 +5622,7 @@ { check_fpu (SD_); check_u64 (SD_, instruction_0); - if (SizeFGR () == 64) - StoreFPR (FS, fmt_uninterpreted_64, GPR[RT]); - else if ((FS & 0x1) == 0) - StoreFPR (FS, fmt_uninterpreted_64, GPR[RT]); - else - Unpredictable (); + do_dmtc1b (SD_, RT, FS); } @@ -4817,10 +5638,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - StoreFPR (FD, fmt_long, Convert (FP_RM_TOMINF, ValueFPR (FS, fmt), fmt, - fmt_long)); + do_floor_fmt (SD_, fmt_long, FMT, FD, FS); } @@ -4838,10 +5656,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - StoreFPR (FD, fmt_word, Convert (FP_RM_TOMINF, ValueFPR (FS, fmt), fmt, - fmt_word)); + do_floor_fmt (SD_, fmt_word, FMT, FD, FS); } @@ -4899,16 +5714,7 @@ "luxc1 f<FD>, r<INDEX>(r<BASE>)" *mips32r2: { - address_word base = GPR[BASE]; - address_word index = GPR[INDEX]; - address_word vaddr = base + index; - check_fpu (SD_); - if (SizeFGR () != 64) - Unpredictable (); - /* Arrange for the bottom 3 bits of (base + index) to be 0. */ - if ((vaddr & 0x7) != 0) - index -= (vaddr & 0x7); - COP_LD (1, FD, do_load_double (SD_, base, index)); + do_luxc1_32 (SD_, FD, INDEX, BASE); } @@ -4918,17 +5724,9 @@ *mips64: *mips64r2: { - address_word base = GPR[BASE]; - address_word index = GPR[INDEX]; - address_word vaddr = base + index; check_fpu (SD_); check_u64 (SD_, instruction_0); - if (SizeFGR () != 64) - Unpredictable (); - /* Arrange for the bottom 3 bits of (base + index) to be 0. */ - if ((vaddr & 0x7) != 0) - index -= (vaddr & 0x7); - COP_LD (1, FD, do_load (SD_, AccessLength_DOUBLEWORD, base, index)); + do_luxc1_64 (SD_, FD, INDEX, BASE); } @@ -4947,8 +5745,7 @@ *vr5000: *r3900: { - check_fpu (SD_); - COP_LW (1, FT, do_load (SD_, AccessLength_WORD, GPR[BASE], EXTEND16 (OFFSET))); + do_lwc1 (SD_, FT, OFFSET, BASE); } @@ -4961,9 +5758,7 @@ *mips64r2: *vr5000: { - check_fpu (SD_); - check_u64 (SD_, instruction_0); - COP_LW (1, FD, do_load (SD_, AccessLength_WORD, GPR[BASE], GPR[INDEX])); + do_lwxc1 (SD_, FD, INDEX, BASE, instruction_0); } @@ -4977,12 +5772,7 @@ *mips64r2: *vr5000: { - int fmt = FMT; - check_fpu (SD_); - check_u64 (SD_, instruction_0); - check_fmt_p (SD_, fmt, instruction_0); - StoreFPR (FD, fmt, MultiplyAdd (ValueFPR (FS, fmt), ValueFPR (FT, fmt), - ValueFPR (FR, fmt), fmt)); + do_madd_fmt (SD_, FMT, FD, FR, FS, FT, instruction_0); } @@ -5011,9 +5801,7 @@ *vr5000: *r3900: { - check_fpu (SD_); - GPR[RT] = EXTEND32 (FGR[FS]); - TRACE_ALU_RESULT (GPR[RT]); + do_mfc1b (SD_, RT, FS); } @@ -5032,10 +5820,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - check_fmt_p (SD_, fmt, instruction_0); - StoreFPR (FD, fmt, ValueFPR (FS, fmt)); + do_mov_fmt (SD_, FMT, FD, FS, instruction_0); } @@ -5051,9 +5836,7 @@ *mips64r2: *vr5000: { - check_fpu (SD_); - if (GETFCC(CC) == TF) - GPR[RD] = GPR[RS]; + do_movtf (SD_, TF, RD, RS, CC); } @@ -5069,24 +5852,7 @@ *mips64r2: *vr5000: { - int fmt = FMT; - check_fpu (SD_); - if (fmt != fmt_ps) - { - if (GETFCC(CC) == TF) - StoreFPR (FD, fmt, ValueFPR (FS, fmt)); - else - StoreFPR (FD, fmt, ValueFPR (FD, fmt)); /* set fmt */ - } - else - { - unsigned64 fd; - fd = PackPS (PSUpper (ValueFPR ((GETFCC (CC+1) == TF) ? FS : FD, - fmt_ps)), - PSLower (ValueFPR ((GETFCC (CC+0) == TF) ? FS : FD, - fmt_ps))); - StoreFPR (FD, fmt_ps, fd); - } + do_movtf_fmt (SD_, TF, FMT, FD, FS, CC); } @@ -5100,11 +5866,7 @@ *mips64r2: *vr5000: { - check_fpu (SD_); - if (GPR[RT] != 0) - StoreFPR (FD, FMT, ValueFPR (FS, FMT)); - else - StoreFPR (FD, FMT, ValueFPR (FD, FMT)); + do_movn_fmt (SD_, FMT, FD, FS, RT); } @@ -5125,11 +5887,7 @@ *mips64r2: *vr5000: { - check_fpu (SD_); - if (GPR[RT] == 0) - StoreFPR (FD, FMT, ValueFPR (FS, FMT)); - else - StoreFPR (FD, FMT, ValueFPR (FD, FMT)); + do_movz_fmt (SD_, FMT, FD, FS, RT); } @@ -5142,12 +5900,7 @@ *mips64r2: *vr5000: { - int fmt = FMT; - check_fpu (SD_); - check_u64 (SD_, instruction_0); - check_fmt_p (SD_, fmt, instruction_0); - StoreFPR (FD, fmt, MultiplySub (ValueFPR (FS, fmt), ValueFPR (FT, fmt), - ValueFPR (FR, fmt), fmt)); + do_msub_fmt (SD_, FMT, FD, FR, FS, FT, instruction_0); } @@ -5177,8 +5930,7 @@ *vr5000: *r3900: { - check_fpu (SD_); - StoreFPR (FS, fmt_uninterpreted_32, VL4_8 (GPR[RT])); + do_mtc1b (SD_, RT, FS); } @@ -5197,10 +5949,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - check_fmt_p (SD_, fmt, instruction_0); - StoreFPR (FD, fmt, Multiply (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt)); + do_mul_fmt (SD_, FMT, FD, FS, FT, instruction_0); } @@ -5219,10 +5968,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - check_fmt_p (SD_, fmt, instruction_0); - StoreFPR (FD, fmt, Negate (ValueFPR (FS, fmt), fmt)); + do_neg_fmt (SD_, FMT, FD, FS, instruction_0); } @@ -5235,12 +5981,7 @@ *mips64r2: *vr5000: { - int fmt = FMT; - check_fpu (SD_); - check_u64 (SD_, instruction_0); - check_fmt_p (SD_, fmt, instruction_0); - StoreFPR (FD, fmt, NegMultiplyAdd (ValueFPR (FS, fmt), ValueFPR (FT, fmt), - ValueFPR (FR, fmt), fmt)); + do_nmadd_fmt (SD_, FMT, FD, FR, FS, FT, instruction_0); } @@ -5253,12 +5994,7 @@ *mips64r2: *vr5000: { - int fmt = FMT; - check_fpu (SD_); - check_u64 (SD_, instruction_0); - check_fmt_p (SD_, fmt, instruction_0); - StoreFPR (FD, fmt, NegMultiplySub (ValueFPR (FS, fmt), ValueFPR (FT, fmt), - ValueFPR (FR, fmt), fmt)); + do_nmsub_fmt (SD_, FMT, FD, FR, FS, FT, instruction_0); } @@ -5269,10 +6005,7 @@ *mips64: *mips64r2: { - check_fpu (SD_); - check_u64 (SD_, instruction_0); - StoreFPR (FD, fmt_ps, PackPS (PSLower (ValueFPR (FS, fmt_ps)), - PSLower (ValueFPR (FT, fmt_ps)))); + do_pll_ps (SD_, FD, FS, FT, instruction_0); } @@ -5283,10 +6016,7 @@ *mips64: *mips64r2: { - check_fpu (SD_); - check_u64 (SD_, instruction_0); - StoreFPR (FD, fmt_ps, PackPS (PSLower (ValueFPR (FS, fmt_ps)), - PSUpper (ValueFPR (FT, fmt_ps)))); + do_plu_ps (SD_, FD, FS, FT, instruction_0); } @@ -5299,15 +6029,7 @@ *mips64r2: *vr5000: { - address_word base = GPR[BASE]; - address_word index = GPR[INDEX]; - { - address_word vaddr = loadstore_ea (SD_, base, index); - address_word paddr; - int uncached; - if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) - Prefetch(uncached,paddr,vaddr,isDATA,HINT); - } + do_prefx (SD_, HINT, INDEX, BASE); } @@ -5318,10 +6040,7 @@ *mips64: *mips64r2: { - check_fpu (SD_); - check_u64 (SD_, instruction_0); - StoreFPR (FD, fmt_ps, PackPS (PSUpper (ValueFPR (FS, fmt_ps)), - PSLower (ValueFPR (FT, fmt_ps)))); + do_pul_ps (SD_, FD, FS, FT, instruction_0); } @@ -5332,10 +6051,7 @@ *mips64: *mips64r2: { - check_fpu (SD_); - check_u64 (SD_, instruction_0); - StoreFPR (FD, fmt_ps, PackPS (PSUpper (ValueFPR (FS, fmt_ps)), - PSUpper (ValueFPR (FT, fmt_ps)))); + do_puu_ps (SD_, FD, FS, FT, instruction_0); } @@ -5348,9 +6064,7 @@ *mips64r2: *vr5000: { - int fmt = FMT; - check_fpu (SD_); - StoreFPR (FD, fmt, Recip (ValueFPR (FS, fmt), fmt)); + do_recip_fmt (SD_, FMT, FD, FS); } @@ -5366,10 +6080,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - StoreFPR (FD, fmt_long, Convert (FP_RM_NEAREST, ValueFPR (FS, fmt), fmt, - fmt_long)); + do_round_fmt (SD_, fmt_long, FMT, FD, FS); } @@ -5387,10 +6098,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - StoreFPR (FD, fmt_word, Convert (FP_RM_NEAREST, ValueFPR (FS, fmt), fmt, - fmt_word)); + do_round_fmt (SD_, fmt_word, FMT, FD, FS); } @@ -5403,9 +6111,7 @@ *mips64r2: *vr5000: { - int fmt = FMT; - check_fpu (SD_); - StoreFPR (FD, fmt, RSquareRoot (ValueFPR (FS, fmt), fmt)); + do_rsqrt_fmt (SD_, FMT, FD, FS); } @@ -5415,8 +6121,7 @@ *mips32: *mips32r2: { - check_fpu (SD_); - do_store_double (SD_, GPR[BASE], EXTEND16 (OFFSET), COP_SD (1, FT)); + do_sdc1 (SD_, FT, OFFSET, BASE); } @@ -5463,16 +6168,7 @@ "suxc1 f<FS>, r<INDEX>(r<BASE>)" *mips32r2: { - address_word base = GPR[BASE]; - address_word index = GPR[INDEX]; - address_word vaddr = base + index; - check_fpu (SD_); - if (SizeFGR () != 64) - Unpredictable (); - /* Arrange for the bottom 3 bits of (base + index) to be 0. */ - if ((vaddr & 0x7) != 0) - index -= (vaddr & 0x7); - do_store_double (SD_, base, index, COP_SD (1, FS)); + do_suxc1_32 (SD_, FS, INDEX, BASE); } @@ -5482,17 +6178,9 @@ *mips64: *mips64r2: { - address_word base = GPR[BASE]; - address_word index = GPR[INDEX]; - address_word vaddr = base + index; check_fpu (SD_); check_u64 (SD_, instruction_0); - if (SizeFGR () != 64) - Unpredictable (); - /* Arrange for the bottom 3 bits of (base + index) to be 0. */ - if ((vaddr & 0x7) != 0) - index -= (vaddr & 0x7); - do_store (SD_, AccessLength_DOUBLEWORD, base, index, COP_SD (1, FS)); + do_suxc1_64 (SD_, FS, INDEX, BASE); } @@ -5510,9 +6198,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - StoreFPR (FD, fmt, (SquareRoot (ValueFPR (FS, fmt), fmt))); + do_sqrt_fmt (SD_, FMT, FD, FS); } @@ -5531,10 +6217,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - check_fmt_p (SD_, fmt, instruction_0); - StoreFPR (FD, fmt, Sub (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt)); + do_sub_fmt (SD_, FMT, FD, FS, FT, instruction_0); } @@ -5554,34 +6237,7 @@ *vr5000: *r3900: { - address_word base = GPR[BASE]; - address_word offset = EXTEND16 (OFFSET); - check_fpu (SD_); - { - address_word vaddr = loadstore_ea (SD_, base, offset); - address_word paddr; - int uncached; - if ((vaddr & 3) != 0) - { - SIM_CORE_SIGNAL (SD, CPU, cia, read_map, AccessLength_WORD+1, vaddr, write_transfer, sim_core_unaligned_signal); - } - else - { - if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) - { - uword64 memval = 0; - uword64 memval1 = 0; - uword64 mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); - address_word reverseendian = (ReverseEndian ?(mask ^ AccessLength_WORD): 0); - address_word bigendiancpu = (BigEndianCPU ?(mask ^ AccessLength_WORD): 0); - unsigned int byte; - paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian)); - byte = ((vaddr & mask) ^ bigendiancpu); - memval = (((uword64)COP_SW(((instruction_0 >> 26) & 0x3),FT)) << (8 * byte)); - StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); - } - } - } + do_swc1 (SD_, FT, OFFSET, BASE, instruction_0); } @@ -5594,38 +6250,7 @@ *mips64r2: *vr5000: { - - address_word base = GPR[BASE]; - address_word index = GPR[INDEX]; - check_fpu (SD_); - check_u64 (SD_, instruction_0); - { - address_word vaddr = loadstore_ea (SD_, base, index); - address_word paddr; - int uncached; - if ((vaddr & 3) != 0) - { - SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, write_transfer, sim_core_unaligned_signal); - } - else - { - if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) - { - unsigned64 memval = 0; - unsigned64 memval1 = 0; - unsigned64 mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3); - address_word reverseendian = (ReverseEndian ? (mask ^ AccessLength_WORD) : 0); - address_word bigendiancpu = (BigEndianCPU ? (mask ^ AccessLength_WORD) : 0); - unsigned int byte; - paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian)); - byte = ((vaddr & mask) ^ bigendiancpu); - memval = (((unsigned64)COP_SW(1,FS)) << (8 * byte)); - { - StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); - } - } - } - } + do_swxc1 (SD_, FS, INDEX, BASE, instruction_0); } @@ -5641,10 +6266,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - StoreFPR (FD, fmt_long, Convert (FP_RM_TOZERO, ValueFPR (FS, fmt), fmt, - fmt_long)); + do_trunc_fmt (SD_, fmt_long, FMT, FD, FS); } @@ -5662,10 +6284,7 @@ *vr5000: *r3900: { - int fmt = FMT; - check_fpu (SD_); - StoreFPR (FD, fmt_word, Convert (FP_RM_TOZERO, ValueFPR (FS, fmt), fmt, - fmt_word)); + do_trunc_fmt (SD_, fmt_word, FMT, FD, FS); } @@ -5768,7 +6387,7 @@ } -010000,00001,5.RT,5.RD,00000000000:COP0:64::DMFC0 +010000,00001,5.RT,5.RD,00000000,3.SEL:COP0:64::DMFC0 "dmfc0 r<RT>, r<RD>" *mipsIII: *mipsIV: @@ -5777,11 +6396,11 @@ *mips64r2: { check_u64 (SD_, instruction_0); - DecodeCoproc (instruction_0); + DecodeCoproc (instruction_0, 0, cp0_dmfc0, RT, RD, SEL); } -010000,00101,5.RT,5.RD,00000000000:COP0:64::DMTC0 +010000,00101,5.RT,5.RD,00000000,3.SEL:COP0:64::DMTC0 "dmtc0 r<RT>, r<RD>" *mipsIII: *mipsIV: @@ -5790,7 +6409,7 @@ *mips64r2: { check_u64 (SD_, instruction_0); - DecodeCoproc (instruction_0); + DecodeCoproc (instruction_0, 0, cp0_dmtc0, RT, RD, SEL); } @@ -5821,8 +6440,8 @@ } -010000,00000,5.RT,5.RD,00000,6.REGX:COP0:32::MFC0 -"mfc0 r<RT>, r<RD> # <REGX>" +010000,00000,5.RT,5.RD,00000000,3.SEL:COP0:32::MFC0 +"mfc0 r<RT>, r<RD> # <SEL>" *mipsI: *mipsII: *mipsIII: @@ -5837,12 +6456,12 @@ *r3900: { TRACE_ALU_INPUT0 (); - DecodeCoproc (instruction_0); + DecodeCoproc (instruction_0, 0, cp0_mfc0, RT, RD, SEL); TRACE_ALU_RESULT (GPR[RT]); } -010000,00100,5.RT,5.RD,00000,6.REGX:COP0:32::MTC0 -"mtc0 r<RT>, r<RD> # <REGX>" +010000,00100,5.RT,5.RD,00000000,3.SEL:COP0:32::MTC0 +"mtc0 r<RT>, r<RD> # <SEL>" *mipsI: *mipsII: *mipsIII: @@ -5856,7 +6475,7 @@ *vr5000: *r3900: { - DecodeCoproc (instruction_0); + DecodeCoproc (instruction_0, 0, cp0_mtc0, RT, RD, SEL); } @@ -5871,7 +6490,7 @@ *vr5000: *r3900: { - DecodeCoproc (instruction_0); + DecodeCoproc (instruction_0, 0, cp0_rfe, 0, 0, 0x10); } @@ -5889,7 +6508,7 @@ *vr4100: *r3900: { - DecodeCoproc (instruction_0); + DecodeCoproc (instruction_0, 2, 0, 0, 0, 0); } @@ -5965,4 +6584,6 @@ :include:::dsp.igen :include:::dsp2.igen :include:::smartmips.igen +:include:::micromips.igen +:include:::micromipsdsp.igen diff --git a/sim/mips/mips3264r2.igen b/sim/mips/mips3264r2.igen index 90ad554..1c299c3 100644 --- a/sim/mips/mips3264r2.igen +++ b/sim/mips/mips3264r2.igen @@ -4,7 +4,7 @@ // Copyright (C) 2004-2015 Free Software Foundation, Inc. // Contributed by David Ung, of MIPS Technologies. // -// This file is part of GDB, the GNU debugger. +// This file is part of the MIPS sim. // // 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 @@ -19,15 +19,183 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +:function:::void:do_dsbh:int rd, int rt +{ + union { unsigned64 d; unsigned16 h[4]; } u; + TRACE_ALU_INPUT1 (GPR[rt]); + u.d = GPR[rt]; + u.h[0] = SWAP_2 (u.h[0]); + u.h[1] = SWAP_2 (u.h[1]); + u.h[2] = SWAP_2 (u.h[2]); + u.h[3] = SWAP_2 (u.h[3]); + GPR[rd] = u.d; + TRACE_ALU_RESULT1 (GPR[rd]); +} + +:function:::void:do_dshd:int rd, int rt +{ + unsigned64 d; + TRACE_ALU_INPUT1 (GPR[rt]); + d = GPR[rt]; + GPR[rd] = ((d >> 48) + | (d << 48) + | ((d & 0x0000ffff00000000ULL) >> 16) + | ((d & 0x00000000ffff0000ULL) << 16)); + TRACE_ALU_RESULT1 (GPR[rd]); +} + +:function:::void:do_dext:int rt, int rs, int lsb, int size +{ + TRACE_ALU_INPUT3 (GPR[rs], lsb, size); + GPR[rt] = EXTRACTED64 (GPR[rs], lsb + size, lsb); + TRACE_ALU_RESULT1 (GPR[rt]); +} + +:function:::void:do_dextm:int rt, int rs, int lsb, int size +{ + TRACE_ALU_INPUT3 (GPR[rs], lsb, size); + GPR[rt] = EXTRACTED64 (GPR[rs], lsb + size + 32, lsb); + TRACE_ALU_RESULT1 (GPR[rt]); +} + +:function:::void:do_dextu:int rt, int rs, int lsb, int size +{ + TRACE_ALU_INPUT3 (GPR[rs], lsb, size); + GPR[rt] = EXTRACTED64 (GPR[rs], lsb + 32 + size, lsb + 32); + TRACE_ALU_RESULT1 (GPR[rt]); +} + +:function:::void:do_di:int rt +{ + TRACE_ALU_INPUT0 (); + GPR[rt] = EXTEND32 (SR); + SR &= ~status_IE; + TRACE_ALU_RESULT1 (GPR[rt]); +} + +:function:::void:do_dins:int rt, int rs, int lsb, int msb +{ + TRACE_ALU_INPUT4 (GPR[rt], GPR[rs], lsb, msb); + if (lsb <= msb) + GPR[rt] ^= (GPR[rt] ^ (GPR[rs] << lsb)) & MASK64 (msb, lsb); + TRACE_ALU_RESULT1 (GPR[rt]); +} + +:function:::void:do_dinsm:int rt, int rs, int lsb, int msb +{ + TRACE_ALU_INPUT4 (GPR[rt], GPR[rs], lsb, msb); + if (lsb <= msb + 32) + GPR[rt] ^= (GPR[rt] ^ (GPR[rs] << lsb)) & MASK64 (msb + 32, lsb); + TRACE_ALU_RESULT1 (GPR[rt]); +} + +:function:::void:do_ei:int rt +{ + TRACE_ALU_INPUT0 (); + GPR[rt] = EXTEND32 (SR); + SR |= status_IE; + TRACE_ALU_RESULT1 (GPR[rt]); +} + +:function:::void:do_ext:int rt, int rs, int lsb, int size +{ + TRACE_ALU_INPUT3 (GPR[rs], lsb, size); + GPR[rt] = EXTEND32 (EXTRACTED32 (GPR[rs], lsb + size, lsb)); + TRACE_ALU_RESULT1 (GPR[rt]); +} + +:function:::void:do_mfhc1:int rt, int fs +{ + check_fpu (SD_); + if (SizeFGR() == 64) + GPR[rt] = EXTEND32 (WORD64HI (FGR[fs])); + else if ((fs & 0x1) == 0) + GPR[rt] = EXTEND32 (FGR[fs + 1]); + else + { + if (STATE_VERBOSE_P(SD)) + sim_io_eprintf (SD, + "Warning: PC 0x%lx: MFHC1 32-bit use of odd FPR number\n", + (long) CIA); + GPR[rt] = EXTEND32 (0xBADF00D); + } + TRACE_ALU_RESULT (GPR[rt]); +} + +:function:::void:do_mthc1:int rt, int fs +{ + check_fpu (SD_); + if (SizeFGR() == 64) + StoreFPR (fs, fmt_uninterpreted_64, SET64HI (GPR[rt]) | VL4_8 (FGR[fs])); + else if ((fs & 0x1) == 0) + StoreFPR (fs + 1, fmt_uninterpreted_32, VL4_8 (GPR[rt])); + else + { + if (STATE_VERBOSE_P(SD)) + sim_io_eprintf (SD, + "Warning: PC 0x%lx: MTHC1 32-bit use of odd FPR number\n", + (long) CIA); + StoreFPR (fs, fmt_uninterpreted_32, 0xDEADC0DE); + } + TRACE_FP_RESULT (GPR[rt]); +} + +:function:::void:do_ins:int rt, int rs, int lsb, int msb +{ + TRACE_ALU_INPUT4 (GPR[rt], GPR[rs], lsb, msb); + if (lsb <= msb) + GPR[rt] = EXTEND32 (GPR[rt] ^ + ((GPR[rt] ^ (GPR[rs] << lsb)) & MASK32 (msb, lsb))); + TRACE_ALU_RESULT1 (GPR[rt]); +} + +:function:::void:do_dinsu:int rt, int rs, int lsb, int msb +{ + TRACE_ALU_INPUT4 (GPR[rt], GPR[rs], lsb, msb); + if (lsb <= msb) + GPR[rt] ^= (GPR[rt] ^ (GPR[rs] << (lsb + 32))) + & MASK64 (msb + 32, lsb + 32); + TRACE_ALU_RESULT1 (GPR[rt]); +} + +:function:::void:do_seb:int rd, int rt +{ + TRACE_ALU_INPUT1 (GPR[rt]); + GPR[rd] = EXTEND8 (GPR[rt]); + TRACE_ALU_RESULT1 (GPR[rd]); +} + +:function:::void:do_seh:int rd, int rt +{ + TRACE_ALU_INPUT1 (GPR[rt]); + GPR[rd] = EXTEND16 (GPR[rt]); + TRACE_ALU_RESULT1 (GPR[rd]); +} + +:function:::void:do_rdhwr:int rt, int rd +{ + // Return 0 for all hardware registers currently + GPR[rt] = EXTEND32 (0); + TRACE_ALU_RESULT1 (GPR[rt]); +} + +:function:::void:do_wsbh:int rd, int rt +{ + union { unsigned32 w; unsigned16 h[2]; } u; + TRACE_ALU_INPUT1 (GPR[rt]); + u.w = GPR[rt]; + u.h[0] = SWAP_2 (u.h[0]); + u.h[1] = SWAP_2 (u.h[1]); + GPR[rd] = EXTEND32 (u.w); + TRACE_ALU_RESULT1 (GPR[rd]); +} 011111,5.RS,5.RT,5.SIZE,5.LSB,000011::64::DEXT "dext r<RT>, r<RS>, <LSB>, <SIZE+1>" *mips64r2: { check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT3 (GPR[RS], LSB, SIZE); - GPR[RT] = EXTRACTED64 (GPR[RS], LSB + SIZE, LSB); - TRACE_ALU_RESULT1 (GPR[RT]); + do_dext (SD_, RT, RS, LSB, SIZE); } 011111,5.RS,5.RT,5.SIZE,5.LSB,000001::64::DEXTM @@ -35,9 +203,7 @@ *mips64r2: { check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT3 (GPR[RS], LSB, SIZE); - GPR[RT] = EXTRACTED64 (GPR[RS], LSB + SIZE + 32, LSB); - TRACE_ALU_RESULT1 (GPR[RT]); + do_dextm (SD_, RT, RS, LSB, SIZE); } 011111,5.RS,5.RT,5.SIZE,5.LSB,000010::64::DEXTU @@ -45,9 +211,7 @@ *mips64r2: { check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT3 (GPR[RS], LSB, SIZE); - GPR[RT] = EXTRACTED64 (GPR[RS], LSB + 32 + SIZE, LSB + 32); - TRACE_ALU_RESULT1 (GPR[RT]); + do_dextu (SD_, RT, RS, LSB, SIZE); } @@ -57,10 +221,7 @@ *mips32r2: *mips64r2: { - TRACE_ALU_INPUT0 (); - GPR[RT] = EXTEND32 (SR); - SR &= ~status_IE; - TRACE_ALU_RESULT1 (GPR[RT]); + do_di (SD_, RT); } @@ -69,10 +230,7 @@ *mips64r2: { check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT4 (GPR[RT], GPR[RS], LSB, MSB); - if (LSB <= MSB) - GPR[RT] ^= (GPR[RT] ^ (GPR[RS] << LSB)) & MASK64 (MSB, LSB); - TRACE_ALU_RESULT1 (GPR[RT]); + do_dins (SD_, RT, RS, LSB, MSB); } 011111,5.RS,5.RT,5.MSB,5.LSB,000101::64::DINSM @@ -80,10 +238,7 @@ *mips64r2: { check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT4 (GPR[RT], GPR[RS], LSB, MSB); - if (LSB <= MSB + 32) - GPR[RT] ^= (GPR[RT] ^ (GPR[RS] << LSB)) & MASK64 (MSB + 32, LSB); - TRACE_ALU_RESULT1 (GPR[RT]); + do_dinsm (SD_, RT, RS, LSB, MSB); } 011111,5.RS,5.RT,5.MSB,5.LSB,000110::64::DINSU @@ -91,11 +246,7 @@ *mips64r2: { check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT4 (GPR[RT], GPR[RS], LSB, MSB); - if (LSB <= MSB) - GPR[RT] ^= (GPR[RT] ^ (GPR[RS] << (LSB + 32))) - & MASK64 (MSB + 32, LSB + 32); - TRACE_ALU_RESULT1 (GPR[RT]); + do_dinsu (SD_, RT, RS, LSB, MSB); } @@ -103,44 +254,25 @@ "dsbh r<RD>, r<RT>" *mips64r2: { - union { unsigned64 d; unsigned16 h[4]; } u; check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT1 (GPR[RT]); - u.d = GPR[RT]; - u.h[0] = SWAP_2 (u.h[0]); - u.h[1] = SWAP_2 (u.h[1]); - u.h[2] = SWAP_2 (u.h[2]); - u.h[3] = SWAP_2 (u.h[3]); - GPR[RD] = u.d; - TRACE_ALU_RESULT1 (GPR[RD]); + do_dsbh (SD_, RD, RT); } 011111,00000,5.RT,5.RD,00101,100100::64::DSHD "dshd r<RD>, r<RT>" *mips64r2: { - unsigned64 d; check_u64 (SD_, instruction_0); - TRACE_ALU_INPUT1 (GPR[RT]); - d = GPR[RT]; - GPR[RD] = ((d >> 48) - | (d << 48) - | ((d & 0x0000ffff00000000ULL) >> 16) - | ((d & 0x00000000ffff0000ULL) << 16)); - TRACE_ALU_RESULT1 (GPR[RD]); + do_dshd (SD_, RD, RT); } - 010000,01011,5.RT,01100,00000,1,00,000::32::EI "ei":RT == 0 "ei r<RT>" *mips32r2: *mips64r2: { - TRACE_ALU_INPUT0 (); - GPR[RT] = EXTEND32 (SR); - SR |= status_IE; - TRACE_ALU_RESULT1 (GPR[RT]); + do_ei (SD_, RT); } @@ -149,9 +281,7 @@ *mips32r2: *mips64r2: { - TRACE_ALU_INPUT3 (GPR[RS], LSB, SIZE); - GPR[RT] = EXTEND32 (EXTRACTED32 (GPR[RS], LSB + SIZE, LSB)); - TRACE_ALU_RESULT1 (GPR[RT]); + do_ext (SD_, RT, RS, LSB, SIZE); } @@ -160,20 +290,7 @@ *mips32r2: *mips64r2: { - check_fpu (SD_); - if (SizeFGR() == 64) - GPR[RT] = EXTEND32 (WORD64HI (FGR[FS])); - else if ((FS & 0x1) == 0) - GPR[RT] = EXTEND32 (FGR[FS + 1]); - else - { - if (STATE_VERBOSE_P(SD)) - sim_io_eprintf (SD, - "Warning: PC 0x%lx: MFHC1 32-bit use of odd FPR number\n", - (long) CIA); - GPR[RT] = EXTEND32 (0xBADF00D); - } - TRACE_ALU_RESULT (GPR[RT]); + do_mfhc1 (SD_, RT, FS); } 010001,00111,5.RT,5.FS,00000000000:COP1Sa:32,f::MTHC1 @@ -181,20 +298,7 @@ *mips32r2: *mips64r2: { - check_fpu (SD_); - if (SizeFGR() == 64) - StoreFPR (FS, fmt_uninterpreted_64, SET64HI (GPR[RT]) | VL4_8 (FGR[FS])); - else if ((FS & 0x1) == 0) - StoreFPR (FS + 1, fmt_uninterpreted_32, VL4_8 (GPR[RT])); - else - { - if (STATE_VERBOSE_P(SD)) - sim_io_eprintf (SD, - "Warning: PC 0x%lx: MTHC1 32-bit use of odd FPR number\n", - (long) CIA); - StoreFPR (FS, fmt_uninterpreted_32, 0xDEADC0DE); - } - TRACE_FP_RESULT (GPR[RT]); + do_mthc1 (SD_, RT, FS); } @@ -203,11 +307,7 @@ *mips32r2: *mips64r2: { - TRACE_ALU_INPUT4 (GPR[RT], GPR[RS], LSB, MSB); - if (LSB <= MSB) - GPR[RT] = EXTEND32 (GPR[RT] ^ - ((GPR[RT] ^ (GPR[RS] << LSB)) & MASK32 (MSB, LSB))); - TRACE_ALU_RESULT1 (GPR[RT]); + do_ins (SD_, RT, RS, LSB, MSB); } @@ -216,9 +316,7 @@ *mips32r2: *mips64r2: { - TRACE_ALU_INPUT1 (GPR[RT]); - GPR[RD] = EXTEND8 (GPR[RT]); - TRACE_ALU_RESULT1 (GPR[RD]); + do_seb (SD_, RD, RT); } 011111,00000,5.RT,5.RD,11000,100000::32::SEH @@ -226,9 +324,7 @@ *mips32r2: *mips64r2: { - TRACE_ALU_INPUT1 (GPR[RT]); - GPR[RD] = EXTEND16 (GPR[RT]); - TRACE_ALU_RESULT1 (GPR[RD]); + do_seh (SD_, RD, RT); } @@ -246,9 +342,7 @@ *mips32r2: *mips64r2: { - // Return 0 for all hardware registers currently - GPR[RT] = EXTEND32 (0); - TRACE_ALU_RESULT1 (GPR[RT]); + do_rdhwr (SD_, RT, RD); } @@ -257,13 +351,7 @@ *mips32r2: *mips64r2: { - union { unsigned32 w; unsigned16 h[2]; } u; - TRACE_ALU_INPUT1 (GPR[RT]); - u.w = GPR[RT]; - u.h[0] = SWAP_2 (u.h[0]); - u.h[1] = SWAP_2 (u.h[1]); - GPR[RD] = EXTEND32 (u.w); - TRACE_ALU_RESULT1 (GPR[RD]); + do_wsbh (SD_, RD, RT); } diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h index 8d698ad..42d8db3 100644 --- a/sim/mips/sim-main.h +++ b/sim/mips/sim-main.h @@ -2,7 +2,7 @@ Copyright (C) 1997-2015 Free Software Foundation, Inc. Contributed by Cygnus Support. -This file is part of GDB, the GNU debugger. +This file is part of the MIPS sim. 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 @@ -49,6 +49,20 @@ typedef unsigned64 uword64; #define NOTHALFWORDVALUE(v) ((((((uword64)(v)>>16) == 0) && !((v) & ((unsigned)1 << 15))) || (((((uword64)(v)>>32) == 0xFFFFFFFF) && ((((uword64)(v)>>16) & 0xFFFF) == 0xFFFF)) && ((v) & ((unsigned)1 << 15)))) ? (1 == 0) : (1 == 1)) +typedef enum { + cp0_dmfc0, + cp0_dmtc0, + cp0_mfc0, + cp0_mtc0, + cp0_tlbr, + cp0_tlbwi, + cp0_tlbwr, + cp0_tlbp, + cp0_cache, + cp0_eret, + cp0_deret, + cp0_rfe +} CP0_operation; /* Floating-point operations: */ @@ -479,6 +493,9 @@ struct sim_state { sim_cpu *cpu[MAX_NR_PROCESSORS]; + /* microMIPS ISA mode. */ + int isa_mode; + sim_state_base base; }; @@ -690,9 +707,12 @@ cop_sw (SD, CPU, cia, coproc_num, coproc_reg) cop_sd (SD, CPU, cia, coproc_num, coproc_reg) -void decode_coproc (SIM_DESC sd, sim_cpu *cpu, address_word cia, unsigned int instruction); -#define DecodeCoproc(instruction) \ -decode_coproc (SD, CPU, cia, (instruction)) +void decode_coproc (SIM_DESC sd, sim_cpu *cpu, address_word cia, + unsigned int instruction, int coprocnum, CP0_operation op, + int rt, int rd, int sel); +#define DecodeCoproc(instruction,coprocnum,op,rt,rd,sel) \ + decode_coproc (SD, CPU, cia, (instruction), (coprocnum), (op), \ + (rt), (rd), (sel)) int sim_monitor (SIM_DESC sd, sim_cpu *cpu, address_word cia, unsigned int arg); @@ -956,6 +976,25 @@ INLINE_SIM_MAIN (unsigned32) ifetch32 (SIM_DESC sd, sim_cpu *cpu, address_word c INLINE_SIM_MAIN (unsigned16) ifetch16 (SIM_DESC sd, sim_cpu *cpu, address_word cia, address_word vaddr); #define IMEM16(CIA) ifetch16 (SD, CPU, (CIA), ((CIA) & ~1)) #define IMEM16_IMMED(CIA,NR) ifetch16 (SD, CPU, (CIA), ((CIA) & ~1) + 2 * (NR)) +#define IMEM32_MICROMIPS(CIA) \ + (ifetch16 (SD, CPU, (CIA), (CIA)) << 16 | ifetch16 (SD, CPU, (CIA + 2), \ + (CIA + 2))) +#define IMEM16_MICROMIPS(CIA) ifetch16 (SD, CPU, (CIA), ((CIA))) + +#define MICROMIPS_MINOR_OPCODE(INSN) ((INSN & 0x1C00) >> 10) + +#define MICROMIPS_DELAYSLOT_SIZE_ANY 0 +#define MICROMIPS_DELAYSLOT_SIZE_16 2 +#define MICROMIPS_DELAYSLOT_SIZE_32 4 + +extern int isa_mode; + +#define ISA_MODE_MIPS32 0 +#define ISA_MODE_MICROMIPS 1 + +address_word micromips_instruction_decode (SIM_DESC sd, sim_cpu * cpu, + address_word cia, + int instruction_size); #if WITH_TRACE_ANY_P void dotrace (SIM_DESC sd, sim_cpu *cpu, FILE *tracefh, int type, SIM_ADDR address, int width, char *comment, ...); |