• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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. */
55 static Bool host_is_bigendian;
56 
57 /* Pointer to the guest code area. */
58 static UChar *guest_code;
59 
60 /* The guest address corresponding to guest_code[0]. */
61 static Addr32 guest_PC_bbstart;
62 
63 /* CONST: The guest address for the instruction currently being
64    translated. */
65 static Addr32 guest_PC_curr_instr;
66 
67 /* MOD: The IRSB* into which we're generating code. */
68 static IRSB *irsb;
69 
70 /* Is our guest binary 32 or 64bit?  Set at each call to
71    disInstr_MIPS below. */
72 static 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 
integerGuestRegOffset(UInt iregNo)89 static 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 
floatGuestRegOffset(UInt fregNo)171 static 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. */
getUInt(UChar * p)249 static 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 
get_opcode(UInt mipsins)331 static UInt get_opcode(UInt mipsins)
332 {
333    return (0xFC000000 & mipsins) >> 26;
334 }
335 
get_rs(UInt mipsins)336 static UInt get_rs(UInt mipsins)
337 {
338    return (0x03E00000 & mipsins) >> 21;
339 }
340 
get_rt(UInt mipsins)341 static UInt get_rt(UInt mipsins)
342 {
343    return (0x001F0000 & mipsins) >> 16;
344 }
345 
get_imm(UInt mipsins)346 static UInt get_imm(UInt mipsins)
347 {
348    return (0x0000FFFF & mipsins);
349 }
350 
get_instr_index(UInt mipsins)351 static UInt get_instr_index(UInt mipsins)
352 {
353    return (0x03FFFFFF & mipsins);
354 }
355 
get_rd(UInt mipsins)356 static UInt get_rd(UInt mipsins)
357 {
358    return (0x0000F800 & mipsins) >> 11;
359 }
360 
get_sa(UInt mipsins)361 static UInt get_sa(UInt mipsins)
362 {
363    return (0x000007C0 & mipsins) >> 6;
364 }
365 
get_function(UInt mipsins)366 static UInt get_function(UInt mipsins)
367 {
368    return (0x0000003F & mipsins);
369 }
370 
get_ft(UInt mipsins)371 static UInt get_ft(UInt mipsins)
372 {
373    return (0x001F0000 & mipsins) >> 16;
374 }
375 
get_fs(UInt mipsins)376 static UInt get_fs(UInt mipsins)
377 {
378    return (0x0000F800 & mipsins) >> 11;
379 }
380 
get_fd(UInt mipsins)381 static UInt get_fd(UInt mipsins)
382 {
383    return (0x000007C0 & mipsins) >> 6;
384 }
385 
get_mov_cc(UInt mipsins)386 static UInt get_mov_cc(UInt mipsins)
387 {
388    return (0x001C0000 & mipsins) >> 18;
389 }
390 
get_bc1_cc(UInt mipsins)391 static UInt get_bc1_cc(UInt mipsins)
392 {
393    return (0x001C0000 & mipsins) >> 18;
394 }
395 
get_fpc_cc(UInt mipsins)396 static UInt get_fpc_cc(UInt mipsins)
397 {
398    return (0x00000700 & mipsins) >> 8;
399 }
400 
get_tf(UInt mipsins)401 static UInt get_tf(UInt mipsins)
402 {
403    return (0x00010000 & mipsins) >> 16;
404 }
405 
get_nd(UInt mipsins)406 static UInt get_nd(UInt mipsins)
407 {
408    return (0x00020000 & mipsins) >> 17;
409 }
410 
get_fmt(UInt mipsins)411 static UInt get_fmt(UInt mipsins)
412 {
413    return (0x03E00000 & mipsins) >> 21;
414 }
415 
get_FC(UInt mipsins)416 static UInt get_FC(UInt mipsins)
417 {
418    return (0x000000F0 & mipsins) >> 4;
419 }
420 
get_cond(UInt mipsins)421 static UInt get_cond(UInt mipsins)
422 {
423    return (0x0000000F & mipsins);
424 }
425 
426 /* for break & syscall */
get_code(UInt mipsins)427 static UInt get_code(UInt mipsins)
428 {
429    return (0xFFC0 & mipsins) >> 6;
430 }
431 
get_lsb(UInt mipsins)432 static UInt get_lsb(UInt mipsins)
433 {
434    return (0x7C0 & mipsins) >> 6;
435 }
436 
get_msb(UInt mipsins)437 static UInt get_msb(UInt mipsins)
438 {
439    return (0x0000F800 & mipsins) >> 11;
440 }
441 
get_rot(UInt mipsins)442 static UInt get_rot(UInt mipsins)
443 {
444    return (0x00200000 & mipsins) >> 21;
445 }
446 
get_rotv(UInt mipsins)447 static UInt get_rotv(UInt mipsins)
448 {
449    return (0x00000040 & mipsins) >> 6;
450 }
451 
get_sel(UInt mipsins)452 static UInt get_sel(UInt mipsins)
453 {
454    return (0x00000007 & mipsins);
455 }
456 
branch_or_jump(UChar * addr)457 static 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 
is_Branch_or_Jump_and_Link(UChar * addr)513 static 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 
branch_or_link_likely(UChar * addr)544 static 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 
mkU8(UInt i)577 static 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 */
mkU32(UInt i)584 static 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 */
mkU64(ULong i)590 static IRExpr *mkU64(ULong i)
591 {
592    return IRExpr_Const(IRConst_U64(i));
593 }
594 
mkexpr(IRTemp tmp)595 static IRExpr *mkexpr(IRTemp tmp)
596 {
597    return IRExpr_RdTmp(tmp);
598 }
599 
unop(IROp op,IRExpr * a)600 static IRExpr *unop(IROp op, IRExpr * a)
601 {
602    return IRExpr_Unop(op, a);
603 }
604 
binop(IROp op,IRExpr * a1,IRExpr * a2)605 static IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2)
606 {
607    return IRExpr_Binop(op, a1, a2);
608 }
609 
triop(IROp op,IRExpr * a1,IRExpr * a2,IRExpr * a3)610 static IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3)
611 {
612    return IRExpr_Triop(op, a1, a2, a3);
613 }
614 
load(IRType ty,IRExpr * addr)615 static 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". */
stmt(IRStmt * st)627 static void stmt(IRStmt * st)
628 {
629    addStmtToIRSB(irsb, st);
630 }
631 
assign(IRTemp dst,IRExpr * e)632 static void assign(IRTemp dst, IRExpr * e)
633 {
634    stmt(IRStmt_WrTmp(dst, e));
635 }
636 
store(IRExpr * addr,IRExpr * data)637 static 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. */
newTemp(IRType ty)647 static 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. */
genROR32(IRExpr * src,Int rot)654 static 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 
genRORV32(IRExpr * src,IRExpr * rs)663 static 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 
extend_s_16to32(UInt x)674 static UInt extend_s_16to32(UInt x)
675 {
676    return (UInt) ((((Int) x) << 16) >> 16);
677 }
678 
extend_s_18to32(UInt x)679 static UInt extend_s_18to32(UInt x)
680 {
681    return (UInt) ((((Int) x) << 14) >> 14);
682 }
683 
jmp_lit(DisResult * dres,IRJumpKind kind,Addr32 d32)684 static 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. */
getIByte(Int delta)697 static UChar getIByte(Int delta)
698 {
699    return guest_code[delta];
700 }
701 
getIReg(UInt iregNo)702 static 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 
getHI(void)713 static IRExpr *getHI(void)
714 {
715    return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32);
716 }
717 
getLO(void)718 static IRExpr *getLO(void)
719 {
720    return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32);
721 }
722 
getFCSR(void)723 static IRExpr *getFCSR(void)
724 {
725    return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32);
726 }
727 
putFCSR(IRExpr * e)728 static void putFCSR(IRExpr * e)
729 {
730    stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
731 }
732 
getULR(void)733 static IRExpr *getULR(void)
734 {
735    return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32);
736 }
737 
putIReg(UInt archreg,IRExpr * e)738 static 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 
putLO(IRExpr * e)747 static void putLO(IRExpr * e)
748 {
749    stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e));
750 }
751 
putHI(IRExpr * e)752 static void putHI(IRExpr * e)
753 {
754    stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e));
755 }
756 
putPC(IRExpr * e)757 static void putPC(IRExpr * e)
758 {
759    stmt(IRStmt_Put(OFFB_PC, e));
760 }
761 
mkWidenFrom32(IRType ty,IRExpr * src,Bool sined)762 static 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. */
narrowTo(IRType dst_ty,IRExpr * e)772 static 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 
mkNarrowTo32(IRType ty,IRExpr * src)802 static 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 
getLoFromF64(IRType ty,IRExpr * src)808 static 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 
mkWidenFromF32(IRType ty,IRExpr * src)822 static 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 
dis_branch_likely(IRExpr * guard,UInt imm)828 static 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 
dis_branch(Bool link,IRExpr * guard,UInt imm,IRStmt ** set)851 static 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 
getFReg(UInt dregNo)875 static 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 
getDReg(UInt dregNo)882 static 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 
putFReg(UInt dregNo,IRExpr * e)903 static 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 
putDReg(UInt dregNo,IRExpr * e)911 static 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 
setFPUCondCode(IRExpr * e,UInt cc)927 static 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 
get_IR_roundingmode(void)941 static 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 /*********************************************************/
dis_instr_CCondFmt(UInt cins)966 static 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 
disInstr_MIPS_WRK(Bool (* resteerOkFn)(void *,Addr64),Bool resteerCisOk,void * callback_opaque,Long delta64,VexArchInfo * archinfo,VexAbiInfo * abiinfo)1192 static 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 
3486 DisResult
disInstr_MIPS(IRSB * irsb_IN,Bool (* resteerOkFn)(void *,Addr64),Bool resteerCisOk,void * callback_opaque,UChar * guest_code_IN,Long delta,Addr64 guest_IP,VexArch guest_arch,VexArchInfo * archinfo,VexAbiInfo * abiinfo,Bool host_bigendian_IN)3487 disInstr_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