Merge in a port for mips32-linux, by Petar Jovanovic and Dejan Jevtic,
mips-valgrind@rt-rk.com, Bug 270777.

VEX: new files for mips32.


git-svn-id: svn://svn.valgrind.org/vex/trunk@2376 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_mips_defs.h b/priv/guest_mips_defs.h
new file mode 100644
index 0000000..afb4f90
--- /dev/null
+++ b/priv/guest_mips_defs.h
@@ -0,0 +1,114 @@
+
+/*---------------------------------------------------------------*/
+/*--- begin                                 guest_mips_defs.h ---*/
+/*---------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2010-2012 RT-RK
+      mips-valgrind@rt-rk.com
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Only to be used within the guest-mips directory. */
+
+#ifndef __VEX_GUEST_MIPS_DEFS_H
+#define __VEX_GUEST_MIPS_DEFS_H
+
+/*---------------------------------------------------------*/
+/*--- mips to IR conversion                             ---*/
+/*---------------------------------------------------------*/
+
+/* Convert one MIPS insn to IR.  See the type DisOneInstrFn in
+   bb_to_IR.h. */
+extern DisResult disInstr_MIPS ( IRSB*        irbb,
+                                 Bool         (*resteerOkFn) (void *, Addr64),
+                                 Bool         resteerCisOk,
+                                 void*        callback_opaque,
+                                 UChar*       guest_code,
+                                 Long         delta,
+                                 Addr64       guest_IP,
+                                 VexArch      guest_arch,
+                                 VexArchInfo* archinfo,
+                                 VexAbiInfo*  abiinfo,
+                                 Bool         host_bigendian );
+
+/* Used by the optimiser to specialise calls to helpers. */
+extern IRExpr *guest_mips32_spechelper(HChar * function_name, IRExpr ** args,
+                                       IRStmt ** precedingStmts,
+                                       Int n_precedingStmts);
+
+/* Describes to the optimser which part of the guest state require
+   precise memory exceptions.  This is logically part of the guest
+   state description. */
+extern Bool guest_mips32_state_requires_precise_mem_exns(Int, Int);
+
+extern VexGuestLayout mips32Guest_layout;
+
+/*---------------------------------------------------------*/
+/*--- mips guest helpers                                 ---*/
+/*---------------------------------------------------------*/
+
+extern UInt mips32_dirtyhelper_mfc0(UInt rd, UInt sel);
+
+extern void mips32_dirtyhelper_sync(UInt sync);
+
+/*---------------------------------------------------------*/
+/*--- Condition code stuff                              ---*/
+/*---------------------------------------------------------*/
+
+/* Defines conditions which we can ask for (MIPS MIPS 2e page A3-6) */
+
+typedef enum {
+   MIPSCondEQ = 0,      /* equal                         : Z=1 */
+   MIPSCondNE = 1,      /* not equal                     : Z=0 */
+
+   MIPSCondHS = 2,      /* >=u (higher or same)          : C=1 */
+   MIPSCondLO = 3,      /* <u  (lower)                   : C=0 */
+
+   MIPSCondMI = 4,      /* minus (negative)              : N=1 */
+   MIPSCondPL = 5,      /* plus (zero or +ve)            : N=0 */
+
+   MIPSCondVS = 6,      /* overflow                      : V=1 */
+   MIPSCondVC = 7,      /* no overflow                   : V=0 */
+
+   MIPSCondHI = 8,      /* >u   (higher)                 : C=1 && Z=0 */
+   MIPSCondLS = 9,      /* <=u  (lower or same)          : C=0 || Z=1 */
+
+   MIPSCondGE = 10,  /* >=s (signed greater or equal) : N=V */
+   MIPSCondLT = 11,  /* <s  (signed less than)        : N!=V */
+
+   MIPSCondGT = 12,  /* >s  (signed greater)          : Z=0 && N=V */
+   MIPSCondLE = 13,  /* <=s (signed less or equal)    : Z=1 || N!=V */
+
+   MIPSCondAL = 14,  /* always (unconditional)        : 1 */
+   MIPSCondNV = 15      /* never (unconditional):        : 0 */
+       /* NB: MIPS have deprecated the use of the NV condition code.
+          You are now supposed to use MOV R0,R0 as a noop rather than
+          MOVNV R0,R0 as was previously recommended.  Future processors
+          may have the NV condition code reused to do other things.  */
+} MIPSCondcode;
+
+#endif            /* __VEX_GUEST_MIPS_DEFS_H */
+
+/*---------------------------------------------------------------*/
+/*--- end                                   guest_mips_defs.h ---*/
+/*---------------------------------------------------------------*/
diff --git a/priv/guest_mips_helpers.c b/priv/guest_mips_helpers.c
new file mode 100644
index 0000000..d992b9c
--- /dev/null
+++ b/priv/guest_mips_helpers.c
@@ -0,0 +1,573 @@
+
+/*---------------------------------------------------------------*/
+/*--- begin                              guest_mips_helpers.c ---*/
+/*---------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2010-2012 RT-RK
+      mips-valgrind@rt-rk.com
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "libvex_basictypes.h"
+#include "libvex_emwarn.h"
+#include "libvex_guest_mips32.h"
+#include "libvex_ir.h"
+#include "libvex.h"
+
+#include "main_util.h"
+#include "guest_generic_bb_to_IR.h"
+#include "guest_mips_defs.h"
+
+/* This file contains helper functions for mips guest code.  Calls to
+   these functions are generated by the back end.
+*/
+
+#define ALWAYSDEFD32(field)                           \
+    { offsetof(VexGuestMIPS32State, field),            \
+      (sizeof ((VexGuestMIPS32State*)0)->field) }
+
+IRExpr *guest_mips32_spechelper(HChar * function_name, IRExpr ** args,
+                                IRStmt ** precedingStmts, Int n_precedingStmts)
+{
+   return NULL;
+}
+
+/* VISIBLE TO LIBVEX CLIENT */
+void LibVEX_GuestMIPS32_initialise( /*OUT*/ VexGuestMIPS32State * vex_state)
+{
+   vex_state->guest_r0 = 0;   /* Hardwired to 0 */
+   vex_state->guest_r1 = 0;   /* Assembler temporary */
+   vex_state->guest_r2 = 0;   /* Values for function returns ... */
+   vex_state->guest_r3 = 0;   /* ...and expression evaluation */
+   vex_state->guest_r4 = 0;   /* Function arguments */
+   vex_state->guest_r5 = 0;
+   vex_state->guest_r6 = 0;
+   vex_state->guest_r7 = 0;
+   vex_state->guest_r8 = 0;   /* Temporaries */
+   vex_state->guest_r9 = 0;
+   vex_state->guest_r10 = 0;
+   vex_state->guest_r11 = 0;
+   vex_state->guest_r12 = 0;
+   vex_state->guest_r13 = 0;
+   vex_state->guest_r14 = 0;
+   vex_state->guest_r15 = 0;
+   vex_state->guest_r16 = 0;  /* Saved temporaries */
+   vex_state->guest_r17 = 0;
+   vex_state->guest_r18 = 0;
+   vex_state->guest_r19 = 0;
+   vex_state->guest_r20 = 0;
+   vex_state->guest_r21 = 0;
+   vex_state->guest_r22 = 0;
+   vex_state->guest_r23 = 0;
+   vex_state->guest_r24 = 0;  /* Temporaries */
+   vex_state->guest_r25 = 0;
+   vex_state->guest_r26 = 0;  /* Reserved for OS kernel */
+   vex_state->guest_r27 = 0;
+   vex_state->guest_r28 = 0;  /* Global pointer */
+   vex_state->guest_r29 = 0;  /* Stack pointer */
+   vex_state->guest_r30 = 0;  /* Frame pointer */
+   vex_state->guest_r31 = 0;  /* Return address */
+   vex_state->guest_PC = 0;   /* Program counter */
+   vex_state->guest_HI = 0;   /* Multiply and divide register higher result */
+   vex_state->guest_LO = 0;   /* Multiply and divide register lower result */
+
+   /* FPU Registers */
+   vex_state->guest_f0 = 0x7ff80000;   /* Floting point general purpose registers */
+   vex_state->guest_f1 = 0x7ff80000;
+   vex_state->guest_f2 = 0x7ff80000;
+   vex_state->guest_f3 = 0x7ff80000;
+   vex_state->guest_f4 = 0x7ff80000;
+   vex_state->guest_f5 = 0x7ff80000;
+   vex_state->guest_f6 = 0x7ff80000;
+   vex_state->guest_f7 = 0x7ff80000;
+   vex_state->guest_f8 = 0x7ff80000;
+   vex_state->guest_f9 = 0x7ff80000;
+   vex_state->guest_f10 = 0x7ff80000;
+   vex_state->guest_f11 = 0x7ff80000;
+   vex_state->guest_f12 = 0x7ff80000;
+   vex_state->guest_f13 = 0x7ff80000;
+   vex_state->guest_f14 = 0x7ff80000;
+   vex_state->guest_f15 = 0x7ff80000;
+   vex_state->guest_f16 = 0x7ff80000;
+   vex_state->guest_f17 = 0x7ff80000;
+   vex_state->guest_f18 = 0x7ff80000;
+   vex_state->guest_f19 = 0x7ff80000;
+   vex_state->guest_f20 = 0x7ff80000;
+   vex_state->guest_f21 = 0x7ff80000;
+   vex_state->guest_f22 = 0x7ff80000;
+   vex_state->guest_f23 = 0x7ff80000;
+   vex_state->guest_f24 = 0x7ff80000;
+   vex_state->guest_f25 = 0x7ff80000;
+   vex_state->guest_f26 = 0x7ff80000;
+   vex_state->guest_f27 = 0x7ff80000;
+   vex_state->guest_f28 = 0x7ff80000;
+   vex_state->guest_f29 = 0x7ff80000;
+   vex_state->guest_f30 = 0x7ff80000;
+   vex_state->guest_f31 = 0x7ff80000;
+
+   vex_state->guest_FIR = 0;  /* FP implementation and revision register */
+   vex_state->guest_FCCR = 0; /* FP condition codes register */
+   vex_state->guest_FEXR = 0; /* FP exceptions register */
+   vex_state->guest_FENR = 0; /* FP enables register */
+   vex_state->guest_FCSR = 0; /* FP control/status register */
+   vex_state->guest_ULR = 0; /* TLS */
+
+   /* Various pseudo-regs mandated by Vex or Valgrind. */
+   /* Emulation warnings */
+   vex_state->guest_EMWARN = 0;
+
+   /* For clflush: record start and length of area to invalidate */
+   vex_state->guest_TISTART = 0;
+   vex_state->guest_TILEN = 0;
+   vex_state->host_EvC_COUNTER = 0;
+   vex_state->host_EvC_FAILADDR = 0;
+
+   /* Used to record the unredirected guest address at the start of
+      a translation whose start has been redirected.  By reading
+      this pseudo-register shortly afterwards, the translation can
+      find out what the corresponding no-redirection address was.
+      Note, this is only set for wrap-style redirects, not for
+      replace-style ones. */
+   vex_state->guest_NRADDR = 0;
+
+   vex_state->guest_COND = 0;
+}
+
+/*-----------------------------------------------------------*/
+/*--- Describing the mips guest state, for the benefit    ---*/
+/*--- of iropt and instrumenters.                         ---*/
+/*-----------------------------------------------------------*/
+
+/* Figure out if any part of the guest state contained in minoff
+   .. maxoff requires precise memory exceptions.  If in doubt return
+   True (but this is generates significantly slower code).  
+
+   We enforce precise exns for guest SP, PC.
+*/
+Bool guest_mips32_state_requires_precise_mem_exns(Int minoff, Int maxoff)
+{
+   Int sp_min = offsetof(VexGuestMIPS32State, guest_r29);
+   Int sp_max = sp_min + 4 - 1;
+   Int pc_min = offsetof(VexGuestMIPS32State, guest_PC);
+   Int pc_max = pc_min + 4 - 1;
+
+   if (maxoff < sp_min || minoff > sp_max) {
+      /* no overlap with sp */
+   } else {
+      return True;
+   }
+
+   if (maxoff < pc_min || minoff > pc_max) {
+      /* no overlap with pc */
+   } else {
+      return True;
+   }
+
+   /* We appear to need precise updates of R11 in order to get proper
+      stacktraces from non-optimised code. */
+   Int fp_min = offsetof(VexGuestMIPS32State, guest_r30);
+   Int fp_max = fp_min + 4 - 1;
+
+   if (maxoff < fp_min || minoff > fp_max) {
+      /* no overlap with fp */
+   } else {
+      return True;
+   }
+
+   return False;
+}
+
+VexGuestLayout mips32Guest_layout = {
+   /* Total size of the guest state, in bytes. */
+   .total_sizeB = sizeof(VexGuestMIPS32State),
+   /* Describe the stack pointer. */
+   .offset_SP = offsetof(VexGuestMIPS32State, guest_r29),
+   .sizeof_SP = 4,
+   /* Describe the frame pointer. */
+   .offset_FP = offsetof(VexGuestMIPS32State, guest_r30),
+   .sizeof_FP = 4,
+   /* Describe the instruction pointer. */
+   .offset_IP = offsetof(VexGuestMIPS32State, guest_PC),
+   .sizeof_IP = 4,
+   /* Describe any sections to be regarded by Memcheck as
+      'always-defined'. */
+   .n_alwaysDefd = 8,
+   /* ? :(  */
+   .alwaysDefd = {
+             /* 0 */ ALWAYSDEFD32(guest_r0),
+             /* 1 */ ALWAYSDEFD32(guest_r1),
+             /* 2 */ ALWAYSDEFD32(guest_EMWARN),
+             /* 3 */ ALWAYSDEFD32(guest_TISTART),
+             /* 4 */ ALWAYSDEFD32(guest_TILEN),
+             /* 5 */ ALWAYSDEFD32(guest_r29),
+             /* 6 */ ALWAYSDEFD32(guest_r31),
+             /* 7 */ ALWAYSDEFD32(guest_ULR)
+             }
+};
+
+#define ASM_VOLATILE_CASE(rd, sel) \
+         case rd: asm volatile ("mfc0 %0, $" #rd ", "#sel"\n\t" :"=r" (x) ); break;
+
+UInt mips32_dirtyhelper_mfc0(UInt rd, UInt sel)
+{
+   UInt x = 0;
+#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2))
+   switch (sel) {
+      case 0:
+         //__asm__("mfc0 %0, $1, 0" :"=r" (x));
+         switch (rd) {
+            ASM_VOLATILE_CASE(0, 0);
+            ASM_VOLATILE_CASE(1, 0);
+            ASM_VOLATILE_CASE(2, 0);
+            ASM_VOLATILE_CASE(3, 0);
+            ASM_VOLATILE_CASE(4, 0);
+            ASM_VOLATILE_CASE(5, 0);
+            ASM_VOLATILE_CASE(6, 0);
+            ASM_VOLATILE_CASE(7, 0);
+            ASM_VOLATILE_CASE(8, 0);
+            ASM_VOLATILE_CASE(9, 0);
+            ASM_VOLATILE_CASE(10, 0);
+            ASM_VOLATILE_CASE(11, 0);
+            ASM_VOLATILE_CASE(12, 0);
+            ASM_VOLATILE_CASE(13, 0);
+            ASM_VOLATILE_CASE(14, 0);
+            ASM_VOLATILE_CASE(15, 0);
+            ASM_VOLATILE_CASE(16, 0);
+            ASM_VOLATILE_CASE(17, 0);
+            ASM_VOLATILE_CASE(18, 0);
+            ASM_VOLATILE_CASE(19, 0);
+            ASM_VOLATILE_CASE(20, 0);
+            ASM_VOLATILE_CASE(21, 0);
+            ASM_VOLATILE_CASE(22, 0);
+            ASM_VOLATILE_CASE(23, 0);
+            ASM_VOLATILE_CASE(24, 0);
+            ASM_VOLATILE_CASE(25, 0);
+            ASM_VOLATILE_CASE(26, 0);
+            ASM_VOLATILE_CASE(27, 0);
+            ASM_VOLATILE_CASE(28, 0);
+            ASM_VOLATILE_CASE(29, 0);
+            ASM_VOLATILE_CASE(30, 0);
+            ASM_VOLATILE_CASE(31, 0);
+         default:
+            break;
+         }
+         break;
+      case 1:
+         //__asm__("mfc0 %0, $1, 0" :"=r" (x));
+         switch (rd) {
+            ASM_VOLATILE_CASE(0, 1);
+            ASM_VOLATILE_CASE(1, 1);
+            ASM_VOLATILE_CASE(2, 1);
+            ASM_VOLATILE_CASE(3, 1);
+            ASM_VOLATILE_CASE(4, 1);
+            ASM_VOLATILE_CASE(5, 1);
+            ASM_VOLATILE_CASE(6, 1);
+            ASM_VOLATILE_CASE(7, 1);
+            ASM_VOLATILE_CASE(8, 1);
+            ASM_VOLATILE_CASE(9, 1);
+            ASM_VOLATILE_CASE(10, 1);
+            ASM_VOLATILE_CASE(11, 1);
+            ASM_VOLATILE_CASE(12, 1);
+            ASM_VOLATILE_CASE(13, 1);
+            ASM_VOLATILE_CASE(14, 1);
+            ASM_VOLATILE_CASE(15, 1);
+            ASM_VOLATILE_CASE(16, 1);
+            ASM_VOLATILE_CASE(17, 1);
+            ASM_VOLATILE_CASE(18, 1);
+            ASM_VOLATILE_CASE(19, 1);
+            ASM_VOLATILE_CASE(20, 1);
+            ASM_VOLATILE_CASE(21, 1);
+            ASM_VOLATILE_CASE(22, 1);
+            ASM_VOLATILE_CASE(23, 1);
+            ASM_VOLATILE_CASE(24, 1);
+            ASM_VOLATILE_CASE(25, 1);
+            ASM_VOLATILE_CASE(26, 1);
+            ASM_VOLATILE_CASE(27, 1);
+            ASM_VOLATILE_CASE(28, 1);
+            ASM_VOLATILE_CASE(29, 1);
+            ASM_VOLATILE_CASE(30, 1);
+            ASM_VOLATILE_CASE(31, 1);
+         default:
+            break;
+         }
+         break;
+      case 2:
+         //__asm__("mfc0 %0, $1, 0" :"=r" (x));
+         switch (rd) {
+            ASM_VOLATILE_CASE(0, 2);
+            ASM_VOLATILE_CASE(1, 2);
+            ASM_VOLATILE_CASE(2, 2);
+            ASM_VOLATILE_CASE(3, 1);
+            ASM_VOLATILE_CASE(4, 2);
+            ASM_VOLATILE_CASE(5, 2);
+            ASM_VOLATILE_CASE(6, 2);
+            ASM_VOLATILE_CASE(7, 2);
+            ASM_VOLATILE_CASE(8, 2);
+            ASM_VOLATILE_CASE(9, 2);
+            ASM_VOLATILE_CASE(10, 2);
+            ASM_VOLATILE_CASE(11, 2);
+            ASM_VOLATILE_CASE(12, 2);
+            ASM_VOLATILE_CASE(13, 2);
+            ASM_VOLATILE_CASE(14, 2);
+            ASM_VOLATILE_CASE(15, 2);
+            ASM_VOLATILE_CASE(16, 2);
+            ASM_VOLATILE_CASE(17, 2);
+            ASM_VOLATILE_CASE(18, 2);
+            ASM_VOLATILE_CASE(19, 2);
+            ASM_VOLATILE_CASE(20, 2);
+            ASM_VOLATILE_CASE(21, 2);
+            ASM_VOLATILE_CASE(22, 2);
+            ASM_VOLATILE_CASE(23, 2);
+            ASM_VOLATILE_CASE(24, 2);
+            ASM_VOLATILE_CASE(25, 2);
+            ASM_VOLATILE_CASE(26, 2);
+            ASM_VOLATILE_CASE(27, 2);
+            ASM_VOLATILE_CASE(28, 2);
+            ASM_VOLATILE_CASE(29, 2);
+            ASM_VOLATILE_CASE(30, 2);
+            ASM_VOLATILE_CASE(31, 2);
+         default:
+            break;
+         }
+         break;
+      case 3:
+         //__asm__("mfc0 %0, $1, 0" :"=r" (x));
+         switch (rd) {
+            ASM_VOLATILE_CASE(0, 3);
+            ASM_VOLATILE_CASE(1, 3);
+            ASM_VOLATILE_CASE(2, 3);
+            ASM_VOLATILE_CASE(3, 3);
+            ASM_VOLATILE_CASE(4, 3);
+            ASM_VOLATILE_CASE(5, 3);
+            ASM_VOLATILE_CASE(6, 3);
+            ASM_VOLATILE_CASE(7, 3);
+            ASM_VOLATILE_CASE(8, 3);
+            ASM_VOLATILE_CASE(9, 3);
+            ASM_VOLATILE_CASE(10, 3);
+            ASM_VOLATILE_CASE(11, 3);
+            ASM_VOLATILE_CASE(12, 3);
+            ASM_VOLATILE_CASE(13, 3);
+            ASM_VOLATILE_CASE(14, 3);
+            ASM_VOLATILE_CASE(15, 3);
+            ASM_VOLATILE_CASE(16, 3);
+            ASM_VOLATILE_CASE(17, 3);
+            ASM_VOLATILE_CASE(18, 3);
+            ASM_VOLATILE_CASE(19, 3);
+            ASM_VOLATILE_CASE(20, 3);
+            ASM_VOLATILE_CASE(21, 3);
+            ASM_VOLATILE_CASE(22, 3);
+            ASM_VOLATILE_CASE(23, 3);
+            ASM_VOLATILE_CASE(24, 3);
+            ASM_VOLATILE_CASE(25, 3);
+            ASM_VOLATILE_CASE(26, 3);
+            ASM_VOLATILE_CASE(27, 3);
+            ASM_VOLATILE_CASE(28, 3);
+            ASM_VOLATILE_CASE(29, 3);
+            ASM_VOLATILE_CASE(30, 3);
+            ASM_VOLATILE_CASE(31, 3);
+         default:
+            break;
+         }
+         break;
+      case 4:
+         //__asm__("mfc0 %0, $1, 0" :"=r" (x));
+         switch (rd) {
+            ASM_VOLATILE_CASE(0, 4);
+            ASM_VOLATILE_CASE(1, 4);
+            ASM_VOLATILE_CASE(2, 4);
+            ASM_VOLATILE_CASE(3, 4);
+            ASM_VOLATILE_CASE(4, 4);
+            ASM_VOLATILE_CASE(5, 4);
+            ASM_VOLATILE_CASE(6, 4);
+            ASM_VOLATILE_CASE(7, 4);
+            ASM_VOLATILE_CASE(8, 4);
+            ASM_VOLATILE_CASE(9, 4);
+            ASM_VOLATILE_CASE(10, 4);
+            ASM_VOLATILE_CASE(11, 4);
+            ASM_VOLATILE_CASE(12, 4);
+            ASM_VOLATILE_CASE(13, 4);
+            ASM_VOLATILE_CASE(14, 4);
+            ASM_VOLATILE_CASE(15, 4);
+            ASM_VOLATILE_CASE(16, 4);
+            ASM_VOLATILE_CASE(17, 4);
+            ASM_VOLATILE_CASE(18, 4);
+            ASM_VOLATILE_CASE(19, 4);
+            ASM_VOLATILE_CASE(20, 4);
+            ASM_VOLATILE_CASE(21, 4);
+            ASM_VOLATILE_CASE(22, 4);
+            ASM_VOLATILE_CASE(23, 4);
+            ASM_VOLATILE_CASE(24, 4);
+            ASM_VOLATILE_CASE(25, 4);
+            ASM_VOLATILE_CASE(26, 4);
+            ASM_VOLATILE_CASE(27, 4);
+            ASM_VOLATILE_CASE(28, 4);
+            ASM_VOLATILE_CASE(29, 4);
+            ASM_VOLATILE_CASE(30, 4);
+            ASM_VOLATILE_CASE(31, 4);
+         default:
+            break;
+         }
+         break;
+      case 5:
+         //__asm__("mfc0 %0, $1, 0" :"=r" (x));
+         switch (rd) {
+            ASM_VOLATILE_CASE(0, 5);
+            ASM_VOLATILE_CASE(1, 5);
+            ASM_VOLATILE_CASE(2, 5);
+            ASM_VOLATILE_CASE(3, 5);
+            ASM_VOLATILE_CASE(4, 5);
+            ASM_VOLATILE_CASE(5, 5);
+            ASM_VOLATILE_CASE(6, 5);
+            ASM_VOLATILE_CASE(7, 5);
+            ASM_VOLATILE_CASE(8, 5);
+            ASM_VOLATILE_CASE(9, 5);
+            ASM_VOLATILE_CASE(10, 5);
+            ASM_VOLATILE_CASE(11, 5);
+            ASM_VOLATILE_CASE(12, 5);
+            ASM_VOLATILE_CASE(13, 5);
+            ASM_VOLATILE_CASE(14, 5);
+            ASM_VOLATILE_CASE(15, 5);
+            ASM_VOLATILE_CASE(16, 5);
+            ASM_VOLATILE_CASE(17, 5);
+            ASM_VOLATILE_CASE(18, 5);
+            ASM_VOLATILE_CASE(19, 5);
+            ASM_VOLATILE_CASE(20, 5);
+            ASM_VOLATILE_CASE(21, 5);
+            ASM_VOLATILE_CASE(22, 5);
+            ASM_VOLATILE_CASE(23, 5);
+            ASM_VOLATILE_CASE(24, 5);
+            ASM_VOLATILE_CASE(25, 5);
+            ASM_VOLATILE_CASE(26, 5);
+            ASM_VOLATILE_CASE(27, 5);
+            ASM_VOLATILE_CASE(28, 5);
+            ASM_VOLATILE_CASE(29, 5);
+            ASM_VOLATILE_CASE(30, 5);
+            ASM_VOLATILE_CASE(31, 5);
+         default:
+            break;
+         }
+         break;
+      case 6:
+         //__asm__("mfc0 %0, $1, 0" :"=r" (x));
+         switch (rd) {
+            ASM_VOLATILE_CASE(0, 6);
+            ASM_VOLATILE_CASE(1, 6);
+            ASM_VOLATILE_CASE(2, 6);
+            ASM_VOLATILE_CASE(3, 6);
+            ASM_VOLATILE_CASE(4, 6);
+            ASM_VOLATILE_CASE(5, 6);
+            ASM_VOLATILE_CASE(6, 6);
+            ASM_VOLATILE_CASE(7, 6);
+            ASM_VOLATILE_CASE(8, 6);
+            ASM_VOLATILE_CASE(9, 6);
+            ASM_VOLATILE_CASE(10, 6);
+            ASM_VOLATILE_CASE(11, 6);
+            ASM_VOLATILE_CASE(12, 6);
+            ASM_VOLATILE_CASE(13, 6);
+            ASM_VOLATILE_CASE(14, 6);
+            ASM_VOLATILE_CASE(15, 6);
+            ASM_VOLATILE_CASE(16, 6);
+            ASM_VOLATILE_CASE(17, 6);
+            ASM_VOLATILE_CASE(18, 6);
+            ASM_VOLATILE_CASE(19, 6);
+            ASM_VOLATILE_CASE(20, 6);
+            ASM_VOLATILE_CASE(21, 6);
+            ASM_VOLATILE_CASE(22, 6);
+            ASM_VOLATILE_CASE(23, 6);
+            ASM_VOLATILE_CASE(24, 6);
+            ASM_VOLATILE_CASE(25, 6);
+            ASM_VOLATILE_CASE(26, 6);
+            ASM_VOLATILE_CASE(27, 6);
+            ASM_VOLATILE_CASE(28, 6);
+            ASM_VOLATILE_CASE(29, 6);
+            ASM_VOLATILE_CASE(30, 6);
+            ASM_VOLATILE_CASE(31, 6);
+         default:
+            break;
+         }
+         break;
+      case 7:
+         //__asm__("mfc0 %0, $1, 0" :"=r" (x));
+         switch (rd) {
+            ASM_VOLATILE_CASE(0, 7);
+            ASM_VOLATILE_CASE(1, 7);
+            ASM_VOLATILE_CASE(2, 7);
+            ASM_VOLATILE_CASE(3, 7);
+            ASM_VOLATILE_CASE(4, 7);
+            ASM_VOLATILE_CASE(5, 7);
+            ASM_VOLATILE_CASE(6, 7);
+            ASM_VOLATILE_CASE(7, 7);
+            ASM_VOLATILE_CASE(8, 7);
+            ASM_VOLATILE_CASE(9, 7);
+            ASM_VOLATILE_CASE(10, 7);
+            ASM_VOLATILE_CASE(11, 7);
+            ASM_VOLATILE_CASE(12, 7);
+            ASM_VOLATILE_CASE(13, 7);
+            ASM_VOLATILE_CASE(14, 7);
+            ASM_VOLATILE_CASE(15, 7);
+            ASM_VOLATILE_CASE(16, 7);
+            ASM_VOLATILE_CASE(17, 7);
+            ASM_VOLATILE_CASE(18, 7);
+            ASM_VOLATILE_CASE(19, 7);
+            ASM_VOLATILE_CASE(20, 7);
+            ASM_VOLATILE_CASE(21, 7);
+            ASM_VOLATILE_CASE(22, 7);
+            ASM_VOLATILE_CASE(23, 7);
+            ASM_VOLATILE_CASE(24, 7);
+            ASM_VOLATILE_CASE(25, 7);
+            ASM_VOLATILE_CASE(26, 7);
+            ASM_VOLATILE_CASE(27, 7);
+            ASM_VOLATILE_CASE(28, 7);
+            ASM_VOLATILE_CASE(29, 7);
+            ASM_VOLATILE_CASE(30, 7);
+            ASM_VOLATILE_CASE(31, 7);
+         default:
+            break;
+         }
+      break;
+
+   default:
+      break;
+   }
+#endif
+   return x;
+}
+
+#undef ASM_VOLATILE_CASE
+
+#define ASM_VOLATILE_CASE(rd, sel) \
+   case rd: asm volatile ("dmfc0 %0, $" #rd ", "#sel"\n\t" :"=r" (x) ); break;
+
+#define ASM_VOLATILE_SYNC(stype) \
+        asm volatile ("sync \n\t");
+
+void mips32_dirtyhelper_sync(UInt stype)
+{
+#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2))
+   ASM_VOLATILE_SYNC(0);
+#endif
+}
+
+/*---------------------------------------------------------------*/
+/*--- end                                guest_mips_helpers.c ---*/
+/*---------------------------------------------------------------*/
diff --git a/priv/guest_mips_toIR.c b/priv/guest_mips_toIR.c
new file mode 100644
index 0000000..80e6d3f
--- /dev/null
+++ b/priv/guest_mips_toIR.c
@@ -0,0 +1,3518 @@
+
+/*--------------------------------------------------------------------*/
+/*--- begin                                      guest_mips_toIR.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2010-2012 RT-RK
+      mips-valgrind@rt-rk.com
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Translates MIPS code to IR. */
+
+#include "libvex_basictypes.h"
+#include "libvex_ir.h"
+#include "libvex.h"
+#include "libvex_guest_mips32.h"
+
+#include "main_util.h"
+#include "main_globals.h"
+#include "guest_generic_bb_to_IR.h"
+#include "guest_mips_defs.h"
+
+/*------------------------------------------------------------*/
+/*--- Globals                                              ---*/
+/*------------------------------------------------------------*/
+
+/* These are set at the start of the translation of a instruction, so
+   that we don't have to pass them around endlessly.  CONST means does
+   not change during translation of the instruction.
+*/
+
+/* CONST: is the host bigendian?  This has to do with float vs double
+   register accesses on VFP, but it's complex and not properly thought
+   out. */
+static Bool host_is_bigendian;
+
+/* Pointer to the guest code area. */
+static UChar *guest_code;
+
+/* The guest address corresponding to guest_code[0]. */
+static Addr32 guest_PC_bbstart;
+
+/* CONST: The guest address for the instruction currently being
+   translated. */
+static Addr32 guest_PC_curr_instr;
+
+/* MOD: The IRSB* into which we're generating code. */
+static IRSB *irsb;
+
+/* Is our guest binary 32 or 64bit?  Set at each call to
+   disInstr_MIPS below. */
+static Bool mode64 = False;
+
+/*------------------------------------------------------------*/
+/*--- Debugging output                                     ---*/
+/*------------------------------------------------------------*/
+
+#define DIP(format, args...)           \
+   if (vex_traceflags & VEX_TRACE_FE)  \
+      vex_printf(format, ## args)
+
+/*------------------------------------------------------------*/
+/*--- Helper bits and pieces for deconstructing the        ---*/
+/*--- mips insn stream.                                    ---*/
+/*------------------------------------------------------------*/
+
+/* ---------------- Integer registers ---------------- */
+
+static UInt integerGuestRegOffset(UInt iregNo)
+{
+   /* Do we care about endianness here?  We do if sub-parts of integer
+      registers are accessed, but I don't think that ever happens on
+      MIPS. */
+   UInt ret;
+   switch (iregNo) {
+      case 0:
+         ret = offsetof(VexGuestMIPS32State, guest_r0); break;
+      case 1:
+         ret = offsetof(VexGuestMIPS32State, guest_r1); break;
+      case 2:
+         ret = offsetof(VexGuestMIPS32State, guest_r2); break;
+      case 3:
+         ret = offsetof(VexGuestMIPS32State, guest_r3); break;
+      case 4:
+         ret = offsetof(VexGuestMIPS32State, guest_r4); break;
+      case 5:
+         ret = offsetof(VexGuestMIPS32State, guest_r5); break;
+      case 6:
+         ret = offsetof(VexGuestMIPS32State, guest_r6); break;
+      case 7:
+         ret = offsetof(VexGuestMIPS32State, guest_r7); break;
+      case 8:
+         ret = offsetof(VexGuestMIPS32State, guest_r8); break;
+      case 9:
+         ret = offsetof(VexGuestMIPS32State, guest_r9); break;
+      case 10:
+         ret = offsetof(VexGuestMIPS32State, guest_r10); break;
+      case 11:
+         ret = offsetof(VexGuestMIPS32State, guest_r11); break;
+      case 12:
+         ret = offsetof(VexGuestMIPS32State, guest_r12); break;
+      case 13:
+         ret = offsetof(VexGuestMIPS32State, guest_r13); break;
+      case 14:
+         ret = offsetof(VexGuestMIPS32State, guest_r14); break;
+      case 15:
+         ret = offsetof(VexGuestMIPS32State, guest_r15); break;
+      case 16:
+         ret = offsetof(VexGuestMIPS32State, guest_r16); break;
+      case 17:
+         ret = offsetof(VexGuestMIPS32State, guest_r17); break;
+      case 18:
+         ret = offsetof(VexGuestMIPS32State, guest_r18); break;
+      case 19:
+         ret = offsetof(VexGuestMIPS32State, guest_r19); break;
+      case 20:
+         ret = offsetof(VexGuestMIPS32State, guest_r20); break;
+      case 21:
+         ret = offsetof(VexGuestMIPS32State, guest_r21); break;
+      case 22:
+         ret = offsetof(VexGuestMIPS32State, guest_r22); break;
+      case 23:
+         ret = offsetof(VexGuestMIPS32State, guest_r23); break;
+      case 24:
+         ret = offsetof(VexGuestMIPS32State, guest_r24); break;
+      case 25:
+         ret = offsetof(VexGuestMIPS32State, guest_r25); break;
+      case 26:
+         ret = offsetof(VexGuestMIPS32State, guest_r26); break;
+      case 27:
+         ret = offsetof(VexGuestMIPS32State, guest_r27); break;
+      case 28:
+         ret = offsetof(VexGuestMIPS32State, guest_r28); break;
+      case 29:
+         ret = offsetof(VexGuestMIPS32State, guest_r29); break;
+      case 30:
+         ret = offsetof(VexGuestMIPS32State, guest_r30); break;
+      case 31:
+         ret = offsetof(VexGuestMIPS32State, guest_r31); break;
+      default:
+         vassert(0);
+         break;
+   }
+   return ret;
+}
+
+#define OFFB_PC     offsetof(VexGuestMIPS32State, guest_PC)
+
+/* ---------------- Floating point registers ---------------- */
+
+static UInt floatGuestRegOffset(UInt fregNo)
+{
+   vassert(fregNo < 32);
+   UInt ret;
+   switch (fregNo) {
+      case 0:
+         ret = offsetof(VexGuestMIPS32State, guest_f0); break;
+      case 1:
+         ret = offsetof(VexGuestMIPS32State, guest_f1); break;
+      case 2:
+         ret = offsetof(VexGuestMIPS32State, guest_f2); break;
+      case 3:
+         ret = offsetof(VexGuestMIPS32State, guest_f3); break;
+      case 4:
+         ret = offsetof(VexGuestMIPS32State, guest_f4); break;
+      case 5:
+         ret = offsetof(VexGuestMIPS32State, guest_f5); break;
+      case 6:
+         ret = offsetof(VexGuestMIPS32State, guest_f6); break;
+      case 7:
+         ret = offsetof(VexGuestMIPS32State, guest_f7); break;
+      case 8:
+         ret = offsetof(VexGuestMIPS32State, guest_f8); break;
+      case 9:
+         ret = offsetof(VexGuestMIPS32State, guest_f9); break;
+      case 10:
+         ret = offsetof(VexGuestMIPS32State, guest_f10); break;
+      case 11:
+         ret = offsetof(VexGuestMIPS32State, guest_f11); break;
+      case 12:
+         ret = offsetof(VexGuestMIPS32State, guest_f12); break;
+      case 13:
+         ret = offsetof(VexGuestMIPS32State, guest_f13); break;
+      case 14:
+         ret = offsetof(VexGuestMIPS32State, guest_f14); break;
+      case 15:
+         ret = offsetof(VexGuestMIPS32State, guest_f15); break;
+      case 16:
+         ret = offsetof(VexGuestMIPS32State, guest_f16); break;
+      case 17:
+         ret = offsetof(VexGuestMIPS32State, guest_f17); break;
+      case 18:
+         ret = offsetof(VexGuestMIPS32State, guest_f18); break;
+      case 19:
+         ret = offsetof(VexGuestMIPS32State, guest_f19); break;
+      case 20:
+         ret = offsetof(VexGuestMIPS32State, guest_f20); break;
+      case 21:
+         ret = offsetof(VexGuestMIPS32State, guest_f21); break;
+      case 22:
+         ret = offsetof(VexGuestMIPS32State, guest_f22); break;
+      case 23:
+         ret = offsetof(VexGuestMIPS32State, guest_f23); break;
+      case 24:
+         ret = offsetof(VexGuestMIPS32State, guest_f24); break;
+      case 25:
+         ret = offsetof(VexGuestMIPS32State, guest_f25); break;
+      case 26:
+         ret = offsetof(VexGuestMIPS32State, guest_f26); break;
+      case 27:
+         ret = offsetof(VexGuestMIPS32State, guest_f27); break;
+      case 28:
+         ret = offsetof(VexGuestMIPS32State, guest_f28); break;
+      case 29:
+         ret = offsetof(VexGuestMIPS32State, guest_f29); break;
+      case 30:
+         ret = offsetof(VexGuestMIPS32State, guest_f30); break;
+      case 31:
+         ret = offsetof(VexGuestMIPS32State, guest_f31); break;
+      default:
+         vassert(0);
+         break;
+   }
+   return ret;
+}
+
+/* Do a endian load of a 32-bit word, regardless of the
+   endianness of the underlying host. */
+static inline UInt getUInt(UChar * p)
+{
+   UInt w = 0;
+#if defined (_MIPSEL)
+   w = (w << 8) | p[3];
+   w = (w << 8) | p[2];
+   w = (w << 8) | p[1];
+   w = (w << 8) | p[0];
+#elif defined (_MIPSEB)
+   w = (w << 8) | p[0];
+   w = (w << 8) | p[1];
+   w = (w << 8) | p[2];
+   w = (w << 8) | p[3];
+#endif
+   return w;
+}
+
+#define BITS2(_b1,_b0) \
+   (((_b1) << 1) | (_b0))
+
+#define BITS3(_b2,_b1,_b0)                      \
+  (((_b2) << 2) | ((_b1) << 1) | (_b0))
+
+#define BITS4(_b3,_b2,_b1,_b0) \
+   (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
+
+#define BITS5(_b4,_b3,_b2,_b1,_b0)  \
+   (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0)))
+
+#define BITS6(_b5,_b4,_b3,_b2,_b1,_b0)  \
+   ((BITS2((_b5),(_b4)) << 4) \
+    | BITS4((_b3),(_b2),(_b1),(_b0)))
+
+#define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0)  \
+   ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
+    | BITS4((_b3),(_b2),(_b1),(_b0)))
+
+#define LOAD_STORE_PATTERN \
+    t1 = newTemp(Ity_I32); \
+    assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); \
+
+#define LWX_SWX_PATTERN \
+   t2 = newTemp(Ity_I32); \
+   assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \
+   t4 = newTemp(Ity_I32); \
+   assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003)))
+
+#define SXXV_PATTERN(op) \
+   putIReg(rd, binop(op, \
+         getIReg(rt), \
+            unop(Iop_32to8, \
+               binop(Iop_And32, \
+                  getIReg(rs), \
+                  mkU32(0x0000001F) \
+               ) \
+            ) \
+         ) \
+      )
+
+#define SXX_PATTERN(op) \
+   putIReg(rd, binop(op, getIReg(rt), mkU8(sa)));
+
+#define ALU_PATTERN(op) \
+   putIReg(rd, binop(op, getIReg(rs), getIReg(rt)));
+
+#define ALUI_PATTERN(op) \
+   putIReg(rt, binop(op, getIReg(rs), mkU32(imm)));
+
+#define ALUI_PATTERN64(op) \
+   putIReg(rt, binop(op, getIReg(rs), mkU64(imm)));
+
+#define FP_CONDITIONAL_CODE \
+    t3 = newTemp(Ity_I32);  \
+    assign(t3, binop(Iop_And32, IRExpr_Mux0X( unop(Iop_1Uto8, \
+               binop(Iop_CmpEQ32, mkU32(cc), mkU32(0))), \
+               binop(Iop_Shr32, getFCSR(), mkU8(24+cc)),  \
+               binop(Iop_Shr32, getFCSR(), mkU8(23))), mkU32(0x1)));
+
+/*------------------------------------------------------------*/
+/*---                           Field helpers              ---*/
+/*------------------------------------------------------------*/
+
+static UInt get_opcode(UInt mipsins)
+{
+   return (0xFC000000 & mipsins) >> 26;
+}
+
+static UInt get_rs(UInt mipsins)
+{
+   return (0x03E00000 & mipsins) >> 21;
+}
+
+static UInt get_rt(UInt mipsins)
+{
+   return (0x001F0000 & mipsins) >> 16;
+}
+
+static UInt get_imm(UInt mipsins)
+{
+   return (0x0000FFFF & mipsins);
+}
+
+static UInt get_instr_index(UInt mipsins)
+{
+   return (0x03FFFFFF & mipsins);
+}
+
+static UInt get_rd(UInt mipsins)
+{
+   return (0x0000F800 & mipsins) >> 11;
+}
+
+static UInt get_sa(UInt mipsins)
+{
+   return (0x000007C0 & mipsins) >> 6;
+}
+
+static UInt get_function(UInt mipsins)
+{
+   return (0x0000003F & mipsins);
+}
+
+static UInt get_ft(UInt mipsins)
+{
+   return (0x001F0000 & mipsins) >> 16;
+}
+
+static UInt get_fs(UInt mipsins)
+{
+   return (0x0000F800 & mipsins) >> 11;
+}
+
+static UInt get_fd(UInt mipsins)
+{
+   return (0x000007C0 & mipsins) >> 6;
+}
+
+static UInt get_mov_cc(UInt mipsins)
+{
+   return (0x001C0000 & mipsins) >> 18;
+}
+
+static UInt get_bc1_cc(UInt mipsins)
+{
+   return (0x001C0000 & mipsins) >> 18;
+}
+
+static UInt get_fpc_cc(UInt mipsins)
+{
+   return (0x00000700 & mipsins) >> 8;
+}
+
+static UInt get_tf(UInt mipsins)
+{
+   return (0x00010000 & mipsins) >> 16;
+}
+
+static UInt get_nd(UInt mipsins)
+{
+   return (0x00020000 & mipsins) >> 17;
+}
+
+static UInt get_fmt(UInt mipsins)
+{
+   return (0x03E00000 & mipsins) >> 21;
+}
+
+static UInt get_FC(UInt mipsins)
+{
+   return (0x000000F0 & mipsins) >> 4;
+}
+
+static UInt get_cond(UInt mipsins)
+{
+   return (0x0000000F & mipsins);
+}
+
+/* for break & syscall */
+static UInt get_code(UInt mipsins)
+{
+   return (0xFFC0 & mipsins) >> 6;
+}
+
+static UInt get_lsb(UInt mipsins)
+{
+   return (0x7C0 & mipsins) >> 6;
+}
+
+static UInt get_msb(UInt mipsins)
+{
+   return (0x0000F800 & mipsins) >> 11;
+}
+
+static UInt get_rot(UInt mipsins)
+{
+   return (0x00200000 & mipsins) >> 21;
+}
+
+static UInt get_rotv(UInt mipsins)
+{
+   return (0x00000040 & mipsins) >> 6;
+}
+
+static UInt get_sel(UInt mipsins)
+{
+   return (0x00000007 & mipsins);
+}
+
+static Bool branch_or_jump(UChar * addr)
+{
+   UInt fmt;
+   UInt cins = getUInt(addr);
+
+   UInt opcode = get_opcode(cins);
+   UInt rt = get_rt(cins);
+   UInt function = get_function(cins);
+
+   /* bgtz, blez, bne, beq, jal */
+   if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04 
+       || opcode == 0x03 || opcode == 0x02) {
+      return True;
+   }
+
+   /* bgez */
+   if (opcode == 0x01 && rt == 0x01) {
+      return True;
+   }
+
+   /* bgezal */
+   if (opcode == 0x01 && rt == 0x11) {
+      return True;
+   }
+
+   /* bltzal */
+   if (opcode == 0x01 && rt == 0x10) {
+      return True;
+   }
+
+   /* bltz */
+   if (opcode == 0x01 && rt == 0x00) {
+      return True;
+   }
+
+   /* jalr */
+   if (opcode == 0x00 && function == 0x09) {
+      return True;
+   }
+
+   /* jr */
+   if (opcode == 0x00 && function == 0x08) {
+      return True;
+   }
+
+   if (opcode == 0x11) {
+      /*bc1f & bc1t */
+      fmt = get_fmt(cins);
+      if (fmt == 0x08) {
+         return True;
+      }
+   }
+
+   return False;
+}
+
+static Bool is_Branch_or_Jump_and_Link(UChar * addr)
+{
+   UInt cins = getUInt(addr);
+
+   UInt opcode = get_opcode(cins);
+   UInt rt = get_rt(cins);
+   UInt function = get_function(cins);
+
+   /* jal */
+   if (opcode == 0x02) {
+      return True;
+   }
+
+   /* bgezal */
+   if (opcode == 0x01 && rt == 0x11) {
+      return True;
+   }
+
+   /* bltzal */
+   if (opcode == 0x01 && rt == 0x10) {
+      return True;
+   }
+
+   /* jalr */
+   if (opcode == 0x00 && function == 0x09) {
+      return True;
+   }
+
+   return False;
+}
+
+static Bool branch_or_link_likely(UChar * addr)
+{
+   UInt cins = getUInt(addr);
+   UInt opcode = get_opcode(cins);
+   UInt rt = get_rt(cins);
+
+   /* bgtzl, blezl, bnel, beql */
+   if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14)
+      return True;
+
+   /* bgezl */
+   if (opcode == 0x01 && rt == 0x03)
+      return True;
+
+   /* bgezall */
+   if (opcode == 0x01 && rt == 0x13)
+      return True;
+
+   /* bltzall */
+   if (opcode == 0x01 && rt == 0x12)
+      return True;
+
+   /* bltzl */
+   if (opcode == 0x01 && rt == 0x02)
+      return True;
+
+   return False;
+}
+
+/*------------------------------------------------------------*/
+/*--- Helper bits and pieces for creating IR fragments.    ---*/
+/*------------------------------------------------------------*/
+
+static IRExpr *mkU8(UInt i)
+{
+   vassert(i < 256);
+   return IRExpr_Const(IRConst_U8((UChar) i));
+}
+
+/* Create an expression node for a 32-bit integer constant */
+static IRExpr *mkU32(UInt i)
+{
+   return IRExpr_Const(IRConst_U32(i));
+}
+
+/* Create an expression node for a 64-bit integer constant */
+static IRExpr *mkU64(ULong i)
+{
+   return IRExpr_Const(IRConst_U64(i));
+}
+
+static IRExpr *mkexpr(IRTemp tmp)
+{
+   return IRExpr_RdTmp(tmp);
+}
+
+static IRExpr *unop(IROp op, IRExpr * a)
+{
+   return IRExpr_Unop(op, a);
+}
+
+static IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2)
+{
+   return IRExpr_Binop(op, a1, a2);
+}
+
+static IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3)
+{
+   return IRExpr_Triop(op, a1, a2, a3);
+}
+
+static IRExpr *load(IRType ty, IRExpr * addr)
+{
+   IRExpr *load1 = NULL;
+#if defined (_MIPSEL)
+   load1 = IRExpr_Load(Iend_LE, ty, addr);
+#elif defined (_MIPSEB)
+   load1 = IRExpr_Load(Iend_BE, ty, addr);
+#endif
+   return load1;
+}
+
+/* Add a statement to the list held by "irsb". */
+static void stmt(IRStmt * st)
+{
+   addStmtToIRSB(irsb, st);
+}
+
+static void assign(IRTemp dst, IRExpr * e)
+{
+   stmt(IRStmt_WrTmp(dst, e));
+}
+
+static void store(IRExpr * addr, IRExpr * data)
+{
+#if defined (_MIPSEL)
+   stmt(IRStmt_Store(Iend_LE, addr, data));
+#elif defined (_MIPSEB)
+   stmt(IRStmt_Store(Iend_BE, addr, data));
+#endif
+}
+
+/* Generate a new temporary of the given type. */
+static IRTemp newTemp(IRType ty)
+{
+   vassert(isPlausibleIRType(ty));
+   return newIRTemp(irsb->tyenv, ty);
+}
+
+/* Generate an expression for SRC rotated right by ROT. */
+static IRExpr *genROR32(IRExpr * src, Int rot)
+{
+   vassert(rot >= 0 && rot < 32);
+   if (rot == 0)
+      return src;
+   return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)),
+                          binop(Iop_Shr32, src, mkU8(rot)));
+}
+
+static IRExpr *genRORV32(IRExpr * src, IRExpr * rs)
+{
+   IRTemp t0 = newTemp(Ity_I8);
+   IRTemp t1 = newTemp(Ity_I8);
+
+   assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F))));
+   assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0)));
+   return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)),
+                          binop(Iop_Shr32, src, mkexpr(t0)));
+}
+
+static UInt extend_s_16to32(UInt x)
+{
+   return (UInt) ((((Int) x) << 16) >> 16);
+}
+
+static UInt extend_s_18to32(UInt x)
+{
+   return (UInt) ((((Int) x) << 14) >> 14);
+}
+
+static void jmp_lit( /*MOD*/DisResult* dres,
+                     IRJumpKind kind, Addr32 d32 )
+{
+   vassert(dres->whatNext    == Dis_Continue);
+   vassert(dres->len         == 0);
+   vassert(dres->continueAt  == 0);
+   vassert(dres->jk_StopHere == Ijk_INVALID);
+   dres->whatNext    = Dis_StopHere;
+   dres->jk_StopHere = kind;
+   stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) );
+}
+
+/* Fetch a byte from the guest insn stream. */
+static UChar getIByte(Int delta)
+{
+   return guest_code[delta];
+}
+
+static IRExpr *getIReg(UInt iregNo)
+{
+   IRType ty = mode64 ? Ity_I64 : Ity_I32;
+   vassert(iregNo < 32);
+   return IRExpr_Get(integerGuestRegOffset(iregNo), ty);
+}
+
+static IRExpr *getHI(void)
+{
+   return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32);
+}
+
+static IRExpr *getLO(void)
+{
+   return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32);
+}
+
+static IRExpr *getFCSR(void)
+{
+   return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32);
+}
+
+static void putFCSR(IRExpr * e)
+{
+   stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
+}
+
+static IRExpr *getULR(void)
+{
+   return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32);
+}
+
+static void putIReg(UInt archreg, IRExpr * e)
+{
+   IRType ty = mode64 ? Ity_I64 : Ity_I32;
+   vassert(archreg < 32);
+   vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
+   if (archreg != 0)
+      stmt(IRStmt_Put(integerGuestRegOffset(archreg), e));
+}
+
+static void putLO(IRExpr * e)
+{
+   stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e));
+}
+
+static void putHI(IRExpr * e)
+{
+   stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e));
+}
+
+static void putPC(IRExpr * e)
+{
+   stmt(IRStmt_Put(OFFB_PC, e));
+}
+
+static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined)
+{
+   vassert(ty == Ity_I32 || ty == Ity_I64);
+   if (ty == Ity_I32)
+      return src;
+   return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
+}
+
+/* Narrow 8/16/32 bit int expr to 8/16/32.  Clearly only some
+   of these combinations make sense. */
+static IRExpr *narrowTo(IRType dst_ty, IRExpr * e)
+{
+   IRType src_ty = typeOfIRExpr(irsb->tyenv, e);
+   if (src_ty == dst_ty)
+      return e;
+   if (src_ty == Ity_I32 && dst_ty == Ity_I16)
+      return unop(Iop_32to16, e);
+   if (src_ty == Ity_I32 && dst_ty == Ity_I8)
+      return unop(Iop_32to8, e);
+   if (src_ty == Ity_I64 && dst_ty == Ity_I8) {
+      vassert(mode64);
+      return unop(Iop_64to8, e);
+   }
+   if (src_ty == Ity_I64 && dst_ty == Ity_I16) {
+      vassert(mode64);
+      return unop(Iop_64to16, e);
+   }
+
+   if (vex_traceflags & VEX_TRACE_FE) {
+      vex_printf("\nsrc, dst tys are: ");
+      ppIRType(src_ty);
+      vex_printf(", ");
+      ppIRType(dst_ty);
+      vex_printf("\n");
+   }
+
+   vpanic("narrowTo(mips)");
+   return 0;
+}
+
+static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src)
+{
+   vassert(ty == Ity_I32 || ty == Ity_I64);
+   return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
+}
+
+static IRExpr *getLoFromF64(IRType ty, IRExpr * src)
+{
+   vassert(ty == Ity_F32 || ty == Ity_F64);
+   if (ty == Ity_F64) {
+      IRTemp t0, t1;
+      t0 = newTemp(Ity_I64);
+      t1 = newTemp(Ity_I32);
+      assign(t0, unop(Iop_ReinterpF64asI64, src));
+      assign(t1, unop(Iop_64to32, mkexpr(t0)));
+      return unop(Iop_ReinterpI32asF32, mkexpr(t1));
+   } else
+      return src;
+}
+
+static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src)
+{
+   vassert(ty == Ity_F32 || ty == Ity_F64);
+   return ty == Ity_F64 ? unop(Iop_F32toF64, src) : src;
+}
+
+static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm)
+{
+   ULong branch_offset;
+   IRTemp t0;
+
+   /* PC = PC + (SignExtend(signed_immed_24) << 2)
+      An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) 
+      is added to the address of the instruction following
+      the branch (not the branch itself), in the branch delay slot, to form 
+      a PC-relative effective target address. */
+   branch_offset = extend_s_18to32(imm << 2);
+
+   t0 = newTemp(Ity_I1);
+   assign(t0, guard);
+
+   stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring, 
+                    IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC));
+
+   irsb->jumpkind = Ijk_Boring;
+
+   return mkU32(guest_PC_curr_instr + 4 + branch_offset);
+}
+
+static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set)
+{
+   ULong branch_offset;
+   IRTemp t0;
+
+   if (link) {    // LR (GPR31) = addr of the 2nd instr after branch instr
+      putIReg(31, mkU32(guest_PC_curr_instr + 8));
+   }
+
+   /* PC = PC + (SignExtend(signed_immed_24) << 2)
+      An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) 
+      is added to the address of the instruction following
+      the branch (not the branch itself), in the branch delay slot, to form 
+      a PC-relative effective target address. */
+
+   branch_offset = extend_s_18to32(imm << 2);
+
+   t0 = newTemp(Ity_I1);
+   assign(t0, guard);
+   *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
+                   IRConst_U32(guest_PC_curr_instr + 4 + (UInt) branch_offset),
+                   OFFB_PC);
+}
+
+static IRExpr *getFReg(UInt dregNo)
+{
+   vassert(dregNo < 32);
+   IRType ty = mode64 ? Ity_F64 : Ity_F32;
+   return IRExpr_Get(floatGuestRegOffset(dregNo), ty);
+}
+
+static IRExpr *getDReg(UInt dregNo)
+{
+   vassert(dregNo < 32);
+   IRTemp t0 = newTemp(Ity_F32);
+   IRTemp t1 = newTemp(Ity_F32);
+   IRTemp t2 = newTemp(Ity_F64);
+   IRTemp t3 = newTemp(Ity_I32);
+   IRTemp t4 = newTemp(Ity_I32);
+   IRTemp t5 = newTemp(Ity_I64);
+
+   assign(t0, getFReg(dregNo));
+   assign(t1, getFReg(dregNo + 1));
+
+   assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
+   assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
+   assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3)));
+   assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5)));
+
+   return mkexpr(t2);
+}
+
+static void putFReg(UInt dregNo, IRExpr * e)
+{
+   vassert(dregNo < 32);
+   IRType ty = mode64 ? Ity_F64 : Ity_F32;
+   vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
+   stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
+}
+
+static void putDReg(UInt dregNo, IRExpr * e)
+{
+   vassert(dregNo < 32);
+   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
+   IRTemp t1 = newTemp(Ity_F64);
+   IRTemp t4 = newTemp(Ity_I32);
+   IRTemp t5 = newTemp(Ity_I32);
+   IRTemp t6 = newTemp(Ity_I64);
+   assign(t1, e);
+   assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1)));
+   assign(t4, unop(Iop_64HIto32, mkexpr(t6)));  // hi
+   assign(t5, unop(Iop_64to32, mkexpr(t6))); //lo
+   putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t5)));
+   putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
+}
+
+static void setFPUCondCode(IRExpr * e, UInt cc)
+{
+   if (cc == 0) {
+      DIP("setFpu: %d\n", cc);
+      putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF)));
+      putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23))));
+   } else {
+      DIP("setFpu1: %d\n", cc);
+      putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32, 
+                               binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc)))));
+      putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc))));
+   }
+}
+
+static IRExpr */* :: Ity_I32 */get_IR_roundingmode(void)
+{
+/* 
+   rounding mode | MIPS | IR
+   ------------------------
+   to nearest    | 00  | 00
+   to zero       | 01  | 11
+   to +infinity  | 10  | 10
+   to -infinity  | 11  | 01
+*/
+   IRTemp rm_MIPS = newTemp(Ity_I32);
+   /* Last two bits in FCSR are rounding mode. */
+
+   assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
+                                    guest_FCSR), Ity_I32), mkU32(3)));
+
+   // rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2)
+
+   return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
+                binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
+}
+
+/*********************************************************/
+/*---             Floating Point Compare              ---*/
+/*********************************************************/
+static Bool dis_instr_CCondFmt(UInt cins)
+{
+   IRTemp t0, t1, t2, t3;
+   IRTemp ccIR = newTemp(Ity_I32);
+   IRTemp ccMIPS = newTemp(Ity_I32);
+   UInt FC = get_FC(cins);
+   UInt fmt = get_fmt(cins);
+   UInt fs = get_fs(cins);
+   UInt ft = get_ft(cins);
+   UInt cond = get_cond(cins);
+
+   if (FC == 0x3) {  // C.cond.fmt
+      UInt fpc_cc = get_fpc_cc(cins);
+      switch (fmt) {
+         case 0x10: {  //C.cond.S
+            DIP("C.cond.S %d f%d, f%d\n", fpc_cc, fs, ft);
+            t0 = newTemp(Ity_I32);
+            t1 = newTemp(Ity_I32);
+            t2 = newTemp(Ity_I32);
+            t3 = newTemp(Ity_I32);
+
+            assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)),
+                                           unop(Iop_F32toF64, getFReg(ft))));
+            /* Map compare result from IR to MIPS */
+            /*
+               FP cmp result | MIPS | IR
+               --------------------------
+               UN            | 0x1 | 0x45
+               EQ            | 0x2 | 0x40
+               GT            | 0x4 | 0x00
+               LT            | 0x8 | 0x01
+             */
+
+            // ccMIPS = Shl(1, (~(ccIR>>5) & 2)
+            //                    | ((ccIR ^ (ccIR>>6)) & 1)
+            assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8, 
+                           binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
+                           binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
+                           binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
+                           binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))), 
+                           mkU32(1))))));
+            assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));   // UN
+            assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+                   mkU8(0x1)), mkU32(0x1))); // EQ
+            assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
+                   mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));  // NGT
+            assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+                   mkU8(0x3)), mkU32(0x1))); // LT
+
+            switch (cond) {
+               case 0x0:
+                  setFPUCondCode(mkU32(0), fpc_cc);
+                  break;
+               case 0x1:
+                  DIP("unorderd: %d\n", fpc_cc);
+                  setFPUCondCode(mkexpr(t0), fpc_cc);
+                  break;
+               case 0x2:
+                  setFPUCondCode(mkexpr(t1), fpc_cc);
+                  break;
+               case 0x3:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+                                       fpc_cc);
+                  break;
+               case 0x4:
+                  setFPUCondCode(mkexpr(t3), fpc_cc);
+                  break;
+               case 0x5:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+                                       fpc_cc);
+                  break;
+               case 0x6:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+                                       fpc_cc);
+                  break;
+               case 0x7:
+                  setFPUCondCode(mkexpr(t2), fpc_cc);
+                  break;
+               case 0x8:
+                  setFPUCondCode(mkU32(0), fpc_cc);
+                  break;
+               case 0x9:
+                  setFPUCondCode(mkexpr(t0), fpc_cc);
+                  break;
+               case 0xA:
+                  setFPUCondCode(mkexpr(t1), fpc_cc);
+                  break;
+               case 0xB:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+                                       fpc_cc);
+                  break;
+               case 0xC:
+                  setFPUCondCode(mkexpr(t3), fpc_cc);
+                  break;
+               case 0xD:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+                                       fpc_cc);
+                  break;
+               case 0xE:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+                                       fpc_cc);
+                  break;
+               case 0xF:
+                  setFPUCondCode(mkexpr(t2), fpc_cc);
+                  break;
+
+               default:
+                  return False;
+            }
+         }
+            break;
+
+         case 0x11:  //C.cond.D
+            DIP("C.%d.D %d f%d, f%d\n", cond, fpc_cc, fs, ft);
+            t0 = newTemp(Ity_I32);
+            t1 = newTemp(Ity_I32);
+            t2 = newTemp(Ity_I32);
+            t3 = newTemp(Ity_I32);
+            assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+            /* Map compare result from IR to MIPS */
+            /*
+               FP cmp result | MIPS | IR
+               --------------------------
+               UN            | 0x1 | 0x45
+               EQ            | 0x2 | 0x40
+               GT            | 0x4 | 0x00
+               LT            | 0x8 | 0x01
+             */
+
+            // ccMIPS = Shl(1, (~(ccIR>>5) & 2)
+            //                    | ((ccIR ^ (ccIR>>6)) & 1)
+            assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
+                           binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
+                           binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
+                           binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
+                           binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
+                           mkU32(1))))));
+
+            assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));   // UN
+            assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+                   mkU8(0x1)), mkU32(0x1))); // EQ
+            assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
+                   mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));  // NGT
+            assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+                   mkU8(0x3)), mkU32(0x1))); // LT
+
+            switch (cond) {
+               case 0x0:
+                  setFPUCondCode(mkU32(0), fpc_cc);
+                  break;
+               case 0x1:
+                  DIP("unorderd: %d\n", fpc_cc);
+                  setFPUCondCode(mkexpr(t0), fpc_cc);
+                  break;
+               case 0x2:
+                  setFPUCondCode(mkexpr(t1), fpc_cc);
+                  break;
+               case 0x3:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+                                       fpc_cc);
+                  break;
+               case 0x4:
+                  setFPUCondCode(mkexpr(t3), fpc_cc);
+                  break;
+               case 0x5:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+                                       fpc_cc);
+                  break;
+               case 0x6:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+                                       fpc_cc);
+                  break;
+               case 0x7:
+                  setFPUCondCode(mkexpr(t2), fpc_cc);
+                  break;
+               case 0x8:
+                  setFPUCondCode(mkU32(0), fpc_cc);
+                  break;
+               case 0x9:
+                  setFPUCondCode(mkexpr(t0), fpc_cc);
+                  break;
+               case 0xA:
+                  setFPUCondCode(mkexpr(t1), fpc_cc);
+                  break;
+               case 0xB:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+                                       fpc_cc);
+                  break;
+               case 0xC:
+                  setFPUCondCode(mkexpr(t3), fpc_cc);
+                  break;
+               case 0xD:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+                                       fpc_cc);
+                  break;
+               case 0xE:
+                  setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+                                       fpc_cc);
+                  break;
+               case 0xF:
+                  setFPUCondCode(mkexpr(t2), fpc_cc);
+                  break;
+               default:
+                  return False;
+            }
+            break;
+
+            default:
+               return False;
+      }
+   } else {
+      return False;
+   }
+
+   return True;
+}
+
+/*------------------------------------------------------------*/
+/*--- Disassemble a single instruction                     ---*/
+/*------------------------------------------------------------*/
+
+/* Disassemble a single instruction into IR.  The instruction is
+   located in host memory at guest_instr, and has guest IP of
+   guest_PC_curr_instr, which will have been set before the call
+   here. */
+
+static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
+                                                                    Addr64),
+                                     Bool         resteerCisOk,
+                                     void*        callback_opaque,
+                                     Long         delta64,
+                                     VexArchInfo* archinfo,
+                                     VexAbiInfo*  abiinfo )
+{
+   IRTemp t0, t1, t2, t3, t4, t5, t6, t7, t8;
+   UInt opcode, cins, rs, rt, rd, sa, ft, fs, fd, fmt, tf, nd, function,
+        trap_code, imm, instr_index, p, msb, lsb, size, rot, sel;
+
+   DisResult dres;
+
+   static IRExpr *lastn = NULL;  /* last jump addr */
+   static IRStmt *bstmt = NULL;  /* branch (Exit) stmt */
+
+   /* The running delta */
+   Int delta = (Int) delta64;
+
+   /* Holds eip at the start of the insn, so that we can print
+      consistent error messages for unimplemented insns. */
+   Int delta_start = delta;
+
+   /* Are we in a delay slot ? */
+   Bool delay_slot_branch, likely_delay_slot, delay_slot_jump;
+
+   /* Set result defaults. */
+   dres.whatNext = Dis_Continue;
+   dres.len = 0;
+   dres.continueAt = 0;
+   dres.jk_StopHere = Ijk_INVALID;
+
+   delay_slot_branch = likely_delay_slot = delay_slot_jump = False;
+
+   UChar *code = (UChar *) (guest_code + delta);
+   cins = getUInt(code);
+
+   if (delta != 0) {
+      if (branch_or_jump(guest_code + delta - 4)) {
+         if (lastn == NULL && bstmt == NULL) {
+            DIP("Info: jump to delay slot insn...\n");
+         } else {
+            dres.whatNext = Dis_StopHere;
+
+            DIP("lastn = %p bstmt = %p\n", lastn, bstmt);
+            if (lastn != NULL) {
+               DIP("delay slot jump\n");
+               if (vex_traceflags & VEX_TRACE_FE)
+                  ppIRExpr(lastn);
+               delay_slot_jump = True;
+            } else if (bstmt != NULL) {
+               DIP("\ndelay slot branch\n");
+               delay_slot_branch = True;
+            }
+            DIP("delay slot\n");
+         }
+      }
+
+      if (branch_or_link_likely(guest_code + delta - 4)) {
+         likely_delay_slot = True;
+      }
+   }
+
+   /* Spot "Special" instructions (see comment at top of file). */
+   {
+      /* Spot the 16-byte preamble: 
+       ****mips32****
+       "srl $0, $0, 13
+       "srl $0, $0, 29
+       "srl $0, $0, 3
+       "srl $0, $0, 19 */
+      UInt word1 = 0x00000342;
+      UInt word2 = 0x00000742;
+      UInt word3 = 0x000000C2;
+      UInt word4 = 0x000004C2;
+      if (getUInt(code + 0) == word1 && getUInt(code + 4) == word2 &&
+          getUInt(code + 8) == word3 && getUInt(code + 12) == word4) {
+         /* Got a "Special" instruction preamble.  Which one is it? */
+         if (getUInt(code + 16) == 0x01ad6825 /* or t5, t5, t5 */ ) {
+            /* v0 = client_request ( t9 ) */
+            DIP("v0 = client_request ( t9 )\n");
+            putPC(mkU32(guest_PC_curr_instr + 20));
+            dres.jk_StopHere = Ijk_ClientReq;
+            dres.whatNext    = Dis_StopHere;
+
+            goto decode_success;
+         } else if (getUInt(code + 16) == 0x01ce7025 /* or t6,t6,t6 */ ) {
+            /* t9 = guest_NRADDR */
+            DIP("t9 = guest_NRADDR\n");
+            dres.len = 20;
+            delta += 20;
+            putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State, guest_NRADDR),
+                                   Ity_I32));
+            goto decode_success;
+         } else if (getUInt(code + 16) == 0x01ef7825/* or t7,t7,t7 */ ) {
+            /*  branch-and-link-to-noredir t9 */
+            DIP("branch-and-link-to-noredir t9\n");
+            putIReg(31, mkU32(guest_PC_curr_instr + 20));
+            putPC(getIReg(25));
+            dres.jk_StopHere = Ijk_NoRedir;
+            dres.whatNext    = Dis_StopHere;
+            goto decode_success;
+         }
+
+         /* We don't know what it is.  Set opc1/opc2 so decode_failure
+            can print the insn following the Special-insn preamble. */
+         delta += 16;
+         goto decode_failure;
+       /*NOTREACHED*/}
+   }
+
+   opcode = get_opcode(cins);
+   imm = get_imm(cins);
+   rs = get_rs(cins);
+   rt = get_rt(cins);
+   rd = get_rd(cins);
+   sa = get_sa(cins);
+   fs = get_fs(cins);
+   fd = get_fd(cins);
+   ft = get_ft(cins);
+   tf = get_tf(cins);
+   nd = get_nd(cins);
+   sel = get_sel(cins);
+   fmt = get_fmt(cins);
+   instr_index = get_instr_index(cins);
+   trap_code = get_code(cins);
+   function = get_function(cins);
+   IRType ty = mode64 ? Ity_I64 : Ity_I32;
+   IRType tyF = mode64 ? Ity_F64 : Ity_F32;
+
+   DIP("[cins = 0x%08x] ", cins);
+
+   switch (opcode) {
+
+   case 0x03:     /* JAL */
+      DIP("jal");
+      putIReg(31, mkU32(guest_PC_curr_instr + 8));
+      t0 = newTemp(ty);
+      assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
+                       (instr_index << 2)));
+      lastn = mkexpr(t0);
+      break;
+   case 0x02:     /* J */
+      DIP("j");
+      t0 = newTemp(ty);
+      assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
+                       (instr_index << 2)));
+      lastn = mkexpr(t0);
+      break;
+
+   case 0x11:     /* COP1 */
+      {
+         UInt bc1_cc = get_bc1_cc(cins);
+         if (0x08 == fmt) {
+            switch (fmt) {
+            case 0x08:  //BC
+               {
+                  DIP("tf: %d, nd: %d\n", tf, nd);
+                  //FcConditionalCode(bc1_cc)
+                  t1 = newTemp(Ity_I32);
+                  t2 = newTemp(Ity_I32);
+                  t3 = newTemp(Ity_I1);
+
+                  assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
+                                                    mkU32(bc1_cc))));
+                  assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
+                             binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
+                             mkU8(24 + bc1_cc)), mkU32(0x1)), binop(Iop_And32,
+                             binop(Iop_Shr32, getFCSR(), mkU8(23)),
+                                   mkU32(0x1))));
+
+                  if (tf == 1 && nd == 0) {
+                     //branch on true
+                     DIP("bc1t \n");
+                     assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
+                     dis_branch(False, mkexpr(t3), imm, &bstmt);
+                     break;
+                  } else if (tf == 0 && nd == 0) {
+                     //branch on false
+                     DIP("bc1f \n");
+                     assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
+                     dis_branch(False, mkexpr(t3), imm, &bstmt);
+                     break;
+                  } else if (nd == 1 && tf == 0) {
+                     DIP("bc1fl \n");
+                     lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2),
+                           mode64 ? mkU64(0x0) : mkU32(0x0)), imm);
+                     break;
+                  } else if (nd == 1 && tf == 1) {
+                     DIP("bc1tl \n");
+                     lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2),
+                                               mkU32(0x0)), imm);
+                     break;
+                  } else
+                     goto decode_failure;
+               }
+
+            default:
+               goto decode_failure;
+            }
+         } else {
+            switch (function) {
+
+            case 0x4:   //SQRT.fmt
+               {
+                  switch (fmt) {
+                  case 0x10:  //S
+                     {
+                        IRExpr *rm = get_IR_roundingmode();
+                        putFReg(fd, mkWidenFromF32(tyF, binop(Iop_SqrtF32, rm,
+                                    getLoFromF64(tyF, getFReg(fs)))));
+                     }
+                     break;
+                  case 0x11:  //D
+                     {
+                        IRExpr *rm = get_IR_roundingmode();
+                        putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs)));
+                     }
+                     break;
+                  }
+               }
+               break;
+            case 0x5:   //abs.fmt
+               switch (fmt) {
+               case 0x10:  //S
+                  DIP("abs.s f%d, f%d\n", fd, fs);
+                  putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32,
+                              getLoFromF64(tyF, getFReg(fs)))));
+                  break;
+               case 0x11:  //D 
+                  DIP("abs.d f%d, f%d\n", fd, fs);
+                  putDReg(fd, unop(Iop_AbsF64, getDReg(fs)));
+                  break;
+               default:
+                  goto decode_failure;
+               }
+               break;   //case 0x5
+
+            case 0x02:  // MUL.fmt
+               switch (fmt) {
+               case 0x11:  // D
+                  {
+                     DIP("mul.d f%d, f%d, f%d", fd, fs, ft);
+                     IRExpr *rm = get_IR_roundingmode();
+                     putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs),
+                                       getDReg(ft)));
+                     break;
+                  }
+               case 0x10:  // S
+                  {
+                     DIP("mul.s f%d, f%d, f%d", fd, fs, ft);
+                     IRExpr *rm = get_IR_roundingmode();
+                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm,
+                                 getLoFromF64(tyF, getFReg(fs)),
+                                 getLoFromF64(tyF, getFReg(ft)))));
+                     break;
+                  }
+               default:
+                  goto decode_failure;
+               }
+               break;   // MUL.fmt
+
+            case 0x03:  // DIV.fmt
+               switch (fmt) {
+               case 0x11:  // D
+                  {
+                     DIP("div.d f%d, f%d, f%d", fd, fs, ft);
+                     IRExpr *rm = get_IR_roundingmode();
+                     putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs),
+                                 getDReg(ft)));
+                     break;
+                  }
+               case 0x10:  // S
+                  {
+                     DIP("div.s f%d, f%d, f%d", fd, fs, ft);
+                     IRExpr *rm = get_IR_roundingmode();
+                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
+                                 getLoFromF64(tyF, getFReg(fs)),
+                                 getLoFromF64(tyF, getFReg(ft)))));
+                     break;
+                  }
+               default:
+                  goto decode_failure;
+               }
+               break;   // DIV.fmt
+
+            case 0x01:  // SUB.fmt
+               switch (fmt) {
+               case 0x11:  // D
+                  {
+                     DIP("sub.d f%d, f%d, f%d", fd, fs, ft);
+                     IRExpr *rm = get_IR_roundingmode();
+                     putDReg(fd, triop(Iop_SubF64, rm, getDReg(fs), getDReg(ft)));
+                     break;
+                  }
+               case 0x10:  // S
+                  {
+                     DIP("sub.s f%d, f%d, f%d", fd, fs, ft);
+                     IRExpr *rm = get_IR_roundingmode();
+                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm,
+                                 getLoFromF64(tyF, getFReg(fs)),
+                                 getLoFromF64(tyF, getFReg(ft)))));
+                     break;
+                  }
+               default:
+                  goto decode_failure;
+               }
+               break;   // SUB.fmt
+
+            case 0x06:  // MOV.fmt
+               switch (fmt) {
+               case 0x11:  // D
+                  /* TODO: Check this for 64 bit FPU registers. */
+                  DIP("mov.d f%d, f%d", fd, fs);
+                  putFReg(fd, getFReg(fs));
+                  putFReg(fd + 1, getFReg(fs + 1));
+                  break;
+               case 0x10:  // S
+                  DIP("mov.s f%d, f%d", fd, fs);
+                  putFReg(fd, getFReg(fs));
+                  break;
+               default:
+                  goto decode_failure;
+               }
+               break;   // MOV.fmt
+
+            case 0x7:   //neg.fmt
+               switch (fmt) {
+               case 0x10:  //S
+                  DIP("neg.s f%d, f%d", fd, fs);
+                  putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32,
+                              getLoFromF64(tyF, getFReg(fs)))));
+                  break;
+               case 0x11:  //D 
+                  DIP("neg.d f%d, f%d", fd, fs);
+                  putDReg(fd, unop(Iop_NegF64, getDReg(fs)));
+                  break;
+               default:
+                  goto decode_failure;
+               }
+               break;   //case 0x7
+
+            case 0x15:  //RECIP.fmt
+               switch (fmt) {
+               case 0x10:
+                  {  //S
+                     DIP("recip.s f%d, f%d\n", fd, fs);
+                     IRExpr *rm = get_IR_roundingmode();
+                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32,
+                                 rm, unop(Iop_ReinterpI32asF32,
+                                 mkU32(0x3F800000)), getLoFromF64(tyF,
+                                 getFReg(fs)))));
+                     break;
+                  }
+               case 0x11:
+                  {  //D
+                     DIP("recip.d f%d, f%d\n", fd, fs);
+                     IRExpr *rm = get_IR_roundingmode();
+                     putDReg(fd, triop(Iop_DivF64, rm, 
+                                 unop(Iop_ReinterpI64asF64,
+                                 mkU64(0x3FF0000000000000ULL)), getDReg(fs)));
+                     break;
+                  }
+               default:
+                  goto decode_failure;
+
+               }
+               break;   //case 0x15
+
+            case 0x13:  //MOVN.fmt
+               switch (fmt) {
+               case 0x10:  // S
+                  DIP("movn.s f%d, f%d, r%d", fd, fs, rt);
+
+                  t1 = newTemp(Ity_F64);
+                  t2 = newTemp(Ity_F64);
+                  t3 = newTemp(Ity_I32);
+                  t4 = newTemp(Ity_F64);
+
+                  assign(t1, unop(Iop_F32toF64, getFReg(fs)));
+                  assign(t2, unop(Iop_F32toF64, getFReg(fd)));
+                  assign(t3, unop(Iop_1Sto32, binop(Iop_CmpNE32, mkU32(0),
+                                                    getIReg(rt))));
+
+                  assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
+                                               mkexpr(t1), mkexpr(t2)));
+
+                  putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
+                                    mkexpr(t4)));
+                  break;
+               case 0x11:  // D
+                  DIP("movn.d f%d, f%d, r%d", fd, fs, rt);
+
+                  t3 = newTemp(Ity_I32);
+                  t4 = newTemp(Ity_F64);
+
+                  assign(t3, unop(Iop_1Sto32, binop(Iop_CmpNE32, mkU32(0),
+                                                    getIReg(rt))));
+                  putDReg(fd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
+                                                getDReg(fs), getDReg(fd)));
+                  break;
+               default:
+                  goto decode_failure;
+               }
+               break;   // MOVN.fmt
+
+            case 0x12:  //MOVZ.fmt
+               switch (fmt) {
+               case 0x10:  // S
+                  DIP("movz.s f%d, f%d, r%d", fd, fs, rt);
+
+                  t1 = newTemp(Ity_F64);
+                  t2 = newTemp(Ity_F64);
+                  t3 = newTemp(Ity_I32);
+                  t4 = newTemp(Ity_F64);
+
+                  assign(t1, unop(Iop_F32toF64, getFReg(fs)));
+                  assign(t2, unop(Iop_F32toF64, getFReg(fd)));
+                  assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
+                                                    getIReg(rt))));
+                  assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
+                                               mkexpr(t1), mkexpr(t2)));
+
+                  putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
+                                    mkexpr(t4)));
+
+                  break;
+               case 0x11:  // D
+                  DIP("movz.d f%d, f%d, r%d", fd, fs, rt);
+
+                  t3 = newTemp(Ity_I32);
+                  t4 = newTemp(Ity_F64);
+
+                  assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
+                                                    getIReg(rt))));
+                  putDReg(fd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
+                                                getDReg(fs), getDReg(fd)));
+                  break;
+               default:
+                  goto decode_failure;
+               }
+               break;   // MOVZ.fmt
+
+            case 0x11:  // MOVT.fmt
+               if (tf == 1) {
+                  UInt mov_cc = get_mov_cc(cins);
+                  switch (fmt)   // MOVCF = 010001
+                  {
+                  case 0x11:  // D
+                     DIP("movt.d f%d, f%d, %d", fd, fs, mov_cc);
+                     t1 = newTemp(Ity_I32);
+                     t2 = newTemp(Ity_I32);
+                     t3 = newTemp(Ity_I32);
+                     t4 = newTemp(Ity_F64);
+
+                     assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
+                                                       mkU32(mov_cc))));
+                     assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
+                                binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
+                                 mkU8(24 + mov_cc)), mkU32(0x1)),
+                                 binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
+                                 mkU8(23)), mkU32(0x1))));
+
+                     assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
+                                mkexpr(t2))));
+                     assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
+                                             getDReg(fs), getDReg(fd)));
+                     putDReg(fd, mkexpr(t4));
+                     break;
+                  case 0x10:  // S
+                     DIP("movt.s f%d, f%d, %d", fd, fs, mov_cc);
+                     t1 = newTemp(Ity_I32);
+                     t2 = newTemp(Ity_I32);
+                     t3 = newTemp(Ity_I32);
+                     t4 = newTemp(Ity_F64);
+                     t5 = newTemp(Ity_F64);
+                     t6 = newTemp(Ity_F64);
+                     t7 = newTemp(Ity_I64);
+
+                     assign(t5, unop(Iop_F32toF64, getFReg(fs)));
+                     assign(t6, unop(Iop_F32toF64, getFReg(fd)));
+
+                     assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
+                                     mkU32(mov_cc))));
+                     assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
+                                             binop(Iop_And32, binop(Iop_Shr32,
+                                             getFCSR(), mkU8(24 + mov_cc)),
+                                             mkU32(0x1)), binop(Iop_And32,
+                                             binop(Iop_Shr32, getFCSR(),
+                                             mkU8(23)), mkU32(0x1))));
+
+                     assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
+                                                       mkexpr(t2))));
+                     assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
+                                             mkexpr(t5), mkexpr(t6)));
+
+                     putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
+                                       mkexpr(t4)));
+                     break;
+                  default:
+                     goto decode_failure;
+                  }
+               } else if (tf == 0)  //movf.fmt
+               {
+                  UInt mov_cc = get_mov_cc(cins);
+                  switch (fmt)   // MOVCF = 010001
+                  {
+                  case 0x11:  // D
+                     DIP("movf.d f%d, f%d, %d", fd, fs, mov_cc);
+                     t1 = newTemp(Ity_I32);
+                     t2 = newTemp(Ity_I32);
+                     t3 = newTemp(Ity_I32);
+                     t4 = newTemp(Ity_F64);
+
+                     assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32,
+                                                 mkU32(0), mkU32(mov_cc))));
+                     assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
+                                binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
+                                mkU8(24 + mov_cc)), mkU32(0x1)),
+                                binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
+                                mkU8(23)), mkU32(0x1))));
+
+                     assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
+                                                       mkexpr(t2))));
+                     assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
+                                             getDReg(fd), getDReg(fs)));
+                     putDReg(fd, mkexpr(t4));
+                     break;
+                  case 0x10:  // S
+                     DIP("movf.s f%d, f%d, %d", fd, fs, mov_cc);
+                     {
+                        t1 = newTemp(Ity_I32);
+                        t2 = newTemp(Ity_I32);
+                        t3 = newTemp(Ity_I32);
+                        t4 = newTemp(Ity_F64);
+                        t5 = newTemp(Ity_F64);
+                        t6 = newTemp(Ity_F64);
+
+                        assign(t5, unop(Iop_F32toF64, getFReg(fs)));
+                        assign(t6, unop(Iop_F32toF64, getFReg(fd)));
+
+                        assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
+                                                          mkU32(mov_cc))));
+                        assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
+                                   binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
+                                   mkU8(24 + mov_cc)), mkU32(0x1)),
+                                   binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
+                                   mkU8(23)), mkU32(0x1))));
+
+                        assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
+                                                          mkexpr(t2))));
+                        assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
+                                                     mkexpr(t6), mkexpr(t5)));
+                        putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
+                                          mkexpr(t4)));
+                     }
+                     break;
+                  default:
+                     goto decode_failure;
+                  }
+               }
+
+               break;   // MOVT.fmt
+
+            case 0x0:   //add.fmt
+               switch (fmt) {
+               case 0x10:  //S
+                  {
+                     DIP("add.s f%d, f%d, f%d\n", fd, fs, ft);
+                     IRExpr *rm = get_IR_roundingmode();
+                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm,
+                                 getLoFromF64(tyF, getFReg(fs)),
+                                 getLoFromF64(tyF, getFReg(ft)))));
+                     break;
+                  }
+               case 0x11:  //D
+                  {
+                     DIP("add.d f%d, f%d, f%d\n", fd, fs, ft);
+                     IRExpr *rm = get_IR_roundingmode();
+                     putDReg(fd, triop(Iop_AddF64, rm, getDReg(fs), 
+                                       getDReg(ft)));
+                     break;
+                  }
+
+               case 0x4:   //MTC1 (Move Word to Floating Point)
+                  DIP("mtc1 r%d, f%d", rt, fs);
+                  putFReg(fs, unop(Iop_ReinterpI32asF32, getIReg(rt)));
+                  break;
+
+               case 0x0:   //MFC1
+                  DIP("mfc1 r%d, f%d", rt, fs);
+                  putIReg(rt, unop(Iop_ReinterpF32asI32, getFReg(fs)));
+                  break;
+
+               case 0x6:   //CTC1
+                  DIP("ctc1 r%d, f%d", rt, fs);
+                  t0 = newTemp(Ity_I32);
+                  t1 = newTemp(Ity_I32);
+                  t2 = newTemp(Ity_I32);
+                  t3 = newTemp(Ity_I32);
+                  t4 = newTemp(Ity_I32);
+                  t5 = newTemp(Ity_I32);
+                  t6 = newTemp(Ity_I32);
+                  assign(t0, mkNarrowTo32(ty, getIReg(rt)));
+                  if (fs == 25) {   //FCCR
+                     assign(t1, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
+                                      mkU32(0x000000FE)), mkU8(24)));
+                     assign(t2, binop(Iop_And32, mkexpr(t0),
+                                      mkU32(0x01000000)));
+                     assign(t3, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
+                                      mkU32(0x00000001)), mkU8(23)));
+                     assign(t4, binop(Iop_And32, mkexpr(t0),
+                                      mkU32(0x007FFFFF)));
+                     putFCSR(binop(Iop_Or32, binop(Iop_Or32, mkexpr(t1),
+                                   mkexpr(t2)), binop(Iop_Or32, mkexpr(t3),
+                                   mkexpr(t4))));
+                  } else if (fs == 26) {  //FEXR
+                     assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFFFC0000)));
+                     assign(t2, binop(Iop_And32, mkexpr(t0),
+                                      mkU32(0x0003F000)));
+                     assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00000F80)));
+                     assign(t4, binop(Iop_And32, mkexpr(t0),
+                                      mkU32(0x0000007C)));
+                     assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x00000003)));
+                     putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
+                                   mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
+                                   mkexpr(t3), mkexpr(t4))), mkexpr(t5)));
+                  } else if (fs == 28) {
+                     assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFE000000)));
+                     assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
+                                mkU32(0x00000002)), mkU8(22)));
+                     assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00FFF000)));
+                     assign(t4, binop(Iop_And32, mkexpr(t0),
+                                mkU32(0x00000F80)));
+                     assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x0000007C)));
+                     assign(t6, binop(Iop_And32, mkexpr(t0),
+                                mkU32(0x00000003)));
+                     putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
+                                   mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
+                                   mkexpr(t3), mkexpr(t4))), binop(Iop_Or32,
+                                   mkexpr(t5), mkexpr(t6))));
+                  } else if (fs == 31) {
+                     putFCSR(mkexpr(t0));
+                  }
+                  break;
+               case 0x2:   //CFC1
+                  DIP("cfc1 r%d, f%d", rt, fs);
+                  t0 = newTemp(Ity_I32);
+                  t1 = newTemp(Ity_I32);
+                  t2 = newTemp(Ity_I32);
+                  t3 = newTemp(Ity_I32);
+                  t4 = newTemp(Ity_I32);
+                  t5 = newTemp(Ity_I32);
+                  t6 = newTemp(Ity_I32);
+                  assign(t0, getFCSR());
+                  if (fs == 0) {
+                     putIReg(rt, mkWidenFrom32(ty,
+                             IRExpr_Get(offsetof(VexGuestMIPS32State,
+                                                 guest_FIR),
+                                       Ity_I32),
+                             False));
+                  } else if (fs == 25) {
+                     assign(t1, mkU32(0x000000FF));
+                     assign(t2, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
+                                      mkU32(0xFE000000)), mkU8(25)));
+                     assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
+                                      mkU32(0x00800000)), mkU8(23)));
+                     putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
+                                 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
+                                 mkexpr(t3)), False));
+                  } else if (fs == 26) {
+                     assign(t1, mkU32(0xFFFFF07C));
+                     assign(t2, binop(Iop_And32, mkexpr(t0),
+                                mkU32(0x0003F000)));
+                     assign(t3, binop(Iop_And32, mkexpr(t0),
+                                      mkU32(0x0000007C)));
+                     putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
+                                 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
+                                 mkexpr(t3)), False));
+                  } else if (fs == 28) {
+                     assign(t1, mkU32(0x00000F87));
+                     assign(t2, binop(Iop_And32, mkexpr(t0),
+                                      mkU32(0x00000F83)));
+                     assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
+                                      mkU32(0x01000000)), mkU8(22)));
+                     putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
+                                 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
+                                 mkexpr(t3)), False));
+                  } else if (fs == 31) {
+                     putIReg(rt, mkWidenFrom32(ty, getFCSR(), False));
+                  }
+                  break;
+               default:
+                  goto decode_failure;
+               }
+               break;   //case 0x0: //add.fmt
+
+            case 0x21:  //CVT.D
+               switch (fmt) {
+               case 0x10:  //S
+                  DIP("cvt.d.s f%d, f%d", fd, fs);
+                  putDReg(fd, unop(Iop_F32toF64, getFReg(fs)));
+                  break;
+
+               case 0x14:
+                  {  //W
+                     DIP("cvt.d.w %d, %d\n", fd, fs);
+                     t0 = newTemp(Ity_I32);
+                     assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
+                     putDReg(fd, unop(Iop_I32StoF64, mkexpr(t0)));
+                  }
+                  break;
+
+               default:
+                  goto decode_failure;
+               }
+               break;   //CVT.D
+
+            case 0x20:  //cvt.s
+               switch (fmt) {
+               case 0x14:  //W
+                  DIP("cvt.s.w %d, %d\n", fd, fs);
+                  t0 = newTemp(Ity_I32);
+                  assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
+                  putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(),
+                              mkexpr(t0)));
+                  break;
+
+               case 0x11:  //D
+                  DIP("cvt.s.d %d, %d\n", fd, fs);
+                  putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
+                                    getDReg(fs)));
+                  break;
+
+               default:
+                  goto decode_failure;
+               }
+               break;   //cvt.s
+
+            case 0x24:  //cvt.w
+               switch (fmt) {
+               case 0x10:  //S
+                  DIP("cvt.w.s %d, %d\n", fd, fs);
+                  putFReg(fd, binop(Iop_RoundF32toInt, get_IR_roundingmode(),
+                                    getFReg(fs)));
+                  break;
+
+               case 0x11:
+                  {  //D
+                     DIP("cvt.w.d %d, %d\n", fd, fs);
+                     t0 = newTemp(Ity_I32);
+
+                     assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(),
+                                      getDReg(fs)));
+
+                     putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+                  }
+                  break;
+
+               default:
+                  goto decode_failure;
+
+               }
+               break;
+
+            case 0x09:  //TRUNC.L
+               switch (fmt) {
+               case 0x10:  //S
+                  DIP("trunc.l.s %d, %d\n", fd, fs);
+                  goto decode_failure;
+
+               case 0x11:  //D
+                  DIP("trunc.l.d %d, %d\n", fd, fs);
+                  goto decode_failure;
+
+               default:
+                  goto decode_failure;
+
+               }
+               break;   //trunc.l
+
+            case 0x0C:  //ROUND.W.fmt
+               switch (fmt) {
+               case 0x10:  //S
+                  DIP("round.w.s f%d, f%d\n", fd, fs);
+                  putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x0),
+                                    getFReg(fs)));
+                  break;
+
+               case 0x11:  //D
+                  DIP("round.w.d f%d, f%d\n", fd, fs);
+                  t0 = newTemp(Ity_I32);
+
+                  assign(t0, binop(Iop_F64toI32S, mkU32(0x0), getDReg(fs)));
+
+                  putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+                  break;
+
+               default:
+                  goto decode_failure;
+
+               }
+               break;   //ROUND.W.fmt
+
+            case 0x0F:  //FLOOR.W.fmt
+               switch (fmt) {
+               case 0x10:  //S
+                  DIP("floor.w.s f%d, f%d\n", fd, fs);
+                  putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x1),
+                                    getFReg(fs)));
+                  break;
+
+               case 0x11:  //D
+                  DIP("floor.w.d f%d, f%d\n", fd, fs);
+                  t0 = newTemp(Ity_I32);
+
+                  assign(t0, binop(Iop_F64toI32S, mkU32(0x1), getDReg(fs)));
+
+                  putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+                  break;
+
+               default:
+                  goto decode_failure;
+
+               }
+               break;   //FLOOR.W.fmt
+
+            case 0x0D:  //TRUNC.W
+               switch (fmt) {
+               case 0x10:  //S
+                  DIP("trunc.w.s %d, %d\n", fd, fs);
+                  putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x3),
+                                    getFReg(fs)));
+                  break;
+
+               case 0x11:  //D
+                  DIP("trunc.w.d %d, %d\n", fd, fs);
+                  t0 = newTemp(Ity_I32);
+
+                  assign(t0, binop(Iop_F64toI32S, mkU32(0x3), getDReg(fs)));
+
+                  putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+                  break;
+
+               default:
+                  goto decode_failure;
+
+               }
+               break;
+            case 0x0E:  //CEIL.W.fmt
+               switch (fmt) {
+               case 0x10:  //S
+                  DIP("ceil.w.s %d, %d\n", fd, fs);
+                  putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x2),
+                                    getFReg(fs)));
+                  break;
+
+               case 0x11:  //D
+                  DIP("ceil.w.d %d, %d\n", fd, fs);
+                  t0 = newTemp(Ity_I32);
+
+                  assign(t0, binop(Iop_F64toI32S, mkU32(0x2), getDReg(fs)));
+
+                  putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+                  break;
+
+               default:
+                  goto decode_failure;
+
+               }
+               break;
+            case 0x0A:  //CEIL.L.fmt
+               switch (fmt) {
+               case 0x10:  //S
+                  DIP("ceil.l.s %d, %d\n", fd, fs);
+                  goto decode_failure;
+
+               case 0x11:  //D
+                  DIP("ceil.l.d %d, %d\n", fd, fs);
+
+                  goto decode_failure;
+
+               default:
+                  goto decode_failure;
+
+               }
+               break;
+
+            case 0x16:  //RSQRT.fmt
+               switch (fmt) {
+               case 0x10:
+                  {  //S
+                     DIP("rsqrt.s %d, %d\n", fd, fs);
+                     IRExpr *rm = get_IR_roundingmode();
+                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
+                                 unop(Iop_ReinterpI32asF32, mkU32(0x3F800000)),
+                                 binop(Iop_SqrtF32, rm, getLoFromF64(tyF,
+                                 getFReg(fs))))));
+                     break;
+                  }
+               case 0x11:
+                  {  //D
+                     DIP("rsqrt.d %d, %d\n", fd, fs);
+                     IRExpr *rm = get_IR_roundingmode();
+                     putDReg(fd, triop(Iop_DivF64, rm,
+                                 unop(Iop_ReinterpI64asF64,
+                                 mkU64(0x3FF0000000000000ULL)),
+                                 binop(Iop_SqrtF64, rm, getDReg(fs))));
+                     break;
+                  }
+               default:
+                  goto decode_failure;
+
+               }
+               break;
+
+            default:
+               if (dis_instr_CCondFmt(cins))
+                  break;
+               goto decode_failure;
+
+            }
+
+         }
+      }
+      break;      /*COP1 */
+   case 0x10:     /* COP0 */
+      if (rs == 0) { /* MFC0 */
+         DIP("mfc0 r%d, r%d, %d", rt, rd, sel);
+
+         IRTemp   val  = newTemp(Ity_I32);
+         IRExpr** args = mkIRExprVec_2 (mkU32(rd), mkU32(sel));
+         IRDirty *d = unsafeIRDirty_1_N(val,
+                                        0,
+                                        "mips32_dirtyhelper_mfc0",
+                                        &mips32_dirtyhelper_mfc0,
+                                        args);
+
+         stmt(IRStmt_Dirty(d));
+         putIReg(rt, mkexpr(val));
+      } else
+         goto decode_failure;
+      break;
+   case 0x31:     /* LWC1 */
+      /* Load Word to Floating Point - LWC1 (MIPS32) */
+      LOAD_STORE_PATTERN;
+      putFReg(ft, load(Ity_F32, mkexpr(t1)));
+
+      DIP("lwc1 f%d, %d(r%d)", ft, imm, rs);
+      break;
+
+   case 0x39:     /* SWC1 */
+      LOAD_STORE_PATTERN;
+      store(mkexpr(t1), getFReg(ft));
+      DIP("swc1 f%d, %d(r%d)", ft, imm, rs);
+      break;
+
+   case 0x33:     /* PREF */
+      DIP("pref)");
+      break;
+
+   case 0x35:
+      /* Load Doubleword to Floating Point - LDC1 (MIPS32) */
+      LOAD_STORE_PATTERN;
+
+      t2 = newTemp(Ity_I32);
+      assign(t2, binop(Iop_Add32, getIReg(rs),
+                       mkU32(extend_s_16to32(imm + 4))));
+
+#if defined (_MIPSEL)
+      putFReg(ft, load(Ity_F32, mkexpr(t1)));
+      putFReg(ft + 1, load(Ity_F32, mkexpr(t2)));
+#elif defined (_MIPSEB)
+      putFReg(ft + 1, load(Ity_F32, mkexpr(t1)));
+      putFReg(ft, load(Ity_F32, mkexpr(t2)));
+#endif
+      DIP("ldc1 f%d, %d(%d) \n", rt, imm, rs);
+      break;
+
+   case 0x3D:
+      /* Store Doubleword from Floating Point - SDC1 */
+      LOAD_STORE_PATTERN;
+
+      t2 = newTemp(Ity_I32);
+      assign(t2, binop(Iop_Add32, getIReg(rs),
+                       mkU32(extend_s_16to32(imm + 4))));
+
+#if defined (_MIPSEL)
+      store(mkexpr(t1), getFReg(ft));
+      store(mkexpr(t2), getFReg(ft + 1));
+#elif defined (_MIPSEB)
+      store(mkexpr(t1), getFReg(ft + 1));
+      store(mkexpr(t2), getFReg(ft));
+#endif
+      DIP("sdc1 f%d, %d(%d)", ft, imm, rs);
+      break;
+
+   case 0x23:     /* LW */
+      DIP("lw r%d, %d(r%d)", rt, imm, rs);
+      LOAD_STORE_PATTERN;
+      putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
+      break;
+
+   case 0x20:     /* LB */
+      DIP("lb");
+      LOAD_STORE_PATTERN;
+      putIReg(rt, unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
+      break;
+
+   case 0x24:     /* LBU */
+      DIP("lbu");
+      LOAD_STORE_PATTERN;
+      putIReg(rt, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t1))));
+      break;
+
+   case 0x21:     /* LH */
+      DIP("lh");
+      LOAD_STORE_PATTERN;
+      putIReg(rt, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t1))));
+      break;
+
+   case 0x25:     /* LHU */
+      DIP("lhu");
+      LOAD_STORE_PATTERN;
+      putIReg(rt, unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
+      break;
+
+   case 0x0F:     /* LUI */
+      p = (imm << 16);
+      DIP("lui rt: %d, imm: %d, imm << 16: %d", rt, imm, p);
+      if ((vex_traceflags & VEX_TRACE_FE) && !mode64)
+         ppIRExpr(mkU32(p));
+      putIReg(rt, mkU32(p));
+      break;
+
+   case 0x13:     /* COP1X */
+      switch (function) {
+      case 0x0: { /* LWXC1 */
+         /* Load Word  Indexed to Floating Point - LWXC1 (MIPS32r2) */
+         DIP("lwxc1 f%d, r%d(r%d) \n", fd, rt, rs);
+         t0 = newTemp(Ity_I32);
+         assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
+         putFReg(fd, load(Ity_F32, mkexpr(t0)));
+         break;
+      }
+
+      case 0x1: { /* LDXC1 */
+         /* Load Doubleword  Indexed to Floating Point - LDXC1 (MIPS32r2) */
+         t0 = newTemp(Ity_I32);
+         assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
+
+         t1 = newTemp(Ity_I32);
+         assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4)));
+
+#if defined (_MIPSEL)
+         putFReg(fd, load(Ity_F32, mkexpr(t0)));
+         putFReg(fd + 1, load(Ity_F32, mkexpr(t1)));
+#elif defined (_MIPSEB)
+         putFReg(fd + 1, load(Ity_F32, mkexpr(t0)));
+         putFReg(fd, load(Ity_F32, mkexpr(t1)));
+#endif
+         DIP("ldxc1 f%d, r%d(r%d) \n", fd, rt, rs);
+         break;
+      }
+
+      case 0x5:   // Load Doubleword Indexed Unaligned 
+         // to Floating Point - LUXC1; MIPS32r2
+         DIP("luxc1 f%d, r%d(r%d) \n", fd, rt, rs);
+         t0 = newTemp(Ity_I64);
+         t1 = newTemp(Ity_I64);
+         assign(t0, binop(Iop_Add64, getIReg(rs), getIReg(rt)));
+         assign(t1, binop(Iop_And64, mkexpr(t0), mkU64(0xfffffffffffffff8ULL)));
+         putFReg(fd, load(Ity_F64, mkexpr(t1)));
+         break;
+
+      case 0x8: { /* SWXC1 */
+         /* Store Word Indexed from Floating Point - SWXC1 */
+         t0 = newTemp(Ity_I32);
+         assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
+
+         store(mkexpr(t0), getFReg(fs));
+
+         DIP("swxc1 f%d, r%d(r%d)", ft, rt, rs);
+         break;
+      }
+      case 0x9: { /* SDXC1 */
+         /* Store Doubleword Indexed from Floating Point - SDXC1 */
+         t0 = newTemp(Ity_I32);
+         assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
+
+         t1 = newTemp(Ity_I32);
+         assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4)));
+
+#if defined (_MIPSEL)
+         store(mkexpr(t0), getFReg(fs));
+         store(mkexpr(t1), getFReg(fs + 1));
+#elif defined (_MIPSEB)
+         store(mkexpr(t0), getFReg(fs + 1));
+         store(mkexpr(t1), getFReg(fs));
+#endif
+
+         DIP("sdc1 f%d, %d(%d)", ft, imm, rs);
+         break;
+      }
+      case 0x0F: {
+         DIP("prefx");
+         break;
+      }
+      case 0x20:  { /* MADD.S */
+         DIP("madd.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
+         IRExpr *rm = get_IR_roundingmode();
+         t1 = newTemp(Ity_F32);
+         assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
+                          getLoFromF64(tyF, getFReg(ft))));
+
+         putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm, mkexpr(t1),
+                                    getLoFromF64(tyF, getFReg(fmt)))));
+         break;   /* MADD.S */
+      }
+      case 0x21: { /* MADD.D */
+         DIP("madd.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
+         IRExpr *rm = get_IR_roundingmode();
+         t1 = newTemp(Ity_F64);
+         assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft)));
+
+         putDReg(fd, triop(Iop_AddF64, rm, mkexpr(t1), getDReg(fmt)));
+         break;   /* MADD.D */
+      }
+      case 0x28: { /* MSUB.S */
+         DIP("msub.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
+         IRExpr *rm = get_IR_roundingmode();
+         t1 = newTemp(Ity_F32);
+         assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
+                          getLoFromF64(tyF, getFReg(ft))));
+
+         putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm,
+                     mkexpr(t1), getLoFromF64(tyF, getFReg(fmt)))));
+         break;   /* MSUB.S */
+      }
+      case 0x29: { /* MSUB.D */
+         DIP("msub.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
+         IRExpr *rm = get_IR_roundingmode();
+         t1 = newTemp(Ity_F64);
+         assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft)));
+
+         putDReg(fd, triop(Iop_SubF64, rm, mkexpr(t1), getDReg(fmt)));
+         break;   /* MSUB.D */
+      }
+      case 0x30: { /* NMADD.S */
+         DIP("nmadd.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
+         IRExpr *rm = get_IR_roundingmode();
+         t1 = newTemp(Ity_F32);
+         t2 = newTemp(Ity_F32);
+         assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
+                getLoFromF64(tyF, getFReg(ft))));
+
+         assign(t2, triop(Iop_AddF32, rm, mkexpr(t1),
+                          getLoFromF64(tyF, getFReg(fmt))));
+
+         putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t2))));
+         break;   /* NMADD.S */
+      }
+      case 0x31: { /* NMADD.D */
+         DIP("nmadd.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
+         IRExpr *rm = get_IR_roundingmode();
+         t1 = newTemp(Ity_F64);
+         t2 = newTemp(Ity_F64);
+         assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft)));
+
+         assign(t2, triop(Iop_AddF64, rm, mkexpr(t1), getDReg(fmt)));
+         putDReg(fd, unop(Iop_NegF64, mkexpr(t2)));
+         break;   /* NMADD.D */
+      }
+      case 0x38: { /* NMSUBB.S */
+         DIP("nmsub.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
+         IRExpr *rm = get_IR_roundingmode();
+         t1 = newTemp(Ity_F32);
+         t2 = newTemp(Ity_F32);
+         assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
+                          getLoFromF64(tyF, getFReg(ft))));
+
+         assign(t2, triop(Iop_SubF32, rm, mkexpr(t1), getLoFromF64(tyF,
+                                                      getFReg(fmt))));
+
+         putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t2))));
+         break;   /* NMSUBB.S */
+      }
+      case 0x39: { /* NMSUBB.D */
+         DIP("nmsub.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
+         IRExpr *rm = get_IR_roundingmode();
+         t1 = newTemp(Ity_F64);
+         t2 = newTemp(Ity_F64);
+         assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft)));
+
+         assign(t2, triop(Iop_SubF64, rm, mkexpr(t1), getDReg(fmt)));
+         putDReg(fd, unop(Iop_NegF64, mkexpr(t2)));
+         break;   /* NMSUBB.D */
+      }
+
+      default:
+         goto decode_failure;
+      }
+      break;
+
+   case 0x22:     /* LWL */
+
+      DIP("lwl");
+      {
+         /* t1 = addr */
+         t1 = newTemp(Ity_I32);
+#if defined (_MIPSEL)
+         assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+#elif defined (_MIPSEB)
+         assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
+                                     mkU32(extend_s_16to32(imm)))));
+#endif
+
+         /* t2 = word addr */
+         /* t4 = addr mod 4 */
+         LWX_SWX_PATTERN;
+
+         /* t3 = word content - shifted */
+         t3 = newTemp(Ity_I32);
+         assign(t3, binop(Iop_Shl32, load(Ity_I32, mkexpr(t2)), narrowTo(Ity_I8,
+                    binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)),
+                    mkU8(3)))));
+
+         /* rt content  - adjusted */
+         t5 = newTemp(Ity_I32);
+         assign(t5, binop(Iop_And32, getIReg(rt), binop(Iop_Shr32,
+                    mkU32(0xFFFFFFFF), narrowTo(Ity_I8, binop(Iop_Shl32,
+                    binop(Iop_Add32, mkexpr(t4), mkU32(0x1)), mkU8(0x3))))));
+
+         putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
+      }
+      break;
+
+   case 0x26:     /* LWR */
+
+      DIP("lwr");
+      {
+         /* t1 = addr */
+         t1 = newTemp(Ity_I32);
+#if defined (_MIPSEL)
+         assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+#elif defined (_MIPSEB)
+         assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
+                                     mkU32(extend_s_16to32(imm)))));
+#endif
+
+         /* t2 = word addr */
+         /* t4 = addr mod 4 */
+         LWX_SWX_PATTERN;
+
+         /* t3 = word content - shifted */
+         t3 = newTemp(Ity_I32);
+         assign(t3, binop(Iop_Shr32, load(Ity_I32, mkexpr(t2)),
+                    narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4),
+                    mkU8(3)))));
+
+         /* rt content  - adjusted */
+         t5 = newTemp(Ity_I32);
+         assign(t5, binop(Iop_And32, getIReg(rt), unop(Iop_Not32,
+                    binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
+                          binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
+
+         putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
+      }
+      break;
+
+   case 0x2B:     /* SW */
+      DIP("sw r%d, %d(r%d)", rt, imm, rs);
+      LOAD_STORE_PATTERN;
+      store(mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)));
+      break;
+
+   case 0x28:     /* SB */
+      DIP("sb");
+      LOAD_STORE_PATTERN;
+      store(mkexpr(t1), narrowTo(Ity_I8, getIReg(rt)));
+      break;
+
+   case 0x29:     /* SH */
+      DIP("sh\n");
+      LOAD_STORE_PATTERN;
+      store(mkexpr(t1), narrowTo(Ity_I16, getIReg(rt)));
+      break;
+
+   case 0x2A:     /* SWL */
+
+      DIP("swl\n");
+      {
+         /* t1 = addr */
+         t1 = newTemp(Ity_I32);
+#if defined (_MIPSEL)
+         assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+#elif defined (_MIPSEB)
+         assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
+                                     mkU32(extend_s_16to32(imm)))));
+#endif
+
+         /* t2 = word addr */
+         /* t4 = addr mod 4 */
+         LWX_SWX_PATTERN;
+
+         /* t3 = rt content - shifted */
+         t3 = newTemp(Ity_I32);
+         assign(t3, binop(Iop_Shr32, getIReg(rt), narrowTo(Ity_I8,
+                    binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)),
+                    mkU8(3)))));
+
+         /* word content  - adjusted */
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+         t7 = newTemp(Ity_I32);
+         t8 = newTemp(Ity_I32);
+
+         // neg(shr(0xFFFFFFFF, mul(sub(3,n), 8)))
+         assign(t5, binop(Iop_Mul32, binop(Iop_Sub32, mkU32(0x3), mkexpr(t4)),
+                          mkU32(0x8)));
+
+         assign(t6, binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
+                                                        mkexpr(t5))));
+         assign(t7, binop(Iop_Xor32, mkU32(0xFFFFFFFF), mkexpr(t6)));
+         assign(t8, binop(Iop_And32, load(Ity_I32, mkexpr(t2)), mkexpr(t7)));
+         store(mkexpr(t2), binop(Iop_Or32, mkexpr(t8), mkexpr(t3)));
+      }
+      break;
+
+   case 0x2E:     /* SWR */
+
+      DIP("swr");
+      {
+         /* t1 = addr */
+         t1 = newTemp(Ity_I32);
+#if defined (_MIPSEL)
+         assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+#elif defined (_MIPSEB)
+         assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
+                                     mkU32(extend_s_16to32(imm)))));
+#endif
+
+         /* t2 = word addr */
+         /* t4 = addr mod 4 */
+         LWX_SWX_PATTERN;
+
+         /* t3 = rt content - shifted */
+         t3 = newTemp(Ity_I32);
+         assign(t3, binop(Iop_Shl32, getIReg(rt), narrowTo(Ity_I8,
+                    binop(Iop_Shl32, mkexpr(t4), mkU8(3)))));
+
+         /* word content  - adjusted */
+         t5 = newTemp(Ity_I32);
+         assign(t5, binop(Iop_And32, load(Ity_I32, mkexpr(t2)), unop(Iop_Not32,
+                    binop(Iop_Shl32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
+                          binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
+
+         store(mkexpr(t2), binop(Iop_Xor32, mkexpr(t5), mkexpr(t3)));
+      }
+      break;
+
+   case 0x1C:     /*Special2 */
+      switch (function) {
+      case 0x02: { /* MUL */
+         DIP("mul");
+         putIReg(rd, binop(Iop_Mul32, getIReg(rs), getIReg(rt)));
+         break;
+      }
+
+      case 0x00: { /* MADD */
+         DIP("madd");
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I64);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+
+         assign(t1, getHI());
+         assign(t2, getLO());
+
+         assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
+
+         assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
+                                                      mkexpr(t3))));
+
+         assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
+                                     unop(Iop_64to32, mkexpr(t3)))));
+         assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
+
+         putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3))));
+         putLO(mkexpr(t4));
+         break;
+      }
+
+      case 0x01: { /* MADDU */
+         DIP("maddu");
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I64);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+
+         assign(t1, getHI());
+         assign(t2, getLO());
+
+         assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
+
+         assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
+                                                      mkexpr(t3))));
+         assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
+                                     unop(Iop_64to32, mkexpr(t3)))));
+         assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
+
+         putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3))));
+         putLO(mkexpr(t4));
+         break;
+      }
+
+      case 0x04: { /* MSUB */
+         DIP("msub");
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I64);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+
+         assign(t1, getHI());
+         assign(t2, getLO());
+
+         assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
+         assign(t4, unop(Iop_64to32, mkexpr(t3))); //new lo
+
+         //if lo<lo(mul) hi = hi - 1
+         assign(t5, unop(Iop_1Sto32, binop(Iop_CmpLT32U, mkexpr(t2),
+                                           mkexpr(t4))));
+
+         assign(t6, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t5)), mkexpr(t1),
+                                 binop(Iop_Sub32, mkexpr(t1), mkU32(0x1))));
+
+         putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3))));
+         putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
+         break;
+      }
+
+      case 0x05: { /* MSUBU */
+         DIP("msubu");
+         t1 = newTemp(Ity_I32);
+         t2 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I64);
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+         t6 = newTemp(Ity_I32);
+
+         assign(t1, getHI());
+         assign(t2, getLO());
+
+         assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
+         assign(t4, unop(Iop_64to32, mkexpr(t3))); //new lo
+
+         //if lo<lo(mul) hi = hi - 1
+         assign(t5, unop(Iop_1Sto32, binop(Iop_CmpLT32U, mkexpr(t2),
+                                           mkexpr(t4))));
+
+         assign(t6, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t5)),
+                    mkexpr(t1), binop(Iop_Sub32, mkexpr(t1), mkU32(0x1))));
+
+         putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3))));
+         putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
+         break;
+      }
+
+      case 0x20: { /* CLZ */
+         DIP("clz r%d, r%d", rd, rs);
+         t1 = newTemp(Ity_I32);
+         assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rs),
+                                           mkU32(0))));
+         putIReg(rd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
+                     unop(Iop_Clz32, getIReg(rs)), mkU32(0x00000020)));
+         break;
+      }
+
+      case 0x21: { /* CLO */
+         DIP("clo r%d, r%d", rd, rs);
+         t1 = newTemp(Ity_I32);
+         assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rs),
+                                           mkU32(0xffffffff))));
+         putIReg(rd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
+                     unop(Iop_Clz32, unop(Iop_Not32, getIReg(rs))),
+                     mkU32(0x00000020)));
+         break;
+      }
+
+      default:
+         goto decode_failure;
+      }
+      break;
+
+   case 0x1F:     /*Special3 */
+      switch (function) {
+      case 0x3B:
+          /*RDHWR*/ {
+            DIP("rdhwr r%d, r%d", rt, rd);
+            if (rd == 29) {
+               putIReg(rt, getULR());
+            } else
+               goto decode_failure;
+            break;
+         }
+      case 0x04:
+          /*INS*/ msb = get_msb(cins);
+         lsb = get_lsb(cins);
+
+         size = msb - lsb + 1;
+
+         vassert(lsb + size <= 32);
+         vassert(lsb + size > 0);
+
+         DIP("ins size:%d msb:%d lsb:%d", size, msb, lsb);
+         /*put size bits from rs at the pos in temporary */
+         t0 = newTemp(Ity_I32);
+         t3 = newTemp(Ity_I32);
+         /*shift left for 32 - size to clear leading bits and get zeros
+           at the end */
+         assign(t0, binop(Iop_Shl32, getIReg(rs), mkU8(32 - size)));
+         /*now set it at pos */
+         t1 = newTemp(Ity_I32);
+         assign(t1, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size - lsb)));
+
+         if (lsb > 0) {
+            t2 = newTemp(Ity_I32);
+            /*clear everything but lower pos bits from rt */
+            assign(t2, binop(Iop_Shl32, getIReg(rt), mkU8(32 - lsb)));
+            assign(t3, binop(Iop_Shr32, mkexpr(t2), mkU8(32 - lsb)));
+         }
+
+         if (msb < 31) {
+            t4 = newTemp(Ity_I32);
+            /*clear everything but upper msb + 1 bits from rt */
+            assign(t4, binop(Iop_Shr32, getIReg(rt), mkU8(msb + 1)));
+            t5 = newTemp(Ity_I32);
+            assign(t5, binop(Iop_Shl32, mkexpr(t4), mkU8(msb + 1)));
+
+            /*now combine these registers */
+            if (lsb > 0) {
+               t6 = newTemp(Ity_I32);
+               assign(t6, binop(Iop_Or32, mkexpr(t5), mkexpr(t1)));
+               putIReg(rt, binop(Iop_Or32, mkexpr(t6), mkexpr(t3)));
+            } else {
+               putIReg(rt, binop(Iop_Or32, mkexpr(t1), mkexpr(t5)));
+            }
+         }
+
+         else {
+            putIReg(rt, binop(Iop_Or32, mkexpr(t1), mkexpr(t3)));
+
+         }
+         break;
+
+      case 0x00:
+         /*EXT*/ msb = get_msb(cins);
+         lsb = get_lsb(cins);
+         size = msb + 1;
+         DIP("ext size:%d msb:%d lsb:%d", size, msb, lsb);
+         vassert(lsb + size <= 32);
+         vassert(lsb + size > 0);
+         /*put size bits from rs at the top of in temporary */
+         if (lsb + size < 32) {
+            t0 = newTemp(Ity_I32);
+            assign(t0, binop(Iop_Shl32, getIReg(rs), mkU8(32 - lsb - size)));
+            putIReg(rt, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size)));
+         } else {
+            putIReg(rt, binop(Iop_Shr32, getIReg(rs), mkU8(32 - size)));
+
+         }
+         break;
+
+      case 0x20:
+         /*BSHFL*/ switch (sa) {
+
+         case 0x10:
+             /*SEB*/ DIP("seb");
+            putIReg(rd, unop(Iop_8Sto32, unop(Iop_32to8, getIReg(rt))));
+            break;
+
+         case 0x18:
+             /*SEH*/ DIP("seh");
+            putIReg(rd, unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
+            break;
+
+         case 0x02:
+             /*WSBH*/ DIP("wsbh");
+            t0 = newTemp(Ity_I32);
+            t1 = newTemp(Ity_I32);
+            t2 = newTemp(Ity_I32);
+            t3 = newTemp(Ity_I32);
+            assign(t0, binop(Iop_Shl32, binop(Iop_And32, getIReg(rt),
+                                        mkU32(0x00FF0000)), mkU8(0x8)));
+            assign(t1, binop(Iop_Shr32, binop(Iop_And32, getIReg(rt),
+                       mkU32(0xFF000000)), mkU8(0x8)));
+            assign(t2, binop(Iop_Shl32, binop(Iop_And32, getIReg(rt),
+                       mkU32(0x000000FF)), mkU8(0x8)));
+            assign(t3, binop(Iop_Shr32, binop(Iop_And32, getIReg(rt),
+                       mkU32(0x0000FF00)), mkU8(0x8)));
+            putIReg(rd, binop(Iop_Or32, binop(Iop_Or32, mkexpr(t0),
+                        mkexpr(t1)), binop(Iop_Or32, mkexpr(t2), mkexpr(t3))));
+            break;
+
+         default:
+            goto decode_failure;
+
+         }
+         break;
+       /*BSHFL*/ default:
+         goto decode_failure;
+
+      }
+      break;      /*Special3 */
+
+   case 0x3B:
+      if (0x3B == function && (archinfo->hwcaps & VEX_PRID_COMP_BROADCOM)) {
+          /*RDHWR*/
+            DIP("rdhwr r%d, r%d", rt, rd);
+            if (rd == 29) {
+               putIReg(rt, getULR());
+            } else
+               goto decode_failure;
+            break;
+      } else {
+         goto decode_failure;
+      }
+
+   case 0x00:     /*Special */
+
+      switch (function) {
+      case 0x1: {
+         UInt mov_cc = get_mov_cc(cins);
+         if (tf == 0) { /* MOVF */
+            DIP("movf r%d, r%d, %d", rd, rs, mov_cc);
+            {
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I32);
+               t4 = newTemp(Ity_I32);
+
+               assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
+                                                 mkU32(mov_cc))));
+               assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
+                          binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
+                          mkU8(24 + mov_cc)), mkU32(0x1)), binop(Iop_And32,
+                          binop(Iop_Shr32, getFCSR(), mkU8(23)),
+                          mkU32(0x1))));
+
+               assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
+                                                 mkexpr(t2))));
+               assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
+                          getIReg(rd), getIReg(rs)));
+               putIReg(rd, mkexpr(t4));
+            }
+         } else if (tf == 1) {   /* MOVT */
+            DIP("movt r%d, r%d, %d", rd, rs,
+                mov_cc);
+            {
+               t1 = newTemp(Ity_I32);
+               t2 = newTemp(Ity_I32);
+               t3 = newTemp(Ity_I32);
+               t4 = newTemp(Ity_I32);
+
+               assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
+                                                 mkU32(mov_cc))));
+               assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
+                          binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
+                          mkU8(24 + mov_cc)), mkU32(0x1)), binop(Iop_And32,
+                          binop(Iop_Shr32, getFCSR(), mkU8(23)),
+                          mkU32(0x1))));
+
+               assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
+                                                 mkexpr(t2))));
+               assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
+                          getIReg(rd), getIReg(rs)));
+               putIReg(rd, mkexpr(t4));
+            }
+         }
+         break;
+      }
+      case 0x0A: {
+         /* MOVZ */
+         DIP("movz");
+         t1 = newTemp(ty);
+         t2 = newTemp(ty);
+         {
+            assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
+                                              mkU32(0x0))));
+            assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
+                                              mkU32(0x0))));
+            putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
+                        mkexpr(t1)), binop(Iop_And32, getIReg(rd),
+                        mkexpr(t2))));
+         }
+         break;
+      }
+
+      case 0x0B: {
+         /* MOVN */
+         DIP("movn");
+         t1 = newTemp(ty);
+         t2 = newTemp(ty);
+         {
+            assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
+                                              mkU32(0x0))));
+            assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
+                                              mkU32(0x0))));
+            putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
+                        mkexpr(t2)), binop(Iop_And32, getIReg(rd),
+                        mkexpr(t1))));
+         }
+         break;
+      }
+
+      case 0x18:  /* MULT */
+         DIP("mult");
+         t2 = newTemp(Ity_I64);
+
+         assign(t2, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
+                          mkNarrowTo32(ty, getIReg(rt))));
+
+         putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
+         putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
+         break;
+
+      case 0x19:  /* MULTU */
+         DIP("multu");
+         t2 = newTemp(Ity_I64);
+
+         assign(t2, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
+                                       mkNarrowTo32(ty, getIReg(rt))));
+
+         putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
+         putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
+         break;
+
+      case 0x20:  /* ADD */
+         DIP("add");
+         {
+            t2 = newTemp(Ity_I32);
+
+            assign(t2, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
+            putIReg(rd, mkexpr(t2));
+         }
+         break;
+
+      case 0x1A:  /* DIV */
+         DIP("div");
+         {
+            t1 = newTemp(Ity_I64);
+            t2 = newTemp(Ity_I64);
+
+            assign(t1, unop(Iop_32Sto64, getIReg(rs)));
+            assign(t2, binop(Iop_DivModS64to32, mkexpr(t1), getIReg(rt)));
+
+            putHI(unop(Iop_64HIto32, mkexpr(t2)));
+            putLO(unop(Iop_64to32, mkexpr(t2)));
+         }
+         break;
+
+      case 0x1B:  /* DIVU */
+         DIP("divu");
+         {
+            t1 = newTemp(Ity_I64);
+            t2 = newTemp(Ity_I64);
+            assign(t1, unop(Iop_32Uto64, getIReg(rs)));
+            assign(t2, binop(Iop_DivModU64to32, mkexpr(t1), getIReg(rt)));
+            putHI(unop(Iop_64HIto32, mkexpr(t2)));
+            putLO(unop(Iop_64to32, mkexpr(t2)));
+         }
+         break;
+
+      case 0x10:  /* MFHI */
+         DIP("mfhi");
+         putIReg(rd, getHI());
+         break;
+
+      case 0x11:  /* MTHI */
+         DIP("mthi");
+         putHI(getIReg(rs));
+         break;
+
+      case 0x12:  /* MFLO */
+         DIP("mflo");
+         putIReg(rd, getLO());
+         break;
+
+      case 0x13:  /* MTLO */
+         DIP("mtlo");
+         putLO(getIReg(rs));
+         break;
+
+      case 0x21:  /* ADDU */
+         DIP("addu");
+         ALU_PATTERN(Iop_Add32);
+         break;
+
+      case 0x22:  /* SUB */
+         DIP("sub");
+         ALU_PATTERN(Iop_Sub32);
+         break;
+
+      case 0x23:  /* SUBU */
+         DIP("subu");
+         ALU_PATTERN(Iop_Sub32);
+         break;
+
+      case 0x24:  /* AND */
+         DIP("and");
+         ALU_PATTERN(Iop_And32);
+         break;
+
+      case 0x25:  /* OR */
+         DIP("or r%d, r%d, r%d", rd, rs, rt);
+         ALU_PATTERN(Iop_Or32);
+         break;
+
+      case 0x26:  /* XOR */
+         DIP("xor");
+         ALU_PATTERN(Iop_Xor32);
+         break;
+
+      case 0x27:  /* NOR */
+         DIP("nor");
+         putIReg(rd, unop(Iop_Not32, binop(Iop_Or32, getIReg(rs),getIReg(rt))));
+         break;
+
+      case 0x08:  /* JR */
+         DIP("jr r%d", rs);
+         t0 = newTemp(ty);
+         assign(t0, getIReg(rs));
+         lastn = mkexpr(t0);
+         break;
+
+      case 0x09:  /* JALR */
+         DIP("jalr r%d r%d", rd, rs);
+         putIReg(rd, mkU32(guest_PC_curr_instr + 8));
+         t0 = newTemp(Ity_I32);
+         assign(t0, getIReg(rs));
+         lastn = mkexpr(t0);
+         break;
+
+      case 0x0C:  /* SYSCALL */
+         DIP("syscall");
+         putPC(mkU32(guest_PC_curr_instr + 4));
+         dres.jk_StopHere = Ijk_Sys_syscall;
+         dres.whatNext    = Dis_StopHere;
+         break;
+
+      case 0x2A:  /* SLT */
+         DIP("slt");
+         putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
+                                      getIReg(rt))));
+         break;
+
+      case 0x2B:  /* SLTU */
+         DIP("sltu");
+         putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
+                                      getIReg(rt))));
+         break;
+
+      case 0x00:
+         /* SLL */
+         DIP("sll");
+         SXX_PATTERN(Iop_Shl32);
+         break;
+
+      case 0x04:  /* SLLV */
+         DIP("sllv");
+         SXXV_PATTERN(Iop_Shl32);
+         break;
+
+      case 0x03:  /* SRA */
+         DIP("sra");
+         SXX_PATTERN(Iop_Sar32);
+         break;
+
+      case 0x07:  /* SRAV */
+         DIP("srav");
+         SXXV_PATTERN(Iop_Sar32);
+         break;
+
+      case 0x02: {  /* SRL */
+         rot = get_rot(cins);
+         if (rot) {
+            DIP("rotr");
+            putIReg(rd, mkWidenFrom32(ty, genROR32(mkNarrowTo32(ty,
+                        getIReg(rt)), sa), False));
+         } else {
+            DIP("srl");
+            SXX_PATTERN(Iop_Shr32);
+         }
+      break;
+      }
+
+      case 0x06: {
+         rot = get_rotv(cins);
+         if (rot) {
+            DIP("rotrv");
+            putIReg(rd, mkWidenFrom32(ty, genRORV32(mkNarrowTo32(ty,
+                        getIReg(rt)), mkNarrowTo32(ty, getIReg(rs))),False));
+            break;
+         } else {
+            /* SRLV */
+            DIP("srlv");
+            SXXV_PATTERN(Iop_Shr32);
+            break;
+         }
+      } 
+
+      case 0x0D:  /* BREAK */
+         DIP("Info: Breakpoint...code = %d", trap_code);
+         jmp_lit(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
+         vassert(dres.whatNext == Dis_StopHere);
+         break;
+
+      case 0x30: { /* TGE */
+         /*tge */ DIP("tge r%d, r%d %d", rs, rt, trap_code);
+         stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rt), getIReg (rs)),
+                            Ijk_SigTRAP,
+                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
+         break;
+      }
+      case 0x31: { /* TGEU */
+         /*tgeu */ DIP("tgeu r%d, r%d %d", rs, rt, trap_code);
+         stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rt), getIReg (rs)),
+                            Ijk_SigTRAP,
+                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
+         break;
+      }
+      case 0x32: { /* TLT */
+         /*tlt */ DIP("tlt r%d, r%d %d", rs, rt, trap_code);
+         stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs), getIReg (rt)),
+                            Ijk_SigTRAP,
+                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
+         break;
+      }
+      case 0x33: { /* TLTU */
+         /*tltu */ DIP("tltu r%d, r%d %d", rs, rt, trap_code);
+         stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs), getIReg (rt)),
+                            Ijk_SigTRAP,
+                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
+         break;
+      }
+      case 0x34: { /* TEQ */
+         /*teq */ DIP("teq r%d, r%d %d", rs, rt, trap_code);
+         stmt (IRStmt_Exit(binop (Iop_CmpEQ32, getIReg (rs), getIReg (rt)),
+               Ijk_SigTRAP, IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
+         break;
+      }
+      case 0x36: { /* TNE */
+         /*tne */ DIP("tne r%d, r%d %d", rs, rt, trap_code);
+         stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs), getIReg (rt)),
+                            Ijk_SigTRAP,
+                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
+         break;
+      }
+      case 0x0F: {
+         /*SYNC*/ DIP("sync r%d, r%d, %d", rt, rd, sel);
+         lsb = get_lsb(cins);
+         IRDirty *d = unsafeIRDirty_0_N(0,
+                                        "mips32_dirtyhelper_sync",
+                                        &mips32_dirtyhelper_sync,
+                                        mkIRExprVec_1
+                                        (mkU32(lsb)));
+
+         d->needsBBP = False;
+         d->nFxState = 0;
+
+         stmt(IRStmt_Dirty(d));
+         break;
+      }
+
+      default:
+         goto decode_failure;
+      }
+      break;
+
+   case 0x01:     /* Regimm */
+
+      switch (rt) {
+      case 0x01:  /* BGEZ */
+         DIP("bgez");
+         dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
+                           mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
+         break;
+
+      case 0x03:  /* BGEZL */
+         DIP("bgezl");
+         lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
+                                   getIReg(rs), mode64 ?
+                                      mkU64(0x8000000000000000ULL)
+                                      :mkU32(0x80000000)),
+                                   mkU32(0x0)), imm);
+         break;
+
+      case 0x00:  /* BLTZ */
+         DIP("bltz");
+         dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
+                    mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
+         break;
+
+      case 0x02:  /* BLTZL */
+         DIP("bltzl");
+         lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
+                                   getIReg(rs), mkU32(0x80000000)),
+                                   mkU32(0x80000000)), imm);
+         break;
+
+      case 0x10:  /* BLTZAL */
+         DIP("bltzal");
+         dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
+                    mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
+         break;
+
+      case 0x12:  /* BLTZALL */
+         DIP("bltzall");
+         putIReg(31, mkU32(guest_PC_curr_instr + 8));
+         lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
+                                   getIReg(rs), mkU32(0x80000000)),
+                                                mkU32(0x80000000)), imm);
+         break;
+
+      case 0x11:  /* BGEZAL */
+         DIP("bgezal");
+         dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
+                    mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
+         break;
+
+      case 0x13:  /* BGEZALL */
+         DIP("bgezall");
+         putIReg(31, mkU32(guest_PC_curr_instr + 8));
+         lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
+                                   getIReg(rs), mkU32(0x80000000)),
+                                   mkU32(0x0)), imm);
+         break;
+
+      case 0x08: { /* TGEI */
+         /*tgei */ DIP("tgei r%d, %d %d", rs, imm, trap_code);
+         stmt (IRStmt_Exit (binop (Iop_CmpLT32S, mkU32 (imm), getIReg (rs)),
+                            Ijk_SigTRAP,
+                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
+         break;
+      }
+      case 0x09: { /* TGEIU */
+         /*tqeiu */ DIP("tgeiu r%d, %d %d", rs, imm, trap_code);
+         stmt (IRStmt_Exit (binop (Iop_CmpLT32U, mkU32 (imm), getIReg (rs)),
+                            Ijk_SigTRAP,
+                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
+         break;
+      }
+      case 0x0A: { /* TLTI */
+         /*tlti */ DIP("tlti r%d, %d %d", rs, imm, trap_code);
+         stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs), mkU32 (imm)),
+                            Ijk_SigTRAP,
+                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
+         break;
+      }
+      case 0x0B: { /* TLTIU */
+         /*tltiu */ DIP("tltiu r%d, %d %d", rs, imm, trap_code);
+         stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs), mkU32 (imm)),
+                            Ijk_SigTRAP,
+                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
+         break;
+      }
+      case 0x0C: { /* TEQI */
+         /*teqi */ DIP("teqi r%d, %d %d", rs, imm, trap_code);
+         stmt (IRStmt_Exit (binop (Iop_CmpEQ32, getIReg (rs), mkU32 (imm)),
+                            Ijk_SigTRAP,
+                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
+         break;
+      }
+      case 0x0E: { /* TNEI */
+         /*tnei */ DIP("tnei r%d, %d %d", rs, imm, trap_code);
+         stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs), mkU32 (imm)),
+                            Ijk_SigTRAP,
+                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
+         break;
+      }
+      case 0x1F:
+          /*SYNCI*/
+             //Just ignore it
+             break;
+
+      default:
+         goto decode_failure;
+      }
+      break;
+
+   case 0x04:
+      DIP("beq");
+      dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)),
+                              imm, &bstmt);
+      break;
+
+   case 0x14:
+      DIP("beql");
+      lastn = dis_branch_likely(binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)),
+                                      imm);
+      break;
+
+   case 0x05:
+      DIP("bne");
+      dis_branch(False, binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)),
+                              imm, &bstmt);
+      break;
+
+   case 0x15:
+      DIP("bnel");
+      lastn =
+          dis_branch_likely(binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)), imm);
+      break;
+
+   case 0x07:     /* BGTZ */
+      DIP("bgtz");
+      dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE32S, getIReg(rs),
+                             mkU32(0x00))), imm, &bstmt);
+      break;
+
+   case 0x17:     /* BGTZL */
+      DIP("bgtzl");
+      lastn = dis_branch_likely(binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x00)),
+                                      imm);
+      break;
+
+   case 0x06:     /* BLEZ */
+      DIP("blez");
+      dis_branch(False,binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x0)), imm,
+                             &bstmt);
+      break;
+
+   case 0x16:     /* BLEZL */
+      DIP("blezl");
+      lastn = dis_branch_likely(unop(Iop_Not1, (binop(Iop_CmpLE32S,
+                                     getIReg(rs), mkU32(0x0)))), imm);
+      break;
+
+   case 0x08:     /* ADDI TODO: Check this */
+      DIP("addi r%d, r%d, %d", rt, rs, imm);
+      putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+      break;
+
+   case 0x09:     /* ADDIU */
+      DIP("addiu r%d, r%d, %d", rt, rs, imm);
+      putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+      break;
+
+   case 0x0C:     /* ANDI */
+      DIP("andi");
+      ALUI_PATTERN(Iop_And32);
+      break;
+
+   case 0x0E:     /* XORI */
+      DIP("xori");
+      ALUI_PATTERN(Iop_Xor32);
+      break;
+
+   case 0x0D:     /* ORI */
+      DIP("ori");
+      ALUI_PATTERN(Iop_Or32);
+      break;
+
+   case 0x0A:     /* SLTI */
+      DIP("slti");
+      putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
+                                         mkU32(extend_s_16to32(imm)))));
+      break;
+
+   case 0x0B:     /* SLTIU */
+      DIP("sltiu");
+      putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
+                                         mkU32(extend_s_16to32(imm)))));
+      break;
+
+   case 0x30:     /* LL / LWC0 */
+      DIP("ll r%d, %d(r%d)", rt, imm, rs);
+      LOAD_STORE_PATTERN;
+
+      t2 = newTemp(Ity_I32);
+#if defined (_MIPSEL)
+      stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), NULL /*this is a load */ ));
+#elif defined (_MIPSEB)
+      stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), NULL /*this is a load */ ));
+#endif
+
+      putIReg(rt, mkexpr(t2));
+      break;
+
+   case 0x38:     /* SC / SWC0 */
+      DIP("sc");
+      LOAD_STORE_PATTERN;
+
+      t2 = newTemp(Ity_I1);
+#if defined (_MIPSEL)
+      stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt))));
+#elif defined (_MIPSEB)
+      stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt))));
+#endif
+
+      putIReg(rt, unop(Iop_1Uto32, mkexpr(t2)));
+      break;
+
+ decode_failure:
+      /* All decode failures end up here. */
+      DIP("vex mips->IR: unhandled instruction bytes: "
+          "0x%x 0x%x 0x%x 0x%x\n",
+          (Int) getIByte(delta_start + 0),
+          (Int) getIByte(delta_start + 1),
+          (Int) getIByte(delta_start + 2),
+          (Int) getIByte(delta_start + 3));
+
+      /* Tell the dispatcher that this insn cannot be decoded, and so has
+         not been executed, and (is currently) the next to be executed.
+         EIP should be up-to-date since it made so at the start bnezof each
+         insn, but nevertheless be paranoid and update it again right
+         now. */
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_PC),
+           mkU32(guest_PC_curr_instr)));
+      jmp_lit(&dres, Ijk_NoDecode, guest_PC_curr_instr);
+      dres.whatNext = Dis_StopHere;
+      dres.len = 0;
+      return dres;
+   }        /* switch (opc) for the main (primary) opcode switch. */
+
+   /* All MIPS insn have 4 bytes */
+
+   if (delay_slot_branch) {
+      delay_slot_branch = False;
+      stmt(bstmt);
+      bstmt = NULL;
+      putPC(mkU32(guest_PC_curr_instr + 4));
+      dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
+                         Ijk_Call : Ijk_Boring;
+   }
+
+   if (likely_delay_slot) {
+      dres.jk_StopHere = Ijk_Boring;
+      dres.whatNext = Dis_StopHere;
+      putPC(lastn);
+      lastn = NULL;
+   }
+   if (delay_slot_jump) {
+      putPC(lastn);
+      lastn = NULL;
+      dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
+                         Ijk_Call : Ijk_Boring;
+   }
+
+ decode_success:
+   /* All decode successes end up here. */
+   switch (dres.whatNext) {
+      case Dis_Continue:
+         putPC(mkU32(guest_PC_curr_instr + 4));
+         break;
+      case Dis_ResteerU:
+      case Dis_ResteerC:
+         putPC(mkU32(dres.continueAt));
+         break;
+      case Dis_StopHere:
+         break;
+      default:
+         vassert(0);
+         break;
+   }
+
+   // On MIPS we need to check if the last instruction
+   // in block is branch or jump
+   if ((vex_control.guest_max_insns - 1) == (delta+4)/4)
+      if (branch_or_jump(guest_code + delta + 4)) {
+         dres.whatNext = Dis_StopHere;
+         dres.jk_StopHere = Ijk_Boring;
+         putPC(mkU32(guest_PC_curr_instr + 4));
+   }
+   dres.len = 4;
+
+   DIP("\n");
+
+   return dres;
+
+}
+
+/*------------------------------------------------------------*/
+/*--- Top-level fn                                         ---*/
+/*------------------------------------------------------------*/
+
+/* Disassemble a single instruction into IR.  The instruction
+   is located in host memory at &guest_code[delta]. */
+
+DisResult
+disInstr_MIPS(IRSB*        irsb_IN,
+              Bool         (*resteerOkFn) (void *, Addr64),
+              Bool         resteerCisOk,
+              void*        callback_opaque,
+              UChar*       guest_code_IN,
+              Long         delta,
+              Addr64       guest_IP,
+              VexArch      guest_arch,
+              VexArchInfo* archinfo,
+              VexAbiInfo*  abiinfo,
+              Bool         host_bigendian_IN)
+{
+   DisResult dres;
+
+   /* Set globals (see top of this file) */
+   vassert(guest_arch == VexArchMIPS32);
+
+   mode64 = guest_arch != VexArchMIPS32;
+
+   guest_code = guest_code_IN;
+   irsb = irsb_IN;
+   host_is_bigendian = host_bigendian_IN;
+   guest_PC_curr_instr = (Addr32) guest_IP;
+   guest_PC_bbstart = (Addr32) toUInt(guest_IP - delta);
+
+   dres = disInstr_MIPS_WRK(resteerOkFn, resteerCisOk, callback_opaque,
+                            delta, archinfo, abiinfo);
+
+   return dres;
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end                                        guest_mips_toIR.c ---*/
+/*--------------------------------------------------------------------*/
diff --git a/priv/host_mips_defs.c b/priv/host_mips_defs.c
new file mode 100644
index 0000000..22082d5
--- /dev/null
+++ b/priv/host_mips_defs.c
@@ -0,0 +1,4048 @@
+
+/*---------------------------------------------------------------*/
+/*--- begin                                  host_mips_defs.c ---*/
+/*---------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2010-2012 RT-RK
+      mips-valgrind@rt-rk.com
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "libvex_basictypes.h"
+#include "libvex.h"
+#include "libvex_trc_values.h"
+
+#include "main_util.h"
+#include "host_generic_regs.h"
+#include "host_mips_defs.h"
+
+/*---------------- Registers ----------------*/
+
+void ppHRegMIPS(HReg reg, Bool mode64)
+{
+   Int r;
+   static HChar *ireg32_names[35]
+       = { "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+      "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
+      "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
+      "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31",
+      "%32", "%33", "%34",
+   };
+
+   static HChar *freg32_names[32]
+       = { "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
+      "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
+      "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
+      "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "f30", "$f31"
+   };
+
+   static HChar *freg64_names[32]
+       = { "$d0", "$d1", "$d2", "$d3", "$d4", "$d5", "$d6", "$d7",
+      "$d8", "$d9", "$d10", "$d11", "$d12", "$d13", "$d14", "$d15",
+   };
+
+   /* Be generic for all virtual regs. */
+   if (hregIsVirtual(reg)) {
+      ppHReg(reg);
+      return;
+   }
+
+   /* But specific for real regs. */
+   vassert(hregClass(reg) == HRcInt32 || hregClass(reg) == HRcInt64 ||
+      hregClass(reg) == HRcFlt32 || hregClass(reg) == HRcFlt64);
+
+   /* But specific for real regs. */
+   {
+      switch (hregClass(reg)) {
+         case HRcInt32:
+            r = hregNumber(reg);
+            vassert(r >= 0 && r < 32);
+            vex_printf("%s", ireg32_names[r]);
+            return;
+         case HRcFlt32:
+            r = hregNumber(reg);
+            vassert(r >= 0 && r < 32);
+            vex_printf("%s", freg32_names[r]);
+            return;
+         case HRcFlt64:
+            r = hregNumber(reg);
+            vassert(r >= 0 && r < 32);
+            vex_printf("%s", freg64_names[r]);
+            return;
+         default:
+            vpanic("ppHRegMIPS");
+            break;
+      }
+   }
+
+   return;
+}
+
+#define MkHRegGPR(_n, _mode64) \
+   mkHReg(_n, _mode64 ? HRcInt64 : HRcInt32, False)
+
+HReg hregMIPS_GPR0(Bool mode64)
+{
+   return MkHRegGPR(0, mode64);
+}
+
+HReg hregMIPS_GPR1(Bool mode64)
+{
+   return MkHRegGPR(1, mode64);
+}
+
+HReg hregMIPS_GPR2(Bool mode64)
+{
+   return MkHRegGPR(2, mode64);
+}
+
+HReg hregMIPS_GPR3(Bool mode64)
+{
+   return MkHRegGPR(3, mode64);
+}
+
+HReg hregMIPS_GPR4(Bool mode64)
+{
+   return MkHRegGPR(4, mode64);
+}
+
+HReg hregMIPS_GPR5(Bool mode64)
+{
+   return MkHRegGPR(5, mode64);
+}
+
+HReg hregMIPS_GPR6(Bool mode64)
+{
+   return MkHRegGPR(6, mode64);
+}
+
+HReg hregMIPS_GPR7(Bool mode64)
+{
+   return MkHRegGPR(7, mode64);
+}
+
+HReg hregMIPS_GPR8(Bool mode64)
+{
+   return MkHRegGPR(8, mode64);
+}
+
+HReg hregMIPS_GPR9(Bool mode64)
+{
+   return MkHRegGPR(9, mode64);
+}
+
+HReg hregMIPS_GPR10(Bool mode64)
+{
+   return MkHRegGPR(10, mode64);
+}
+
+HReg hregMIPS_GPR11(Bool mode64)
+{
+   return MkHRegGPR(11, mode64);
+}
+
+HReg hregMIPS_GPR12(Bool mode64)
+{
+   return MkHRegGPR(12, mode64);
+}
+
+HReg hregMIPS_GPR13(Bool mode64)
+{
+   return MkHRegGPR(13, mode64);
+}
+
+HReg hregMIPS_GPR14(Bool mode64)
+{
+   return MkHRegGPR(14, mode64);
+}
+
+HReg hregMIPS_GPR15(Bool mode64)
+{
+   return MkHRegGPR(15, mode64);
+}
+
+HReg hregMIPS_GPR16(Bool mode64)
+{
+   return MkHRegGPR(16, mode64);
+}
+
+HReg hregMIPS_GPR17(Bool mode64)
+{
+   return MkHRegGPR(17, mode64);
+}
+
+HReg hregMIPS_GPR18(Bool mode64)
+{
+   return MkHRegGPR(18, mode64);
+}
+
+HReg hregMIPS_GPR19(Bool mode64)
+{
+   return MkHRegGPR(19, mode64);
+}
+
+HReg hregMIPS_GPR20(Bool mode64)
+{
+   return MkHRegGPR(20, mode64);
+}
+
+HReg hregMIPS_GPR21(Bool mode64)
+{
+   return MkHRegGPR(21, mode64);
+}
+
+HReg hregMIPS_GPR22(Bool mode64)
+{
+   return MkHRegGPR(22, mode64);
+}
+
+HReg hregMIPS_GPR23(Bool mode64)
+{
+   return MkHRegGPR(23, mode64);
+}
+
+HReg hregMIPS_GPR24(Bool mode64)
+{
+   return MkHRegGPR(24, mode64);
+}
+
+HReg hregMIPS_GPR25(Bool mode64)
+{
+   return MkHRegGPR(25, mode64);
+}
+
+HReg hregMIPS_GPR26(Bool mode64)
+{
+   return MkHRegGPR(26, mode64);
+}
+
+HReg hregMIPS_GPR27(Bool mode64)
+{
+   return MkHRegGPR(27, mode64);
+}
+
+HReg hregMIPS_GPR28(Bool mode64)
+{
+   return MkHRegGPR(28, mode64);
+}
+
+HReg hregMIPS_GPR29(Bool mode64)
+{
+   return MkHRegGPR(29, mode64);
+}
+
+HReg hregMIPS_GPR30(Bool mode64)
+{
+   return MkHRegGPR(30, mode64);
+}
+
+HReg hregMIPS_GPR31(Bool mode64)
+{
+   return MkHRegGPR(31, mode64);
+}
+
+#define MkHRegFPR(_n, _mode64) \
+   mkHReg(_n, _mode64 ? HRcFlt64 : HRcFlt32, False)
+
+HReg hregMIPS_F0(Bool mode64)
+{
+   return MkHRegFPR(0, mode64);
+}
+
+HReg hregMIPS_F1(Bool mode64)
+{
+   return MkHRegFPR(1, mode64);
+}
+
+HReg hregMIPS_F2(Bool mode64)
+{
+   return MkHRegFPR(2, mode64);
+}
+
+HReg hregMIPS_F3(Bool mode64)
+{
+   return MkHRegFPR(3, mode64);
+}
+
+HReg hregMIPS_F4(Bool mode64)
+{
+   return MkHRegFPR(4, mode64);
+}
+
+HReg hregMIPS_F5(Bool mode64)
+{
+   return MkHRegFPR(5, mode64);
+}
+
+HReg hregMIPS_F6(Bool mode64)
+{
+   return MkHRegFPR(6, mode64);
+}
+
+HReg hregMIPS_F7(Bool mode64)
+{
+   return MkHRegFPR(7, mode64);
+}
+
+HReg hregMIPS_F8(Bool mode64)
+{
+   return MkHRegFPR(8, mode64);
+}
+
+HReg hregMIPS_F9(Bool mode64)
+{
+   return MkHRegFPR(9, mode64);
+}
+
+HReg hregMIPS_F10(Bool mode64)
+{
+   return MkHRegFPR(10, mode64);
+}
+
+HReg hregMIPS_F11(Bool mode64)
+{
+   return MkHRegFPR(11, mode64);
+}
+
+HReg hregMIPS_F12(Bool mode64)
+{
+   return MkHRegFPR(12, mode64);
+}
+
+HReg hregMIPS_F13(Bool mode64)
+{
+   return MkHRegFPR(13, mode64);
+}
+
+HReg hregMIPS_F14(Bool mode64)
+{
+   return MkHRegFPR(14, mode64);
+}
+
+HReg hregMIPS_F15(Bool mode64)
+{
+   return MkHRegFPR(15, mode64);
+}
+
+HReg hregMIPS_F16(Bool mode64)
+{
+   return MkHRegFPR(16, mode64);
+}
+
+HReg hregMIPS_F17(Bool mode64)
+{
+   return MkHRegFPR(17, mode64);
+}
+
+HReg hregMIPS_F18(Bool mode64)
+{
+   return MkHRegFPR(18, mode64);
+}
+
+HReg hregMIPS_F19(Bool mode64)
+{
+   return MkHRegFPR(19, mode64);
+}
+
+HReg hregMIPS_F20(Bool mode64)
+{
+   return MkHRegFPR(20, mode64);
+}
+
+HReg hregMIPS_F21(Bool mode64)
+{
+   return MkHRegFPR(21, mode64);
+}
+
+HReg hregMIPS_F22(Bool mode64)
+{
+   return MkHRegFPR(22, mode64);
+}
+
+HReg hregMIPS_F23(Bool mode64)
+{
+   return MkHRegFPR(23, mode64);
+}
+
+HReg hregMIPS_F24(Bool mode64)
+{
+   return MkHRegFPR(24, mode64);
+}
+
+HReg hregMIPS_F25(Bool mode64)
+{
+   return MkHRegFPR(25, mode64);
+}
+
+HReg hregMIPS_F26(Bool mode64)
+{
+   return MkHRegFPR(26, mode64);
+}
+
+HReg hregMIPS_F27(Bool mode64)
+{
+   return MkHRegFPR(27, mode64);
+}
+
+HReg hregMIPS_F28(Bool mode64)
+{
+   return MkHRegFPR(28, mode64);
+}
+
+HReg hregMIPS_F29(Bool mode64)
+{
+   return MkHRegFPR(29, mode64);
+}
+
+HReg hregMIPS_F30(Bool mode64)
+{
+   return MkHRegFPR(30, mode64);
+}
+
+HReg hregMIPS_F31(Bool mode64)
+{
+   return MkHRegFPR(31, mode64);
+}
+
+HReg hregMIPS_PC(Bool mode64)
+{
+   return mkHReg(32, mode64 ? HRcFlt64 : HRcFlt32, False);
+}
+
+HReg hregMIPS_HI(Bool mode64)
+{
+   return mkHReg(33, mode64 ? HRcFlt64 : HRcFlt32, False);
+}
+
+HReg hregMIPS_LO(Bool mode64)
+{
+   return mkHReg(34, mode64 ? HRcFlt64 : HRcFlt32, False);
+}
+
+HReg hregMIPS_D0(void)
+{
+   return mkHReg(0, HRcFlt64, False);
+}
+
+HReg hregMIPS_D1(void)
+{
+   return mkHReg(2, HRcFlt64, False);
+}
+
+HReg hregMIPS_D2(void)
+{
+   return mkHReg(4, HRcFlt64, False);
+}
+
+HReg hregMIPS_D3(void)
+{
+   return mkHReg(6, HRcFlt64, False);
+}
+
+HReg hregMIPS_D4(void)
+{
+   return mkHReg(8, HRcFlt64, False);
+}
+
+HReg hregMIPS_D5(void)
+{
+   return mkHReg(10, HRcFlt64, False);
+}
+
+HReg hregMIPS_D6(void)
+{
+   return mkHReg(12, HRcFlt64, False);
+}
+
+HReg hregMIPS_D7(void)
+{
+   return mkHReg(14, HRcFlt64, False);
+}
+
+HReg hregMIPS_D8(void)
+{
+   return mkHReg(16, HRcFlt64, False);
+}
+
+HReg hregMIPS_D9(void)
+{
+   return mkHReg(18, HRcFlt64, False);
+}
+
+HReg hregMIPS_D10(void)
+{
+   return mkHReg(20, HRcFlt64, False);
+}
+
+HReg hregMIPS_D11(void)
+{
+   return mkHReg(22, HRcFlt64, False);
+}
+
+HReg hregMIPS_D12(void)
+{
+   return mkHReg(24, HRcFlt64, False);
+}
+
+HReg hregMIPS_D13(void)
+{
+   return mkHReg(26, HRcFlt64, False);
+}
+
+HReg hregMIPS_D14(void)
+{
+   return mkHReg(28, HRcFlt64, False);
+}
+
+HReg hregMIPS_D15(void)
+{
+   return mkHReg(30, HRcFlt64, False);
+}
+
+HReg hregMIPS_FIR(void)
+{
+   return mkHReg(35, HRcInt32, False);
+}
+
+HReg hregMIPS_FCCR(void)
+{
+   return mkHReg(36, HRcInt32, False);
+}
+
+HReg hregMIPS_FEXR(void)
+{
+   return mkHReg(37, HRcInt32, False);
+}
+
+HReg hregMIPS_FENR(void)
+{
+   return mkHReg(38, HRcInt32, False);
+}
+
+HReg hregMIPS_FCSR(void)
+{
+   return mkHReg(39, HRcInt32, False);
+}
+
+HReg hregMIPS_COND(void)
+{
+   return mkHReg(47, HRcInt32, False);
+}
+
+void getAllocableRegs_MIPS(Int * nregs, HReg ** arr, Bool mode64)
+{
+   if (mode64)
+      *nregs = 27;
+   else
+      *nregs = 34;
+   UInt i = 0;
+   *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
+
+   //ZERO = constant 0
+   //AT = assembler temporary
+   // callee saves ones are listed first, since we prefer them
+   // if they're available
+   (*arr)[i++] = hregMIPS_GPR16(mode64);
+   (*arr)[i++] = hregMIPS_GPR17(mode64);
+   (*arr)[i++] = hregMIPS_GPR18(mode64);
+   (*arr)[i++] = hregMIPS_GPR19(mode64);
+   (*arr)[i++] = hregMIPS_GPR20(mode64);
+   (*arr)[i++] = hregMIPS_GPR21(mode64);
+   (*arr)[i++] = hregMIPS_GPR22(mode64);
+   if (!mode64)
+      (*arr)[i++] = hregMIPS_GPR23(mode64);
+
+   // otherwise we'll have to slum it out with caller-saves ones
+   if (mode64) {
+      (*arr)[i++] = hregMIPS_GPR8(mode64);
+      (*arr)[i++] = hregMIPS_GPR9(mode64);
+      (*arr)[i++] = hregMIPS_GPR10(mode64);
+      (*arr)[i++] = hregMIPS_GPR11(mode64);
+   }
+   (*arr)[i++] = hregMIPS_GPR12(mode64);
+   (*arr)[i++] = hregMIPS_GPR13(mode64);
+   (*arr)[i++] = hregMIPS_GPR14(mode64);
+   (*arr)[i++] = hregMIPS_GPR15(mode64);
+   (*arr)[i++] = hregMIPS_GPR24(mode64);
+    /***********mips32********************/
+   // t0  (=dispatch_ctr)
+   // t1  spill reg temp
+   // t2  (=guest_state)
+   // t3  (=PC = next guest address)
+   // K0 and K1 are reserved for OS kernel
+   // GP = global pointer
+   // SP = stack pointer
+   // FP = frame pointer
+   // RA = link register
+   // + PC, HI and LO
+   (*arr)[i++] = hregMIPS_F20(mode64);
+   (*arr)[i++] = hregMIPS_F21(mode64);
+   (*arr)[i++] = hregMIPS_F22(mode64);
+   (*arr)[i++] = hregMIPS_F23(mode64);
+   (*arr)[i++] = hregMIPS_F24(mode64);
+   (*arr)[i++] = hregMIPS_F25(mode64);
+   (*arr)[i++] = hregMIPS_F26(mode64);
+   (*arr)[i++] = hregMIPS_F27(mode64);
+   (*arr)[i++] = hregMIPS_F28(mode64);
+   (*arr)[i++] = hregMIPS_F29(mode64);
+   (*arr)[i++] = hregMIPS_F30(mode64);
+   if (!mode64) {
+      /* Fake double floating point */
+      (*arr)[i++] = hregMIPS_D0();
+      (*arr)[i++] = hregMIPS_D1();
+      (*arr)[i++] = hregMIPS_D2();
+      (*arr)[i++] = hregMIPS_D3();
+      (*arr)[i++] = hregMIPS_D4();
+      (*arr)[i++] = hregMIPS_D5();
+      (*arr)[i++] = hregMIPS_D6();
+      (*arr)[i++] = hregMIPS_D7();
+      (*arr)[i++] = hregMIPS_D8();
+      (*arr)[i++] = hregMIPS_D9();
+   }
+   vassert(i == *nregs);
+
+}
+
+/*----------------- Condition Codes ----------------------*/
+
+HChar *showMIPSCondCode(MIPSCondCode cond)
+{
+   HChar* ret;
+   switch (cond) {
+      case MIPScc_EQ:
+         ret = "EQ"; /* equal */
+         break;
+      case MIPScc_NE:
+         ret = "NEQ";   /* not equal */
+         break;
+      case MIPScc_HS:
+         ret = "GE";   /* >=u (Greater Than or Equal) */
+         break;
+      case MIPScc_LO:
+         ret = "LT";   /* <u  (lower) */
+         break;
+      case MIPScc_MI:
+         ret = "mi";   /* minus (negative) */
+         break;
+      case MIPScc_PL:
+         ret = "pl";   /* plus (zero or +ve) */
+         break;
+      case MIPScc_VS:
+         ret = "vs";   /* overflow */
+         break;
+      case MIPScc_VC:
+         ret = "vc";   /* no overflow */
+         break;
+      case MIPScc_HI:
+         ret = "hi";   /* >u   (higher) */
+         break;
+      case MIPScc_LS:
+         ret = "ls";   /* <=u  (lower or same) */
+         break;
+      case MIPScc_GE:
+         ret = "ge";   /* >=s (signed greater or equal) */
+         break;
+      case MIPScc_LT:
+         ret = "lt";   /* <s  (signed less than) */
+         break;
+      case MIPScc_GT:
+         ret = "gt";   /* >s  (signed greater) */
+         break;
+      case MIPScc_LE:
+         ret = "le";   /* <=s (signed less or equal) */
+         break;
+      case MIPScc_AL:
+         ret = "al";   /* always (unconditional) */
+         break;
+      case MIPScc_NV:
+         ret = "nv";   /* never (unconditional): */
+         break;
+      default:
+         vpanic("showMIPSCondCode");
+         break;
+   }
+   return ret;
+}
+
+HChar *showMIPSFpOp(MIPSFpOp op)
+{
+   HChar *ret;
+   switch (op) {
+      case Mfp_ADDD:
+         ret = "ADD.D";
+         break;
+      case Mfp_SUBD:
+         ret = "SUB.D";
+         break;
+      case Mfp_MULD:
+         ret = "MUL.D";
+         break;
+      case Mfp_DIVD:
+         ret = "DIV.D";
+         break;
+      case Mfp_MADDD:
+         ret = "MADD.D";
+         break;
+      case Mfp_MSUBD:
+         ret = "MSUB.D";
+         break;
+      case Mfp_MADDS:
+         ret = "MADD.S";
+         break;
+      case Mfp_MSUBS:
+         ret = "MSUB.S";
+         break;
+      case Mfp_ADDS:
+         ret = "ADD.S";
+         break;
+      case Mfp_SUBS:
+         ret = "SUB.S";
+         break;
+      case Mfp_MULS:
+         ret = "MUL.S";
+         break;
+      case Mfp_DIVS:
+         ret = "DIV.S";
+         break;
+      case Mfp_SQRTS:
+         ret = "SQRT.S";
+         break;
+      case Mfp_SQRTD:
+         ret = "SQRT.D";
+         break;
+      case Mfp_RSQRTS:
+         ret = "RSQRT.S";
+         break;
+      case Mfp_RSQRTD:
+         ret = "RSQRT.D";
+         break;
+      case Mfp_RECIPS:
+         ret = "RECIP.S";
+         break;
+      case Mfp_RECIPD:
+         ret = "RECIP.D";
+         break;
+      case Mfp_ABSS:
+         ret = "ABS.S";
+         break;
+      case Mfp_ABSD:
+         ret = "ABS.D";
+         break;
+      case Mfp_NEGS:
+         ret = "NEG.S";
+         break;
+      case Mfp_NEGD:
+         ret = "NEG.D";
+         break;
+      case Mfp_MOVS:
+         ret = "MOV.S";
+         break;
+      case Mfp_MOVD:
+         ret = "MOV.D";
+         break;
+      case Mfp_RES:
+         ret = "RES";
+         break;
+      case Mfp_ROUNDWS:
+         ret = "ROUND.W.S";
+         break;
+      case Mfp_ROUNDWD:
+         ret = "ROUND.W.D";
+         break;
+      case Mfp_FLOORWS:
+         ret = "FLOOR.W.S";
+         break;
+      case Mfp_FLOORWD:
+         ret = "FLOOR.W.D";
+         break;
+      case Mfp_RSQRTE:
+         ret = "frsqrte";
+         break;
+      case Mfp_CVTDW:
+      case Mfp_CVTD:
+         ret = "CVT.D";
+         break;
+      case Mfp_CVTSD:
+      case Mfp_CVTSW:
+         ret = "CVT.S";
+         break;
+      case Mfp_CVTWS:
+      case Mfp_CVTWD:
+         ret = "CVT.W";
+         break;
+      case Mfp_TRUWD:
+      case Mfp_TRUWS:
+         ret = "TRUNC.W";
+         break;
+      case Mfp_TRULD:
+      case Mfp_TRULS:
+         ret = "TRUNC.L";
+         break;
+      case Mfp_CEILWS:
+      case Mfp_CEILWD:
+         ret = "CEIL.W";
+         break;
+      case Mfp_CEILLS:
+      case Mfp_CEILLD:
+         ret = "CEIL.L";
+         break;
+      case Mfp_CMP:
+         ret = "C.cond.d";
+         break;
+      default:
+         vpanic("showMIPSFpOp");
+         break;
+   }
+   return ret;
+}
+
+/* --------- MIPSAMode: memory address expressions. --------- */
+
+MIPSAMode *MIPSAMode_IR(Int idx, HReg base)
+{
+   MIPSAMode *am = LibVEX_Alloc(sizeof(MIPSAMode));
+   am->tag = Mam_IR;
+   am->Mam.IR.base = base;
+   am->Mam.IR.index = idx;
+
+   return am;
+}
+
+MIPSAMode *MIPSAMode_RR(HReg idx, HReg base)
+{
+   MIPSAMode *am = LibVEX_Alloc(sizeof(MIPSAMode));
+   am->tag = Mam_RR;
+   am->Mam.RR.base = base;
+   am->Mam.RR.index = idx;
+
+   return am;
+}
+
+MIPSAMode *dopyMIPSAMode(MIPSAMode * am)
+{
+   MIPSAMode* ret;
+   switch (am->tag) {
+      case Mam_IR:
+         ret = MIPSAMode_IR(am->Mam.IR.index, am->Mam.IR.base);
+         break;
+      case Mam_RR:
+         ret = MIPSAMode_RR(am->Mam.RR.index, am->Mam.RR.base);
+         break;
+      default:
+         vpanic("dopyMIPSAMode");
+         break;
+   }
+   return ret;
+}
+
+MIPSAMode *nextMIPSAModeFloat(MIPSAMode * am)
+{
+   MIPSAMode* ret;
+   switch (am->tag) {
+      case Mam_IR:
+         ret = MIPSAMode_IR(am->Mam.IR.index + 8, am->Mam.IR.base);
+         break;
+      case Mam_RR:
+         ret = MIPSAMode_RR(am->Mam.RR.index + 1, am->Mam.RR.base);
+         break;
+      default:
+         vpanic("dopyMIPSAMode");
+         break;
+   }
+   return ret;
+}
+
+MIPSAMode *nextMIPSAModeInt(MIPSAMode * am)
+{
+   MIPSAMode* ret;
+   switch (am->tag) {
+      case Mam_IR:
+         ret = MIPSAMode_IR(am->Mam.IR.index + 4, am->Mam.IR.base);
+         break;
+      case Mam_RR:
+         ret = MIPSAMode_RR(am->Mam.RR.index + 1, am->Mam.RR.base);
+         break;
+      default:
+         vpanic("dopyMIPSAMode");
+         break;
+   }
+   return ret;
+}
+
+void ppMIPSAMode(MIPSAMode * am, Bool mode64)
+{
+   switch (am->tag) {
+      case Mam_IR:
+         if (am->Mam.IR.index == 0)
+            vex_printf("0(");
+         else
+            vex_printf("%d(", (Int) am->Mam.IR.index);
+         ppHRegMIPS(am->Mam.IR.base, mode64);
+         vex_printf(")");
+         return;
+      case Mam_RR:
+         ppHRegMIPS(am->Mam.RR.base, mode64);
+         vex_printf(", ");
+         ppHRegMIPS(am->Mam.RR.index, mode64);
+         return;
+      default:
+         vpanic("ppMIPSAMode");
+         break;
+   }
+}
+
+static void addRegUsage_MIPSAMode(HRegUsage * u, MIPSAMode * am)
+{
+   switch (am->tag) {
+      case Mam_IR:
+         addHRegUse(u, HRmRead, am->Mam.IR.base);
+         return;
+      case Mam_RR:
+         addHRegUse(u, HRmRead, am->Mam.RR.base);
+         addHRegUse(u, HRmRead, am->Mam.RR.index);
+         return;
+      default:
+         vpanic("addRegUsage_MIPSAMode");
+         break;
+   }
+}
+
+static void mapRegs_MIPSAMode(HRegRemap * m, MIPSAMode * am)
+{
+   switch (am->tag) {
+      case Mam_IR:
+         am->Mam.IR.base = lookupHRegRemap(m, am->Mam.IR.base);
+         return;
+      case Mam_RR:
+         am->Mam.RR.base = lookupHRegRemap(m, am->Mam.RR.base);
+         am->Mam.RR.index = lookupHRegRemap(m, am->Mam.RR.index);
+         return;
+      default:
+         vpanic("mapRegs_MIPSAMode");
+         break;
+   }
+}
+
+/* --------- Operand, which can be a reg or a u16/s16. --------- */
+
+MIPSRH *MIPSRH_Imm(Bool syned, UShort imm16)
+{
+   MIPSRH *op = LibVEX_Alloc(sizeof(MIPSRH));
+   op->tag = Mrh_Imm;
+   op->Mrh.Imm.syned = syned;
+   op->Mrh.Imm.imm16 = imm16;
+   /* If this is a signed value, ensure it's not -32768, so that we
+      are guaranteed always to be able to negate if needed. */
+   if (syned)
+      vassert(imm16 != 0x8000);
+   vassert(syned == True || syned == False);
+   return op;
+}
+
+MIPSRH *MIPSRH_Reg(HReg reg)
+{
+   MIPSRH *op = LibVEX_Alloc(sizeof(MIPSRH));
+   op->tag = Mrh_Reg;
+   op->Mrh.Reg.reg = reg;
+   return op;
+}
+
+void ppMIPSRH(MIPSRH * op, Bool mode64)
+{
+   MIPSRHTag tag = op->tag;
+   switch (tag) {
+      case Mrh_Imm:
+         if (op->Mrh.Imm.syned)
+            vex_printf("%d", (Int) (Short) op->Mrh.Imm.imm16);
+         else
+            vex_printf("%u", (UInt) (UShort) op->Mrh.Imm.imm16);
+         return;
+      case Mrh_Reg:
+         ppHRegMIPS(op->Mrh.Reg.reg, mode64);
+         return;
+      default:
+         vpanic("ppMIPSRH");
+         break;
+   }
+}
+
+/* An MIPSRH can only be used in a "read" context (what would it mean
+   to write or modify a literal?) and so we enumerate its registers
+   accordingly. */
+static void addRegUsage_MIPSRH(HRegUsage * u, MIPSRH * op)
+{
+   switch (op->tag) {
+      case Mrh_Imm:
+         return;
+      case Mrh_Reg:
+         addHRegUse(u, HRmRead, op->Mrh.Reg.reg);
+         return;
+      default:
+         vpanic("addRegUsage_MIPSRH");
+         break;
+   }
+}
+
+static void mapRegs_MIPSRH(HRegRemap * m, MIPSRH * op)
+{
+   switch (op->tag) {
+      case Mrh_Imm:
+         return;
+      case Mrh_Reg:
+         op->Mrh.Reg.reg = lookupHRegRemap(m, op->Mrh.Reg.reg);
+         return;
+      default:
+         vpanic("mapRegs_MIPSRH");
+         break;
+   }
+}
+
+/* --------- Instructions. --------- */
+
+HChar *showMIPSUnaryOp(MIPSUnaryOp op)
+{
+   HChar* ret;
+   switch (op) {
+      case Mun_CLO:
+         ret = "clo";
+         break;
+      case Mun_CLZ:
+         ret = "clz";
+         break;
+      case Mun_NOP:
+         ret = "nop";
+         break;
+      default:
+         vpanic("showMIPSUnaryOp");
+         break;
+   }
+   return ret;
+}
+
+HChar *showMIPSAluOp(MIPSAluOp op, Bool immR)
+{
+   HChar* ret;
+   switch (op) {
+      case Malu_ADD:
+         ret = immR ? "addiu" : "addu";
+         break;
+      case Malu_SUB:
+         ret = "subu";
+         break;
+      case Malu_AND:
+         ret = immR ? "andi" : "and";
+         break;
+      case Malu_OR:
+         ret = immR ? "ori" : "or";
+         break;
+      case Malu_NOR:
+         vassert(immR == False); /*there's no nor with an immediate operand!? */
+         ret = "nor";
+         break;
+      case Malu_XOR:
+         ret = immR ? "xori" : "xor";
+         break;
+      default:
+         vpanic("showMIPSAluOp");
+         break;
+   }
+   return ret;
+}
+
+HChar *showMIPSShftOp(MIPSShftOp op, Bool immR, Bool sz32)
+{
+   HChar *ret;
+   switch (op) {
+      case Mshft_SRA:
+         ret = immR ? (sz32 ? "sar" : "dsar") : (sz32 ? "sarv" : "dsrav");
+         break;
+      case Mshft_SLL:
+         ret = immR ? (sz32 ? "sll" : "dsll") : (sz32 ? "sllv" : "dsllv");
+         break;
+      case Mshft_SRL:
+         ret = immR ? (sz32 ? "srl" : "dsrl") : (sz32 ? "srlv" : "dsrlv");
+         break;
+      default:
+         vpanic("showMIPSShftOp");
+         break;
+   }
+   return ret;
+}
+
+HChar *showMIPSMaccOp(MIPSMaccOp op, Bool variable)
+{
+   HChar *ret;
+   switch (op) {
+      case Macc_ADD:
+         ret = variable ? "madd" : "maddu";
+         break;
+      case Macc_SUB:
+         ret = variable ? "msub" : "msubu";
+         break;
+      default:
+         vpanic("showMIPSAccOp");
+         break;
+   }
+   return ret;
+}
+
+MIPSInstr *MIPSInstr_LI(HReg dst, ULong imm)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_LI;
+   i->Min.LI.dst = dst;
+   i->Min.LI.imm = imm;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_Alu(MIPSAluOp op, HReg dst, HReg srcL, MIPSRH * srcR)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Alu;
+   i->Min.Alu.op = op;
+   i->Min.Alu.dst = dst;
+   i->Min.Alu.srcL = srcL;
+   i->Min.Alu.srcR = srcR;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_Shft(MIPSShftOp op, Bool sz32, HReg dst, HReg srcL,
+                          MIPSRH * srcR)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Shft;
+   i->Min.Shft.op = op;
+   i->Min.Shft.sz32 = sz32;
+   i->Min.Shft.dst = dst;
+   i->Min.Shft.srcL = srcL;
+   i->Min.Shft.srcR = srcR;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_Unary(MIPSUnaryOp op, HReg dst, HReg src)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Unary;
+   i->Min.Unary.op = op;
+   i->Min.Unary.dst = dst;
+   i->Min.Unary.src = src;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_Cmp(Bool syned, Bool sz32, HReg dst, HReg srcL, HReg srcR,
+                         MIPSCondCode cond)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Cmp;
+   i->Min.Cmp.syned = syned;
+   i->Min.Cmp.sz32 = sz32;
+   i->Min.Cmp.dst = dst;
+   i->Min.Cmp.srcL = srcL;
+   i->Min.Cmp.srcR = srcR;
+   i->Min.Cmp.cond = cond;
+   return i;
+}
+
+/* multiply */
+MIPSInstr *MIPSInstr_Mul(Bool syned, Bool wid, Bool sz32, HReg dst, HReg srcL,
+                         HReg srcR)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Mul;
+   i->Min.Mul.syned = syned;
+   i->Min.Mul.widening = wid; /* widen=True else False */
+   i->Min.Mul.sz32 = sz32; /* True = 32 bits */
+   i->Min.Mul.dst = dst;
+   i->Min.Mul.srcL = srcL;
+   i->Min.Mul.srcR = srcR;
+   return i;
+}
+
+/* msub */
+MIPSInstr *MIPSInstr_Msub(Bool syned, HReg srcL, HReg srcR)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Macc;
+
+   i->Min.Macc.op = Macc_SUB;
+   i->Min.Macc.syned = syned;
+   i->Min.Macc.srcL = srcL;
+   i->Min.Macc.srcR = srcR;
+   return i;
+}
+
+/* madd */
+MIPSInstr *MIPSInstr_Madd(Bool syned, HReg srcL, HReg srcR)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Macc;
+
+   i->Min.Macc.op = Macc_ADD;
+   i->Min.Macc.syned = syned;
+   i->Min.Macc.srcL = srcL;
+   i->Min.Macc.srcR = srcR;
+   return i;
+}
+
+/* div */
+MIPSInstr *MIPSInstr_Div(Bool syned, Bool sz32, HReg srcL, HReg srcR)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Div;
+   i->Min.Div.syned = syned;
+   i->Min.Div.sz32 = sz32; /* True = 32 bits */
+   i->Min.Div.srcL = srcL;
+   i->Min.Div.srcR = srcR;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_Call(MIPSCondCode cond, Addr32 target, UInt argiregs,
+                          HReg src)
+{
+   UInt mask;
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Call;
+   i->Min.Call.cond = cond;
+   i->Min.Call.target = target;
+   i->Min.Call.argiregs = argiregs;
+   i->Min.Call.src = src;
+   /* Only r4 .. r7 inclusive may be used as arg regs. Hence: */
+   mask = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7);
+   vassert(0 == (argiregs & ~mask));
+   return i;
+}
+
+MIPSInstr *MIPSInstr_CallAlways(MIPSCondCode cond, Addr32 target, UInt argiregs)
+{
+   UInt mask;
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Call;
+   i->Min.Call.cond = cond;
+   i->Min.Call.target = target;
+   i->Min.Call.argiregs = argiregs;
+   /* Only r4 .. r7 inclusive may be used as arg regs. Hence: */
+   mask = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7);
+   vassert(0 == (argiregs & ~mask));
+   return i;
+}
+
+MIPSInstr *MIPSInstr_XDirect ( Addr32 dstGA, MIPSAMode* amPC,
+                               MIPSCondCode cond, Bool toFastEP ) {
+   MIPSInstr* i               = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag                     = Min_XDirect;
+   i->Min.XDirect.dstGA       = dstGA;
+   i->Min.XDirect.amPC        = amPC;
+   i->Min.XDirect.cond        = cond;
+   i->Min.XDirect.toFastEP    = toFastEP;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_XIndir ( HReg dstGA, MIPSAMode* amPC,
+                              MIPSCondCode cond ) {
+   MIPSInstr* i            = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag                  = Min_XIndir;
+   i->Min.XIndir.dstGA     = dstGA;
+   i->Min.XIndir.amPC      = amPC;
+   i->Min.XIndir.cond      = cond;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_XAssisted ( HReg dstGA, MIPSAMode* amPC,
+                                 MIPSCondCode cond, IRJumpKind jk ) {
+   MIPSInstr* i               = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag                     = Min_XAssisted;
+   i->Min.XAssisted.dstGA     = dstGA;
+   i->Min.XAssisted.amPC      = amPC;
+   i->Min.XAssisted.cond      = cond;
+   i->Min.XAssisted.jk        = jk;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_Load(UChar sz, HReg dst, MIPSAMode * src, Bool mode64)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Load;
+   i->Min.Load.sz = sz;
+   i->Min.Load.src = src;
+   i->Min.Load.dst = dst;
+   vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
+
+   if (sz == 8)
+      vassert(mode64);
+   return i;
+}
+
+MIPSInstr *MIPSInstr_Store(UChar sz, MIPSAMode * dst, HReg src, Bool mode64)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Store;
+   i->Min.Store.sz = sz;
+   i->Min.Store.src = src;
+   i->Min.Store.dst = dst;
+   vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
+
+   if (sz == 8)
+      vassert(mode64);
+   return i;
+}
+
+MIPSInstr *MIPSInstr_LoadL(UChar sz, HReg dst, MIPSAMode * src, Bool mode64)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_LoadL;
+   i->Min.LoadL.sz  = sz;
+   i->Min.LoadL.src = src;
+   i->Min.LoadL.dst = dst;
+   vassert(sz == 4 || sz == 8);
+
+   if (sz == 8)
+      vassert(mode64);
+   return i;
+}
+
+MIPSInstr *MIPSInstr_StoreC(UChar sz, MIPSAMode * dst, HReg src, Bool mode64)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_StoreC;
+   i->Min.StoreC.sz  = sz;
+   i->Min.StoreC.src = src;
+   i->Min.StoreC.dst = dst;
+   vassert(sz == 4 || sz == 8);
+
+   if (sz == 8)
+      vassert(mode64);
+   return i;
+}
+
+MIPSInstr *MIPSInstr_Mthi(HReg src)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Mthi;
+   i->Min.MtHL.src = src;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_Mtlo(HReg src)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Mtlo;
+   i->Min.MtHL.src = src;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_Mfhi(HReg dst)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Mfhi;
+   i->Min.MfHL.dst = dst;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_Mflo(HReg dst)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_Mflo;
+   i->Min.MfHL.dst = dst;
+   return i;
+}
+
+/* Read/Write Link Register */
+MIPSInstr *MIPSInstr_RdWrLR(Bool wrLR, HReg gpr)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_RdWrLR;
+   i->Min.RdWrLR.wrLR = wrLR;
+   i->Min.RdWrLR.gpr = gpr;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_FpLdSt(Bool isLoad, UChar sz, HReg reg, MIPSAMode * addr)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_FpLdSt;
+   i->Min.FpLdSt.isLoad = isLoad;
+   i->Min.FpLdSt.sz = sz;
+   i->Min.FpLdSt.reg = reg;
+   i->Min.FpLdSt.addr = addr;
+   vassert(sz == 4 || sz == 8);
+   return i;
+}
+
+MIPSInstr *MIPSInstr_FpUnary(MIPSFpOp op, HReg dst, HReg src)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_FpUnary;
+   i->Min.FpUnary.op = op;
+   i->Min.FpUnary.dst = dst;
+   i->Min.FpUnary.src = src;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_FpBinary(MIPSFpOp op, HReg dst, HReg srcL, HReg srcR)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_FpBinary;
+   i->Min.FpBinary.op = op;
+   i->Min.FpBinary.dst = dst;
+   i->Min.FpBinary.srcL = srcL;
+   i->Min.FpBinary.srcR = srcR;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_FpConvert(MIPSFpOp op, HReg dst, HReg src)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_FpConvert;
+   i->Min.FpConvert.op = op;
+   i->Min.FpConvert.dst = dst;
+   i->Min.FpConvert.src = src;
+   return i;
+
+}
+
+MIPSInstr *MIPSInstr_FpCompare(MIPSFpOp op, HReg dst, HReg srcL, HReg srcR,
+                               UChar cond1)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_FpCompare;
+   i->Min.FpCompare.op = op;
+   i->Min.FpCompare.dst = dst;
+   i->Min.FpCompare.srcL = srcL;
+   i->Min.FpCompare.srcR = srcR;
+   i->Min.FpCompare.cond1 = cond1;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_MovCond(HReg dst, HReg argL, MIPSRH * argR, HReg condR,
+                              MIPSCondCode cond)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_MovCond;
+   i->Min.MovCond.dst = dst;
+   i->Min.MovCond.srcL = argL;
+   i->Min.MovCond.srcR = argR;
+   i->Min.MovCond.condR = condR;
+   i->Min.MovCond.cond = cond;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_MtFCSR(HReg src)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_MtFCSR;
+   i->Min.MtFCSR.src = src;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_MfFCSR(HReg dst)
+{
+   MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag = Min_MfFCSR;
+   i->Min.MfFCSR.dst = dst;
+   return i;
+}
+
+MIPSInstr *MIPSInstr_EvCheck ( MIPSAMode* amCounter,
+                            MIPSAMode* amFailAddr ) {
+   MIPSInstr* i                 = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag                       = Min_EvCheck;
+   i->Min.EvCheck.amCounter     = amCounter;
+   i->Min.EvCheck.amFailAddr    = amFailAddr;
+   return i;
+}
+
+MIPSInstr* MIPSInstr_ProfInc ( void ) {
+   MIPSInstr* i = LibVEX_Alloc(sizeof(MIPSInstr));
+   i->tag       = Min_ProfInc;
+   return i;
+}
+
+/* -------- Pretty Print instructions ------------- */
+static void ppLoadImm(HReg dst, ULong imm, Bool mode64)
+{
+   vex_printf("li ");
+   ppHRegMIPS(dst, mode64);
+   vex_printf(",0x%016llx", imm);
+}
+
+void ppMIPSInstr(MIPSInstr * i, Bool mode64)
+{
+   switch (i->tag) {
+      case Min_LI:
+         ppLoadImm(i->Min.LI.dst, i->Min.LI.imm, mode64);
+         break;
+      case Min_Alu: {
+         HReg r_srcL = i->Min.Alu.srcL;
+         MIPSRH *rh_srcR = i->Min.Alu.srcR;
+         /* generic */
+         vex_printf("%s ", showMIPSAluOp(i->Min.Alu.op,
+                                         toBool(rh_srcR->tag == Mrh_Imm)));
+         ppHRegMIPS(i->Min.Alu.dst, mode64);
+         vex_printf(",");
+         ppHRegMIPS(r_srcL, mode64);
+         vex_printf(",");
+         ppMIPSRH(rh_srcR, mode64);
+         return;
+      }
+      case Min_Shft: {
+         HReg r_srcL = i->Min.Shft.srcL;
+         MIPSRH *rh_srcR = i->Min.Shft.srcR;
+         vex_printf("%s ", showMIPSShftOp(i->Min.Shft.op,
+                                          toBool(rh_srcR->tag == Mrh_Imm),
+                                          i->Min.Shft.sz32));
+         ppHRegMIPS(i->Min.Shft.dst, mode64);
+         vex_printf(",");
+         ppHRegMIPS(r_srcL, mode64);
+         vex_printf(",");
+         ppMIPSRH(rh_srcR, mode64);
+         return;
+      }
+      case Min_Unary: {
+         vex_printf("%s ", showMIPSUnaryOp(i->Min.Unary.op));
+         ppHRegMIPS(i->Min.Unary.dst, mode64);
+         vex_printf(",");
+         ppHRegMIPS(i->Min.Unary.src, mode64);
+         return;
+      }
+      case Min_Cmp: {
+         vex_printf("word_compare ");
+         ppHRegMIPS(i->Min.Cmp.dst, mode64);
+         vex_printf(" = %s ( ", showMIPSCondCode(i->Min.Cmp.cond));
+         ppHRegMIPS(i->Min.Cmp.srcL, mode64);
+         vex_printf(", ");
+         ppHRegMIPS(i->Min.Cmp.srcR, mode64);
+         vex_printf(" )");
+
+         return;
+      }
+      case Min_Mul: {
+         switch (i->Min.Mul.widening) {
+            case False:
+               vex_printf("mul ");
+               ppHRegMIPS(i->Min.Mul.dst, mode64);
+               vex_printf(", ");
+               ppHRegMIPS(i->Min.Mul.srcL, mode64);
+               vex_printf(", ");
+               ppHRegMIPS(i->Min.Mul.srcR, mode64);
+               return;
+            case True:
+               vex_printf("%s%s ", i->Min.Mul.sz32 ? "mult" : "dmult",
+                                   i->Min.Mul.syned ? "" : "u");
+               ppHRegMIPS(i->Min.Mul.dst, mode64);
+               vex_printf(", ");
+               ppHRegMIPS(i->Min.Mul.srcL, mode64);
+               vex_printf(", ");
+               ppHRegMIPS(i->Min.Mul.srcR, mode64);
+               return;
+            }
+         break;
+      }
+      case Min_Mthi: {
+         vex_printf("mthi ");
+         ppHRegMIPS(i->Min.MtHL.src, mode64);
+         return;
+      }
+      case Min_Mtlo: {
+         vex_printf("mtlo ");
+         ppHRegMIPS(i->Min.MtHL.src, mode64);
+         return;
+      }
+      case Min_Mfhi: {
+         vex_printf("mfhi ");
+         ppHRegMIPS(i->Min.MfHL.dst, mode64);
+         return;
+      }
+      case Min_Mflo: {
+         vex_printf("mflo ");
+         ppHRegMIPS(i->Min.MfHL.dst, mode64);
+         return;
+      }
+      case Min_Macc: {
+         vex_printf("%s ", showMIPSMaccOp(i->Min.Macc.op, i->Min.Macc.syned));
+         ppHRegMIPS(i->Min.Macc.srcL, mode64);
+         vex_printf(", ");
+         ppHRegMIPS(i->Min.Macc.srcR, mode64);
+         return;
+      }
+      case Min_Div: {
+         if (!i->Min.Div.sz32)
+            vex_printf("d");
+         vex_printf("div");
+         vex_printf("%s ", i->Min.Div.syned ? "s" : "u");
+         ppHRegMIPS(i->Min.Div.srcL, mode64);
+         vex_printf(", ");
+         ppHRegMIPS(i->Min.Div.srcR, mode64);
+         return;
+      }
+      case Min_Call: {
+         Int n;
+         vex_printf("call: ");
+         if (i->Min.Call.cond != MIPScc_AL) {
+            vex_printf("if (%s) ", showMIPSCondCode(i->Min.Call.cond));
+         }
+         vex_printf("{ ");
+         ppLoadImm(hregMIPS_GPR11(mode64), i->Min.Call.target, mode64);
+
+         vex_printf(" ; mtctr r10 ; bctrl [");
+         for (n = 0; n < 32; n++) {
+            if (i->Min.Call.argiregs & (1 << n)) {
+               vex_printf("r%d", n);
+               if ((i->Min.Call.argiregs >> n) > 1)
+                  vex_printf(",");
+            }
+         }
+         vex_printf("] }");
+         break;
+      }
+      case Min_XDirect:
+         vex_printf("(xDirect) ");
+         vex_printf("if (guest_COND.%s) { ",
+                    showMIPSCondCode(i->Min.XDirect.cond));
+         vex_printf("move $9, 0x%x,", i->Min.XDirect.dstGA);
+         vex_printf("; sw $9, ");
+         ppMIPSAMode(i->Min.XDirect.amPC, mode64);
+         vex_printf("; move $9, $disp_cp_chain_me_to_%sEP; jalr $9; nop}",
+                    i->Min.XDirect.toFastEP ? "fast" : "slow");
+         return;
+      case Min_XIndir:
+         vex_printf("(xIndir) ");
+         vex_printf("if (guest_COND.%s) { sw ",
+        	        showMIPSCondCode(i->Min.XIndir.cond));
+         ppHRegMIPS(i->Min.XIndir.dstGA, mode64);
+         vex_printf(", ");
+         ppMIPSAMode(i->Min.XIndir.amPC, mode64);
+         vex_printf("; move $9, $disp_indir; jalr $9; nop}");
+         return;
+      case Min_XAssisted:
+         vex_printf("(xAssisted) ");
+         vex_printf("if (guest_COND.%s) { ",
+                    showMIPSCondCode(i->Min.XAssisted.cond));
+         vex_printf("sw ");
+         ppHRegMIPS(i->Min.XAssisted.dstGA, mode64);
+         vex_printf(", ");
+         ppMIPSAMode(i->Min.XAssisted.amPC, mode64);
+         vex_printf("; move $9, $IRJumpKind_to_TRCVAL(%d)",
+                    (Int)i->Min.XAssisted.jk);
+         vex_printf("; move $9, $disp_assisted; jalr $9; nop; }");
+         return;
+      case Min_Load: {
+         Bool idxd = toBool(i->Min.Load.src->tag == Mam_RR);
+         UChar sz = i->Min.Load.sz;
+         UChar c_sz = sz == 1 ? 'b' : sz == 2 ? 'h' : sz == 4 ? 'w' : 'd';
+         vex_printf("l%c%s ", c_sz, idxd ? "x" : "");
+         ppHRegMIPS(i->Min.Load.dst, mode64);
+         vex_printf(",");
+         ppMIPSAMode(i->Min.Load.src, mode64);
+         return;
+      }
+      case Min_Store: {
+         UChar sz = i->Min.Store.sz;
+         Bool idxd = toBool(i->Min.Store.dst->tag == Mam_RR);
+         UChar c_sz = sz == 1 ? 'b' : sz == 2 ? 'h' : sz == 4 ? 'w' : 'd';
+         vex_printf("s%c%s ", c_sz, idxd ? "x" : "");
+         ppHRegMIPS(i->Min.Store.src, mode64);
+         vex_printf(",");
+         ppMIPSAMode(i->Min.Store.dst, mode64);
+         return;
+      }
+      case Min_LoadL: {
+         vex_printf("ll ");
+         ppHRegMIPS(i->Min.LoadL.dst, mode64);
+         vex_printf(",");
+         ppMIPSAMode(i->Min.LoadL.src, mode64);
+         return;
+      }
+      case Min_StoreC: {
+         vex_printf("sc ");
+         ppHRegMIPS(i->Min.StoreC.src, mode64);
+         vex_printf(",");
+         ppMIPSAMode(i->Min.StoreC.dst, mode64);
+         return;
+      }
+      case Min_RdWrLR: {
+         vex_printf("%s ", i->Min.RdWrLR.wrLR ? "mtlr" : "mflr");
+         ppHRegMIPS(i->Min.RdWrLR.gpr, mode64);
+         return;
+      }
+      case Min_FpUnary:
+         vex_printf("%s ", showMIPSFpOp(i->Min.FpUnary.op));
+         ppHRegMIPS(i->Min.FpUnary.dst, mode64);
+         vex_printf(",");
+         ppHRegMIPS(i->Min.FpUnary.src, mode64);
+         return;
+      case Min_FpBinary:
+         vex_printf("%s", showMIPSFpOp(i->Min.FpBinary.op));
+         ppHRegMIPS(i->Min.FpBinary.dst, mode64);
+         vex_printf(",");
+         ppHRegMIPS(i->Min.FpBinary.srcL, mode64);
+         vex_printf(",");
+         ppHRegMIPS(i->Min.FpBinary.srcR, mode64);
+         return;
+      case Min_FpConvert:
+         vex_printf("%s", showMIPSFpOp(i->Min.FpConvert.op));
+         ppHRegMIPS(i->Min.FpConvert.dst, mode64);
+         vex_printf(",");
+         ppHRegMIPS(i->Min.FpConvert.src, mode64);
+         return;
+      case Min_FpCompare:
+         vex_printf("%s ", showMIPSFpOp(i->Min.FpCompare.op));
+         ppHRegMIPS(i->Min.FpCompare.srcL, mode64);
+         vex_printf(",");
+         ppHRegMIPS(i->Min.FpCompare.srcR, mode64);
+         vex_printf(" cond: %c", i->Min.FpCompare.cond1);
+         return;
+      case Min_FpMulAcc:
+         vex_printf("%s ", showMIPSFpOp(i->Min.FpMulAcc.op));
+         ppHRegMIPS(i->Min.FpMulAcc.dst, mode64);
+         vex_printf(",");
+         ppHRegMIPS(i->Min.FpMulAcc.srcML, mode64);
+         vex_printf(",");
+         ppHRegMIPS(i->Min.FpMulAcc.srcMR, mode64);
+         vex_printf(",");
+         ppHRegMIPS(i->Min.FpMulAcc.srcAcc, mode64);
+         return;
+      case Min_FpLdSt: {
+         if (i->Min.FpLdSt.sz == 4) {
+            if (i->Min.FpLdSt.isLoad) {
+               vex_printf("lwc1 ");
+               ppHRegMIPS(i->Min.FpLdSt.reg, mode64);
+               vex_printf(",");
+               ppMIPSAMode(i->Min.FpLdSt.addr, mode64);
+            } else {
+               vex_printf("swc1 ");
+               ppHRegMIPS(i->Min.FpLdSt.reg, mode64);
+               vex_printf(",");
+               ppMIPSAMode(i->Min.FpLdSt.addr, mode64);
+            }
+         } else if (i->Min.FpLdSt.sz == 8) {
+            if (i->Min.FpLdSt.isLoad) {
+               if (mode64)
+                  vex_printf("ldc1 ");
+               else
+                  vex_printf("lwc1 ");
+               ppHRegMIPS(i->Min.FpLdSt.reg, mode64);
+               vex_printf(",");
+               ppMIPSAMode(i->Min.FpLdSt.addr, mode64);
+            } else {
+               if (mode64)
+                  vex_printf("sdc1 ");
+               else
+                  vex_printf("swc1 ");
+               ppHRegMIPS(i->Min.FpLdSt.reg, mode64);
+               vex_printf(",");
+               ppMIPSAMode(i->Min.FpLdSt.addr, mode64);
+            }
+         }
+         return;
+      }
+      case Min_MovCond: {
+         if (i->Min.MovCond.cond == MIPScc_MI) {
+            vex_printf("\ncond move\n");
+            return;
+
+         }
+         break;
+      }
+      case Min_MtFCSR: {
+         vex_printf("ctc1  ");
+         ppHRegMIPS(i->Min.MtFCSR.src, mode64);
+         vex_printf(", $31");
+         return;
+      }
+   
+      case Min_MfFCSR: {
+         vex_printf("ctc1  ");
+         ppHRegMIPS(i->Min.MfFCSR.dst, mode64);
+         vex_printf(", $31");
+         return;
+      }
+      case Min_EvCheck:
+         vex_printf("(evCheck) lw $9, ");
+         ppMIPSAMode(i->Min.EvCheck.amCounter, mode64);
+         vex_printf("; addiu $9, $9, -1");
+         vex_printf("; sw $9, ");
+         ppMIPSAMode(i->Min.EvCheck.amCounter, mode64);
+         vex_printf("; bgez $t9, nofail; jalr *");
+         ppMIPSAMode(i->Min.EvCheck.amFailAddr, mode64);
+         vex_printf("; nofail:");
+         return;
+      case Min_ProfInc:
+         vex_printf("(profInc) move $9, ($NotKnownYet); "
+                    "lw $8, 0($9); "
+                    "addiu $8, $8, 1; "
+                    "sw $8, 0($9); "
+                    "sltiu $1, $8, 1; "
+                    "lw $8, 4($9); "
+                    "addu $8, $8, $1; "
+                    "sw $8, 4($9); " );
+         return;
+      default:
+         vpanic("ppMIPSInstr");
+         break;
+   }
+}
+
+/* --------- Helpers for register allocation. --------- */
+
+void getRegUsage_MIPSInstr(HRegUsage * u, MIPSInstr * i, Bool mode64)
+{
+   initHRegUsage(u);
+   switch (i->tag) {
+      case Min_LI:
+         addHRegUse(u, HRmWrite, i->Min.LI.dst);
+         break;
+      case Min_Alu:
+         addHRegUse(u, HRmRead, i->Min.Alu.srcL);
+         addRegUsage_MIPSRH(u, i->Min.Alu.srcR);
+         addHRegUse(u, HRmWrite, i->Min.Alu.dst);
+         return;
+      case Min_Shft:
+         addHRegUse(u, HRmRead, i->Min.Shft.srcL);
+         addRegUsage_MIPSRH(u, i->Min.Shft.srcR);
+         addHRegUse(u, HRmWrite, i->Min.Shft.dst);
+         return;
+      case Min_Cmp:
+         addHRegUse(u, HRmRead, i->Min.Cmp.srcL);
+         addHRegUse(u, HRmRead, i->Min.Cmp.srcR);
+         addHRegUse(u, HRmWrite, i->Min.Cmp.dst);
+         return;
+      case Min_Unary:
+         addHRegUse(u, HRmRead, i->Min.Unary.src);
+         addHRegUse(u, HRmWrite, i->Min.Unary.dst);
+         return;
+      case Min_Mul:
+         addHRegUse(u, HRmWrite, i->Min.Mul.dst);
+         addHRegUse(u, HRmRead, i->Min.Mul.srcL);
+         addHRegUse(u, HRmRead, i->Min.Mul.srcR);
+         return;
+      case Min_Mthi:
+      case Min_Mtlo:
+         addHRegUse(u, HRmWrite, hregMIPS_HI(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_LO(mode64));
+         addHRegUse(u, HRmRead, i->Min.MtHL.src);
+         return;
+      case Min_Mfhi:
+      case Min_Mflo:
+         addHRegUse(u, HRmRead, hregMIPS_HI(mode64));
+         addHRegUse(u, HRmRead, hregMIPS_LO(mode64));
+         addHRegUse(u, HRmWrite, i->Min.MfHL.dst);
+         return;
+      case Min_MtFCSR:
+         addHRegUse(u, HRmRead, i->Min.MtFCSR.src);
+         return;
+      case Min_MfFCSR:
+         addHRegUse(u, HRmWrite, i->Min.MfFCSR.dst);
+         return;
+      case Min_Macc:
+         addHRegUse(u, HRmModify, hregMIPS_HI(mode64));
+         addHRegUse(u, HRmModify, hregMIPS_LO(mode64));
+         addHRegUse(u, HRmRead, i->Min.Macc.srcL);
+         addHRegUse(u, HRmRead, i->Min.Macc.srcR);
+         return;
+      case Min_Div:
+         addHRegUse(u, HRmWrite, hregMIPS_HI(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_LO(mode64));
+         addHRegUse(u, HRmRead, i->Min.Div.srcL);
+         addHRegUse(u, HRmRead, i->Min.Div.srcR);
+         return;
+      case Min_Call: {
+         if (i->Min.Call.cond != MIPScc_AL)
+            addHRegUse(u, HRmRead, i->Min.Call.src);
+         UInt argir;
+         addHRegUse(u, HRmWrite, hregMIPS_GPR1(mode64));
+
+         addHRegUse(u, HRmWrite, hregMIPS_GPR2(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR3(mode64));
+
+         addHRegUse(u, HRmWrite, hregMIPS_GPR4(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR5(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR6(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR7(mode64));
+
+         addHRegUse(u, HRmWrite, hregMIPS_GPR8(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR9(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR10(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR11(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR12(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR13(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR14(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR15(mode64));
+
+         addHRegUse(u, HRmWrite, hregMIPS_GPR24(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR25(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR26(mode64));
+         addHRegUse(u, HRmWrite, hregMIPS_GPR27(mode64));
+
+         /* Now we have to state any parameter-carrying registers
+            which might be read.  This depends on the argiregs field. */
+         argir = i->Min.Call.argiregs;
+         if (argir & (1 << 7))
+            addHRegUse(u, HRmRead, hregMIPS_GPR7(mode64));
+         if (argir & (1 << 6))
+            addHRegUse(u, HRmRead, hregMIPS_GPR6(mode64));
+         if (argir & (1 << 5))
+            addHRegUse(u, HRmRead, hregMIPS_GPR5(mode64));
+         if (argir & (1 << 4))
+            addHRegUse(u, HRmRead, hregMIPS_GPR4(mode64));
+
+         vassert(0 == (argir & ~((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7))));
+         return;
+      }
+      /* XDirect/XIndir/XAssisted are also a bit subtle.  They
+         conditionally exit the block.  Hence we only need to list (1)
+         the registers that they read, and (2) the registers that they
+         write in the case where the block is not exited.  (2) is
+         empty, hence only (1) is relevant here. */
+      case Min_XDirect:
+         addRegUsage_MIPSAMode(u, i->Min.XDirect.amPC);
+         return;
+      case Min_XIndir:
+         addHRegUse(u, HRmRead, i->Min.XIndir.dstGA);
+         addRegUsage_MIPSAMode(u, i->Min.XIndir.amPC);
+         return;
+      case Min_XAssisted:
+         addHRegUse(u, HRmRead, i->Min.XAssisted.dstGA);
+         addRegUsage_MIPSAMode(u, i->Min.XAssisted.amPC);
+         return;
+      case Min_Load:
+         addRegUsage_MIPSAMode(u, i->Min.Load.src);
+         addHRegUse(u, HRmWrite, i->Min.Load.dst);
+         return;
+      case Min_Store:
+         addHRegUse(u, HRmRead, i->Min.Store.src);
+         addRegUsage_MIPSAMode(u, i->Min.Store.dst);
+         return;
+      case Min_LoadL:
+         addRegUsage_MIPSAMode(u, i->Min.LoadL.src);
+         addHRegUse(u, HRmWrite, i->Min.LoadL.dst);
+         return;
+      case Min_StoreC:
+         addHRegUse(u, HRmWrite, i->Min.StoreC.src);
+         addHRegUse(u, HRmRead, i->Min.StoreC.src);
+         addRegUsage_MIPSAMode(u, i->Min.StoreC.dst);
+         return;
+      case Min_RdWrLR:
+         addHRegUse(u, (i->Min.RdWrLR.wrLR ? HRmRead : HRmWrite),
+                        i->Min.RdWrLR.gpr);
+         return;
+      case Min_FpLdSt:
+         if (i->Min.FpLdSt.sz == 4) {
+            addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead),
+                           i->Min.FpLdSt.reg);
+            addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr);
+            return;
+         } else if (i->Min.FpLdSt.sz == 8) {
+            if (mode64) {
+               addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead),
+                              i->Min.FpLdSt.reg);
+               addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr);
+            } else {
+               addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead),
+                              i->Min.FpLdSt.reg);
+               addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr);
+               addRegUsage_MIPSAMode(u, nextMIPSAModeFloat(i->Min.FpLdSt.addr));
+            }
+            return;
+         }
+         break;
+      case Min_FpUnary:
+         if (i->Min.FpUnary.op == Mfp_CVTD) {
+            addHRegUse(u, HRmWrite, i->Min.FpUnary.dst);
+            addHRegUse(u, HRmRead, i->Min.FpUnary.src);
+            return;
+         } else {
+            addHRegUse(u, HRmWrite, i->Min.FpUnary.dst);
+            addHRegUse(u, HRmRead, i->Min.FpUnary.src);
+            return;
+         }
+      case Min_FpBinary:
+         addHRegUse(u, HRmWrite, i->Min.FpBinary.dst);
+         addHRegUse(u, HRmRead, i->Min.FpBinary.srcL);
+         addHRegUse(u, HRmRead, i->Min.FpBinary.srcR);
+         return;
+      case Min_FpConvert:
+         addHRegUse(u, HRmWrite, i->Min.FpConvert.dst);
+         addHRegUse(u, HRmRead, i->Min.FpConvert.src);
+         return;
+      case Min_FpCompare:
+         addHRegUse(u, HRmWrite, i->Min.FpCompare.dst);
+         addHRegUse(u, HRmRead, i->Min.FpCompare.srcL);
+         addHRegUse(u, HRmRead, i->Min.FpCompare.srcR);
+         return;
+      case Min_MovCond:
+         if (i->Min.MovCond.srcR->tag == Mrh_Reg) {
+            addHRegUse(u, HRmRead, i->Min.MovCond.srcR->Mrh.Reg.reg);
+         }
+         addHRegUse(u, HRmRead, i->Min.MovCond.srcL);
+         addHRegUse(u, HRmRead, i->Min.MovCond.condR);
+         addHRegUse(u, HRmWrite, i->Min.MovCond.dst);
+         return;
+      case Min_EvCheck:
+         /* We expect both amodes only to mention %ebp, so this is in
+            fact pointless, since %ebp isn't allocatable, but anyway.. */
+         addRegUsage_MIPSAMode(u, i->Min.EvCheck.amCounter);
+         addRegUsage_MIPSAMode(u, i->Min.EvCheck.amFailAddr);
+         return;
+      case Min_ProfInc:
+         /* does not use any registers. */
+         return;
+      default:
+         ppMIPSInstr(i, mode64);
+         vpanic("getRegUsage_MIPSInstr");
+         break;
+   }
+}
+
+/* local helper */
+static void mapReg(HRegRemap * m, HReg * r)
+{
+   *r = lookupHRegRemap(m, *r);
+}
+
+void mapRegs_MIPSInstr(HRegRemap * m, MIPSInstr * i, Bool mode64)
+{
+   switch (i->tag) {
+      case Min_LI:
+         mapReg(m, &i->Min.LI.dst);
+         break;
+      case Min_Alu:
+         mapReg(m, &i->Min.Alu.srcL);
+         mapRegs_MIPSRH(m, i->Min.Alu.srcR);
+         mapReg(m, &i->Min.Alu.dst);
+         return;
+      case Min_Shft:
+         mapReg(m, &i->Min.Shft.srcL);
+         mapRegs_MIPSRH(m, i->Min.Shft.srcR);
+         mapReg(m, &i->Min.Shft.dst);
+         return;
+      case Min_Cmp:
+         mapReg(m, &i->Min.Cmp.srcL);
+         mapReg(m, &i->Min.Cmp.srcR);
+         mapReg(m, &i->Min.Cmp.dst);
+         return;
+      case Min_Unary:
+         mapReg(m, &i->Min.Unary.src);
+         mapReg(m, &i->Min.Unary.dst);
+         return;
+      case Min_Mul:
+         mapReg(m, &i->Min.Mul.dst);
+         mapReg(m, &i->Min.Mul.srcL);
+         mapReg(m, &i->Min.Mul.srcR);
+         return;
+      case Min_Mthi:
+      case Min_Mtlo:
+         mapReg(m, &i->Min.MtHL.src);
+         return;
+      case Min_Mfhi:
+      case Min_Mflo:
+         mapReg(m, &i->Min.MfHL.dst);
+         return;
+      case Min_Macc:
+         mapReg(m, &i->Min.Macc.srcL);
+         mapReg(m, &i->Min.Macc.srcR);
+         return;
+      case Min_Div:
+         mapReg(m, &i->Min.Div.srcL);
+         mapReg(m, &i->Min.Div.srcR);
+         return;
+      case Min_Call:
+         {
+            if (i->Min.Call.cond != MIPScc_AL)
+               mapReg(m, &i->Min.Call.src);
+            return;
+         }
+      case Min_XDirect:
+         mapRegs_MIPSAMode(m, i->Min.XDirect.amPC);
+         return;
+      case Min_XIndir:
+         mapReg(m, &i->Min.XIndir.dstGA);
+         mapRegs_MIPSAMode(m, i->Min.XIndir.amPC);
+         return;
+      case Min_XAssisted:
+         mapReg(m, &i->Min.XAssisted.dstGA);
+         mapRegs_MIPSAMode(m, i->Min.XAssisted.amPC);
+         return;
+      case Min_Load:
+         mapRegs_MIPSAMode(m, i->Min.Load.src);
+         mapReg(m, &i->Min.Load.dst);
+         return;
+      case Min_Store:
+         mapReg(m, &i->Min.Store.src);
+         mapRegs_MIPSAMode(m, i->Min.Store.dst);
+         return;
+      case Min_LoadL:
+         mapRegs_MIPSAMode(m, i->Min.LoadL.src);
+         mapReg(m, &i->Min.LoadL.dst);
+         return;
+      case Min_StoreC:
+         mapReg(m, &i->Min.StoreC.src);
+         mapRegs_MIPSAMode(m, i->Min.StoreC.dst);
+         return;
+      case Min_RdWrLR:
+         mapReg(m, &i->Min.RdWrLR.gpr);
+         return;
+      case Min_FpLdSt:
+         if (i->Min.FpLdSt.sz == 4) {
+            mapReg(m, &i->Min.FpLdSt.reg);
+            mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr);
+            return;
+         } else if (i->Min.FpLdSt.sz == 8) {
+            if (mode64) {
+               mapReg(m, &i->Min.FpLdSt.reg);
+               mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr);
+            } else {
+               mapReg(m, &i->Min.FpLdSt.reg);
+               mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr);
+               mapRegs_MIPSAMode(m, nextMIPSAModeFloat(i->Min.FpLdSt.addr));
+            }
+            return;
+         }
+         break;
+      case Min_FpUnary:
+         if (i->Min.FpUnary.op == Mfp_CVTD) {
+            mapReg(m, &i->Min.FpUnary.dst);
+            mapReg(m, &i->Min.FpUnary.src);
+            return;
+         } else {
+            mapReg(m, &i->Min.FpUnary.dst);
+            mapReg(m, &i->Min.FpUnary.src);
+            return;
+         }
+      case Min_FpBinary:
+         mapReg(m, &i->Min.FpBinary.dst);
+         mapReg(m, &i->Min.FpBinary.srcL);
+         mapReg(m, &i->Min.FpBinary.srcR);
+         return;
+      case Min_FpConvert:
+         mapReg(m, &i->Min.FpConvert.dst);
+         mapReg(m, &i->Min.FpConvert.src);
+         return;
+      case Min_FpCompare:
+         mapReg(m, &i->Min.FpCompare.dst);
+         mapReg(m, &i->Min.FpCompare.srcL);
+         mapReg(m, &i->Min.FpCompare.srcR);
+         return;
+      case Min_MtFCSR:
+         mapReg(m, &i->Min.MtFCSR.src);
+         return;
+      case Min_MfFCSR:
+         mapReg(m, &i->Min.MfFCSR.dst);
+         return;
+      case Min_MovCond:
+         if (i->Min.MovCond.srcR->tag == Mrh_Reg) {
+            mapReg(m, &(i->Min.MovCond.srcR->Mrh.Reg.reg));
+         }
+         mapReg(m, &i->Min.MovCond.srcL);
+         mapReg(m, &i->Min.MovCond.condR);
+         mapReg(m, &i->Min.MovCond.dst);
+
+         return;
+      case Min_EvCheck:
+         /* We expect both amodes only to mention %ebp, so this is in
+            fact pointless, since %ebp isn't allocatable, but anyway.. */
+         mapRegs_MIPSAMode(m, i->Min.EvCheck.amCounter);
+         mapRegs_MIPSAMode(m, i->Min.EvCheck.amFailAddr);
+         return;
+      case Min_ProfInc:
+         /* does not use any registers. */
+         return;
+      default:
+         ppMIPSInstr(i, mode64);
+         vpanic("mapRegs_MIPSInstr");
+         break;
+   }
+
+}
+
+/* Figure out if i represents a reg-reg move, and if so assign the
+   source and destination to *src and *dst.  If in doubt say No.  Used
+   by the register allocator to do move coalescing. 
+*/
+Bool isMove_MIPSInstr(MIPSInstr * i, HReg * src, HReg * dst)
+{
+   /* Moves between integer regs */
+   if (i->tag == Min_Alu) {
+      // or Rd,Rs,Rs == mr Rd,Rs
+      if (i->Min.Alu.op != Malu_OR)
+         return False;
+      if (i->Min.Alu.srcR->tag != Mrh_Reg)
+         return False;
+      if (i->Min.Alu.srcR->Mrh.Reg.reg != i->Min.Alu.srcL)
+         return False;
+      *src = i->Min.Alu.srcL;
+      *dst = i->Min.Alu.dst;
+      return True;
+   }
+   return False;
+}
+
+/* Generate mips spill/reload instructions under the direction of the
+   register allocator.
+*/
+void genSpill_MIPS( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2, HReg rreg,
+                    Int offsetB, Bool mode64)
+{
+   MIPSAMode *am;
+   vassert(offsetB >= 0);
+   vassert(!hregIsVirtual(rreg));
+   *i1 = *i2 = NULL;
+   am = MIPSAMode_IR(offsetB, GuestStatePointer(mode64));
+
+   switch (hregClass(rreg)) {
+      case HRcInt64:
+         vassert(mode64);
+         *i1 = MIPSInstr_Store(8, am, rreg, mode64);
+         break;
+      case HRcInt32:
+         vassert(!mode64);
+         *i1 = MIPSInstr_Store(4, am, rreg, mode64);
+         break;
+      case HRcFlt32:
+         vassert(!mode64);
+         *i1 = MIPSInstr_FpLdSt(False /*Store */ , 4, rreg, am);
+         break;
+      case HRcFlt64:
+         *i1 = MIPSInstr_FpLdSt(False /*Store */ , 8, rreg, am);
+         break;
+      default:
+         ppHRegClass(hregClass(rreg));
+         vpanic("genSpill_MIPS: unimplemented regclass");
+         break;
+   }
+}
+
+void genReload_MIPS( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2, HReg rreg,
+                     Int offsetB, Bool mode64)
+{
+   MIPSAMode *am;
+   vassert(!hregIsVirtual(rreg));
+   am = MIPSAMode_IR(offsetB, GuestStatePointer(mode64));
+
+   switch (hregClass(rreg)) {
+      case HRcInt64:
+         vassert(mode64);
+         *i1 = MIPSInstr_Load(8, rreg, am, mode64);
+         break;
+      case HRcInt32:
+         vassert(!mode64);
+         *i1 = MIPSInstr_Load(4, rreg, am, mode64);
+         break;
+      case HRcFlt32:
+         if (mode64)
+            *i1 = MIPSInstr_FpLdSt(True /*Load */ , 8, rreg, am);
+         else
+            *i1 = MIPSInstr_FpLdSt(True /*Load */ , 4, rreg, am);
+         break;
+      case HRcFlt64:
+         *i1 = MIPSInstr_FpLdSt(True /*Load */ , 8, rreg, am);
+         break;
+      default:
+         ppHRegClass(hregClass(rreg));
+         vpanic("genReload_MIPS: unimplemented regclass");
+         break;
+   }
+}
+
+/* --------- The mips assembler --------- */
+
+static UInt iregNo(HReg r, Bool mode64)
+{
+   UInt n;
+   vassert(hregClass(r) == mode64 ? HRcInt64 : HRcInt32);
+   vassert(!hregIsVirtual(r));
+   n = hregNumber(r);
+   vassert(n <= 32);
+   return n;
+}
+
+static UChar fregNo(HReg r, Bool mode64)
+{
+   UInt n;
+   vassert(hregClass(r) == mode64 ? HRcFlt64 : HRcFlt32);
+   vassert(!hregIsVirtual(r));
+   n = hregNumber(r);
+   vassert(n <= 31);
+   return n;
+}
+
+static UChar dregNo(HReg r)
+{
+   UInt n;
+   vassert(hregClass(r) == HRcFlt64);
+   vassert(!hregIsVirtual(r));
+   n = hregNumber(r);
+   vassert(n <= 31);
+   return n;
+}
+
+/* Emit 32bit instruction */
+static UChar *emit32(UChar * p, UInt w32)
+{
+#if defined (_MIPSEL)
+   *p++ = toUChar(w32 & 0x000000FF);
+   *p++ = toUChar((w32 >> 8) & 0x000000FF);
+   *p++ = toUChar((w32 >> 16) & 0x000000FF);
+   *p++ = toUChar((w32 >> 24) & 0x000000FF);
+#elif defined (_MIPSEB)
+   *p++ = toUChar((w32 >> 24) & 0x000000FF);
+   *p++ = toUChar((w32 >> 16) & 0x000000FF);
+   *p++ = toUChar((w32 >> 8) & 0x000000FF);
+   *p++ = toUChar(w32 & 0x000000FF);
+#endif
+   return p;
+}
+/* Fetch an instruction */
+static UInt fetch32 ( UChar* p )
+{
+   UInt w32 = 0;
+#if defined (_MIPSEL)
+   w32 |= ((0xFF & (UInt)p[0]) << 0);
+   w32 |= ((0xFF & (UInt)p[1]) << 8);
+   w32 |= ((0xFF & (UInt)p[2]) << 16);
+   w32 |= ((0xFF & (UInt)p[3]) << 24);
+#elif defined (_MIPSEB)
+   w32 |= ((0xFF & (UInt)p[0]) << 24);
+   w32 |= ((0xFF & (UInt)p[1]) << 16);
+   w32 |= ((0xFF & (UInt)p[2]) <<  8);
+   w32 |= ((0xFF & (UInt)p[3]) <<  0);
+#endif
+   return w32;
+}
+
+/* physical structure of mips instructions */
+/* type I : opcode    - 6 bits 
+         rs         - 5 bits
+         rt         - 5 bits
+         immediate - 16 bits
+*/
+static UChar *mkFormI(UChar * p, UInt opc, UInt rs, UInt rt, UInt imm)
+{
+   UInt theInstr;
+   vassert(opc < 0x40);
+   vassert(rs < 0x20);
+   vassert(rt < 0x20);
+   imm = imm & 0xFFFF;
+   theInstr = ((opc << 26) | (rs << 21) | (rt << 16) | (imm));
+   return emit32(p, theInstr);
+}
+
+/* type R: opcode    - 6 bits
+         rs    - 5 bits
+         rt    - 5 bits
+         rd    - 5 bits
+         sa    - 5 bits
+         func  - 6 bits
+*/
+static UChar *mkFormR(UChar * p, UInt opc, UInt rs, UInt rt, UInt rd, UInt sa,
+            UInt func)
+{
+   if (rs >= 0x20)
+      vex_printf("rs = %d\n", rs);
+   UInt theInstr;
+   vassert(opc < 0x40);
+   vassert(rs < 0x20);
+   vassert(rt < 0x20);
+   vassert(rd < 0x20);
+   vassert(sa < 0x20);
+   func = func & 0xFFFF;
+   theInstr = ((opc << 26) | (rs << 21) | (rt << 16) | (rd << 11) | (sa << 6) |
+               (func));
+
+   return emit32(p, theInstr);
+}
+
+static UChar *mkFormS(UChar * p, UInt opc1, UInt rRD, UInt rRS, UInt rRT,
+                      UInt sa, UInt opc2)
+{
+   UInt theInstr;
+   vassert(opc1 <= 0x3F);
+   vassert(rRD < 0x20);
+   vassert(rRS < 0x20);
+   vassert(rRT < 0x20);
+   vassert(opc2 <= 0x3F);
+   vassert(sa >= 0 && sa <= 0x3F);
+
+   theInstr = ((opc1 << 26) | (rRS << 21) | (rRT << 16) | (rRD << 11) |
+              ((sa & 0x1F) << 6) | (opc2));
+
+   return emit32(p, theInstr);
+}
+
+static UChar *doAMode_IR(UChar * p, UInt opc1, UInt rSD, MIPSAMode * am,
+                         Bool mode64)
+{
+   UInt rA, idx, r_dst;
+   vassert(am->tag == Mam_IR);
+   vassert(am->Mam.IR.index < 0x10000);
+
+   rA = iregNo(am->Mam.IR.base, mode64);
+   idx = am->Mam.IR.index;
+
+   if (rSD == 33 || rSD == 34)
+      r_dst = 24;
+   else
+      r_dst = rSD;
+
+   if (opc1 < 40) {
+      //load
+      if (rSD == 33)
+         /* mfhi */
+         p = mkFormR(p, 0, 0, 0, r_dst, 0, 16);
+      else if (rSD == 34)
+         /* mflo */
+         p = mkFormR(p, 0, 0, 0, r_dst, 0, 18);
+   }
+
+   p = mkFormI(p, opc1, rA, r_dst, idx);
+
+   if (opc1 >= 40) {
+      //store
+      if (rSD == 33)
+         /* mthi */
+         p = mkFormR(p, 0, r_dst, 0, 0, 0, 17);
+      else if (rSD == 34)
+         /* mtlo */
+         p = mkFormR(p, 0, r_dst, 0, 0, 0, 19);
+   }
+
+   return p;
+}
+
+static UChar *doAMode_RR(UChar * p, UInt opc1, UInt rSD, MIPSAMode * am,
+                         Bool mode64)
+{
+   UInt rA, rB, r_dst;
+   vassert(am->tag == Mam_RR);
+
+   rA = iregNo(am->Mam.RR.base, mode64);
+   rB = iregNo(am->Mam.RR.index, mode64);
+
+   if (rSD == 33 || rSD == 34)
+      r_dst = 24;
+   else
+      r_dst = rSD;
+
+   if (opc1 < 40) {
+      //load
+      if (rSD == 33)
+         /* mfhi */
+         p = mkFormR(p, 0, 0, 0, r_dst, 0, 16);
+      else if (rSD == 34)
+         /* mflo */
+         p = mkFormR(p, 0, 0, 0, r_dst, 0, 18);
+   }
+   /* addiu sp, sp, -4
+    * sw rA, 0(sp)
+    * addu rA, rA, rB 
+    * sw/lw r_dst, 0(rA)
+    * lw rA, 0(sp) 
+    * addiu sp, sp, 4 */
+   if (mode64) {
+      p = mkFormI(p, 25, 29, 29, 0xFFFC);
+      p = mkFormI(p, 63, 29, rA, 0);
+      p = mkFormR(p, 0, rA, rB, rA, 0, 45);
+      p = mkFormI(p, opc1, rA, r_dst, 0);
+      p = mkFormI(p, 55, 29, rA, 0);
+      p = mkFormI(p, 25, 29, 29, 4);
+   } else {
+      p = mkFormI(p, 9, 29, 29, 0xFFFC);
+      p = mkFormI(p, 43, 29, rA, 0);
+      p = mkFormR(p, 0, rA, rB, rA, 0, 33);
+      p = mkFormI(p, opc1, rA, r_dst, 0);
+      p = mkFormI(p, 35, 29, rA, 0);
+      p = mkFormI(p, 9, 29, 29, 4);
+   }
+   if (opc1 >= 40) {
+      //store
+      if (rSD == 33)
+         /* mthi */
+         p = mkFormR(p, 0, r_dst, 0, 0, 0, 17);
+      else if (rSD == 34)
+         /* mtlo */
+         p = mkFormR(p, 0, r_dst, 0, 0, 0, 19);
+   }
+
+   return p;
+}
+
+/* Load imm to r_dst */
+static UChar *mkLoadImm(UChar * p, UInt r_dst, ULong imm, Bool mode64)
+{
+   if (!mode64) {
+      vassert(r_dst < 0x20);
+      UInt u32 = (UInt) imm;
+      Int s32 = (Int) u32;
+      Long s64 = (Long) s32;
+      imm = (ULong) s64;
+   }
+
+   if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) {
+      // sign-extendable from 16 bits
+      // addiu r_dst,0,imm  => li r_dst,imm
+      p = mkFormI(p, 9, 0, r_dst, imm & 0xFFFF);
+   } else {
+      if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) {
+         // sign-extendable from 32 bits
+         // addiu r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
+         // lui r_dst, (imm>>16)
+         p = mkFormI(p, 15, 0, r_dst, (imm >> 16) & 0xFFFF);
+         // ori r_dst, r_dst, (imm & 0xFFFF)
+         p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF);
+      } else {
+         vassert(mode64);
+         // lui load in upper half of low word
+         p = mkFormI(p, 15, 0, r_dst, (imm >> 48) & 0xFFFF);
+         // ori
+         p = mkFormI(p, 13, r_dst, r_dst, (imm >> 32) & 0xFFFF);
+         //shift
+         p = mkFormS(p, 0, r_dst, 0, r_dst, 16, 56);
+         // ori
+         p = mkFormI(p, 13, r_dst, r_dst, (imm >> 16) & 0xFFFF);
+         //shift
+         p = mkFormS(p, 0, r_dst, 0, r_dst, 16, 56);
+         // ori
+         p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF);
+      }
+   }
+   return p;
+}
+
+/* A simplified version of mkLoadImm that always generates 2 or 5
+   instructions (32 or 64 bits respectively) even if it could generate
+   fewer.  This is needed for generating fixed sized patchable
+   sequences. */
+static UChar* mkLoadImm_EXACTLY2or5 ( UChar* p,
+                                      UInt r_dst, ULong imm, Bool mode64 )
+{
+   vassert(r_dst < 0x20);
+
+   if (!mode64) {
+      /* In 32-bit mode, make sure the top 32 bits of imm are a sign
+         extension of the bottom 32 bits.  (Probably unnecessary.) */
+      UInt u32 = (UInt)imm;
+      Int  s32 = (Int)u32;
+      Long s64 = (Long)s32;
+      imm = (ULong)s64;
+   }
+
+   if (!mode64) {
+      // sign-extendable from 32 bits
+      // addiu r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
+      // lui r_dst, (imm>>16)
+      p = mkFormI(p, 15, 0, r_dst, (imm >> 16) & 0xFFFF);
+      // ori r_dst, r_dst, (imm & 0xFFFF)
+      p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF);
+   } else {
+      vassert(0);
+   }
+   return p;
+}
+
+/* Checks whether the sequence of bytes at p was indeed created
+   by mkLoadImm_EXACTLY2or5 with the given parameters. */
+static Bool isLoadImm_EXACTLY2or5 ( UChar* p_to_check,
+                                    UInt r_dst, ULong imm, Bool mode64 )
+{
+   vassert(r_dst < 0x20);
+   Bool ret;
+   if (!mode64) {
+      /* In 32-bit mode, make sure the top 32 bits of imm are a sign
+         extension of the bottom 32 bits.  (Probably unnecessary.) */
+      UInt u32 = (UInt)imm;
+      Int  s32 = (Int)u32;
+      Long s64 = (Long)s32;
+      imm = (ULong)s64;
+   }
+
+   if (!mode64) {
+      UInt   expect[2] = { 0, 0 };
+      UChar* p         = (UChar*)&expect[0];
+      // lui r_dst, (imm>>16)
+      p = mkFormI(p, 15, 0, r_dst, (imm >> 16) & 0xFFFF);
+      // ori r_dst, r_dst, (imm & 0xFFFF)
+      p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF);
+      vassert(p == (UChar*)&expect[2]);
+
+      ret = fetch32(p_to_check + 0) == expect[0]
+             && fetch32(p_to_check + 4) == expect[1];
+
+   } else {
+      vassert(0);
+   }
+   return ret;
+}
+
+/* Generate a machine-word sized load or store.  Simplified version of
+   the Min_Load and Min_Store cases below. */
+static UChar* do_load_or_store_machine_word ( 
+                 UChar* p, Bool isLoad,
+                 UInt reg, MIPSAMode* am, Bool mode64 )
+{
+   if (isLoad) { /* load */
+      UInt opc1, sz = mode64 ? 8 : 4;
+      switch (am->tag) {
+         case Mam_IR:
+            if (mode64) {
+               vassert(0 == (am->Mam.IR.index & 3));
+            }
+            switch (sz) {
+               case 1:
+                  opc1 = 32;
+                  break;
+               case 2:
+                  opc1 = 33;
+                  break;
+               case 4:
+                  opc1 = 35;
+                  break;
+               case 8:
+                  opc1 = 55;
+                  vassert(mode64);
+                  break;
+                  break;
+               default:
+                  vassert(0);
+                  break;
+            }
+            p = doAMode_IR(p, opc1, reg, am, mode64);
+            break;
+         case Mam_RR:
+            /* we could handle this case, but we don't expect to ever
+               need to. */
+            vassert(0);
+            break;
+         default:
+            vassert(0);
+            break;
+      }
+   } else /* store */ {
+      UInt opc1, sz = mode64 ? 8 : 4;
+      switch (am->tag) {
+         case Mam_IR:
+            if (mode64) {
+               vassert(0 == (am->Mam.IR.index & 3));
+            }
+            switch (sz) {
+               case 1:
+                  opc1 = 40;
+                  break;
+               case 2:
+                  opc1 = 41;
+                  break;
+               case 4:
+                  opc1 = 43;
+                  break;
+               case 8:
+                  vassert(mode64);
+                  opc1 = 63;
+                  break;
+               default:
+                  vassert(0);
+                  break;
+            }
+            p = doAMode_IR(p, opc1, reg, am, mode64);
+            break;
+         case Mam_RR:
+            /* we could handle this case, but we don't expect to ever
+               need to. */
+            vassert(0);
+            break;
+         default:
+            vassert(0);
+            break;
+      }
+   }
+   return p;
+}
+
+/* Move r_dst to r_src */
+static UChar *mkMoveReg(UChar * p, UInt r_dst, UInt r_src)
+{
+   vassert(r_dst < 0x20);
+   vassert(r_src < 0x20);
+
+   if (r_dst != r_src) {
+      /* or r_dst, r_src, r_src */
+      p = mkFormR(p, 0, r_src, r_src, r_dst, 0, 37);
+   }
+   return p;
+}
+
+/* Emit an instruction into buf and return the number of bytes used.
+   Note that buf is not the insn's final place, and therefore it is
+   imperative to emit position-independent code.  If the emitted
+   instruction was a profiler inc, set *is_profInc to True, else
+   leave it unchanged. */
+Int emit_MIPSInstr ( /*MB_MOD*/Bool* is_profInc,
+                     UChar* buf, Int nbuf, MIPSInstr* i, 
+                     Bool mode64,
+                     void* disp_cp_chain_me_to_slowEP,
+                     void* disp_cp_chain_me_to_fastEP,
+                     void* disp_cp_xindir,
+                     void* disp_cp_xassisted )
+{
+   UChar *p = &buf[0];
+   UChar *ptmp = p;
+   vassert(nbuf >= 32);
+
+   switch (i->tag) {
+      case Min_MovCond: {
+         MIPSRH *srcR = i->Min.MovCond.srcR;
+         UInt condR = iregNo(i->Min.MovCond.condR, mode64);
+         UInt dst = iregNo(i->Min.MovCond.dst, mode64);
+
+         UInt srcL = iregNo(i->Min.MovCond.srcL, mode64);
+
+         p = mkMoveReg(p, dst, srcL);
+         if (i->Min.MovCond.cond == MIPScc_MI) {
+            p = mkFormI(p, 7, condR, 0, 2);  //bgtz cond,2
+         }
+
+         p = mkFormR(p, 0, 0, 0, 0, 0, 0);   //nop
+   
+         if (srcR->tag == Mrh_Reg) {
+            //or dst,src,src
+            p = mkMoveReg(p, dst, iregNo(srcR->Mrh.Reg.reg, mode64));
+            /*p = mkFormR(p, 0, dst, iregNo(src->Mrh.Reg.reg, mode64),
+                        iregNo(src->Mrh.Reg.reg, mode64), 0, 37);*/
+         } else {
+            p = mkLoadImm(p, dst, srcR->Mrh.Imm.imm16, mode64);
+         }
+      }
+         goto done;
+   
+      case Min_LI:
+         p = mkLoadImm(p, iregNo(i->Min.LI.dst, mode64), i->Min.LI.imm, mode64);
+         goto done;
+   
+      case Min_Alu: {
+         MIPSRH *srcR = i->Min.Alu.srcR;
+         Bool immR = toBool(srcR->tag == Mrh_Imm);
+         UInt r_dst = iregNo(i->Min.Alu.dst, mode64);
+         UInt r_srcL = iregNo(i->Min.Alu.srcL, mode64);
+         UInt r_srcR = immR ? (-1) /*bogus */ : iregNo(srcR->Mrh.Reg.reg, mode64);
+   
+         switch (i->Min.Alu.op) {
+            /*Malu_ADD, Malu_SUB, Malu_AND, Malu_OR, Malu_NOR, Malu_XOR */
+            case Malu_ADD:
+               if (immR) {
+                  vassert(srcR->Mrh.Imm.imm16 != 0x8000);
+                  if (srcR->Mrh.Imm.syned)
+                     /* addi */
+                     p = mkFormI(p, 9, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
+                  else
+                     /* addiu */
+                     p = mkFormI(p, 9, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
+               } else {
+                  /* addu */
+                  p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 33);
+               }
+               break;
+            case Malu_SUB:
+               if (immR) {
+                  /* addi , but with negated imm */
+                  vassert(srcR->Mrh.Imm.syned);
+                  vassert(srcR->Mrh.Imm.imm16 != 0x8000);
+                  p = mkFormI(p, 8, r_srcL, r_dst, (-srcR->Mrh.Imm.imm16));
+               } else {
+                  /* subu */
+                  p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 35);
+               }
+               break;
+            case Malu_AND:
+               if (immR) {
+                  /* andi */
+                  vassert(!srcR->Mrh.Imm.syned);
+                  p = mkFormI(p, 12, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
+               } else {
+                  /* and */
+                  p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 36);
+               }
+               break;
+            case Malu_OR:
+               if (immR) {
+                  /* ori */
+                  vassert(!srcR->Mrh.Imm.syned);
+                  p = mkFormI(p, 13, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
+               } else {
+                  /* or */
+                  if (r_srcL == 33)
+                     //MFHI
+                     p = mkFormR(p, 0, 0, 0, r_dst, 0, 16);
+                  else if (r_srcL == 34)
+                     //MFLO
+                     p = mkFormR(p, 0, 0, 0, r_dst, 0, 18);
+                  else if (r_dst == 33)
+                     //MTHI
+                     p = mkFormR(p, 0, r_srcL, 0, 0, 0, 17);
+                  else if (r_dst == 34)
+                     //MTLO
+                     p = mkFormR(p, 0, r_srcL, 0, 0, 0, 19);
+                  else
+                     p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 37);
+               }
+               break;
+            case Malu_NOR:
+               /* nor */
+               vassert(!immR);
+               p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 39);
+               break;
+            case Malu_XOR:
+               if (immR) {
+                  /* xori */
+                  vassert(!srcR->Mrh.Imm.syned);
+                  p = mkFormI(p, 14, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
+               } else {
+                  /* xor */
+                  p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 38);
+               }
+               break;
+      
+            default:
+               goto bad;
+         }
+         goto done;
+      }
+
+      case Min_Shft: {
+         MIPSRH *srcR = i->Min.Shft.srcR;
+         Bool sz32 = i->Min.Shft.sz32;
+         Bool immR = toBool(srcR->tag == Mrh_Imm);
+         UInt r_dst = iregNo(i->Min.Shft.dst, mode64);
+         UInt r_srcL = iregNo(i->Min.Shft.srcL, mode64);
+         UInt r_srcR = immR ? (-1) /*bogus */ : iregNo(srcR->Mrh.Reg.reg,
+                                                       mode64);
+         if (!mode64)
+            vassert(sz32);
+         switch (i->Min.Shft.op) {
+            case Mshft_SLL:
+               if (sz32) {
+                  if (immR) {
+                     UInt n = srcR->Mrh.Imm.imm16;
+                     vassert(n >= 0 && n < 32);
+                     p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 0);
+                  } else {
+                     /* shift variable */
+                     p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 4);
+                  }
+               } else {
+                  if (immR) {
+                     UInt n = srcR->Mrh.Imm.imm16;
+                     vassert((n >= 0 && n < 32) || (n > 31 && n < 64));
+                     if (n >= 0 && n < 32) {
+                        p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 56);
+                     } else {
+                        p = mkFormS(p, 0, r_dst, 0, r_srcL, n - 32, 60);
+                     }
+                  } else {
+                     p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 20);
+                  }
+               }
+               break;
+   
+            case Mshft_SRL:
+               if (sz32) {
+                  // SRL, SRLV
+                  if (immR) {
+                     UInt n = srcR->Mrh.Imm.imm16;
+                     vassert(n >= 0 && n < 32);
+                     p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 2);
+                  } else {
+                     /* shift variable */
+                     p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 6);
+                  }
+               } else {
+                  // DSRL, DSRL32, DSRLV
+                  if (immR) {
+                     UInt n = srcR->Mrh.Imm.imm16;
+                     vassert((n >= 0 && n < 32) || (n > 31 && n < 64));
+                     if (n >= 0 && n < 32) {
+                        p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 58);
+                     } else {
+                        p = mkFormS(p, 0, r_dst, 0, r_srcL, n - 32, 62);
+                     }
+                  } else {
+                     p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 22);
+                  }
+               }
+               break;
+   
+            case Mshft_SRA:
+               if (sz32) {
+                  // SRA, SRAV
+                  if (immR) {
+                     UInt n = srcR->Mrh.Imm.imm16;
+                     vassert(n >= 0 && n < 32);
+                     p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 3);
+                  } else {
+                     /* shift variable */
+                     p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 7);
+                  }
+               } else {
+                  // DSRA, DSRA32, DSRAV
+                  if (immR) {
+                     UInt n = srcR->Mrh.Imm.imm16;
+                     vassert((n >= 0 && n < 32) || (n > 31 && n < 64));
+                     if (n >= 0 && n < 32) {
+                        p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 59);
+                     } else {
+                        p = mkFormS(p, 0, r_dst, 0, r_srcL, n - 32, 63);
+                     }
+                  } else {
+                     p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 23);
+                  }
+               }
+               break;
+   
+            default:
+               goto bad;
+         }
+
+         goto done;
+      }
+   
+      case Min_Unary: {
+         UInt r_dst = iregNo(i->Min.Unary.dst, mode64);
+         UInt r_src = iregNo(i->Min.Unary.src, mode64);
+
+         switch (i->Min.Unary.op) {
+            /*Mun_CLO, Mun_CLZ, Mun_NOP */
+            case Mun_CLO:  //clo
+               p = mkFormR(p, 28, r_src, 0 /*whatever */ , r_dst, 0, 33);
+               break;
+            case Mun_CLZ:  //clz
+               p = mkFormR(p, 28, r_src, 0 /*whatever */ , r_dst, 0, 32);
+               break;
+            case Mun_NOP:  //nop (sll r0,r0,0)
+               p = mkFormR(p, 0, 0, 0, 0, 0, 0);
+               break;
+         }
+         goto done;
+      }
+   
+      case Min_Cmp: {
+         UInt r_srcL = iregNo(i->Min.Cmp.srcL, mode64);
+         UInt r_srcR = iregNo(i->Min.Cmp.srcR, mode64);
+         UInt r_dst = iregNo(i->Min.Cmp.dst, mode64);
+
+         switch (i->Min.Cmp.cond) {
+            case MIPScc_EQ:
+               /*  addiu r_dst, r0, 1
+                  beq r_srcL, r_srcR, 2
+                  nop
+                  addiu r_dst, r0, 0
+                */
+               p = mkFormI(p, 9, 0, r_dst, 1);
+               p = mkFormI(p, 4, r_srcL, r_srcR, 2);
+               p = mkFormR(p, 0, 0, 0, 0, 0, 0);
+               p = mkFormI(p, 9, 0, r_dst, 0);
+               break;
+            case MIPScc_NE:
+               /*  addiu r_dst, r0, 1
+                  bne r_srcL, r_srcR, 2
+                  nop
+                  addiu r_dst, r0, 0
+                */
+               p = mkFormI(p, 9, 0, r_dst, 1);
+               p = mkFormI(p, 5, r_srcL, r_srcR, 2);
+               p = mkFormR(p, 0, 0, 0, 0, 0, 0);
+               p = mkFormI(p, 9, 0, r_dst, 0);
+               break;
+            case MIPScc_LT:
+               /*  slt r_dst, r_srcL, r_srcR */
+               p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 42);
+               break;
+            case MIPScc_LO:
+               /*  sltu r_dst, r_srcL, r_srcR */
+               p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 43);
+               break;
+            case MIPScc_LE:
+               /*  addiu r_dst, r0, 1
+                  beq r_srcL, r_srcR, 2
+                  nop
+                  slt r_dst, r_srcL, r_srcR */
+               p = mkFormI(p, 9, 0, r_dst, 1);
+               p = mkFormI(p, 4, r_srcL, r_srcR, 2);
+               p = mkFormR(p, 0, 0, 0, 0, 0, 0);
+               p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 42);
+               break;
+            case MIPScc_LS:
+               /*  addiu r_dst, r0, 1
+                  beq r_srcL, r_srcR, 2
+                  nop
+                  sltu r_dst, r_srcL, r_srcR */
+               p = mkFormI(p, 9, 0, r_dst, 1);
+               p = mkFormI(p, 4, r_srcL, r_srcR, 2);
+               p = mkFormR(p, 0, 0, 0, 0, 0, 0);
+               p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 43);
+               break;
+            default:
+               goto bad;
+         }
+         goto done;
+      }
+   
+      case Min_Mul: {
+         Bool syned = i->Min.Mul.syned;
+         Bool widening = i->Min.Mul.widening;
+         Bool sz32 = i->Min.Mul.sz32;
+         UInt r_srcL = iregNo(i->Min.Mul.srcL, mode64);
+         UInt r_srcR = iregNo(i->Min.Mul.srcR, mode64);
+         UInt r_dst = iregNo(i->Min.Mul.dst, mode64);
+
+         if (widening) {
+            if (sz32) {
+               if (syned)
+                  /* mult */
+                  p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 24);
+               else
+                  /* multu */
+                  p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 25);
+            } else {
+               if (syned)  /* DMULT  r_dst,r_srcL,r_srcR */
+                  p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 28);
+               else  /* DMULTU r_dst,r_srcL,r_srcR */
+                  p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 29);
+            }
+         } else {
+            if (sz32)
+               /* mul */
+               p = mkFormR(p, 28, r_srcL, r_srcR, r_dst, 0, 2);
+            else if (mode64 && !sz32)
+               p = mkFormR(p, 28, r_srcL, r_srcR, r_dst, 0, 2);
+            else
+               goto bad;
+         }
+         goto done;
+      }
+   
+      case Min_Macc: {
+         Bool syned = i->Min.Macc.syned;
+         UInt r_srcL = iregNo(i->Min.Macc.srcL, mode64);
+         UInt r_srcR = iregNo(i->Min.Macc.srcR, mode64);
+
+         if (syned) {
+            switch (i->Min.Macc.op) {
+               case Macc_ADD:
+                  //madd
+                  p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0, 0);
+                  break;
+               case Macc_SUB:
+                  //msub
+                  p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0,
+                         4);
+                  break;
+               default:
+                  goto bad;
+            }
+         } else {
+            switch (i->Min.Macc.op) {
+               case Macc_ADD:
+                  //maddu
+                  p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0,
+                         1);
+                  break;
+               case Macc_SUB:
+                  //msubu
+                  p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0,
+                         5);
+                  break;
+               default:
+                  goto bad;
+            }
+         }
+
+         goto done;
+      }
+
+      case Min_Div: {
+         Bool syned = i->Min.Div.syned;
+         Bool sz32 = i->Min.Div.sz32;
+         UInt r_srcL = iregNo(i->Min.Div.srcL, mode64);
+         UInt r_srcR = iregNo(i->Min.Div.srcR, mode64);
+         if (sz32) {
+            if (syned) {
+               /* div */
+               p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 26);
+            } else
+               /* divu */
+               p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 27);
+            goto done;
+         } else {
+            if (syned) {
+               /* ddiv */
+               p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 30);
+            } else
+               /* ddivu */
+               p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 31);
+            goto done;
+         }
+      }
+   
+      case Min_Mthi: {
+         UInt r_src = iregNo(i->Min.MtHL.src, mode64);
+         p = mkFormR(p, 0, r_src, 0, 0, 0, 17);
+         goto done;
+      }
+   
+      case Min_Mtlo: {
+         UInt r_src = iregNo(i->Min.MtHL.src, mode64);
+         p = mkFormR(p, 0, r_src, 0, 0, 0, 19);
+         goto done;
+      }
+   
+      case Min_Mfhi: {
+         UInt r_dst = iregNo(i->Min.MfHL.dst, mode64);
+         p = mkFormR(p, 0, 0, 0, r_dst, 0, 16);
+         goto done;
+      }
+   
+      case Min_Mflo: {
+         UInt r_dst = iregNo(i->Min.MfHL.dst, mode64);
+         p = mkFormR(p, 0, 0, 0, r_dst, 0, 18);
+         goto done;
+      }
+   
+      case Min_MtFCSR: {
+         UInt r_src = iregNo(i->Min.MtFCSR.src, mode64);
+         /* ctc1 */
+         p = mkFormR(p, 17, 6, r_src, 31, 0, 0);
+         goto done;
+      }
+   
+      case Min_MfFCSR: {
+         UInt r_dst = iregNo(i->Min.MfFCSR.dst, mode64);
+         /* cfc1 */
+         p = mkFormR(p, 17, 2, r_dst, 31, 0, 0);
+         goto done;
+      }
+   
+      case Min_Call: {
+         MIPSCondCode cond = i->Min.Call.cond;
+         UInt r_dst = 25;  /* using %r25 as address temporary - 
+                     see getRegUsage_MIPSInstr */
+
+         /* jump over the following insns if condition does not hold */
+         if (cond != MIPScc_AL) {
+            /* jmp fwds if !condition */
+            /* don't know how many bytes to jump over yet...
+               make space for a jump instruction + nop!!! and fill in later. */
+            ptmp = p;   /* fill in this bit later */
+            p += 8;  // p += 8
+         }
+
+         /* load target to r_dst */// p += 4|8
+         p = mkLoadImm(p, r_dst, i->Min.Call.target, mode64);
+
+         /* jalr %r_dst */
+         p = mkFormR(p, 0, r_dst, 0, 31, 0, 9); // p += 4
+         p = mkFormR(p, 0, 0, 0, 0, 0, 0);   // p += 4
+
+         /* Fix up the conditional jump, if there was one. */
+         if (cond != MIPScc_AL) {
+            UInt r_src = iregNo(i->Min.Call.src, mode64);
+            Int delta = p - ptmp;
+
+            vassert(delta >= 20 && delta <= 32);
+            /* bc !ct,cf,delta/4 */
+            /* blez r_src, delta/4-1 */
+            vassert(cond == MIPScc_EQ);
+            ptmp = mkFormI(ptmp, 6, r_src, 0, delta / 4 - 1);
+            ptmp = mkFormR(ptmp, 0, 0, 0, 0, 0, 0);
+         }
+         goto done;
+      }
+
+      case Min_XDirect: {
+         /* NB: what goes on here has to be very closely coordinated
+            with the chainXDirect_MIPS and unchainXDirect_MIPS below. */
+         /* We're generating chain-me requests here, so we need to be
+            sure this is actually allowed -- no-redir translations
+            can't use chain-me's.  Hence: */
+         vassert(disp_cp_chain_me_to_slowEP != NULL);
+         vassert(disp_cp_chain_me_to_fastEP != NULL);
+
+         /* Use ptmp for backpatching conditional jumps. */
+         ptmp = NULL;
+
+         /* First off, if this is conditional, create a conditional
+            jump over the rest of it.  Or at least, leave a space for
+            it that we will shortly fill in. */
+         if (i->Min.XDirect.cond != MIPScc_AL) {
+            vassert(i->Min.XDirect.cond != MIPScc_NV);
+            ptmp = p;
+            p += 12;
+         }
+
+         /* Update the guest PC. */
+         /* move r9, dstGA */
+         /* sw r9, amPC */
+         p = mkLoadImm_EXACTLY2or5(p, /*r*/9,
+                                  (ULong)i->Min.XDirect.dstGA, mode64);
+         p = do_load_or_store_machine_word(p, False/*!isLoad*/,
+                                /*r*/9, i->Min.XDirect.amPC, mode64);
+
+         /* --- FIRST PATCHABLE BYTE follows --- */
+         /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're
+            calling to) backs up the return address, so as to find the
+            address of the first patchable byte.  So: don't change the
+            number of instructions (3) below. */
+         /* move r9, VG_(disp_cp_chain_me_to_{slowEP,fastEP}) */
+         /* jr  r9  */
+         void* disp_cp_chain_me
+                  = i->Min.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP 
+                                              : disp_cp_chain_me_to_slowEP;
+         p = mkLoadImm_EXACTLY2or5(p, /*r*/9,
+                                     Ptr_to_ULong(disp_cp_chain_me), mode64);
+         /* jalr $9 */
+         /* nop */
+         p = mkFormR(p, 0, 9, 0, 31, 0, 9); // p += 4
+         p = mkFormR(p, 0, 0, 0, 0, 0, 0);   // p += 4
+         /* --- END of PATCHABLE BYTES --- */
+
+         /* Fix up the conditional jump, if there was one. */
+         if (i->Min.XDirect.cond != MIPScc_AL) {
+            Int delta = p - ptmp;
+            delta = delta / 4 - 3;
+            vassert(delta > 0 && delta < 40);
+            /* lw $9, 316($10)  // guest_COND
+               beq $9, $0, 2
+               nop*/
+            ptmp = mkFormI(ptmp, 35, 10, 9, 316);
+            ptmp = mkFormI(ptmp, 4, 0, 9, (delta));
+            ptmp = mkFormR(ptmp, 0, 0, 0, 0, 0, 0);
+         }
+         goto done;
+      }
+
+      case Min_XIndir: {
+         /* We're generating transfers that could lead indirectly to a
+            chain-me, so we need to be sure this is actually allowed --
+            no-redir translations are not allowed to reach normal
+            translations without going through the scheduler.  That means
+            no XDirects or XIndirs out from no-redir translations.
+            Hence: */
+         vassert(disp_cp_xindir != NULL);
+
+         /* Use ptmp for backpatching conditional jumps. */
+         ptmp = NULL;
+
+         /* First off, if this is conditional, create a conditional
+            jump over the rest of it. */
+         if (i->Min.XIndir.cond != MIPScc_AL) {
+            vassert(i->Min.XIndir.cond != MIPScc_NV);
+            ptmp = p;
+            p += 12;
+         }
+
+         /* Update the guest PC. */
+         /* sw r-dstGA, amPC */
+         p = do_load_or_store_machine_word(p, False/*!isLoad*/,
+                                           iregNo(i->Min.XIndir.dstGA, mode64),
+                                           i->Min.XIndir.amPC, mode64);
+
+         /* move r9, VG_(disp_cp_xindir) */
+         /* jalr   r9 */
+         /* nop */
+         p = mkLoadImm_EXACTLY2or5 ( p, /*r*/9,
+                                     Ptr_to_ULong(disp_cp_xindir), mode64);
+         p = mkFormR(p, 0, 9, 0, 31, 0, 9); // p += 4
+         p = mkFormR(p, 0, 0, 0, 0, 0, 0);   // p += 4
+
+         /* Fix up the conditional jump, if there was one. */
+         if (i->Min.XIndir.cond != MIPScc_AL) {
+            Int delta = p - ptmp;
+            delta = delta / 4 - 3;
+            vassert(delta > 0 && delta < 40);
+            /* lw $9, 316($10)  // guest_COND
+               beq $9, $0, 2
+               nop*/
+            ptmp = mkFormI(ptmp, 35, 10, 9, 316);
+            ptmp = mkFormI(ptmp, 4, 0, 9, (delta));
+            ptmp = mkFormR(ptmp, 0, 0, 0, 0, 0, 0);
+         }
+         goto done;
+      }
+
+      case Min_XAssisted: {
+         /* First off, if this is conditional, create a conditional jump
+            over the rest of it.  Or at least, leave a space for it that
+            we will shortly fill in. */
+         ptmp = NULL;
+         if (i->Min.XAssisted.cond != MIPScc_AL) {
+            vassert(i->Min.XAssisted.cond != MIPScc_NV);
+            ptmp = p;
+            p += 12;
+         }
+
+         /* Update the guest PC. */
+         /* sw r-dstGA, amPC */
+         p = do_load_or_store_machine_word(p, False/*!isLoad*/,
+                                           iregNo(i->Min.XIndir.dstGA, mode64),
+                                           i->Min.XIndir.amPC, mode64);
+
+         /* imm32/64 r31, $magic_number */
+         UInt trcval = 0;
+         switch (i->Min.XAssisted.jk) {
+            case Ijk_ClientReq:   trcval = VEX_TRC_JMP_CLIENTREQ;   break;
+            case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
+            //case Ijk_Sys_int128:  trcval = VEX_TRC_JMP_SYS_INT128;  break;
+            //case Ijk_Yield:       trcval = VEX_TRC_JMP_YIELD;       break;
+            case Ijk_EmWarn:      trcval = VEX_TRC_JMP_EMWARN;      break;
+            case Ijk_EmFail:      trcval = VEX_TRC_JMP_EMFAIL;      break;
+            //case Ijk_MapFail:     trcval = VEX_TRC_JMP_MAPFAIL;     break;
+            case Ijk_NoDecode:    trcval = VEX_TRC_JMP_NODECODE;    break;
+            case Ijk_TInval:      trcval = VEX_TRC_JMP_TINVAL;      break;
+            case Ijk_NoRedir:     trcval = VEX_TRC_JMP_NOREDIR;     break;
+            case Ijk_SigTRAP:     trcval = VEX_TRC_JMP_SIGTRAP;     break;
+            //case Ijk_SigSEGV:     trcval = VEX_TRC_JMP_SIGSEGV;     break;
+            case Ijk_SigBUS:        trcval = VEX_TRC_JMP_SIGBUS;    break;
+            case Ijk_Boring:      trcval = VEX_TRC_JMP_BORING;      break;
+            /* We don't expect to see the following being assisted. */
+            //case Ijk_Ret:
+            //case Ijk_Call:
+            /* fallthrough */
+            default: 
+               ppIRJumpKind(i->Min.XAssisted.jk);
+               vpanic("emit_MIPSInstr.Min_XAssisted: unexpected jump kind");
+         }
+         vassert(trcval != 0);
+         p = mkLoadImm_EXACTLY2or5(p, /*r*/10, trcval, mode64);
+
+         /* move r9, VG_(disp_cp_xassisted) */
+         p = mkLoadImm_EXACTLY2or5(p, /*r*/9,
+                          (ULong)Ptr_to_ULong(disp_cp_xassisted), mode64);
+         /* jalr $9
+             nop */
+         p = mkFormR(p, 0, 9, 0, 31, 0, 9); // p += 4
+         p = mkFormR(p, 0, 0, 0, 0, 0, 0);   // p += 4
+
+         /* Fix up the conditional jump, if there was one. */
+         if (i->Min.XAssisted.cond != MIPScc_AL) {
+            Int delta = p - ptmp;
+            delta = delta / 4 - 3;
+            vassert(delta > 0 && delta < 40);
+            /* lw $9, 316($10)  // guest_COND
+               beq $9, $0, 2
+               nop*/
+            ptmp = mkFormI(ptmp, 35, 10, 9, 316);
+            ptmp = mkFormI(ptmp, 4, 0, 9, (delta));
+            ptmp = mkFormR(ptmp, 0, 0, 0, 0, 0, 0);
+         }
+         goto done;
+      }
+
+      case Min_Load: {
+         MIPSAMode *am_addr = i->Min.Load.src;
+         if (am_addr->tag == Mam_IR) {
+            UInt r_dst = iregNo(i->Min.Load.dst, mode64);
+            UInt opc, sz = i->Min.Load.sz;
+            if (mode64 && (sz == 4 || sz == 8)) {
+               /* should be guaranteed to us by iselWordExpr_AMode */
+               vassert(0 == (am_addr->Mam.IR.index & 3));
+            }
+            switch (sz) {
+               case 1:
+                  opc = 32;
+                  break;
+               case 2:
+                  opc = 33;
+                  break;
+               case 4:
+                  opc = 35;
+                  break;
+               case 8:
+                  opc = 55;
+                  vassert(mode64);
+                  break;
+                  break;
+               default:
+                  goto bad;
+            }
+
+            p = doAMode_IR(p, opc, r_dst, am_addr, mode64);
+            goto done;
+         } else if (am_addr->tag == Mam_RR) {
+            UInt r_dst = iregNo(i->Min.Load.dst, mode64);
+            UInt opc, sz = i->Min.Load.sz;
+
+            switch (sz) {
+               case 1:
+                  opc = 32;
+                  break;
+               case 2:
+                  opc = 33;
+                  break;
+               case 4:
+                  opc = 35;
+                  break;
+               case 8:
+                  opc = 55;
+                  vassert(mode64);
+                  break;
+                  break;
+               default:
+                  goto bad;
+            }
+
+            p = doAMode_RR(p, opc, r_dst, am_addr, mode64);
+            goto done;
+         }
+         break;
+      }
+   
+      case Min_Store: {
+         MIPSAMode *am_addr = i->Min.Store.dst;
+         if (am_addr->tag == Mam_IR) {
+            UInt r_src = iregNo(i->Min.Store.src, mode64);
+            UInt opc, sz = i->Min.Store.sz;
+            if (mode64 && (sz == 4 || sz == 8)) {
+               /* should be guaranteed to us by iselWordExpr_AMode */
+               vassert(0 == (am_addr->Mam.IR.index & 3));
+            }
+            switch (sz) {
+               case 1:
+                  opc = 40;
+                  break;
+               case 2:
+                  opc = 41;
+                  break;
+               case 4:
+                  opc = 43;
+                  break;
+               case 8:
+                  vassert(mode64);
+                  opc = 63;
+                  break;
+               default:
+                  goto bad;
+            }
+
+            p = doAMode_IR(p, opc, r_src, am_addr, mode64);
+            goto done;
+         } else if (am_addr->tag == Mam_RR) {
+            UInt r_src = iregNo(i->Min.Store.src, mode64);
+            UInt opc, sz = i->Min.Store.sz;
+
+            switch (sz) {
+               case 1:
+                  opc = 40;
+                  break;
+               case 2:
+                  opc = 41;
+                  break;
+               case 4:
+                  opc = 43;
+                  break;
+               case 8:
+                  vassert(mode64);
+                  opc = 63;
+                  break;
+               default:
+                  goto bad;
+            }
+
+            p = doAMode_RR(p, opc, r_src, am_addr, mode64);
+            goto done;
+         }
+         break;
+      }
+      case Min_LoadL: {
+         MIPSAMode *am_addr = i->Min.LoadL.src;
+         UInt r_src = iregNo(am_addr->Mam.IR.base, mode64);
+         UInt idx = am_addr->Mam.IR.index;
+         UInt r_dst = iregNo(i->Min.LoadL.dst, mode64);
+
+         p = mkFormI(p, 0x30, r_src, r_dst, idx);
+         goto done;
+      }
+      case Min_StoreC: {
+         MIPSAMode *am_addr = i->Min.StoreC.dst;
+         UInt r_src = iregNo(i->Min.StoreC.src, mode64);
+         UInt idx = am_addr->Mam.IR.index;
+         UInt r_dst = iregNo(am_addr->Mam.IR.base, mode64);
+
+         p = mkFormI(p, 0x38, r_dst, r_src, idx);
+         goto done;
+      }
+      case Min_RdWrLR: {
+         UInt reg = iregNo(i->Min.RdWrLR.gpr, mode64);
+         Bool wrLR = i->Min.RdWrLR.wrLR;
+         if (wrLR)
+            p = mkMoveReg(p, 31, reg);
+         else
+            p = mkMoveReg(p, reg, 31);
+         goto done;
+      }
+   
+         // Floating point
+   
+      case Min_FpLdSt: {
+         MIPSAMode *am_addr = i->Min.FpLdSt.addr;
+         UChar sz = i->Min.FpLdSt.sz;
+         vassert(sz == 4 || sz == 8);
+         if (sz == 4) {
+            UInt f_reg = fregNo(i->Min.FpLdSt.reg, mode64);
+            if (i->Min.FpLdSt.isLoad) {
+               if (am_addr->tag == Mam_IR)
+                  p = doAMode_IR(p, 0x31, f_reg, am_addr, mode64);
+               else if (am_addr->tag == Mam_RR)
+                  p = doAMode_RR(p, 0x31, f_reg, am_addr, mode64);
+            } else {
+               if (am_addr->tag == Mam_IR)
+                  p = doAMode_IR(p, 0x39, f_reg, am_addr, mode64);
+               else if (am_addr->tag == Mam_RR)
+                  p = doAMode_RR(p, 0x39, f_reg, am_addr, mode64);
+            }
+         } else if (sz == 8) {
+            UInt f_reg = dregNo(i->Min.FpLdSt.reg);
+            if (i->Min.FpLdSt.isLoad) {
+               if (am_addr->tag == Mam_IR) {
+                  if (mode64) {
+                     p = doAMode_IR(p, 0x35, f_reg, am_addr, mode64);
+                  } else {
+                     p = doAMode_IR(p, 0x31, f_reg, am_addr, mode64);
+                     p = doAMode_IR(p, 0x31, f_reg + 1,
+                                   nextMIPSAModeFloat(am_addr), mode64);
+                  }
+               } else if (am_addr->tag == Mam_RR) {
+                  if (mode64) {
+                     p = doAMode_RR(p, 0x35, f_reg, am_addr, mode64);
+                  } else {
+                     p = doAMode_RR(p, 0x31, f_reg, am_addr, mode64);
+                     p = doAMode_RR(p, 0x31, f_reg + 1,
+                                    nextMIPSAModeFloat(am_addr), mode64);
+                  }
+               }
+            } else {
+               if (am_addr->tag == Mam_IR) {
+                  if (mode64) {
+                     p = doAMode_IR(p, 0x3d, f_reg, am_addr, mode64);
+                  } else {
+                     p = doAMode_IR(p, 0x39, f_reg, am_addr, mode64);
+                     p = doAMode_IR(p, 0x39, f_reg + 1,
+                                    nextMIPSAModeFloat(am_addr), mode64);
+                  }
+               } else if (am_addr->tag == Mam_RR) {
+                  if (mode64) {
+                     p = doAMode_RR(p, 0x3d, f_reg, am_addr, mode64);
+                  } else {
+                     p = doAMode_RR(p, 0x39, f_reg, am_addr, mode64);
+                     p = doAMode_RR(p, 0x39, f_reg + 1,
+                                    nextMIPSAModeFloat(am_addr), mode64);
+                  }
+               }
+            }
+         }
+         goto done;
+      }
+
+      case Min_FpUnary: {
+         switch (i->Min.FpUnary.op) {
+            case Mfp_MOVS: { // FP move
+               UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
+               UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
+               p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x6);
+               break;
+            }
+            case Mfp_MOVD: { // FP move
+                UInt fr_dst = dregNo(i->Min.FpUnary.dst);
+                UInt fr_src = dregNo(i->Min.FpUnary.src);
+                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x6);
+                break;
+             }
+            case Mfp_ABSS: { // ABSS
+               UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
+               UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
+               p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x5);
+               break;
+            }
+            case Mfp_ABSD: { // ABSD
+               UInt fr_dst = dregNo(i->Min.FpUnary.dst);
+               UInt fr_src = dregNo(i->Min.FpUnary.src);
+               p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x5);
+               break;
+            }
+            case Mfp_NEGS: { // ABSS
+               UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
+               UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
+               p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x7);
+               break;
+            }
+            case Mfp_NEGD: { // ABSD
+               UInt fr_dst = dregNo(i->Min.FpUnary.dst);
+               UInt fr_src = dregNo(i->Min.FpUnary.src);
+               p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x7);
+               break;
+            }
+            case Mfp_CVTD: { //CVT.D
+               UInt fr_dst = dregNo(i->Min.FpUnary.dst);
+               UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
+               p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x21);
+               break;
+            }
+            case Mfp_SQRTS: { //SQRT.S
+               UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
+               UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
+               p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x04);
+               break;
+            }
+            case Mfp_SQRTD: { //SQRT.D
+               UInt fr_dst = dregNo(i->Min.FpUnary.dst);
+               UInt fr_src = dregNo(i->Min.FpUnary.src);
+               p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x04);
+               break;
+            }
+            case Mfp_RSQRTS: { //RSQRT.S
+                UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
+                UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
+                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x16);
+                break;
+             }
+            case Mfp_RSQRTD: { //RSQRT.D
+               UInt fr_dst = dregNo(i->Min.FpUnary.dst);
+               UInt fr_src = dregNo(i->Min.FpUnary.src);
+               p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x16);
+               break;
+            }
+            case Mfp_RECIPS: { //RECIP.S
+               UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
+               UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
+               p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x15);
+               break;
+            }
+            case Mfp_RECIPD: { //RECIP.D
+               UInt fr_dst = dregNo(i->Min.FpUnary.dst);
+               UInt fr_src = dregNo(i->Min.FpUnary.src);
+               p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x15);
+               break;
+            }
+            default:
+               goto bad;
+         }
+         goto done;
+      }
+
+      case Min_FpBinary: {
+         switch (i->Min.FpBinary.op) {
+            case Mfp_ADDS: {
+               UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64);
+               UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64);
+               UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64);
+               p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 0);
+               break;
+            }
+            case Mfp_SUBS: {
+               UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64);
+               UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64);
+               UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64);
+               p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 1);
+               break;
+            }
+            case Mfp_MULS: {
+               UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64);
+               UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64);
+               UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64);
+               p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 2);
+               break;
+            }
+            case Mfp_DIVS: {
+               UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64);
+               UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64);
+               UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64);
+               p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 3);
+               break;
+            }
+            case Mfp_ADDD: {
+               UInt fr_dst = dregNo(i->Min.FpBinary.dst);
+               UInt fr_srcL = dregNo(i->Min.FpBinary.srcL);
+               UInt fr_srcR = dregNo(i->Min.FpBinary.srcR);
+               p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 0);
+               break;
+            }
+            case Mfp_SUBD: {
+               UInt fr_dst = dregNo(i->Min.FpBinary.dst);
+               UInt fr_srcL = dregNo(i->Min.FpBinary.srcL);
+               UInt fr_srcR = dregNo(i->Min.FpBinary.srcR);
+               p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 1);
+               break;
+            }
+            case Mfp_MULD: {
+               UInt fr_dst = dregNo(i->Min.FpBinary.dst);
+               UInt fr_srcL = dregNo(i->Min.FpBinary.srcL);
+               UInt fr_srcR = dregNo(i->Min.FpBinary.srcR);
+               p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 2);
+               break;
+            }
+            case Mfp_DIVD: {
+               UInt fr_dst = dregNo(i->Min.FpBinary.dst);
+               UInt fr_srcL = dregNo(i->Min.FpBinary.srcL);
+               UInt fr_srcR = dregNo(i->Min.FpBinary.srcR);
+               p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 3);
+               break;
+            }
+            default:
+               goto bad;
+         }
+         goto done;
+      }
+
+      case Min_FpConvert: {
+         switch (i->Min.FpConvert.op) {
+            UInt fr_dst, fr_src;
+            case Mfp_CVTSD:
+               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+               fr_src = dregNo(i->Min.FpConvert.src);
+               p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x20);
+               break;
+            case Mfp_CVTSW:
+               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+               fr_src = fregNo(i->Min.FpConvert.src, mode64);
+               p = mkFormR(p, 0x11, 0x14, 0, fr_src, fr_dst, 0x20);
+               break;
+            case Mfp_CVTWD:
+               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+               fr_src = dregNo(i->Min.FpConvert.src);
+               p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x24);
+               break;
+            case Mfp_CVTWS:
+               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+               fr_src = fregNo(i->Min.FpConvert.src, mode64);
+               p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x24);
+               break;
+            case Mfp_CVTDW:
+               fr_dst = dregNo(i->Min.FpConvert.dst);
+               fr_src = fregNo(i->Min.FpConvert.src, mode64);
+               p = mkFormR(p, 0x11, 0x14, 0, fr_src, fr_dst, 0x21);
+               break;
+            case Mfp_TRUWS:
+               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+               fr_src = fregNo(i->Min.FpConvert.src, mode64);
+               p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0D);
+               break;
+            case Mfp_TRUWD:
+               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+               fr_src = dregNo(i->Min.FpConvert.src);
+               p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0D);
+               break;
+            case Mfp_TRULS:
+               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+               fr_src = dregNo(i->Min.FpConvert.src);
+               p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x09);
+               break;
+            case Mfp_TRULD:
+               fr_dst = dregNo(i->Min.FpConvert.dst);
+               fr_src = dregNo(i->Min.FpConvert.src);
+               p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x09);
+               break;
+            case Mfp_CEILWS:
+               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+               fr_src = fregNo(i->Min.FpConvert.src, mode64);
+               p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0E);
+               break;
+            case Mfp_CEILWD:
+               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+               fr_src = dregNo(i->Min.FpConvert.src);
+               p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0E);
+               break;
+            case Mfp_CEILLS:
+               fr_dst = dregNo(i->Min.FpConvert.dst);
+               fr_src = fregNo(i->Min.FpConvert.src, mode64);
+               p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0A);
+               break;
+            case Mfp_CEILLD:
+               fr_dst = dregNo(i->Min.FpConvert.dst);
+               fr_src = dregNo(i->Min.FpConvert.src);
+               p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0A);
+               break;
+            case Mfp_ROUNDWS:
+               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+               fr_src = fregNo(i->Min.FpConvert.src, mode64);
+               p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0C);
+               break;
+            case Mfp_ROUNDWD:
+               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+               fr_src = dregNo(i->Min.FpConvert.src);
+               p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0C);
+               break;
+            case Mfp_FLOORWS:
+               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+               fr_src = fregNo(i->Min.FpConvert.src, mode64);
+               p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0F);
+               break;
+            case Mfp_FLOORWD:
+               fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
+               fr_src = dregNo(i->Min.FpConvert.src);
+               p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0F);
+               break;
+
+            default:
+               goto bad;
+         }
+         goto done;
+      }
+
+      case Min_FpCompare: {
+         UInt r_dst = iregNo(i->Min.FpCompare.dst, mode64);
+         UInt fr_srcL = dregNo(i->Min.FpCompare.srcL);
+         UInt fr_srcR = dregNo(i->Min.FpCompare.srcR);
+
+         switch (i->Min.FpConvert.op) {
+            case Mfp_CMP:
+               p = mkFormR(p, 0x11, 0x11, fr_srcL, fr_srcR, 0,
+                          (i->Min.FpCompare.cond1 + 48));
+               p = mkFormR(p, 0x11, 0x2, r_dst, 31, 0, 0);
+               break;
+            default:
+               goto bad;
+         }
+         goto done;
+      }
+      case Min_EvCheck: {
+         /* This requires a 32-bit dec/test in 32 mode. */
+         /* We generate:
+               lw      r9, amCounter
+               addiu   r9, r9, -1
+               sw      r9, amCounter
+               bgez    r9, nofail
+               lw      r9, amFailAddr
+               jalr    r9
+               nop
+              nofail:
+         */
+         UChar* p0 = p;
+         /* lw  r9, amCounter */
+         p = do_load_or_store_machine_word(p, True/*isLoad*/, /*r*/9,
+                                     i->Min.EvCheck.amCounter, mode64);
+         /* addiu r9,r9,-1 */
+         p = mkFormI(p, 9, 9, 9, 0xFFFF);
+         /* sw r30, amCounter */
+         p = do_load_or_store_machine_word(p, False/*!isLoad*/, /*r*/9,
+                                     i->Min.EvCheck.amCounter, mode64);
+         /* bgez t9, nofail */
+         p = mkFormI(p, 1, 9, 1, 3);
+         /* lw r9, amFailAddr */
+         p = do_load_or_store_machine_word(p, True/*isLoad*/, /*r*/9,
+                                           i->Min.EvCheck.amFailAddr, mode64);
+         /* jalr $9 */
+         p = mkFormR(p, 0, 9, 0, 31, 0, 9); // p += 4
+         p = mkFormR(p, 0, 0, 0, 0, 0, 0);   // p += 4
+         /* nofail: */
+   
+         /* Crosscheck */
+         vassert(evCheckSzB_MIPS() == (UChar*)p - (UChar*)p0);
+         goto done;
+      }
+
+      case Min_ProfInc: {
+         /* Generate a code template to increment a memory location whose
+            address will be known later as an immediate value. This code
+            template will be patched once the memory location is known.
+            For now we do this with address == 0x65556555. 
+               32-bit:
+
+                 move r9, 0x65556555
+                 lw r8, 0(r9)
+                 addiu r8, r8, 1         # add least significant word
+                 sw r8, 0(r9)
+                 sltiu r1, r8, 1         # set carry-in bit
+                 lw r8, 4(r9)
+                 addu r8, r8, r1
+                 sw r8, 4(r9) */
+
+         if (mode64) {
+            vassert(0);
+         } else {
+            // move r9, 0x65556555
+            p = mkLoadImm_EXACTLY2or5(p, /*r*/9, 0x65556555ULL,
+                                      False/*!mode64*/);
+            // lw r8, 0(r9)
+            p = mkFormI(p, 35, 9, 8, 0);
+
+            // addiu r8, r8, 1         # add least significant word
+            p = mkFormI(p, 9, 8, 8, 1);
+
+            // sw r8, 0(r9)
+            p = mkFormI(p, 43, 9, 8, 0);
+
+            // sltiu r1, r8, 1         # set carry-in bit
+            p = mkFormI(p, 11, 8, 1, 1);
+
+            // lw r8, 4(r9)
+            p = mkFormI(p, 35, 9, 8, 4);
+
+            // addu r8, r8, r1
+            p = mkFormR(p, 0, 8, 1, 8, 0, 33);
+
+            // sw r8, 4(r9)
+            p = mkFormI(p, 43, 9, 8, 4);
+
+         }
+         /* Tell the caller .. */
+         vassert(!(*is_profInc));
+         *is_profInc = True;
+         goto done;
+      }
+   
+      default:
+         goto bad;
+
+   }
+
+   bad:
+      vex_printf("\n=> ");
+      ppMIPSInstr(i, mode64);
+      vpanic("emit_MIPSInstr");
+      /*NOTREACHED*/ done:
+      //vassert(p - &buf[0] <= 32);
+      return p - &buf[0];
+}
+
+/* How big is an event check?  See case for Min_EvCheck in
+   emit_MIPSInstr just above.  That crosschecks what this returns, so
+   we can tell if we're inconsistent. */
+Int evCheckSzB_MIPS ( void )
+{
+  UInt kInstrSize = 4;
+  return 7*kInstrSize;
+}
+
+/* NB: what goes on here has to be very closely coordinated with the
+   emitInstr case for XDirect, above. */
+VexInvalRange chainXDirect_MIPS ( void* place_to_chain,
+                                  void* disp_cp_chain_me_EXPECTED,
+                                  void* place_to_jump_to,
+                                  Bool  mode64 )
+{
+   /* What we're expecting to see is:
+        move r9, disp_cp_chain_me_to_EXPECTED
+        jalr r9
+        nop
+      viz
+        <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
+        0x120F809  // jalr r9
+        0x00000000 // nop
+   */
+   UChar* p = (UChar*)place_to_chain;
+   vassert(0 == (3 & (HWord)p));
+   vassert(isLoadImm_EXACTLY2or5(p, /*r*/9,
+                                 (UInt)Ptr_to_ULong(disp_cp_chain_me_EXPECTED),
+                                 mode64));
+   vassert(fetch32(p + (mode64 ? 20 : 8) + 0) == 0x120F809);
+   vassert(fetch32(p + (mode64 ? 20 : 8) + 4) == 0x00000000);
+   /* And what we want to change it to is either:
+          move r9, place_to_jump_to
+          jalr r9
+          nop
+        viz
+          <8 bytes generated by mkLoadImm_EXACTLY2or5>
+          0x120F809  // jalr r9
+          0x00000000 // nop
+
+      The replacement has the same length as the original.
+   */
+
+   p = mkLoadImm_EXACTLY2or5(p, /*r*/9,
+                             Ptr_to_ULong(place_to_jump_to), mode64);
+   p = emit32(p, 0x120F809);
+   p = emit32(p, 0x00000000);
+
+   Int len = p - (UChar*)place_to_chain;
+   vassert(len == (mode64 ? 28 : 16)); /* stay sane */
+   VexInvalRange vir = {(HWord)place_to_chain, len};
+   return vir;
+}
+
+/* NB: what goes on here has to be very closely coordinated with the
+   emitInstr case for XDirect, above. */
+VexInvalRange unchainXDirect_MIPS ( void* place_to_unchain,
+                                    void* place_to_jump_to_EXPECTED,
+                                    void* disp_cp_chain_me,
+                                    Bool  mode64 )
+{
+   /* What we're expecting to see is:
+        move r9, place_to_jump_to_EXPECTED
+        jalr r9
+        nop
+      viz
+        <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
+        0x120F809  // jalr r9
+        0x00000000 // nop
+   */
+   UChar* p = (UChar*)place_to_unchain;
+   vassert(0 == (3 & (HWord)p));
+   vassert(isLoadImm_EXACTLY2or5(p, /*r*/9,
+                                 Ptr_to_ULong(place_to_jump_to_EXPECTED),
+                                 mode64));
+   vassert(fetch32(p + (mode64 ? 20 : 8) + 0) == 0x120F809);
+   vassert(fetch32(p + (mode64 ? 20 : 8) + 4) == 0x00000000);
+   /* And what we want to change it to is:
+        move r9, disp_cp_chain_me
+        jalr r9
+        nop
+      viz
+        <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
+        0x120F809  // jalr r9
+        0x00000000 // nop
+      The replacement has the same length as the original.
+   */
+   p = mkLoadImm_EXACTLY2or5(p, /*r*/9,
+                             Ptr_to_ULong(disp_cp_chain_me), mode64);
+   p = emit32(p, 0x120F809);
+   p = emit32(p, 0x00000000);
+
+   Int len = p - (UChar*)place_to_unchain;
+   vassert(len == (mode64 ? 28 : 16)); /* stay sane */
+   VexInvalRange vir = {(HWord)place_to_unchain, len};
+   return vir;
+}
+
+/* Patch the counter address into a profile inc point, as previously
+   created by the Min_ProfInc case for emit_MIPSInstr. */
+VexInvalRange patchProfInc_MIPS ( void*  place_to_patch,
+                                  ULong* location_of_counter, Bool mode64 )
+{
+   vassert(sizeof(ULong*) == 4);
+   UChar* p = (UChar*)place_to_patch;
+   vassert(0 == (3 & (HWord)p));
+   vassert(isLoadImm_EXACTLY2or5((UChar *)p, /*r*/9, 0x65556555, mode64));
+
+   vassert(fetch32(p + (mode64 ? 20 : 8) + 0) == 0x8D280000);
+   vassert(fetch32(p + (mode64 ? 20 : 8) + 4) == 0x25080001);
+   vassert(fetch32(p + (mode64 ? 20 : 8) + 8) == 0xAD280000);
+   vassert(fetch32(p + (mode64 ? 20 : 8) + 12) == 0x2d010001);
+   vassert(fetch32(p + (mode64 ? 20 : 8) + 16) == 0x8d280004);
+   vassert(fetch32(p + (mode64 ? 20 : 8) + 20) == 0x01014021);
+   vassert(fetch32(p + (mode64 ? 20 : 8) + 24) == 0xad280004);
+
+   p = mkLoadImm_EXACTLY2or5(p, /*r*/9,
+                             Ptr_to_ULong(location_of_counter), mode64);
+
+   VexInvalRange vir = {(HWord)p, 8};
+   return vir;
+}
+
+
+/*---------------------------------------------------------------*/
+/*--- end                                    host_mips_defs.c ---*/
+/*---------------------------------------------------------------*/
diff --git a/priv/host_mips_defs.h b/priv/host_mips_defs.h
new file mode 100644
index 0000000..1431ff5
--- /dev/null
+++ b/priv/host_mips_defs.h
@@ -0,0 +1,753 @@
+
+/*---------------------------------------------------------------*/
+/*--- begin                                  host_mips_defs.h ---*/
+/*---------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2010-2012 RT-RK
+      mips-valgrind@rt-rk.com
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __VEX_HOST_MIPS_DEFS_H
+#define __VEX_HOST_MIPS_DEFS_H
+
+/* Num registers used for function calls */
+#define MIPS_N_REGPARMS 4
+
+/* --------- Registers. --------- */
+
+/* The usual HReg abstraction.
+   There are 32 general purpose regs.
+*/
+
+extern void ppHRegMIPS(HReg, Bool);
+
+extern HReg hregMIPS_GPR0(Bool mode64);   // scratch reg / zero reg
+extern HReg hregMIPS_GPR1(Bool mode64);   // reserved for trap handling 
+extern HReg hregMIPS_GPR2(Bool mode64);   // reserved for trap handling
+extern HReg hregMIPS_GPR3(Bool mode64);
+extern HReg hregMIPS_GPR4(Bool mode64);
+extern HReg hregMIPS_GPR5(Bool mode64);
+extern HReg hregMIPS_GPR6(Bool mode64);
+extern HReg hregMIPS_GPR7(Bool mode64);
+extern HReg hregMIPS_GPR8(Bool mode64);
+extern HReg hregMIPS_GPR9(Bool mode64);
+extern HReg hregMIPS_GPR10(Bool mode64);
+extern HReg hregMIPS_GPR11(Bool mode64);
+extern HReg hregMIPS_GPR12(Bool mode64);
+extern HReg hregMIPS_GPR13(Bool mode64);
+extern HReg hregMIPS_GPR14(Bool mode64);
+extern HReg hregMIPS_GPR15(Bool mode64);
+extern HReg hregMIPS_GPR16(Bool mode64);
+extern HReg hregMIPS_GPR17(Bool mode64);
+extern HReg hregMIPS_GPR18(Bool mode64);
+extern HReg hregMIPS_GPR19(Bool mode64);
+extern HReg hregMIPS_GPR20(Bool mode64);
+extern HReg hregMIPS_GPR21(Bool mode64);
+extern HReg hregMIPS_GPR22(Bool mode64);
+extern HReg hregMIPS_GPR23(Bool mode64);  // GuestStatePtr
+extern HReg hregMIPS_GPR24(Bool mode64);  // reserved for dispatcher
+extern HReg hregMIPS_GPR25(Bool mode64);
+extern HReg hregMIPS_GPR26(Bool mode64);
+extern HReg hregMIPS_GPR27(Bool mode64);
+extern HReg hregMIPS_GPR28(Bool mode64);
+extern HReg hregMIPS_GPR29(Bool mode64);
+extern HReg hregMIPS_GPR30(Bool mode64);
+extern HReg hregMIPS_GPR31(Bool mode64);
+extern HReg hregMIPS_PC(Bool mode64);
+
+extern HReg hregMIPS_HI(Bool mode64);
+extern HReg hregMIPS_LO(Bool mode64);
+
+extern HReg hregMIPS_F0(Bool mode64);
+extern HReg hregMIPS_F1(Bool mode64);
+extern HReg hregMIPS_F2(Bool mode64);
+extern HReg hregMIPS_F3(Bool mode64);
+extern HReg hregMIPS_F4(Bool mode64);
+extern HReg hregMIPS_F5(Bool mode64);
+extern HReg hregMIPS_F6(Bool mode64);
+extern HReg hregMIPS_F7(Bool mode64);
+extern HReg hregMIPS_F8(Bool mode64);
+extern HReg hregMIPS_F9(Bool mode64);
+extern HReg hregMIPS_F10(Bool mode64);
+extern HReg hregMIPS_F11(Bool mode64);
+extern HReg hregMIPS_F12(Bool mode64);
+extern HReg hregMIPS_F13(Bool mode64);
+extern HReg hregMIPS_F14(Bool mode64);
+extern HReg hregMIPS_F15(Bool mode64);
+extern HReg hregMIPS_F16(Bool mode64);
+extern HReg hregMIPS_F17(Bool mode64);
+extern HReg hregMIPS_F18(Bool mode64);
+extern HReg hregMIPS_F19(Bool mode64);
+extern HReg hregMIPS_F20(Bool mode64);
+extern HReg hregMIPS_F21(Bool mode64);
+extern HReg hregMIPS_F22(Bool mode64);
+extern HReg hregMIPS_F23(Bool mode64);
+extern HReg hregMIPS_F24(Bool mode64);
+extern HReg hregMIPS_F25(Bool mode64);
+extern HReg hregMIPS_F26(Bool mode64);
+extern HReg hregMIPS_F27(Bool mode64);
+extern HReg hregMIPS_F28(Bool mode64);
+extern HReg hregMIPS_F29(Bool mode64);
+extern HReg hregMIPS_F30(Bool mode64);
+extern HReg hregMIPS_F31(Bool mode64);
+extern HReg hregMIPS_FIR(void);
+extern HReg hregMIPS_FCCR(void);
+extern HReg hregMIPS_FEXR(void);
+extern HReg hregMIPS_FENR(void);
+extern HReg hregMIPS_FCSR(void);
+extern HReg hregMIPS_COND(void);
+
+extern HReg hregMIPS_D0(void);
+extern HReg hregMIPS_D1(void);
+extern HReg hregMIPS_D2(void);
+extern HReg hregMIPS_D3(void);
+extern HReg hregMIPS_D4(void);
+extern HReg hregMIPS_D5(void);
+extern HReg hregMIPS_D6(void);
+extern HReg hregMIPS_D7(void);
+extern HReg hregMIPS_D8(void);
+extern HReg hregMIPS_D9(void);
+extern HReg hregMIPS_D10(void);
+extern HReg hregMIPS_D11(void);
+extern HReg hregMIPS_D12(void);
+extern HReg hregMIPS_D13(void);
+extern HReg hregMIPS_D14(void);
+extern HReg hregMIPS_D15(void);
+
+#define GuestStatePointer(_mode64)     hregMIPS_GPR10(_mode64)
+
+#define StackFramePointer(_mode64)     hregMIPS_GPR30(_mode64)
+#define LinkRegister(_mode64)          hregMIPS_GPR31(_mode64)
+#define StackPointer(_mode64)          hregMIPS_GPR29(_mode64)
+#define FCSR()                         hregMIPS_FCSR()
+#define COND()                         hregMIPS_COND()
+
+#define HIRegister(_mode64)        hregMIPS_HI(_mode64)
+#define LORegister(_mode64)        hregMIPS_LO(_mode64)
+
+/* a0, a1, a2, a3 */
+#define MIPS_N_ARGREGS 4
+
+/* --------- Condition codes, Intel encoding. --------- */
+typedef enum {
+   MIPScc_EQ = 0,    /* equal */
+   MIPScc_NE = 1,    /* not equal */
+
+   MIPScc_HS = 2,    /* >=u (higher or same) */
+   MIPScc_LO = 3,    /* <u  (lower) */
+
+   MIPScc_MI = 4,    /* minus (negative) */
+   MIPScc_PL = 5,    /* plus (zero or +ve) */
+
+   MIPScc_VS = 6,    /* overflow */
+   MIPScc_VC = 7,    /* no overflow */
+
+   MIPScc_HI = 8,    /* >u   (higher) */
+   MIPScc_LS = 9,    /* <=u  (lower or same) */
+
+   MIPScc_GE = 10,      /* >=s (signed greater or equal) */
+   MIPScc_LT = 11,      /* <s  (signed less than) */
+
+   MIPScc_GT = 12,      /* >s  (signed greater) */
+   MIPScc_LE = 13,      /* <=s (signed less or equal) */
+
+   MIPScc_AL = 14,      /* always (unconditional) */
+   MIPScc_NV = 15    /* never (unconditional): */
+} MIPSCondCode;
+
+extern HChar *showMIPSCondCode(MIPSCondCode);
+
+/* --------- Memory address expressions (amodes). --------- */
+typedef enum {
+   Mam_IR,        /* Immediate (signed 16-bit) + Reg */
+   Mam_RR         /* Reg1 + Reg2 */
+} MIPSAModeTag;
+
+typedef struct {
+   MIPSAModeTag tag;
+   union {
+      struct {
+         HReg base;
+         Int index;
+      } IR;
+      struct {
+         HReg base;
+         HReg index;
+      } RR;
+   } Mam;
+} MIPSAMode;
+
+extern MIPSAMode *MIPSAMode_IR(Int, HReg);
+extern MIPSAMode *MIPSAMode_RR(HReg, HReg);
+
+extern MIPSAMode *dopyMIPSAMode(MIPSAMode *);
+extern MIPSAMode *nextMIPSAModeFloat(MIPSAMode *);
+extern MIPSAMode *nextMIPSAModeInt(MIPSAMode *);
+
+extern void ppMIPSAMode(MIPSAMode *, Bool);
+
+/* --------- Operand, which can be a reg or a u16/s16. --------- */
+/* ("RH" == "Register or Halfword immediate") */
+typedef enum {
+   Mrh_Imm,
+   Mrh_Reg
+} MIPSRHTag;
+
+typedef struct {
+   MIPSRHTag tag;
+   union {
+      struct {
+         Bool syned;
+         UShort imm16;
+      } Imm;
+      struct {
+         HReg reg;
+      } Reg;
+   } Mrh;
+} MIPSRH;
+
+extern void ppMIPSRH(MIPSRH *, Bool);
+
+extern MIPSRH *MIPSRH_Imm(Bool, UShort);
+extern MIPSRH *MIPSRH_Reg(HReg);
+
+/* --- Addressing Mode suitable for VFP --- */
+typedef struct {
+   HReg reg;
+   Int simm11;
+} MIPSAModeV;
+
+extern MIPSAModeV *mkMIPSAModeV(HReg reg, Int simm11);
+
+extern void ppMIPSAModeV(MIPSAModeV *);
+
+/* --------- Reg or imm-8x4 operands --------- */
+/* a.k.a (a very restricted form of) Shifter Operand,
+   in the MIPS parlance. */
+
+typedef enum {
+   MIPSri84_I84 = 5, /* imm8 `ror` (2 * imm4) */
+   MIPSri84_R     /* reg */
+} MIPSRI84Tag;
+
+typedef struct {
+   MIPSRI84Tag tag;
+   union {
+      struct {
+         UShort imm8;
+         UShort imm4;
+      } I84;
+      struct {
+         HReg reg;
+      } R;
+   } MIPSri84;
+} MIPSRI84;
+
+extern MIPSRI84 *MIPSRI84_I84(UShort imm8, UShort imm4);
+extern MIPSRI84 *MIPSRI84_R(HReg);
+
+extern void ppMIPSRI84(MIPSRI84 *);
+
+/* --------- Reg or imm5 operands --------- */
+typedef enum {
+   MIPSri5_I5 = 7,      /* imm5, 1 .. 31 only (no zero!) */
+   MIPSri5_R      /* reg */
+} MIPSRI5Tag;
+
+typedef struct {
+   MIPSRI5Tag tag;
+   union {
+      struct {
+         UInt imm5;
+      } I5;
+      struct {
+         HReg reg;
+      } R;
+   } MIPSri5;
+} MIPSRI5;
+
+extern MIPSRI5 *MIPSRI5_I5(UInt imm5);
+extern MIPSRI5 *MIPSRI5_R(HReg);
+
+extern void ppMIPSRI5(MIPSRI5 *);
+
+/* --------- Instructions. --------- */
+
+/*Tags for operations*/
+
+/* --------- */
+typedef enum {
+   Mun_CLO,
+   Mun_CLZ,
+   Mun_NOP,
+} MIPSUnaryOp;
+
+extern HChar *showMIPSUnaryOp(MIPSUnaryOp);
+/* --------- */
+
+/* --------- */
+
+typedef enum {
+   Malu_INVALID,
+   Malu_ADD, Malu_SUB,
+   Malu_AND, Malu_OR, Malu_NOR, Malu_XOR,
+} MIPSAluOp;
+
+extern HChar *showMIPSAluOp(MIPSAluOp,
+                            Bool /* is the 2nd operand an immediate? */ );
+
+/* --------- */
+typedef enum {
+   Mshft_INVALID,
+   Mshft_SLL, Mshft_SRL,
+   Mshft_SRA
+} MIPSShftOp;
+
+extern HChar *showMIPSShftOp(MIPSShftOp,
+                             Bool /* is the 2nd operand an immediate? */ ,
+                             Bool /* is this a 32bit or 64bit op? */ );
+
+/* --------- */
+typedef enum {
+   Macc_ADD,
+   Macc_SUB
+} MIPSMaccOp;
+
+extern HChar *showMIPSMaccOp(MIPSMaccOp, Bool);
+/* --------- */
+
+/* ----- Instruction tags ----- */
+typedef enum {
+   Min_LI,        /* load word (32/64-bit) immediate (fake insn) */
+   Min_Alu,    /* word add/sub/and/or/xor/nor/others? */
+   Min_Shft,      /* word sll/srl/sra */
+   Min_Unary,     /* clo, clz, nop, neg */
+
+   Min_Cmp,    /* word compare (fake insn) */
+
+   Min_Mul,    /* widening/non-widening multiply */
+   Min_Div,    /* div */
+
+   Min_Call,      /* call to address in register */
+
+   /* The following 5 insns are mandated by translation chaining */
+   Min_XDirect,     /* direct transfer to GA */
+   Min_XIndir,      /* indirect transfer to GA */
+   Min_XAssisted,   /* assisted transfer to GA */
+   Min_EvCheck,     /* Event check */
+   Min_ProfInc,     /* 64-bit profile counter increment */
+
+   Min_RdWrLR,    /* Read/Write Link Register */
+   Min_Mthi,      /* Move to HI from GP register */
+   Min_Mtlo,      /* Move to LO from GP register */
+   Min_Mfhi,      /* Move from HI to GP register */
+   Min_Mflo,      /* Move from LO to GP register */
+   Min_Macc,      /* Multiply and accumulate */
+
+   Min_Load,      /* zero-extending load a 8|16|32 bit value from mem */
+   Min_Store,     /* store a 8|16|32 bit value to mem */
+   Min_LoadL,     /* mips Load Linked Word */
+   Min_StoreC,    /* mips Store Conditional Word */
+
+   Min_FpUnary,      /* FP unary op */
+   Min_FpBinary,     /* FP binary op */
+   Min_FpConvert,    /* FP conversion op */
+   Min_FpMulAcc,     /* FP multipy-accumulate style op */
+   Min_FpLdSt,    /* FP load/store */
+   Min_FpSTFIW,      /* stfiwx */
+   Min_FpRSP,     /* FP round IEEE754 double to IEEE754 single */
+   Min_FpCftI,    /* fcfid/fctid/fctiw */
+   Min_FpCMov,    /* FP floating point conditional move */
+   Min_MtFCSR,    /* set FCSR register */
+   Min_MfFCSR,    /* get FCSR register */
+   Min_FpCompare,    /* FP compare, generating value into int reg */
+   Min_MovCond
+} MIPSInstrTag;
+
+/* --------- */
+typedef enum {
+   Mfp_INVALID,
+
+   /* Ternary */
+   Mfp_MADDD, Mfp_MSUBD,
+   Mfp_MADDS, Mfp_MSUBS,
+
+   /* Binary */
+   Mfp_ADDD, Mfp_SUBD, Mfp_MULD, Mfp_DIVD,
+   Mfp_ADDS, Mfp_SUBS, Mfp_MULS, Mfp_DIVS, Mfp_CVTSD, Mfp_CVTSW, Mfp_CVTWD,
+   Mfp_CVTWS, Mfp_TRULS, Mfp_TRULD, Mfp_TRUWS, Mfp_TRUWD, Mfp_FLOORWS,
+   Mfp_FLOORWD, Mfp_ROUNDWS, Mfp_ROUNDWD, Mfp_CVTDW, Mfp_CMP,
+   Mfp_CEILWS, Mfp_CEILWD, Mfp_CEILLS, Mfp_CEILLD,
+
+   /* Unary */
+   Mfp_SQRTS, Mfp_SQRTD, Mfp_RSQRTS, Mfp_RSQRTD, Mfp_RECIPS, Mfp_RECIPD,
+   Mfp_ABSS, Mfp_ABSD, Mfp_NEGS, Mfp_NEGD, Mfp_MOVS, Mfp_MOVD,
+   Mfp_RES, Mfp_RSQRTE, Mfp_FRIN, Mfp_FRIM, Mfp_FRIP, Mfp_FRIZ, Mfp_CVTD
+} MIPSFpOp;
+
+extern HChar *showMIPSFpOp(MIPSFpOp);
+
+/*--------- Structure for instructions ----------*/
+/* Destinations are on the LEFT (first operand) */
+
+typedef struct {
+   MIPSInstrTag tag;
+   union {
+      /* Get a 32/64-bit literal into a register.
+         May turn into a number of real insns. */
+      struct {
+         HReg dst;
+         ULong imm;
+      } LI;
+      /* Integer add/sub/and/or/xor.  Limitations:
+         - For add, the immediate, if it exists, is a signed 16.
+         - For sub, the immediate, if it exists, is a signed 16
+         which may not be -32768, since no such instruction 
+         exists, and so we have to emit addi with +32768, but 
+         that is not possible.
+         - For and/or/xor,  the immediate, if it exists, 
+         is an unsigned 16.
+       */
+      struct {
+         MIPSAluOp op;
+         HReg dst;
+         HReg srcL;
+         MIPSRH *srcR;
+      } Alu;
+      /* Integer shl/shr/sar.
+         Limitations: the immediate, if it exists,
+         is a signed 5-bit value between 1 and 31 inclusive.
+       */
+      struct {
+         MIPSShftOp op;
+         Bool sz32;  /* mode64 has both 32 and 64bit shft */
+         HReg dst;
+         HReg srcL;
+         MIPSRH *srcR;
+      } Shft;
+      /* Clz, Clo, nop */
+      struct {
+         MIPSUnaryOp op;
+         HReg dst;
+         HReg src;
+      } Unary;
+      /* Word compare. Fake instruction, used for basic block ending */
+      struct {
+         Bool syned;
+         Bool sz32;
+         HReg dst;
+         HReg srcL;
+         HReg srcR;
+
+         MIPSCondCode cond;
+      } Cmp;
+      struct {
+         Bool widening; //True => widening, False => non-widening
+         Bool syned; //signed/unsigned - meaningless if widenind = False
+         Bool sz32;
+         HReg dst;
+         HReg srcL;
+         HReg srcR;
+      } Mul;
+      struct {
+         Bool syned; //signed/unsigned - meaningless if widenind = False
+         Bool sz32;
+         HReg srcL;
+         HReg srcR;
+      } Div;
+      /* Pseudo-insn.  Call target (an absolute address), on given
+         condition (which could be Mcc_ALWAYS).  argiregs indicates
+         which of r3 .. r10 
+         carries argument values for this call,
+         using a bit mask (1<<N is set if rN holds an arg, for N in
+         3 .. 10 inclusive). 
+         If cond is != Mcc_ALWAYS, src is checked.
+         Otherwise, unconditional call */
+      struct {
+         MIPSCondCode cond;
+         Addr32 target;
+         UInt argiregs;
+         HReg src;
+      } Call;
+      /* Update the guest EIP value, then exit requesting to chain
+         to it.  May be conditional.  Urr, use of Addr32 implicitly
+         assumes that wordsize(guest) == wordsize(host). */
+      struct {
+         Addr32      dstGA;    /* next guest address */
+         MIPSAMode*   amPC;    /* amode in guest state for PC */
+         MIPSCondCode cond;     /* can be MIPScc_AL */
+         Bool        toFastEP; /* chain to the slow or fast point? */
+      } XDirect;
+      /* Boring transfer to a guest address not known at JIT time.
+         Not chainable.  May be conditional. */
+      struct {
+         HReg        dstGA;
+         MIPSAMode*   amPC;
+         MIPSCondCode cond; /* can be MIPScc_AL */
+      } XIndir;
+      /* Assisted transfer to a guest address, most general case.
+         Not chainable.  May be conditional. */
+      struct {
+         HReg        dstGA;
+         MIPSAMode*   amPC;
+         MIPSCondCode cond; /* can be MIPScc_AL */
+         IRJumpKind  jk;
+      } XAssisted;
+      /* Zero extending loads.  Dst size is host word size */
+      struct {
+         UChar sz;   /* 1|2|4|8 */
+         HReg dst;
+         MIPSAMode *src;
+      } Load;
+      /* 64/32/16/8 bit stores */
+      struct {
+         UChar sz;   /* 1|2|4|8 */
+         MIPSAMode *dst;
+         HReg src;
+      } Store;
+      struct {
+         UChar sz;   /* 4|8 */
+         HReg dst;
+         MIPSAMode *src;
+      } LoadL;
+      struct {
+         UChar sz;   /* 4|8 */
+         MIPSAMode *dst;
+         HReg src;
+      } StoreC;
+      /* Move from HI/LO register to GP register. */
+      struct {
+         HReg dst;
+      } MfHL;
+
+      /* Move to HI/LO register from GP register. */
+      struct {
+         HReg src;
+      } MtHL;
+
+      /* Read/Write Link Register */
+      struct {
+         Bool wrLR;
+         HReg gpr;
+      } RdWrLR;
+
+      /* MIPS Multiply and accumulate instructions. */
+      struct {
+         MIPSMaccOp op;
+         Bool syned;
+
+         HReg srcL;
+         HReg srcR;
+      } Macc;
+
+      /* MIPS Floating point */
+      struct {
+         MIPSFpOp op;
+         HReg dst;
+         HReg src;
+      } FpUnary;
+      struct {
+         MIPSFpOp op;
+         HReg dst;
+         HReg srcL;
+         HReg srcR;
+      } FpBinary;
+      struct {
+         MIPSFpOp op;
+         HReg dst;
+         HReg srcML;
+         HReg srcMR;
+         HReg srcAcc;
+      } FpMulAcc;
+      struct {
+         Bool isLoad;
+         UChar sz;   /* only 4 (IEEE single) or 8 (IEEE double) */
+         HReg reg;
+         MIPSAMode *addr;
+      } FpLdSt;
+
+      struct {
+         MIPSFpOp op;
+         HReg dst;
+         HReg src;
+      } FpConvert;
+      struct {
+         MIPSFpOp op;
+         HReg dst;
+         HReg srcL;
+         HReg srcR;
+         UChar cond1;
+      } FpCompare;
+      struct {
+         MIPSFpOp op;
+         HReg dst;
+         HReg srcL;
+         MIPSRH *srcR;
+         HReg condR;
+         MIPSCondCode cond;
+      } MovCond;
+      /* Move from GP register to FCSR register. */
+      struct {
+         HReg src;
+      } MtFCSR;
+      /* Move from FCSR register to GP register. */
+      struct {
+         HReg dst;
+      } MfFCSR;
+      struct {
+         MIPSAMode* amCounter;
+         MIPSAMode* amFailAddr;
+      } EvCheck;
+      struct {
+         /* No fields.  The address of the counter to inc is
+            installed later, post-translation, by patching it in,
+            as it is not known at translation time. */
+      } ProfInc;
+
+   } Min;
+} MIPSInstr;
+
+extern MIPSInstr *MIPSInstr_LI(HReg, ULong);
+extern MIPSInstr *MIPSInstr_Alu(MIPSAluOp, HReg, HReg, MIPSRH *);
+extern MIPSInstr *MIPSInstr_Shft(MIPSShftOp, Bool sz32, HReg, HReg, MIPSRH *);
+extern MIPSInstr *MIPSInstr_Unary(MIPSUnaryOp op, HReg dst, HReg src);
+extern MIPSInstr *MIPSInstr_Cmp(Bool, Bool, HReg, HReg, HReg, MIPSCondCode);
+
+extern MIPSInstr *MIPSInstr_Mul(Bool syned, Bool hi32, Bool sz32, HReg,
+                                HReg, HReg);
+extern MIPSInstr *MIPSInstr_Div(Bool syned, Bool sz32, HReg, HReg);
+extern MIPSInstr *MIPSInstr_Madd(Bool, HReg, HReg);
+extern MIPSInstr *MIPSInstr_Msub(Bool, HReg, HReg);
+
+extern MIPSInstr *MIPSInstr_Load(UChar sz, HReg dst, MIPSAMode * src,
+                                 Bool mode64);
+extern MIPSInstr *MIPSInstr_Store(UChar sz, MIPSAMode * dst, HReg src,
+                                  Bool mode64);
+
+extern MIPSInstr *MIPSInstr_LoadL(UChar sz, HReg dst, MIPSAMode * src,
+                                  Bool mode64);
+extern MIPSInstr *MIPSInstr_StoreC(UChar sz, MIPSAMode * dst, HReg src,
+                                   Bool mode64);
+
+extern MIPSInstr *MIPSInstr_Call(MIPSCondCode, Addr32, UInt, HReg);
+extern MIPSInstr *MIPSInstr_CallAlways(MIPSCondCode, Addr32, UInt);
+
+extern MIPSInstr *MIPSInstr_XDirect(Addr32 dstGA, MIPSAMode* amPC,
+                                     MIPSCondCode cond, Bool toFastEP);
+extern MIPSInstr *MIPSInstr_XIndir(HReg dstGA, MIPSAMode* amPC,
+                                     MIPSCondCode cond);
+extern MIPSInstr *MIPSInstr_XAssisted(HReg dstGA, MIPSAMode* amPC,
+                                      MIPSCondCode cond, IRJumpKind jk);
+
+extern MIPSInstr *MIPSInstr_FpUnary(MIPSFpOp op, HReg dst, HReg src);
+extern MIPSInstr *MIPSInstr_FpBinary(MIPSFpOp op, HReg dst, HReg srcL,
+                                     HReg srcR);
+extern MIPSInstr *MIPSInstr_FpConvert(MIPSFpOp op, HReg dst, HReg src);
+extern MIPSInstr *MIPSInstr_FpCompare(MIPSFpOp op, HReg dst, HReg srcL,
+                  HReg srcR, UChar cond1);
+extern MIPSInstr *MIPSInstr_FpMulAcc(MIPSFpOp op, HReg dst, HReg srcML,
+                                     HReg srcMR, HReg srcAcc);
+extern MIPSInstr *MIPSInstr_FpLdSt(Bool isLoad, UChar sz, HReg, MIPSAMode *);
+extern MIPSInstr *MIPSInstr_FpSTFIW(HReg addr, HReg data);
+extern MIPSInstr *MIPSInstr_FpRSP(HReg dst, HReg src);
+extern MIPSInstr *MIPSInstr_FpCftI(Bool fromI, Bool int32, HReg dst, HReg src);
+extern MIPSInstr *MIPSInstr_FpCMov(MIPSCondCode, HReg dst, HReg src);
+extern MIPSInstr *MIPSInstr_MtFCSR(HReg src);
+extern MIPSInstr *MIPSInstr_MfFCSR(HReg dst);
+extern MIPSInstr *MIPSInstr_FpCmp(HReg dst, HReg srcL, HReg srcR);
+
+extern MIPSInstr *MIPSInstr_Mfhi(HReg dst);
+extern MIPSInstr *MIPSInstr_Mflo(HReg dst);
+extern MIPSInstr *MIPSInstr_Mthi(HReg src);
+extern MIPSInstr *MIPSInstr_Mtlo(HReg src);
+
+extern MIPSInstr *MIPSInstr_RdWrLR(Bool wrLR, HReg gpr);
+
+// srcL will be copied if !condR
+extern MIPSInstr *MIPSInstr_MovCond(HReg dst, HReg srcL, MIPSRH * src,
+                                    HReg condR, MIPSCondCode cond);
+
+extern MIPSInstr *MIPSInstr_EvCheck(MIPSAMode* amCounter,
+                                    MIPSAMode* amFailAddr );
+extern MIPSInstr *MIPSInstr_ProfInc( void );
+
+extern void ppMIPSInstr(MIPSInstr *, Bool mode64);
+
+/* Some functions that insulate the register allocator from details
+   of the underlying instruction set. */
+extern void       getRegUsage_MIPSInstr (HRegUsage *, MIPSInstr *, Bool);
+extern void       mapRegs_MIPSInstr     (HRegRemap *, MIPSInstr *, Bool mode64);
+extern Bool       isMove_MIPSInstr      (MIPSInstr *, HReg *, HReg *);
+extern Int        emit_MIPSInstr        (/*MB_MOD*/Bool* is_profInc,
+                                         UChar* buf, Int nbuf, MIPSInstr* i,
+                                         Bool mode64,
+                                         void* disp_cp_chain_me_to_slowEP,
+                                         void* disp_cp_chain_me_to_fastEP,
+                                         void* disp_cp_xindir,
+                                         void* disp_cp_xassisted );
+
+extern void genSpill_MIPS ( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2,
+                            HReg rreg, Int offset, Bool);
+extern void genReload_MIPS( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2,
+                            HReg rreg, Int offset, Bool);
+
+extern void        getAllocableRegs_MIPS (Int *, HReg **, Bool mode64);
+extern HInstrArray *iselSB_MIPS          ( IRSB*,
+                                           VexArch,
+                                           VexArchInfo*,
+                                           VexAbiInfo*,
+                                           Int offs_Host_EvC_Counter,
+                                           Int offs_Host_EvC_FailAddr,
+                                           Bool chainingAllowed,
+                                           Bool addProfInc,
+                                           Addr64 max_ga );
+
+/* How big is an event check?  This is kind of a kludge because it
+   depends on the offsets of host_EvC_FAILADDR and host_EvC_COUNTER,
+   and so assumes that they are both <= 128, and so can use the short
+   offset encoding.  This is all checked with assertions, so in the
+   worst case we will merely assert at startup. */
+extern Int evCheckSzB_MIPS ( void );
+
+/* Perform a chaining and unchaining of an XDirect jump. */
+extern VexInvalRange chainXDirect_MIPS ( void* place_to_chain,
+                                         void* disp_cp_chain_me_EXPECTED,
+                                         void* place_to_jump_to,
+                                         Bool  mode64 );
+
+extern VexInvalRange unchainXDirect_MIPS ( void* place_to_unchain,
+                                           void* place_to_jump_to_EXPECTED,
+                                           void* disp_cp_chain_me,
+                                           Bool  mode64 );
+
+/* Patch the counter location into an existing ProfInc point. */
+extern VexInvalRange patchProfInc_MIPS ( void*  place_to_patch,
+                                         ULong* location_of_counter,
+                                         Bool  mode64 );
+
+#endif            /* ndef __LIBVEX_HOST_MIPS_HDEFS_H */
+
+/*---------------------------------------------------------------*/
+/*--- end                                    host-mips_defs.h ---*/
+/*---------------------------------------------------------------*/
diff --git a/priv/host_mips_isel.c b/priv/host_mips_isel.c
new file mode 100644
index 0000000..ebda3df
--- /dev/null
+++ b/priv/host_mips_isel.c
@@ -0,0 +1,3262 @@
+
+/*---------------------------------------------------------------*/
+/*--- begin                                   host_mips_isel.c ---*/
+/*---------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2010-2012 RT-RK
+      mips-valgrind@rt-rk.com
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "libvex_basictypes.h"
+#include "libvex_ir.h"
+#include "libvex.h"
+
+#include "main_util.h"
+#include "main_globals.h"
+#include "host_generic_regs.h"
+#include "host_mips_defs.h"
+
+/*---------------------------------------------------------*/
+/*--- Register Usage Conventions                        ---*/
+/*---------------------------------------------------------*/
+/*
+
+Integer Regs
+------------
+ZERO0       Reserved
+GPR1:9      Allocateable
+10          GuestStatePointer
+GPR1:9      Allocateable
+SP          StackFramePointer
+RA          LinkRegister
+
+*/
+
+static Bool mode64 = False;
+
+/* GPR register class for mips32/64 */
+#define HRcGPR(__mode64) (__mode64 ? HRcInt64 : HRcInt32)
+
+/* FPR register class for mips32/64 */
+#define HRcFPR(__mode64) (__mode64 ? HRcFlt64 : HRcFlt32)
+
+/*---------------------------------------------------------*/
+/*--- ISelEnv                                           ---*/
+/*---------------------------------------------------------*/
+
+/* This carries around:
+
+   - A mapping from IRTemp to IRType, giving the type of any IRTemp we
+     might encounter.  This is computed before insn selection starts,
+     and does not change.
+
+   - A mapping from IRTemp to HReg.  This tells the insn selector
+     which virtual register(s) are associated with each IRTemp
+     temporary.  This is computed before insn selection starts, and
+     does not change.  We expect this mapping to map precisely the
+     same set of IRTemps as the type mapping does.
+
+        - vregmap   holds the primary register for the IRTemp.
+        - vregmapHI is only used for 64-bit integer-typed
+             IRTemps.  It holds the identity of a second
+             32-bit virtual HReg, which holds the high half
+             of the value.
+
+   - The code array, that is, the insns selected so far.
+
+   - A counter, for generating new virtual registers.
+
+   - The host subarchitecture we are selecting insns for.  
+     This is set at the start and does not change.
+
+   - A Bool for indicating whether we may generate chain-me
+     instructions for control flow transfers, or whether we must use
+     XAssisted.
+
+   - The maximum guest address of any guest insn in this block.
+     Actually, the address of the highest-addressed byte from any insn
+     in this block.  Is set at the start and does not change.  This is
+     used for detecting jumps which are definitely forward-edges from
+     this block, and therefore can be made (chained) to the fast entry
+     point of the destination, thereby avoiding the destination's
+     event check.
+
+   Note, this is all (well, mostly) host-independent.
+*/
+
+typedef
+   struct {
+      /* Constant -- are set at the start and do not change. */
+      IRTypeEnv*   type_env;
+
+      HReg*        vregmap;
+      HReg*        vregmapHI;
+      Int          n_vregmap;
+
+      UInt         hwcaps;
+      Bool         mode64;
+
+      Bool         chainingAllowed;
+      Addr64       max_ga;
+
+      /* These are modified as we go along. */
+      HInstrArray* code;
+      Int          vreg_ctr;
+   }
+   ISelEnv;
+
+static HReg lookupIRTemp(ISelEnv * env, IRTemp tmp)
+{
+   vassert(tmp >= 0);
+   vassert(tmp < env->n_vregmap);
+   return env->vregmap[tmp];
+}
+
+static void lookupIRTemp64(HReg * vrHI, HReg * vrLO, ISelEnv * env, IRTemp tmp)
+{
+   vassert(tmp >= 0);
+   vassert(tmp < env->n_vregmap);
+   vassert(env->vregmapHI[tmp] != INVALID_HREG);
+   *vrLO = env->vregmap[tmp];
+   *vrHI = env->vregmapHI[tmp];
+}
+
+static void
+lookupIRTempPair(HReg * vrHI, HReg * vrLO, ISelEnv * env, IRTemp tmp)
+{
+   vassert(env->mode64);
+   vassert(tmp >= 0);
+   vassert(tmp < env->n_vregmap);
+   vassert(env->vregmapHI[tmp] != INVALID_HREG);
+   *vrLO = env->vregmap[tmp];
+   *vrHI = env->vregmapHI[tmp];
+}
+
+static void addInstr(ISelEnv * env, MIPSInstr * instr)
+{
+   addHInstr(env->code, instr);
+   if (vex_traceflags & VEX_TRACE_VCODE) {
+      ppMIPSInstr(instr, mode64);
+      vex_printf("\n");
+   }
+}
+
+static HReg newVRegI(ISelEnv * env)
+{
+   HReg reg = mkHReg(env->vreg_ctr, HRcGPR(env->mode64), 
+                     True /*virtual reg */ );
+   env->vreg_ctr++;
+   return reg;
+}
+
+static HReg newVRegD(ISelEnv * env)
+{
+   HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True /*virtual reg */ );
+   env->vreg_ctr++;
+   return reg;
+}
+
+static HReg newVRegF(ISelEnv * env)
+{
+   HReg reg = mkHReg(env->vreg_ctr, HRcFPR(env->mode64), 
+                     True /*virtual reg */ );
+   env->vreg_ctr++;
+   return reg;
+}
+
+static void add_to_sp(ISelEnv * env, UInt n)
+{
+   HReg sp = StackPointer(mode64);
+   vassert(n < 256 && (n % 8) == 0);
+   addInstr(env, MIPSInstr_Alu(Malu_ADD, sp, sp, MIPSRH_Imm(True,
+                                                            toUShort(n))));
+}
+
+static void sub_from_sp(ISelEnv * env, UInt n)
+{
+   HReg sp = StackPointer(mode64);
+   vassert(n < 256 && (n % 8) == 0);
+   addInstr(env, MIPSInstr_Alu(Malu_SUB, sp, sp,
+                               MIPSRH_Imm(True, toUShort(n))));
+}
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Forward declarations                        ---*/
+/*---------------------------------------------------------*/
+
+/* These are organised as iselXXX and iselXXX_wrk pairs.  The
+   iselXXX_wrk do the real work, but are not to be called directly.
+   For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
+   checks that all returned registers are virtual.  You should not
+   call the _wrk version directly.
+*/
+/* 32-bit mode: Compute an I8/I16/I32 into a RH
+                (reg-or-halfword-immediate).
+   It's important to specify whether the immediate is to be regarded
+   as signed or not.  If yes, this will never return -32768 as an
+   immediate; this guaranteed that all signed immediates that are
+   return can have their sign inverted if need be. 
+*/
+static MIPSRH *iselWordExpr_RH_wrk(ISelEnv * env, Bool syned, IRExpr * e);
+static MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e);
+
+/* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter being an immediate in
+   the range 1 .. 31 inclusive.  Used for doing shift amounts. */
+static MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e);
+static MIPSRH *iselWordExpr_RH5u(ISelEnv * env, IRExpr * e);
+
+/* compute an I8/I16/I32 into a GPR*/
+static HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e);
+static HReg iselWordExpr_R(ISelEnv * env, IRExpr * e);
+
+/* compute an I32 into an AMode. */
+static MIPSAMode *iselWordExpr_AMode_wrk(ISelEnv * env, IRExpr * e,
+                                         IRType xferTy);
+static MIPSAMode *iselWordExpr_AMode(ISelEnv * env, IRExpr * e, IRType xferTy);
+
+static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env,
+                              IRExpr * e);
+static void iselInt64Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e);
+
+/* 64-bit mode ONLY: compute an I128 into a GPR64 pair. */
+static void iselInt128Expr_wrk(HReg * rHi, HReg * rLo,
+                               ISelEnv * env, IRExpr * e);
+static void iselInt128Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e);
+
+static MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e);
+static MIPSCondCode iselCondCode(ISelEnv * env, IRExpr * e);
+
+static HReg iselDblExpr_wrk(ISelEnv * env, IRExpr * e);
+static HReg iselDblExpr(ISelEnv * env, IRExpr * e);
+
+static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e);
+static HReg iselFltExpr(ISelEnv * env, IRExpr * e);
+
+static void set_MIPS_rounding_mode(ISelEnv * env, IRExpr * mode)
+{
+   /*
+      rounding mode | MIPS | IR
+      ------------------------
+      to nearest    | 00  | 00
+      to zero       | 01  | 11
+      to +infinity  | 10  | 10
+      to -infinity  | 11  | 01
+    */
+   // rm_MIPS32  = XOR(rm_IR , (rm_IR << 1)) & 2
+   HReg irrm = iselWordExpr_R(env, mode);
+   HReg tmp = newVRegI(env);
+   HReg fcsr_old = newVRegI(env);
+   MIPSAMode *am_addr;
+
+   addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, irrm,
+                                MIPSRH_Imm(False, 1)));
+   addInstr(env, MIPSInstr_Alu(Malu_XOR, tmp, irrm, MIPSRH_Reg(tmp)));
+   addInstr(env, MIPSInstr_Alu(Malu_AND, irrm, tmp, MIPSRH_Imm(False, 3)));
+   /* save old value of FCSR */
+   addInstr(env, MIPSInstr_MfFCSR(fcsr_old));
+   sub_from_sp(env, 8); // Move SP down 4 bytes
+   am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+   //store old FCSR to stack
+   addInstr(env, MIPSInstr_Store(4, am_addr, fcsr_old, mode64));
+
+   //set new value of FCSR
+   addInstr(env, MIPSInstr_MtFCSR(irrm));
+}
+
+static void set_MIPS_rounding_default(ISelEnv * env)
+{
+   HReg fcsr = newVRegI(env);
+   // load as float
+   MIPSAMode *am_addr;
+   am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+   addInstr(env, MIPSInstr_Load(4, fcsr, am_addr, mode64));
+
+   add_to_sp(env, 8);   // Reset SP
+
+   //set new value of FCSR
+   addInstr(env, MIPSInstr_MtFCSR(fcsr));
+}
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Misc helpers                                ---*/
+/*---------------------------------------------------------*/
+
+/* Make an int reg-reg move. */
+static MIPSInstr *mk_iMOVds_RR(HReg r_dst, HReg r_src)
+{
+   vassert(hregClass(r_dst) == hregClass(r_src));
+   vassert(hregClass(r_src) == HRcInt32 || hregClass(r_src) == HRcInt64);
+   return MIPSInstr_Alu(Malu_OR, r_dst, r_src, MIPSRH_Reg(r_src));
+}
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Function call helpers                       ---*/
+/*---------------------------------------------------------*/
+
+/* Used only in doHelperCall.  See big comment in doHelperCall re
+   handling of register-parameter args.  This function figures out
+   whether evaluation of an expression might require use of a fixed
+   register.  If in doubt return True (safe but suboptimal).
+*/
+static Bool mightRequireFixedRegs(IRExpr * e)
+{
+   switch (e->tag) {
+      case Iex_RdTmp:
+      case Iex_Const:
+      case Iex_Get:
+         return False;
+      default:
+         return True;
+   }
+}
+
+/* Load 2*I32 regs to fp reg */
+static HReg mk_LoadRR32toFPR(ISelEnv * env, HReg r_srcHi, HReg r_srcLo)
+{
+   HReg fr_dst = newVRegD(env);
+   MIPSAMode *am_addr0, *am_addr1;
+
+   vassert(hregClass(r_srcHi) == HRcInt32);
+   vassert(hregClass(r_srcLo) == HRcInt32);
+
+   sub_from_sp(env, 16);   // Move SP down 16 bytes
+   am_addr0 = MIPSAMode_IR(0, StackPointer(mode64));
+   am_addr1 = MIPSAMode_IR(8, StackPointer(mode64));
+
+   // store hi,lo as Ity_I32's
+   addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcLo, mode64));
+   addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcHi, mode64));
+
+   // load as float
+   addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, fr_dst, am_addr0));
+
+   add_to_sp(env, 16);  // Reset SP
+   return fr_dst;
+}
+
+/* Do a complete function call.  guard is a Ity_Bit expression
+   indicating whether or not the call happens.  If guard==NULL, the
+   call is unconditional. */
+
+static void doHelperCall(ISelEnv * env, Bool passBBP, IRExpr * guard,
+                         IRCallee * cee, IRExpr ** args)
+{
+   MIPSCondCode cc;
+   HReg argregs[MIPS_N_REGPARMS];
+   HReg tmpregs[MIPS_N_REGPARMS];
+   Bool go_fast;
+   Int n_args, i, argreg;
+   UInt argiregs;
+   ULong target;
+   HReg src = 0;
+
+   /* MIPS O32 calling convention: up to four registers ($a0 ... $a3)
+      are allowed to be used for passing integer arguments. They correspond
+      to regs GPR4 ... GPR7. Note that the cee->regparms field is meaningless 
+      on MIPS host (since we only implement one calling convention) and so we 
+      always ignore it. */
+
+   /* MIPS 64 calling convention: up to four registers ($a0 ... $a7)
+      are allowed to be used for passing integer arguments. They correspond
+      to regs GPR4 ... GPR11. Note that the cee->regparms field is meaningless 
+      on MIPS host (since we only implement one calling convention) and so we 
+      always ignore it. */
+   n_args = 0;
+   for (i = 0; args[i]; i++)
+      n_args++;
+
+   if (MIPS_N_REGPARMS < n_args + (passBBP ? 1 : 0)) {
+      vpanic("doHelperCall(MIPS): cannot currently handle > 4 args");
+   }
+   argregs[0] = hregMIPS_GPR4(mode64);
+   argregs[1] = hregMIPS_GPR5(mode64);
+   argregs[2] = hregMIPS_GPR6(mode64);
+   argregs[3] = hregMIPS_GPR7(mode64);
+   argiregs = 0;
+
+   tmpregs[0] = tmpregs[1] = tmpregs[2] = tmpregs[3] = INVALID_HREG;
+
+   /* First decide which scheme (slow or fast) is to be used.  First
+      assume the fast scheme, and select slow if any contraindications
+      (wow) appear. */
+
+   go_fast = True;
+
+   if (guard) {
+      if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1
+          && guard->Iex.Const.con->Ico.U1 == True) {
+         /* unconditional */
+      } else {
+         /* Not manifestly unconditional -- be conservative. */
+         go_fast = False;
+      }
+   }
+
+   if (go_fast) {
+      for (i = 0; i < n_args; i++) {
+         if (mightRequireFixedRegs(args[i])) {
+            go_fast = False;
+            break;
+         }
+      }
+   }
+
+   /* save GuestStatePointer on the stack */
+   sub_from_sp(env, 8);   // Move SP down 4 bytes
+   addInstr(env, MIPSInstr_Store(4, MIPSAMode_IR(0, StackPointer(mode64)),
+                                    GuestStatePointer(mode64), mode64));
+
+   /* At this point the scheme to use has been established.  Generate
+      code to get the arg values into the argument rregs. */
+   if (go_fast) {
+      /* FAST SCHEME */
+      argreg = 0;
+      if (passBBP) {
+         argiregs |= (1 << (argreg + 4));
+         addInstr(env, mk_iMOVds_RR(argregs[argreg],
+                  GuestStatePointer(mode64)));
+         argreg++;
+      }
+
+      for (i = 0; i < n_args; i++) {
+         vassert(argreg < MIPS_N_REGPARMS);
+         vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32
+                 || typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
+         if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) {
+            argiregs |= (1 << (argreg + 4));
+            addInstr(env, mk_iMOVds_RR(argregs[argreg], iselWordExpr_R(env,
+                     args[i])));
+         } else { // Ity_I64
+            vassert(mode64);
+            argiregs |= (1 << (argreg + 4));
+            addInstr(env, mk_iMOVds_RR(argregs[argreg], iselWordExpr_R(env,
+                     args[i])));
+         }
+         argreg++;
+      }
+      /* Fast scheme only applies for unconditional calls.  Hence: */
+      cc = MIPScc_AL;
+   } else {
+      /* SLOW SCHEME; move via temporaries */
+      argreg = 0;
+      if (passBBP) {
+         /* This is pretty stupid; better to move directly to r3
+            after the rest of the args are done. */
+         tmpregs[argreg] = newVRegI(env);
+         addInstr(env, mk_iMOVds_RR(tmpregs[argreg],
+                  GuestStatePointer(mode64)));
+         argreg++;
+      }
+      for (i = 0; i < n_args; i++) {
+         vassert(argreg < MIPS_N_REGPARMS);
+         vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32
+                 || typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
+         if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) {
+            tmpregs[argreg] = iselWordExpr_R(env, args[i]);
+         } else { // Ity_I64
+            vassert(mode64);
+            tmpregs[argreg] = iselWordExpr_R(env, args[i]);
+         }
+         argreg++;
+      }
+
+      /* Now we can compute the condition.  We can't do it earlier
+         because the argument computations could trash the condition
+         codes.  Be a bit clever to handle the common case where the
+         guard is 1:Bit. */
+      cc = MIPScc_AL;
+      if (guard) {
+         if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1
+             && guard->Iex.Const.con->Ico.U1 == True) {
+            /* unconditional -- do nothing */
+         } else {
+            cc = iselCondCode(env, guard);
+            src = iselWordExpr_R(env, guard);
+         }
+      }
+      /* Move the args to their final destinations. */
+      for (i = 0; i < argreg; i++) {
+         if (tmpregs[i] == INVALID_HREG)  // Skip invalid regs
+            continue;
+         /* None of these insns, including any spill code that might
+            be generated, may alter the condition codes. */
+         argiregs |= (1 << (i + 4));
+         addInstr(env, mk_iMOVds_RR(argregs[i], tmpregs[i]));
+      }
+   }
+
+   target = toUInt(Ptr_to_ULong(cee->addr));
+
+   /* Finally, the call itself. */
+   if (mode64)
+      if (cc == MIPScc_AL) {
+         addInstr(env, MIPSInstr_CallAlways(cc, target, argiregs));
+      } else {
+         addInstr(env, MIPSInstr_Call(cc, target, argiregs, src));
+   } else if (cc == MIPScc_AL) {
+      addInstr(env, MIPSInstr_CallAlways(cc, (Addr32) target, argiregs));
+   } else {
+      addInstr(env, MIPSInstr_Call(cc, (Addr32) target, argiregs, src));
+   }
+   /* restore GuestStatePointer */
+   addInstr(env, MIPSInstr_Load(4, GuestStatePointer(mode64),
+            MIPSAMode_IR(0, StackPointer(mode64)), mode64));
+   add_to_sp(env, 8);  // Reset SP
+}
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Integer expression auxiliaries              ---*/
+/*---------------------------------------------------------*/
+
+/* --------------------- AMODEs --------------------- */
+
+/* Return an AMode which computes the value of the specified
+   expression, possibly also adding insns to the code list as a
+   result.  The expression may only be a word-size one.
+*/
+
+static Bool uInt_fits_in_16_bits(UInt u)
+{
+   Int i = u & 0xFFFF;
+   i <<= 16;
+   i >>= 16;
+   return toBool(u == (UInt) i);
+}
+
+static Bool sane_AMode(ISelEnv * env, MIPSAMode * am)
+{
+   switch (am->tag) {
+      case Mam_IR:
+         return toBool(hregClass(am->Mam.IR.base) == HRcGPR(mode64) &&
+                  hregIsVirtual(am->Mam.IR.base) &&
+                  uInt_fits_in_16_bits(am->Mam.IR.index));
+      case Mam_RR:
+         return toBool(hregClass(am->Mam.RR.base) == HRcGPR(mode64) &&
+                  hregIsVirtual(am->Mam.RR.base) &&
+                  hregClass(am->Mam.RR.index) == HRcGPR(mode64) &&
+                  hregIsVirtual(am->Mam.IR.index));
+      default:
+         vpanic("sane_AMode: unknown mips amode tag");
+   }
+}
+
+static MIPSAMode *iselWordExpr_AMode(ISelEnv * env, IRExpr * e, IRType xferTy)
+{
+   MIPSAMode *am = iselWordExpr_AMode_wrk(env, e, xferTy);
+   vassert(sane_AMode(env, am));
+   return am;
+}
+
+/* DO NOT CALL THIS DIRECTLY ! */
+static MIPSAMode *iselWordExpr_AMode_wrk(ISelEnv * env, IRExpr * e,
+                IRType xferTy)
+{
+   IRType ty = typeOfIRExpr(env->type_env, e);
+   {
+      vassert(ty == Ity_I32);
+
+      /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */
+      if (e->tag == Iex_Binop
+          && e->Iex.Binop.op == Iop_Add32
+          && e->Iex.Binop.arg2->tag == Iex_Const
+          && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32
+          && uInt_fits_in_16_bits(e->Iex.Binop.arg2->Iex.Const.con-> Ico.U32)) {
+         return MIPSAMode_IR((Int) e->Iex.Binop.arg2->Iex.Const.con->Ico.U32,
+                              iselWordExpr_R(env, e->Iex.Binop.arg1));
+      }
+
+      /* Add32(expr,expr) */
+      if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add32) {
+         HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
+         HReg r_idx = iselWordExpr_R(env, e->Iex.Binop.arg2);
+
+         return MIPSAMode_RR(r_idx, r_base);
+      }
+   }
+
+   /* Doesn't match anything in particular.  Generate it into
+      a register and use that. */
+   return MIPSAMode_IR(0, iselWordExpr_R(env, e));
+}
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
+/*---------------------------------------------------------*/
+
+/* Select insns for an integer-typed expression, and add them to the
+   code list.  Return a reg holding the result.  This reg will be a
+   virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
+   want to modify it, ask for a new vreg, copy it in there, and modify
+   the copy.  The register allocator will do its best to map both
+   vregs to the same real register, so the copies will often disappear
+   later in the game.
+
+   This should handle expressions of 64, 32, 16 and 8-bit type.
+   All results are returned in a (mode64 ? 64bit : 32bit) register.
+   For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
+   are arbitrary, so you should mask or sign extend partial values
+   if necessary.
+*/
+static HReg iselWordExpr_R(ISelEnv * env, IRExpr * e)
+{
+   HReg r = iselWordExpr_R_wrk(env, e);
+   /* sanity checks ... */
+
+   vassert(hregClass(r) == HRcGPR(env->mode64));
+   vassert(hregIsVirtual(r));
+   return r;
+}
+
+/* DO NOT CALL THIS DIRECTLY ! */
+static HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e)
+{
+   IRType ty = typeOfIRExpr(env->type_env, e);
+   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I1
+           || ty == Ity_F32 || (ty == Ity_I64 && mode64)
+           || (ty == Ity_I128 && mode64));
+
+   switch (e->tag) {
+      /* --------- TEMP --------- */
+      case Iex_RdTmp:
+         return lookupIRTemp(env, e->Iex.RdTmp.tmp);
+
+      /* --------- LOAD --------- */
+      case Iex_Load: {
+         HReg r_dst = newVRegI(env);
+         MIPSAMode *am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
+
+         if (e->Iex.Load.end != Iend_LE
+             && e->Iex.Load.end != Iend_BE)
+            goto irreducible;
+
+         addInstr(env, MIPSInstr_Load(toUChar(sizeofIRType(ty)),
+                                      r_dst, am_addr, mode64));
+         return r_dst;
+         break;
+      }
+      /* --------- BINARY OP --------- */
+      case Iex_Binop: {
+         MIPSAluOp aluOp;
+         MIPSShftOp shftOp;
+
+         /* Is it an addition or logical style op? */
+         switch (e->Iex.Binop.op) {
+            case Iop_Add32:
+               aluOp = Malu_ADD;
+               break;
+   
+            case Iop_Sub8:
+            case Iop_Sub16:
+            case Iop_Sub32:
+               aluOp = Malu_SUB;
+               break;
+   
+            case Iop_And32:
+            case Iop_And64:
+               aluOp = Malu_AND;
+               break;
+   
+            case Iop_Or32:
+            case Iop_Or64:
+               aluOp = Malu_OR;
+               break;
+   
+            case Iop_Xor32:
+            case Iop_Xor64:
+               aluOp = Malu_XOR;
+               break;
+   
+            default:
+               aluOp = Malu_INVALID;
+               break;
+         }
+
+         /* For commutative ops we assume any literal
+            values are on the second operand. */
+         if (aluOp != Malu_INVALID) {
+            HReg r_dst = newVRegI(env);
+            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
+            MIPSRH *ri_srcR = NULL;
+            /* get right arg into an RH, in the appropriate way */
+            switch (aluOp) {
+               case Malu_ADD:
+               case Malu_SUB:
+                  ri_srcR = iselWordExpr_RH(env, True /*signed */ ,
+                                            e->Iex.Binop.arg2);
+                  break;
+               case Malu_AND:
+               case Malu_OR:
+               case Malu_XOR:
+                  ri_srcR = iselWordExpr_RH(env, False /*unsigned */,
+                                            e->Iex.Binop.arg2);
+                  break;
+               default:
+                  vpanic("iselWordExpr_R_wrk-aluOp-arg2");
+            }
+            addInstr(env, MIPSInstr_Alu(aluOp, r_dst, r_srcL, ri_srcR));
+            return r_dst;
+         }
+
+         /* a shift? */
+         switch (e->Iex.Binop.op) {
+            case Iop_Shl32:
+            case Iop_Shl64:
+               shftOp = Mshft_SLL;
+               break;
+            case Iop_Shr32:
+            case Iop_Shr64:
+               shftOp = Mshft_SRL;
+               break;
+            case Iop_Sar32:
+            case Iop_Sar64:
+               shftOp = Mshft_SRA;
+               break;
+            default:
+               shftOp = Mshft_INVALID;
+               break;
+         }
+
+         /* we assume any literal values are on the second operand. */
+         if (shftOp != Mshft_INVALID) {
+            HReg r_dst = newVRegI(env);
+            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
+            MIPSRH *ri_srcR = NULL;
+            /* get right arg into an RH, in the appropriate way */
+            switch (shftOp) {
+               case Mshft_SLL:
+               case Mshft_SRL:
+               case Mshft_SRA:
+                  ri_srcR = iselWordExpr_RH5u(env, e->Iex.Binop. arg2);
+                  break;
+               default:
+                  vpanic("iselIntExpr_R_wrk-shftOp-arg2");
+            }
+            /* widen the left arg if needed */
+            /*TODO do we need this? */
+            if (ty == Ity_I8 || ty == Ity_I16)
+               goto irreducible;
+            if (ty == Ity_I64) {
+               vassert(mode64);
+               addInstr(env, MIPSInstr_Shft(shftOp, False/*64bit shift */,
+                                            r_dst, r_srcL, ri_srcR));
+            } else {
+               addInstr(env, MIPSInstr_Shft(shftOp, True /*32bit shift */,
+                                            r_dst, r_srcL, ri_srcR));
+            }
+            return r_dst;
+         }
+
+         /* Cmp*32*(x,y) ? */
+         if (e->Iex.Binop.op == Iop_CmpEQ32
+             || e->Iex.Binop.op == Iop_CmpNE32
+             || e->Iex.Binop.op == Iop_CmpNE64
+             || e->Iex.Binop.op == Iop_CmpLT32S
+             || e->Iex.Binop.op == Iop_CmpLT32U
+             || e->Iex.Binop.op == Iop_CmpLT64U
+             || e->Iex.Binop.op == Iop_CmpLE32S
+             || e->Iex.Binop.op == Iop_CmpLE64S
+             || e->Iex.Binop.op == Iop_CmpLT64S
+             || e->Iex.Binop.op == Iop_CmpEQ64) {
+
+            Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
+                         || e->Iex.Binop.op == Iop_CmpLE32S
+                         || e->Iex.Binop.op == Iop_CmpLT64S
+                         || e->Iex.Binop.op == Iop_CmpLE64S);
+            Bool size32;
+            HReg dst = newVRegI(env);
+            HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
+            HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
+
+            MIPSCondCode cc;
+
+            switch (e->Iex.Binop.op) {
+               case Iop_CmpEQ32:
+                  cc = MIPScc_EQ;
+                  size32 = True;
+                  break;
+               case Iop_CmpNE32:
+                  cc = MIPScc_NE;
+                  size32 = True;
+                  break;
+               case Iop_CmpNE64:
+                  cc = MIPScc_NE;
+                  size32 = True;
+                  break;
+               case Iop_CmpLT32S:
+                  cc = MIPScc_LT;
+                  size32 = True;
+                  break;
+               case Iop_CmpLT32U:
+                  cc = MIPScc_LO;
+                  size32 = True;
+                  break;
+               case Iop_CmpLT64U:
+                  cc = MIPScc_LO;
+                  size32 = False;
+                  break;
+               case Iop_CmpLE32S:
+                  cc = MIPScc_LE;
+                  size32 = True;
+                  break;
+               case Iop_CmpLE64S:
+                  cc = MIPScc_LE;
+                  size32 = False;
+                  break;
+               case Iop_CmpLT64S:
+                  cc = MIPScc_LT;
+                  size32 = False;
+                  break;
+               case Iop_CmpEQ64:
+                  cc = MIPScc_EQ;
+                  size32 = False;
+                  break;
+               default:
+                  vpanic
+                      ("iselCondCode(mips): CmpXX32 or CmpXX64");
+            }
+
+            addInstr(env, MIPSInstr_Cmp(syned, size32, dst, r1, r2, cc));
+            return dst;
+
+            break;
+
+         }
+
+         if (e->Iex.Binop.op == Iop_Max32U) {
+            /*
+               tmp = argR - argL;
+               dst = argL;
+               bltz tmp,2;
+               dst = argR;
+
+             */
+            HReg argL = iselWordExpr_R(env, e->Iex.Binop.arg1);
+            MIPSRH *argR = iselWordExpr_RH(env, False /*signed */ ,
+                                           e->Iex.Binop.arg2);
+            HReg dst = newVRegI(env);
+            HReg tmp = newVRegI(env);
+            addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp, argL, argR));
+            addInstr(env, MIPSInstr_MovCond(dst, argL, argR, tmp, MIPScc_MI));
+
+            return dst;
+         }
+
+         if (e->Iex.Binop.op == Iop_Mul32 || e->Iex.Binop.op == Iop_Mul64) {
+            Bool sz32 = (e->Iex.Binop.op == Iop_Mul32);
+            HReg r_dst = newVRegI(env);
+            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
+            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
+            addInstr(env, MIPSInstr_Mul(False/*Unsigned or Signed */ ,
+                                       False /*widen */ ,
+                                       sz32 /*32bit or 64bit */,
+                                       r_dst, r_srcL, r_srcR));
+            return r_dst;
+         }
+
+         if (e->Iex.Binop.op == Iop_MullU32 || e->Iex.Binop.op == Iop_MullS32) {
+            HReg r_dst = newVRegI(env);
+            HReg tHi = newVRegI(env);
+            HReg tLo = newVRegI(env);
+            HReg tLo_1 = newVRegI(env);
+            HReg tHi_1 = newVRegI(env);
+            HReg mask = newVRegI(env);
+
+            Bool syned = toBool(e->Iex.Binop.op == Iop_MullS32);
+            Bool size = toBool(e->Iex.Binop.op == Iop_MullS32)
+                        || toBool(e->Iex.Binop.op == Iop_MullU32);
+            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
+            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
+            addInstr(env, MIPSInstr_Mul(syned /*Unsigned or Signed */ ,
+                                        True /*widen */ ,
+                                        size /*32bit or 64bit mul */ ,
+                                        r_dst, r_srcL, r_srcR));
+
+            addInstr(env, MIPSInstr_Mfhi(tHi));
+            addInstr(env, MIPSInstr_Mflo(tLo));
+
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1,
+                          tHi, MIPSRH_Imm(False, 32)));
+
+            addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
+            addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
+                          MIPSRH_Reg(mask)));
+
+            addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
+                          MIPSRH_Reg(tLo_1)));
+
+            return r_dst;
+         }
+
+         if (e->Iex.Binop.op == Iop_CmpF64) {
+            HReg r_srcL, r_srcR;
+            {
+               r_srcL = iselDblExpr(env, e->Iex.Binop.arg1);
+               r_srcR = iselDblExpr(env, e->Iex.Binop.arg2);
+            }
+            HReg tmp = newVRegI(env);
+            HReg r_ccMIPS = newVRegI(env);
+            HReg r_ccIR = newVRegI(env);
+            HReg r_ccIR_b0 = newVRegI(env);
+            HReg r_ccIR_b2 = newVRegI(env);
+            HReg r_ccIR_b6 = newVRegI(env);
+
+            /* Create in dst, the IRCmpF64Result encoded result. */
+            // chech for EQ
+            addInstr(env, MIPSInstr_FpCompare(Mfp_CMP, tmp, r_srcL, r_srcR,
+                                              toUChar(2)));
+            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, r_ccMIPS, tmp,
+                                         MIPSRH_Imm(False, 22)));
+            // chech for UN
+            addInstr(env, MIPSInstr_FpCompare(Mfp_CMP, tmp, r_srcL, r_srcR,
+                                              toUChar(1)));
+            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, tmp,
+                                        MIPSRH_Imm(False, 23)));
+            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
+                                        MIPSRH_Reg(tmp)));
+            // chech for LT
+            addInstr(env, MIPSInstr_FpCompare(Mfp_CMP, tmp, r_srcL, r_srcR,
+                                              toUChar(12)));
+            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp,
+                                         tmp, MIPSRH_Imm(False, 21)));
+            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
+                                        MIPSRH_Reg(tmp)));
+            // chech for GT
+            addInstr(env, MIPSInstr_FpCompare(Mfp_CMP, tmp, r_srcL, r_srcR,
+                                              toUChar(15)));
+            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, tmp,
+                                         MIPSRH_Imm(False, 20)));
+
+            addInstr(env, MIPSInstr_Alu(Malu_NOR, tmp, tmp, MIPSRH_Reg(tmp)));
+            addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp,
+                                        MIPSRH_Imm(False, 8)));
+            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
+                                        MIPSRH_Reg(tmp)));
+            /* Map compare result from PPC to IR,
+               conforming to CmpF64 definition. */
+            /*
+               FP cmp result | MIPS | IR
+               --------------------------
+               UN            | 0x1 | 0x45
+               EQ            | 0x2 | 0x40
+               GT            | 0x4 | 0x00
+               LT            | 0x8 | 0x01
+             */
+
+            // r_ccIR_b0 = r_ccPPC[0] | r_ccPPC[3]
+            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True, r_ccIR_b0, r_ccMIPS,
+                          MIPSRH_Imm(False, 0x3)));
+            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR_b0, r_ccMIPS,
+                          MIPSRH_Reg(r_ccIR_b0)));
+            addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b0, r_ccIR_b0,
+                          MIPSRH_Imm(False, 0x1)));
+
+            // r_ccIR_b2 = r_ccPPC[0]
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccIR_b2, r_ccMIPS,
+                          MIPSRH_Imm(False, 0x2)));
+            addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b2, r_ccIR_b2,
+                          MIPSRH_Imm(False, 0x4)));
+
+            // r_ccIR_b6 = r_ccPPC[0] | r_ccPPC[1]
+            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True, r_ccIR_b6,
+                          r_ccMIPS, MIPSRH_Imm(False, 0x1)));
+            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR_b6, r_ccMIPS,
+                          MIPSRH_Reg(r_ccIR_b6)));
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccIR_b6, r_ccIR_b6,
+                          MIPSRH_Imm(False, 0x6)));
+            addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b6, r_ccIR_b6,
+                          MIPSRH_Imm(False, 0x40)));
+
+            // r_ccIR = r_ccIR_b0 | r_ccIR_b2 | r_ccIR_b6
+            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR, r_ccIR_b0,
+                          MIPSRH_Reg(r_ccIR_b2)));
+            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR, r_ccIR,
+                          MIPSRH_Reg(r_ccIR_b6)));
+            return r_ccIR;
+         }
+
+         if (e->Iex.Binop.op == Iop_DivModU64to32 ||
+             e->Iex.Binop.op == Iop_DivModS64to32) {
+            HReg tLo = newVRegI(env);
+            HReg tHi = newVRegI(env);
+            HReg mask = newVRegI(env);
+            HReg tLo_1 = newVRegI(env);
+            HReg tHi_1 = newVRegI(env);
+            HReg r_dst = newVRegI(env);
+            Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS64to32);
+
+            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
+            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
+
+            addInstr(env, MIPSInstr_Div(syned, True, r_srcL, r_srcR));
+            addInstr(env, MIPSInstr_Mfhi(tHi));
+            addInstr(env, MIPSInstr_Mflo(tLo));
+
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1, tHi,
+                                         MIPSRH_Imm(False, 32)));
+
+            addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
+            addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
+                          MIPSRH_Reg(mask)));
+
+            addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
+                          MIPSRH_Reg(tLo_1)));
+
+            return r_dst;
+         }
+
+         if (e->Iex.Binop.op == Iop_32HLto64) {
+            vassert(mode64);
+            HReg tHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
+            HReg tLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
+            HReg tLo_1 = newVRegI(env);
+            HReg tHi_1 = newVRegI(env);
+            HReg r_dst = newVRegI(env);
+            HReg mask = newVRegI(env);
+
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1, tHi,
+                                         MIPSRH_Imm(False, 32)));
+
+            addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
+            addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
+                          MIPSRH_Reg(mask)));
+            addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
+                          MIPSRH_Reg(tLo_1)));
+
+            return r_dst;
+         }
+      }
+
+      /* --------- UNARY OP --------- */
+   case Iex_Unop: {
+      IROp op_unop = e->Iex.Unop.op;
+
+      switch (op_unop) {
+         case Iop_1Sto32:
+         case Iop_8Sto32:
+         case Iop_16Sto32:
+         case Iop_16Sto64:
+         case Iop_8Sto64:
+         case Iop_1Sto64: {
+            HReg r_dst = newVRegI(env);
+            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+            Bool sz32;
+            UShort amt;
+            switch (op_unop) {
+               case Iop_1Sto32:
+                  amt = 31;
+                  sz32 = True;
+                  break;
+               case Iop_16Sto32:
+                  amt = 16;
+                  sz32 = True;
+                  break;
+               case Iop_16Sto64:
+                  amt = 48;
+                  sz32 = False;
+                  break;
+               case Iop_8Sto32:
+                  amt = 24;
+                  sz32 = True;
+                  break;
+               case Iop_8Sto64:
+                  amt = 56;
+                  sz32 = False;
+                  break;
+               case Iop_1Sto64:
+                  amt = 63;
+                  sz32 = False;
+                  break;
+               default:
+                  vassert(0);
+            }
+
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, sz32, r_dst, r_src,
+                                         MIPSRH_Imm(False, amt)));
+            addInstr(env, MIPSInstr_Shft(Mshft_SRA, sz32, r_dst, r_dst,
+                                         MIPSRH_Imm(False, amt)));
+            return r_dst;
+         }
+
+         /*not(x) = nor(x,x) */
+         case Iop_Not1: {
+            HReg r_dst = newVRegI(env);
+            HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
+            MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
+
+            addInstr(env, MIPSInstr_LI(r_dst, 0x1));
+            addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, r_dst, r_srcR));
+            return r_dst;
+         }
+
+         case Iop_Not32:
+         case Iop_Not64: {
+            HReg r_dst = newVRegI(env);
+            HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
+            MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
+
+            addInstr(env, MIPSInstr_Alu(Malu_NOR, r_dst, r_srcL, r_srcR));
+            return r_dst;
+         }
+
+         case Iop_ReinterpF32asI32: {
+            MIPSAMode *am_addr;
+            HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
+            HReg r_dst = newVRegI(env);
+
+            sub_from_sp(env, 16);   // Move SP down 16 bytes
+            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+            // store as F32
+            addInstr(env, MIPSInstr_FpLdSt(False/*store */ , 4, fr_src,
+                                           am_addr));
+            // load as Ity_I32
+            addInstr(env, MIPSInstr_Load(4, r_dst, am_addr, mode64));
+
+            add_to_sp(env, 16);  // Reset SP
+            return r_dst;
+         }
+
+         case Iop_ReinterpF64asI64: {
+            vassert(mode64);
+            MIPSAMode *am_addr;
+            HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
+            HReg r_dst = newVRegI(env);
+
+            sub_from_sp(env, 16);   // Move SP down 16 bytes
+            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+            // store as F64
+            addInstr(env, MIPSInstr_FpLdSt(False/*store */ , 8, fr_src,
+                                           am_addr));
+            // load as Ity_I64
+            addInstr(env, MIPSInstr_Load(8, r_dst, am_addr, mode64));
+
+            add_to_sp(env, 16);  // Reset SP
+            return r_dst;
+         }
+   
+         case Iop_F64toI32S: {
+            HReg valD = iselDblExpr(env, e->Iex.Binop.arg2);
+            HReg valS = newVRegF(env);
+            HReg r_dst = newVRegI(env);
+            MIPSAMode *am_addr;
+
+            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
+            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWD, valS, valD));
+            set_MIPS_rounding_default(env);
+
+            sub_from_sp(env, 16);   // Move SP down 16 bytes
+            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+            // store as F32
+            addInstr(env, MIPSInstr_FpLdSt(False/*store */ , 4, valS, am_addr));
+            // load as I32                              
+            addInstr(env, MIPSInstr_Load(4, r_dst, am_addr, mode64));
+
+            add_to_sp(env, 16);  // Reset SP
+
+            return r_dst;
+         }
+
+         case Iop_32to8:
+         case Iop_32to16:
+            return iselWordExpr_R(env, e->Iex.Unop.arg);
+
+         case Iop_64to8: {
+            vassert(mode64);
+            HReg r_src, r_dst;
+            r_dst = newVRegI(env);
+            r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+            addInstr(env, MIPSInstr_Alu(Malu_AND, r_dst, r_src,
+                          MIPSRH_Imm(False, 0xFF)));
+            return r_dst;
+         }
+   
+         case Iop_16Uto32:
+         case Iop_8Uto32:
+         case Iop_1Uto32: {
+            HReg r_dst = newVRegI(env);
+            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+            UShort amt;
+            switch (op_unop) {
+               case Iop_1Uto32:
+               case Iop_1Uto8:
+                  amt = 31;
+                  break;
+   
+               case Iop_16Uto32:
+                  amt = 16;
+                  break;
+   
+               default:
+                  amt = 24;
+                  break;
+            }
+
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_dst, r_src,
+                          MIPSRH_Imm(False, amt)));
+            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True, r_dst, r_dst,
+                          MIPSRH_Imm(False, amt)));
+            return r_dst;
+         }
+
+         case Iop_8Uto16:
+         case Iop_8Uto64:
+         case Iop_16Uto64: {
+            vassert(mode64);
+            HReg r_dst = newVRegI(env);
+            HReg r_src = iselWordExpr_R(env,  e->Iex.Unop.arg);
+            UShort mask = toUShort(op_unop == Iop_16Uto64 ? 0xFFFF :
+                                   op_unop == Iop_16Uto32 ? 0xFFFF : 0xFF);
+            addInstr(env, MIPSInstr_Alu(Malu_AND, r_dst, r_src,
+                          MIPSRH_Imm(False, mask)));
+            return r_dst;
+         }
+
+         case Iop_32Uto64: {
+            HReg r_dst = newVRegI(env);
+            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+            vassert(mode64);
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, False/*!32bit shift */,
+                                         r_dst, r_src, MIPSRH_Imm(False, 32)));
+            addInstr(env, MIPSInstr_Shft(Mshft_SRL, False/*!32bit shift */,
+                                         r_dst, r_dst, MIPSRH_Imm(False, 32)));
+            return r_dst;
+         }
+
+         case Iop_1Uto64:
+            vassert(mode64);
+            return iselWordExpr_R(env, e->Iex.Unop.arg);
+
+         case Iop_64HIto32: {
+            HReg rHi, rLo;
+            iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
+            return rHi;
+         }
+
+         case Iop_64to32: {
+            HReg rHi, rLo;
+            iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
+            return rLo;
+         }
+   
+         case Iop_64to16: {
+            vassert(env->mode64);
+            HReg r_dst = newVRegI(env);
+            r_dst = iselWordExpr_R(env, e->Iex.Unop.arg);
+            return r_dst;
+         }
+   
+         case Iop_32Sto64: {
+            HReg r_dst = newVRegI(env);
+            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+            vassert(mode64);
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True/*!32bit shift */,
+                                         r_dst, r_src, MIPSRH_Imm(True, 0)));
+            return r_dst;
+         }
+   
+         case Iop_CmpNEZ8: {
+            HReg r_dst = newVRegI(env);
+            HReg tmp = newVRegI(env);
+            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+
+            MIPSCondCode cc;
+
+            cc = MIPScc_NE;
+            addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, r_src,
+                                        MIPSRH_Imm(False, 0xFF)));
+            addInstr(env, MIPSInstr_Cmp(False, True, r_dst, tmp,
+                                        hregMIPS_GPR0(mode64), cc));
+            return r_dst;
+         }
+
+         case Iop_CmpNEZ32: {
+            HReg r_dst = newVRegI(env);
+            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+
+            MIPSCondCode cc;
+
+            cc = MIPScc_NE;
+
+            addInstr(env, MIPSInstr_Cmp(False, True, r_dst, r_src,
+                                        hregMIPS_GPR0(mode64), cc));
+            return r_dst;
+         }
+
+         case Iop_CmpwNEZ32: {
+            HReg r_dst = newVRegI(env);
+            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+
+            addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, hregMIPS_GPR0(mode64),
+                          MIPSRH_Reg(r_src)));
+
+            addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
+                                        MIPSRH_Reg(r_src)));
+            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, r_dst, r_dst,
+                                         MIPSRH_Imm(False, 31)));
+            return r_dst;
+         }
+
+         case Iop_Left8:
+         case Iop_Left32:
+         case Iop_Left64: {
+            if (op_unop == Iop_Left64 && !mode64)
+               goto irreducible;
+            HReg r_dst = newVRegI(env);
+            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+            addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, hregMIPS_GPR0(mode64),
+                          MIPSRH_Reg(r_src)));
+            addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
+                          MIPSRH_Reg(r_src)));
+            return r_dst;
+         }
+
+         case Iop_Clz32: {
+            HReg r_dst = newVRegI(env);
+            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+            addInstr(env, MIPSInstr_Unary(Mun_CLZ, r_dst, r_src));
+            return r_dst;
+         }
+
+         case Iop_CmpNEZ64: {
+            HReg hi, lo;
+            HReg r_dst = newVRegI(env);
+            HReg r_src;
+            r_src = newVRegI(env);
+            iselInt64Expr(&hi, &lo, env, e->Iex.Unop.arg);
+            addInstr(env, MIPSInstr_Alu(Malu_OR, r_src, lo, MIPSRH_Reg(hi)));
+            MIPSCondCode cc;
+
+            cc = MIPScc_NE;
+
+            addInstr(env, MIPSInstr_Cmp(False, !(env->mode64), r_dst, r_src,
+                                        hregMIPS_GPR0(mode64), cc));
+            return r_dst;
+         }
+
+         case Iop_CmpwNEZ64: {
+            HReg tmp1;
+            HReg tmp2 = newVRegI(env);
+            vassert(env->mode64);
+            tmp1 = iselWordExpr_R(env, e->Iex.Unop.arg);
+
+            addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2, hregMIPS_GPR0(mode64),
+                          MIPSRH_Reg(tmp1)));
+
+            addInstr(env, MIPSInstr_Alu(Malu_OR, tmp2, tmp2, MIPSRH_Reg(tmp1)));
+            addInstr(env, MIPSInstr_Shft(Mshft_SRA, False, tmp2, tmp2,
+                                         MIPSRH_Imm (False, 63)));
+            return tmp2;
+         }
+
+         case Iop_128HIto64: {
+            vassert(mode64);
+            HReg rHi, rLo;
+            iselInt128Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
+            return rHi; /* and abandon rLo .. poor wee thing :-) */
+         }
+
+         case Iop_128to64: {
+            vassert(mode64);
+            HReg rHi, rLo;
+            iselInt128Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
+            return rLo; /* and abandon rLo .. poor wee thing :-) */
+         }
+
+         default:
+            break;
+      }
+      break;
+   }
+
+      /* --------- GET --------- */
+   case Iex_Get: {
+      if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32
+          || ((ty == Ity_I64) && mode64)) {
+         HReg r_dst = newVRegI(env);
+
+         MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
+                                           GuestStatePointer(mode64));
+         addInstr(env, MIPSInstr_Load(toUChar(sizeofIRType(ty)), r_dst, am_addr,
+                                      mode64));
+         return r_dst;
+      }
+   }
+
+      /* --------- MULTIPLEX --------- */
+   case Iex_Mux0X: {
+      if ((ty == Ity_I8 || ty == Ity_I16 ||
+           ty == Ity_I32 || ((ty == Ity_I64))) &&
+           typeOfIRExpr(env->type_env, e->Iex.Mux0X.cond) == Ity_I8) {
+         /*
+          * r_dst = cond && rX
+          * cond = not(cond)
+          * tmp = cond && r0
+          * r_dst = tmp + r_dst
+          */
+         HReg r0 = iselWordExpr_R(env, e->Iex.Mux0X.expr0);
+         HReg rX = iselWordExpr_R(env, e->Iex.Mux0X.exprX);
+         HReg r_cond = iselWordExpr_R(env, e->Iex.Mux0X.cond);
+         HReg r_dst = newVRegI(env);
+         HReg r_tmp = newVRegI(env);
+         HReg r_tmp1 = newVRegI(env);
+         HReg r_cond_neg = newVRegI(env);
+
+         addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp, r_cond, MIPSRH_Reg(rX)));
+         addInstr(env, MIPSInstr_Alu(Malu_NOR, r_cond_neg, r_cond,
+                       MIPSRH_Reg(r_cond)));
+         addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp1, r_cond_neg,
+                       MIPSRH_Reg(r0)));
+         addInstr(env, MIPSInstr_Alu(Malu_ADD, r_dst, r_tmp,
+                       MIPSRH_Reg(r_tmp1)));
+
+         return r_dst;
+      }
+   }
+
+      /* --------- LITERAL --------- */
+      /* 32/16/8-bit literals */
+   case Iex_Const: {
+      Long l;
+      HReg r_dst = newVRegI(env);
+      IRConst *con = e->Iex.Const.con;
+      switch (con->tag) {
+         case Ico_U64:
+            if (!mode64)
+               goto irreducible;
+            l = (Long) con->Ico.U64;
+            break;
+         case Ico_U32:
+            l = (Long) (Int) con->Ico.U32;
+            break;
+         case Ico_U16:
+            l = (Long) (Int) (Short) con->Ico.U16;
+            break;
+         case Ico_U8:
+            l = (Long) (Int) (Char) con->Ico.U8;
+            break;
+         default:
+            vpanic("iselIntExpr_R.const(mips)");
+      }
+      addInstr(env, MIPSInstr_LI(r_dst, (ULong) l));
+      return r_dst;
+   }
+
+      /* --------- CCALL --------- */
+   case Iex_CCall: {
+      HReg r_dst = newVRegI(env);
+      vassert(ty == e->Iex.CCall.retty);
+
+      /* be very restrictive for now.  Only 32/64-bit ints allowed
+         for args, and 32 bits for return type. */
+      if (e->Iex.CCall.retty != Ity_I32 && !mode64)
+         goto irreducible;
+
+      /* Marshal args, do the call, clear stack. */
+      doHelperCall(env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args);
+      addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
+      return r_dst;
+   }
+
+   default:
+      break;
+   }        /* end switch(e->tag) */
+
+   /* We get here if no pattern matched. */
+   irreducible:
+      vex_printf("--------------->\n");
+      if (e->tag == Iex_RdTmp)
+         vex_printf("Iex_RdTmp \n");
+      ppIRExpr(e);
+
+      vpanic("iselWordExpr_R(mips): cannot reduce tree");
+}
+
+/* --------------------- RH --------------------- */
+
+/* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
+   (reg-or-halfword-immediate).  It's important to specify whether the
+   immediate is to be regarded as signed or not.  If yes, this will
+   never return -32768 as an immediate; this guaranteed that all
+   signed immediates that are return can have their sign inverted if
+   need be. */
+
+static MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e)
+{
+   MIPSRH *ri = iselWordExpr_RH_wrk(env, syned, e);
+   /* sanity checks ... */
+   switch (ri->tag) {
+      case Mrh_Imm:
+         vassert(ri->Mrh.Imm.syned == syned);
+         if (syned)
+            vassert(ri->Mrh.Imm.imm16 != 0x8000);
+         return ri;
+      case Mrh_Reg:
+         vassert(hregClass(ri->Mrh.Reg.reg) == HRcGPR(env->mode64));
+         vassert(hregIsVirtual(ri->Mrh.Reg.reg));
+         return ri;
+      default:
+         vpanic("iselIntExpr_RH: unknown mips RH tag");
+   }
+}
+
+/* DO NOT CALL THIS DIRECTLY ! */
+static MIPSRH *iselWordExpr_RH_wrk(ISelEnv * env, Bool syned, IRExpr * e)
+{
+   ULong u;
+   Long l;
+   IRType ty = typeOfIRExpr(env->type_env, e);
+   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
+          ((ty == Ity_I64) && env->mode64));
+
+   /* special case: immediate */
+   if (e->tag == Iex_Const) {
+      IRConst *con = e->Iex.Const.con;
+      /* What value are we aiming to generate? */
+      switch (con->tag) {
+         /* Note: Not sign-extending - we carry 'syned' around */
+         case Ico_U64:
+            vassert(env->mode64);
+            u = con->Ico.U64;
+            break;
+         case Ico_U32:
+            u = 0xFFFFFFFF & con->Ico.U32;
+            break;
+         case Ico_U16:
+            u = 0x0000FFFF & con->Ico.U16;
+            break;
+         case Ico_U8:
+            u = 0x000000FF & con->Ico.U8;
+            break;
+         default:
+            vpanic("iselIntExpr_RH.Iex_Const(mips)");
+      }
+      l = (Long) u;
+      /* Now figure out if it's representable. */
+      if (!syned && u <= 65535) {
+         return MIPSRH_Imm(False /*unsigned */ , toUShort(u & 0xFFFF));
+      }
+      if (syned && l >= -32767 && l <= 32767) {
+         return MIPSRH_Imm(True /*signed */ , toUShort(u & 0xFFFF));
+      }
+      /* no luck; use the Slow Way. */
+   }
+   /* default case: calculate into a register and return that */
+   return MIPSRH_Reg(iselWordExpr_R(env, e));
+}
+
+/* --------------------- RH5u --------------------- */
+
+/* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
+   being an immediate in the range 1 .. 31 inclusive.  Used for doing
+   shift amounts. */
+
+static MIPSRH *iselWordExpr_RH5u(ISelEnv * env, IRExpr * e)
+{
+   MIPSRH *ri;
+   ri = iselWordExpr_RH5u_wrk(env, e);
+   /* sanity checks ... */
+   switch (ri->tag) {
+      case Mrh_Imm:
+         vassert(ri->Mrh.Imm.imm16 >= 1 && ri->Mrh.Imm.imm16 <= 31);
+         vassert(!ri->Mrh.Imm.syned);
+         return ri;
+      case Mrh_Reg:
+         vassert(hregClass(ri->Mrh.Reg.reg) == HRcInt32);
+         vassert(hregIsVirtual(ri->Mrh.Reg.reg));
+         return ri;
+      default:
+         vpanic("iselIntExpr_RH5u: unknown mips RH tag");
+   }
+}
+
+/* DO NOT CALL THIS DIRECTLY ! */
+static MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e)
+{
+   IRType ty = typeOfIRExpr(env->type_env, e);
+   vassert(ty == Ity_I8);
+
+   /* special case: immediate */
+   if (e->tag == Iex_Const
+       && e->Iex.Const.con->tag == Ico_U8
+       && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 31) {
+      return MIPSRH_Imm(False /*unsigned */ , e->Iex.Const.con->Ico.U8);
+   }
+
+   /* default case: calculate into a register and return that */
+   return MIPSRH_Reg(iselWordExpr_R(env, e));
+}
+
+/* --------------------- CONDCODE --------------------- */
+
+/* Generate code to evaluated a bit-typed expression, returning the
+   condition code which would correspond when the expression would
+   notionally have returned 1. */
+
+static MIPSCondCode iselCondCode(ISelEnv * env, IRExpr * e)
+{
+   MIPSCondCode cc = iselCondCode_wrk(env,e);
+   vassert(cc != MIPScc_NV);
+   return cc;
+}
+
+/* DO NOT CALL THIS DIRECTLY ! */
+static MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e)
+{
+   vassert(e);
+   vassert(typeOfIRExpr(env->type_env, e) == Ity_I1);
+   /* Cmp*32*(x,y) ? */
+   if (e->Iex.Binop.op == Iop_CmpEQ32
+       || e->Iex.Binop.op == Iop_CmpNE32
+       || e->Iex.Binop.op == Iop_CmpNE64
+       || e->Iex.Binop.op == Iop_CmpLT32S
+       || e->Iex.Binop.op == Iop_CmpLT32U
+       || e->Iex.Binop.op == Iop_CmpLT64U
+       || e->Iex.Binop.op == Iop_CmpLE32S
+       || e->Iex.Binop.op == Iop_CmpLE64S
+       || e->Iex.Binop.op == Iop_CmpLT64S
+       || e->Iex.Binop.op == Iop_CmpEQ64) {
+
+      Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
+                   || e->Iex.Binop.op == Iop_CmpLE32S
+                   || e->Iex.Binop.op == Iop_CmpLT64S
+                   || e->Iex.Binop.op == Iop_CmpLE64S);
+      Bool size32;
+      HReg dst = newVRegI(env);
+      HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
+      HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
+
+      MIPSCondCode cc;
+
+      switch (e->Iex.Binop.op) {
+         case Iop_CmpEQ32:
+            cc = MIPScc_EQ;
+            size32 = True;
+            break;
+         case Iop_CmpNE32:
+            cc = MIPScc_NE;
+            size32 = True;
+            break;
+         case Iop_CmpNE64:
+            cc = MIPScc_NE;
+            size32 = True;
+            break;
+         case Iop_CmpLT32S:
+            cc = MIPScc_LT;
+            size32 = True;
+            break;
+         case Iop_CmpLT32U:
+            cc = MIPScc_LO;
+            size32 = True;
+            break;
+         case Iop_CmpLT64U:
+            cc = MIPScc_LO;
+            size32 = False;
+            break;
+         case Iop_CmpLE32S:
+            cc = MIPScc_LE;
+            size32 = True;
+            break;
+         case Iop_CmpLE64S:
+            cc = MIPScc_LE;
+            size32 = False;
+            break;
+         case Iop_CmpLT64S:
+            cc = MIPScc_LT;
+            size32 = False;
+            break;
+         case Iop_CmpEQ64:
+            cc = MIPScc_EQ;
+            size32 = False;
+            break;
+         default:
+            vpanic
+                ("iselCondCode(mips): CmpXX32 or CmpXX64");
+      }
+
+      addInstr(env, MIPSInstr_Cmp(syned, size32, dst, r1, r2, cc));
+      // Store result to guest_COND
+      MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
+
+      addInstr(env, MIPSInstr_Store(4,
+               MIPSAMode_IR(am_addr->Mam.IR.index + 316, am_addr->Mam.IR.base),
+               dst, mode64));
+      return cc;
+   }
+   if (e->Iex.Binop.op == Iop_Not1) {
+      HReg r_dst = newVRegI(env);
+      HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
+      MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
+
+      addInstr(env, MIPSInstr_LI(r_dst, 0x1));
+      addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, r_dst, r_srcR));
+      // Store result to guest_COND
+      MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
+
+      addInstr(env, MIPSInstr_Store(4,
+               MIPSAMode_IR(am_addr->Mam.IR.index + 316, am_addr->Mam.IR.base),
+               r_dst, mode64));
+      return MIPScc_NE;
+   }
+   if (e->tag == Iex_RdTmp || e->tag == Iex_Unop) {
+      HReg r_dst = iselWordExpr_R_wrk(env, e);
+      // Store result to guest_COND
+      MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
+
+      addInstr(env, MIPSInstr_Store(4,
+               MIPSAMode_IR(am_addr->Mam.IR.index + 316, am_addr->Mam.IR.base),
+               r_dst, mode64));
+      return MIPScc_EQ;
+   }
+
+   vex_printf("iselCondCode(mips): No such tag(%u)\n", e->tag);
+   ppIRExpr(e);
+   vpanic("iselCondCode(mips)");
+}
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Integer expressions (128 bit)               ---*/
+/*---------------------------------------------------------*/
+
+/* 64-bit mode ONLY: compute a 128-bit value into a register pair,
+   which is returned as the first two parameters.  As with
+   iselWordExpr_R, these may be either real or virtual regs; in any
+   case they must not be changed by subsequent code emitted by the
+   caller.  */
+
+static void iselInt128Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
+{
+   vassert(env->mode64);
+   iselInt128Expr_wrk(rHi, rLo, env, e);
+#  if 0
+   vex_printf("\n");
+   ppIRExpr(e);
+   vex_printf("\n");
+#  endif
+   vassert(hregClass(*rHi) == HRcGPR(env->mode64));
+   vassert(hregIsVirtual(*rHi));
+   vassert(hregClass(*rLo) == HRcGPR(env->mode64));
+   vassert(hregIsVirtual(*rLo));
+}
+
+/* DO NOT CALL THIS DIRECTLY ! */
+static void iselInt128Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env,
+                               IRExpr * e)
+{
+   vassert(e);
+   vassert(typeOfIRExpr(env->type_env, e) == Ity_I128);
+
+   /* read 128-bit IRTemp */
+   if (e->tag == Iex_RdTmp) {
+      lookupIRTempPair(rHi, rLo, env, e->Iex.RdTmp.tmp);
+      return;
+   }
+
+   /* --------- BINARY ops --------- */
+   if (e->tag == Iex_Binop) {
+      switch (e->Iex.Binop.op) {
+         /* 64 x 64 -> 128 multiply */
+         case Iop_MullU64:
+         case Iop_MullS64:
+            {
+               HReg tLo = newVRegI(env);
+               HReg tHi = newVRegI(env);
+               Bool syned = toBool(e->Iex.Binop.op == Iop_MullS64);
+               HReg r_dst = newVRegI(env);
+               HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
+               HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
+               addInstr(env, MIPSInstr_Mul(syned, True, False /*64bit mul */ ,
+                                           r_dst, r_srcL, r_srcR));
+               addInstr(env, MIPSInstr_Mfhi(tHi));
+               addInstr(env, MIPSInstr_Mflo(tLo));
+               *rHi = tHi;
+               *rLo = tLo;
+               return;
+            }
+   
+         /* 64HLto128(e1,e2) */
+         case Iop_64HLto128:
+            *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
+            *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
+            return;
+   
+         case Iop_DivModS64to64: {
+            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
+            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
+            HReg tLo = newVRegI(env);
+            HReg tHi = newVRegI(env);
+            Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS64to64);
+
+            addInstr(env, MIPSInstr_Div(syned, False, r_srcL, r_srcR));
+            addInstr(env, MIPSInstr_Mfhi(tHi));
+            addInstr(env, MIPSInstr_Mflo(tLo));
+            *rHi = tHi;
+            *rLo = tLo;
+            return;
+         }
+   
+         case Iop_DivModU128to64: {
+            vassert(mode64);
+            HReg rHi1, rLo1;
+            iselInt128Expr(&rHi1, &rLo1, env, e->Iex.Binop.arg1);
+
+            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
+            HReg tLo = newVRegI(env);
+            HReg tHi = newVRegI(env);
+            Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS128to64);
+
+            addInstr(env, MIPSInstr_Div(syned, False, rLo1, r_srcR));
+            addInstr(env, MIPSInstr_Mfhi(tHi));
+            addInstr(env, MIPSInstr_Mflo(tLo));
+            *rHi = tHi;
+            *rLo = tLo;
+            return;
+         }
+   
+         default:
+            break;
+      }
+   }
+   vex_printf("iselInt128Expr(mips64): No such tag(%u)\n", e->tag);
+   ppIRExpr(e);
+   vpanic("iselInt128Expr(mips64)");
+}
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Integer expressions (64 bit)                ---*/
+/*---------------------------------------------------------*/
+
+/* 32-bit mode ONLY. Compute a 64-bit value into the register 
+ * pair HI, LO. HI and LO must not be changed by subsequent
+ *  code emitted by the caller. */
+
+static void iselInt64Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
+{
+   vassert(!env->mode64);
+   iselInt64Expr_wrk(rHi, rLo, env, e);
+   vassert(hregClass(*rHi) == HRcInt32);
+   vassert(hregIsVirtual(*rHi));
+   vassert(hregClass(*rLo) == HRcInt32);
+   vassert(hregIsVirtual(*rLo));
+}
+
+/* DO NOT CALL THIS DIRECTLY ! */
+static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
+{
+   vassert(e);
+   vassert(typeOfIRExpr(env->type_env, e) == Ity_I64);
+
+   /* read 64-bit IRTemp */
+   if (e->tag == Iex_RdTmp) {
+      lookupIRTemp64(rHi, rLo, env, e->Iex.RdTmp.tmp);
+      return;
+   }
+   /* 64-bit load */
+   if (e->tag == Iex_Load) {
+      HReg tLo = newVRegI(env);
+      HReg tHi = newVRegI(env);
+      HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr);
+      addInstr(env, MIPSInstr_Load(4, tHi, MIPSAMode_IR(0, r_addr), mode64));
+      addInstr(env, MIPSInstr_Load(4, tLo, MIPSAMode_IR(4, r_addr), mode64));
+      *rHi = tHi;
+      *rLo = tLo;
+      return;
+   }
+
+   /* 64-bit literal */
+   if (e->tag == Iex_Const) {
+      ULong w64 = e->Iex.Const.con->Ico.U64;
+      UInt wHi = toUInt(w64 >> 32);
+      UInt wLo = toUInt(w64);
+      HReg tLo = newVRegI(env);
+      HReg tHi = newVRegI(env);
+      vassert(e->Iex.Const.con->tag == Ico_U64);
+
+      if (wLo == wHi) {
+         /* Save a precious Int register in this special case. */
+         addInstr(env, MIPSInstr_LI(tLo, (ULong) wLo));
+         *rHi = tLo;
+         *rLo = tLo;
+      } else {
+         addInstr(env, MIPSInstr_LI(tHi, (ULong) wHi));
+         addInstr(env, MIPSInstr_LI(tLo, (ULong) wLo));
+         *rHi = tHi;
+         *rLo = tLo;
+      }
+
+      return;
+   }
+
+   /* 64-bit GET */
+   if (e->tag == Iex_Get) {
+      HReg tLo = newVRegI(env);
+      HReg tHi = newVRegI(env);
+
+      MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
+                                        GuestStatePointer(mode64));
+      addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
+      addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeInt(am_addr), mode64));
+      *rHi = tHi;
+      *rLo = tLo;
+      return;
+   }
+
+   /* 64-bit Mux0X */
+   if (e->tag == Iex_Mux0X) {
+      HReg expr0Lo, expr0Hi;
+      HReg exprXLo, exprXHi;
+      HReg tmpHi = newVRegI(env);
+      HReg tmpLo = newVRegI(env);
+      HReg tmp1Hi = newVRegI(env);
+      HReg tmp1Lo = newVRegI(env);
+      HReg r_cond = iselWordExpr_R(env, e->Iex.Mux0X.cond);
+      HReg r_cond_neg = newVRegI(env);
+      HReg desLo = newVRegI(env);
+      HReg desHi = newVRegI(env);
+
+      /* expr0Hi:expr0Lo = expr0 */
+      /* exprXHi:exprXLo = exprX */
+      iselInt64Expr(&expr0Hi, &expr0Lo, env, e->Iex.Mux0X.expr0);
+      iselInt64Expr(&exprXHi, &exprXLo, env, e->Iex.Mux0X.exprX);
+
+      addInstr(env, MIPSInstr_Alu(Malu_AND, tmpLo, r_cond,
+                                  MIPSRH_Reg(exprXLo)));
+      addInstr(env, MIPSInstr_Alu(Malu_AND, tmpHi, r_cond,
+                                  MIPSRH_Reg(exprXHi)));
+      addInstr(env, MIPSInstr_Alu(Malu_NOR, r_cond_neg, r_cond,
+                                  MIPSRH_Reg(r_cond)));
+      addInstr(env, MIPSInstr_Alu(Malu_AND, tmp1Lo, r_cond_neg,
+                                  MIPSRH_Reg(exprXLo)));
+      addInstr(env, MIPSInstr_Alu(Malu_AND, tmp1Hi, r_cond_neg,
+                                  MIPSRH_Reg(exprXHi)));
+      addInstr(env, MIPSInstr_Alu(Malu_ADD, desLo, tmpLo,
+                                  MIPSRH_Reg(tmp1Lo)));
+      addInstr(env, MIPSInstr_Alu(Malu_ADD, desHi, tmpHi,
+                                  MIPSRH_Reg(tmp1Hi)));
+      *rHi = desHi;
+      *rLo = desLo;
+      return;
+   }
+
+   /* --------- BINARY ops --------- */
+   if (e->tag == Iex_Binop) {
+      IROp op_binop = e->Iex.Binop.op;
+      switch (op_binop) {
+         /* 32 x 32 -> 64 multiply */
+         /* Add64 */
+         case Iop_Add64: {
+            HReg xLo, xHi, yLo, yHi;
+            HReg tHi = newVRegI(env);
+            HReg tLo = newVRegI(env);
+            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
+            iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
+            addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, xHi, MIPSRH_Reg(yHi)));
+            addInstr(env, MIPSInstr_Alu(Malu_ADD, tLo, xLo, MIPSRH_Reg(yLo)));
+            *rHi = tHi;
+            *rLo = tLo;
+            return;
+         }
+         case Iop_MullU32:
+         case Iop_MullS32: {
+            HReg tLo = newVRegI(env);
+            HReg tHi = newVRegI(env);
+            HReg r_dst = newVRegI(env);
+            Bool syned = toBool(op_binop == Iop_MullS32);
+            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
+            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
+
+            addInstr(env, MIPSInstr_Mul(syned/*Unsigned or Signed */ ,
+                                        True /*widen */ , True,
+                                        r_dst, r_srcL, r_srcR));
+            addInstr(env, MIPSInstr_Mfhi(tHi));
+            addInstr(env, MIPSInstr_Mflo(tLo));
+            *rHi = tHi;
+            *rLo = tLo;
+
+            return;
+         }
+         case Iop_DivModS64to32:
+         case Iop_DivModU64to32: {
+            HReg r_sHi, r_sLo;
+            HReg tLo = newVRegI(env);
+            HReg tHi = newVRegI(env);
+            Bool syned = toBool(op_binop == Iop_DivModS64to32);
+            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
+
+            iselInt64Expr(&r_sHi, &r_sLo, env, e->Iex.Binop.arg1);
+            addInstr(env, MIPSInstr_Div(syned, True, r_sLo, r_srcR));
+            addInstr(env, MIPSInstr_Mfhi(tHi));
+            addInstr(env, MIPSInstr_Mflo(tLo));
+            *rHi = tHi;
+            *rLo = tLo;
+
+            return;
+         }
+
+            /* 32HLto64(e1,e2) */
+         case Iop_32HLto64:
+            *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
+            *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
+
+            return;
+            /* Or64/And64/Xor64 */
+         case Iop_Or64:
+         case Iop_And64:
+         case Iop_Xor64: {
+            HReg xLo, xHi, yLo, yHi;
+            HReg tLo = newVRegI(env);
+            HReg tHi = newVRegI(env);
+            MIPSAluOp op = (op_binop == Iop_Or64) ? Malu_OR :
+                           (op_binop == Iop_And64) ? Malu_AND : Malu_XOR;
+            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
+            iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
+            addInstr(env, MIPSInstr_Alu(op, tHi, xHi, MIPSRH_Reg(yHi)));
+            addInstr(env, MIPSInstr_Alu(op, tLo, xLo, MIPSRH_Reg(yLo)));
+            *rHi = tHi;
+            *rLo = tLo;
+            return;
+         }
+
+         default:
+            break;
+      }
+   }
+
+   /* --------- UNARY ops --------- */
+   if (e->tag == Iex_Unop) {
+
+      switch (e->Iex.Unop.op) {
+         case Iop_1Sto64: {
+            HReg tLo = newVRegI(env);
+            HReg tHi = newVRegI(env);
+            HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
+            HReg tmp = newVRegI(env);
+
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, src,
+                          MIPSRH_Imm(False, 31)));
+            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, src,
+                          MIPSRH_Imm(False, 31)));
+
+            addInstr(env, mk_iMOVds_RR(tHi, tmp));
+            addInstr(env, mk_iMOVds_RR(tLo, tmp));
+
+            *rHi = tHi;
+            *rLo = tLo;
+            return;
+         }
+
+         /* 32Sto64(e) */
+         case Iop_32Sto64: {
+            HReg tLo = newVRegI(env);
+            HReg tHi = newVRegI(env);
+            HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
+            addInstr(env, mk_iMOVds_RR(tHi, src));
+            addInstr(env, mk_iMOVds_RR(tLo, src));
+            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tHi, tHi,
+                          MIPSRH_Imm(False, 31)));
+            *rHi = tHi;
+            *rLo = tLo;
+            return;
+         }
+
+         /* 32Uto64(e) */
+         case Iop_32Uto64: {
+            HReg tLo = newVRegI(env);
+            HReg tHi = newVRegI(env);
+            HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
+            addInstr(env, mk_iMOVds_RR(tLo, src));
+            addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, hregMIPS_GPR0(mode64),
+                          MIPSRH_Reg(hregMIPS_GPR0(mode64))));
+            *rHi = tHi;
+            *rLo = tLo;
+            return;
+         }
+   
+         case Iop_CmpwNEZ64: {
+            HReg srcLo, srcHi;
+            HReg tmp1 = newVRegI(env);
+            HReg tmp2 = newVRegI(env);
+            /* srcHi:srcLo = arg */
+            iselInt64Expr(&srcHi, &srcLo, env, e->Iex.Unop.arg);
+            /* tmp1 = srcHi | srcLo */
+            addInstr(env, MIPSInstr_Alu(Malu_OR, tmp1, srcLo,
+                                        MIPSRH_Reg(srcHi)));
+            /* tmp2 = (tmp1 | -tmp1) >>s 31 */
+
+            addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2, hregMIPS_GPR0(mode64),
+                                        MIPSRH_Reg(tmp1)));
+
+            addInstr(env, MIPSInstr_Alu(Malu_OR, tmp2, tmp2, MIPSRH_Reg(tmp1)));
+            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp2, tmp2,
+                          MIPSRH_Imm(False, 31)));
+            *rHi = tmp2;
+            *rLo = tmp2;
+            return;
+
+         }
+         case Iop_ReinterpF64asI64: {
+            HReg tLo = newVRegI(env);
+            HReg tHi = newVRegI(env);
+            MIPSAMode *am_addr;
+            HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg);
+
+            sub_from_sp(env, 16);   // Move SP down 16 bytes
+            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+            // store as F64
+            addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
+                                           am_addr));
+            // load as 2xI32                              
+            addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
+            addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
+                                         mode64));
+
+            add_to_sp(env, 16);  // Reset SP
+
+            *rHi = tHi;
+            *rLo = tLo;
+            return;
+         }
+   
+         default:
+            vex_printf("UNARY: No such op: ");
+            ppIROp(e->Iex.Unop.op);
+            vex_printf("\n");
+            break;
+      }
+   }
+
+   vex_printf("iselInt64Expr(mips): No such tag(%u)\n", e->tag);
+   ppIRExpr(e);
+   vpanic("iselInt64Expr(mips)");
+}
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Floating point expressions (32 bit)         ---*/
+/*---------------------------------------------------------*/
+
+/* Nothing interesting here; really just wrappers for
+   64-bit stuff. */
+
+static HReg iselFltExpr(ISelEnv * env, IRExpr * e)
+{
+   HReg r = iselFltExpr_wrk(env, e);
+   vassert(hregIsVirtual(r));
+   return r;
+}
+
+/* DO NOT CALL THIS DIRECTLY */
+static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e)
+{
+   IRType ty = typeOfIRExpr(env->type_env, e);
+   vassert(ty == Ity_F32 || (ty == Ity_F64 && mode64));
+
+   if (e->tag == Iex_RdTmp) {
+      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
+   }
+
+   if (e->tag == Iex_Load) {
+      MIPSAMode *am_addr;
+      HReg r_dst = newVRegF(env);
+      vassert(e->Iex.Load.ty == Ity_F32
+             || (e->Iex.Load.ty == Ity_F64 && mode64));
+      am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
+      addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, r_dst, am_addr));
+      return r_dst;
+   }
+
+   if (e->tag == Iex_Get) {
+      HReg r_dst = newVRegF(env);
+      MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
+                                        GuestStatePointer(mode64));
+      addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, r_dst, am_addr));
+      return r_dst;
+   }
+
+   if (e->tag == Iex_Unop) {
+      switch (e->Iex.Unop.op) {
+      case Iop_ReinterpI32asF32: {
+         MIPSAMode *am_addr;
+         HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+         HReg r_dst = newVRegF(env);
+
+         sub_from_sp(env, 16);   // Move SP down 16 bytes
+         am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+         // store as I32                                 
+         addInstr(env, MIPSInstr_Store(4, am_addr, fr_src, mode64));
+
+         // load as Ity_F32
+         addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, r_dst, am_addr));
+
+         add_to_sp(env, 16);  // Reset SP
+         return r_dst;
+
+      }
+      case Iop_F32toF64: {
+         /* first arg is rounding mode; we ignore it. */
+         MIPSAMode *am_addr;
+         HReg src = iselFltExpr(env, e->Iex.Unop.arg);
+         HReg dst = newVRegF(env);
+
+         sub_from_sp(env, 16);   // Move SP down 16 bytes
+         am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+         addInstr(env, MIPSInstr_Store(4,
+                                       MIPSAMode_IR(am_addr->Mam.IR.index + 4,
+                                       am_addr->Mam.IR.base),
+                                       hregMIPS_GPR0(mode64), mode64));
+         addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, src, am_addr));
+
+         // load as Ity_F32
+         addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, dst, am_addr));
+         add_to_sp(env, 16);  // Reset SP
+
+         return dst;
+      }
+      case Iop_ReinterpI64asF64:
+         {
+            vassert(mode64);
+            MIPSAMode *am_addr;
+            HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+            HReg r_dst = newVRegF(env);
+
+            sub_from_sp(env, 16);   // Move SP down 16 bytes
+            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+            // store as I32                                 
+            addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
+
+            // load as Ity_F32
+            addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
+
+            add_to_sp(env, 16);  // Reset SP
+            return r_dst;
+         }
+      case Iop_AbsF32:
+      case Iop_AbsF64: {
+         Bool sz32 = e->Iex.Unop.op == Iop_AbsF32;
+         HReg src = iselFltExpr(env, e->Iex.Unop.arg);
+         HReg dst = newVRegF(env);
+         addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_ABSS : Mfp_ABSD, dst, src));
+         return dst;
+      }
+      case Iop_NegF32:
+      case Iop_NegF64: {
+         Bool sz32 = e->Iex.Unop.op == Iop_NegF32;
+         HReg src = iselFltExpr(env, e->Iex.Unop.arg);
+         HReg dst = newVRegF(env);
+         addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_NEGS : Mfp_NEGD, dst, src));
+         return dst;
+      }
+      default:
+         break;
+      }
+   }
+
+   if (e->tag == Iex_Triop) {
+      switch (e->Iex.Triop.details->op) {
+         case Iop_DivF32:
+         case Iop_DivF64:
+         case Iop_MulF32:
+         case Iop_MulF64:
+         case Iop_AddF32:
+         case Iop_AddF64:
+         case Iop_SubF32:
+         case Iop_SubF64: {
+            MIPSFpOp op = 0;
+            /*INVALID*/ HReg argL = iselFltExpr(env, e->Iex.Triop.details->arg2);
+            HReg argR = iselFltExpr(env, e->Iex.Triop.details->arg3);
+            HReg dst = newVRegF(env);
+            switch (e->Iex.Triop.details->op) {
+               case Iop_DivF32:
+                  op = Mfp_DIVS;
+                  break;
+               case Iop_MulF32:
+                  op = Mfp_MULS;
+                  break;
+               case Iop_AddF32:
+                  op = Mfp_ADDS;
+                  break;
+               case Iop_SubF32:
+                  op = Mfp_SUBS;
+                  break;
+               default:
+                  vassert(0);
+            }
+            addInstr(env, MIPSInstr_FpBinary(op, dst, argL, argR));
+            return dst;
+         }
+         default:
+            break;
+      }
+   }
+
+   if (e->tag == Iex_Binop) {
+      switch (e->Iex.Binop.op) {
+         case Iop_F64toF32: {
+            HReg valD = iselDblExpr(env, e->Iex.Binop.arg2);
+            HReg valS = newVRegF(env);
+
+            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
+            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSD, valS, valD));
+            set_MIPS_rounding_default(env);
+            return valS;
+         }
+
+         case Iop_RoundF32toInt: {
+               HReg valS = newVRegF(env);
+               HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
+
+               set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
+               addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWS, valS, valF));
+
+               set_MIPS_rounding_default(env);
+               return valS;
+            }
+
+         case Iop_I32StoF32: {
+            HReg r_dst = newVRegF(env);
+
+            MIPSAMode *am_addr;
+            HReg fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
+            HReg tmp = newVRegF(env);
+
+            sub_from_sp(env, 16);   // Move SP down 16 bytes
+            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+            // store as I32
+            addInstr(env, MIPSInstr_Store(4, am_addr, fr_src, mode64));
+
+            // load as Ity_F32
+            addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, tmp, am_addr));
+
+            add_to_sp(env, 16);  // Reset SP
+
+            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
+            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSW, r_dst, tmp));
+            set_MIPS_rounding_default(env);
+
+            return r_dst;
+         }
+
+         case Iop_SqrtF32:
+         case Iop_SqrtF64: {
+            /* first arg is rounding mode; we ignore it. */
+            Bool sz32 = e->Iex.Binop.op == Iop_SqrtF32;
+            HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
+            HReg dst = newVRegF(env);
+            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
+            addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_SQRTS : Mfp_SQRTD, dst,
+                                            src));
+            set_MIPS_rounding_default(env);
+            return dst;
+         }
+   
+         default:
+            break;
+      }
+   }
+
+   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_TruncF64asF32) {
+      /* This is quite subtle.  The only way to do the relevant
+         truncation is to do a single-precision store and then a
+         double precision load to get it back into a register.  The
+         problem is, if the data is then written to memory a second
+         time, as in
+
+         STbe(...) = TruncF64asF32(...)
+
+         then will the second truncation further alter the value?  The
+         answer is no: flds (as generated here) followed by fsts
+         (generated for the STbe) is the identity function on 32-bit
+         floats, so we are safe.
+
+         Another upshot of this is that if iselStmt can see the
+         entirety of
+
+         STbe(...) = TruncF64asF32(arg)
+
+         then it can short circuit having to deal with TruncF64asF32
+         individually; instead just compute arg into a 64-bit FP
+         register and do 'fsts' (since that itself does the
+         truncation).
+
+         We generate pretty poor code here (should be ok both for
+         32-bit and 64-bit mode); but it is expected that for the most
+         part the latter optimisation will apply and hence this code
+         will not often be used.
+       */
+      HReg fsrc = iselDblExpr(env, e->Iex.Unop.arg);
+      HReg fdst = newVRegF(env);
+      MIPSAMode *zero_r1 = MIPSAMode_IR(0, StackPointer(mode64));
+
+      sub_from_sp(env, 16);
+      // store as F32, hence truncating
+      addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fsrc, zero_r1));
+      // and reload.  Good huh?! (sigh)
+      addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, fdst, zero_r1));
+      add_to_sp(env, 16);
+      return fdst;
+   }
+
+   vex_printf("iselFltExpr(mips): No such tag(0x%x)\n", e->tag);
+   ppIRExpr(e);
+   vpanic("iselFltExpr_wrk(mips)");
+}
+
+static HReg iselDblExpr(ISelEnv * env, IRExpr * e)
+{
+   HReg r = iselDblExpr_wrk(env, e);
+   vassert(hregClass(r) == HRcFlt64);
+   vassert(hregIsVirtual(r));
+   return r;
+}
+
+/* DO NOT CALL THIS DIRECTLY */
+static HReg iselDblExpr_wrk(ISelEnv * env, IRExpr * e)
+{
+   IRType ty = typeOfIRExpr(env->type_env, e);
+   vassert(e);
+   vassert(ty == Ity_F64);
+
+   if (e->tag == Iex_RdTmp) {
+      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
+   }
+
+   /* --------- LOAD --------- */
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
+      HReg r_dst = newVRegD(env);
+      MIPSAMode *am_addr;
+      vassert(e->Iex.Load.ty == Ity_F64);
+      am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
+      addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
+      return r_dst;
+   }
+
+   /* --------- GET --------- */
+   if (e->tag == Iex_Get) {
+
+      HReg r_dst = newVRegD(env);
+      MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
+                                        GuestStatePointer(mode64));
+      addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
+      return r_dst;
+   }
+
+   if (e->tag == Iex_Unop) {
+      MIPSFpOp fpop = Mfp_INVALID;
+      switch (e->Iex.Unop.op) {
+         case Iop_NegF64:
+            fpop = Mfp_NEGD;
+            break;
+         case Iop_AbsF64:
+            fpop = Mfp_ABSD;
+            break;
+         case Iop_F32toF64: {
+            HReg src = iselFltExpr(env, e->Iex.Unop.arg);
+            HReg dst = newVRegD(env);
+
+            HReg irrm = newVRegI(env);
+
+            MIPSAMode *am_addr1 = MIPSAMode_IR(284, GuestStatePointer(mode64));
+
+            addInstr(env, MIPSInstr_Load(4, irrm, am_addr1, mode64));
+
+            // set new FCSR
+            HReg tmp = newVRegI(env);
+            HReg fcsr_old = newVRegI(env);
+            MIPSAMode *am_addr;
+
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, irrm,
+                                        MIPSRH_Imm(False, 1)));
+            addInstr(env, MIPSInstr_Alu(Malu_XOR, tmp, irrm, MIPSRH_Reg(tmp)));
+            addInstr(env, MIPSInstr_Alu(Malu_AND, irrm, tmp,
+                                        MIPSRH_Imm(False, 3)));
+            /* save old value of FCSR */
+            addInstr(env, MIPSInstr_MfFCSR(fcsr_old));
+            sub_from_sp(env, 8); // Move SP down 4 bytes
+            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+            //store old FCSR to stack
+            addInstr(env, MIPSInstr_Store(4, am_addr, fcsr_old, mode64));
+
+            //set new value of FCSR
+            addInstr(env, MIPSInstr_MtFCSR(irrm));
+
+            //set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
+            addInstr(env, MIPSInstr_FpUnary(Mfp_CVTD, dst, src));
+            set_MIPS_rounding_default(env);
+            return dst;
+         }
+         case Iop_ReinterpI64asF64: {
+            HReg Hi;
+            HReg Lo;
+            HReg dst = newVRegD(env);
+
+            iselInt64Expr(&Hi, &Lo, env, e->Iex.Unop.arg);
+
+            dst = mk_LoadRR32toFPR(env, Hi, Lo);   // 2*I32 -> F64
+            return dst;
+         }
+         case Iop_I32StoF64: {
+            HReg dst = newVRegD(env);
+            HReg tmp1 = newVRegF(env);
+            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
+            MIPSAMode *am_addr;
+            sub_from_sp(env, 16);   // Move SP down 16 bytes
+            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+            // store as I32
+            addInstr(env, MIPSInstr_Store(4, am_addr, r_src, mode64));
+
+            // load as Ity_F32
+            addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, tmp1, am_addr));
+
+            add_to_sp(env, 16);  // Reset SP
+
+            HReg irrm = newVRegI(env);
+
+            MIPSAMode *am_addr1 = MIPSAMode_IR(284, GuestStatePointer(mode64));
+
+            addInstr(env, MIPSInstr_Load(4, irrm, am_addr1, mode64));
+
+            //set rounding mode
+            HReg tmp = newVRegI(env);
+            HReg fcsr_old = newVRegI(env);
+
+            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, irrm,
+                                         MIPSRH_Imm(False, 1)));
+            addInstr(env, MIPSInstr_Alu(Malu_XOR, tmp, irrm, MIPSRH_Reg(tmp)));
+            addInstr(env, MIPSInstr_Alu(Malu_AND, irrm, tmp,
+                                        MIPSRH_Imm(False, 3)));
+            /* save old value of FCSR */
+            addInstr(env, MIPSInstr_MfFCSR(fcsr_old));
+            sub_from_sp(env, 8); // Move SP down 4 bytes
+            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+            //store old FCSR to stack
+            addInstr(env, MIPSInstr_Store(4, am_addr, fcsr_old, mode64));
+
+            //set new value of FCSR
+            addInstr(env, MIPSInstr_MtFCSR(irrm));
+
+            // and do convert
+            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDW, dst, tmp1));
+            set_MIPS_rounding_default(env);
+
+            return dst;
+         }
+         default:
+            break;
+      }
+
+      if (fpop != Mfp_INVALID) {
+         HReg src = iselDblExpr(env, e->Iex.Unop.arg);
+         HReg dst = newVRegD(env);
+         addInstr(env, MIPSInstr_FpUnary(fpop, dst, src));
+         return dst;
+      }
+   }
+
+   if (e->tag == Iex_Binop) {
+      switch (e->Iex.Binop.op) {
+         case Iop_RoundF64toInt: {
+            HReg valD = iselDblExpr(env, e->Iex.Binop.arg2);
+            MIPSRH *fmt = iselWordExpr_RH(env, False, e->Iex.Binop.arg1);
+            HReg valD1 = newVRegD(env);
+
+            if (fmt->Mrh.Imm.imm16 == 0x3)
+               addInstr(env, MIPSInstr_FpConvert(Mfp_TRULD, valD1, valD));
+            else if (fmt->Mrh.Imm.imm16 == 0x2)
+               addInstr(env, MIPSInstr_FpConvert(Mfp_CEILLD, valD1, valD));
+            else
+               vassert(0);
+            return valD1;
+         }
+
+         case Iop_SqrtF64:{
+            /* first arg is rounding mode; we ignore it. */
+            HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
+            HReg dst = newVRegD(env);
+            addInstr(env, MIPSInstr_FpUnary(Mfp_SQRTD, dst, src));
+            return dst;
+         }
+
+         default:
+            break;
+
+      }
+   }
+
+   if (e->tag == Iex_Triop) {
+      switch (e->Iex.Triop.details->op) {
+         case Iop_DivF64:
+         case Iop_DivF32:
+         case Iop_MulF64:
+         case Iop_AddF64:
+         case Iop_SubF64: {
+            MIPSFpOp op = 0;
+            /*INVALID*/ HReg argL = iselDblExpr(env, e->Iex.Triop.details->arg2);
+            HReg argR = iselDblExpr(env, e->Iex.Triop.details->arg3);
+            HReg dst = newVRegD(env);
+            switch (e->Iex.Triop.details->op) {
+               case Iop_DivF64:
+                  op = Mfp_DIVD;
+                  break;
+               case Iop_MulF64:
+                  op = Mfp_MULD;
+                  break;
+               case Iop_AddF64:
+                  op = Mfp_ADDD;
+                  break;
+               case Iop_SubF64:
+                  op = Mfp_SUBD;
+                  break;
+               default:
+                  vassert(0);
+            }
+            addInstr(env, MIPSInstr_FpBinary(op, dst, argL, argR));
+            return dst;
+         }
+         default:
+            break;
+      }
+   }
+
+   /* --------- MULTIPLEX --------- */
+   if (e->tag == Iex_Mux0X) {
+      if (ty == Ity_F64
+          && typeOfIRExpr(env->type_env, e->Iex.Mux0X.cond) == Ity_I8) {
+         HReg r0 = iselDblExpr(env, e->Iex.Mux0X.expr0);
+         HReg rX = iselDblExpr(env, e->Iex.Mux0X.exprX);
+         HReg r_cond = iselWordExpr_R(env, e->Iex.Mux0X.cond);
+         HReg r_cond_neg = newVRegI(env);
+         HReg r_dst = newVRegD(env);
+         HReg r_tmp_lo = newVRegI(env);
+         HReg r_tmp_hi = newVRegI(env);
+         HReg r_tmp1_lo = newVRegI(env);
+         HReg r_tmp1_hi = newVRegI(env);
+         HReg r_r0_lo = newVRegI(env);
+         HReg r_r0_hi = newVRegI(env);
+         HReg r_rX_lo = newVRegI(env);
+         HReg r_rX_hi = newVRegI(env);
+         HReg r_dst_lo = newVRegI(env);
+         HReg r_dst_hi = newVRegI(env);
+
+         sub_from_sp(env, 16);   // Move SP down 16 bytes
+         MIPSAMode *am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+         // store as Ity_F64
+         addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, r0, am_addr));
+
+         // load as 2xI32                              
+         addInstr(env, MIPSInstr_Load(4, r_r0_lo, am_addr, mode64));
+         addInstr(env, MIPSInstr_Load(4, r_r0_hi, nextMIPSAModeFloat(am_addr),
+                                      mode64));
+
+         add_to_sp(env, 16);  // Reset SP
+
+         addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp_lo, r_cond,
+                                     MIPSRH_Reg(r_r0_lo)));
+         addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp_hi, r_cond,
+                       MIPSRH_Reg(r_r0_hi)));
+
+         addInstr(env, MIPSInstr_Alu(Malu_NOR, r_cond_neg, r_cond,
+                       MIPSRH_Reg(r_cond)));
+
+         sub_from_sp(env, 16);   // Move SP down 16 bytes
+         am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+         // store as Ity_F64
+         addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, rX, am_addr));
+
+         // load as 2xI32                              
+         addInstr(env, MIPSInstr_Load(4, r_rX_lo, am_addr, mode64));
+         addInstr(env, MIPSInstr_Load(4, r_rX_hi, nextMIPSAModeFloat(am_addr),
+                                      mode64));
+
+         add_to_sp(env, 16);  // Reset SP
+
+         addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp1_lo, r_cond_neg,
+                                     MIPSRH_Reg(r_rX_lo)));
+         addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmp1_hi, r_cond_neg,
+                                     MIPSRH_Reg(r_rX_hi)));
+
+         addInstr(env, MIPSInstr_Alu(Malu_ADD, r_dst_lo, r_tmp_lo,
+                                     MIPSRH_Reg(r_tmp1_lo)));
+         addInstr(env, MIPSInstr_Alu(Malu_ADD, r_dst_hi, r_tmp_hi,
+                                     MIPSRH_Reg(r_tmp1_hi)));
+
+         sub_from_sp(env, 16);   // Move SP down 16 bytes
+         am_addr = MIPSAMode_IR(0, StackPointer(mode64));
+
+         // store as I32
+         addInstr(env, MIPSInstr_Store(4, am_addr, r_dst_lo, mode64));
+         addInstr(env, MIPSInstr_Store(4, nextMIPSAModeFloat(am_addr),
+                  r_dst_hi, mode64));
+
+         // load as Ity_F32
+         addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
+
+         add_to_sp(env, 16);  // Reset SP      
+
+         return r_dst;
+      }
+   }
+
+   vex_printf("iselDblExpr(mips): No such tag(%u)\n", e->tag);
+   ppIRExpr(e);
+   vpanic("iselDblExpr_wrk(mips)");
+}
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Statements                                  ---*/
+/*---------------------------------------------------------*/
+
+static void iselStmt(ISelEnv * env, IRStmt * stmt)
+{
+   if (vex_traceflags & VEX_TRACE_VCODE) {
+      vex_printf("\n-- ");
+
+      ppIRStmt(stmt);
+      vex_printf("\n");
+   }
+
+   switch (stmt->tag) {
+      /* --------- STORE --------- */
+      case Ist_Store: {
+         MIPSAMode *am_addr;
+         IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
+
+         /*constructs addressing mode from address provided */
+         am_addr = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd);
+
+         if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
+             (mode64 && (tyd == Ity_I64))) {
+            HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data);
+            addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(tyd)),
+                     am_addr, r_src, mode64));
+            return;
+         }
+         if (!mode64 && (tyd == Ity_I64)) {
+            HReg vHi, vLo;
+            HReg r_addr = iselWordExpr_R(env, stmt->Ist.Store.addr);
+
+            iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Store.data);
+
+            addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
+                          MIPSAMode_IR(0, r_addr), vHi, mode64));
+            addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
+                          MIPSAMode_IR(4, r_addr), vLo, mode64));
+            return;
+         }
+         if (tyd == Ity_F32) {
+            HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data);
+            addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fr_src,
+                                           am_addr));
+            return;
+         }
+
+         break;
+      }
+
+      /* --------- PUT --------- */
+      case Ist_Put: {
+         IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
+   
+         if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
+             (ty == Ity_I64 && mode64)) {
+            HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data);
+            MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
+                                              GuestStatePointer(mode64));
+            addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(ty)),
+                                          am_addr, r_src, mode64));
+            return;
+         }
+   
+         if (ty == Ity_I64 && !mode64) {
+            HReg vHi, vLo;
+            MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
+                                              GuestStatePointer(mode64));
+            MIPSAMode *am_addr4 = MIPSAMode_IR(stmt->Ist.Put.offset + 4,
+                                               GuestStatePointer(mode64));
+            iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Put.data);
+            addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
+                                          am_addr, vLo, mode64));
+            addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
+                                          am_addr4, vHi, mode64));
+            return;
+   
+         }
+   
+         if (ty == Ity_F32) {
+            HReg fr_src = iselFltExpr(env, stmt->Ist.Put.data);
+            MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
+                                              GuestStatePointer(mode64));
+            addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fr_src,
+                                           am_addr));
+            return;
+         }
+   
+         if (ty == Ity_F64) {
+            HReg fr_src;
+            fr_src = iselDblExpr(env, stmt->Ist.Put.data);
+            MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
+                                              GuestStatePointer(mode64));
+            addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
+                                           am_addr));
+            return;
+         }
+         break;
+      }
+
+      /* --------- TMP --------- */
+      case Ist_WrTmp: {
+         IRTemp tmp = stmt->Ist.WrTmp.tmp;
+         IRType ty = typeOfIRTemp(env->type_env, tmp);
+
+         if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I1) {
+            HReg r_dst = lookupIRTemp(env, tmp);
+            HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
+            addInstr(env, mk_iMOVds_RR(r_dst, r_src));
+            return;
+         }
+
+         if (ty == Ity_I64) {
+             HReg rHi, rLo, dstHi, dstLo;
+             iselInt64Expr(&rHi, &rLo, env, stmt->Ist.WrTmp.data);
+             lookupIRTemp64(&dstHi, &dstLo, env, tmp);
+             addInstr(env, mk_iMOVds_RR(dstHi, rHi));
+             addInstr(env, mk_iMOVds_RR(dstLo, rLo));
+             return;
+         }
+
+         if (ty == Ity_F32) {
+            HReg fr_dst = lookupIRTemp(env, tmp);
+            HReg fr_src = iselFltExpr(env, stmt->Ist.WrTmp.data);
+            addInstr(env, MIPSInstr_FpUnary(Mfp_MOVS, fr_dst, fr_src));
+            return;
+         }
+
+         if (ty == Ity_F64) {
+             HReg src = iselDblExpr(env, stmt->Ist.WrTmp.data);
+             HReg dst = lookupIRTemp(env, tmp);
+             addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, dst, src));
+             return;
+         }
+         break;
+      }
+
+      /* --------- Call to DIRTY helper --------- */
+      case Ist_Dirty: {
+         IRType retty;
+         IRDirty *d = stmt->Ist.Dirty.details;
+         Bool passBBP = False;
+
+         if (d->nFxState == 0)
+            vassert(!d->needsBBP);
+         passBBP = toBool(d->nFxState > 0 && d->needsBBP);
+
+         /* Marshal args, do the call, clear stack. */
+         doHelperCall(env, passBBP, d->guard, d->cee, d->args);
+
+         /* Now figure out what to do with the returned value, if any. */
+         if (d->tmp == IRTemp_INVALID)
+            /* No return value.  Nothing to do. */
+            return;
+
+         retty = typeOfIRTemp(env->type_env, d->tmp);
+         if (retty == Ity_I64 && !mode64) {
+            vex_printf
+                ("Dirty! Return 64 bits. Not implemented (yet!)\n");
+            return;
+         }
+         if (retty == Ity_I8 || retty == Ity_I16 || retty == Ity_I32
+             || (retty == Ity_I64 && mode64)) {
+            /* The returned value is in %r2.  Park it in the register
+               associated with tmp. */
+            HReg r_dst = lookupIRTemp(env, d->tmp);
+            addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
+            return;
+         }
+         break;
+      }
+
+      /* --------- Load Linked or Store Conditional --------- */
+      case Ist_LLSC: {
+         //Temporary solution; this need to be rewritten again for MIPS.
+         //On MIPS you can not read from address that is locked with LL before SC.
+         // If you read from address that is locked than SC will fall.
+         IRTemp res = stmt->Ist.LLSC.result;
+         IRType tyRes = typeOfIRTemp(env->type_env, res);
+         IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
+
+         if (!mode64 && (tyAddr != Ity_I32))
+            goto stmt_fail;
+
+         if (stmt->Ist.LLSC.storedata == NULL) {
+            /* LL */
+            MIPSAMode *r_addr;
+            /*constructs addressing mode from address provided */
+            r_addr = iselWordExpr_AMode(env, stmt->Ist.LLSC.addr, tyAddr);
+
+            HReg r_dst = lookupIRTemp(env, res);
+            if (tyRes == Ity_I32) {
+               addInstr(env, MIPSInstr_Load(4, r_dst, r_addr, mode64));
+               return;
+            } else if (tyRes == Ity_I64 && mode64) {
+               addInstr(env, MIPSInstr_Load(8, r_dst, r_addr, mode64));
+               return;
+            }
+            /* fallthru */ ;
+         } else {
+            /* SC */
+            MIPSAMode *r_addr;
+            r_addr = iselWordExpr_AMode(env, stmt->Ist.LLSC.addr, tyAddr);
+            HReg r_src = iselWordExpr_R(env, stmt->Ist.LLSC.storedata);
+            HReg r_dst = lookupIRTemp(env, res);
+            IRType tyData = typeOfIRExpr(env->type_env, 
+                                         stmt->Ist.LLSC.storedata);
+
+            if (tyData == Ity_I32) {
+               addInstr(env, MIPSInstr_Store(4, r_addr, r_src, mode64));
+               addInstr(env, MIPSInstr_LI(r_dst, 0x1));
+               return;
+            } else if (tyData == Ity_I64 && mode64) {
+               addInstr(env, MIPSInstr_Store(8, r_addr, r_src, mode64));
+               addInstr(env, MIPSInstr_LI(r_dst, 0x1));
+               return;
+            }
+            /* fallthru */
+         }
+         goto stmt_fail;
+       /*NOTREACHED*/}
+
+      /* --------- INSTR MARK --------- */
+      /* Doesn't generate any executable code ... */
+   case Ist_IMark:
+      return;
+
+      /* --------- ABI HINT --------- */
+      /* These have no meaning (denotation in the IR) and so we ignore
+         them ... if any actually made it this far. */
+   case Ist_AbiHint:
+      return;
+
+      /* --------- NO-OP --------- */
+      /* Fairly self-explanatory, wouldn't you say? */
+   case Ist_NoOp:
+      return;
+
+   /* --------- EXIT --------- */
+   case Ist_Exit: {
+      IRConst* dst = stmt->Ist.Exit.dst;
+      if (!mode64 && dst->tag != Ico_U32)
+         vpanic("iselStmt(mips32): Ist_Exit: dst is not a 32-bit value");
+      if (mode64 && dst->tag != Ico_U64)
+         vpanic("iselStmt(mips64): Ist_Exit: dst is not a 64-bit value");
+
+      MIPSCondCode cc   = iselCondCode(env, stmt->Ist.Exit.guard);
+      MIPSAMode*   amPC = MIPSAMode_IR(stmt->Ist.Exit.offsIP,
+                                      hregMIPS_GPR10(mode64));
+
+      /* Case: boring transfer to known address */
+      if (stmt->Ist.Exit.jk == Ijk_Boring
+          || stmt->Ist.Exit.jk == Ijk_Call
+          /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
+         if (env->chainingAllowed) {
+            /* .. almost always true .. */
+            /* Skip the event check at the dst if this is a forwards
+               edge. */
+            Bool toFastEP
+               = mode64
+               ? (((Addr64)stmt->Ist.Exit.dst->Ico.U64) > (Addr64)env->max_ga)
+               : (((Addr32)stmt->Ist.Exit.dst->Ico.U32) > (Addr32)env->max_ga);
+            if (0) vex_printf("%s", toFastEP ? "Y" : ",");
+            addInstr(env, MIPSInstr_XDirect(
+                             mode64 ? (Addr64)stmt->Ist.Exit.dst->Ico.U64
+                                    : (Addr64)stmt->Ist.Exit.dst->Ico.U32,
+                             amPC, cc, toFastEP));
+         } else {
+            /* .. very occasionally .. */
+            /* We can't use chaining, so ask for an assisted transfer,
+               as that's the only alternative that is allowable. */
+            HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
+            addInstr(env, MIPSInstr_XAssisted(r, amPC, cc, Ijk_Boring));
+         }
+         return;
+      }
+
+      /* Case: assisted transfer to arbitrary address */
+      switch (stmt->Ist.Exit.jk) {
+         /* Keep this list in sync with that in iselNext below */
+         case Ijk_ClientReq:
+         case Ijk_EmFail:
+         case Ijk_EmWarn:
+         case Ijk_NoDecode:
+         case Ijk_NoRedir:
+         case Ijk_SigBUS:
+         case Ijk_SigTRAP:
+         case Ijk_Sys_syscall:
+         case Ijk_TInval:
+         {
+            HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
+            addInstr(env, MIPSInstr_XAssisted(r, amPC, cc,
+                                             stmt->Ist.Exit.jk));
+            return;
+         }
+         default:
+            break;
+      }
+
+      /* Do we ever expect to see any other kind? */
+      goto stmt_fail;
+   }
+
+   default:
+      break;
+   }
+
+   stmt_fail:
+      vex_printf("stmt_fail tag: 0x%x\n", stmt->tag);
+      ppIRStmt(stmt);
+      vpanic("iselStmt:\n");
+}
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Basic block terminators (Nexts)             ---*/
+/*---------------------------------------------------------*/
+
+static void iselNext ( ISelEnv* env,
+                       IRExpr* next, IRJumpKind jk, Int offsIP )
+{
+   if (vex_traceflags & VEX_TRACE_VCODE) {
+      vex_printf( "\n-- PUT(%d) = ", offsIP);
+      ppIRExpr( next );
+      vex_printf( "; exit-");
+      ppIRJumpKind(jk);
+      vex_printf( "\n");
+   }
+
+   /* Case: boring transfer to known address */
+   if (next->tag == Iex_Const) {
+      IRConst* cdst = next->Iex.Const.con;
+      vassert(cdst->tag == (env->mode64 ? Ico_U64 :Ico_U32));
+      if (jk == Ijk_Boring || jk == Ijk_Call) {
+         /* Boring transfer to known address */
+         MIPSAMode* amPC = MIPSAMode_IR(offsIP, hregMIPS_GPR10(env->mode64));
+         if (env->chainingAllowed) {
+            /* .. almost always true .. */
+            /* Skip the event check at the dst if this is a forwards
+               edge. */
+            Bool toFastEP
+               = env->mode64
+               ? (((Addr64)cdst->Ico.U64) > (Addr64)env->max_ga)
+               : (((Addr32)cdst->Ico.U32) > (Addr32)env->max_ga);
+            if (0) vex_printf("%s", toFastEP ? "X" : ".");
+            addInstr(env, MIPSInstr_XDirect(
+                             env->mode64 ? (Addr64)cdst->Ico.U64
+                                         : (Addr64)cdst->Ico.U32,
+                             amPC, MIPScc_AL, toFastEP));
+         } else {
+            /* .. very occasionally .. */
+            /* We can't use chaining, so ask for an assisted transfer,
+               as that's the only alternative that is allowable. */
+            HReg r = iselWordExpr_R(env, next);
+            addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL,
+                                              Ijk_Boring));
+         }
+         return;
+      }
+   }
+
+   /* Case: call/return (==boring) transfer to any address */
+   switch (jk) {
+      case Ijk_Boring: case Ijk_Ret: case Ijk_Call: {
+
+         HReg       r     = iselWordExpr_R(env, next);
+         MIPSAMode*  amPC = MIPSAMode_IR(offsIP, hregMIPS_GPR10(env->mode64));
+         if (env->chainingAllowed) {
+            addInstr(env, MIPSInstr_XIndir(r, amPC, MIPScc_AL));
+         } else {
+            addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL,
+                                             Ijk_Boring));
+         }
+         return;
+      }
+      default:
+         break;
+   }
+
+   /* Case: assisted transfer to arbitrary address */
+   switch (jk) {
+      /* Keep this list in sync with that for Ist_Exit above */
+      case Ijk_ClientReq:
+      case Ijk_EmFail:
+      case Ijk_EmWarn:
+      case Ijk_NoDecode:
+      case Ijk_NoRedir:
+      case Ijk_SigBUS:
+      case Ijk_SigTRAP:
+      case Ijk_Sys_syscall:
+      case Ijk_TInval: {
+         HReg      r     = iselWordExpr_R(env, next);
+         MIPSAMode* amPC = MIPSAMode_IR(offsIP, hregMIPS_GPR10(env->mode64));
+         addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL, jk));
+         return;
+      }
+      default:
+         break;
+   }
+
+   vex_printf( "\n-- PUT(%d) = ", offsIP);
+   ppIRExpr( next );
+   vex_printf( "; exit-");
+   ppIRJumpKind(jk);
+   vex_printf( "\n");
+   vassert(0); // are we expecting any other kind?
+}
+
+/*---------------------------------------------------------*/
+/*--- Insn selector top-level                           ---*/
+/*---------------------------------------------------------*/
+
+/* Translate an entire BB to mips code. */
+HInstrArray *iselSB_MIPS ( IRSB* bb,
+                           VexArch arch_host,
+                           VexArchInfo* archinfo_host,
+                           VexAbiInfo* vbi,
+                           Int offs_Host_EvC_Counter,
+                           Int offs_Host_EvC_FailAddr,
+                           Bool chainingAllowed,
+                           Bool addProfInc,
+                           Addr64 max_ga )
+{
+   Int      i, j;
+   HReg     hreg, hregHI;
+   ISelEnv* env;
+   UInt     hwcaps_host = archinfo_host->hwcaps;
+   MIPSAMode *amCounter, *amFailAddr;
+
+   /* sanity ... */
+   vassert(arch_host == VexArchMIPS32);
+   vassert(VEX_PRID_COMP_MIPS == hwcaps_host
+           || VEX_PRID_COMP_BROADCOM == hwcaps_host);
+
+   mode64 = arch_host != VexArchMIPS32;
+
+   /* Make up an initial environment to use. */
+   env = LibVEX_Alloc(sizeof(ISelEnv));
+   env->vreg_ctr = 0;
+   env->mode64 = mode64;
+
+   /* Set up output code array. */
+   env->code = newHInstrArray();
+
+   /* Copy BB's type env. */
+   env->type_env = bb->tyenv;
+
+   /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
+      change as we go along. */
+   env->n_vregmap = bb->tyenv->types_used;
+   env->vregmap = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
+   env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
+
+   /* and finally ... */
+   env->hwcaps          = hwcaps_host;
+   env->chainingAllowed = chainingAllowed;
+   env->hwcaps          = hwcaps_host;
+   env->max_ga          = max_ga;
+
+   /* For each IR temporary, allocate a suitably-kinded virtual
+      register. */
+   j = 0;
+   for (i = 0; i < env->n_vregmap; i++) {
+      hregHI = hreg = INVALID_HREG;
+      switch (bb->tyenv->types[i]) {
+         case Ity_I1:
+         case Ity_I8:
+         case Ity_I16:
+         case Ity_I32: {
+            hreg = mkHReg(j++, HRcInt32, True);
+            break;
+         }
+         case Ity_I64: {
+            hreg = mkHReg(j++, HRcInt32, True);
+            hregHI = mkHReg(j++, HRcInt32, True);
+            break;
+         }
+         case Ity_I128:
+            vassert(mode64);
+            hreg = mkHReg(j++, HRcInt64, True);
+            hregHI = mkHReg(j++, HRcInt64, True);
+            break;
+         case Ity_F32: {
+            hreg = mkHReg(j++, HRcFlt32, True);
+            break;
+         }
+         case Ity_F64:
+            hreg = mkHReg(j++, HRcFlt64, True);
+            break;
+         default:
+            ppIRType(bb->tyenv->types[i]);
+            vpanic("iselBB(mips): IRTemp type");
+      }
+      env->vregmap[i] = hreg;
+      env->vregmapHI[i] = hregHI;
+   }
+   env->vreg_ctr = j;
+
+   /* The very first instruction must be an event check. */
+   amCounter = MIPSAMode_IR(offs_Host_EvC_Counter, hregMIPS_GPR10(mode64));
+   amFailAddr = MIPSAMode_IR(offs_Host_EvC_FailAddr, hregMIPS_GPR10(mode64));
+   addInstr(env, MIPSInstr_EvCheck(amCounter, amFailAddr));
+
+   /* Possibly a block counter increment (for profiling).  At this
+      point we don't know the address of the counter, so just pretend
+      it is zero.  It will have to be patched later, but before this
+      translation is used, by a call to LibVEX_patchProfCtr. */
+   if (addProfInc) {
+      addInstr(env, MIPSInstr_ProfInc());
+   }
+
+   /* Ok, finally we can iterate over the statements. */
+   for (i = 0; i < bb->stmts_used; i++)
+      iselStmt(env, bb->stmts[i]);
+
+   iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
+
+   /* record the number of vregs we used. */
+   env->code->n_vregs = env->vreg_ctr;
+   return env->code;
+
+}
+
+/*---------------------------------------------------------------*/
+/*--- end                                    host_mips_isel.c ---*/
+/*---------------------------------------------------------------*/
diff --git a/pub/libvex_guest_mips32.h b/pub/libvex_guest_mips32.h
new file mode 100644
index 0000000..177bf6b
--- /dev/null
+++ b/pub/libvex_guest_mips32.h
@@ -0,0 +1,161 @@
+
+/*---------------------------------------------------------------*/
+/*--- begin                             libvex_guest_mips32.h ---*/
+/*---------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2010-2012 RT-RK
+      mips-valgrind@rt-rk.com
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __LIBVEX_PUB_GUEST_MIPS32_H
+#define __LIBVEX_PUB_GUEST_MIPS32_H
+
+#include "libvex_basictypes.h"
+#include "libvex_emwarn.h"
+
+
+/*---------------------------------------------------------------*/
+/*--- Vex's representation of the MIPS32 CPU state.           ---*/
+/*---------------------------------------------------------------*/
+
+typedef
+   struct {
+      /* CPU Registers */
+      /*   0 */ UInt guest_r0; /* Hardwired to 0 */
+      /*   4 */ UInt guest_r1;   /* Assembler temporary */
+      /*   8 */ UInt guest_r2;   /* Values for function returns ...*/
+      /*   12 */ UInt guest_r3;   /* ...and expression evaluation */
+      /*   16 */ UInt guest_r4;   /* Function arguments */
+      /*   20 */ UInt guest_r5;
+      /*   24 */ UInt guest_r6;
+      /*   28 */ UInt guest_r7;
+      /*   32 */ UInt guest_r8;   /* Temporaries */
+      /*   36 */ UInt guest_r9;
+      /*   40 */ UInt guest_r10;
+      /*   44 */ UInt guest_r11;
+      /*   48 */ UInt guest_r12;
+      /*   52 */ UInt guest_r13;
+      /*   56 */ UInt guest_r14;
+      /*   60 */ UInt guest_r15;
+      /*   64 */ UInt guest_r16;   /* Saved temporaries */
+      /*   68 */ UInt guest_r17;
+      /*   72 */ UInt guest_r18;
+      /*   76 */ UInt guest_r19;
+      /*   80 */ UInt guest_r20;
+      /*   84 */ UInt guest_r21;
+      /*   88 */ UInt guest_r22;
+      /*   92 */ UInt guest_r23;
+      /*   96 */ UInt guest_r24;   /* Temporaries */
+      /*   100 */ UInt guest_r25;
+      /*   104 */ UInt guest_r26;   /* Reserved for OS kernel */
+      /*   108 */ UInt guest_r27;
+      /*   112 */ UInt guest_r28;   /* Global pointer */
+      /*   116 */ UInt guest_r29;   /* Stack pointer */
+      /*   120 */ UInt guest_r30;   /* Frame pointer */
+      /*   124 */ UInt guest_r31;   /* Return address */
+      /*   128 */ UInt guest_PC;   /* Program counter */
+      /*   132 */ UInt guest_HI;/* Multiply and divide register higher result */
+      /*   136 */ UInt guest_LO;/* Multiply and divide register lower result */
+
+      /* FPU Registers */
+      /*   140 */ UInt guest_f0; /* Floting point general purpose registers */
+      /*   144 */ UInt guest_f1;
+      /*   148 */ UInt guest_f2;
+      /*   152 */ UInt guest_f3;
+      /*   156 */ UInt guest_f4;
+      /*   160 */ UInt guest_f5;
+      /*   164 */ UInt guest_f6;
+      /*   168 */ UInt guest_f7;
+      /*   172 */ UInt guest_f8;
+      /*   176 */ UInt guest_f9;
+      /*   180 */ UInt guest_f10;
+      /*   184 */ UInt guest_f11;
+      /*   188 */ UInt guest_f12;
+      /*   192 */ UInt guest_f13;
+      /*   196 */ UInt guest_f14;
+      /*   200 */ UInt guest_f15;
+      /*   204 */ UInt guest_f16;
+      /*   208 */ UInt guest_f17;
+      /*   212 */ UInt guest_f18;
+      /*   216 */ UInt guest_f19;
+      /*   220 */ UInt guest_f20;
+      /*   224 */ UInt guest_f21;
+      /*   228 */ UInt guest_f22;
+      /*   232 */ UInt guest_f23;
+      /*   236 */ UInt guest_f24;
+      /*   240 */ UInt guest_f25;
+      /*   244 */ UInt guest_f26;
+      /*   248 */ UInt guest_f27;
+      /*   252 */ UInt guest_f28;
+      /*   256 */ UInt guest_f29;
+      /*   260 */ UInt guest_f30;
+      /*   264 */ UInt guest_f31;
+  
+      /*   268 */ UInt guest_FIR;
+      /*   272 */ UInt guest_FCCR;
+      /*   276 */ UInt guest_FEXR;
+      /*   280 */ UInt guest_FENR;
+      /*   284 */ UInt guest_FCSR;
+
+      /* TLS pointer for the thread. It's read-only in user space.
+         On Linux it is set in user space by various thread-related
+         syscalls.
+         User Local Register.
+         This register provides read access to the coprocessor 0
+         UserLocal register, if it is implemented. In some operating
+         environments, the UserLocal register is a pointer to a
+         thread-specific storage block.
+      */
+      /*   288 */ UInt guest_ULR;
+
+      /* Emulation warnings */
+          UInt   guest_EMWARN;  /* 292 */
+
+      /* For clflush: record start and length of area to invalidate */
+        UInt guest_TISTART;     /* 296 */
+        UInt guest_TILEN;       /* 300 */ 
+        UInt guest_NRADDR;      /* 304 */
+
+        UInt host_EvC_FAILADDR; /* 308 */
+        UInt host_EvC_COUNTER;  /* 312 */
+        UInt guest_COND;        /* 316 */
+} VexGuestMIPS32State;
+/*---------------------------------------------------------------*/
+/*--- Utility functions for MIPS32 guest stuff.               ---*/
+/*---------------------------------------------------------------*/
+
+/* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT */
+
+/* Initialise all guest MIPS32 state. */
+
+extern
+void LibVEX_GuestMIPS32_initialise ( /*OUT*/VexGuestMIPS32State* vex_state );
+
+
+#endif /* ndef __LIBVEX_PUB_GUEST_MIPS32_H */
+
+
+/*---------------------------------------------------------------*/
+/*---                                   libvex_guest_mips32.h ---*/
+/*---------------------------------------------------------------*/