aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sim/common/ChangeLog7
-rw-r--r--sim/common/sim-bits.h3
-rw-r--r--sim/mips/ChangeLog72
-rw-r--r--sim/mips/Makefile.in324
-rwxr-xr-xsim/mips/configure61
-rw-r--r--sim/mips/configure.ac59
-rw-r--r--sim/mips/dsp.igen1041
-rw-r--r--sim/mips/dsp2.igen84
-rw-r--r--sim/mips/interp.c53
-rw-r--r--sim/mips/m16.igen10
-rw-r--r--sim/mips/micromips.dc15
-rw-r--r--sim/mips/micromips.igen3091
-rw-r--r--sim/mips/micromips16.dc11
-rw-r--r--sim/mips/micromipsdsp.igen1137
-rw-r--r--sim/mips/micromipsrun.c135
-rw-r--r--sim/mips/mips.igen2235
-rw-r--r--sim/mips/mips3264r2.igen290
-rw-r--r--sim/mips/sim-main.h47
-rw-r--r--sim/testsuite/sim/mips/ChangeLog11
-rw-r--r--sim/testsuite/sim/mips/basic.exp29
-rw-r--r--sim/testsuite/sim/mips/hilo-hazard-4.s37
-rw-r--r--sim/testsuite/sim/mips/testutils.inc6
22 files changed, 7290 insertions, 1468 deletions
diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog
index 8e47936..2aa178c 100644
--- a/sim/common/ChangeLog
+++ b/sim/common/ChangeLog
@@ -1,3 +1,10 @@
+2015-09-25 Andrew Bennett <andrew.bennett@imgtec.com>
+ Ali Lown <ali.lown@imgtec.com>
+
+ * sim-bits.h (EXTEND6): New macro.
+ (EXTEND12): New macro.
+ (EXTEND25): New macro.
+
2015-06-24 Mike Frysinger <vapier@gentoo.org>
* sim-trace.c (trace_one_insn): Delete.
diff --git a/sim/common/sim-bits.h b/sim/common/sim-bits.h
index fb6a821..ecfd230 100644
--- a/sim/common/sim-bits.h
+++ b/sim/common/sim-bits.h
@@ -501,11 +501,14 @@ INLINE_SIM_BITS(unsigned_word) MSINSERTED (unsigned_word val, int start, int sto
#define EXTEND4(X) (LSSEXT ((X), 3))
#define EXTEND5(X) (LSSEXT ((X), 4))
+#define EXTEND6(X) (LSSEXT ((X), 5))
#define EXTEND8(X) ((signed_word)(signed8)(X))
#define EXTEND11(X) (LSSEXT ((X), 10))
+#define EXTEND12(X) (LSSEXT ((X), 11))
#define EXTEND15(X) (LSSEXT ((X), 14))
#define EXTEND16(X) ((signed_word)(signed16)(X))
#define EXTEND24(X) (LSSEXT ((X), 23))
+#define EXTEND25(X) (LSSEXT ((X), 24))
#define EXTEND32(X) ((signed_word)(signed32)(X))
#define EXTEND64(X) ((signed_word)(signed64)(X))
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, ...);
diff --git a/sim/testsuite/sim/mips/ChangeLog b/sim/testsuite/sim/mips/ChangeLog
index e5913c1..ada4e4c 100644
--- a/sim/testsuite/sim/mips/ChangeLog
+++ b/sim/testsuite/sim/mips/ChangeLog
@@ -1,3 +1,14 @@
+2015-09-25 Andrew Bennett <andrew.bennett@imgtec.com>
+ Ali Lown <ali.lown@imgtec.com>
+
+ * 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.
+
2015-04-13 Hans-Peter Nilsson <hp@axis.com>
* basic.exp: Don't unset target ldscript here.
diff --git a/sim/testsuite/sim/mips/basic.exp b/sim/testsuite/sim/mips/basic.exp
index ddef535..f810741 100644
--- a/sim/testsuite/sim/mips/basic.exp
+++ b/sim/testsuite/sim/mips/basic.exp
@@ -25,12 +25,28 @@ proc run_hilo_test {testfile models nops} {
}
}
+# Runs micromips tests by adding -mmicromips to as options
+proc run_micromips_test { name requested_machs } {
+ global global_as_options;
+ set gas_old $global_as_options;
+ append global_as_options " -mmicromips "
+ run_sim_test $name $requested_machs
+ set global_as_options $gas_old
+}
+
+# Runs all specified tests
+proc run_sim_tests { name requested_machs { requested_micromips_machs "" } } {
+ run_sim_test $name $requested_machs
+ run_micromips_test $name $requested_micromips_machs
+}
# Only test mips*-*-elf (e.g., no mips*-*-linux)
if {[istarget mips*-*-elf]} {
set dspmodels ""
set mdmxmodels ""
+ set micromipsmodels ""
+ set micromipsdspmodels ""
if {[istarget mipsisa64sb1*-*-elf]} {
set models "sb1"
@@ -46,11 +62,15 @@ if {[istarget mips*-*-elf]} {
set submodels ""
append dspmodels " mips32r2 mips64r2"
append mdmxmodels " mips64 mips32r2 mips64r2"
+ append micromipsmodels " mips32r2"
+ append micromipsdspmodels " mips32r2 mips64r2"
} elseif {[istarget mipsisa32*-*-elf]} {
set models "mips32 mips32r2"
set submodels "mips1 mips2"
append dspmodels " mips32r2"
append mdmxmodels " mips32r2"
+ append micromipsmodels " mips32r2"
+ append micromipsdspmodels " mips32r2"
} elseif {[istarget mips64vr*-*-elf]} {
set models "vr4100 vr4111 vr4120 vr5000 vr5400 vr5500"
set submodels "mips1 mips2 mips3 mips4"
@@ -65,12 +85,14 @@ if {[istarget mips*-*-elf]} {
append submodels " " $models
set cpu_option -march
- run_sim_test sanity.s $submodels
+ run_sim_tests sanity.s $submodels $micromipsmodels
+
foreach nops {0 1} {
run_hilo_test hilo-hazard-1.s $models $nops
run_hilo_test hilo-hazard-2.s $models $nops
}
run_hilo_test hilo-hazard-3.s $models 2
+ run_hilo_test hilo-hazard-4.s $micromipsmodels 2
run_sim_test fpu64-ps.s $submodels
run_sim_test fpu64-ps-sb1.s $submodels
@@ -78,6 +100,7 @@ if {[istarget mips*-*-elf]} {
run_sim_test mdmx-ob.s $mdmxmodels
run_sim_test mdmx-ob-sb1.s $mdmxmodels
- run_sim_test mips32-dsp.s $dspmodels
- run_sim_test mips32-dsp2.s $dspmodels
+ run_sim_tests mips32-dsp.s $dspmodels $micromipsdspmodels
+ run_sim_tests mips32-dsp2.s $dspmodels $micromipsdspmodels
+
}
diff --git a/sim/testsuite/sim/mips/hilo-hazard-4.s b/sim/testsuite/sim/mips/hilo-hazard-4.s
new file mode 100644
index 0000000..e83fbfa
--- /dev/null
+++ b/sim/testsuite/sim/mips/hilo-hazard-4.s
@@ -0,0 +1,37 @@
+# Test for mf{hi,lo} -> mult/div/mt{hi,lo} with 2 nops inbetween.
+#
+# mach: all
+# as: -mabi=eabi -mmicromips
+# ld: -N -Ttext=0x80010000
+# output: pass\\n
+
+# Copyright (C) 2013-2015 Imagination Technologies, Ltd.
+# All rights reserved.
+# Contributed 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, 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 "hilo-hazard.inc"
+ .include "testutils.inc"
+
+ setup
+
+ .set noreorder
+ .ent DIAG
+DIAG:
+ hilo
+ pass
+ .end DIAG
diff --git a/sim/testsuite/sim/mips/testutils.inc b/sim/testsuite/sim/mips/testutils.inc
index 6ea59f0..0029fc0 100644
--- a/sim/testsuite/sim/mips/testutils.inc
+++ b/sim/testsuite/sim/mips/testutils.inc
@@ -21,12 +21,12 @@
# $1, $4, $5, %6, are used as temps by the macros defined here.
.macro writemsg msg
+ la $5, 901f
+ li $6, 902f - 901f
.data
901: .ascii "\msg\n"
902:
.previous
- la $5, 901b
- li $6, 902b - 901b
.set push
.set noreorder
jal _dowrite
@@ -81,7 +81,7 @@ _pass:
_dowrite:
# Write opcode (reserved instruction). See sim_monitor and its
# callers in sim/mips/interp.c.
- .word 0x00000005 | ((8 << 1) << 6)
+ .word 0x00000039 | ((8 << 1) << 6)
.end _dowrite
.endm # setup