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