This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] [PATCH] Add micromips support to the MIPS simulator


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8e394ffc7ab691eafcf276d7ae578454a8c5548f

commit 8e394ffc7ab691eafcf276d7ae578454a8c5548f
Author: Andrew Bennett <andrew.bennett@imgtec.com>
Date:   Fri Sep 25 15:52:18 2015 +0100

    [PATCH] Add micromips support to the MIPS simulator
    
    2015-09-25  Andrew Bennett  <andrew.bennett@imgtec.com>
     	      Ali Lown  <ali.lown@imgtec.com>
    
    	sim/common/
    	* sim-bits.h (EXTEND6): New macro.
    	(EXTEND12): New macro.
    	(EXTEND25): New macro.
    
    	sim/mips/
    	* Makefile.in (tmp-micromips): New rule.
    	(tmp-mach-multi): Add support for micromips.
    	* configure.ac (mips*-sde-elf* | mips*-mti-elf*): Made a multi sim
    	that works for both mips64 and micromips64.
    	(mipsisa32r2*-*-*): Made a multi sim that works for mips32 and
    	micromips32.
    	Add build support for micromips.
    	* dsp.igen (do_ph_s_absq, do_w_s_absq, do_qb_s_absq, do_addsc,
    	do_addwc, do_bitrev, do_extpv, do_extrv, do_extrv_s_h, do_insv,
    	do_lxx do_modsub, do_mthlip, do_mulsaq_s_w_ph, do_ph_packrl, do_qb_pick
    	do_ph_pick, do_qb_ph_precequ, do_qb_ph_preceu, do_w_preceq
    	do_w_ph_precrq, do_ph_qb_precrq, do_w_ph_rs_precrq do_qb_w_raddu,
    	do_rddsp, do_repl, do_shilov, do_ph_shl, do_qb_shl do_w_s_shllv,
    	do_ph_shrlv, do_w_r_shrav, do_wrdsp, do_qb_shrav, do_append,
    	do_balign, do_ph_w_mulsa, do_ph_qb_precr, do_prepend): New functions.
    	Refactored instruction code to use these functions.
    	* dsp2.igen: Refactored instruction code to use the new functions.
    	* interp.c (decode_coproc): Refactored to work with any instruction
    	encoding.
    	(isa_mode): New variable
    	(RSVD_INSTRUCTION): Changed to 0x00000039.
    	* m16.igen (BREAK16): Refactored instruction to use do_break16.
    	(JALX32): Add mips32, mips64, mips32r2 and mips64r2 models.
    	* micromips.dc: New file.
    	* micromips.igen: New file.
    	* micromips16.dc: New file.
    	* micromipsdsp.igen: New file.
    	* micromipsrun.c: New file.
    	* mips.igen (do_swc1): Changed to work with any instruction encoding.
    	(do_add do_addi do_andi do_dadd do_daddi do_dsll32 do_dsra32
    	do_dsrl32, do_dsub, do_break, do_break16, do_clo, do_clz, do_dclo
    	do_dclz, do_lb, do_lh, do_lwr, do_lwl, do_lwc, do_lw, do_lwu, do_lhu
    	do_ldc, do_lbu, do_ll, do_lld, do_lui, do_madd, do_dsp_madd, do_maddu
    	do_dsp_maddu, do_dsp_mfhi, do_dsp_mflo, do_movn, do_movz, do_msub
    	do_dsp_msub, do_msubu, do_dsp_msubu, do_mthi, do_dsp_mthi, do_mtlo
    	do_dsp_mtlo, do_mul, do_dsp_mult, do_dsp_multu, do_pref, do_sc, do_scd
    	do_sub, do_sw, do_teq, do_teqi, do_tge, do_tgei, do_tgeiu, do_tgeu, do_tlt
    	do_tlti, do_tltiu, do_tltu, do_tne, do_tnei, do_abs_fmt, do_add_fmt
    	do_alnv_ps, do_c_cond_fmt, do_ceil_fmt, do_cfc1, do_ctc1, do_cvt_d_fmt
    	do_cvt_l_fmt, do_cvt_ps_s, do_cvt_s_fmt, do_cvt_s_pl, do_cvt_s_pu
    	do_cvt_w_fmt, do_div_fmt, do_dmfc1b, do_dmtc1b, do_floor_fmt, do_luxc1_32
    	do_luxc1_64, do_lwc1, do_lwxc1, do_madd_fmt, do_mfc1b, do_mov_fmt, do_movtf
    	do_movtf_fmt, do_movn_fmt, do_movz_fmt, do_msub_fmt, do_mtc1b, do_mul_fmt
    	do_neg_fmt, do_nmadd_fmt, do_nmsub_fmt, do_pll_ps, do_plu_ps, do_pul_ps
    	do_puu_ps, do_recip_fmt, do_round_fmt, do_rsqrt_fmt, do_prefx, do_sdc1
    	do_suxc1_32, do_suxc1_64, do_sqrt_fmt, do_sub_fmt, do_swc1, do_swxc1
    	do_trunc_fmt): New functions, refactored from existing instructions.
    	Refactored instruction code to use these functions.
    	(RSVD): Changed to use new reserved instruction.
    	(loadstore_ea, not_word_value, unpredictable, check_mt_hilo, check_mf_hilo,
    	check_mult_hilo, check_div_hilo, check_u64, do_luxc1_32, do_sdc1, do_suxc1_32,
    	check_fmt_p, check_fpu, do_load_double, do_store_double):  Added micromips32
    	and micromips64 models.
    	Added include for micromips.igen and micromipsdsp.igen
    	Add micromips32 and micromips64 models.
    	(DecodeCoproc): Updated to use new macro definition.
    	* mips3264r2.igen (do_dsbh, do_dshd, do_dext, do_dextm, do_dextu, do_di,
    	do_dins, do_dinsm, do_ei, do_ext, do_mfhc1, do_mthc1, do_ins, do_dinsu,
    	do_seb, do_seh do_rdhwr, do_wsbh): New functions.
    	Refactored instruction code to use these functions.
    	* sim-main.h (CP0_operation): New enum.
    	(DecodeCoproc): Updated macro.
    	(IMEM32_MICROMIPS, IMEM16_MICROMIPS, MICROMIPS_MINOR_OPCODE,
    	MICROMIPS_DELAYSLOT_SIZE_ANY, MICROMIPS_DELAYSLOT_SIZE_16, MICROMIPS_DELAYSLOT_SIZE_32,
    	ISA_MODE_MIPS32 and ISA_MODE_MICROMIPS): New defines.
    	(sim_state): Add isa_mode field.
    
    	sim/testsuite/sim/mips/
           * basic.exp (run_micromips_test, run_sim_tests): New functions
    	Add support for micromips tests.
    	* hilo-hazard-4.s: New file.
    	* testutils.inc (_dowrite): Changed reserved instruction encoding.
    	(writemsg): Moved the la and li instructions before the data they are
    	assigned to, which prevents a bug where MIPS32 relocations are used instead
    	of micromips relocations when building for micromips.

