1
2/*--------------------------------------------------------------------*/
3/*--- begin                                      guest_mips_toIR.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
9
10   Copyright (C) 2010-2012 RT-RK
11      mips-valgrind@rt-rk.com
12
13   This program is free software; you can redistribute it and/or
14   modify it under the terms of the GNU General Public License as
15   published by the Free Software Foundation; either version 2 of the
16   License, or (at your option) any later version.
17
18   This program is distributed in the hope that it will be useful, but
19   WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21   General Public License for more details.
22
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26   02111-1307, USA.
27
28   The GNU General Public License is contained in the file COPYING.
29*/
30
31/* Translates MIPS code to IR. */
32
33#include "libvex_basictypes.h"
34#include "libvex_ir.h"
35#include "libvex.h"
36#include "libvex_guest_mips32.h"
37
38#include "main_util.h"
39#include "main_globals.h"
40#include "guest_generic_bb_to_IR.h"
41#include "guest_mips_defs.h"
42
43/*------------------------------------------------------------*/
44/*--- Globals                                              ---*/
45/*------------------------------------------------------------*/
46
47/* These are set at the start of the translation of a instruction, so
48   that we don't have to pass them around endlessly.  CONST means does
49   not change during translation of the instruction.
50*/
51
52/* CONST: is the host bigendian?  This has to do with float vs double
53   register accesses on VFP, but it's complex and not properly thought
54   out. */
55static Bool host_is_bigendian;
56
57/* Pointer to the guest code area. */
58static UChar *guest_code;
59
60/* The guest address corresponding to guest_code[0]. */
61static Addr32 guest_PC_bbstart;
62
63/* CONST: The guest address for the instruction currently being
64   translated. */
65static Addr32 guest_PC_curr_instr;
66
67/* MOD: The IRSB* into which we're generating code. */
68static IRSB *irsb;
69
70/* Is our guest binary 32 or 64bit?  Set at each call to
71   disInstr_MIPS below. */
72static Bool mode64 = False;
73
74/*------------------------------------------------------------*/
75/*--- Debugging output                                     ---*/
76/*------------------------------------------------------------*/
77
78#define DIP(format, args...)           \
79   if (vex_traceflags & VEX_TRACE_FE)  \
80      vex_printf(format, ## args)
81
82/*------------------------------------------------------------*/
83/*--- Helper bits and pieces for deconstructing the        ---*/
84/*--- mips insn stream.                                    ---*/
85/*------------------------------------------------------------*/
86
87/* ---------------- Integer registers ---------------- */
88
89static UInt integerGuestRegOffset(UInt iregNo)
90{
91   /* Do we care about endianness here?  We do if sub-parts of integer
92      registers are accessed, but I don't think that ever happens on
93      MIPS. */
94   UInt ret;
95   switch (iregNo) {
96      case 0:
97         ret = offsetof(VexGuestMIPS32State, guest_r0); break;
98      case 1:
99         ret = offsetof(VexGuestMIPS32State, guest_r1); break;
100      case 2:
101         ret = offsetof(VexGuestMIPS32State, guest_r2); break;
102      case 3:
103         ret = offsetof(VexGuestMIPS32State, guest_r3); break;
104      case 4:
105         ret = offsetof(VexGuestMIPS32State, guest_r4); break;
106      case 5:
107         ret = offsetof(VexGuestMIPS32State, guest_r5); break;
108      case 6:
109         ret = offsetof(VexGuestMIPS32State, guest_r6); break;
110      case 7:
111         ret = offsetof(VexGuestMIPS32State, guest_r7); break;
112      case 8:
113         ret = offsetof(VexGuestMIPS32State, guest_r8); break;
114      case 9:
115         ret = offsetof(VexGuestMIPS32State, guest_r9); break;
116      case 10:
117         ret = offsetof(VexGuestMIPS32State, guest_r10); break;
118      case 11:
119         ret = offsetof(VexGuestMIPS32State, guest_r11); break;
120      case 12:
121         ret = offsetof(VexGuestMIPS32State, guest_r12); break;
122      case 13:
123         ret = offsetof(VexGuestMIPS32State, guest_r13); break;
124      case 14:
125         ret = offsetof(VexGuestMIPS32State, guest_r14); break;
126      case 15:
127         ret = offsetof(VexGuestMIPS32State, guest_r15); break;
128      case 16:
129         ret = offsetof(VexGuestMIPS32State, guest_r16); break;
130      case 17:
131         ret = offsetof(VexGuestMIPS32State, guest_r17); break;
132      case 18:
133         ret = offsetof(VexGuestMIPS32State, guest_r18); break;
134      case 19:
135         ret = offsetof(VexGuestMIPS32State, guest_r19); break;
136      case 20:
137         ret = offsetof(VexGuestMIPS32State, guest_r20); break;
138      case 21:
139         ret = offsetof(VexGuestMIPS32State, guest_r21); break;
140      case 22:
141         ret = offsetof(VexGuestMIPS32State, guest_r22); break;
142      case 23:
143         ret = offsetof(VexGuestMIPS32State, guest_r23); break;
144      case 24:
145         ret = offsetof(VexGuestMIPS32State, guest_r24); break;
146      case 25:
147         ret = offsetof(VexGuestMIPS32State, guest_r25); break;
148      case 26:
149         ret = offsetof(VexGuestMIPS32State, guest_r26); break;
150      case 27:
151         ret = offsetof(VexGuestMIPS32State, guest_r27); break;
152      case 28:
153         ret = offsetof(VexGuestMIPS32State, guest_r28); break;
154      case 29:
155         ret = offsetof(VexGuestMIPS32State, guest_r29); break;
156      case 30:
157         ret = offsetof(VexGuestMIPS32State, guest_r30); break;
158      case 31:
159         ret = offsetof(VexGuestMIPS32State, guest_r31); break;
160      default:
161         vassert(0);
162         break;
163   }
164   return ret;
165}
166
167#define OFFB_PC     offsetof(VexGuestMIPS32State, guest_PC)
168
169/* ---------------- Floating point registers ---------------- */
170
171static UInt floatGuestRegOffset(UInt fregNo)
172{
173   vassert(fregNo < 32);
174   UInt ret;
175   switch (fregNo) {
176      case 0:
177         ret = offsetof(VexGuestMIPS32State, guest_f0); break;
178      case 1:
179         ret = offsetof(VexGuestMIPS32State, guest_f1); break;
180      case 2:
181         ret = offsetof(VexGuestMIPS32State, guest_f2); break;
182      case 3:
183         ret = offsetof(VexGuestMIPS32State, guest_f3); break;
184      case 4:
185         ret = offsetof(VexGuestMIPS32State, guest_f4); break;
186      case 5:
187         ret = offsetof(VexGuestMIPS32State, guest_f5); break;
188      case 6:
189         ret = offsetof(VexGuestMIPS32State, guest_f6); break;
190      case 7:
191         ret = offsetof(VexGuestMIPS32State, guest_f7); break;
192      case 8:
193         ret = offsetof(VexGuestMIPS32State, guest_f8); break;
194      case 9:
195         ret = offsetof(VexGuestMIPS32State, guest_f9); break;
196      case 10:
197         ret = offsetof(VexGuestMIPS32State, guest_f10); break;
198      case 11:
199         ret = offsetof(VexGuestMIPS32State, guest_f11); break;
200      case 12:
201         ret = offsetof(VexGuestMIPS32State, guest_f12); break;
202      case 13:
203         ret = offsetof(VexGuestMIPS32State, guest_f13); break;
204      case 14:
205         ret = offsetof(VexGuestMIPS32State, guest_f14); break;
206      case 15:
207         ret = offsetof(VexGuestMIPS32State, guest_f15); break;
208      case 16:
209         ret = offsetof(VexGuestMIPS32State, guest_f16); break;
210      case 17:
211         ret = offsetof(VexGuestMIPS32State, guest_f17); break;
212      case 18:
213         ret = offsetof(VexGuestMIPS32State, guest_f18); break;
214      case 19:
215         ret = offsetof(VexGuestMIPS32State, guest_f19); break;
216      case 20:
217         ret = offsetof(VexGuestMIPS32State, guest_f20); break;
218      case 21:
219         ret = offsetof(VexGuestMIPS32State, guest_f21); break;
220      case 22:
221         ret = offsetof(VexGuestMIPS32State, guest_f22); break;
222      case 23:
223         ret = offsetof(VexGuestMIPS32State, guest_f23); break;
224      case 24:
225         ret = offsetof(VexGuestMIPS32State, guest_f24); break;
226      case 25:
227         ret = offsetof(VexGuestMIPS32State, guest_f25); break;
228      case 26:
229         ret = offsetof(VexGuestMIPS32State, guest_f26); break;
230      case 27:
231         ret = offsetof(VexGuestMIPS32State, guest_f27); break;
232      case 28:
233         ret = offsetof(VexGuestMIPS32State, guest_f28); break;
234      case 29:
235         ret = offsetof(VexGuestMIPS32State, guest_f29); break;
236      case 30:
237         ret = offsetof(VexGuestMIPS32State, guest_f30); break;
238      case 31:
239         ret = offsetof(VexGuestMIPS32State, guest_f31); break;
240      default:
241         vassert(0);
242         break;
243   }
244   return ret;
245}
246
247/* Do a endian load of a 32-bit word, regardless of the
248   endianness of the underlying host. */
249static inline UInt getUInt(UChar * p)
250{
251   UInt w = 0;
252#if defined (_MIPSEL)
253   w = (w << 8) | p[3];
254   w = (w << 8) | p[2];
255   w = (w << 8) | p[1];
256   w = (w << 8) | p[0];
257#elif defined (_MIPSEB)
258   w = (w << 8) | p[0];
259   w = (w << 8) | p[1];
260   w = (w << 8) | p[2];
261   w = (w << 8) | p[3];
262#endif
263   return w;
264}
265
266#define BITS2(_b1,_b0) \
267   (((_b1) << 1) | (_b0))
268
269#define BITS3(_b2,_b1,_b0)                      \
270  (((_b2) << 2) | ((_b1) << 1) | (_b0))
271
272#define BITS4(_b3,_b2,_b1,_b0) \
273   (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
274
275#define BITS5(_b4,_b3,_b2,_b1,_b0)  \
276   (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0)))
277
278#define BITS6(_b5,_b4,_b3,_b2,_b1,_b0)  \
279   ((BITS2((_b5),(_b4)) << 4) \
280    | BITS4((_b3),(_b2),(_b1),(_b0)))
281
282#define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0)  \
283   ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
284    | BITS4((_b3),(_b2),(_b1),(_b0)))
285
286#define LOAD_STORE_PATTERN \
287    t1 = newTemp(Ity_I32); \
288    assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); \
289
290#define LWX_SWX_PATTERN \
291   t2 = newTemp(Ity_I32); \
292   assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \
293   t4 = newTemp(Ity_I32); \
294   assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003)))
295
296#define SXXV_PATTERN(op) \
297   putIReg(rd, binop(op, \
298         getIReg(rt), \
299            unop(Iop_32to8, \
300               binop(Iop_And32, \
301                  getIReg(rs), \
302                  mkU32(0x0000001F) \
303               ) \
304            ) \
305         ) \
306      )
307
308#define SXX_PATTERN(op) \
309   putIReg(rd, binop(op, getIReg(rt), mkU8(sa)));
310
311#define ALU_PATTERN(op) \
312   putIReg(rd, binop(op, getIReg(rs), getIReg(rt)));
313
314#define ALUI_PATTERN(op) \
315   putIReg(rt, binop(op, getIReg(rs), mkU32(imm)));
316
317#define ALUI_PATTERN64(op) \
318   putIReg(rt, binop(op, getIReg(rs), mkU64(imm)));
319
320#define FP_CONDITIONAL_CODE \
321    t3 = newTemp(Ity_I32);  \
322    assign(t3, binop(Iop_And32, IRExpr_Mux0X( unop(Iop_1Uto8, \
323               binop(Iop_CmpEQ32, mkU32(cc), mkU32(0))), \
324               binop(Iop_Shr32, getFCSR(), mkU8(24+cc)),  \
325               binop(Iop_Shr32, getFCSR(), mkU8(23))), mkU32(0x1)));
326
327/*------------------------------------------------------------*/
328/*---                           Field helpers              ---*/
329/*------------------------------------------------------------*/
330
331static UInt get_opcode(UInt mipsins)
332{
333   return (0xFC000000 & mipsins) >> 26;
334}
335
336static UInt get_rs(UInt mipsins)
337{
338   return (0x03E00000 & mipsins) >> 21;
339}
340
341static UInt get_rt(UInt mipsins)
342{
343   return (0x001F0000 & mipsins) >> 16;
344}
345
346static UInt get_imm(UInt mipsins)
347{
348   return (0x0000FFFF & mipsins);
349}
350
351static UInt get_instr_index(UInt mipsins)
352{
353   return (0x03FFFFFF & mipsins);
354}
355
356static UInt get_rd(UInt mipsins)
357{
358   return (0x0000F800 & mipsins) >> 11;
359}
360
361static UInt get_sa(UInt mipsins)
362{
363   return (0x000007C0 & mipsins) >> 6;
364}
365
366static UInt get_function(UInt mipsins)
367{
368   return (0x0000003F & mipsins);
369}
370
371static UInt get_ft(UInt mipsins)
372{
373   return (0x001F0000 & mipsins) >> 16;
374}
375
376static UInt get_fs(UInt mipsins)
377{
378   return (0x0000F800 & mipsins) >> 11;
379}
380
381static UInt get_fd(UInt mipsins)
382{
383   return (0x000007C0 & mipsins) >> 6;
384}
385
386static UInt get_mov_cc(UInt mipsins)
387{
388   return (0x001C0000 & mipsins) >> 18;
389}
390
391static UInt get_bc1_cc(UInt mipsins)
392{
393   return (0x001C0000 & mipsins) >> 18;
394}
395
396static UInt get_fpc_cc(UInt mipsins)
397{
398   return (0x00000700 & mipsins) >> 8;
399}
400
401static UInt get_tf(UInt mipsins)
402{
403   return (0x00010000 & mipsins) >> 16;
404}
405
406static UInt get_nd(UInt mipsins)
407{
408   return (0x00020000 & mipsins) >> 17;
409}
410
411static UInt get_fmt(UInt mipsins)
412{
413   return (0x03E00000 & mipsins) >> 21;
414}
415
416static UInt get_FC(UInt mipsins)
417{
418   return (0x000000F0 & mipsins) >> 4;
419}
420
421static UInt get_cond(UInt mipsins)
422{
423   return (0x0000000F & mipsins);
424}
425
426/* for break & syscall */
427static UInt get_code(UInt mipsins)
428{
429   return (0xFFC0 & mipsins) >> 6;
430}
431
432static UInt get_lsb(UInt mipsins)
433{
434   return (0x7C0 & mipsins) >> 6;
435}
436
437static UInt get_msb(UInt mipsins)
438{
439   return (0x0000F800 & mipsins) >> 11;
440}
441
442static UInt get_rot(UInt mipsins)
443{
444   return (0x00200000 & mipsins) >> 21;
445}
446
447static UInt get_rotv(UInt mipsins)
448{
449   return (0x00000040 & mipsins) >> 6;
450}
451
452static UInt get_sel(UInt mipsins)
453{
454   return (0x00000007 & mipsins);
455}
456
457static Bool branch_or_jump(UChar * addr)
458{
459   UInt fmt;
460   UInt cins = getUInt(addr);
461
462   UInt opcode = get_opcode(cins);
463   UInt rt = get_rt(cins);
464   UInt function = get_function(cins);
465
466   /* bgtz, blez, bne, beq, jal */
467   if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04
468       || opcode == 0x03 || opcode == 0x02) {
469      return True;
470   }
471
472   /* bgez */
473   if (opcode == 0x01 && rt == 0x01) {
474      return True;
475   }
476
477   /* bgezal */
478   if (opcode == 0x01 && rt == 0x11) {
479      return True;
480   }
481
482   /* bltzal */
483   if (opcode == 0x01 && rt == 0x10) {
484      return True;
485   }
486
487   /* bltz */
488   if (opcode == 0x01 && rt == 0x00) {
489      return True;
490   }
491
492   /* jalr */
493   if (opcode == 0x00 && function == 0x09) {
494      return True;
495   }
496
497   /* jr */
498   if (opcode == 0x00 && function == 0x08) {
499      return True;
500   }
501
502   if (opcode == 0x11) {
503      /*bc1f & bc1t */
504      fmt = get_fmt(cins);
505      if (fmt == 0x08) {
506         return True;
507      }
508   }
509
510   return False;
511}
512
513static Bool is_Branch_or_Jump_and_Link(UChar * addr)
514{
515   UInt cins = getUInt(addr);
516
517   UInt opcode = get_opcode(cins);
518   UInt rt = get_rt(cins);
519   UInt function = get_function(cins);
520
521   /* jal */
522   if (opcode == 0x02) {
523      return True;
524   }
525
526   /* bgezal */
527   if (opcode == 0x01 && rt == 0x11) {
528      return True;
529   }
530
531   /* bltzal */
532   if (opcode == 0x01 && rt == 0x10) {
533      return True;
534   }
535
536   /* jalr */
537   if (opcode == 0x00 && function == 0x09) {
538      return True;
539   }
540
541   return False;
542}
543
544static Bool branch_or_link_likely(UChar * addr)
545{
546   UInt cins = getUInt(addr);
547   UInt opcode = get_opcode(cins);
548   UInt rt = get_rt(cins);
549
550   /* bgtzl, blezl, bnel, beql */
551   if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14)
552      return True;
553
554   /* bgezl */
555   if (opcode == 0x01 && rt == 0x03)
556      return True;
557
558   /* bgezall */
559   if (opcode == 0x01 && rt == 0x13)
560      return True;
561
562   /* bltzall */
563   if (opcode == 0x01 && rt == 0x12)
564      return True;
565
566   /* bltzl */
567   if (opcode == 0x01 && rt == 0x02)
568      return True;
569
570   return False;
571}
572
573/*------------------------------------------------------------*/
574/*--- Helper bits and pieces for creating IR fragments.    ---*/
575/*------------------------------------------------------------*/
576
577static IRExpr *mkU8(UInt i)
578{
579   vassert(i < 256);
580   return IRExpr_Const(IRConst_U8((UChar) i));
581}
582
583/* Create an expression node for a 32-bit integer constant */
584static IRExpr *mkU32(UInt i)
585{
586   return IRExpr_Const(IRConst_U32(i));
587}
588
589/* Create an expression node for a 64-bit integer constant */
590static IRExpr *mkU64(ULong i)
591{
592   return IRExpr_Const(IRConst_U64(i));
593}
594
595static IRExpr *mkexpr(IRTemp tmp)
596{
597   return IRExpr_RdTmp(tmp);
598}
599
600static IRExpr *unop(IROp op, IRExpr * a)
601{
602   return IRExpr_Unop(op, a);
603}
604
605static IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2)
606{
607   return IRExpr_Binop(op, a1, a2);
608}
609
610static IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3)
611{
612   return IRExpr_Triop(op, a1, a2, a3);
613}
614
615static IRExpr *load(IRType ty, IRExpr * addr)
616{
617   IRExpr *load1 = NULL;
618#if defined (_MIPSEL)
619   load1 = IRExpr_Load(Iend_LE, ty, addr);
620#elif defined (_MIPSEB)
621   load1 = IRExpr_Load(Iend_BE, ty, addr);
622#endif
623   return load1;
624}
625
626/* Add a statement to the list held by "irsb". */
627static void stmt(IRStmt * st)
628{
629   addStmtToIRSB(irsb, st);
630}
631
632static void assign(IRTemp dst, IRExpr * e)
633{
634   stmt(IRStmt_WrTmp(dst, e));
635}
636
637static void store(IRExpr * addr, IRExpr * data)
638{
639#if defined (_MIPSEL)
640   stmt(IRStmt_Store(Iend_LE, addr, data));
641#elif defined (_MIPSEB)
642   stmt(IRStmt_Store(Iend_BE, addr, data));
643#endif
644}
645
646/* Generate a new temporary of the given type. */
647static IRTemp newTemp(IRType ty)
648{
649   vassert(isPlausibleIRType(ty));
650   return newIRTemp(irsb->tyenv, ty);
651}
652
653/* Generate an expression for SRC rotated right by ROT. */
654static IRExpr *genROR32(IRExpr * src, Int rot)
655{
656   vassert(rot >= 0 && rot < 32);
657   if (rot == 0)
658      return src;
659   return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)),
660                          binop(Iop_Shr32, src, mkU8(rot)));
661}
662
663static IRExpr *genRORV32(IRExpr * src, IRExpr * rs)
664{
665   IRTemp t0 = newTemp(Ity_I8);
666   IRTemp t1 = newTemp(Ity_I8);
667
668   assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F))));
669   assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0)));
670   return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)),
671                          binop(Iop_Shr32, src, mkexpr(t0)));
672}
673
674static UInt extend_s_16to32(UInt x)
675{
676   return (UInt) ((((Int) x) << 16) >> 16);
677}
678
679static UInt extend_s_18to32(UInt x)
680{
681   return (UInt) ((((Int) x) << 14) >> 14);
682}
683
684static void jmp_lit( /*MOD*/DisResult* dres,
685                     IRJumpKind kind, Addr32 d32 )
686{
687   vassert(dres->whatNext    == Dis_Continue);
688   vassert(dres->len         == 0);
689   vassert(dres->continueAt  == 0);
690   vassert(dres->jk_StopHere == Ijk_INVALID);
691   dres->whatNext    = Dis_StopHere;
692   dres->jk_StopHere = kind;
693   stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) );
694}
695
696/* Fetch a byte from the guest insn stream. */
697static UChar getIByte(Int delta)
698{
699   return guest_code[delta];
700}
701
702static IRExpr *getIReg(UInt iregNo)
703{
704   if (0 == iregNo) {
705      return mode64 ? mkU64(0x0) : mkU32(0x0);
706   } else {
707      IRType ty = mode64 ? Ity_I64 : Ity_I32;
708      vassert(iregNo < 32);
709      return IRExpr_Get(integerGuestRegOffset(iregNo), ty);
710   }
711}
712
713static IRExpr *getHI(void)
714{
715   return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32);
716}
717
718static IRExpr *getLO(void)
719{
720   return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32);
721}
722
723static IRExpr *getFCSR(void)
724{
725   return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32);
726}
727
728static void putFCSR(IRExpr * e)
729{
730   stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
731}
732
733static IRExpr *getULR(void)
734{
735   return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32);
736}
737
738static void putIReg(UInt archreg, IRExpr * e)
739{
740   IRType ty = mode64 ? Ity_I64 : Ity_I32;
741   vassert(archreg < 32);
742   vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
743   if (archreg != 0)
744      stmt(IRStmt_Put(integerGuestRegOffset(archreg), e));
745}
746
747static void putLO(IRExpr * e)
748{
749   stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e));
750}
751
752static void putHI(IRExpr * e)
753{
754   stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e));
755}
756
757static void putPC(IRExpr * e)
758{
759   stmt(IRStmt_Put(OFFB_PC, e));
760}
761
762static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined)
763{
764   vassert(ty == Ity_I32 || ty == Ity_I64);
765   if (ty == Ity_I32)
766      return src;
767   return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
768}
769
770/* Narrow 8/16/32 bit int expr to 8/16/32.  Clearly only some
771   of these combinations make sense. */
772static IRExpr *narrowTo(IRType dst_ty, IRExpr * e)
773{
774   IRType src_ty = typeOfIRExpr(irsb->tyenv, e);
775   if (src_ty == dst_ty)
776      return e;
777   if (src_ty == Ity_I32 && dst_ty == Ity_I16)
778      return unop(Iop_32to16, e);
779   if (src_ty == Ity_I32 && dst_ty == Ity_I8)
780      return unop(Iop_32to8, e);
781   if (src_ty == Ity_I64 && dst_ty == Ity_I8) {
782      vassert(mode64);
783      return unop(Iop_64to8, e);
784   }
785   if (src_ty == Ity_I64 && dst_ty == Ity_I16) {
786      vassert(mode64);
787      return unop(Iop_64to16, e);
788   }
789
790   if (vex_traceflags & VEX_TRACE_FE) {
791      vex_printf("\nsrc, dst tys are: ");
792      ppIRType(src_ty);
793      vex_printf(", ");
794      ppIRType(dst_ty);
795      vex_printf("\n");
796   }
797
798   vpanic("narrowTo(mips)");
799   return 0;
800}
801
802static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src)
803{
804   vassert(ty == Ity_I32 || ty == Ity_I64);
805   return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
806}
807
808static IRExpr *getLoFromF64(IRType ty, IRExpr * src)
809{
810   vassert(ty == Ity_F32 || ty == Ity_F64);
811   if (ty == Ity_F64) {
812      IRTemp t0, t1;
813      t0 = newTemp(Ity_I64);
814      t1 = newTemp(Ity_I32);
815      assign(t0, unop(Iop_ReinterpF64asI64, src));
816      assign(t1, unop(Iop_64to32, mkexpr(t0)));
817      return unop(Iop_ReinterpI32asF32, mkexpr(t1));
818   } else
819      return src;
820}
821
822static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src)
823{
824   vassert(ty == Ity_F32 || ty == Ity_F64);
825   return ty == Ity_F64 ? unop(Iop_F32toF64, src) : src;
826}
827
828static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm)
829{
830   ULong branch_offset;
831   IRTemp t0;
832
833   /* PC = PC + (SignExtend(signed_immed_24) << 2)
834      An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
835      is added to the address of the instruction following
836      the branch (not the branch itself), in the branch delay slot, to form
837      a PC-relative effective target address. */
838   branch_offset = extend_s_18to32(imm << 2);
839
840   t0 = newTemp(Ity_I1);
841   assign(t0, guard);
842
843   stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
844                    IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC));
845
846   irsb->jumpkind = Ijk_Boring;
847
848   return mkU32(guest_PC_curr_instr + 4 + branch_offset);
849}
850
851static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set)
852{
853   ULong branch_offset;
854   IRTemp t0;
855
856   if (link) {    // LR (GPR31) = addr of the 2nd instr after branch instr
857      putIReg(31, mkU32(guest_PC_curr_instr + 8));
858   }
859
860   /* PC = PC + (SignExtend(signed_immed_24) << 2)
861      An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
862      is added to the address of the instruction following
863      the branch (not the branch itself), in the branch delay slot, to form
864      a PC-relative effective target address. */
865
866   branch_offset = extend_s_18to32(imm << 2);
867
868   t0 = newTemp(Ity_I1);
869   assign(t0, guard);
870   *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
871                   IRConst_U32(guest_PC_curr_instr + 4 + (UInt) branch_offset),
872                   OFFB_PC);
873}
874
875static IRExpr *getFReg(UInt dregNo)
876{
877   vassert(dregNo < 32);
878   IRType ty = mode64 ? Ity_F64 : Ity_F32;
879   return IRExpr_Get(floatGuestRegOffset(dregNo), ty);
880}
881
882static IRExpr *getDReg(UInt dregNo)
883{
884   vassert(dregNo < 32);
885   IRTemp t0 = newTemp(Ity_F32);
886   IRTemp t1 = newTemp(Ity_F32);
887   IRTemp t2 = newTemp(Ity_F64);
888   IRTemp t3 = newTemp(Ity_I32);
889   IRTemp t4 = newTemp(Ity_I32);
890   IRTemp t5 = newTemp(Ity_I64);
891
892   assign(t0, getFReg(dregNo));
893   assign(t1, getFReg(dregNo + 1));
894
895   assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
896   assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
897   assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3)));
898   assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5)));
899
900   return mkexpr(t2);
901}
902
903static void putFReg(UInt dregNo, IRExpr * e)
904{
905   vassert(dregNo < 32);
906   IRType ty = mode64 ? Ity_F64 : Ity_F32;
907   vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
908   stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
909}
910
911static void putDReg(UInt dregNo, IRExpr * e)
912{
913   vassert(dregNo < 32);
914   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
915   IRTemp t1 = newTemp(Ity_F64);
916   IRTemp t4 = newTemp(Ity_I32);
917   IRTemp t5 = newTemp(Ity_I32);
918   IRTemp t6 = newTemp(Ity_I64);
919   assign(t1, e);
920   assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1)));
921   assign(t4, unop(Iop_64HIto32, mkexpr(t6)));  // hi
922   assign(t5, unop(Iop_64to32, mkexpr(t6))); //lo
923   putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t5)));
924   putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
925}
926
927static void setFPUCondCode(IRExpr * e, UInt cc)
928{
929   if (cc == 0) {
930      DIP("setFpu: %d\n", cc);
931      putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF)));
932      putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23))));
933   } else {
934      DIP("setFpu1: %d\n", cc);
935      putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32,
936                               binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc)))));
937      putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc))));
938   }
939}
940
941static IRExpr */* :: Ity_I32 */get_IR_roundingmode(void)
942{
943/*
944   rounding mode | MIPS | IR
945   ------------------------
946   to nearest    | 00  | 00
947   to zero       | 01  | 11
948   to +infinity  | 10  | 10
949   to -infinity  | 11  | 01
950*/
951   IRTemp rm_MIPS = newTemp(Ity_I32);
952   /* Last two bits in FCSR are rounding mode. */
953
954   assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
955                                    guest_FCSR), Ity_I32), mkU32(3)));
956
957   // rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2)
958
959   return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
960                binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
961}
962
963/*********************************************************/
964/*---             Floating Point Compare              ---*/
965/*********************************************************/
966static Bool dis_instr_CCondFmt(UInt cins)
967{
968   IRTemp t0, t1, t2, t3;
969   IRTemp ccIR = newTemp(Ity_I32);
970   IRTemp ccMIPS = newTemp(Ity_I32);
971   UInt FC = get_FC(cins);
972   UInt fmt = get_fmt(cins);
973   UInt fs = get_fs(cins);
974   UInt ft = get_ft(cins);
975   UInt cond = get_cond(cins);
976
977   if (FC == 0x3) {  // C.cond.fmt
978      UInt fpc_cc = get_fpc_cc(cins);
979      switch (fmt) {
980         case 0x10: {  //C.cond.S
981            DIP("C.cond.S %d f%d, f%d\n", fpc_cc, fs, ft);
982            t0 = newTemp(Ity_I32);
983            t1 = newTemp(Ity_I32);
984            t2 = newTemp(Ity_I32);
985            t3 = newTemp(Ity_I32);
986
987            assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)),
988                                           unop(Iop_F32toF64, getFReg(ft))));
989            /* Map compare result from IR to MIPS */
990            /*
991               FP cmp result | MIPS | IR
992               --------------------------
993               UN            | 0x1 | 0x45
994               EQ            | 0x2 | 0x40
995               GT            | 0x4 | 0x00
996               LT            | 0x8 | 0x01
997             */
998
999            // ccMIPS = Shl(1, (~(ccIR>>5) & 2)
1000            //                    | ((ccIR ^ (ccIR>>6)) & 1)
1001            assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
1002                           binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
1003                           binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
1004                           binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
1005                           binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
1006                           mkU32(1))))));
1007            assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));   // UN
1008            assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
1009                   mkU8(0x1)), mkU32(0x1))); // EQ
1010            assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
1011                   mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));  // NGT
1012            assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
1013                   mkU8(0x3)), mkU32(0x1))); // LT
1014
1015            switch (cond) {
1016               case 0x0:
1017                  setFPUCondCode(mkU32(0), fpc_cc);
1018                  break;
1019               case 0x1:
1020                  DIP("unorderd: %d\n", fpc_cc);
1021                  setFPUCondCode(mkexpr(t0), fpc_cc);
1022                  break;
1023               case 0x2:
1024                  setFPUCondCode(mkexpr(t1), fpc_cc);
1025                  break;
1026               case 0x3:
1027                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
1028                                       fpc_cc);
1029                  break;
1030               case 0x4:
1031                  setFPUCondCode(mkexpr(t3), fpc_cc);
1032                  break;
1033               case 0x5:
1034                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
1035                                       fpc_cc);
1036                  break;
1037               case 0x6:
1038                  setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
1039                                       fpc_cc);
1040                  break;
1041               case 0x7:
1042                  setFPUCondCode(mkexpr(t2), fpc_cc);
1043                  break;
1044               case 0x8:
1045                  setFPUCondCode(mkU32(0), fpc_cc);
1046                  break;
1047               case 0x9:
1048                  setFPUCondCode(mkexpr(t0), fpc_cc);
1049                  break;
1050               case 0xA:
1051                  setFPUCondCode(mkexpr(t1), fpc_cc);
1052                  break;
1053               case 0xB:
1054                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
1055                                       fpc_cc);
1056                  break;
1057               case 0xC:
1058                  setFPUCondCode(mkexpr(t3), fpc_cc);
1059                  break;
1060               case 0xD:
1061                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
1062                                       fpc_cc);
1063                  break;
1064               case 0xE:
1065                  setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
1066                                       fpc_cc);
1067                  break;
1068               case 0xF:
1069                  setFPUCondCode(mkexpr(t2), fpc_cc);
1070                  break;
1071
1072               default:
1073                  return False;
1074            }
1075         }
1076            break;
1077
1078         case 0x11:  //C.cond.D
1079            DIP("C.%d.D %d f%d, f%d\n", cond, fpc_cc, fs, ft);
1080            t0 = newTemp(Ity_I32);
1081            t1 = newTemp(Ity_I32);
1082            t2 = newTemp(Ity_I32);
1083            t3 = newTemp(Ity_I32);
1084            assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
1085            /* Map compare result from IR to MIPS */
1086            /*
1087               FP cmp result | MIPS | IR
1088               --------------------------
1089               UN            | 0x1 | 0x45
1090               EQ            | 0x2 | 0x40
1091               GT            | 0x4 | 0x00
1092               LT            | 0x8 | 0x01
1093             */
1094
1095            // ccMIPS = Shl(1, (~(ccIR>>5) & 2)
1096            //                    | ((ccIR ^ (ccIR>>6)) & 1)
1097            assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
1098                           binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
1099                           binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
1100                           binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
1101                           binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
1102                           mkU32(1))))));
1103
1104            assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));   // UN
1105            assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
1106                   mkU8(0x1)), mkU32(0x1))); // EQ
1107            assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
1108                   mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));  // NGT
1109            assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
1110                   mkU8(0x3)), mkU32(0x1))); // LT
1111
1112            switch (cond) {
1113               case 0x0:
1114                  setFPUCondCode(mkU32(0), fpc_cc);
1115                  break;
1116               case 0x1:
1117                  DIP("unorderd: %d\n", fpc_cc);
1118                  setFPUCondCode(mkexpr(t0), fpc_cc);
1119                  break;
1120               case 0x2:
1121                  setFPUCondCode(mkexpr(t1), fpc_cc);
1122                  break;
1123               case 0x3:
1124                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
1125                                       fpc_cc);
1126                  break;
1127               case 0x4:
1128                  setFPUCondCode(mkexpr(t3), fpc_cc);
1129                  break;
1130               case 0x5:
1131                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
1132                                       fpc_cc);
1133                  break;
1134               case 0x6:
1135                  setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
1136                                       fpc_cc);
1137                  break;
1138               case 0x7:
1139                  setFPUCondCode(mkexpr(t2), fpc_cc);
1140                  break;
1141               case 0x8:
1142                  setFPUCondCode(mkU32(0), fpc_cc);
1143                  break;
1144               case 0x9:
1145                  setFPUCondCode(mkexpr(t0), fpc_cc);
1146                  break;
1147               case 0xA:
1148                  setFPUCondCode(mkexpr(t1), fpc_cc);
1149                  break;
1150               case 0xB:
1151                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
1152                                       fpc_cc);
1153                  break;
1154               case 0xC:
1155                  setFPUCondCode(mkexpr(t3), fpc_cc);
1156                  break;
1157               case 0xD:
1158                  setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
1159                                       fpc_cc);
1160                  break;
1161               case 0xE:
1162                  setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
1163                                       fpc_cc);
1164                  break;
1165               case 0xF:
1166                  setFPUCondCode(mkexpr(t2), fpc_cc);
1167                  break;
1168               default:
1169                  return False;
1170            }
1171            break;
1172
1173            default:
1174               return False;
1175      }
1176   } else {
1177      return False;
1178   }
1179
1180   return True;
1181}
1182
1183/*------------------------------------------------------------*/
1184/*--- Disassemble a single instruction                     ---*/
1185/*------------------------------------------------------------*/
1186
1187/* Disassemble a single instruction into IR.  The instruction is
1188   located in host memory at guest_instr, and has guest IP of
1189   guest_PC_curr_instr, which will have been set before the call
1190   here. */
1191
1192static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
1193                                                                    Addr64),
1194                                     Bool         resteerCisOk,
1195                                     void*        callback_opaque,
1196                                     Long         delta64,
1197                                     VexArchInfo* archinfo,
1198                                     VexAbiInfo*  abiinfo )
1199{
1200   IRTemp t0, t1, t2, t3, t4, t5, t6, t7, t8;
1201   UInt opcode, cins, rs, rt, rd, sa, ft, fs, fd, fmt, tf, nd, function,
1202        trap_code, imm, instr_index, p, msb, lsb, size, rot, sel;
1203
1204   DisResult dres;
1205
1206   static IRExpr *lastn = NULL;  /* last jump addr */
1207   static IRStmt *bstmt = NULL;  /* branch (Exit) stmt */
1208
1209   /* The running delta */
1210   Int delta = (Int) delta64;
1211
1212   /* Holds eip at the start of the insn, so that we can print
1213      consistent error messages for unimplemented insns. */
1214   Int delta_start = delta;
1215
1216   /* Are we in a delay slot ? */
1217   Bool delay_slot_branch, likely_delay_slot, delay_slot_jump;
1218
1219   /* Set result defaults. */
1220   dres.whatNext = Dis_Continue;
1221   dres.len = 0;
1222   dres.continueAt = 0;
1223   dres.jk_StopHere = Ijk_INVALID;
1224
1225   delay_slot_branch = likely_delay_slot = delay_slot_jump = False;
1226
1227   UChar *code = (UChar *) (guest_code + delta);
1228   cins = getUInt(code);
1229
1230   if (delta != 0) {
1231      if (branch_or_jump(guest_code + delta - 4)) {
1232         if (lastn == NULL && bstmt == NULL) {
1233            DIP("Info: jump to delay slot insn...\n");
1234         } else {
1235            dres.whatNext = Dis_StopHere;
1236
1237            DIP("lastn = %p bstmt = %p\n", lastn, bstmt);
1238            if (lastn != NULL) {
1239               DIP("delay slot jump\n");
1240               if (vex_traceflags & VEX_TRACE_FE)
1241                  ppIRExpr(lastn);
1242               delay_slot_jump = True;
1243            } else if (bstmt != NULL) {
1244               DIP("\ndelay slot branch\n");
1245               delay_slot_branch = True;
1246            }
1247            DIP("delay slot\n");
1248         }
1249      }
1250
1251      if (branch_or_link_likely(guest_code + delta - 4)) {
1252         likely_delay_slot = True;
1253      }
1254   }
1255
1256   /* Spot "Special" instructions (see comment at top of file). */
1257   {
1258      /* Spot the 16-byte preamble:
1259       ****mips32****
1260       "srl $0, $0, 13
1261       "srl $0, $0, 29
1262       "srl $0, $0, 3
1263       "srl $0, $0, 19 */
1264      UInt word1 = 0x00000342;
1265      UInt word2 = 0x00000742;
1266      UInt word3 = 0x000000C2;
1267      UInt word4 = 0x000004C2;
1268      if (getUInt(code + 0) == word1 && getUInt(code + 4) == word2 &&
1269          getUInt(code + 8) == word3 && getUInt(code + 12) == word4) {
1270         /* Got a "Special" instruction preamble.  Which one is it? */
1271         if (getUInt(code + 16) == 0x01ad6825 /* or t5, t5, t5 */ ) {
1272            /* v0 = client_request ( t9 ) */
1273            DIP("v0 = client_request ( t9 )\n");
1274            putPC(mkU32(guest_PC_curr_instr + 20));
1275            dres.jk_StopHere = Ijk_ClientReq;
1276            dres.whatNext    = Dis_StopHere;
1277
1278            goto decode_success;
1279         } else if (getUInt(code + 16) == 0x01ce7025 /* or t6,t6,t6 */ ) {
1280            /* t9 = guest_NRADDR */
1281            DIP("t9 = guest_NRADDR\n");
1282            dres.len = 20;
1283            delta += 20;
1284            putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State, guest_NRADDR),
1285                                   Ity_I32));
1286            goto decode_success;
1287         } else if (getUInt(code + 16) == 0x01ef7825/* or t7,t7,t7 */ ) {
1288            /*  branch-and-link-to-noredir t9 */
1289            DIP("branch-and-link-to-noredir t9\n");
1290            putIReg(31, mkU32(guest_PC_curr_instr + 20));
1291            putPC(getIReg(25));
1292            dres.jk_StopHere = Ijk_NoRedir;
1293            dres.whatNext    = Dis_StopHere;
1294            goto decode_success;
1295         }
1296
1297         /* We don't know what it is.  Set opc1/opc2 so decode_failure
1298            can print the insn following the Special-insn preamble. */
1299         delta += 16;
1300         goto decode_failure;
1301       /*NOTREACHED*/}
1302   }
1303
1304   opcode = get_opcode(cins);
1305   imm = get_imm(cins);
1306   rs = get_rs(cins);
1307   rt = get_rt(cins);
1308   rd = get_rd(cins);
1309   sa = get_sa(cins);
1310   fs = get_fs(cins);
1311   fd = get_fd(cins);
1312   ft = get_ft(cins);
1313   tf = get_tf(cins);
1314   nd = get_nd(cins);
1315   sel = get_sel(cins);
1316   fmt = get_fmt(cins);
1317   instr_index = get_instr_index(cins);
1318   trap_code = get_code(cins);
1319   function = get_function(cins);
1320   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1321   IRType tyF = mode64 ? Ity_F64 : Ity_F32;
1322
1323   DIP("[cins = 0x%08x] ", cins);
1324
1325   switch (opcode) {
1326
1327   case 0x03:     /* JAL */
1328      DIP("jal 0x%x", instr_index);
1329      putIReg(31, mkU32(guest_PC_curr_instr + 8));
1330      t0 = newTemp(ty);
1331      assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
1332                       (instr_index << 2)));
1333      lastn = mkexpr(t0);
1334      break;
1335   case 0x02:     /* J */
1336      DIP("j 0x%x", instr_index);
1337      t0 = newTemp(ty);
1338      assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
1339                       (instr_index << 2)));
1340      lastn = mkexpr(t0);
1341      break;
1342
1343   case 0x11:     /* COP1 */
1344      {
1345         UInt bc1_cc = get_bc1_cc(cins);
1346         if (0x08 == fmt) {
1347            switch (fmt) {
1348            case 0x08:  //BC
1349               {
1350                  DIP("tf: %d, nd: %d\n", tf, nd);
1351                  //FcConditionalCode(bc1_cc)
1352                  t1 = newTemp(Ity_I32);
1353                  t2 = newTemp(Ity_I32);
1354                  t3 = newTemp(Ity_I1);
1355
1356                  assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
1357                                                    mkU32(bc1_cc))));
1358                  assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
1359                             binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
1360                             mkU8(24 + bc1_cc)), mkU32(0x1)), binop(Iop_And32,
1361                             binop(Iop_Shr32, getFCSR(), mkU8(23)),
1362                                   mkU32(0x1))));
1363
1364                  if (tf == 1 && nd == 0) {
1365                     //branch on true
1366                     DIP("bc1t %d, %d", bc1_cc, imm);
1367                     assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
1368                     dis_branch(False, mkexpr(t3), imm, &bstmt);
1369                     break;
1370                  } else if (tf == 0 && nd == 0) {
1371                     //branch on false
1372                     DIP("bc1f %d, %d", bc1_cc, imm);
1373                     assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
1374                     dis_branch(False, mkexpr(t3), imm, &bstmt);
1375                     break;
1376                  } else if (nd == 1 && tf == 0) {
1377                     DIP("bc1fl %d, %d", bc1_cc, imm);
1378                     lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2),
1379                           mode64 ? mkU64(0x0) : mkU32(0x0)), imm);
1380                     break;
1381                  } else if (nd == 1 && tf == 1) {
1382                     DIP("bc1tl %d, %d", bc1_cc, imm);
1383                     lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2),
1384                                               mkU32(0x0)), imm);
1385                     break;
1386                  } else
1387                     goto decode_failure;
1388               }
1389
1390            default:
1391               goto decode_failure;
1392            }
1393         } else {
1394            switch (function) {
1395
1396            case 0x4:   //SQRT.fmt
1397               {
1398                  switch (fmt) {
1399                  case 0x10:  //S
1400                     {
1401                        IRExpr *rm = get_IR_roundingmode();
1402                        putFReg(fd, mkWidenFromF32(tyF, binop(Iop_SqrtF32, rm,
1403                                    getLoFromF64(tyF, getFReg(fs)))));
1404                     }
1405                     break;
1406                  case 0x11:  //D
1407                     {
1408                        IRExpr *rm = get_IR_roundingmode();
1409                        putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs)));
1410                     }
1411                     break;
1412                  }
1413               }
1414               break;
1415            case 0x5:   //abs.fmt
1416               switch (fmt) {
1417               case 0x10:  //S
1418                  DIP("abs.s f%d, f%d\n", fd, fs);
1419                  putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32,
1420                              getLoFromF64(tyF, getFReg(fs)))));
1421                  break;
1422               case 0x11:  //D
1423                  DIP("abs.d f%d, f%d\n", fd, fs);
1424                  putDReg(fd, unop(Iop_AbsF64, getDReg(fs)));
1425                  break;
1426               default:
1427                  goto decode_failure;
1428               }
1429               break;   //case 0x5
1430
1431            case 0x02:  // MUL.fmt
1432               switch (fmt) {
1433               case 0x11:  // D
1434                  {
1435                     DIP("mul.d f%d, f%d, f%d", fd, fs, ft);
1436                     IRExpr *rm = get_IR_roundingmode();
1437                     putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs),
1438                                       getDReg(ft)));
1439                     break;
1440                  }
1441               case 0x10:  // S
1442                  {
1443                     DIP("mul.s f%d, f%d, f%d", fd, fs, ft);
1444                     IRExpr *rm = get_IR_roundingmode();
1445                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm,
1446                                 getLoFromF64(tyF, getFReg(fs)),
1447                                 getLoFromF64(tyF, getFReg(ft)))));
1448                     break;
1449                  }
1450               default:
1451                  goto decode_failure;
1452               }
1453               break;   // MUL.fmt
1454
1455            case 0x03:  // DIV.fmt
1456               switch (fmt) {
1457               case 0x11:  // D
1458                  {
1459                     DIP("div.d f%d, f%d, f%d", fd, fs, ft);
1460                     IRExpr *rm = get_IR_roundingmode();
1461                     putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs),
1462                                 getDReg(ft)));
1463                     break;
1464                  }
1465               case 0x10:  // S
1466                  {
1467                     DIP("div.s f%d, f%d, f%d", fd, fs, ft);
1468                     IRExpr *rm = get_IR_roundingmode();
1469                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
1470                                 getLoFromF64(tyF, getFReg(fs)),
1471                                 getLoFromF64(tyF, getFReg(ft)))));
1472                     break;
1473                  }
1474               default:
1475                  goto decode_failure;
1476               }
1477               break;   // DIV.fmt
1478
1479            case 0x01:  // SUB.fmt
1480               switch (fmt) {
1481               case 0x11:  // D
1482                  {
1483                     DIP("sub.d f%d, f%d, f%d", fd, fs, ft);
1484                     IRExpr *rm = get_IR_roundingmode();
1485                     putDReg(fd, triop(Iop_SubF64, rm, getDReg(fs), getDReg(ft)));
1486                     break;
1487                  }
1488               case 0x10:  // S
1489                  {
1490                     DIP("sub.s f%d, f%d, f%d", fd, fs, ft);
1491                     IRExpr *rm = get_IR_roundingmode();
1492                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm,
1493                                 getLoFromF64(tyF, getFReg(fs)),
1494                                 getLoFromF64(tyF, getFReg(ft)))));
1495                     break;
1496                  }
1497               default:
1498                  goto decode_failure;
1499               }
1500               break;   // SUB.fmt
1501
1502            case 0x06:  // MOV.fmt
1503               switch (fmt) {
1504               case 0x11:  // D
1505                  /* TODO: Check this for 64 bit FPU registers. */
1506                  DIP("mov.d f%d, f%d", fd, fs);
1507                  putFReg(fd, getFReg(fs));
1508                  putFReg(fd + 1, getFReg(fs + 1));
1509                  break;
1510               case 0x10:  // S
1511                  DIP("mov.s f%d, f%d", fd, fs);
1512                  putFReg(fd, getFReg(fs));
1513                  break;
1514               default:
1515                  goto decode_failure;
1516               }
1517               break;   // MOV.fmt
1518
1519            case 0x7:   //neg.fmt
1520               switch (fmt) {
1521               case 0x10:  //S
1522                  DIP("neg.s f%d, f%d", fd, fs);
1523                  putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32,
1524                              getLoFromF64(tyF, getFReg(fs)))));
1525                  break;
1526               case 0x11:  //D
1527                  DIP("neg.d f%d, f%d", fd, fs);
1528                  putDReg(fd, unop(Iop_NegF64, getDReg(fs)));
1529                  break;
1530               default:
1531                  goto decode_failure;
1532               }
1533               break;   //case 0x7
1534
1535            case 0x15:  //RECIP.fmt
1536               switch (fmt) {
1537               case 0x10:
1538                  {  //S
1539                     DIP("recip.s f%d, f%d\n", fd, fs);
1540                     IRExpr *rm = get_IR_roundingmode();
1541                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32,
1542                                 rm, unop(Iop_ReinterpI32asF32,
1543                                 mkU32(0x3F800000)), getLoFromF64(tyF,
1544                                 getFReg(fs)))));
1545                     break;
1546                  }
1547               case 0x11:
1548                  {  //D
1549                     DIP("recip.d f%d, f%d\n", fd, fs);
1550                     IRExpr *rm = get_IR_roundingmode();
1551                     putDReg(fd, triop(Iop_DivF64, rm,
1552                                 unop(Iop_ReinterpI64asF64,
1553                                 mkU64(0x3FF0000000000000ULL)), getDReg(fs)));
1554                     break;
1555                  }
1556               default:
1557                  goto decode_failure;
1558
1559               }
1560               break;   //case 0x15
1561
1562            case 0x13:  //MOVN.fmt
1563               switch (fmt) {
1564               case 0x10:  // S
1565                  DIP("movn.s f%d, f%d, r%d", fd, fs, rt);
1566
1567                  t1 = newTemp(Ity_F64);
1568                  t2 = newTemp(Ity_F64);
1569                  t3 = newTemp(Ity_I32);
1570                  t4 = newTemp(Ity_F64);
1571
1572                  assign(t1, unop(Iop_F32toF64, getFReg(fs)));
1573                  assign(t2, unop(Iop_F32toF64, getFReg(fd)));
1574                  assign(t3, unop(Iop_1Sto32, binop(Iop_CmpNE32, mkU32(0),
1575                                                    getIReg(rt))));
1576
1577                  assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
1578                                               mkexpr(t2), mkexpr(t1)));
1579
1580                  putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
1581                                    mkexpr(t4)));
1582                  break;
1583               case 0x11:  // D
1584                  DIP("movn.d f%d, f%d, r%d", fd, fs, rt);
1585
1586                  t3 = newTemp(Ity_I32);
1587                  t4 = newTemp(Ity_F64);
1588
1589                  assign(t3, unop(Iop_1Sto32, binop(Iop_CmpNE32, mkU32(0),
1590                                                    getIReg(rt))));
1591                  putDReg(fd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
1592                                                getDReg(fd), getDReg(fs)));
1593                  break;
1594               default:
1595                  goto decode_failure;
1596               }
1597               break;   // MOVN.fmt
1598
1599            case 0x12:  //MOVZ.fmt
1600               switch (fmt) {
1601               case 0x10:  // S
1602                  DIP("movz.s f%d, f%d, r%d", fd, fs, rt);
1603
1604                  t1 = newTemp(Ity_F64);
1605                  t2 = newTemp(Ity_F64);
1606                  t3 = newTemp(Ity_I32);
1607                  t4 = newTemp(Ity_F64);
1608
1609                  assign(t1, unop(Iop_F32toF64, getFReg(fs)));
1610                  assign(t2, unop(Iop_F32toF64, getFReg(fd)));
1611                  assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
1612                                                    getIReg(rt))));
1613                  assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
1614                                               mkexpr(t2), mkexpr(t1)));
1615
1616                  putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
1617                                    mkexpr(t4)));
1618
1619                  break;
1620               case 0x11:  // D
1621                  DIP("movz.d f%d, f%d, r%d", fd, fs, rt);
1622
1623                  t3 = newTemp(Ity_I32);
1624                  t4 = newTemp(Ity_F64);
1625
1626                  assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
1627                                                    getIReg(rt))));
1628                  putDReg(fd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
1629                                                getDReg(fd), getDReg(fs)));
1630                  break;
1631               default:
1632                  goto decode_failure;
1633               }
1634               break;   // MOVZ.fmt
1635
1636            case 0x11:  // MOVT.fmt
1637               if (tf == 1) {
1638                  UInt mov_cc = get_mov_cc(cins);
1639                  switch (fmt)   // MOVCF = 010001
1640                  {
1641                  case 0x11:  // D
1642                     DIP("movt.d f%d, f%d, %d", fd, fs, mov_cc);
1643                     t1 = newTemp(Ity_I32);
1644                     t2 = newTemp(Ity_I32);
1645                     t3 = newTemp(Ity_I32);
1646                     t4 = newTemp(Ity_F64);
1647
1648                     assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
1649                                                       mkU32(mov_cc))));
1650                     assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
1651                                binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
1652                                 mkU8(24 + mov_cc)), mkU32(0x1)),
1653                                 binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
1654                                 mkU8(23)), mkU32(0x1))));
1655
1656                     assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
1657                                mkexpr(t2))));
1658                     assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
1659                                             getDReg(fs), getDReg(fd)));
1660                     putDReg(fd, mkexpr(t4));
1661                     break;
1662                  case 0x10:  // S
1663                     DIP("movt.s f%d, f%d, %d", fd, fs, mov_cc);
1664                     t1 = newTemp(Ity_I32);
1665                     t2 = newTemp(Ity_I32);
1666                     t3 = newTemp(Ity_I32);
1667                     t4 = newTemp(Ity_F64);
1668                     t5 = newTemp(Ity_F64);
1669                     t6 = newTemp(Ity_F64);
1670                     t7 = newTemp(Ity_I64);
1671
1672                     assign(t5, unop(Iop_F32toF64, getFReg(fs)));
1673                     assign(t6, unop(Iop_F32toF64, getFReg(fd)));
1674
1675                     assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
1676                                     mkU32(mov_cc))));
1677                     assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
1678                                             binop(Iop_And32, binop(Iop_Shr32,
1679                                             getFCSR(), mkU8(24 + mov_cc)),
1680                                             mkU32(0x1)), binop(Iop_And32,
1681                                             binop(Iop_Shr32, getFCSR(),
1682                                             mkU8(23)), mkU32(0x1))));
1683
1684                     assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
1685                                                       mkexpr(t2))));
1686                     assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
1687                                             mkexpr(t5), mkexpr(t6)));
1688
1689                     putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
1690                                       mkexpr(t4)));
1691                     break;
1692                  default:
1693                     goto decode_failure;
1694                  }
1695               } else if (tf == 0)  //movf.fmt
1696               {
1697                  UInt mov_cc = get_mov_cc(cins);
1698                  switch (fmt)   // MOVCF = 010001
1699                  {
1700                  case 0x11:  // D
1701                     DIP("movf.d f%d, f%d, %d", fd, fs, mov_cc);
1702                     t1 = newTemp(Ity_I32);
1703                     t2 = newTemp(Ity_I32);
1704                     t3 = newTemp(Ity_I32);
1705                     t4 = newTemp(Ity_F64);
1706
1707                     assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32,
1708                                                 mkU32(0), mkU32(mov_cc))));
1709                     assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
1710                                binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
1711                                mkU8(24 + mov_cc)), mkU32(0x1)),
1712                                binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
1713                                mkU8(23)), mkU32(0x1))));
1714
1715                     assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
1716                                                       mkexpr(t2))));
1717                     assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
1718                                             getDReg(fd), getDReg(fs)));
1719                     putDReg(fd, mkexpr(t4));
1720                     break;
1721                  case 0x10:  // S
1722                     DIP("movf.s f%d, f%d, %d", fd, fs, mov_cc);
1723                     {
1724                        t1 = newTemp(Ity_I32);
1725                        t2 = newTemp(Ity_I32);
1726                        t3 = newTemp(Ity_I32);
1727                        t4 = newTemp(Ity_F64);
1728                        t5 = newTemp(Ity_F64);
1729                        t6 = newTemp(Ity_F64);
1730
1731                        assign(t5, unop(Iop_F32toF64, getFReg(fs)));
1732                        assign(t6, unop(Iop_F32toF64, getFReg(fd)));
1733
1734                        assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
1735                                                          mkU32(mov_cc))));
1736                        assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
1737                                   binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
1738                                   mkU8(24 + mov_cc)), mkU32(0x1)),
1739                                   binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
1740                                   mkU8(23)), mkU32(0x1))));
1741
1742                        assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
1743                                                          mkexpr(t2))));
1744                        assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
1745                                                     mkexpr(t6), mkexpr(t5)));
1746                        putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
1747                                          mkexpr(t4)));
1748                     }
1749                     break;
1750                  default:
1751                     goto decode_failure;
1752                  }
1753               }
1754
1755               break;   // MOVT.fmt
1756
1757            case 0x0:   //add.fmt
1758               switch (fmt) {
1759               case 0x10:  //S
1760                  {
1761                     DIP("add.s f%d, f%d, f%d\n", fd, fs, ft);
1762                     IRExpr *rm = get_IR_roundingmode();
1763                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm,
1764                                 getLoFromF64(tyF, getFReg(fs)),
1765                                 getLoFromF64(tyF, getFReg(ft)))));
1766                     break;
1767                  }
1768               case 0x11:  //D
1769                  {
1770                     DIP("add.d f%d, f%d, f%d\n", fd, fs, ft);
1771                     IRExpr *rm = get_IR_roundingmode();
1772                     putDReg(fd, triop(Iop_AddF64, rm, getDReg(fs),
1773                                       getDReg(ft)));
1774                     break;
1775                  }
1776
1777               case 0x4:   //MTC1 (Move Word to Floating Point)
1778                  DIP("mtc1 r%d, f%d", rt, fs);
1779                  putFReg(fs, unop(Iop_ReinterpI32asF32, getIReg(rt)));
1780                  break;
1781
1782               case 0x0:   //MFC1
1783                  DIP("mfc1 r%d, f%d", rt, fs);
1784                  putIReg(rt, unop(Iop_ReinterpF32asI32, getFReg(fs)));
1785                  break;
1786
1787               case 0x6:   //CTC1
1788                  DIP("ctc1 r%d, f%d", rt, fs);
1789                  t0 = newTemp(Ity_I32);
1790                  t1 = newTemp(Ity_I32);
1791                  t2 = newTemp(Ity_I32);
1792                  t3 = newTemp(Ity_I32);
1793                  t4 = newTemp(Ity_I32);
1794                  t5 = newTemp(Ity_I32);
1795                  t6 = newTemp(Ity_I32);
1796                  assign(t0, mkNarrowTo32(ty, getIReg(rt)));
1797                  if (fs == 25) {   //FCCR
1798                     assign(t1, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
1799                                      mkU32(0x000000FE)), mkU8(24)));
1800                     assign(t2, binop(Iop_And32, mkexpr(t0),
1801                                      mkU32(0x01000000)));
1802                     assign(t3, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
1803                                      mkU32(0x00000001)), mkU8(23)));
1804                     assign(t4, binop(Iop_And32, mkexpr(t0),
1805                                      mkU32(0x007FFFFF)));
1806                     putFCSR(binop(Iop_Or32, binop(Iop_Or32, mkexpr(t1),
1807                                   mkexpr(t2)), binop(Iop_Or32, mkexpr(t3),
1808                                   mkexpr(t4))));
1809                  } else if (fs == 26) {  //FEXR
1810                     assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFFFC0000)));
1811                     assign(t2, binop(Iop_And32, mkexpr(t0),
1812                                      mkU32(0x0003F000)));
1813                     assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00000F80)));
1814                     assign(t4, binop(Iop_And32, mkexpr(t0),
1815                                      mkU32(0x0000007C)));
1816                     assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x00000003)));
1817                     putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
1818                                   mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
1819                                   mkexpr(t3), mkexpr(t4))), mkexpr(t5)));
1820                  } else if (fs == 28) {
1821                     assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFE000000)));
1822                     assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
1823                                mkU32(0x00000002)), mkU8(22)));
1824                     assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00FFF000)));
1825                     assign(t4, binop(Iop_And32, mkexpr(t0),
1826                                mkU32(0x00000F80)));
1827                     assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x0000007C)));
1828                     assign(t6, binop(Iop_And32, mkexpr(t0),
1829                                mkU32(0x00000003)));
1830                     putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
1831                                   mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
1832                                   mkexpr(t3), mkexpr(t4))), binop(Iop_Or32,
1833                                   mkexpr(t5), mkexpr(t6))));
1834                  } else if (fs == 31) {
1835                     putFCSR(mkexpr(t0));
1836                  }
1837                  break;
1838               case 0x2:   //CFC1
1839                  DIP("cfc1 r%d, f%d", rt, fs);
1840                  t0 = newTemp(Ity_I32);
1841                  t1 = newTemp(Ity_I32);
1842                  t2 = newTemp(Ity_I32);
1843                  t3 = newTemp(Ity_I32);
1844                  t4 = newTemp(Ity_I32);
1845                  t5 = newTemp(Ity_I32);
1846                  t6 = newTemp(Ity_I32);
1847                  assign(t0, getFCSR());
1848                  if (fs == 0) {
1849                     putIReg(rt, mkWidenFrom32(ty,
1850                             IRExpr_Get(offsetof(VexGuestMIPS32State,
1851                                                 guest_FIR),
1852                                       Ity_I32),
1853                             False));
1854                  } else if (fs == 25) {
1855                     assign(t1, mkU32(0x000000FF));
1856                     assign(t2, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
1857                                      mkU32(0xFE000000)), mkU8(25)));
1858                     assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
1859                                      mkU32(0x00800000)), mkU8(23)));
1860                     putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
1861                                 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
1862                                 mkexpr(t3)), False));
1863                  } else if (fs == 26) {
1864                     assign(t1, mkU32(0xFFFFF07C));
1865                     assign(t2, binop(Iop_And32, mkexpr(t0),
1866                                mkU32(0x0003F000)));
1867                     assign(t3, binop(Iop_And32, mkexpr(t0),
1868                                      mkU32(0x0000007C)));
1869                     putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
1870                                 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
1871                                 mkexpr(t3)), False));
1872                  } else if (fs == 28) {
1873                     assign(t1, mkU32(0x00000F87));
1874                     assign(t2, binop(Iop_And32, mkexpr(t0),
1875                                      mkU32(0x00000F83)));
1876                     assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
1877                                      mkU32(0x01000000)), mkU8(22)));
1878                     putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
1879                                 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
1880                                 mkexpr(t3)), False));
1881                  } else if (fs == 31) {
1882                     putIReg(rt, mkWidenFrom32(ty, getFCSR(), False));
1883                  }
1884                  break;
1885               default:
1886                  goto decode_failure;
1887               }
1888               break;   //case 0x0: //add.fmt
1889
1890            case 0x21:  //CVT.D
1891               switch (fmt) {
1892               case 0x10:  //S
1893                  DIP("cvt.d.s f%d, f%d", fd, fs);
1894                  putDReg(fd, unop(Iop_F32toF64, getFReg(fs)));
1895                  break;
1896
1897               case 0x14:
1898                  {  //W
1899                     DIP("cvt.d.w %d, %d\n", fd, fs);
1900                     t0 = newTemp(Ity_I32);
1901                     assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
1902                     putDReg(fd, unop(Iop_I32StoF64, mkexpr(t0)));
1903                  }
1904                  break;
1905
1906               default:
1907                  goto decode_failure;
1908               }
1909               break;   //CVT.D
1910
1911            case 0x20:  //cvt.s
1912               switch (fmt) {
1913               case 0x14:  //W
1914                  DIP("cvt.s.w %d, %d\n", fd, fs);
1915                  t0 = newTemp(Ity_I32);
1916                  assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
1917                  putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(),
1918                              mkexpr(t0)));
1919                  break;
1920
1921               case 0x11:  //D
1922                  DIP("cvt.s.d %d, %d\n", fd, fs);
1923                  putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
1924                                    getDReg(fs)));
1925                  break;
1926
1927               default:
1928                  goto decode_failure;
1929               }
1930               break;   //cvt.s
1931
1932            case 0x24:  //cvt.w
1933               switch (fmt) {
1934               case 0x10:  //S
1935                  DIP("cvt.w.s %d, %d\n", fd, fs);
1936                  putFReg(fd, binop(Iop_RoundF32toInt, get_IR_roundingmode(),
1937                                    getFReg(fs)));
1938                  break;
1939
1940               case 0x11:
1941                  {  //D
1942                     DIP("cvt.w.d %d, %d\n", fd, fs);
1943                     t0 = newTemp(Ity_I32);
1944
1945                     assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(),
1946                                      getDReg(fs)));
1947
1948                     putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
1949                  }
1950                  break;
1951
1952               default:
1953                  goto decode_failure;
1954
1955               }
1956               break;
1957
1958            case 0x09:  //TRUNC.L
1959               switch (fmt) {
1960               case 0x10:  //S
1961                  DIP("trunc.l.s %d, %d\n", fd, fs);
1962                  goto decode_failure;
1963
1964               case 0x11:  //D
1965                  DIP("trunc.l.d %d, %d\n", fd, fs);
1966                  goto decode_failure;
1967
1968               default:
1969                  goto decode_failure;
1970
1971               }
1972               break;   //trunc.l
1973
1974            case 0x0C:  //ROUND.W.fmt
1975               switch (fmt) {
1976               case 0x10:  //S
1977                  DIP("round.w.s f%d, f%d\n", fd, fs);
1978                  putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x0),
1979                                    getFReg(fs)));
1980                  break;
1981
1982               case 0x11:  //D
1983                  DIP("round.w.d f%d, f%d\n", fd, fs);
1984                  t0 = newTemp(Ity_I32);
1985
1986                  assign(t0, binop(Iop_F64toI32S, mkU32(0x0), getDReg(fs)));
1987
1988                  putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
1989                  break;
1990
1991               default:
1992                  goto decode_failure;
1993
1994               }
1995               break;   //ROUND.W.fmt
1996
1997            case 0x0F:  //FLOOR.W.fmt
1998               switch (fmt) {
1999               case 0x10:  //S
2000                  DIP("floor.w.s f%d, f%d\n", fd, fs);
2001                  putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x1),
2002                                    getFReg(fs)));
2003                  break;
2004
2005               case 0x11:  //D
2006                  DIP("floor.w.d f%d, f%d\n", fd, fs);
2007                  t0 = newTemp(Ity_I32);
2008
2009                  assign(t0, binop(Iop_F64toI32S, mkU32(0x1), getDReg(fs)));
2010
2011                  putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
2012                  break;
2013
2014               default:
2015                  goto decode_failure;
2016
2017               }
2018               break;   //FLOOR.W.fmt
2019
2020            case 0x0D:  //TRUNC.W
2021               switch (fmt) {
2022               case 0x10:  //S
2023                  DIP("trunc.w.s %d, %d\n", fd, fs);
2024                  putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x3),
2025                                    getFReg(fs)));
2026                  break;
2027
2028               case 0x11:  //D
2029                  DIP("trunc.w.d %d, %d\n", fd, fs);
2030                  t0 = newTemp(Ity_I32);
2031
2032                  assign(t0, binop(Iop_F64toI32S, mkU32(0x3), getDReg(fs)));
2033
2034                  putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
2035                  break;
2036
2037               default:
2038                  goto decode_failure;
2039
2040               }
2041               break;
2042            case 0x0E:  //CEIL.W.fmt
2043               switch (fmt) {
2044               case 0x10:  //S
2045                  DIP("ceil.w.s %d, %d\n", fd, fs);
2046                  putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x2),
2047                                    getFReg(fs)));
2048                  break;
2049
2050               case 0x11:  //D
2051                  DIP("ceil.w.d %d, %d\n", fd, fs);
2052                  t0 = newTemp(Ity_I32);
2053
2054                  assign(t0, binop(Iop_F64toI32S, mkU32(0x2), getDReg(fs)));
2055
2056                  putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
2057                  break;
2058
2059               default:
2060                  goto decode_failure;
2061
2062               }
2063               break;
2064            case 0x0A:  //CEIL.L.fmt
2065               switch (fmt) {
2066               case 0x10:  //S
2067                  DIP("ceil.l.s %d, %d\n", fd, fs);
2068                  goto decode_failure;
2069
2070               case 0x11:  //D
2071                  DIP("ceil.l.d %d, %d\n", fd, fs);
2072
2073                  goto decode_failure;
2074
2075               default:
2076                  goto decode_failure;
2077
2078               }
2079               break;
2080
2081            case 0x16:  //RSQRT.fmt
2082               switch (fmt) {
2083               case 0x10:
2084                  {  //S
2085                     DIP("rsqrt.s %d, %d\n", fd, fs);
2086                     IRExpr *rm = get_IR_roundingmode();
2087                     putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
2088                                 unop(Iop_ReinterpI32asF32, mkU32(0x3F800000)),
2089                                 binop(Iop_SqrtF32, rm, getLoFromF64(tyF,
2090                                 getFReg(fs))))));
2091                     break;
2092                  }
2093               case 0x11:
2094                  {  //D
2095                     DIP("rsqrt.d %d, %d\n", fd, fs);
2096                     IRExpr *rm = get_IR_roundingmode();
2097                     putDReg(fd, triop(Iop_DivF64, rm,
2098                                 unop(Iop_ReinterpI64asF64,
2099                                 mkU64(0x3FF0000000000000ULL)),
2100                                 binop(Iop_SqrtF64, rm, getDReg(fs))));
2101                     break;
2102                  }
2103               default:
2104                  goto decode_failure;
2105
2106               }
2107               break;
2108
2109            default:
2110               if (dis_instr_CCondFmt(cins))
2111                  break;
2112               goto decode_failure;
2113
2114            }
2115
2116         }
2117      }
2118      break;      /*COP1 */
2119   case 0x10:     /* COP0 */
2120      if (rs == 0) { /* MFC0 */
2121         DIP("mfc0 r%d, r%d, %d", rt, rd, sel);
2122
2123         IRTemp   val  = newTemp(Ity_I32);
2124         IRExpr** args = mkIRExprVec_2 (mkU32(rd), mkU32(sel));
2125         IRDirty *d = unsafeIRDirty_1_N(val,
2126                                        0,
2127                                        "mips32_dirtyhelper_mfc0",
2128                                        &mips32_dirtyhelper_mfc0,
2129                                        args);
2130
2131         stmt(IRStmt_Dirty(d));
2132         putIReg(rt, mkexpr(val));
2133      } else
2134         goto decode_failure;
2135      break;
2136   case 0x31:     /* LWC1 */
2137      /* Load Word to Floating Point - LWC1 (MIPS32) */
2138      LOAD_STORE_PATTERN;
2139      putFReg(ft, load(Ity_F32, mkexpr(t1)));
2140
2141      DIP("lwc1 f%d, %d(r%d)", ft, imm, rs);
2142      break;
2143
2144   case 0x39:     /* SWC1 */
2145      LOAD_STORE_PATTERN;
2146      store(mkexpr(t1), getFReg(ft));
2147      DIP("swc1 f%d, %d(r%d)", ft, imm, rs);
2148      break;
2149
2150   case 0x33:     /* PREF */
2151      DIP("pref");
2152      break;
2153
2154   case 0x35:
2155      /* Load Doubleword to Floating Point - LDC1 (MIPS32) */
2156      LOAD_STORE_PATTERN;
2157
2158      t2 = newTemp(Ity_I32);
2159      assign(t2, binop(Iop_Add32, getIReg(rs),
2160                       mkU32(extend_s_16to32(imm + 4))));
2161
2162#if defined (_MIPSEL)
2163      putFReg(ft, load(Ity_F32, mkexpr(t1)));
2164      putFReg(ft + 1, load(Ity_F32, mkexpr(t2)));
2165#elif defined (_MIPSEB)
2166      putFReg(ft + 1, load(Ity_F32, mkexpr(t1)));
2167      putFReg(ft, load(Ity_F32, mkexpr(t2)));
2168#endif
2169      DIP("ldc1 f%d, %d(%d) \n", rt, imm, rs);
2170      break;
2171
2172   case 0x3D:
2173      /* Store Doubleword from Floating Point - SDC1 */
2174      LOAD_STORE_PATTERN;
2175
2176      t2 = newTemp(Ity_I32);
2177      assign(t2, binop(Iop_Add32, getIReg(rs),
2178                       mkU32(extend_s_16to32(imm + 4))));
2179
2180#if defined (_MIPSEL)
2181      store(mkexpr(t1), getFReg(ft));
2182      store(mkexpr(t2), getFReg(ft + 1));
2183#elif defined (_MIPSEB)
2184      store(mkexpr(t1), getFReg(ft + 1));
2185      store(mkexpr(t2), getFReg(ft));
2186#endif
2187      DIP("sdc1 f%d, %d(%d)", ft, imm, rs);
2188      break;
2189
2190   case 0x23:     /* LW */
2191      DIP("lw r%d, %d(r%d)", rt, imm, rs);
2192      LOAD_STORE_PATTERN;
2193      putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
2194      break;
2195
2196   case 0x20:     /* LB */
2197      DIP("lb r%d, %d(r%d)", rt, imm, rs);
2198      LOAD_STORE_PATTERN;
2199      putIReg(rt, unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
2200      break;
2201
2202   case 0x24:     /* LBU */
2203      DIP("lbu r%d, %d(r%d)", rt, imm, rs);
2204      LOAD_STORE_PATTERN;
2205      putIReg(rt, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t1))));
2206      break;
2207
2208   case 0x21:     /* LH */
2209      DIP("lh r%d, %d(r%d)", rt, imm, rs);
2210      LOAD_STORE_PATTERN;
2211      putIReg(rt, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t1))));
2212      break;
2213
2214   case 0x25:     /* LHU */
2215      DIP("lhu r%d, %d(r%d)", rt, imm, rs);
2216      LOAD_STORE_PATTERN;
2217      putIReg(rt, unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
2218      break;
2219
2220   case 0x0F:     /* LUI */
2221      p = (imm << 16);
2222      DIP("lui rt: %d, imm: %d, imm << 16: %d", rt, imm, p);
2223      if ((vex_traceflags & VEX_TRACE_FE) && !mode64)
2224         ppIRExpr(mkU32(p));
2225      putIReg(rt, mkU32(p));
2226      break;
2227
2228   case 0x13:     /* COP1X */
2229      switch (function) {
2230      case 0x0: { /* LWXC1 */
2231         /* Load Word  Indexed to Floating Point - LWXC1 (MIPS32r2) */
2232         DIP("lwxc1 f%d, r%d(r%d) \n", fd, rt, rs);
2233         t0 = newTemp(Ity_I32);
2234         assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
2235         putFReg(fd, load(Ity_F32, mkexpr(t0)));
2236         break;
2237      }
2238
2239      case 0x1: { /* LDXC1 */
2240         /* Load Doubleword  Indexed to Floating Point - LDXC1 (MIPS32r2) */
2241         t0 = newTemp(Ity_I32);
2242         assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
2243
2244         t1 = newTemp(Ity_I32);
2245         assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4)));
2246
2247#if defined (_MIPSEL)
2248         putFReg(fd, load(Ity_F32, mkexpr(t0)));
2249         putFReg(fd + 1, load(Ity_F32, mkexpr(t1)));
2250#elif defined (_MIPSEB)
2251         putFReg(fd + 1, load(Ity_F32, mkexpr(t0)));
2252         putFReg(fd, load(Ity_F32, mkexpr(t1)));
2253#endif
2254         DIP("ldxc1 f%d, r%d(r%d) \n", fd, rt, rs);
2255         break;
2256      }
2257
2258      case 0x5:   // Load Doubleword Indexed Unaligned
2259         // to Floating Point - LUXC1; MIPS32r2
2260         DIP("luxc1 f%d, r%d(r%d) \n", fd, rt, rs);
2261         t0 = newTemp(Ity_I64);
2262         t1 = newTemp(Ity_I64);
2263         assign(t0, binop(Iop_Add64, getIReg(rs), getIReg(rt)));
2264         assign(t1, binop(Iop_And64, mkexpr(t0), mkU64(0xfffffffffffffff8ULL)));
2265         putFReg(fd, load(Ity_F64, mkexpr(t1)));
2266         break;
2267
2268      case 0x8: { /* SWXC1 */
2269         /* Store Word Indexed from Floating Point - SWXC1 */
2270         t0 = newTemp(Ity_I32);
2271         assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
2272
2273         store(mkexpr(t0), getFReg(fs));
2274
2275         DIP("swxc1 f%d, r%d(r%d)", ft, rt, rs);
2276         break;
2277      }
2278      case 0x9: { /* SDXC1 */
2279         /* Store Doubleword Indexed from Floating Point - SDXC1 */
2280         t0 = newTemp(Ity_I32);
2281         assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
2282
2283         t1 = newTemp(Ity_I32);
2284         assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4)));
2285
2286#if defined (_MIPSEL)
2287         store(mkexpr(t0), getFReg(fs));
2288         store(mkexpr(t1), getFReg(fs + 1));
2289#elif defined (_MIPSEB)
2290         store(mkexpr(t0), getFReg(fs + 1));
2291         store(mkexpr(t1), getFReg(fs));
2292#endif
2293
2294         DIP("sdc1 f%d, %d(%d)", ft, imm, rs);
2295         break;
2296      }
2297      case 0x0F: {
2298         DIP("prefx");
2299         break;
2300      }
2301      case 0x20:  { /* MADD.S */
2302         DIP("madd.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
2303         IRExpr *rm = get_IR_roundingmode();
2304         t1 = newTemp(Ity_F32);
2305         assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
2306                          getLoFromF64(tyF, getFReg(ft))));
2307
2308         putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm, mkexpr(t1),
2309                                    getLoFromF64(tyF, getFReg(fmt)))));
2310         break;   /* MADD.S */
2311      }
2312      case 0x21: { /* MADD.D */
2313         DIP("madd.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
2314         IRExpr *rm = get_IR_roundingmode();
2315         t1 = newTemp(Ity_F64);
2316         assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft)));
2317
2318         putDReg(fd, triop(Iop_AddF64, rm, mkexpr(t1), getDReg(fmt)));
2319         break;   /* MADD.D */
2320      }
2321      case 0x28: { /* MSUB.S */
2322         DIP("msub.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
2323         IRExpr *rm = get_IR_roundingmode();
2324         t1 = newTemp(Ity_F32);
2325         assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
2326                          getLoFromF64(tyF, getFReg(ft))));
2327
2328         putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm,
2329                     mkexpr(t1), getLoFromF64(tyF, getFReg(fmt)))));
2330         break;   /* MSUB.S */
2331      }
2332      case 0x29: { /* MSUB.D */
2333         DIP("msub.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
2334         IRExpr *rm = get_IR_roundingmode();
2335         t1 = newTemp(Ity_F64);
2336         assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft)));
2337
2338         putDReg(fd, triop(Iop_SubF64, rm, mkexpr(t1), getDReg(fmt)));
2339         break;   /* MSUB.D */
2340      }
2341      case 0x30: { /* NMADD.S */
2342         DIP("nmadd.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
2343         IRExpr *rm = get_IR_roundingmode();
2344         t1 = newTemp(Ity_F32);
2345         t2 = newTemp(Ity_F32);
2346         assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
2347                getLoFromF64(tyF, getFReg(ft))));
2348
2349         assign(t2, triop(Iop_AddF32, rm, mkexpr(t1),
2350                          getLoFromF64(tyF, getFReg(fmt))));
2351
2352         putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t2))));
2353         break;   /* NMADD.S */
2354      }
2355      case 0x31: { /* NMADD.D */
2356         DIP("nmadd.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
2357         IRExpr *rm = get_IR_roundingmode();
2358         t1 = newTemp(Ity_F64);
2359         t2 = newTemp(Ity_F64);
2360         assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft)));
2361
2362         assign(t2, triop(Iop_AddF64, rm, mkexpr(t1), getDReg(fmt)));
2363         putDReg(fd, unop(Iop_NegF64, mkexpr(t2)));
2364         break;   /* NMADD.D */
2365      }
2366      case 0x38: { /* NMSUBB.S */
2367         DIP("nmsub.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
2368         IRExpr *rm = get_IR_roundingmode();
2369         t1 = newTemp(Ity_F32);
2370         t2 = newTemp(Ity_F32);
2371         assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
2372                          getLoFromF64(tyF, getFReg(ft))));
2373
2374         assign(t2, triop(Iop_SubF32, rm, mkexpr(t1), getLoFromF64(tyF,
2375                                                      getFReg(fmt))));
2376
2377         putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t2))));
2378         break;   /* NMSUBB.S */
2379      }
2380      case 0x39: { /* NMSUBB.D */
2381         DIP("nmsub.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd);
2382         IRExpr *rm = get_IR_roundingmode();
2383         t1 = newTemp(Ity_F64);
2384         t2 = newTemp(Ity_F64);
2385         assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft)));
2386
2387         assign(t2, triop(Iop_SubF64, rm, mkexpr(t1), getDReg(fmt)));
2388         putDReg(fd, unop(Iop_NegF64, mkexpr(t2)));
2389         break;   /* NMSUBB.D */
2390      }
2391
2392      default:
2393         goto decode_failure;
2394      }
2395      break;
2396
2397   case 0x22:     /* LWL */
2398
2399      DIP("lwl r%d, %d(r%d)", rt, imm, rs);
2400      {
2401         /* t1 = addr */
2402         t1 = newTemp(Ity_I32);
2403#if defined (_MIPSEL)
2404         assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
2405#elif defined (_MIPSEB)
2406         assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
2407                                     mkU32(extend_s_16to32(imm)))));
2408#endif
2409
2410         /* t2 = word addr */
2411         /* t4 = addr mod 4 */
2412         LWX_SWX_PATTERN;
2413
2414         /* t3 = word content - shifted */
2415         t3 = newTemp(Ity_I32);
2416         assign(t3, binop(Iop_Shl32, load(Ity_I32, mkexpr(t2)), narrowTo(Ity_I8,
2417                    binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)),
2418                    mkU8(3)))));
2419
2420         /* rt content  - adjusted */
2421         t5 = newTemp(Ity_I32);
2422         assign(t5, binop(Iop_And32, getIReg(rt), binop(Iop_Shr32,
2423                    mkU32(0xFFFFFFFF), narrowTo(Ity_I8, binop(Iop_Shl32,
2424                    binop(Iop_Add32, mkexpr(t4), mkU32(0x1)), mkU8(0x3))))));
2425
2426         putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
2427      }
2428      break;
2429
2430   case 0x26:     /* LWR */
2431
2432      DIP("lwr r%d, %d(r%d)", rt, imm, rs);
2433      {
2434         /* t1 = addr */
2435         t1 = newTemp(Ity_I32);
2436#if defined (_MIPSEL)
2437         assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
2438#elif defined (_MIPSEB)
2439         assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
2440                                     mkU32(extend_s_16to32(imm)))));
2441#endif
2442
2443         /* t2 = word addr */
2444         /* t4 = addr mod 4 */
2445         LWX_SWX_PATTERN;
2446
2447         /* t3 = word content - shifted */
2448         t3 = newTemp(Ity_I32);
2449         assign(t3, binop(Iop_Shr32, load(Ity_I32, mkexpr(t2)),
2450                    narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4),
2451                    mkU8(3)))));
2452
2453         /* rt content  - adjusted */
2454         t5 = newTemp(Ity_I32);
2455         assign(t5, binop(Iop_And32, getIReg(rt), unop(Iop_Not32,
2456                    binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
2457                          binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
2458
2459         putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
2460      }
2461      break;
2462
2463   case 0x2B:     /* SW */
2464      DIP("sw r%d, %d(r%d)", rt, imm, rs);
2465      LOAD_STORE_PATTERN;
2466      store(mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)));
2467      break;
2468
2469   case 0x28:     /* SB */
2470      DIP("sb r%d, %d(r%d)", rt, imm, rs);
2471      LOAD_STORE_PATTERN;
2472      store(mkexpr(t1), narrowTo(Ity_I8, getIReg(rt)));
2473      break;
2474
2475   case 0x29:     /* SH */
2476      DIP("sh r%d, %d(r%d)", rt, imm, rs);
2477      LOAD_STORE_PATTERN;
2478      store(mkexpr(t1), narrowTo(Ity_I16, getIReg(rt)));
2479      break;
2480
2481   case 0x2A:     /* SWL */
2482
2483      DIP("swl r%d, %d(r%d)", rt, imm, rs);
2484      {
2485         /* t1 = addr */
2486         t1 = newTemp(Ity_I32);
2487#if defined (_MIPSEL)
2488         assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
2489#elif defined (_MIPSEB)
2490         assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
2491                                     mkU32(extend_s_16to32(imm)))));
2492#endif
2493
2494         /* t2 = word addr */
2495         /* t4 = addr mod 4 */
2496         LWX_SWX_PATTERN;
2497
2498         /* t3 = rt content - shifted */
2499         t3 = newTemp(Ity_I32);
2500         assign(t3, binop(Iop_Shr32, getIReg(rt), narrowTo(Ity_I8,
2501                    binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)),
2502                    mkU8(3)))));
2503
2504         /* word content  - adjusted */
2505         t5 = newTemp(Ity_I32);
2506         t6 = newTemp(Ity_I32);
2507         t7 = newTemp(Ity_I32);
2508         t8 = newTemp(Ity_I32);
2509
2510         // neg(shr(0xFFFFFFFF, mul(sub(3,n), 8)))
2511         assign(t5, binop(Iop_Mul32, binop(Iop_Sub32, mkU32(0x3), mkexpr(t4)),
2512                          mkU32(0x8)));
2513
2514         assign(t6, binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
2515                                                        mkexpr(t5))));
2516         assign(t7, binop(Iop_Xor32, mkU32(0xFFFFFFFF), mkexpr(t6)));
2517         assign(t8, binop(Iop_And32, load(Ity_I32, mkexpr(t2)), mkexpr(t7)));
2518         store(mkexpr(t2), binop(Iop_Or32, mkexpr(t8), mkexpr(t3)));
2519      }
2520      break;
2521
2522   case 0x2E:     /* SWR */
2523
2524      DIP("swr r%d, %d(r%d)", rt, imm, rs);
2525      {
2526         /* t1 = addr */
2527         t1 = newTemp(Ity_I32);
2528#if defined (_MIPSEL)
2529         assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
2530#elif defined (_MIPSEB)
2531         assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
2532                                     mkU32(extend_s_16to32(imm)))));
2533#endif
2534
2535         /* t2 = word addr */
2536         /* t4 = addr mod 4 */
2537         LWX_SWX_PATTERN;
2538
2539         /* t3 = rt content - shifted */
2540         t3 = newTemp(Ity_I32);
2541         assign(t3, binop(Iop_Shl32, getIReg(rt), narrowTo(Ity_I8,
2542                    binop(Iop_Shl32, mkexpr(t4), mkU8(3)))));
2543
2544         /* word content  - adjusted */
2545         t5 = newTemp(Ity_I32);
2546         assign(t5, binop(Iop_And32, load(Ity_I32, mkexpr(t2)), unop(Iop_Not32,
2547                    binop(Iop_Shl32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
2548                          binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
2549
2550         store(mkexpr(t2), binop(Iop_Xor32, mkexpr(t5), mkexpr(t3)));
2551      }
2552      break;
2553
2554   case 0x1C:     /*Special2 */
2555      switch (function) {
2556      case 0x02: { /* MUL */
2557         DIP("mul r%d, r%d, r%d", rd, rs, rt);
2558         putIReg(rd, binop(Iop_Mul32, getIReg(rs), getIReg(rt)));
2559         break;
2560      }
2561
2562      case 0x00: { /* MADD */
2563         DIP("madd r%d, r%d", rs, rt);
2564         t1 = newTemp(Ity_I32);
2565         t2 = newTemp(Ity_I32);
2566         t3 = newTemp(Ity_I64);
2567         t4 = newTemp(Ity_I32);
2568         t5 = newTemp(Ity_I32);
2569         t6 = newTemp(Ity_I32);
2570
2571         assign(t1, getHI());
2572         assign(t2, getLO());
2573
2574         assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
2575
2576         assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
2577                                                      mkexpr(t3))));
2578
2579         assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
2580                                     unop(Iop_64to32, mkexpr(t3)))));
2581         assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
2582
2583         putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3))));
2584         putLO(mkexpr(t4));
2585         break;
2586      }
2587
2588      case 0x01: { /* MADDU */
2589         DIP("maddu r%d, r%d", rs, rt);
2590         t1 = newTemp(Ity_I32);
2591         t2 = newTemp(Ity_I32);
2592         t3 = newTemp(Ity_I64);
2593         t4 = newTemp(Ity_I32);
2594         t5 = newTemp(Ity_I32);
2595         t6 = newTemp(Ity_I32);
2596
2597         assign(t1, getHI());
2598         assign(t2, getLO());
2599
2600         assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
2601
2602         assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
2603                                                      mkexpr(t3))));
2604         assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
2605                                     unop(Iop_64to32, mkexpr(t3)))));
2606         assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
2607
2608         putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3))));
2609         putLO(mkexpr(t4));
2610         break;
2611      }
2612
2613      case 0x04: { /* MSUB */
2614         DIP("msub r%d, r%d", rs, rt);
2615         t1 = newTemp(Ity_I32);
2616         t2 = newTemp(Ity_I32);
2617         t3 = newTemp(Ity_I64);
2618         t4 = newTemp(Ity_I32);
2619         t5 = newTemp(Ity_I32);
2620         t6 = newTemp(Ity_I32);
2621
2622         assign(t1, getHI());
2623         assign(t2, getLO());
2624
2625         assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
2626         assign(t4, unop(Iop_64to32, mkexpr(t3))); //new lo
2627
2628         //if lo<lo(mul) hi = hi - 1
2629         assign(t5, unop(Iop_1Sto32, binop(Iop_CmpLT32U, mkexpr(t2),
2630                                           mkexpr(t4))));
2631
2632         assign(t6, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t5)), mkexpr(t1),
2633                                 binop(Iop_Sub32, mkexpr(t1), mkU32(0x1))));
2634
2635         putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3))));
2636         putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
2637         break;
2638      }
2639
2640      case 0x05: { /* MSUBU */
2641         DIP("msubu r%d, r%d", rs, rt);
2642         t1 = newTemp(Ity_I32);
2643         t2 = newTemp(Ity_I32);
2644         t3 = newTemp(Ity_I64);
2645         t4 = newTemp(Ity_I32);
2646         t5 = newTemp(Ity_I32);
2647         t6 = newTemp(Ity_I32);
2648
2649         assign(t1, getHI());
2650         assign(t2, getLO());
2651
2652         assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
2653         assign(t4, unop(Iop_64to32, mkexpr(t3))); //new lo
2654
2655         //if lo<lo(mul) hi = hi - 1
2656         assign(t5, unop(Iop_1Sto32, binop(Iop_CmpLT32U, mkexpr(t2),
2657                                           mkexpr(t4))));
2658
2659         assign(t6, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t5)),
2660                    mkexpr(t1), binop(Iop_Sub32, mkexpr(t1), mkU32(0x1))));
2661
2662         putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3))));
2663         putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
2664         break;
2665      }
2666
2667      case 0x20: { /* CLZ */
2668         DIP("clz r%d, r%d", rd, rs);
2669         t1 = newTemp(Ity_I32);
2670         assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rs),
2671                                           mkU32(0))));
2672         putIReg(rd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
2673                     unop(Iop_Clz32, getIReg(rs)), mkU32(0x00000020)));
2674         break;
2675      }
2676
2677      case 0x21: { /* CLO */
2678         DIP("clo r%d, r%d", rd, rs);
2679         t1 = newTemp(Ity_I32);
2680         assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rs),
2681                                           mkU32(0xffffffff))));
2682         putIReg(rd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
2683                     unop(Iop_Clz32, unop(Iop_Not32, getIReg(rs))),
2684                     mkU32(0x00000020)));
2685         break;
2686      }
2687
2688      default:
2689         goto decode_failure;
2690      }
2691      break;
2692
2693   case 0x1F:     /*Special3 */
2694      switch (function) {
2695      case 0x3B:
2696          /*RDHWR*/ {
2697            DIP("rdhwr r%d, r%d", rt, rd);
2698            if (rd == 29) {
2699               putIReg(rt, getULR());
2700            } else
2701               goto decode_failure;
2702            break;
2703         }
2704      case 0x04:
2705          /*INS*/ msb = get_msb(cins);
2706         lsb = get_lsb(cins);
2707
2708         size = msb - lsb + 1;
2709
2710         vassert(lsb + size <= 32);
2711         vassert(lsb + size > 0);
2712
2713         DIP("ins size:%d msb:%d lsb:%d", size, msb, lsb);
2714         /*put size bits from rs at the pos in temporary */
2715         t0 = newTemp(Ity_I32);
2716         t3 = newTemp(Ity_I32);
2717         /*shift left for 32 - size to clear leading bits and get zeros
2718           at the end */
2719         assign(t0, binop(Iop_Shl32, getIReg(rs), mkU8(32 - size)));
2720         /*now set it at pos */
2721         t1 = newTemp(Ity_I32);
2722         assign(t1, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size - lsb)));
2723
2724         if (lsb > 0) {
2725            t2 = newTemp(Ity_I32);
2726            /*clear everything but lower pos bits from rt */
2727            assign(t2, binop(Iop_Shl32, getIReg(rt), mkU8(32 - lsb)));
2728            assign(t3, binop(Iop_Shr32, mkexpr(t2), mkU8(32 - lsb)));
2729         }
2730
2731         if (msb < 31) {
2732            t4 = newTemp(Ity_I32);
2733            /*clear everything but upper msb + 1 bits from rt */
2734            assign(t4, binop(Iop_Shr32, getIReg(rt), mkU8(msb + 1)));
2735            t5 = newTemp(Ity_I32);
2736            assign(t5, binop(Iop_Shl32, mkexpr(t4), mkU8(msb + 1)));
2737
2738            /*now combine these registers */
2739            if (lsb > 0) {
2740               t6 = newTemp(Ity_I32);
2741               assign(t6, binop(Iop_Or32, mkexpr(t5), mkexpr(t1)));
2742               putIReg(rt, binop(Iop_Or32, mkexpr(t6), mkexpr(t3)));
2743            } else {
2744               putIReg(rt, binop(Iop_Or32, mkexpr(t1), mkexpr(t5)));
2745            }
2746         }
2747
2748         else {
2749            putIReg(rt, binop(Iop_Or32, mkexpr(t1), mkexpr(t3)));
2750
2751         }
2752         break;
2753
2754      case 0x00:
2755         /*EXT*/ msb = get_msb(cins);
2756         lsb = get_lsb(cins);
2757         size = msb + 1;
2758         DIP("ext size:%d msb:%d lsb:%d", size, msb, lsb);
2759         vassert(lsb + size <= 32);
2760         vassert(lsb + size > 0);
2761         /*put size bits from rs at the top of in temporary */
2762         if (lsb + size < 32) {
2763            t0 = newTemp(Ity_I32);
2764            assign(t0, binop(Iop_Shl32, getIReg(rs), mkU8(32 - lsb - size)));
2765            putIReg(rt, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size)));
2766         } else {
2767            putIReg(rt, binop(Iop_Shr32, getIReg(rs), mkU8(32 - size)));
2768
2769         }
2770         break;
2771
2772      case 0x20:
2773         /*BSHFL*/ switch (sa) {
2774         case 0x10:
2775             /*SEB*/ DIP("seb r%d, r%d", rd, rt);
2776            putIReg(rd, unop(Iop_8Sto32, unop(Iop_32to8, getIReg(rt))));
2777            break;
2778
2779         case 0x18:
2780             /*SEH*/ DIP("seh r%d, r%d", rd, rt);
2781            putIReg(rd, unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
2782            break;
2783
2784         case 0x02:
2785             /*WSBH*/ DIP("wsbh r%d, r%d", rd, rt);
2786            t0 = newTemp(Ity_I32);
2787            t1 = newTemp(Ity_I32);
2788            t2 = newTemp(Ity_I32);
2789            t3 = newTemp(Ity_I32);
2790            assign(t0, binop(Iop_Shl32, binop(Iop_And32, getIReg(rt),
2791                                        mkU32(0x00FF0000)), mkU8(0x8)));
2792            assign(t1, binop(Iop_Shr32, binop(Iop_And32, getIReg(rt),
2793                       mkU32(0xFF000000)), mkU8(0x8)));
2794            assign(t2, binop(Iop_Shl32, binop(Iop_And32, getIReg(rt),
2795                       mkU32(0x000000FF)), mkU8(0x8)));
2796            assign(t3, binop(Iop_Shr32, binop(Iop_And32, getIReg(rt),
2797                       mkU32(0x0000FF00)), mkU8(0x8)));
2798            putIReg(rd, binop(Iop_Or32, binop(Iop_Or32, mkexpr(t0),
2799                        mkexpr(t1)), binop(Iop_Or32, mkexpr(t2), mkexpr(t3))));
2800            break;
2801
2802         default:
2803            goto decode_failure;
2804
2805         }
2806         break;
2807       /*BSHFL*/ default:
2808         goto decode_failure;
2809
2810      }
2811      break;      /*Special3 */
2812
2813   case 0x3B:
2814      if (0x3B == function && (archinfo->hwcaps & VEX_PRID_COMP_BROADCOM)) {
2815          /*RDHWR*/
2816            DIP("rdhwr r%d, r%d", rt, rd);
2817            if (rd == 29) {
2818               putIReg(rt, getULR());
2819            } else
2820               goto decode_failure;
2821            break;
2822      } else {
2823         goto decode_failure;
2824      }
2825
2826   case 0x00:     /*Special */
2827
2828      switch (function) {
2829      case 0x1: {
2830         UInt mov_cc = get_mov_cc(cins);
2831         if (tf == 0) { /* MOVF */
2832            DIP("movf r%d, r%d, %d", rd, rs, mov_cc);
2833            {
2834               t1 = newTemp(Ity_I32);
2835               t2 = newTemp(Ity_I32);
2836               t3 = newTemp(Ity_I32);
2837               t4 = newTemp(Ity_I32);
2838
2839               assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
2840                                                 mkU32(mov_cc))));
2841               assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
2842                          binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
2843                          mkU8(24 + mov_cc)), mkU32(0x1)), binop(Iop_And32,
2844                          binop(Iop_Shr32, getFCSR(), mkU8(23)),
2845                          mkU32(0x1))));
2846
2847               assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
2848                                                 mkexpr(t2))));
2849               assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
2850                          getIReg(rd), getIReg(rs)));
2851               putIReg(rd, mkexpr(t4));
2852            }
2853         } else if (tf == 1) {   /* MOVT */
2854            DIP("movt r%d, r%d, %d", rd, rs, mov_cc);
2855            {
2856               t1 = newTemp(Ity_I32);
2857               t2 = newTemp(Ity_I32);
2858               t3 = newTemp(Ity_I32);
2859               t4 = newTemp(Ity_I32);
2860
2861               assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0),
2862                                                 mkU32(mov_cc))));
2863               assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)),
2864                          binop(Iop_And32, binop(Iop_Shr32, getFCSR(),
2865                          mkU8(24 + mov_cc)), mkU32(0x1)), binop(Iop_And32,
2866                          binop(Iop_Shr32, getFCSR(), mkU8(23)),
2867                          mkU32(0x1))));
2868
2869               assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1),
2870                                                 mkexpr(t2))));
2871               assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)),
2872                          getIReg(rd), getIReg(rs)));
2873               putIReg(rd, mkexpr(t4));
2874            }
2875         }
2876         break;
2877      }
2878      case 0x0A: {
2879         /* MOVZ */
2880         DIP("movz r%d, r%d, r%d", rd, rs, rt);
2881         t1 = newTemp(ty);
2882         t2 = newTemp(ty);
2883         {
2884            assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
2885                                              mkU32(0x0))));
2886            assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
2887                                              mkU32(0x0))));
2888            putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
2889                        mkexpr(t1)), binop(Iop_And32, getIReg(rd),
2890                        mkexpr(t2))));
2891         }
2892         break;
2893      }
2894
2895      case 0x0B: {
2896         /* MOVN */
2897         DIP("movn r%d, r%d, r%d", rd, rs, rt);
2898         t1 = newTemp(ty);
2899         t2 = newTemp(ty);
2900         {
2901            assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
2902                                              mkU32(0x0))));
2903            assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
2904                                              mkU32(0x0))));
2905            putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
2906                        mkexpr(t2)), binop(Iop_And32, getIReg(rd),
2907                        mkexpr(t1))));
2908         }
2909         break;
2910      }
2911
2912      case 0x18:  /* MULT */
2913         DIP("mult r%d, r%d", rs, rt);
2914         t2 = newTemp(Ity_I64);
2915
2916         assign(t2, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
2917                          mkNarrowTo32(ty, getIReg(rt))));
2918
2919         putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
2920         putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
2921         break;
2922
2923      case 0x19:  /* MULTU */
2924         DIP("multu r%d, r%d", rs, rt);
2925         t2 = newTemp(Ity_I64);
2926
2927         assign(t2, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
2928                                       mkNarrowTo32(ty, getIReg(rt))));
2929
2930         putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
2931         putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
2932         break;
2933
2934      case 0x20:  /* ADD */
2935         DIP("add r%d, r%d, r%d", rd, rs, rt);
2936         {
2937            t2 = newTemp(Ity_I32);
2938
2939            assign(t2, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
2940            putIReg(rd, mkexpr(t2));
2941         }
2942         break;
2943
2944      case 0x1A:  /* DIV */
2945         DIP("div r%d, r%d", rs, rt);
2946         {
2947            t1 = newTemp(Ity_I64);
2948            t2 = newTemp(Ity_I64);
2949
2950            assign(t1, unop(Iop_32Sto64, getIReg(rs)));
2951            assign(t2, binop(Iop_DivModS64to32, mkexpr(t1), getIReg(rt)));
2952
2953            putHI(unop(Iop_64HIto32, mkexpr(t2)));
2954            putLO(unop(Iop_64to32, mkexpr(t2)));
2955         }
2956         break;
2957
2958      case 0x1B:  /* DIVU */
2959         DIP("divu r%d, r%d", rs, rt);
2960         {
2961            t1 = newTemp(Ity_I64);
2962            t2 = newTemp(Ity_I64);
2963            assign(t1, unop(Iop_32Uto64, getIReg(rs)));
2964            assign(t2, binop(Iop_DivModU64to32, mkexpr(t1), getIReg(rt)));
2965            putHI(unop(Iop_64HIto32, mkexpr(t2)));
2966            putLO(unop(Iop_64to32, mkexpr(t2)));
2967         }
2968         break;
2969
2970      case 0x10:  /* MFHI */
2971         DIP("mfhi r%d", rd);
2972         putIReg(rd, getHI());
2973         break;
2974
2975      case 0x11:  /* MTHI */
2976         DIP("mthi r%d", rs);
2977         putHI(getIReg(rs));
2978         break;
2979
2980      case 0x12:  /* MFLO */
2981         DIP("mflo r%d", rd);
2982         putIReg(rd, getLO());
2983         break;
2984
2985      case 0x13:  /* MTLO */
2986         DIP("mtlo r%d", rs);
2987         putLO(getIReg(rs));
2988         break;
2989
2990      case 0x21:  /* ADDU */
2991         DIP("addu r%d, r%d, r%d", rd, rs, rt);
2992         ALU_PATTERN(Iop_Add32);
2993         break;
2994
2995      case 0x22:  /* SUB */
2996         DIP("sub r%d, r%d, r%d", rd, rs, rt);
2997         ALU_PATTERN(Iop_Sub32);
2998         break;
2999
3000      case 0x23:  /* SUBU */
3001         DIP("subu r%d, r%d, r%d", rd, rs, rt);
3002         ALU_PATTERN(Iop_Sub32);
3003         break;
3004
3005      case 0x24:  /* AND */
3006         DIP("and r%d, r%d, r%d", rd, rs, rt);
3007         ALU_PATTERN(Iop_And32);
3008         break;
3009
3010      case 0x25:  /* OR */
3011         DIP("or r%d, r%d, r%d", rd, rs, rt);
3012         ALU_PATTERN(Iop_Or32);
3013         break;
3014
3015      case 0x26:  /* XOR */
3016         DIP("xor r%d, r%d, r%d", rd, rs, rt);
3017         ALU_PATTERN(Iop_Xor32);
3018         break;
3019
3020      case 0x27:  /* NOR */
3021         DIP("nor r%d, r%d, r%d", rd, rs, rt);
3022         putIReg(rd, unop(Iop_Not32, binop(Iop_Or32, getIReg(rs),getIReg(rt))));
3023         break;
3024
3025      case 0x08:  /* JR */
3026         DIP("jr r%d", rs);
3027         t0 = newTemp(ty);
3028         assign(t0, getIReg(rs));
3029         lastn = mkexpr(t0);
3030         break;
3031
3032      case 0x09:  /* JALR */
3033         DIP("jalr r%d r%d", rd, rs);
3034         putIReg(rd, mkU32(guest_PC_curr_instr + 8));
3035         t0 = newTemp(Ity_I32);
3036         assign(t0, getIReg(rs));
3037         lastn = mkexpr(t0);
3038         break;
3039
3040      case 0x0C:  /* SYSCALL */
3041         DIP("syscall");
3042         putPC(mkU32(guest_PC_curr_instr + 4));
3043         dres.jk_StopHere = Ijk_Sys_syscall;
3044         dres.whatNext    = Dis_StopHere;
3045         break;
3046
3047      case 0x2A:  /* SLT */
3048         DIP("slt r%d, r%d, r%d", rd, rs, rt);
3049         putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
3050                                      getIReg(rt))));
3051         break;
3052
3053      case 0x2B:  /* SLTU */
3054         DIP("sltu r%d, r%d, r%d", rd, rs, rt);
3055         putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
3056                                      getIReg(rt))));
3057         break;
3058
3059      case 0x00:
3060         /* SLL */
3061         DIP("sll r%d, r%d, %d", rd, rt, sa);
3062         SXX_PATTERN(Iop_Shl32);
3063         break;
3064
3065      case 0x04:  /* SLLV */
3066         DIP("sllv r%d, r%d, r%d", rd, rt, rs);
3067         SXXV_PATTERN(Iop_Shl32);
3068         break;
3069
3070      case 0x03:  /* SRA */
3071         DIP("sra r%d, r%d, %d", rd, rt, sa);
3072         SXX_PATTERN(Iop_Sar32);
3073         break;
3074
3075      case 0x07:  /* SRAV */
3076         DIP("srav r%d, r%d, r%d", rd, rt, rs);
3077         SXXV_PATTERN(Iop_Sar32);
3078         break;
3079
3080      case 0x02: {  /* SRL */
3081         rot = get_rot(cins);
3082         if (rot) {
3083            DIP("rotr r%d, r%d, %d", rd, rt, sa);
3084            putIReg(rd, mkWidenFrom32(ty, genROR32(mkNarrowTo32(ty,
3085                        getIReg(rt)), sa), False));
3086         } else {
3087            DIP("srl r%d, r%d, %d", rd, rt, sa);
3088            SXX_PATTERN(Iop_Shr32);
3089         }
3090      break;
3091      }
3092
3093      case 0x06: {
3094         rot = get_rotv(cins);
3095         if (rot) {
3096            DIP("rotrv r%d, r%d, r%d", rd, rt, rs);
3097            putIReg(rd, mkWidenFrom32(ty, genRORV32(mkNarrowTo32(ty,
3098                        getIReg(rt)), mkNarrowTo32(ty, getIReg(rs))),False));
3099            break;
3100         } else {
3101            /* SRLV */
3102            DIP("srlv r%d, r%d, r%d", rd, rt, rs);
3103            SXXV_PATTERN(Iop_Shr32);
3104            break;
3105         }
3106      }
3107
3108      case 0x0D:  /* BREAK */
3109         DIP("Info: Breakpoint...code = %d", trap_code);
3110         jmp_lit(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
3111         vassert(dres.whatNext == Dis_StopHere);
3112         break;
3113
3114      case 0x30: { /* TGE */
3115         /*tge */ DIP("tge r%d, r%d %d", rs, rt, trap_code);
3116         stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rt), getIReg (rs)),
3117                            Ijk_SigTRAP,
3118                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
3119         break;
3120      }
3121      case 0x31: { /* TGEU */
3122         /*tgeu */ DIP("tgeu r%d, r%d %d", rs, rt, trap_code);
3123         stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rt), getIReg (rs)),
3124                            Ijk_SigTRAP,
3125                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
3126         break;
3127      }
3128      case 0x32: { /* TLT */
3129         /*tlt */ DIP("tlt r%d, r%d %d", rs, rt, trap_code);
3130         stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs), getIReg (rt)),
3131                            Ijk_SigTRAP,
3132                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
3133         break;
3134      }
3135      case 0x33: { /* TLTU */
3136         /*tltu */ DIP("tltu r%d, r%d %d", rs, rt, trap_code);
3137         stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs), getIReg (rt)),
3138                            Ijk_SigTRAP,
3139                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
3140         break;
3141      }
3142      case 0x34: { /* TEQ */
3143         /*teq */ DIP("teq r%d, r%d %d", rs, rt, trap_code);
3144         stmt (IRStmt_Exit(binop (Iop_CmpEQ32, getIReg (rs), getIReg (rt)),
3145               Ijk_SigTRAP, IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
3146         break;
3147      }
3148      case 0x36: { /* TNE */
3149         /*tne */ DIP("tne r%d, r%d %d", rs, rt, trap_code);
3150         stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs), getIReg (rt)),
3151                            Ijk_SigTRAP,
3152                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
3153         break;
3154      }
3155      case 0x0F: {
3156         /*SYNC*/ DIP("sync r%d, r%d, %d", rt, rd, sel);
3157         lsb = get_lsb(cins);
3158         IRDirty *d = unsafeIRDirty_0_N(0,
3159                                        "mips32_dirtyhelper_sync",
3160                                        &mips32_dirtyhelper_sync,
3161                                        mkIRExprVec_1
3162                                        (mkU32(lsb)));
3163
3164         d->needsBBP = False;
3165         d->nFxState = 0;
3166
3167         stmt(IRStmt_Dirty(d));
3168         break;
3169      }
3170
3171      default:
3172         goto decode_failure;
3173      }
3174      break;
3175
3176   case 0x01:     /* Regimm */
3177
3178      switch (rt) {
3179      case 0x01:  /* BGEZ */
3180         DIP("bgez r%d, %d", rs, imm);
3181         dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
3182                           mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
3183         break;
3184
3185      case 0x03:  /* BGEZL */
3186         DIP("bgezl r%d, %d", rs, imm);
3187         lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
3188                                   getIReg(rs), mode64 ?
3189                                      mkU64(0x8000000000000000ULL)
3190                                      :mkU32(0x80000000)),
3191                                   mkU32(0x0)), imm);
3192         break;
3193
3194      case 0x00:  /* BLTZ */
3195         DIP("bltz r%d, %d", rs, imm);
3196         dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
3197                    mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
3198         break;
3199
3200      case 0x02:  /* BLTZL */
3201         DIP("bltzl r%d, %d", rs, imm);
3202         lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
3203                                   getIReg(rs), mkU32(0x80000000)),
3204                                   mkU32(0x80000000)), imm);
3205         break;
3206
3207      case 0x10:  /* BLTZAL */
3208         DIP("bltzal r%d, %d", rs, imm);
3209         dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
3210                    mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
3211         break;
3212
3213      case 0x12:  /* BLTZALL */
3214         DIP("bltzall r%d, %d", rs, imm);
3215         putIReg(31, mkU32(guest_PC_curr_instr + 8));
3216         lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
3217                                   getIReg(rs), mkU32(0x80000000)),
3218                                                mkU32(0x80000000)), imm);
3219         break;
3220
3221      case 0x11:  /* BGEZAL */
3222         DIP("bgezal r%d, %d", rs, imm);
3223         dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
3224                    mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
3225         break;
3226
3227      case 0x13:  /* BGEZALL */
3228         DIP("bgezall r%d, %d", rs, imm);
3229         putIReg(31, mkU32(guest_PC_curr_instr + 8));
3230         lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
3231                                   getIReg(rs), mkU32(0x80000000)),
3232                                   mkU32(0x0)), imm);
3233         break;
3234
3235      case 0x08: { /* TGEI */
3236         /*tgei */ DIP("tgei r%d, %d %d", rs, imm, trap_code);
3237         stmt (IRStmt_Exit (binop (Iop_CmpLT32S, mkU32 (imm), getIReg (rs)),
3238                            Ijk_SigTRAP,
3239                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
3240         break;
3241      }
3242      case 0x09: { /* TGEIU */
3243         /*tqeiu */ DIP("tgeiu r%d, %d %d", rs, imm, trap_code);
3244         stmt (IRStmt_Exit (binop (Iop_CmpLT32U, mkU32 (imm), getIReg (rs)),
3245                            Ijk_SigTRAP,
3246                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
3247         break;
3248      }
3249      case 0x0A: { /* TLTI */
3250         /*tlti */ DIP("tlti r%d, %d %d", rs, imm, trap_code);
3251         stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs), mkU32 (imm)),
3252                            Ijk_SigTRAP,
3253                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
3254         break;
3255      }
3256      case 0x0B: { /* TLTIU */
3257         /*tltiu */ DIP("tltiu r%d, %d %d", rs, imm, trap_code);
3258         stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs), mkU32 (imm)),
3259                            Ijk_SigTRAP,
3260                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
3261         break;
3262      }
3263      case 0x0C: { /* TEQI */
3264         /*teqi */ DIP("teqi r%d, %d %d", rs, imm, trap_code);
3265         stmt (IRStmt_Exit (binop (Iop_CmpEQ32, getIReg (rs), mkU32 (imm)),
3266                            Ijk_SigTRAP,
3267                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
3268         break;
3269      }
3270      case 0x0E: { /* TNEI */
3271         /*tnei */ DIP("tnei r%d, %d %d", rs, imm, trap_code);
3272         stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs), mkU32 (imm)),
3273                            Ijk_SigTRAP,
3274                            IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC));
3275         break;
3276      }
3277      case 0x1F:
3278          /*SYNCI*/
3279             //Just ignore it
3280             break;
3281
3282      default:
3283         goto decode_failure;
3284      }
3285      break;
3286
3287   case 0x04:
3288      DIP("beq r%d, r%d, %d", rs, rt, imm);
3289      dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)),
3290                              imm, &bstmt);
3291      break;
3292
3293   case 0x14:
3294      DIP("beql r%d, r%d, %d", rs, rt, imm);
3295      lastn = dis_branch_likely(binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)),
3296                                      imm);
3297      break;
3298
3299   case 0x05:
3300      DIP("bne r%d, r%d, %d", rs, rt, imm);
3301      dis_branch(False, binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)),
3302                              imm, &bstmt);
3303      break;
3304
3305   case 0x15:
3306      DIP("bnel r%d, r%d, %d", rs, rt, imm);
3307      lastn =
3308          dis_branch_likely(binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)), imm);
3309      break;
3310
3311   case 0x07:     /* BGTZ */
3312      DIP("bgtz r%d, %d", rs, imm);
3313      dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE32S, getIReg(rs),
3314                             mkU32(0x00))), imm, &bstmt);
3315      break;
3316
3317   case 0x17:     /* BGTZL */
3318      DIP("bgtzl r%d, %d", rs, imm);
3319      lastn = dis_branch_likely(binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x00)),
3320                                      imm);
3321      break;
3322
3323   case 0x06:     /* BLEZ */
3324      DIP("blez r%d, %d", rs, imm);
3325      dis_branch(False,binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x0)), imm,
3326                             &bstmt);
3327      break;
3328
3329   case 0x16:     /* BLEZL */
3330      DIP("blezl r%d, %d", rs, imm);
3331      lastn = dis_branch_likely(unop(Iop_Not1, (binop(Iop_CmpLE32S,
3332                                     getIReg(rs), mkU32(0x0)))), imm);
3333      break;
3334
3335   case 0x08:     /* ADDI TODO: Check this */
3336      DIP("addi r%d, r%d, %d", rt, rs, imm);
3337      putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
3338      break;
3339
3340   case 0x09:     /* ADDIU */
3341      DIP("addiu r%d, r%d, %d", rt, rs, imm);
3342      putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
3343      break;
3344
3345   case 0x0C:     /* ANDI */
3346      DIP("andi r%d, r%d, %d", rt, rs, imm);
3347      ALUI_PATTERN(Iop_And32);
3348      break;
3349
3350   case 0x0E:     /* XORI */
3351      DIP("xori r%d, r%d, %d", rt, rs, imm);
3352      ALUI_PATTERN(Iop_Xor32);
3353      break;
3354
3355   case 0x0D:     /* ORI */
3356      DIP("ori r%d, r%d, %d", rt, rs, imm);
3357      ALUI_PATTERN(Iop_Or32);
3358      break;
3359
3360   case 0x0A:     /* SLTI */
3361      DIP("slti r%d, r%d, %d", rt, rs, imm);
3362      putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
3363                                         mkU32(extend_s_16to32(imm)))));
3364      break;
3365
3366   case 0x0B:     /* SLTIU */
3367      DIP("sltiu r%d, r%d, %d", rt, rs, imm);
3368      putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
3369                                         mkU32(extend_s_16to32(imm)))));
3370      break;
3371
3372   case 0x30:     /* LL / LWC0 */
3373      DIP("ll r%d, %d(r%d)", rt, imm, rs);
3374      LOAD_STORE_PATTERN;
3375
3376      t2 = newTemp(Ity_I32);
3377#if defined (_MIPSEL)
3378      stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), NULL /*this is a load */ ));
3379#elif defined (_MIPSEB)
3380      stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), NULL /*this is a load */ ));
3381#endif
3382
3383      putIReg(rt, mkexpr(t2));
3384      break;
3385
3386   case 0x38:     /* SC / SWC0 */
3387      DIP("sc r%d, %d(r%d)", rt, imm, rs);
3388      LOAD_STORE_PATTERN;
3389
3390      t2 = newTemp(Ity_I1);
3391#if defined (_MIPSEL)
3392      stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt))));
3393#elif defined (_MIPSEB)
3394      stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt))));
3395#endif
3396
3397      putIReg(rt, unop(Iop_1Uto32, mkexpr(t2)));
3398      break;
3399
3400 decode_failure:
3401      /* All decode failures end up here. */
3402      DIP("vex mips->IR: unhandled instruction bytes: "
3403          "0x%x 0x%x 0x%x 0x%x\n",
3404          (Int) getIByte(delta_start + 0),
3405          (Int) getIByte(delta_start + 1),
3406          (Int) getIByte(delta_start + 2),
3407          (Int) getIByte(delta_start + 3));
3408
3409      /* Tell the dispatcher that this insn cannot be decoded, and so has
3410         not been executed, and (is currently) the next to be executed.
3411         EIP should be up-to-date since it made so at the start bnezof each
3412         insn, but nevertheless be paranoid and update it again right
3413         now. */
3414      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_PC),
3415           mkU32(guest_PC_curr_instr)));
3416      jmp_lit(&dres, Ijk_NoDecode, guest_PC_curr_instr);
3417      dres.whatNext = Dis_StopHere;
3418      dres.len = 0;
3419      return dres;
3420   }        /* switch (opc) for the main (primary) opcode switch. */
3421
3422   /* All MIPS insn have 4 bytes */
3423
3424   if (delay_slot_branch) {
3425      delay_slot_branch = False;
3426      stmt(bstmt);
3427      bstmt = NULL;
3428      putPC(mkU32(guest_PC_curr_instr + 4));
3429      dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
3430                         Ijk_Call : Ijk_Boring;
3431   }
3432
3433   if (likely_delay_slot) {
3434      dres.jk_StopHere = Ijk_Boring;
3435      dres.whatNext = Dis_StopHere;
3436      putPC(lastn);
3437      lastn = NULL;
3438   }
3439   if (delay_slot_jump) {
3440      putPC(lastn);
3441      lastn = NULL;
3442      dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
3443                         Ijk_Call : Ijk_Boring;
3444   }
3445
3446 decode_success:
3447   /* All decode successes end up here. */
3448   switch (dres.whatNext) {
3449      case Dis_Continue:
3450         putPC(mkU32(guest_PC_curr_instr + 4));
3451         break;
3452      case Dis_ResteerU:
3453      case Dis_ResteerC:
3454         putPC(mkU32(dres.continueAt));
3455         break;
3456      case Dis_StopHere:
3457         break;
3458      default:
3459         vassert(0);
3460         break;
3461   }
3462
3463   // On MIPS we need to check if the last instruction
3464   // in block is branch or jump
3465   if ((vex_control.guest_max_insns - 1) == (delta+4)/4)
3466      if (branch_or_jump(guest_code + delta + 4)) {
3467         dres.whatNext = Dis_StopHere;
3468         dres.jk_StopHere = Ijk_Boring;
3469         putPC(mkU32(guest_PC_curr_instr + 4));
3470   }
3471   dres.len = 4;
3472
3473   DIP("\n");
3474
3475   return dres;
3476
3477}
3478
3479/*------------------------------------------------------------*/
3480/*--- Top-level fn                                         ---*/
3481/*------------------------------------------------------------*/
3482
3483/* Disassemble a single instruction into IR.  The instruction
3484   is located in host memory at &guest_code[delta]. */
3485
3486DisResult
3487disInstr_MIPS(IRSB*        irsb_IN,
3488              Bool         (*resteerOkFn) (void *, Addr64),
3489              Bool         resteerCisOk,
3490              void*        callback_opaque,
3491              UChar*       guest_code_IN,
3492              Long         delta,
3493              Addr64       guest_IP,
3494              VexArch      guest_arch,
3495              VexArchInfo* archinfo,
3496              VexAbiInfo*  abiinfo,
3497              Bool         host_bigendian_IN)
3498{
3499   DisResult dres;
3500
3501   /* Set globals (see top of this file) */
3502   vassert(guest_arch == VexArchMIPS32);
3503
3504   mode64 = guest_arch != VexArchMIPS32;
3505
3506   guest_code = guest_code_IN;
3507   irsb = irsb_IN;
3508   host_is_bigendian = host_bigendian_IN;
3509   guest_PC_curr_instr = (Addr32) guest_IP;
3510   guest_PC_bbstart = (Addr32) toUInt(guest_IP - delta);
3511
3512   dres = disInstr_MIPS_WRK(resteerOkFn, resteerCisOk, callback_opaque,
3513                            delta, archinfo, abiinfo);
3514
3515   return dres;
3516}
3517
3518/*--------------------------------------------------------------------*/
3519/*--- end                                        guest_mips_toIR.c ---*/
3520/*--------------------------------------------------------------------*/
3521