Diff:
---
 sim/common/ChangeLog                   |    7 +
 sim/common/sim-bits.h                  |    3 +
 sim/mips/ChangeLog                     |   72 +
 sim/mips/Makefile.in                   |  324 +++-
 sim/mips/configure                     |   61 +-
 sim/mips/configure.ac                  |   59 +-
 sim/mips/dsp.igen                      | 1041 +++++++----
 sim/mips/dsp2.igen                     |   84 +-
 sim/mips/interp.c                      |   53 +-
 sim/mips/m16.igen                      |   10 +-
 sim/mips/micromips.dc                  |   15 +
 sim/mips/micromips.igen                | 3091 ++++++++++++++++++++++++++++++++
 sim/mips/micromips16.dc                |   11 +
 sim/mips/micromipsdsp.igen             | 1137 ++++++++++++
 sim/mips/micromipsrun.c                |  135 ++
 sim/mips/mips.igen                     | 2269 ++++++++++++++---------
 sim/mips/mips3264r2.igen               |  290 +--
 sim/mips/sim-main.h                    |   47 +-
 sim/testsuite/sim/mips/ChangeLog       |   11 +
 sim/testsuite/sim/mips/basic.exp       |   29 +-
 sim/testsuite/sim/mips/hilo-hazard-4.s |   37 +
 sim/testsuite/sim/mips/testutils.inc   |    6 +-
 22 files changed, 7307 insertions(+), 1485 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>"
+*micro[...]

[diff truncated at 100000 bytes]


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]