blob: a41ce4193ed4fc7fd62730c5cc262ffc71ffb7f5 [file] [log] [blame]
sewardj362cf842012-06-07 08:59:53 +00001
2/*--------------------------------------------------------------------*/
3/*--- begin guest_mips_toIR.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
petarjb92a9542013-02-27 22:57:17 +000010 Copyright (C) 2010-2013 RT-RK
sewardj362cf842012-06-07 08:59:53 +000011 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"
petarjb92a9542013-02-27 22:57:17 +000037#include "libvex_guest_mips64.h"
sewardj362cf842012-06-07 08:59:53 +000038
39#include "main_util.h"
40#include "main_globals.h"
41#include "guest_generic_bb_to_IR.h"
42#include "guest_mips_defs.h"
43
44/*------------------------------------------------------------*/
petarjb92a9542013-02-27 22:57:17 +000045/*--- Globals ---*/
sewardj362cf842012-06-07 08:59:53 +000046/*------------------------------------------------------------*/
47
48/* These are set at the start of the translation of a instruction, so
petarjb92a9542013-02-27 22:57:17 +000049 that we don't have to pass them around endlessly. CONST means does
50 not change during translation of the instruction. */
sewardj362cf842012-06-07 08:59:53 +000051
sewardj9b769162014-07-24 12:42:03 +000052/* CONST: what is the host's endianness? This has to do with float vs
53 double register accesses on VFP, but it's complex and not properly
54 thought out. */
55static VexEndness host_endness;
sewardj362cf842012-06-07 08:59:53 +000056
57/* Pointer to the guest code area. */
florian8462d112014-09-24 15:18:09 +000058static const UChar *guest_code;
sewardj362cf842012-06-07 08:59:53 +000059
sewardj362cf842012-06-07 08:59:53 +000060/* CONST: The guest address for the instruction currently being
61 translated. */
petarjb92a9542013-02-27 22:57:17 +000062#if defined(VGP_mips32_linux)
sewardj362cf842012-06-07 08:59:53 +000063static Addr32 guest_PC_curr_instr;
petarjb92a9542013-02-27 22:57:17 +000064#else
65static Addr64 guest_PC_curr_instr;
66#endif
sewardj362cf842012-06-07 08:59:53 +000067
68/* MOD: The IRSB* into which we're generating code. */
69static IRSB *irsb;
70
petarjb92a9542013-02-27 22:57:17 +000071/* Is our guest binary 32 or 64bit? Set at each call to
sewardj362cf842012-06-07 08:59:53 +000072 disInstr_MIPS below. */
73static Bool mode64 = False;
74
dejanj0e006f22014-02-19 11:56:29 +000075/* CPU has FPU and 32 dbl. prec. FP registers. */
76static Bool fp_mode64 = False;
77
petarj0c30de82013-04-19 12:35:00 +000078/* Define 1.0 in single and double precision. */
79#define ONE_SINGLE 0x3F800000
80#define ONE_DOUBLE 0x3FF0000000000000ULL
81
sewardj362cf842012-06-07 08:59:53 +000082/*------------------------------------------------------------*/
petarjb92a9542013-02-27 22:57:17 +000083/*--- Debugging output ---*/
sewardj362cf842012-06-07 08:59:53 +000084/*------------------------------------------------------------*/
85
86#define DIP(format, args...) \
87 if (vex_traceflags & VEX_TRACE_FE) \
88 vex_printf(format, ## args)
89
90/*------------------------------------------------------------*/
91/*--- Helper bits and pieces for deconstructing the ---*/
92/*--- mips insn stream. ---*/
93/*------------------------------------------------------------*/
94
95/* ---------------- Integer registers ---------------- */
96
97static UInt integerGuestRegOffset(UInt iregNo)
98{
99 /* Do we care about endianness here? We do if sub-parts of integer
100 registers are accessed, but I don't think that ever happens on
101 MIPS. */
102 UInt ret;
petarjb92a9542013-02-27 22:57:17 +0000103 if (!mode64)
104 switch (iregNo) {
105 case 0:
106 ret = offsetof(VexGuestMIPS32State, guest_r0); break;
107 case 1:
108 ret = offsetof(VexGuestMIPS32State, guest_r1); break;
109 case 2:
110 ret = offsetof(VexGuestMIPS32State, guest_r2); break;
111 case 3:
112 ret = offsetof(VexGuestMIPS32State, guest_r3); break;
113 case 4:
114 ret = offsetof(VexGuestMIPS32State, guest_r4); break;
115 case 5:
116 ret = offsetof(VexGuestMIPS32State, guest_r5); break;
117 case 6:
118 ret = offsetof(VexGuestMIPS32State, guest_r6); break;
119 case 7:
120 ret = offsetof(VexGuestMIPS32State, guest_r7); break;
121 case 8:
122 ret = offsetof(VexGuestMIPS32State, guest_r8); break;
123 case 9:
124 ret = offsetof(VexGuestMIPS32State, guest_r9); break;
125 case 10:
126 ret = offsetof(VexGuestMIPS32State, guest_r10); break;
127 case 11:
128 ret = offsetof(VexGuestMIPS32State, guest_r11); break;
129 case 12:
130 ret = offsetof(VexGuestMIPS32State, guest_r12); break;
131 case 13:
132 ret = offsetof(VexGuestMIPS32State, guest_r13); break;
133 case 14:
134 ret = offsetof(VexGuestMIPS32State, guest_r14); break;
135 case 15:
136 ret = offsetof(VexGuestMIPS32State, guest_r15); break;
137 case 16:
138 ret = offsetof(VexGuestMIPS32State, guest_r16); break;
139 case 17:
140 ret = offsetof(VexGuestMIPS32State, guest_r17); break;
141 case 18:
142 ret = offsetof(VexGuestMIPS32State, guest_r18); break;
143 case 19:
144 ret = offsetof(VexGuestMIPS32State, guest_r19); break;
145 case 20:
146 ret = offsetof(VexGuestMIPS32State, guest_r20); break;
147 case 21:
148 ret = offsetof(VexGuestMIPS32State, guest_r21); break;
149 case 22:
150 ret = offsetof(VexGuestMIPS32State, guest_r22); break;
151 case 23:
152 ret = offsetof(VexGuestMIPS32State, guest_r23); break;
153 case 24:
154 ret = offsetof(VexGuestMIPS32State, guest_r24); break;
155 case 25:
156 ret = offsetof(VexGuestMIPS32State, guest_r25); break;
157 case 26:
158 ret = offsetof(VexGuestMIPS32State, guest_r26); break;
159 case 27:
160 ret = offsetof(VexGuestMIPS32State, guest_r27); break;
161 case 28:
162 ret = offsetof(VexGuestMIPS32State, guest_r28); break;
163 case 29:
164 ret = offsetof(VexGuestMIPS32State, guest_r29); break;
165 case 30:
166 ret = offsetof(VexGuestMIPS32State, guest_r30); break;
167 case 31:
168 ret = offsetof(VexGuestMIPS32State, guest_r31); break;
169 default:
170 vassert(0);
171 break;
172 }
173 else
174 switch (iregNo) {
175 case 0:
176 ret = offsetof(VexGuestMIPS64State, guest_r0); break;
177 case 1:
178 ret = offsetof(VexGuestMIPS64State, guest_r1); break;
179 case 2:
180 ret = offsetof(VexGuestMIPS64State, guest_r2); break;
181 case 3:
182 ret = offsetof(VexGuestMIPS64State, guest_r3); break;
183 case 4:
184 ret = offsetof(VexGuestMIPS64State, guest_r4); break;
185 case 5:
186 ret = offsetof(VexGuestMIPS64State, guest_r5); break;
187 case 6:
188 ret = offsetof(VexGuestMIPS64State, guest_r6); break;
189 case 7:
190 ret = offsetof(VexGuestMIPS64State, guest_r7); break;
191 case 8:
192 ret = offsetof(VexGuestMIPS64State, guest_r8); break;
193 case 9:
194 ret = offsetof(VexGuestMIPS64State, guest_r9); break;
195 case 10:
196 ret = offsetof(VexGuestMIPS64State, guest_r10); break;
197 case 11:
198 ret = offsetof(VexGuestMIPS64State, guest_r11); break;
199 case 12:
200 ret = offsetof(VexGuestMIPS64State, guest_r12); break;
201 case 13:
202 ret = offsetof(VexGuestMIPS64State, guest_r13); break;
203 case 14:
204 ret = offsetof(VexGuestMIPS64State, guest_r14); break;
205 case 15:
206 ret = offsetof(VexGuestMIPS64State, guest_r15); break;
207 case 16:
208 ret = offsetof(VexGuestMIPS64State, guest_r16); break;
209 case 17:
210 ret = offsetof(VexGuestMIPS64State, guest_r17); break;
211 case 18:
212 ret = offsetof(VexGuestMIPS64State, guest_r18); break;
213 case 19:
214 ret = offsetof(VexGuestMIPS64State, guest_r19); break;
215 case 20:
216 ret = offsetof(VexGuestMIPS64State, guest_r20); break;
217 case 21:
218 ret = offsetof(VexGuestMIPS64State, guest_r21); break;
219 case 22:
220 ret = offsetof(VexGuestMIPS64State, guest_r22); break;
221 case 23:
222 ret = offsetof(VexGuestMIPS64State, guest_r23); break;
223 case 24:
224 ret = offsetof(VexGuestMIPS64State, guest_r24); break;
225 case 25:
226 ret = offsetof(VexGuestMIPS64State, guest_r25); break;
227 case 26:
228 ret = offsetof(VexGuestMIPS64State, guest_r26); break;
229 case 27:
230 ret = offsetof(VexGuestMIPS64State, guest_r27); break;
231 case 28:
232 ret = offsetof(VexGuestMIPS64State, guest_r28); break;
233 case 29:
234 ret = offsetof(VexGuestMIPS64State, guest_r29); break;
235 case 30:
236 ret = offsetof(VexGuestMIPS64State, guest_r30); break;
237 case 31:
238 ret = offsetof(VexGuestMIPS64State, guest_r31); break;
239 default:
240 vassert(0);
241 break;
242 }
sewardj362cf842012-06-07 08:59:53 +0000243 return ret;
244}
245
petarjb92a9542013-02-27 22:57:17 +0000246#if defined(VGP_mips32_linux)
sewardj362cf842012-06-07 08:59:53 +0000247#define OFFB_PC offsetof(VexGuestMIPS32State, guest_PC)
petarjb92a9542013-02-27 22:57:17 +0000248#else
249#define OFFB_PC offsetof(VexGuestMIPS64State, guest_PC)
250#endif
sewardj362cf842012-06-07 08:59:53 +0000251
252/* ---------------- Floating point registers ---------------- */
253
254static UInt floatGuestRegOffset(UInt fregNo)
255{
256 vassert(fregNo < 32);
257 UInt ret;
petarjb92a9542013-02-27 22:57:17 +0000258 if (!mode64)
259 switch (fregNo) {
260 case 0:
261 ret = offsetof(VexGuestMIPS32State, guest_f0); break;
262 case 1:
263 ret = offsetof(VexGuestMIPS32State, guest_f1); break;
264 case 2:
265 ret = offsetof(VexGuestMIPS32State, guest_f2); break;
266 case 3:
267 ret = offsetof(VexGuestMIPS32State, guest_f3); break;
268 case 4:
269 ret = offsetof(VexGuestMIPS32State, guest_f4); break;
270 case 5:
271 ret = offsetof(VexGuestMIPS32State, guest_f5); break;
272 case 6:
273 ret = offsetof(VexGuestMIPS32State, guest_f6); break;
274 case 7:
275 ret = offsetof(VexGuestMIPS32State, guest_f7); break;
276 case 8:
277 ret = offsetof(VexGuestMIPS32State, guest_f8); break;
278 case 9:
279 ret = offsetof(VexGuestMIPS32State, guest_f9); break;
280 case 10:
281 ret = offsetof(VexGuestMIPS32State, guest_f10); break;
282 case 11:
283 ret = offsetof(VexGuestMIPS32State, guest_f11); break;
284 case 12:
285 ret = offsetof(VexGuestMIPS32State, guest_f12); break;
286 case 13:
287 ret = offsetof(VexGuestMIPS32State, guest_f13); break;
288 case 14:
289 ret = offsetof(VexGuestMIPS32State, guest_f14); break;
290 case 15:
291 ret = offsetof(VexGuestMIPS32State, guest_f15); break;
292 case 16:
293 ret = offsetof(VexGuestMIPS32State, guest_f16); break;
294 case 17:
295 ret = offsetof(VexGuestMIPS32State, guest_f17); break;
296 case 18:
297 ret = offsetof(VexGuestMIPS32State, guest_f18); break;
298 case 19:
299 ret = offsetof(VexGuestMIPS32State, guest_f19); break;
300 case 20:
301 ret = offsetof(VexGuestMIPS32State, guest_f20); break;
302 case 21:
303 ret = offsetof(VexGuestMIPS32State, guest_f21); break;
304 case 22:
305 ret = offsetof(VexGuestMIPS32State, guest_f22); break;
306 case 23:
307 ret = offsetof(VexGuestMIPS32State, guest_f23); break;
308 case 24:
309 ret = offsetof(VexGuestMIPS32State, guest_f24); break;
310 case 25:
311 ret = offsetof(VexGuestMIPS32State, guest_f25); break;
312 case 26:
313 ret = offsetof(VexGuestMIPS32State, guest_f26); break;
314 case 27:
315 ret = offsetof(VexGuestMIPS32State, guest_f27); break;
316 case 28:
317 ret = offsetof(VexGuestMIPS32State, guest_f28); break;
318 case 29:
319 ret = offsetof(VexGuestMIPS32State, guest_f29); break;
320 case 30:
321 ret = offsetof(VexGuestMIPS32State, guest_f30); break;
322 case 31:
323 ret = offsetof(VexGuestMIPS32State, guest_f31); break;
324 default:
325 vassert(0);
326 break;
327 }
328 else
329 switch (fregNo) {
330 case 0:
331 ret = offsetof(VexGuestMIPS64State, guest_f0); break;
332 case 1:
333 ret = offsetof(VexGuestMIPS64State, guest_f1); break;
334 case 2:
335 ret = offsetof(VexGuestMIPS64State, guest_f2); break;
336 case 3:
337 ret = offsetof(VexGuestMIPS64State, guest_f3); break;
338 case 4:
339 ret = offsetof(VexGuestMIPS64State, guest_f4); break;
340 case 5:
341 ret = offsetof(VexGuestMIPS64State, guest_f5); break;
342 case 6:
343 ret = offsetof(VexGuestMIPS64State, guest_f6); break;
344 case 7:
345 ret = offsetof(VexGuestMIPS64State, guest_f7); break;
346 case 8:
347 ret = offsetof(VexGuestMIPS64State, guest_f8); break;
348 case 9:
349 ret = offsetof(VexGuestMIPS64State, guest_f9); break;
350 case 10:
351 ret = offsetof(VexGuestMIPS64State, guest_f10); break;
352 case 11:
353 ret = offsetof(VexGuestMIPS64State, guest_f11); break;
354 case 12:
355 ret = offsetof(VexGuestMIPS64State, guest_f12); break;
356 case 13:
357 ret = offsetof(VexGuestMIPS64State, guest_f13); break;
358 case 14:
359 ret = offsetof(VexGuestMIPS64State, guest_f14); break;
360 case 15:
361 ret = offsetof(VexGuestMIPS64State, guest_f15); break;
362 case 16:
363 ret = offsetof(VexGuestMIPS64State, guest_f16); break;
364 case 17:
365 ret = offsetof(VexGuestMIPS64State, guest_f17); break;
366 case 18:
367 ret = offsetof(VexGuestMIPS64State, guest_f18); break;
368 case 19:
369 ret = offsetof(VexGuestMIPS64State, guest_f19); break;
370 case 20:
371 ret = offsetof(VexGuestMIPS64State, guest_f20); break;
372 case 21:
373 ret = offsetof(VexGuestMIPS64State, guest_f21); break;
374 case 22:
375 ret = offsetof(VexGuestMIPS64State, guest_f22); break;
376 case 23:
377 ret = offsetof(VexGuestMIPS64State, guest_f23); break;
378 case 24:
379 ret = offsetof(VexGuestMIPS64State, guest_f24); break;
380 case 25:
381 ret = offsetof(VexGuestMIPS64State, guest_f25); break;
382 case 26:
383 ret = offsetof(VexGuestMIPS64State, guest_f26); break;
384 case 27:
385 ret = offsetof(VexGuestMIPS64State, guest_f27); break;
386 case 28:
387 ret = offsetof(VexGuestMIPS64State, guest_f28); break;
388 case 29:
389 ret = offsetof(VexGuestMIPS64State, guest_f29); break;
390 case 30:
391 ret = offsetof(VexGuestMIPS64State, guest_f30); break;
392 case 31:
393 ret = offsetof(VexGuestMIPS64State, guest_f31); break;
394 default:
395 vassert(0);
396 break;
397 }
sewardj362cf842012-06-07 08:59:53 +0000398 return ret;
399}
400
dejanjc3fee0d2013-07-25 09:08:03 +0000401/* ---------------- MIPS32 DSP ASE(r2) accumulators ---------------- */
402
403static UInt accumulatorGuestRegOffset(UInt acNo)
404{
405 vassert(!mode64);
406 vassert(acNo <= 3);
407 UInt ret;
408 switch (acNo) {
409 case 0:
410 ret = offsetof(VexGuestMIPS32State, guest_ac0); break;
411 case 1:
412 ret = offsetof(VexGuestMIPS32State, guest_ac1); break;
413 case 2:
414 ret = offsetof(VexGuestMIPS32State, guest_ac2); break;
415 case 3:
416 ret = offsetof(VexGuestMIPS32State, guest_ac3); break;
417 default:
418 vassert(0);
419 break;
420 }
421 return ret;
422}
423
424/* Do a endian load of a 32-bit word, regardless of the endianness of the
425 underlying host. */
florian8462d112014-09-24 15:18:09 +0000426static inline UInt getUInt(const UChar * p)
sewardj362cf842012-06-07 08:59:53 +0000427{
428 UInt w = 0;
429#if defined (_MIPSEL)
430 w = (w << 8) | p[3];
431 w = (w << 8) | p[2];
432 w = (w << 8) | p[1];
433 w = (w << 8) | p[0];
434#elif defined (_MIPSEB)
435 w = (w << 8) | p[0];
436 w = (w << 8) | p[1];
437 w = (w << 8) | p[2];
438 w = (w << 8) | p[3];
439#endif
440 return w;
441}
442
443#define BITS2(_b1,_b0) \
444 (((_b1) << 1) | (_b0))
445
446#define BITS3(_b2,_b1,_b0) \
447 (((_b2) << 2) | ((_b1) << 1) | (_b0))
448
449#define BITS4(_b3,_b2,_b1,_b0) \
450 (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
451
452#define BITS5(_b4,_b3,_b2,_b1,_b0) \
453 (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0)))
454
455#define BITS6(_b5,_b4,_b3,_b2,_b1,_b0) \
456 ((BITS2((_b5),(_b4)) << 4) \
457 | BITS4((_b3),(_b2),(_b1),(_b0)))
458
459#define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
460 ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
461 | BITS4((_b3),(_b2),(_b1),(_b0)))
462
463#define LOAD_STORE_PATTERN \
petarjb92a9542013-02-27 22:57:17 +0000464 t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
465 if(!mode64) \
466 assign(t1, binop(Iop_Add32, getIReg(rs), \
467 mkU32(extend_s_16to32(imm)))); \
468 else \
469 assign(t1, binop(Iop_Add64, getIReg(rs), \
470 mkU64(extend_s_16to64(imm)))); \
471
petarjd20794a2014-01-31 12:14:20 +0000472#define LOADX_STORE_PATTERN \
473 t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
474 if(!mode64) \
475 assign(t1, binop(Iop_Add32, getIReg(regRs), getIReg(regRt))); \
476 else \
477 assign(t1, binop(Iop_Add64, getIReg(regRs), getIReg(regRt)));
478
petarjb92a9542013-02-27 22:57:17 +0000479#define LWX_SWX_PATTERN64 \
480 t2 = newTemp(Ity_I64); \
petarjfdb2a4c2013-03-02 02:37:01 +0000481 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); \
petarjb92a9542013-02-27 22:57:17 +0000482 t4 = newTemp(Ity_I32); \
483 assign(t4, mkNarrowTo32( ty, binop(Iop_And64, \
484 mkexpr(t1), mkU64(0x3))));
dejanjc3fee0d2013-07-25 09:08:03 +0000485
petarjb92a9542013-02-27 22:57:17 +0000486#define LWX_SWX_PATTERN64_1 \
487 t2 = newTemp(Ity_I64); \
petarjfdb2a4c2013-03-02 02:37:01 +0000488 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); \
petarjb92a9542013-02-27 22:57:17 +0000489 t4 = newTemp(Ity_I64); \
490 assign(t4, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
sewardj362cf842012-06-07 08:59:53 +0000491
492#define LWX_SWX_PATTERN \
493 t2 = newTemp(Ity_I32); \
494 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \
495 t4 = newTemp(Ity_I32); \
496 assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003)))
497
498#define SXXV_PATTERN(op) \
499 putIReg(rd, binop(op, \
500 getIReg(rt), \
501 unop(Iop_32to8, \
502 binop(Iop_And32, \
503 getIReg(rs), \
504 mkU32(0x0000001F) \
505 ) \
506 ) \
507 ) \
508 )
509
petarjb92a9542013-02-27 22:57:17 +0000510#define SXXV_PATTERN64(op) \
511 putIReg(rd, mkWidenFrom32(ty, binop(op, \
512 mkNarrowTo32(ty, getIReg(rt)), \
513 unop(Iop_32to8, \
514 binop(Iop_And32, \
515 mkNarrowTo32(ty, getIReg(rs)), \
516 mkU32(0x0000001F) \
517 ) \
518 ) \
519 ), True \
520 ))
521
sewardj362cf842012-06-07 08:59:53 +0000522#define SXX_PATTERN(op) \
523 putIReg(rd, binop(op, getIReg(rt), mkU8(sa)));
524
525#define ALU_PATTERN(op) \
526 putIReg(rd, binop(op, getIReg(rs), getIReg(rt)));
527
528#define ALUI_PATTERN(op) \
529 putIReg(rt, binop(op, getIReg(rs), mkU32(imm)));
530
531#define ALUI_PATTERN64(op) \
532 putIReg(rt, binop(op, getIReg(rs), mkU64(imm)));
533
petarjb92a9542013-02-27 22:57:17 +0000534#define ALU_PATTERN64(op) \
535 putIReg(rd, mkWidenFrom32(ty, binop(op, \
536 mkNarrowTo32(ty, getIReg(rs)), \
537 mkNarrowTo32(ty, getIReg(rt))), True));
538
sewardj362cf842012-06-07 08:59:53 +0000539#define FP_CONDITIONAL_CODE \
florian99dd03e2013-01-29 03:56:06 +0000540 t3 = newTemp(Ity_I32); \
541 assign(t3, binop(Iop_And32, \
petarjd4564182013-01-29 15:42:29 +0000542 IRExpr_ITE( binop(Iop_CmpEQ32, mkU32(cc), mkU32(0)), \
florian99dd03e2013-01-29 03:56:06 +0000543 binop(Iop_Shr32, getFCSR(), mkU8(23)), \
544 binop(Iop_Shr32, getFCSR(), mkU8(24+cc))), \
545 mkU32(0x1)));
sewardj362cf842012-06-07 08:59:53 +0000546
dejanj0e006f22014-02-19 11:56:29 +0000547#define ILLEGAL_INSTRUCTON \
548 putPC(mkU32(guest_PC_curr_instr + 4)); \
549 dres.jk_StopHere = Ijk_SigILL; \
550 dres.whatNext = Dis_StopHere;
551
sewardj362cf842012-06-07 08:59:53 +0000552/*------------------------------------------------------------*/
petarjb92a9542013-02-27 22:57:17 +0000553/*--- Field helpers ---*/
sewardj362cf842012-06-07 08:59:53 +0000554/*------------------------------------------------------------*/
555
556static UInt get_opcode(UInt mipsins)
557{
558 return (0xFC000000 & mipsins) >> 26;
559}
560
561static UInt get_rs(UInt mipsins)
562{
563 return (0x03E00000 & mipsins) >> 21;
564}
565
566static UInt get_rt(UInt mipsins)
567{
568 return (0x001F0000 & mipsins) >> 16;
569}
570
571static UInt get_imm(UInt mipsins)
572{
573 return (0x0000FFFF & mipsins);
574}
575
576static UInt get_instr_index(UInt mipsins)
577{
578 return (0x03FFFFFF & mipsins);
579}
580
581static UInt get_rd(UInt mipsins)
582{
583 return (0x0000F800 & mipsins) >> 11;
584}
585
586static UInt get_sa(UInt mipsins)
587{
588 return (0x000007C0 & mipsins) >> 6;
589}
590
591static UInt get_function(UInt mipsins)
592{
593 return (0x0000003F & mipsins);
594}
595
596static UInt get_ft(UInt mipsins)
597{
598 return (0x001F0000 & mipsins) >> 16;
599}
600
601static UInt get_fs(UInt mipsins)
602{
603 return (0x0000F800 & mipsins) >> 11;
604}
605
606static UInt get_fd(UInt mipsins)
607{
608 return (0x000007C0 & mipsins) >> 6;
609}
610
611static UInt get_mov_cc(UInt mipsins)
612{
613 return (0x001C0000 & mipsins) >> 18;
614}
615
616static UInt get_bc1_cc(UInt mipsins)
617{
618 return (0x001C0000 & mipsins) >> 18;
619}
620
621static UInt get_fpc_cc(UInt mipsins)
622{
623 return (0x00000700 & mipsins) >> 8;
624}
625
626static UInt get_tf(UInt mipsins)
627{
628 return (0x00010000 & mipsins) >> 16;
629}
630
631static UInt get_nd(UInt mipsins)
632{
633 return (0x00020000 & mipsins) >> 17;
634}
635
636static UInt get_fmt(UInt mipsins)
637{
638 return (0x03E00000 & mipsins) >> 21;
639}
640
641static UInt get_FC(UInt mipsins)
642{
643 return (0x000000F0 & mipsins) >> 4;
644}
645
646static UInt get_cond(UInt mipsins)
647{
648 return (0x0000000F & mipsins);
649}
650
651/* for break & syscall */
652static UInt get_code(UInt mipsins)
653{
654 return (0xFFC0 & mipsins) >> 6;
655}
656
657static UInt get_lsb(UInt mipsins)
658{
659 return (0x7C0 & mipsins) >> 6;
660}
661
662static UInt get_msb(UInt mipsins)
663{
664 return (0x0000F800 & mipsins) >> 11;
665}
666
667static UInt get_rot(UInt mipsins)
668{
669 return (0x00200000 & mipsins) >> 21;
670}
671
672static UInt get_rotv(UInt mipsins)
673{
674 return (0x00000040 & mipsins) >> 6;
675}
676
677static UInt get_sel(UInt mipsins)
678{
679 return (0x00000007 & mipsins);
680}
681
dejanjc3fee0d2013-07-25 09:08:03 +0000682/* Get acc number for all MIPS32 DSP ASE(r2) instructions that use them,
683 except for MFHI and MFLO. */
684static UInt get_acNo(UInt mipsins)
685{
686 return (0x00001800 & mipsins) >> 11;
687}
688
689/* Get accumulator number for MIPS32 DSP ASEr2 MFHI and MFLO instructions. */
690static UInt get_acNo_mfhilo(UInt mipsins)
691{
692 return (0x00600000 & mipsins) >> 21;
693}
694
695/* Get mask field (helper function for wrdsp instruction). */
696static UInt get_wrdspMask(UInt mipsins)
697{
698 return (0x001ff800 & mipsins) >> 11;
699}
700
701/* Get mask field (helper function for rddsp instruction). */
702static UInt get_rddspMask(UInt mipsins)
703{
704 return (0x03ff0000 & mipsins) >> 16;
705}
706
707/* Get shift field (helper function for DSP ASE instructions). */
708static UInt get_shift(UInt mipsins)
709{
710 return (0x03f00000 & mipsins) >> 20;
711}
712
713/* Get immediate field for DSP ASE instructions. */
714static UInt get_dspImm(UInt mipsins)
715{
716 return (0x03ff0000 & mipsins) >> 16;
717}
718
florian8462d112014-09-24 15:18:09 +0000719static Bool branch_or_jump(const UChar * addr)
sewardj362cf842012-06-07 08:59:53 +0000720{
721 UInt fmt;
722 UInt cins = getUInt(addr);
723
724 UInt opcode = get_opcode(cins);
725 UInt rt = get_rt(cins);
726 UInt function = get_function(cins);
727
728 /* bgtz, blez, bne, beq, jal */
dejanjc3fee0d2013-07-25 09:08:03 +0000729 if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04
sewardj362cf842012-06-07 08:59:53 +0000730 || opcode == 0x03 || opcode == 0x02) {
731 return True;
732 }
733
734 /* bgez */
735 if (opcode == 0x01 && rt == 0x01) {
736 return True;
737 }
738
739 /* bgezal */
740 if (opcode == 0x01 && rt == 0x11) {
741 return True;
742 }
743
744 /* bltzal */
745 if (opcode == 0x01 && rt == 0x10) {
746 return True;
747 }
748
749 /* bltz */
750 if (opcode == 0x01 && rt == 0x00) {
751 return True;
752 }
753
754 /* jalr */
755 if (opcode == 0x00 && function == 0x09) {
756 return True;
757 }
758
759 /* jr */
760 if (opcode == 0x00 && function == 0x08) {
761 return True;
762 }
763
764 if (opcode == 0x11) {
765 /*bc1f & bc1t */
766 fmt = get_fmt(cins);
767 if (fmt == 0x08) {
768 return True;
769 }
770 }
771
dejanjc3fee0d2013-07-25 09:08:03 +0000772 /* bposge32 */
773 if (opcode == 0x01 && rt == 0x1c) {
774 return True;
775 }
776
petarja90baf72014-09-03 14:39:56 +0000777 /* Cavium Specific instructions. */
petarj166d6452014-11-26 23:47:08 +0000778 if (opcode == 0x32 || opcode == 0x3A || opcode == 0x36 || opcode == 0x3E) {
779 /* BBIT0, BBIT1, BBIT032, BBIT132 */
petarja90baf72014-09-03 14:39:56 +0000780 return True;
781 }
782
sewardj362cf842012-06-07 08:59:53 +0000783 return False;
784}
785
florian8462d112014-09-24 15:18:09 +0000786static Bool is_Branch_or_Jump_and_Link(const UChar * addr)
sewardj362cf842012-06-07 08:59:53 +0000787{
788 UInt cins = getUInt(addr);
789
790 UInt opcode = get_opcode(cins);
791 UInt rt = get_rt(cins);
792 UInt function = get_function(cins);
793
794 /* jal */
795 if (opcode == 0x02) {
796 return True;
797 }
798
799 /* bgezal */
800 if (opcode == 0x01 && rt == 0x11) {
801 return True;
802 }
803
804 /* bltzal */
805 if (opcode == 0x01 && rt == 0x10) {
806 return True;
807 }
808
809 /* jalr */
810 if (opcode == 0x00 && function == 0x09) {
811 return True;
812 }
813
814 return False;
815}
816
florian8462d112014-09-24 15:18:09 +0000817static Bool branch_or_link_likely(const UChar * addr)
sewardj362cf842012-06-07 08:59:53 +0000818{
819 UInt cins = getUInt(addr);
820 UInt opcode = get_opcode(cins);
821 UInt rt = get_rt(cins);
822
823 /* bgtzl, blezl, bnel, beql */
824 if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14)
825 return True;
826
827 /* bgezl */
828 if (opcode == 0x01 && rt == 0x03)
829 return True;
830
831 /* bgezall */
832 if (opcode == 0x01 && rt == 0x13)
833 return True;
834
835 /* bltzall */
836 if (opcode == 0x01 && rt == 0x12)
837 return True;
838
839 /* bltzl */
840 if (opcode == 0x01 && rt == 0x02)
841 return True;
842
843 return False;
844}
845
846/*------------------------------------------------------------*/
847/*--- Helper bits and pieces for creating IR fragments. ---*/
848/*------------------------------------------------------------*/
849
850static IRExpr *mkU8(UInt i)
851{
852 vassert(i < 256);
853 return IRExpr_Const(IRConst_U8((UChar) i));
854}
855
dejanjc3fee0d2013-07-25 09:08:03 +0000856/* Create an expression node for a 16-bit integer constant. */
857static IRExpr *mkU16(UInt i)
858{
859 return IRExpr_Const(IRConst_U16(i));
860}
861
862/* Create an expression node for a 32-bit integer constant. */
sewardj362cf842012-06-07 08:59:53 +0000863static IRExpr *mkU32(UInt i)
864{
865 return IRExpr_Const(IRConst_U32(i));
866}
867
dejanjc3fee0d2013-07-25 09:08:03 +0000868/* Create an expression node for a 64-bit integer constant. */
sewardj362cf842012-06-07 08:59:53 +0000869static IRExpr *mkU64(ULong i)
870{
871 return IRExpr_Const(IRConst_U64(i));
872}
873
874static IRExpr *mkexpr(IRTemp tmp)
875{
876 return IRExpr_RdTmp(tmp);
877}
878
879static IRExpr *unop(IROp op, IRExpr * a)
880{
881 return IRExpr_Unop(op, a);
882}
883
884static IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2)
885{
886 return IRExpr_Binop(op, a1, a2);
887}
888
889static IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3)
890{
891 return IRExpr_Triop(op, a1, a2, a3);
892}
893
petarjb92a9542013-02-27 22:57:17 +0000894static IRExpr *qop ( IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3,
895 IRExpr * a4 )
896{
897 return IRExpr_Qop(op, a1, a2, a3, a4);
898}
899
sewardj362cf842012-06-07 08:59:53 +0000900static IRExpr *load(IRType ty, IRExpr * addr)
901{
902 IRExpr *load1 = NULL;
903#if defined (_MIPSEL)
904 load1 = IRExpr_Load(Iend_LE, ty, addr);
905#elif defined (_MIPSEB)
906 load1 = IRExpr_Load(Iend_BE, ty, addr);
907#endif
908 return load1;
909}
910
911/* Add a statement to the list held by "irsb". */
912static void stmt(IRStmt * st)
913{
914 addStmtToIRSB(irsb, st);
915}
916
917static void assign(IRTemp dst, IRExpr * e)
918{
919 stmt(IRStmt_WrTmp(dst, e));
920}
921
922static void store(IRExpr * addr, IRExpr * data)
923{
924#if defined (_MIPSEL)
925 stmt(IRStmt_Store(Iend_LE, addr, data));
926#elif defined (_MIPSEB)
927 stmt(IRStmt_Store(Iend_BE, addr, data));
928#endif
929}
930
931/* Generate a new temporary of the given type. */
932static IRTemp newTemp(IRType ty)
933{
934 vassert(isPlausibleIRType(ty));
935 return newIRTemp(irsb->tyenv, ty);
936}
937
938/* Generate an expression for SRC rotated right by ROT. */
939static IRExpr *genROR32(IRExpr * src, Int rot)
940{
941 vassert(rot >= 0 && rot < 32);
942 if (rot == 0)
943 return src;
944 return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)),
945 binop(Iop_Shr32, src, mkU8(rot)));
946}
947
948static IRExpr *genRORV32(IRExpr * src, IRExpr * rs)
949{
950 IRTemp t0 = newTemp(Ity_I8);
951 IRTemp t1 = newTemp(Ity_I8);
952
953 assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F))));
954 assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0)));
955 return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)),
956 binop(Iop_Shr32, src, mkexpr(t0)));
957}
958
dejanjc3fee0d2013-07-25 09:08:03 +0000959static UShort extend_s_10to16(UInt x)
960{
961 return (UShort) ((((Int) x) << 22) >> 22);
962}
963
petarj5cc3b452013-09-18 02:17:43 +0000964static ULong extend_s_10to32(UInt x)
965{
966 return (ULong)((((Long) x) << 22) >> 22);
967}
968
969static ULong extend_s_10to64(UInt x)
970{
971 return (ULong)((((Long) x) << 54) >> 54);
972}
973
sewardj362cf842012-06-07 08:59:53 +0000974static UInt extend_s_16to32(UInt x)
975{
976 return (UInt) ((((Int) x) << 16) >> 16);
977}
978
979static UInt extend_s_18to32(UInt x)
980{
981 return (UInt) ((((Int) x) << 14) >> 14);
982}
983
petarjb92a9542013-02-27 22:57:17 +0000984static ULong extend_s_16to64 ( UInt x )
985{
986 return (ULong) ((((Long) x) << 48) >> 48);
987}
988
989static ULong extend_s_18to64 ( UInt x )
990{
991 return (ULong) ((((Long) x) << 46) >> 46);
992}
993
994static ULong extend_s_32to64 ( UInt x )
995{
996 return (ULong) ((((Long) x) << 32) >> 32);
997}
998
999static void jmp_lit32 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr32 d32 )
sewardj362cf842012-06-07 08:59:53 +00001000{
1001 vassert(dres->whatNext == Dis_Continue);
1002 vassert(dres->len == 0);
1003 vassert(dres->continueAt == 0);
1004 vassert(dres->jk_StopHere == Ijk_INVALID);
1005 dres->whatNext = Dis_StopHere;
1006 dres->jk_StopHere = kind;
1007 stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) );
1008}
1009
petarjb92a9542013-02-27 22:57:17 +00001010static void jmp_lit64 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr64 d64 )
1011{
1012 vassert(dres->whatNext == Dis_Continue);
1013 vassert(dres->len == 0);
1014 vassert(dres->continueAt == 0);
1015 vassert(dres->jk_StopHere == Ijk_INVALID);
1016 dres->whatNext = Dis_StopHere;
1017 dres->jk_StopHere = kind;
1018 stmt(IRStmt_Put(OFFB_PC, mkU64(d64)));
1019}
1020
dejanjc3fee0d2013-07-25 09:08:03 +00001021/* Get value from accumulator (helper function for MIPS32 DSP ASE instructions).
1022 This function should be called before any other operation if widening
1023 multiplications are used. */
1024static IRExpr *getAcc(UInt acNo)
1025{
1026 vassert(!mode64);
1027 vassert(acNo <= 3);
1028 return IRExpr_Get(accumulatorGuestRegOffset(acNo), Ity_I64);
1029}
1030
1031/* Get value from DSPControl register (helper function for MIPS32 DSP ASE
1032 instructions). */
1033static IRExpr *getDSPControl(void)
1034{
1035 vassert(!mode64);
1036 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_DSPControl), Ity_I32);
1037}
1038
1039/* Put value to DSPControl register. Expression e is written to DSPControl as
1040 is. If only certain bits of DSPControl need to be changed, it should be done
1041 before calling putDSPControl(). It could be done by reading DSPControl and
1042 ORing it with appropriate mask. */
1043static void putDSPControl(IRExpr * e)
1044{
1045 vassert(!mode64);
1046 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_DSPControl), e));
1047}
1048
sewardj362cf842012-06-07 08:59:53 +00001049/* Fetch a byte from the guest insn stream. */
1050static UChar getIByte(Int delta)
1051{
1052 return guest_code[delta];
1053}
1054
1055static IRExpr *getIReg(UInt iregNo)
1056{
petarj191c6eb2012-06-07 16:52:41 +00001057 if (0 == iregNo) {
1058 return mode64 ? mkU64(0x0) : mkU32(0x0);
1059 } else {
1060 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1061 vassert(iregNo < 32);
1062 return IRExpr_Get(integerGuestRegOffset(iregNo), ty);
1063 }
sewardj362cf842012-06-07 08:59:53 +00001064}
1065
1066static IRExpr *getHI(void)
1067{
petarjb92a9542013-02-27 22:57:17 +00001068 if (mode64)
1069 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_HI), Ity_I64);
1070 else
1071 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32);
sewardj362cf842012-06-07 08:59:53 +00001072}
1073
1074static IRExpr *getLO(void)
1075{
petarjb92a9542013-02-27 22:57:17 +00001076 if (mode64)
1077 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LO), Ity_I64);
1078 else
1079 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32);
sewardj362cf842012-06-07 08:59:53 +00001080}
1081
1082static IRExpr *getFCSR(void)
1083{
petarjb92a9542013-02-27 22:57:17 +00001084 if (mode64)
1085 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_FCSR), Ity_I32);
1086 else
1087 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32);
sewardj362cf842012-06-07 08:59:53 +00001088}
1089
petarjccd78cd2013-05-31 15:09:56 +00001090/* Get byte from register reg, byte pos from 0 to 3 (or 7 for MIPS64) . */
1091static IRExpr *getByteFromReg(UInt reg, UInt byte_pos)
1092{
1093 UInt pos = byte_pos * 8;
1094 if (mode64)
1095 return unop(Iop_64to8, binop(Iop_And64,
1096 binop(Iop_Shr64, getIReg(reg), mkU8(pos)),
1097 mkU64(0xFF)));
1098 else
1099 return unop(Iop_32to8, binop(Iop_And32,
1100 binop(Iop_Shr32, getIReg(reg), mkU8(pos)),
1101 mkU32(0xFF)));
1102}
1103
sewardj362cf842012-06-07 08:59:53 +00001104static void putFCSR(IRExpr * e)
1105{
petarjb92a9542013-02-27 22:57:17 +00001106 if (mode64)
1107 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_FCSR), e));
1108 else
1109 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
sewardj362cf842012-06-07 08:59:53 +00001110}
1111
dejanja445f1b2013-10-22 08:52:46 +00001112/* fs - fpu source register number.
1113 inst - fpu instruction that needs to be executed.
dejanj41833222013-11-14 15:44:42 +00001114 sz32 - size of source register.
1115 opN - number of operads:
1116 1 - unary operation.
1117 2 - binary operation. */
1118static void calculateFCSR(UInt fs, UInt ft, UInt inst, Bool sz32, UInt opN)
dejanj8007ea62013-09-18 10:06:13 +00001119{
1120 IRDirty *d;
1121 IRTemp fcsr = newTemp(Ity_I32);
dejanj0e006f22014-02-19 11:56:29 +00001122 /* IRExpr_BBPTR() => Need to pass pointer to guest state to helper. */
1123 if (fp_mode64)
1124 d = unsafeIRDirty_1_N(fcsr, 0,
1125 "mips_dirtyhelper_calculate_FCSR_fp64",
1126 &mips_dirtyhelper_calculate_FCSR_fp64,
1127 mkIRExprVec_4(IRExpr_BBPTR(),
1128 mkU32(fs),
1129 mkU32(ft),
1130 mkU32(inst)));
1131 else
1132 d = unsafeIRDirty_1_N(fcsr, 0,
1133 "mips_dirtyhelper_calculate_FCSR_fp32",
1134 &mips_dirtyhelper_calculate_FCSR_fp32,
1135 mkIRExprVec_4(IRExpr_BBPTR(),
1136 mkU32(fs),
1137 mkU32(ft),
1138 mkU32(inst)));
dejanj8007ea62013-09-18 10:06:13 +00001139
dejanj41833222013-11-14 15:44:42 +00001140 if (opN == 1) { /* Unary operation. */
1141 /* Declare we're reading guest state. */
dejanj0e006f22014-02-19 11:56:29 +00001142 if (sz32 || fp_mode64)
dejanj41833222013-11-14 15:44:42 +00001143 d->nFxState = 2;
dejanj0e006f22014-02-19 11:56:29 +00001144 else
1145 d->nFxState = 3;
dejanj41833222013-11-14 15:44:42 +00001146 vex_bzero(&d->fxState, sizeof(d->fxState));
dejanj8007ea62013-09-18 10:06:13 +00001147
dejanj41833222013-11-14 15:44:42 +00001148 d->fxState[0].fx = Ifx_Read; /* read */
dejanjb176a6f2014-03-03 14:13:37 +00001149 if (mode64)
1150 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
1151 else
1152 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
dejanj8007ea62013-09-18 10:06:13 +00001153 d->fxState[0].size = sizeof(UInt);
dejanj8007ea62013-09-18 10:06:13 +00001154 d->fxState[1].fx = Ifx_Read; /* read */
dejanj41833222013-11-14 15:44:42 +00001155 d->fxState[1].offset = floatGuestRegOffset(fs);
dejanj0e006f22014-02-19 11:56:29 +00001156 d->fxState[1].size = sizeof(ULong);
dejanj41833222013-11-14 15:44:42 +00001157
dejanj0e006f22014-02-19 11:56:29 +00001158 if (!(sz32 || fp_mode64)) {
dejanj41833222013-11-14 15:44:42 +00001159 d->fxState[2].fx = Ifx_Read; /* read */
1160 d->fxState[2].offset = floatGuestRegOffset(fs+1);
dejanj0e006f22014-02-19 11:56:29 +00001161 d->fxState[2].size = sizeof(ULong);
dejanj41833222013-11-14 15:44:42 +00001162 }
1163 } else if (opN == 2) { /* Binary operation. */
1164 /* Declare we're reading guest state. */
dejanj0e006f22014-02-19 11:56:29 +00001165 if (sz32 || fp_mode64)
dejanj41833222013-11-14 15:44:42 +00001166 d->nFxState = 3;
dejanj0e006f22014-02-19 11:56:29 +00001167 else
1168 d->nFxState = 5;
dejanj41833222013-11-14 15:44:42 +00001169 vex_bzero(&d->fxState, sizeof(d->fxState));
1170
1171 d->fxState[0].fx = Ifx_Read; /* read */
dejanjb176a6f2014-03-03 14:13:37 +00001172 if (mode64)
1173 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
1174 else
1175 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
dejanj41833222013-11-14 15:44:42 +00001176 d->fxState[0].size = sizeof(UInt);
1177 d->fxState[1].fx = Ifx_Read; /* read */
1178 d->fxState[1].offset = floatGuestRegOffset(fs);
dejanj0e006f22014-02-19 11:56:29 +00001179 d->fxState[1].size = sizeof(ULong);
dejanj41833222013-11-14 15:44:42 +00001180 d->fxState[2].fx = Ifx_Read; /* read */
1181 d->fxState[2].offset = floatGuestRegOffset(ft);
dejanj0e006f22014-02-19 11:56:29 +00001182 d->fxState[2].size = sizeof(ULong);
1183
1184 if (!(sz32 || fp_mode64)) {
dejanj41833222013-11-14 15:44:42 +00001185 d->fxState[3].fx = Ifx_Read; /* read */
1186 d->fxState[3].offset = floatGuestRegOffset(fs+1);
dejanj0e006f22014-02-19 11:56:29 +00001187 d->fxState[3].size = sizeof(ULong);
dejanj41833222013-11-14 15:44:42 +00001188 d->fxState[4].fx = Ifx_Read; /* read */
1189 d->fxState[4].offset = floatGuestRegOffset(ft+1);
dejanj0e006f22014-02-19 11:56:29 +00001190 d->fxState[4].size = sizeof(ULong);
dejanj41833222013-11-14 15:44:42 +00001191 }
dejanj8007ea62013-09-18 10:06:13 +00001192 }
1193
1194 stmt(IRStmt_Dirty(d));
1195
1196 putFCSR(mkexpr(fcsr));
1197}
1198
sewardj362cf842012-06-07 08:59:53 +00001199static IRExpr *getULR(void)
1200{
petarjb92a9542013-02-27 22:57:17 +00001201 if (mode64)
1202 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_ULR), Ity_I64);
1203 else
1204 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32);
sewardj362cf842012-06-07 08:59:53 +00001205}
1206
1207static void putIReg(UInt archreg, IRExpr * e)
1208{
1209 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1210 vassert(archreg < 32);
1211 vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
1212 if (archreg != 0)
1213 stmt(IRStmt_Put(integerGuestRegOffset(archreg), e));
1214}
1215
dejanj0e006f22014-02-19 11:56:29 +00001216static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src)
1217{
1218 vassert(ty == Ity_I32 || ty == Ity_I64);
1219 return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
1220}
1221
sewardj362cf842012-06-07 08:59:53 +00001222static void putLO(IRExpr * e)
1223{
dejanjc3fee0d2013-07-25 09:08:03 +00001224 if (mode64) {
petarjb92a9542013-02-27 22:57:17 +00001225 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LO), e));
dejanjc3fee0d2013-07-25 09:08:03 +00001226 } else {
petarjb92a9542013-02-27 22:57:17 +00001227 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e));
dejanjc3fee0d2013-07-25 09:08:03 +00001228 /* Add value to lower 32 bits of ac0 to maintain compatibility between
1229 regular MIPS32 instruction set and MIPS DSP ASE. Keep higher 32bits
1230 unchanged. */
1231 IRTemp t_lo = newTemp(Ity_I32);
1232 IRTemp t_hi = newTemp(Ity_I32);
1233 assign(t_lo, e);
1234 assign(t_hi, unop(Iop_64HIto32, getAcc(0)));
1235 stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
1236 binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
1237 }
sewardj362cf842012-06-07 08:59:53 +00001238}
1239
1240static void putHI(IRExpr * e)
1241{
dejanjc3fee0d2013-07-25 09:08:03 +00001242 if (mode64) {
petarjb92a9542013-02-27 22:57:17 +00001243 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_HI), e));
dejanjc3fee0d2013-07-25 09:08:03 +00001244 } else {
petarjb92a9542013-02-27 22:57:17 +00001245 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e));
dejanjc3fee0d2013-07-25 09:08:03 +00001246 /* Add value to higher 32 bits of ac0 to maintain compatibility between
1247 regular MIPS32 instruction set and MIPS DSP ASE. Keep lower 32bits
1248 unchanged. */
1249 IRTemp t_lo = newTemp(Ity_I32);
1250 IRTemp t_hi = newTemp(Ity_I32);
1251 assign(t_hi, e);
1252 assign(t_lo, unop(Iop_64to32, getAcc(0)));
1253 stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
1254 binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
1255 }
1256}
1257
1258/* Put value to accumulator(helper function for MIPS32 DSP ASE instructions). */
1259static void putAcc(UInt acNo, IRExpr * e)
1260{
1261 vassert(!mode64);
1262 vassert(acNo <= 3);
1263 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64);
1264 stmt(IRStmt_Put(accumulatorGuestRegOffset(acNo), e));
1265/* If acNo = 0, split value to HI and LO regs in order to maintain compatibility
1266 between MIPS32 and MIPS DSP ASE insn sets. */
1267 if (0 == acNo) {
1268 putLO(unop(Iop_64to32, e));
1269 putHI(unop(Iop_64HIto32, e));
1270 }
petarjb92a9542013-02-27 22:57:17 +00001271}
1272
1273static IRExpr *mkNarrowTo8 ( IRType ty, IRExpr * src )
1274{
1275 vassert(ty == Ity_I32 || ty == Ity_I64);
1276 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
sewardj362cf842012-06-07 08:59:53 +00001277}
1278
1279static void putPC(IRExpr * e)
1280{
1281 stmt(IRStmt_Put(OFFB_PC, e));
1282}
1283
1284static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined)
1285{
1286 vassert(ty == Ity_I32 || ty == Ity_I64);
1287 if (ty == Ity_I32)
1288 return src;
1289 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
1290}
1291
1292/* Narrow 8/16/32 bit int expr to 8/16/32. Clearly only some
1293 of these combinations make sense. */
1294static IRExpr *narrowTo(IRType dst_ty, IRExpr * e)
1295{
1296 IRType src_ty = typeOfIRExpr(irsb->tyenv, e);
1297 if (src_ty == dst_ty)
1298 return e;
1299 if (src_ty == Ity_I32 && dst_ty == Ity_I16)
1300 return unop(Iop_32to16, e);
1301 if (src_ty == Ity_I32 && dst_ty == Ity_I8)
1302 return unop(Iop_32to8, e);
1303 if (src_ty == Ity_I64 && dst_ty == Ity_I8) {
1304 vassert(mode64);
1305 return unop(Iop_64to8, e);
1306 }
1307 if (src_ty == Ity_I64 && dst_ty == Ity_I16) {
1308 vassert(mode64);
1309 return unop(Iop_64to16, e);
1310 }
sewardj362cf842012-06-07 08:59:53 +00001311 vpanic("narrowTo(mips)");
1312 return 0;
1313}
1314
sewardj362cf842012-06-07 08:59:53 +00001315static IRExpr *getLoFromF64(IRType ty, IRExpr * src)
1316{
1317 vassert(ty == Ity_F32 || ty == Ity_F64);
1318 if (ty == Ity_F64) {
1319 IRTemp t0, t1;
1320 t0 = newTemp(Ity_I64);
1321 t1 = newTemp(Ity_I32);
1322 assign(t0, unop(Iop_ReinterpF64asI64, src));
1323 assign(t1, unop(Iop_64to32, mkexpr(t0)));
1324 return unop(Iop_ReinterpI32asF32, mkexpr(t1));
1325 } else
1326 return src;
1327}
1328
1329static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src)
1330{
1331 vassert(ty == Ity_F32 || ty == Ity_F64);
petarjb92a9542013-02-27 22:57:17 +00001332 if (ty == Ity_F64) {
1333 IRTemp t0 = newTemp(Ity_I32);
1334 IRTemp t1 = newTemp(Ity_I64);
1335 assign(t0, unop(Iop_ReinterpF32asI32, src));
1336 assign(t1, binop(Iop_32HLto64, mkU32(0x0), mkexpr(t0)));
1337 return unop(Iop_ReinterpI64asF64, mkexpr(t1));
1338 } else
1339 return src;
sewardj362cf842012-06-07 08:59:53 +00001340}
1341
1342static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm)
1343{
1344 ULong branch_offset;
1345 IRTemp t0;
1346
1347 /* PC = PC + (SignExtend(signed_immed_24) << 2)
dejanjc3fee0d2013-07-25 09:08:03 +00001348 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
sewardj362cf842012-06-07 08:59:53 +00001349 is added to the address of the instruction following
dejanjc3fee0d2013-07-25 09:08:03 +00001350 the branch (not the branch itself), in the branch delay slot, to form
sewardj362cf842012-06-07 08:59:53 +00001351 a PC-relative effective target address. */
petarjb92a9542013-02-27 22:57:17 +00001352 if (mode64)
1353 branch_offset = extend_s_18to64(imm << 2);
1354 else
1355 branch_offset = extend_s_18to32(imm << 2);
sewardj362cf842012-06-07 08:59:53 +00001356
1357 t0 = newTemp(Ity_I1);
1358 assign(t0, guard);
1359
petarjb92a9542013-02-27 22:57:17 +00001360 if (mode64)
1361 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
1362 IRConst_U64(guest_PC_curr_instr + 8), OFFB_PC));
1363 else
dejanjc3fee0d2013-07-25 09:08:03 +00001364 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
petarjb92a9542013-02-27 22:57:17 +00001365 IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC));
sewardj362cf842012-06-07 08:59:53 +00001366
1367 irsb->jumpkind = Ijk_Boring;
1368
petarjb92a9542013-02-27 22:57:17 +00001369 if (mode64)
1370 return mkU64(guest_PC_curr_instr + 4 + branch_offset);
1371 else
1372 return mkU32(guest_PC_curr_instr + 4 + branch_offset);
sewardj362cf842012-06-07 08:59:53 +00001373}
1374
1375static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set)
1376{
1377 ULong branch_offset;
1378 IRTemp t0;
1379
petarjb92a9542013-02-27 22:57:17 +00001380 if (link) { /* LR (GPR31) = addr of the 2nd instr after branch instr */
1381 if (mode64)
1382 putIReg(31, mkU64(guest_PC_curr_instr + 8));
1383 else
1384 putIReg(31, mkU32(guest_PC_curr_instr + 8));
sewardj362cf842012-06-07 08:59:53 +00001385 }
1386
1387 /* PC = PC + (SignExtend(signed_immed_24) << 2)
dejanjc3fee0d2013-07-25 09:08:03 +00001388 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
sewardj362cf842012-06-07 08:59:53 +00001389 is added to the address of the instruction following
dejanjc3fee0d2013-07-25 09:08:03 +00001390 the branch (not the branch itself), in the branch delay slot, to form
sewardj362cf842012-06-07 08:59:53 +00001391 a PC-relative effective target address. */
1392
petarjb92a9542013-02-27 22:57:17 +00001393 if (mode64)
1394 branch_offset = extend_s_18to64(imm << 2);
1395 else
1396 branch_offset = extend_s_18to32(imm << 2);
sewardj362cf842012-06-07 08:59:53 +00001397
1398 t0 = newTemp(Ity_I1);
1399 assign(t0, guard);
petarjb92a9542013-02-27 22:57:17 +00001400 if (mode64)
1401 *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
1402 IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
1403 OFFB_PC);
1404 else
1405 *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
1406 IRConst_U32(guest_PC_curr_instr + 4 +
1407 (UInt) branch_offset), OFFB_PC);
sewardj362cf842012-06-07 08:59:53 +00001408}
1409
dejanj0e006f22014-02-19 11:56:29 +00001410static IRExpr *getFReg(UInt fregNo)
sewardj362cf842012-06-07 08:59:53 +00001411{
dejanj0e006f22014-02-19 11:56:29 +00001412 vassert(fregNo < 32);
1413 IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
1414 return IRExpr_Get(floatGuestRegOffset(fregNo), ty);
sewardj362cf842012-06-07 08:59:53 +00001415}
1416
1417static IRExpr *getDReg(UInt dregNo)
1418{
dejanj0e006f22014-02-19 11:56:29 +00001419 vassert(dregNo < 32);
1420 if (fp_mode64) {
1421 return IRExpr_Get(floatGuestRegOffset(dregNo), Ity_F64);
petarjb92a9542013-02-27 22:57:17 +00001422 } else {
dejanj0e006f22014-02-19 11:56:29 +00001423 /* Read a floating point register pair and combine their contents into a
1424 64-bit value */
petarjb92a9542013-02-27 22:57:17 +00001425 IRTemp t0 = newTemp(Ity_F32);
1426 IRTemp t1 = newTemp(Ity_F32);
1427 IRTemp t2 = newTemp(Ity_F64);
1428 IRTemp t3 = newTemp(Ity_I32);
1429 IRTemp t4 = newTemp(Ity_I32);
1430 IRTemp t5 = newTemp(Ity_I64);
sewardj362cf842012-06-07 08:59:53 +00001431
petarjb92a9542013-02-27 22:57:17 +00001432 assign(t0, getFReg(dregNo));
1433 assign(t1, getFReg(dregNo + 1));
sewardj362cf842012-06-07 08:59:53 +00001434
petarjb92a9542013-02-27 22:57:17 +00001435 assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
1436 assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
1437 assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3)));
1438 assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5)));
sewardj362cf842012-06-07 08:59:53 +00001439
petarjb92a9542013-02-27 22:57:17 +00001440 return mkexpr(t2);
1441 }
sewardj362cf842012-06-07 08:59:53 +00001442}
1443
1444static void putFReg(UInt dregNo, IRExpr * e)
1445{
1446 vassert(dregNo < 32);
dejanj0e006f22014-02-19 11:56:29 +00001447 IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
sewardj362cf842012-06-07 08:59:53 +00001448 vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
1449 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
1450}
1451
1452static void putDReg(UInt dregNo, IRExpr * e)
1453{
dejanj0e006f22014-02-19 11:56:29 +00001454 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +00001455 vassert(dregNo < 32);
1456 IRType ty = Ity_F64;
1457 vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
1458 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
1459 } else {
1460 vassert(dregNo < 32);
1461 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1462 IRTemp t1 = newTemp(Ity_F64);
1463 IRTemp t4 = newTemp(Ity_I32);
1464 IRTemp t5 = newTemp(Ity_I32);
1465 IRTemp t6 = newTemp(Ity_I64);
1466 assign(t1, e);
1467 assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1)));
1468 assign(t4, unop(Iop_64HIto32, mkexpr(t6))); /* hi */
1469 assign(t5, unop(Iop_64to32, mkexpr(t6))); /* lo */
petarjb92a9542013-02-27 22:57:17 +00001470 putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t5)));
1471 putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
petarjb92a9542013-02-27 22:57:17 +00001472 }
sewardj362cf842012-06-07 08:59:53 +00001473}
1474
1475static void setFPUCondCode(IRExpr * e, UInt cc)
1476{
1477 if (cc == 0) {
sewardj362cf842012-06-07 08:59:53 +00001478 putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF)));
1479 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23))));
1480 } else {
dejanjc3fee0d2013-07-25 09:08:03 +00001481 putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32,
sewardj362cf842012-06-07 08:59:53 +00001482 binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc)))));
1483 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc))));
1484 }
1485}
1486
petarjb92a9542013-02-27 22:57:17 +00001487static IRExpr* get_IR_roundingmode ( void )
sewardj362cf842012-06-07 08:59:53 +00001488{
dejanjc3fee0d2013-07-25 09:08:03 +00001489/*
sewardj362cf842012-06-07 08:59:53 +00001490 rounding mode | MIPS | IR
1491 ------------------------
1492 to nearest | 00 | 00
1493 to zero | 01 | 11
1494 to +infinity | 10 | 10
1495 to -infinity | 11 | 01
1496*/
1497 IRTemp rm_MIPS = newTemp(Ity_I32);
1498 /* Last two bits in FCSR are rounding mode. */
1499
petarjb92a9542013-02-27 22:57:17 +00001500 if (mode64)
1501 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
1502 guest_FCSR), Ity_I32), mkU32(3)));
1503 else
1504 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
1505 guest_FCSR), Ity_I32), mkU32(3)));
sewardj362cf842012-06-07 08:59:53 +00001506
petarjb92a9542013-02-27 22:57:17 +00001507 /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
sewardj362cf842012-06-07 08:59:53 +00001508
1509 return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
1510 binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
1511}
1512
petarjb92a9542013-02-27 22:57:17 +00001513/* sz, ULong -> IRExpr */
1514static IRExpr *mkSzImm ( IRType ty, ULong imm64 )
1515{
1516 vassert(ty == Ity_I32 || ty == Ity_I64);
1517 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt) imm64);
1518}
1519
1520static IRConst *mkSzConst ( IRType ty, ULong imm64 )
1521{
1522 vassert(ty == Ity_I32 || ty == Ity_I64);
1523 return (ty == Ity_I64 ? IRConst_U64(imm64) : IRConst_U32((UInt) imm64));
1524}
1525
1526/* Make sure we get valid 32 and 64bit addresses */
1527static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
1528{
1529 vassert(ty == Ity_I32 || ty == Ity_I64);
dejanjc3fee0d2013-07-25 09:08:03 +00001530 return (ty == Ity_I64 ? (Addr64) addr :
petarjb92a9542013-02-27 22:57:17 +00001531 (Addr64) extend_s_32to64(toUInt(addr)));
1532}
1533
1534/* Shift and Rotate instructions for MIPS64 */
1535static Bool dis_instr_shrt ( UInt theInstr )
1536{
1537 UInt opc2 = get_function(theInstr);
1538 UChar regRs = get_rs(theInstr);
1539 UChar regRt = get_rt(theInstr);
1540 UChar regRd = get_rd(theInstr);
1541 UChar uImmsa = get_sa(theInstr);
1542 Long sImmsa = extend_s_16to64(uImmsa);
1543 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1544 IRTemp tmp = newTemp(ty);
1545 IRTemp tmpOr = newTemp(ty);
1546 IRTemp tmpRt = newTemp(ty);
1547 IRTemp tmpRs = newTemp(ty);
1548 IRTemp tmpRd = newTemp(ty);
1549
1550 assign(tmpRs, getIReg(regRs));
1551 assign(tmpRt, getIReg(regRt));
1552
1553 switch (opc2) {
1554 case 0x3A:
1555 if ((regRs & 0x01) == 0) {
1556 /* Doubleword Shift Right Logical - DSRL; MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +00001557 DIP("dsrl r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
petarjb92a9542013-02-27 22:57:17 +00001558 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
1559 putIReg(regRd, mkexpr(tmpRd));
1560 } else if ((regRs & 0x01) == 1) {
1561 /* Doubleword Rotate Right - DROTR; MIPS64r2 */
1562 vassert(mode64);
petarj1fb1e342013-04-27 02:18:11 +00001563 DIP("drotr r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
petarjb92a9542013-02-27 22:57:17 +00001564 IRTemp tmpL = newTemp(ty);
1565 IRTemp tmpR = newTemp(ty);
1566 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
1567 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(63 - uImmsa)));
1568 assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
1569 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
1570 putIReg(regRd, mkexpr(tmpRd));
1571 } else
1572 return False;
1573 break;
1574
1575 case 0x3E:
1576 if ((regRs & 0x01) == 0) {
1577 /* Doubleword Shift Right Logical Plus 32 - DSRL32; MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +00001578 DIP("dsrl32 r%u, r%u, %d", regRd, regRt, (Int)(sImmsa + 32));
petarjb92a9542013-02-27 22:57:17 +00001579 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
1580 putIReg(regRd, mkexpr(tmpRd));
1581 } else if ((regRs & 0x01) == 1) {
1582 /* Doubleword Rotate Right Plus 32 - DROTR32; MIPS64r2 */
petarj1fb1e342013-04-27 02:18:11 +00001583 DIP("drotr32 r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
petarjb92a9542013-02-27 22:57:17 +00001584 vassert(mode64);
1585 IRTemp tmpL = newTemp(ty);
1586 IRTemp tmpR = newTemp(ty);
1587 /* (tmpRt >> sa) | (tmpRt << (64 - sa)) */
1588 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
1589 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt),
1590 mkU8(63 - (uImmsa + 32))));
1591 assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
1592 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
1593 putIReg(regRd, mkexpr(tmpRd));
1594 } else
1595 return False;
1596 break;
1597
1598 case 0x16:
1599 if ((uImmsa & 0x01) == 0) {
1600 /* Doubleword Shift Right Logical Variable - DSRLV; MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +00001601 DIP("dsrlv r%u, r%u, r%u", regRd, regRt, regRs);
petarjb92a9542013-02-27 22:57:17 +00001602 IRTemp tmpRs8 = newTemp(Ity_I8);
1603 /* s = tmpRs[5..0] */
1604 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkU64(63)));
1605 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
1606 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
1607 putIReg(regRd, mkexpr(tmpRd));
1608 } else if ((uImmsa & 0x01) == 1) {
1609 /* Doubleword Rotate Right Variable - DROTRV; MIPS64r2 */
petarj1fb1e342013-04-27 02:18:11 +00001610 DIP("drotrv r%u, r%u, r%u", regRd, regRt, regRs);
petarjb92a9542013-02-27 22:57:17 +00001611 IRTemp tmpL = newTemp(ty);
1612 IRTemp tmpR = newTemp(ty);
1613 IRTemp tmpRs8 = newTemp(Ity_I8);
1614 IRTemp tmpLs8 = newTemp(Ity_I8);
1615 IRTemp tmp64 = newTemp(ty);
1616 /* s = tmpRs[5...0]
1617 m = 64 - s
1618 (tmpRt << s) | (tmpRt >> m) */
1619
1620 assign(tmp64, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
1621 assign(tmp, binop(Iop_Sub64, mkU64(63), mkexpr(tmp64)));
1622
1623 assign(tmpLs8, mkNarrowTo8(ty, mkexpr(tmp)));
1624 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp64)));
1625
1626 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
1627 assign(tmpL, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpLs8)));
1628 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpL), mkU8(1)));
1629 assign(tmpOr, binop(Iop_Or64, mkexpr(tmpRd), mkexpr(tmpR)));
1630
1631 putIReg(regRd, mkexpr(tmpOr));
1632 } else
1633 return False;
1634 break;
1635
1636 case 0x38: /* Doubleword Shift Left Logical - DSLL; MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +00001637 DIP("dsll r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
petarjb92a9542013-02-27 22:57:17 +00001638 vassert(mode64);
1639 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa)));
1640 putIReg(regRd, mkexpr(tmpRd));
1641 break;
1642
1643 case 0x3C: /* Doubleword Shift Left Logical Plus 32 - DSLL32; MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +00001644 DIP("dsll32 r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
petarjb92a9542013-02-27 22:57:17 +00001645 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
1646 putIReg(regRd, mkexpr(tmpRd));
1647 break;
1648
1649 case 0x14: { /* Doubleword Shift Left Logical Variable - DSLLV; MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +00001650 DIP("dsllv r%u, r%u, r%u", regRd, regRt, regRs);
petarjb92a9542013-02-27 22:57:17 +00001651 IRTemp tmpRs8 = newTemp(Ity_I8);
1652
1653 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
1654 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
1655 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpRs8)));
1656 putIReg(regRd, mkexpr(tmpRd));
1657 break;
1658 }
1659
1660 case 0x3B: /* Doubleword Shift Right Arithmetic - DSRA; MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +00001661 DIP("dsra r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
petarjb92a9542013-02-27 22:57:17 +00001662 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa)));
1663 putIReg(regRd, mkexpr(tmpRd));
1664 break;
1665
1666 case 0x3F: /* Doubleword Shift Right Arithmetic Plus 32 - DSRA32;
1667 MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +00001668 DIP("dsra32 r%u, r%u, %d", regRd, regRt, (Int)sImmsa);
petarjb92a9542013-02-27 22:57:17 +00001669 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
1670 putIReg(regRd, mkexpr(tmpRd));
1671 break;
1672
1673 case 0x17: { /* Doubleword Shift Right Arithmetic Variable - DSRAV;
1674 MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +00001675 DIP("dsrav r%u, r%u, r%u", regRd, regRt, regRs);
petarjb92a9542013-02-27 22:57:17 +00001676 IRTemp tmpRs8 = newTemp(Ity_I8);
1677 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
1678 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
1679 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkexpr(tmpRs8)));
1680 putIReg(regRd, mkexpr(tmpRd));
1681 break;
1682
1683 }
1684
1685 default:
1686 return False;
1687
1688 }
1689 return True;
1690}
1691
1692static IROp mkSzOp ( IRType ty, IROp op8 )
1693{
1694 Int adj;
1695 vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
1696 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8
1697 || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
1698 || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
1699 || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || op8 == Iop_Not8);
1700 adj = ty == Ity_I8 ? 0 : (ty == Ity_I16 ? 1 : (ty == Ity_I32 ? 2 : 3));
1701 return adj + op8;
1702}
1703
sewardj362cf842012-06-07 08:59:53 +00001704/*********************************************************/
1705/*--- Floating Point Compare ---*/
1706/*********************************************************/
petarj1fb1e342013-04-27 02:18:11 +00001707/* Function that returns a string that represent mips cond
1708 mnemonic for the input code. */
1709static const HChar* showCondCode(UInt code) {
1710 const HChar* ret;
1711 switch (code) {
dejanjf37c0862014-02-25 15:25:49 +00001712 case 0: ret = "f"; break;
1713 case 1: ret = "un"; break;
1714 case 2: ret = "eq"; break;
1715 case 3: ret = "ueq"; break;
1716 case 4: ret = "olt"; break;
1717 case 5: ret = "ult"; break;
1718 case 6: ret = "ole"; break;
1719 case 7: ret = "ule"; break;
1720 case 8: ret = "sf"; break;
1721 case 9: ret = "ngle"; break;
1722 case 10: ret = "seq"; break;
1723 case 11: ret = "ngl"; break;
1724 case 12: ret = "lt"; break;
1725 case 13: ret = "nge"; break;
1726 case 14: ret = "le"; break;
1727 case 15: ret = "ngt"; break;
petarj1fb1e342013-04-27 02:18:11 +00001728 default: vpanic("showCondCode"); break;
1729 }
1730 return ret;
1731}
1732
petarjb92a9542013-02-27 22:57:17 +00001733static Bool dis_instr_CCondFmt ( UInt cins )
sewardj362cf842012-06-07 08:59:53 +00001734{
petarjb92a9542013-02-27 22:57:17 +00001735 IRTemp t0, t1, t2, t3, tmp5, tmp6;
sewardj362cf842012-06-07 08:59:53 +00001736 IRTemp ccIR = newTemp(Ity_I32);
1737 IRTemp ccMIPS = newTemp(Ity_I32);
1738 UInt FC = get_FC(cins);
1739 UInt fmt = get_fmt(cins);
1740 UInt fs = get_fs(cins);
1741 UInt ft = get_ft(cins);
1742 UInt cond = get_cond(cins);
1743
petarjb92a9542013-02-27 22:57:17 +00001744 if (FC == 0x3) { /* C.cond.fmt */
sewardj362cf842012-06-07 08:59:53 +00001745 UInt fpc_cc = get_fpc_cc(cins);
1746 switch (fmt) {
petarjb92a9542013-02-27 22:57:17 +00001747 case 0x10: { /* C.cond.S */
dejanjf37c0862014-02-25 15:25:49 +00001748 DIP("c.%s.s %d, f%d, f%d", showCondCode(cond), fpc_cc, fs, ft);
dejanj0e006f22014-02-19 11:56:29 +00001749 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +00001750 t0 = newTemp(Ity_I32);
1751 t1 = newTemp(Ity_I32);
1752 t2 = newTemp(Ity_I32);
1753 t3 = newTemp(Ity_I32);
sewardj362cf842012-06-07 08:59:53 +00001754
petarjb92a9542013-02-27 22:57:17 +00001755 tmp5 = newTemp(Ity_F64);
1756 tmp6 = newTemp(Ity_F64);
sewardj362cf842012-06-07 08:59:53 +00001757
petarjb92a9542013-02-27 22:57:17 +00001758 assign(tmp5, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
1759 getFReg(fs))));
1760 assign(tmp6, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
1761 getFReg(ft))));
sewardj362cf842012-06-07 08:59:53 +00001762
petarjb92a9542013-02-27 22:57:17 +00001763 assign(ccIR, binop(Iop_CmpF64, mkexpr(tmp5), mkexpr(tmp6)));
dejanj0e006f22014-02-19 11:56:29 +00001764 putHI(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32,
1765 mkexpr(ccIR), True));
petarjb92a9542013-02-27 22:57:17 +00001766 /* Map compare result from IR to MIPS
1767 FP cmp result | MIPS | IR
1768 --------------------------
1769 UN | 0x1 | 0x45
1770 EQ | 0x2 | 0x40
1771 GT | 0x4 | 0x00
1772 LT | 0x8 | 0x01
1773 */
sewardj362cf842012-06-07 08:59:53 +00001774
petarjb92a9542013-02-27 22:57:17 +00001775 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
dejanjc3fee0d2013-07-25 09:08:03 +00001776 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
petarjb92a9542013-02-27 22:57:17 +00001777 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
1778 binop(Iop_Shr32, mkexpr(ccIR),mkU8(5))),mkU32(2)),
1779 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
dejanjc3fee0d2013-07-25 09:08:03 +00001780 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
petarjb92a9542013-02-27 22:57:17 +00001781 mkU32(1))))));
dejanj0e006f22014-02-19 11:56:29 +00001782 putLO(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32,
1783 mkexpr(ccMIPS), True));
petarjb92a9542013-02-27 22:57:17 +00001784
1785 /* UN */
1786 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
1787 /* EQ */
1788 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
1789 mkU8(0x1)), mkU32(0x1)));
1790 /* NGT */
1791 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
1792 mkexpr(ccMIPS), mkU8(0x2))),mkU32(0x1)));
1793 /* LT */
1794 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
1795 mkU8(0x3)), mkU32(0x1)));
1796 switch (cond) {
1797 case 0x0:
1798 setFPUCondCode(mkU32(0), fpc_cc);
1799 break;
1800 case 0x1:
petarjb92a9542013-02-27 22:57:17 +00001801 setFPUCondCode(mkexpr(t0), fpc_cc);
1802 break;
1803 case 0x2:
1804 setFPUCondCode(mkexpr(t1), fpc_cc);
1805 break;
1806 case 0x3:
1807 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
1808 fpc_cc);
1809 break;
1810 case 0x4:
1811 setFPUCondCode(mkexpr(t3), fpc_cc);
1812 break;
1813 case 0x5:
1814 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
1815 fpc_cc);
1816 break;
1817 case 0x6:
1818 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
1819 fpc_cc);
1820 break;
1821 case 0x7:
1822 setFPUCondCode(mkexpr(t2), fpc_cc);
1823 break;
1824 case 0x8:
1825 setFPUCondCode(mkU32(0), fpc_cc);
1826 break;
1827 case 0x9:
1828 setFPUCondCode(mkexpr(t0), fpc_cc);
1829 break;
1830 case 0xA:
1831 setFPUCondCode(mkexpr(t1), fpc_cc);
1832 break;
1833 case 0xB:
1834 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
1835 fpc_cc);
1836 break;
1837 case 0xC:
1838 setFPUCondCode(mkexpr(t3), fpc_cc);
1839 break;
1840 case 0xD:
1841 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
1842 fpc_cc);
1843 break;
1844 case 0xE:
1845 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
1846 fpc_cc);
1847 break;
1848 case 0xF:
1849 setFPUCondCode(mkexpr(t2), fpc_cc);
1850 break;
dejanjc3fee0d2013-07-25 09:08:03 +00001851
petarjb92a9542013-02-27 22:57:17 +00001852 default:
1853 return False;
1854 }
1855
1856 } else {
1857 t0 = newTemp(Ity_I32);
1858 t1 = newTemp(Ity_I32);
1859 t2 = newTemp(Ity_I32);
1860 t3 = newTemp(Ity_I32);
1861
1862 assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)),
1863 unop(Iop_F32toF64, getFReg(ft))));
1864 /* Map compare result from IR to MIPS
1865 FP cmp result | MIPS | IR
1866 --------------------------
1867 UN | 0x1 | 0x45
1868 EQ | 0x2 | 0x40
1869 GT | 0x4 | 0x00
1870 LT | 0x8 | 0x01
1871 */
1872
1873 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
dejanjc3fee0d2013-07-25 09:08:03 +00001874 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
petarjb92a9542013-02-27 22:57:17 +00001875 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
1876 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))),
1877 mkU32(2)), binop(Iop_And32,
1878 binop(Iop_Xor32, mkexpr(ccIR),
dejanjc3fee0d2013-07-25 09:08:03 +00001879 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
petarjb92a9542013-02-27 22:57:17 +00001880 mkU32(1))))));
1881 /* UN */
1882 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
1883 /* EQ */
1884 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
1885 mkU8(0x1)), mkU32(0x1)));
1886 /* NGT */
1887 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
1888 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
1889 /* LT */
1890 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
1891 mkU8(0x3)), mkU32(0x1)));
1892
1893 switch (cond) {
1894 case 0x0:
1895 setFPUCondCode(mkU32(0), fpc_cc);
1896 break;
1897 case 0x1:
petarjb92a9542013-02-27 22:57:17 +00001898 setFPUCondCode(mkexpr(t0), fpc_cc);
1899 break;
1900 case 0x2:
1901 setFPUCondCode(mkexpr(t1), fpc_cc);
1902 break;
1903 case 0x3:
1904 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
1905 fpc_cc);
1906 break;
1907 case 0x4:
1908 setFPUCondCode(mkexpr(t3), fpc_cc);
1909 break;
1910 case 0x5:
1911 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
1912 fpc_cc);
1913 break;
1914 case 0x6:
1915 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
1916 fpc_cc);
1917 break;
1918 case 0x7:
1919 setFPUCondCode(mkexpr(t2), fpc_cc);
1920 break;
1921 case 0x8:
1922 setFPUCondCode(mkU32(0), fpc_cc);
1923 break;
1924 case 0x9:
1925 setFPUCondCode(mkexpr(t0), fpc_cc);
1926 break;
1927 case 0xA:
1928 setFPUCondCode(mkexpr(t1), fpc_cc);
1929 break;
1930 case 0xB:
1931 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
1932 fpc_cc);
1933 break;
1934 case 0xC:
1935 setFPUCondCode(mkexpr(t3), fpc_cc);
1936 break;
1937 case 0xD:
1938 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
1939 fpc_cc);
1940 break;
1941 case 0xE:
1942 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
1943 fpc_cc);
1944 break;
1945 case 0xF:
1946 setFPUCondCode(mkexpr(t2), fpc_cc);
1947 break;
dejanjc3fee0d2013-07-25 09:08:03 +00001948
petarjb92a9542013-02-27 22:57:17 +00001949 default:
1950 return False;
1951 }
sewardj362cf842012-06-07 08:59:53 +00001952 }
1953 }
1954 break;
1955
petarjb92a9542013-02-27 22:57:17 +00001956 case 0x11: { /* C.cond.D */
dejanjf37c0862014-02-25 15:25:49 +00001957 DIP("c.%s.d %d, f%d, f%d", showCondCode(cond), fpc_cc, fs, ft);
sewardj362cf842012-06-07 08:59:53 +00001958 t0 = newTemp(Ity_I32);
1959 t1 = newTemp(Ity_I32);
1960 t2 = newTemp(Ity_I32);
1961 t3 = newTemp(Ity_I32);
1962 assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
petarjb92a9542013-02-27 22:57:17 +00001963 /* Map compare result from IR to MIPS
sewardj362cf842012-06-07 08:59:53 +00001964 FP cmp result | MIPS | IR
1965 --------------------------
1966 UN | 0x1 | 0x45
1967 EQ | 0x2 | 0x40
1968 GT | 0x4 | 0x00
1969 LT | 0x8 | 0x01
1970 */
1971
petarjb92a9542013-02-27 22:57:17 +00001972 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
sewardj362cf842012-06-07 08:59:53 +00001973 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
1974 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
1975 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
1976 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
1977 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
1978 mkU32(1))))));
dejanjc3fee0d2013-07-25 09:08:03 +00001979
petarjb92a9542013-02-27 22:57:17 +00001980 /* UN */
1981 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
1982 /* EQ */
sewardj362cf842012-06-07 08:59:53 +00001983 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
petarjb92a9542013-02-27 22:57:17 +00001984 mkU8(0x1)), mkU32(0x1)));
1985 /* NGT */
sewardj362cf842012-06-07 08:59:53 +00001986 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
petarjb92a9542013-02-27 22:57:17 +00001987 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
1988 /* LT */
sewardj362cf842012-06-07 08:59:53 +00001989 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
petarjb92a9542013-02-27 22:57:17 +00001990 mkU8(0x3)), mkU32(0x1)));
sewardj362cf842012-06-07 08:59:53 +00001991
1992 switch (cond) {
1993 case 0x0:
1994 setFPUCondCode(mkU32(0), fpc_cc);
1995 break;
1996 case 0x1:
sewardj362cf842012-06-07 08:59:53 +00001997 setFPUCondCode(mkexpr(t0), fpc_cc);
1998 break;
1999 case 0x2:
2000 setFPUCondCode(mkexpr(t1), fpc_cc);
2001 break;
2002 case 0x3:
2003 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2004 fpc_cc);
2005 break;
2006 case 0x4:
2007 setFPUCondCode(mkexpr(t3), fpc_cc);
2008 break;
2009 case 0x5:
2010 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2011 fpc_cc);
2012 break;
2013 case 0x6:
2014 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2015 fpc_cc);
2016 break;
2017 case 0x7:
2018 setFPUCondCode(mkexpr(t2), fpc_cc);
2019 break;
2020 case 0x8:
2021 setFPUCondCode(mkU32(0), fpc_cc);
2022 break;
2023 case 0x9:
2024 setFPUCondCode(mkexpr(t0), fpc_cc);
2025 break;
2026 case 0xA:
2027 setFPUCondCode(mkexpr(t1), fpc_cc);
2028 break;
2029 case 0xB:
2030 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2031 fpc_cc);
2032 break;
2033 case 0xC:
2034 setFPUCondCode(mkexpr(t3), fpc_cc);
2035 break;
2036 case 0xD:
2037 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2038 fpc_cc);
2039 break;
2040 case 0xE:
2041 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2042 fpc_cc);
2043 break;
2044 case 0xF:
2045 setFPUCondCode(mkexpr(t2), fpc_cc);
2046 break;
2047 default:
2048 return False;
2049 }
petarjb92a9542013-02-27 22:57:17 +00002050 }
2051 break;
sewardj362cf842012-06-07 08:59:53 +00002052
petarjb92a9542013-02-27 22:57:17 +00002053 default:
2054 return False;
sewardj362cf842012-06-07 08:59:53 +00002055 }
2056 } else {
2057 return False;
2058 }
2059
2060 return True;
2061}
2062
petarjb92a9542013-02-27 22:57:17 +00002063/*********************************************************/
2064/*--- Branch Instructions for mips64 ---*/
2065/*********************************************************/
2066static Bool dis_instr_branch ( UInt theInstr, DisResult * dres,
2067 Bool(*resteerOkFn) (void *, Addr64),
2068 void *callback_opaque, IRStmt ** set )
2069{
2070 UInt jmpKind = 0;
2071 UChar opc1 = get_opcode(theInstr);
2072 UChar regRs = get_rs(theInstr);
2073 UChar regRt = get_rt(theInstr);
2074 UInt offset = get_imm(theInstr);
2075 Long sOffset = extend_s_16to64(offset);
2076 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2077 IROp opSlt = mode64 ? Iop_CmpLT64S : Iop_CmpLT32S;
2078
2079 IRTemp tmp = newTemp(ty);
2080 IRTemp tmpRs = newTemp(ty);
2081 IRTemp tmpRt = newTemp(ty);
2082 IRTemp tmpLt = newTemp(ty);
2083 IRTemp tmpReg0 = newTemp(ty);
2084
2085 UChar regLnk = 31; /* reg 31 is link reg in MIPS */
2086 Addr64 addrTgt = 0;
2087 Addr64 cia = guest_PC_curr_instr;
2088
2089 IRExpr *eConst0 = mkSzImm(ty, (UInt) 0);
2090 IRExpr *eNia = mkSzImm(ty, cia + 8);
2091 IRExpr *eCond = NULL;
2092
2093 assign(tmpRs, getIReg(regRs));
2094 assign(tmpRt, getIReg(regRt));
2095 assign(tmpReg0, getIReg(0));
2096
2097 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpReg0), mkexpr(tmpReg0));
2098
2099 switch (opc1) {
2100 case 0x01:
2101 switch (regRt) {
2102 case 0x00: { /* BLTZ rs, offset */
2103 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
2104 IRTemp tmpLtRes = newTemp(Ity_I1);
2105
2106 assign(tmp, eConst0);
2107 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
2108 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
2109 unop(Iop_1Uto32, mkexpr(tmpLtRes)));
2110
2111 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpLt),
2112 mkexpr(tmpReg0));
2113
petarjef6f26a2014-09-04 17:34:56 +00002114 jmpKind = Ijk_Boring;
petarjb92a9542013-02-27 22:57:17 +00002115 break;
2116 }
2117
2118 case 0x01: { /* BGEZ rs, offset */
2119 IRTemp tmpLtRes = newTemp(Ity_I1);
2120 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
2121
2122 assign(tmp, eConst0);
2123 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
2124 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
2125 unop(Iop_1Uto32, mkexpr(tmpLtRes)));
2126 eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
2127 mkexpr(tmpReg0));
2128
petarjef6f26a2014-09-04 17:34:56 +00002129 jmpKind = Ijk_Boring;
petarjb92a9542013-02-27 22:57:17 +00002130 break;
2131 }
2132
2133 case 0x11: { /* BGEZAL rs, offset */
2134 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
2135 putIReg(regLnk, eNia);
2136 IRTemp tmpLtRes = newTemp(Ity_I1);
2137
2138 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), eConst0));
2139 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
2140 unop(Iop_1Uto32, mkexpr(tmpLtRes)));
2141
2142 eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
2143 mkexpr(tmpReg0));
2144
2145 jmpKind = Ijk_Call;
2146 break;
2147 }
2148
2149 case 0x10: { /* BLTZAL rs, offset */
2150 IRTemp tmpLtRes = newTemp(Ity_I1);
2151 IRTemp tmpRes = newTemp(ty);
2152
2153 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
2154 putIReg(regLnk, eNia);
2155
2156 assign(tmp, eConst0);
2157 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
2158 assign(tmpRes, mode64 ? unop(Iop_1Uto64,
2159 mkexpr(tmpLtRes)) : unop(Iop_1Uto32, mkexpr(tmpLtRes)));
2160 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpRes),
2161 mkexpr(tmpReg0));
2162
2163 jmpKind = Ijk_Call;
2164 break;
2165 }
2166
2167 }
2168 break;
2169 default:
2170 return False;
2171 }
2172 *set = IRStmt_Exit(eCond, jmpKind, mkSzConst(ty, addrTgt), OFFB_PC);
2173 return True;
2174}
2175
petarj5cc3b452013-09-18 02:17:43 +00002176/*********************************************************/
2177/*--- Cavium Specific Instructions ---*/
2178/*********************************************************/
dejanj6ced72b2014-06-04 11:28:07 +00002179
2180/* Convenience function to yield to thread scheduler */
2181static void jump_back(IRExpr *condition)
2182{
2183 stmt( IRStmt_Exit(condition,
2184 Ijk_Yield,
2185 IRConst_U64( guest_PC_curr_instr ),
2186 OFFB_PC) );
2187}
2188
2189/* Based on s390_irgen_load_and_add32. */
2190static void mips_irgen_load_and_add32(IRTemp op1addr, IRTemp new_val,
2191 UChar rd, Bool putIntoRd)
2192{
2193 IRCAS *cas;
2194 IRTemp old_mem = newTemp(Ity_I32);
2195 IRTemp expd = newTemp(Ity_I32);
2196
2197 assign(expd, load(Ity_I32, mkexpr(op1addr)));
2198
2199 cas = mkIRCAS(IRTemp_INVALID, old_mem,
2200 Iend_LE, mkexpr(op1addr),
2201 NULL, mkexpr(expd), /* expected value */
2202 NULL, mkexpr(new_val) /* new value */);
2203 stmt(IRStmt_CAS(cas));
2204
2205 /* If old_mem contains the expected value, then the CAS succeeded.
2206 Otherwise, it did not */
2207 jump_back(binop(Iop_CmpNE32, mkexpr(old_mem), mkexpr(expd)));
2208 if (putIntoRd)
2209 putIReg(rd, mkWidenFrom32(Ity_I64, mkexpr(old_mem), True));
2210}
2211
2212/* Based on s390_irgen_load_and_add64. */
2213static void mips_irgen_load_and_add64(IRTemp op1addr, IRTemp new_val,
2214 UChar rd, Bool putIntoRd)
2215{
2216 IRCAS *cas;
2217 IRTemp old_mem = newTemp(Ity_I64);
2218 IRTemp expd = newTemp(Ity_I64);
2219
2220 assign(expd, load(Ity_I64, mkexpr(op1addr)));
2221
2222 cas = mkIRCAS(IRTemp_INVALID, old_mem,
2223 Iend_LE, mkexpr(op1addr),
2224 NULL, mkexpr(expd), /* expected value */
2225 NULL, mkexpr(new_val) /* new value */);
2226 stmt(IRStmt_CAS(cas));
2227
2228 /* If old_mem contains the expected value, then the CAS succeeded.
2229 Otherwise, it did not */
2230 jump_back(binop(Iop_CmpNE64, mkexpr(old_mem), mkexpr(expd)));
2231 if (putIntoRd)
2232 putIReg(rd, mkexpr(old_mem));
2233}
2234
petarj5cc3b452013-09-18 02:17:43 +00002235static Bool dis_instr_CVM ( UInt theInstr )
2236{
2237 UChar opc2 = get_function(theInstr);
petarjd20794a2014-01-31 12:14:20 +00002238 UChar opc1 = get_opcode(theInstr);
petarj5cc3b452013-09-18 02:17:43 +00002239 UChar regRs = get_rs(theInstr);
2240 UChar regRt = get_rt(theInstr);
2241 UChar regRd = get_rd(theInstr);
dejanj6ced72b2014-06-04 11:28:07 +00002242 UInt imm = get_imm(theInstr);
petarj5cc3b452013-09-18 02:17:43 +00002243 UChar lenM1 = get_msb(theInstr);
2244 UChar p = get_lsb(theInstr);
2245 IRType ty = mode64? Ity_I64 : Ity_I32;
2246 IRTemp tmp = newTemp(ty);
2247 IRTemp tmpRs = newTemp(ty);
2248 IRTemp tmpRt = newTemp(ty);
petarjd20794a2014-01-31 12:14:20 +00002249 IRTemp t1 = newTemp(ty);
petarj5cc3b452013-09-18 02:17:43 +00002250 UInt size;
2251 assign(tmpRs, getIReg(regRs));
2252
dejanj6ced72b2014-06-04 11:28:07 +00002253 switch(opc1) {
2254 case 0x1C: {
petarjd20794a2014-01-31 12:14:20 +00002255 switch(opc2) {
2256 case 0x03: { /* DMUL rd, rs, rt */
2257 DIP("dmul r%d, r%d, r%d", regRd, regRs, regRt);
petarjc328e152014-08-29 17:05:40 +00002258 IRTemp t0 = newTemp(Ity_I128);
petarjd20794a2014-01-31 12:14:20 +00002259 assign(t0, binop(Iop_MullU64, getIReg(regRs), getIReg(regRt)));
2260 putIReg(regRd, unop(Iop_128to64, mkexpr(t0)));
2261 break;
2262 }
petarj5cc3b452013-09-18 02:17:43 +00002263
dejanj6ced72b2014-06-04 11:28:07 +00002264 case 0x18: { /* Store Atomic Add Word - SAA; Cavium OCTEON */
2265 DIP("saa r%u, (r%u)", regRt, regRs);
2266 IRTemp addr = newTemp(Ity_I64);
2267 IRTemp new = newTemp(Ity_I32);
2268 assign (addr, getIReg(regRs));
2269 assign(new, binop(Iop_Add32,
2270 load(Ity_I32, mkexpr(addr)),
2271 mkNarrowTo32(ty, getIReg(regRt))));
2272 mips_irgen_load_and_add32(addr, new, 0, False);
2273 break;
2274 }
2275
2276 /* Store Atomic Add Doubleword - SAAD; Cavium OCTEON */
2277 case 0x19: {
2278 DIP( "saad r%u, (r%u)", regRt, regRs);
2279 IRTemp addr = newTemp(Ity_I64);
2280 IRTemp new = newTemp(Ity_I64);
2281 assign (addr, getIReg(regRs));
2282 assign(new, binop(Iop_Add64,
2283 load(Ity_I64, mkexpr(addr)),
2284 getIReg(regRt)));
2285 mips_irgen_load_and_add64(addr, new, 0, False);
2286 break;
2287 }
2288
2289 /* LAI, LAID, LAD, LADD, LAS, LASD,
2290 LAC, LACD, LAA, LAAD, LAW, LAWD */
2291 case 0x1f: {
2292 UInt opc3 = get_sa(theInstr);
2293 IRTemp addr = newTemp(Ity_I64);
2294 switch (opc3) {
2295 /* Load Atomic Increment Word - LAI; Cavium OCTEON2 */
2296 case 0x02: {
2297 DIP("lai r%u,(r%u)\n", regRd, regRs);
2298 IRTemp new = newTemp(Ity_I32);
2299 assign(addr, getIReg(regRs));
2300 assign(new, binop(Iop_Add32,
2301 load(Ity_I32, mkexpr(addr)),
2302 mkU32(1)));
2303 mips_irgen_load_and_add32(addr, new, regRd, True);
2304 break;
2305 }
2306 /* Load Atomic Increment Doubleword - LAID; Cavium OCTEON2 */
2307 case 0x03: {
2308 DIP("laid r%u,(r%u)\n", regRd, regRs);
2309 IRTemp new = newTemp(Ity_I64);
2310 assign(addr, getIReg(regRs));
2311 assign(new, binop(Iop_Add64,
2312 load(Ity_I64, mkexpr(addr)),
2313 mkU64(1)));
2314 mips_irgen_load_and_add64(addr, new, regRd, True);
2315 break;
2316 }
2317 /* Load Atomic Decrement Word - LAD; Cavium OCTEON2 */
2318 case 0x06: {
2319 DIP("lad r%u,(r%u)\n", regRd, regRs);
2320 IRTemp new = newTemp(Ity_I32);
2321 assign(addr, getIReg(regRs));
2322 assign(new, binop(Iop_Sub32,
2323 load(Ity_I32, mkexpr(addr)),
2324 mkU32(1)));
2325 mips_irgen_load_and_add32(addr, new, regRd, True);
2326 break;
2327 }
2328 /* Load Atomic Decrement Doubleword - LADD; Cavium OCTEON2 */
2329 case 0x07: {
2330 DIP("ladd r%u,(r%u)\n", regRd, regRs);
2331 IRTemp new = newTemp(Ity_I64);
2332 assign (addr, getIReg(regRs));
2333 assign(new, binop(Iop_Sub64,
2334 load(Ity_I64, mkexpr(addr)),
2335 mkU64(1)));
2336 mips_irgen_load_and_add64(addr, new, regRd, True);
2337 break;
2338 }
2339 /* Load Atomic Set Word - LAS; Cavium OCTEON2 */
2340 case 0x0a: {
2341 DIP("las r%u,(r%u)\n", regRd, regRs);
2342 IRTemp new = newTemp(Ity_I32);
2343 assign(addr, getIReg(regRs));
2344 assign(new, mkU32(0xffffffff));
2345 mips_irgen_load_and_add32(addr, new, regRd, True);
2346 break;
2347 }
2348 /* Load Atomic Set Doubleword - LASD; Cavium OCTEON2 */
2349 case 0x0b: {
2350 DIP("lasd r%u,(r%u)\n", regRd, regRs);
2351 IRTemp new = newTemp(Ity_I64);
2352 assign (addr, getIReg(regRs));
dejanjd3194d12014-06-09 10:54:49 +00002353 assign(new, mkU64(0xffffffffffffffffULL));
dejanj6ced72b2014-06-04 11:28:07 +00002354 mips_irgen_load_and_add64(addr, new, regRd, True);
2355 break;
2356 }
2357 /* Load Atomic Clear Word - LAC; Cavium OCTEON2 */
2358 case 0x0e: {
2359 DIP("lac r%u,(r%u)\n", regRd, regRs);
2360 IRTemp new = newTemp(Ity_I32);
2361 assign (addr, getIReg(regRs));
2362 assign(new, mkU32(0));
2363 mips_irgen_load_and_add32(addr, new, regRd, True);
2364 break;
2365 }
2366 /* Load Atomic Clear Doubleword - LACD; Cavium OCTEON2 */
2367 case 0x0f: {
2368 DIP("lacd r%u,(r%u)\n", regRd, regRs);
2369 IRTemp new = newTemp(Ity_I64);
2370 assign(addr, getIReg(regRs));
2371 assign(new, mkU64(0));
2372 mips_irgen_load_and_add64(addr, new, regRd, True);
2373 break;
2374 }
2375 /* Load Atomic Add Word - LAA; Cavium OCTEON2 */
2376 case 0x12: {
2377 DIP("laa r%u,(r%u),r%u\n", regRd, regRs, regRt);
2378 IRTemp new = newTemp(Ity_I32);
2379 assign(addr, getIReg(regRs));
2380 assign(new, binop(Iop_Add32,
2381 load(Ity_I32, mkexpr(addr)),
2382 mkNarrowTo32(ty, getIReg(regRt))));
2383 mips_irgen_load_and_add32(addr, new, regRd, True);
2384 break;
2385 }
2386 /* Load Atomic Add Doubleword - LAAD; Cavium OCTEON2 */
2387 case 0x13: {
2388 DIP("laad r%u,(r%u),r%u\n", regRd, regRs, regRt);
2389 IRTemp new = newTemp(Ity_I64);
2390 assign (addr, getIReg(regRs));
2391 assign(new, binop(Iop_Add64,
2392 load(Ity_I64, mkexpr(addr)),
2393 getIReg(regRt)));
2394 mips_irgen_load_and_add64(addr, new, regRd, True);
2395 break;
2396 }
2397 /* Load Atomic Swap Word - LAW; Cavium OCTEON2 */
2398 case 0x16: {
2399 DIP("law r%u,(r%u)\n", regRd, regRs);
2400 IRTemp new = newTemp(Ity_I32);
2401 assign(addr, getIReg(regRs));
2402 assign(new, mkNarrowTo32(ty, getIReg(regRt)));
2403 mips_irgen_load_and_add32(addr, new, regRd, True);
2404 break;
2405 }
2406 /* Load Atomic Swap Doubleword - LAWD; Cavium OCTEON2 */
2407 case 0x17: {
2408 DIP("lawd r%u,(r%u)\n", regRd, regRs);
2409 IRTemp new = newTemp(Ity_I64);
2410 assign(addr, getIReg(regRs));
2411 assign(new, getIReg(regRt));
2412 mips_irgen_load_and_add64(addr, new, regRd, True);
2413 break;
2414 }
2415 default:
2416 vex_printf("Unknown laxx instruction, opc3=0x%x\n", opc3);
2417 vex_printf("Instruction=0x%08x\n", theInstr);
2418 return False;
2419 }
2420 break;
2421 }
2422
2423 /* Unsigned Byte Add - BADDU rd, rs, rt; Cavium OCTEON */
2424 case 0x28: {
2425 DIP("BADDU r%d, r%d, r%d", regRs, regRt, regRd);
2426 IRTemp t0 = newTemp(Ity_I8);
2427
2428 assign(t0, binop(Iop_Add8,
2429 mkNarrowTo8(ty, getIReg(regRs)),
2430 mkNarrowTo8(ty, getIReg(regRt))));
2431
2432 if (mode64)
2433 putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
2434 unop(Iop_8Uto64, mkexpr(t0)),
2435 mkSzImm(ty, 0xFF)));
2436 else
2437 putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
2438 unop(Iop_8Uto32, mkexpr(t0)),
2439 mkSzImm(ty, 0xFF)));
2440 break;
2441 }
2442
2443 case 0x2c: { /* Count Ones in a Word - POP; Cavium OCTEON */
2444 int i, shift[5];
2445 IRTemp mask[5];
2446 IRTemp old = newTemp(ty);
2447 IRTemp nyu = IRTemp_INVALID;
2448 assign(old, getIReg(regRs));
2449 DIP("pop r%d, r%d", regRd, regRs);
2450
2451 for (i = 0; i < 5; i++) {
2452 mask[i] = newTemp(ty);
2453 shift[i] = 1 << i;
2454 }
2455 if(mode64) {
2456 assign(mask[0], mkU64(0x0000000055555555));
2457 assign(mask[1], mkU64(0x0000000033333333));
2458 assign(mask[2], mkU64(0x000000000F0F0F0F));
2459 assign(mask[3], mkU64(0x0000000000FF00FF));
2460 assign(mask[4], mkU64(0x000000000000FFFF));
2461
2462 for (i = 0; i < 5; i++) {
2463 nyu = newTemp(ty);
2464 assign(nyu,
2465 binop(Iop_Add64,
2466 binop(Iop_And64,
2467 mkexpr(old), mkexpr(mask[i])),
2468 binop(Iop_And64,
2469 binop(Iop_Shr64,
2470 mkexpr(old), mkU8(shift[i])),
2471 mkexpr(mask[i]))));
2472 old = nyu;
2473 }
2474 } else {
2475 assign(mask[0], mkU32(0x55555555));
2476 assign(mask[1], mkU32(0x33333333));
2477 assign(mask[2], mkU32(0x0F0F0F0F));
2478 assign(mask[3], mkU32(0x00FF00FF));
2479 assign(mask[4], mkU32(0x0000FFFF));
2480 assign(old, getIReg(regRs));
2481
2482 for (i = 0; i < 5; i++) {
2483 nyu = newTemp(ty);
2484 assign(nyu,
2485 binop(Iop_Add32,
2486 binop(Iop_And32,
2487 mkexpr(old), mkexpr(mask[i])),
2488 binop(Iop_And32,
2489 binop(Iop_Shr32,
2490 mkexpr(old), mkU8(shift[i])),
2491 mkexpr(mask[i]))));
2492 old = nyu;
2493 }
2494 }
2495 putIReg(regRd, mkexpr(nyu));
2496 break;
2497 }
2498
2499 /* Count Ones in a Doubleword - DPOP; Cavium OCTEON */
2500 case 0x2d: {
2501 int i, shift[6];
2502 IRTemp mask[6];
2503 IRTemp old = newTemp(ty);
2504 IRTemp nyu = IRTemp_INVALID;
2505 DIP("dpop r%d, r%d", regRd, regRs);
2506
2507 for (i = 0; i < 6; i++) {
2508 mask[i] = newTemp(ty);
2509 shift[i] = 1 << i;
2510 }
2511 vassert(mode64); /*Caution! Only for Mode 64*/
2512 assign(mask[0], mkU64(0x5555555555555555ULL));
2513 assign(mask[1], mkU64(0x3333333333333333ULL));
2514 assign(mask[2], mkU64(0x0F0F0F0F0F0F0F0FULL));
2515 assign(mask[3], mkU64(0x00FF00FF00FF00FFULL));
2516 assign(mask[4], mkU64(0x0000FFFF0000FFFFULL));
2517 assign(mask[5], mkU64(0x00000000FFFFFFFFULL));
2518 assign(old, getIReg(regRs));
2519 for (i = 0; i < 6; i++) {
2520 nyu = newTemp(Ity_I64);
2521 assign(nyu,
2522 binop(Iop_Add64,
2523 binop(Iop_And64,
2524 mkexpr(old), mkexpr(mask[i])),
2525 binop(Iop_And64,
2526 binop(Iop_Shr64,
2527 mkexpr(old), mkU8(shift[i])),
2528 mkexpr(mask[i]))));
2529 old = nyu;
2530 }
2531 putIReg(regRd, mkexpr(nyu));
2532 break;
2533 }
2534
petarjd20794a2014-01-31 12:14:20 +00002535 case 0x32: /* 5. CINS rd, rs, p, lenm1 */
2536 DIP("cins r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
2537 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
2538 mkU8(64-( lenM1+1 ))));
2539 assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
2540 mkU8(64-(p+lenM1+1))));
2541 putIReg( regRt, mkexpr(tmpRt));
2542 break;
petarj5cc3b452013-09-18 02:17:43 +00002543
petarjd20794a2014-01-31 12:14:20 +00002544 case 0x33: /* 6. CINS32 rd, rs, p+32, lenm1 */
2545 DIP("cins32 r%u, r%u, %d, %d\n", regRt, regRs, p+32, lenM1);
2546 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
2547 mkU8(64-( lenM1+1 ))));
2548 assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
2549 mkU8(32-(p+lenM1+1))));
2550 putIReg( regRt, mkexpr(tmpRt));
2551 break;
petarj5cc3b452013-09-18 02:17:43 +00002552
petarjd20794a2014-01-31 12:14:20 +00002553 case 0x3A: /* 3. EXTS rt, rs, p len */
2554 DIP("exts r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
2555 size = lenM1 + 1; /* lenm1+1 */
2556 UChar lsAmt = 64 - (p + size); /* p+lenm1+1 */
2557 UChar rsAmt = 64 - size; /* lenm1+1 */
2558 tmp = newTemp(Ity_I64);
2559 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
2560 putIReg(regRt, binop(Iop_Sar64, mkexpr(tmp), mkU8(rsAmt)));
2561 break;
petarj5cc3b452013-09-18 02:17:43 +00002562
petarjd20794a2014-01-31 12:14:20 +00002563 case 0x3B: /* 4. EXTS32 rt, rs, p len */
2564 DIP("exts32 r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
2565 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
2566 mkU8(32-(p+lenM1+1))));
2567 assign ( tmpRt, binop(Iop_Sar64, mkexpr(tmp),
2568 mkU8(64-(lenM1+1))) );
2569 putIReg( regRt, mkexpr(tmpRt));
2570 break;
petarj5cc3b452013-09-18 02:17:43 +00002571
petarjd20794a2014-01-31 12:14:20 +00002572 case 0x2B: /* 20. SNE rd, rs, rt */
2573 DIP("sne r%d, r%d, r%d", regRd,regRs, regRt);
2574 if (mode64)
2575 putIReg(regRd, unop(Iop_1Uto64, binop(Iop_CmpNE64,
2576 getIReg(regRs),
2577 getIReg(regRt))));
2578 else
2579 putIReg(regRd,unop(Iop_1Uto32, binop(Iop_CmpNE32,
2580 getIReg(regRs),
2581 getIReg(regRt))));
2582 break;
petarj5cc3b452013-09-18 02:17:43 +00002583
petarjd20794a2014-01-31 12:14:20 +00002584 case 0x2A: /* Set Equals - SEQ; Cavium OCTEON */
2585 DIP("seq r%d, r%d, %d", regRd, regRs, regRt);
2586 if (mode64)
2587 putIReg(regRd, unop(Iop_1Uto64,
2588 binop(Iop_CmpEQ64, getIReg(regRs),
2589 getIReg(regRt))));
2590 else
2591 putIReg(regRd, unop(Iop_1Uto32,
2592 binop(Iop_CmpEQ32, getIReg(regRs),
2593 getIReg(regRt))));
2594 break;
petarj5cc3b452013-09-18 02:17:43 +00002595
petarjd20794a2014-01-31 12:14:20 +00002596 case 0x2E: /* Set Equals Immediate - SEQI; Cavium OCTEON */
2597 DIP("seqi r%d, r%d, %d", regRt, regRs, imm);
2598 if (mode64)
2599 putIReg(regRt, unop(Iop_1Uto64,
2600 binop(Iop_CmpEQ64, getIReg(regRs),
2601 mkU64(extend_s_10to64(imm)))));
2602 else
2603 putIReg(regRt, unop(Iop_1Uto32,
2604 binop(Iop_CmpEQ32, getIReg(regRs),
2605 mkU32(extend_s_10to32(imm)))));
2606 break;
petarj5cc3b452013-09-18 02:17:43 +00002607
petarjd20794a2014-01-31 12:14:20 +00002608 case 0x2F: /* Set Not Equals Immediate - SNEI; Cavium OCTEON */
2609 DIP("snei r%d, r%d, %d", regRt, regRs, imm);
2610 if (mode64)
2611 putIReg(regRt, unop(Iop_1Uto64,
2612 binop(Iop_CmpNE64,
2613 getIReg(regRs),
2614 mkU64(extend_s_10to64(imm)))));
2615 else
2616 putIReg(regRt, unop(Iop_1Uto32,
2617 binop(Iop_CmpNE32,
2618 getIReg(regRs),
2619 mkU32(extend_s_10to32(imm)))));
2620 break;
2621
2622 default:
2623 return False;
2624 }
2625 break;
2626 } /* opc1 0x1C ends here*/
dejanj6ced72b2014-06-04 11:28:07 +00002627 case 0x1F: {
petarjd20794a2014-01-31 12:14:20 +00002628 switch(opc2) {
2629 case 0x0A: { // lx - Load indexed instructions
2630 switch (get_sa(theInstr)) {
petarj95d9e8f2014-02-14 17:28:15 +00002631 case 0x00: { // LWX rd, index(base)
2632 DIP("lwx r%d, r%d(r%d)", regRd, regRt, regRs);
2633 LOADX_STORE_PATTERN;
2634 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
2635 True));
2636 break;
2637 }
2638 case 0x08: { // LDX rd, index(base)
2639 DIP("ldx r%d, r%d(r%d)", regRd, regRt, regRs);
2640 vassert(mode64); /* Currently Implemented only for n64 */
2641 LOADX_STORE_PATTERN;
2642 putIReg(regRd, load(Ity_I64, mkexpr(t1)));
2643 break;
2644 }
2645 case 0x06: { // LBUX rd, index(base)
2646 DIP("lbux r%d, r%d(r%d)", regRd, regRt, regRs);
2647 LOADX_STORE_PATTERN;
2648 if (mode64)
2649 putIReg(regRd, unop(Iop_8Uto64, load(Ity_I8,
2650 mkexpr(t1))));
2651 else
2652 putIReg(regRd, unop(Iop_8Uto32, load(Ity_I8,
2653 mkexpr(t1))));
2654 break;
2655 }
petarjd20794a2014-01-31 12:14:20 +00002656 case 0x10: { // LWUX rd, index(base) (Cavium OCTEON)
2657 DIP("lwux r%d, r%d(r%d)", regRd, regRt, regRs);
2658 LOADX_STORE_PATTERN; /* same for both 32 and 64 modes*/
2659 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
2660 False));
2661 break;
2662 }
2663 case 0x14: { // LHUX rd, index(base) (Cavium OCTEON)
2664 DIP("lhux r%d, r%d(r%d)", regRd, regRt, regRs);
2665 LOADX_STORE_PATTERN;
2666 if (mode64)
2667 putIReg(regRd,
2668 unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
2669 else
2670 putIReg(regRd,
2671 unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
2672 break;
2673 }
2674 case 0x16: { // LBX rd, index(base) (Cavium OCTEON)
2675 DIP("lbx r%d, r%d(r%d)", regRd, regRs, regRt);
2676 LOADX_STORE_PATTERN;
2677 if (mode64)
2678 putIReg(regRd,
2679 unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
2680 else
2681 putIReg(regRd,
2682 unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
2683 break;
2684 }
2685 default:
2686 vex_printf("\nUnhandled LX instruction opc3 = %x\n",
2687 get_sa(theInstr));
2688 return False;
2689 }
2690 break;
2691 }
2692 } /* opc1 = 0x1F & opc2 = 0xA (LX) ends here*/
2693 break;
2694 } /* opc1 = 0x1F ends here*/
petarj5cc3b452013-09-18 02:17:43 +00002695 default:
petarjd20794a2014-01-31 12:14:20 +00002696 return False;
2697 } /* main opc1 switch ends here */
petarj5cc3b452013-09-18 02:17:43 +00002698 return True;
2699}
2700
sewardj362cf842012-06-07 08:59:53 +00002701/*------------------------------------------------------------*/
dejanjc3fee0d2013-07-25 09:08:03 +00002702/*--- Disassemble a single DSP ASE instruction ---*/
2703/*------------------------------------------------------------*/
2704
2705static UInt disDSPInstr_MIPS_WRK ( UInt cins )
2706{
2707 IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14,
dejanj781f1bd2013-10-23 14:05:15 +00002708 t15, t16, t17;
dejanjc3fee0d2013-07-25 09:08:03 +00002709 UInt opcode, rs, rt, rd, sa, function, ac, ac_mfhilo, rddsp_mask,
2710 wrdsp_mask, dsp_imm, shift;
2711
2712 opcode = get_opcode(cins);
2713 rs = get_rs(cins);
2714 rt = get_rt(cins);
2715 rd = get_rd(cins);
2716 sa = get_sa(cins);
2717 function = get_function(cins);
2718 ac = get_acNo(cins);
2719 ac_mfhilo = get_acNo_mfhilo(cins);
2720 rddsp_mask = get_rddspMask(cins);
2721 wrdsp_mask = get_wrdspMask(cins);
2722 dsp_imm = get_dspImm(cins);
2723 shift = get_shift(cins);
2724
2725 switch (opcode) {
2726 case 0x00: { /* Special */
2727 switch (function) {
2728 case 0x10: { /* MFHI */
2729 DIP("mfhi ac%d r%d", ac_mfhilo, rd);
2730 putIReg(rd, unop(Iop_64HIto32, getAcc(ac_mfhilo)));
2731 break;
2732 }
2733
2734 case 0x11: { /* MTHI */
2735 DIP("mthi ac%d r%d", ac, rs);
2736 t1 = newTemp(Ity_I32);
2737 assign(t1, unop(Iop_64to32, getAcc(ac)));
2738 putAcc(ac, binop(Iop_32HLto64, getIReg(rs), mkexpr(t1)));
2739 break;
2740 }
2741
2742 case 0x12: { /* MFLO */
2743 DIP("mflo ac%d r%d", ac_mfhilo, rd);
2744 putIReg(rd, unop(Iop_64to32, getAcc(ac_mfhilo)));
2745 break;
2746 }
2747
2748 case 0x13: { /* MTLO */
2749 DIP("mtlo ac%d r%d", ac, rs);
2750 t1 = newTemp(Ity_I32);
2751 assign(t1, unop(Iop_64HIto32, getAcc(ac)));
2752 putAcc(ac, binop(Iop_32HLto64, mkexpr(t1), getIReg(rs)));
2753 break;
2754 }
2755
2756 case 0x18: { /* MULT */
2757 DIP("mult ac%d r%d, r%d", ac, rs, rt);
2758 t1 = newTemp(Ity_I64);
2759 assign(t1, binop(Iop_MullS32, mkNarrowTo32(Ity_I32, getIReg(rs)),
2760 mkNarrowTo32(Ity_I32, getIReg(rt))));
2761 putAcc(ac, mkexpr(t1));
2762 break;
2763 }
2764
2765 case 0x19: { /* MULTU */
2766 DIP("multu ac%d r%d, r%d", ac, rs, rt);
2767 t1 = newTemp(Ity_I64);
2768 assign(t1, binop(Iop_MullU32, mkNarrowTo32(Ity_I32, getIReg(rs)),
2769 mkNarrowTo32(Ity_I32,
2770 getIReg(rt))));
2771 putAcc(ac, mkexpr(t1));
2772 break;
2773 }
2774 }
2775 break;
2776 }
2777 case 0x1C: { /* Special2 */
2778 switch (function) {
2779 case 0x00: { /* MADD */
2780 DIP("madd ac%d, r%d, r%d", ac, rs, rt);
2781 t1 = newTemp(Ity_I64);
2782 t2 = newTemp(Ity_I64);
2783 t3 = newTemp(Ity_I64);
2784
2785 assign(t1, getAcc(ac));
2786 assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
2787 assign(t3, binop(Iop_Add64, mkexpr(t1), mkexpr(t2)));
2788
2789 putAcc(ac, mkexpr(t3));
2790 break;
2791 }
2792 case 0x01: { /* MADDU */
2793 DIP("maddu ac%d r%d, r%d", ac, rs, rt);
2794 t1 = newTemp(Ity_I64);
2795 t2 = newTemp(Ity_I64);
2796 t3 = newTemp(Ity_I64);
2797
2798 assign(t1, getAcc(ac));
2799 assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
2800 assign(t3, binop(Iop_Add64, mkexpr(t2), mkexpr(t1)));
2801
2802 putAcc(ac, mkexpr(t3));
2803 break;
2804 }
2805 case 0x04: { /* MSUB */
2806 DIP("msub ac%d r%d, r%d", ac, rs, rt);
2807 t1 = newTemp(Ity_I64);
2808 t2 = newTemp(Ity_I64);
2809 t3 = newTemp(Ity_I64);
2810
2811 assign(t1, getAcc(ac));
2812 assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
2813 assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));
2814
2815 putAcc(ac, mkexpr(t3));
2816 break;
2817 }
2818 case 0x05: { /* MSUBU */
2819 DIP("msubu ac%d r%d, r%d", ac, rs, rt);
2820 t1 = newTemp(Ity_I64);
2821 t2 = newTemp(Ity_I64);
2822 t3 = newTemp(Ity_I64);
2823
2824 assign(t1, getAcc(ac));
2825 assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
2826 assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));
2827
2828 putAcc(ac, mkexpr(t3));
2829 break;
2830 }
2831 }
2832 break;
2833 }
2834 case 0x1F: { /* Special3 */
2835 switch (function) {
2836 case 0x12: { /* ABSQ_S.PH */
2837 switch (sa) {
2838 case 0x1: { /* ABSQ_S.QB */
2839 DIP("absq_s.qb r%d, r%d", rd, rt);
2840 vassert(!mode64);
2841 t0 = newTemp(Ity_I8);
2842 t1 = newTemp(Ity_I1);
2843 t2 = newTemp(Ity_I1);
2844 t3 = newTemp(Ity_I8);
2845 t4 = newTemp(Ity_I8);
2846 t5 = newTemp(Ity_I1);
2847 t6 = newTemp(Ity_I1);
2848 t7 = newTemp(Ity_I8);
2849 t8 = newTemp(Ity_I8);
2850 t9 = newTemp(Ity_I1);
2851 t10 = newTemp(Ity_I1);
2852 t11 = newTemp(Ity_I8);
2853 t12 = newTemp(Ity_I8);
2854 t13 = newTemp(Ity_I1);
2855 t14 = newTemp(Ity_I1);
2856 t15 = newTemp(Ity_I8);
2857 t16 = newTemp(Ity_I32);
2858 t17 = newTemp(Ity_I32);
2859
2860 /* Absolute value of the rightmost byte (bits 7-0). */
2861 /* t0 - rightmost byte. */
2862 assign(t0, unop(Iop_16to8, unop(Iop_32to16, getIReg(rt))));
2863 /* t1 holds 1 if t0 is equal to 0x80, or 0 otherwise. */
2864 assign(t1, binop(Iop_CmpEQ32,
2865 unop(Iop_8Uto32, mkexpr(t0)),
2866 mkU32(0x00000080)));
2867 /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
2868 assign(t2, unop(Iop_32to1,
2869 binop(Iop_Shr32,
2870 binop(Iop_And32,
2871 getIReg(rt),
2872 mkU32(0x00000080)),
2873 mkU8(0x7))));
2874 /* t3 holds abs(t0). */
2875 assign(t3, IRExpr_ITE(mkexpr(t1),
2876 mkU8(0x7F),
2877 IRExpr_ITE(mkexpr(t2),
2878 binop(Iop_Add8,
2879 unop(Iop_Not8,
2880 mkexpr(t0)),
2881 mkU8(0x1)),
2882 mkexpr(t0))));
2883
2884 /* Absolute value of bits 15-8. */
2885 /* t4 - input byte. */
2886 assign(t4,
2887 unop(Iop_16HIto8, unop(Iop_32to16, getIReg(rt))));
2888 /* t5 holds 1 if t4 is equal to 0x80, or 0 otherwise. */
2889 assign(t5, binop(Iop_CmpEQ32,
2890 unop(Iop_8Uto32, mkexpr(t4)),
2891 mkU32(0x00000080)));
2892 /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
2893 assign(t6, unop(Iop_32to1,
2894 binop(Iop_Shr32,
2895 binop(Iop_And32,
2896 getIReg(rt),
2897 mkU32(0x00008000)),
2898 mkU8(15))));
2899 /* t3 holds abs(t4). */
2900 assign(t7, IRExpr_ITE(mkexpr(t5),
2901 mkU8(0x7F),
2902 IRExpr_ITE(mkexpr(t6),
2903 binop(Iop_Add8,
2904 unop(Iop_Not8,
2905 mkexpr(t4)),
2906 mkU8(0x1)),
2907 mkexpr(t4))));
2908
2909 /* Absolute value of bits 23-15. */
2910 /* t8 - input byte. */
2911 assign(t8,
2912 unop(Iop_16to8, unop(Iop_32HIto16, getIReg(rt))));
2913 /* t9 holds 1 if t8 is equal to 0x80, or 0 otherwise. */
2914 assign(t9, binop(Iop_CmpEQ32,
2915 unop(Iop_8Uto32, mkexpr(t8)),
2916 mkU32(0x00000080)));
2917 /* t6 holds 1 if value in t8 is negative, 0 otherwise. */
2918 assign(t10, unop(Iop_32to1,
2919 binop(Iop_Shr32,
2920 binop(Iop_And32,
2921 getIReg(rt),
2922 mkU32(0x00800000)),
2923 mkU8(23))));
2924 /* t3 holds abs(t8). */
2925 assign(t11, IRExpr_ITE(mkexpr(t9),
2926 mkU8(0x7F),
2927 IRExpr_ITE(mkexpr(t10),
2928 binop(Iop_Add8,
2929 unop(Iop_Not8,
2930 mkexpr(t8)),
2931 mkU8(0x1)),
2932 mkexpr(t8))));
2933
2934 /* Absolute value of bits 31-24. */
2935 /* t12 - input byte. */
2936 assign(t12,
2937 unop(Iop_16HIto8, unop(Iop_32HIto16, getIReg(rt))));
2938 /* t13 holds 1 if t12 is equal to 0x80, or 0 otherwise. */
2939 assign(t13, binop(Iop_CmpEQ32,
2940 unop(Iop_8Uto32, mkexpr(t12)),
2941 mkU32(0x00000080)));
2942 /* t14 holds 1 if value in t12 is negative, 0 otherwise. */
2943 assign(t14, unop(Iop_32to1,
2944 binop(Iop_Shr32,
2945 binop(Iop_And32,
2946 getIReg(rt),
2947 mkU32(0x80000000)),
2948 mkU8(31))));
2949 /* t15 holds abs(t12). */
2950 assign(t15, IRExpr_ITE(mkexpr(t13),
2951 mkU8(0x7F),
2952 IRExpr_ITE(mkexpr(t14),
2953 binop(Iop_Add8,
2954 unop(Iop_Not8,
2955 mkexpr(t12)),
2956 mkU8(0x1)),
2957 mkexpr(t12))));
2958
2959 /* t16 holds !0 if any of input bytes is 0x80 or 0
2960 otherwise. */
2961 assign(t16,
2962 binop(Iop_Or32,
2963 binop(Iop_Or32,
2964 binop(Iop_Or32,
2965 unop(Iop_1Sto32, mkexpr(t13)),
2966 unop(Iop_1Sto32, mkexpr(t9))),
2967 unop(Iop_1Sto32, mkexpr(t5))),
2968 unop(Iop_1Sto32, mkexpr(t1))));
2969
2970 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
2971 mkexpr(t16),
2972 mkU32(0x0)),
2973 getDSPControl(),
2974 binop(Iop_Or32,
2975 getDSPControl(),
2976 mkU32(0x00100000))));
2977
2978 /* t17 = t15|t11|t7|t3 */
2979 assign(t17,
2980 binop(Iop_16HLto32,
2981 binop(Iop_8HLto16, mkexpr(t15), mkexpr(t11)),
2982 binop(Iop_8HLto16, mkexpr(t7), mkexpr(t3))));
2983
2984 putIReg(rd, mkexpr(t17));
2985 break;
2986 }
2987 case 0x2: { /* REPL.QB */
2988 DIP("repl.qb r%d, %d", rd, dsp_imm);
2989 vassert(!mode64);
2990
2991 putIReg(rd, mkU32((dsp_imm << 24) | (dsp_imm << 16) |
2992 (dsp_imm << 8) | (dsp_imm)));
2993 break;
2994 }
2995 case 0x3: { /* REPLV.QB */
2996 DIP("replv.qb r%d, r%d", rd, rt);
2997 vassert(!mode64);
2998 t0 = newTemp(Ity_I8);
2999
3000 assign(t0, unop(Iop_32to8,
3001 binop(Iop_And32, getIReg(rt), mkU32(0xff))));
3002 putIReg(rd,
3003 binop(Iop_16HLto32,
3004 binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)),
3005 binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0))));
3006 break;
3007 }
3008 case 0x4: { /* PRECEQU.PH.QBL */
3009 DIP("precequ.ph.qbl r%d, r%d", rd, rt);
3010 vassert(!mode64);
3011
3012 putIReg(rd, binop(Iop_Or32,
3013 binop(Iop_Shr32,
3014 binop(Iop_And32,
3015 getIReg(rt),
3016 mkU32(0xff000000)),
3017 mkU8(1)),
3018 binop(Iop_Shr32,
3019 binop(Iop_And32,
3020 getIReg(rt),
3021 mkU32(0x00ff0000)),
3022 mkU8(9))));
3023 break;
3024 }
3025 case 0x5: { /* PRECEQU.PH.QBR */
3026 DIP("precequ.ph.qbr r%d, r%d", rd, rt);
3027 vassert(!mode64);
3028
3029 putIReg(rd, binop(Iop_Or32,
3030 binop(Iop_Shl32,
3031 binop(Iop_And32,
3032 getIReg(rt),
3033 mkU32(0x0000ff00)),
3034 mkU8(15)),
3035 binop(Iop_Shl32,
3036 binop(Iop_And32,
3037 getIReg(rt),
3038 mkU32(0x000000ff)),
3039 mkU8(7))));
3040 break;
3041 }
3042 case 0x6: { /* PRECEQU.PH.QBLA */
3043 DIP("precequ.ph.qbla r%d, r%d", rd, rt);
3044 vassert(!mode64);
3045
3046 putIReg(rd, binop(Iop_Or32,
3047 binop(Iop_Shr32,
3048 binop(Iop_And32,
3049 getIReg(rt),
3050 mkU32(0xff000000)),
3051 mkU8(1)),
3052 binop(Iop_Shr32,
3053 binop(Iop_And32,
3054 getIReg(rt),
3055 mkU32(0x0000ff00)),
3056 mkU8(1))));
3057 break;
3058 }
3059 case 0x7: { /* PRECEQU.PH.QBRA */
3060 DIP("precequ.ph.qbra r%d, r%d", rd, rt);
3061 vassert(!mode64);
3062
3063 putIReg(rd, binop(Iop_Or32,
3064 binop(Iop_Shl32,
3065 binop(Iop_And32,
3066 getIReg(rt),
3067 mkU32(0x00ff0000)),
3068 mkU8(7)),
3069 binop(Iop_Shl32,
3070 binop(Iop_And32,
3071 getIReg(rt),
3072 mkU32(0x000000ff)),
3073 mkU8(7))));
3074 break;
3075 }
3076 case 0x9: { /* ABSQ_S.PH */
3077 DIP("absq_s.ph r%d, r%d", rd, rt);
3078 vassert(!mode64);
3079 t0 = newTemp(Ity_I16);
3080 t1 = newTemp(Ity_I1);
3081 t2 = newTemp(Ity_I1);
3082 t3 = newTemp(Ity_I16);
3083 t4 = newTemp(Ity_I16);
3084 t5 = newTemp(Ity_I1);
3085 t6 = newTemp(Ity_I1);
3086 t7 = newTemp(Ity_I16);
3087 t8 = newTemp(Ity_I32);
3088 t9 = newTemp(Ity_I32);
3089
3090 /* t0 holds lower 16 bits of value in rt. */
3091 assign(t0, unop(Iop_32to16, getIReg(rt)));
3092 /* t1 holds 1 if t0 is equal to 0x8000. */
3093 assign(t1, binop(Iop_CmpEQ32,
3094 unop(Iop_16Uto32, mkexpr(t0)),
3095 mkU32(0x00008000)));
3096 /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
3097 assign(t2, unop(Iop_32to1,
3098 binop(Iop_Shr32,
3099 binop(Iop_And32,
3100 getIReg(rt),
3101 mkU32(0x00008000)),
3102 mkU8(15))));
3103 /* t3 holds abs(t0). */
3104 assign(t3, IRExpr_ITE(mkexpr(t1),
3105 mkU16(0x7FFF),
3106 IRExpr_ITE(mkexpr(t2),
3107 binop(Iop_Add16,
3108 unop(Iop_Not16,
3109 mkexpr(t0)),
3110 mkU16(0x1)),
3111 mkexpr(t0))));
3112
3113 /* t4 holds lower 16 bits of value in rt. */
3114 assign(t4, unop(Iop_32HIto16, getIReg(rt)));
3115 /* t5 holds 1 if t4 is equal to 0x8000. */
3116 assign(t5, binop(Iop_CmpEQ32,
3117 unop(Iop_16Uto32, mkexpr(t4)),
3118 mkU32(0x00008000)));
3119 /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
3120 assign(t6, unop(Iop_32to1,
3121 binop(Iop_Shr32,
3122 binop(Iop_And32,
3123 getIReg(rt),
3124 mkU32(0x80000000)),
3125 mkU8(31))));
3126 /* t7 holds abs(t4). */
3127 assign(t7, IRExpr_ITE(mkexpr(t5),
3128 mkU16(0x7FFF),
3129 IRExpr_ITE(mkexpr(t6),
3130 binop(Iop_Add16,
3131 unop(Iop_Not16,
3132 mkexpr(t4)),
3133 mkU16(0x1)),
3134 mkexpr(t4))));
3135 /* If any of the two input halfwords is equal 0x8000,
3136 set bit 20 in DSPControl register. */
3137 assign(t8, binop(Iop_Or32,
3138 unop(Iop_1Sto32, mkexpr(t5)),
3139 unop(Iop_1Sto32, mkexpr(t1))));
3140
3141 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
3142 mkexpr(t8),
3143 mkU32(0x0)),
3144 getDSPControl(),
3145 binop(Iop_Or32,
3146 getDSPControl(),
3147 mkU32(0x00100000))));
3148
3149 /* t9 = t7|t3 */
3150 assign(t9, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3)));
3151
3152 putIReg(rd, mkexpr(t9));
3153 break;
3154 }
3155 case 0xA: { /* REPL.PH */
3156 DIP("repl.ph r%d, %d", rd, dsp_imm);
3157 vassert(!mode64);
3158 UShort immediate = extend_s_10to16(dsp_imm);
3159
3160 putIReg(rd, mkU32(immediate << 16 | immediate));
3161 break;
3162 }
3163 case 0xB: { /* REPLV.PH */
3164 DIP("replv.ph r%d, r%d", rd, rt);
3165 vassert(!mode64);
3166
3167 putIReg(rd, binop(Iop_16HLto32,
3168 unop(Iop_32to16, getIReg(rt)),
3169 unop(Iop_32to16, getIReg(rt))));
3170 break;
3171 }
3172 case 0xC: { /* PRECEQ.W.PHL */
3173 DIP("preceq.w.phl r%d, r%d", rd, rt);
3174 vassert(!mode64);
3175 putIReg(rd, binop(Iop_And32,
3176 getIReg(rt),
3177 mkU32(0xffff0000)));
3178 break;
3179 }
3180 case 0xD: { /* PRECEQ.W.PHR */
3181 DIP("preceq.w.phr r%d, r%d", rd, rt);
3182 vassert(!mode64);
3183 putIReg(rd, binop(Iop_16HLto32,
3184 unop(Iop_32to16, getIReg(rt)),
3185 mkU16(0x0)));
3186 break;
3187 }
3188 case 0x11: { /* ABSQ_S.W */
3189 DIP("absq_s.w r%d, r%d", rd, rt);
3190 vassert(!mode64);
3191 t0 = newTemp(Ity_I1);
3192 t1 = newTemp(Ity_I1);
3193 t2 = newTemp(Ity_I32);
3194
3195 assign(t0,
3196 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000)));
3197
3198 putDSPControl(IRExpr_ITE(mkexpr(t0),
3199 binop(Iop_Or32,
3200 getDSPControl(),
3201 mkU32(0x00100000)),
3202 getDSPControl()));
3203
3204 assign(t1, binop(Iop_CmpLT32S, getIReg(rt), mkU32(0x0)));
3205
3206 assign(t2, IRExpr_ITE(mkexpr(t0),
3207 mkU32(0x7FFFFFFF),
3208 IRExpr_ITE(mkexpr(t1),
3209 binop(Iop_Add32,
3210 unop(Iop_Not32,
3211 getIReg(rt)),
3212 mkU32(0x1)),
3213 getIReg(rt))));
3214 putIReg(rd, mkexpr(t2));
3215 break;
3216 }
3217 case 0x1B: { /* BITREV */
3218 DIP("bitrev r%d, r%d", rd, rt);
3219 vassert(!mode64);
3220 /* 32bit reversal as seen on Bit Twiddling Hacks site
3221 http://graphics.stanford.edu/~seander/bithacks.html
3222 section ReverseParallel */
3223 t1 = newTemp(Ity_I32);
3224 t2 = newTemp(Ity_I32);
3225 t3 = newTemp(Ity_I32);
3226 t4 = newTemp(Ity_I32);
3227 t5 = newTemp(Ity_I32);
3228
3229 assign(t1, binop(Iop_Or32,
3230 binop(Iop_Shr32,
3231 binop(Iop_And32,
3232 getIReg(rt),
3233 mkU32(0xaaaaaaaa)),
3234 mkU8(0x1)),
3235 binop(Iop_Shl32,
3236 binop(Iop_And32,
3237 getIReg(rt),
3238 mkU32(0x55555555)),
3239 mkU8(0x1))));
3240 assign(t2, binop(Iop_Or32,
3241 binop(Iop_Shr32,
3242 binop(Iop_And32,
3243 mkexpr(t1),
3244 mkU32(0xcccccccc)),
3245 mkU8(0x2)),
3246 binop(Iop_Shl32,
3247 binop(Iop_And32,
3248 mkexpr(t1),
3249 mkU32(0x33333333)),
3250 mkU8(0x2))));
3251 assign(t3, binop(Iop_Or32,
3252 binop(Iop_Shr32,
3253 binop(Iop_And32,
3254 mkexpr(t2),
3255 mkU32(0xf0f0f0f0)),
3256 mkU8(0x4)),
3257 binop(Iop_Shl32,
3258 binop(Iop_And32,
3259 mkexpr(t2),
3260 mkU32(0x0f0f0f0f)),
3261 mkU8(0x4))));
3262 assign(t4, binop(Iop_Or32,
3263 binop(Iop_Shr32,
3264 binop(Iop_And32,
3265 mkexpr(t3),
3266 mkU32(0xff00ff00)),
3267 mkU8(0x8)),
3268 binop(Iop_Shl32,
3269 binop(Iop_And32,
3270 mkexpr(t3),
3271 mkU32(0x00ff00ff)),
3272 mkU8(0x8))));
3273 assign(t5, binop(Iop_Or32,
3274 binop(Iop_Shr32,
3275 mkexpr(t4),
3276 mkU8(0x10)),
3277 binop(Iop_Shl32,
3278 mkexpr(t4),
3279 mkU8(0x10))));
3280 putIReg(rd, binop(Iop_Shr32,
3281 mkexpr(t5),
3282 mkU8(16)));
3283 break;
3284 }
3285 case 0x1C: { /* PRECEU.PH.QBL */
3286 DIP("preceu.ph.qbl r%d, r%d", rd, rt);
3287 vassert(!mode64);
3288
3289 putIReg(rd, binop(Iop_Or32,
3290 binop(Iop_Shr32,
3291 binop(Iop_And32,
3292 getIReg(rt),
3293 mkU32(0xff000000)),
3294 mkU8(8)),
3295 binop(Iop_Shr32,
3296 binop(Iop_And32,
3297 getIReg(rt),
3298 mkU32(0x00ff0000)),
3299 mkU8(16))));
3300 break;
3301 }
3302 case 0x1E: { /* PRECEU.PH.QBLA */
3303 DIP("preceu.ph.qbla r%d, r%d", rd, rt);
3304 vassert(!mode64);
3305
3306 putIReg(rd, binop(Iop_Or32,
3307 binop(Iop_Shr32,
3308 binop(Iop_And32,
3309 getIReg(rt),
3310 mkU32(0xff000000)),
3311 mkU8(8)),
3312 binop(Iop_Shr32,
3313 binop(Iop_And32,
3314 getIReg(rt),
3315 mkU32(0x0000ff00)),
3316 mkU8(8))));
3317 break;
3318 }
3319 case 0x1D: { /* PRECEU.PH.QBR */
3320 DIP("preceu.ph.qbr r%d, r%d", rd, rt);
3321 vassert(!mode64);
3322
3323 putIReg(rd, binop(Iop_Or32,
3324 binop(Iop_Shl32,
3325 binop(Iop_And32,
3326 getIReg(rt),
3327 mkU32(0x0000ff00)),
3328 mkU8(8)),
3329 binop(Iop_And32,
3330 getIReg(rt),
3331 mkU32(0x000000ff))));
3332 break;
3333 }
3334 case 0x1F: { /* PRECEU.PH.QBRA */
3335 DIP("preceu.ph.qbra r%d, r%d", rd, rt);
3336 vassert(!mode64);
3337
3338 putIReg(rd, binop(Iop_Or32,
3339 binop(Iop_And32,
3340 getIReg(rt),
3341 mkU32(0x00ff0000)),
3342 binop(Iop_And32,
3343 getIReg(rt),
3344 mkU32(0x000000ff))));
3345 break;
3346 }
3347 default:
3348 return -1;
3349 }
3350 break; /* end of ABSQ_S.PH */
3351 }
3352 case 0x38: { /* EXTR.W */
3353 switch(sa) {
3354 case 0x0: { /* EXTR.W */
3355 DIP("extr.w r%d, ac%d, %d", rt, ac, rs);
3356 vassert(!mode64);
3357 t0 = newTemp(Ity_I64);
3358 t1 = newTemp(Ity_I64);
3359 t2 = newTemp(Ity_I32);
dejanj781f1bd2013-10-23 14:05:15 +00003360 t3 = newTemp(Ity_I1);
3361 t4 = newTemp(Ity_I1);
3362 t5 = newTemp(Ity_I1);
3363 t6 = newTemp(Ity_I1);
3364 t7 = newTemp(Ity_I32);
3365 t8 = newTemp(Ity_I64);
3366 t9 = newTemp(Ity_I64);
3367 t10 = newTemp(Ity_I1);
3368 t11 = newTemp(Ity_I1);
3369 t12 = newTemp(Ity_I1);
3370 t13 = newTemp(Ity_I1);
3371 t14 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +00003372
3373 assign(t0, getAcc(ac));
dejanj781f1bd2013-10-23 14:05:15 +00003374 if (0 == rs) {
3375 assign(t1, mkexpr(t0));
3376 } else {
3377 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
3378 }
3379 /* Check if bits 63..31 of the result in t1 aren't 0. */
3380 assign(t3, binop(Iop_CmpNE32,
3381 unop(Iop_64HIto32,
3382 mkexpr(t1)),
3383 mkU32(0)));
3384 assign(t4, binop(Iop_CmpNE32,
3385 binop(Iop_And32,
3386 unop(Iop_64to32,
3387 mkexpr(t1)),
3388 mkU32(0x80000000)),
3389 mkU32(0)));
3390 /* Check if bits 63..31 of the result in t1 aren't
3391 0x1ffffffff. */
3392 assign(t5, binop(Iop_CmpNE32,
3393 unop(Iop_64HIto32,
3394 mkexpr(t1)),
3395 mkU32(0xffffffff)));
3396 assign(t6, binop(Iop_CmpNE32,
3397 binop(Iop_And32,
3398 unop(Iop_64to32,
3399 mkexpr(t1)),
3400 mkU32(0x80000000)),
3401 mkU32(0x80000000)));
3402 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
3403 control register. */
3404 assign(t7, binop(Iop_And32,
3405 binop(Iop_Or32,
3406 unop(Iop_1Sto32, mkexpr(t3)),
3407 unop(Iop_1Sto32, mkexpr(t4))),
3408 binop(Iop_Or32,
3409 unop(Iop_1Sto32, mkexpr(t5)),
3410 unop(Iop_1Sto32, mkexpr(t6)))));
3411 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
3412 mkexpr(t7),
3413 mkU32(0)),
3414 binop(Iop_Or32,
3415 getDSPControl(),
3416 mkU32(0x00800000)),
3417 getDSPControl()));
dejanjc3fee0d2013-07-25 09:08:03 +00003418
dejanj781f1bd2013-10-23 14:05:15 +00003419 /* If the last discarded bit is 1, there would be carry
3420 when rounding, otherwise there wouldn't. We use that
3421 fact and just add the value of the last discarded bit
3422 to the least sifgnificant bit of the shifted value
3423 from acc. */
3424 if (0 == rs) {
3425 assign(t8, mkU64(0x0ULL));
3426 } else {
3427 assign(t8, binop(Iop_And64,
3428 binop(Iop_Shr64,
3429 mkexpr(t0),
3430 mkU8(rs-1)),
3431 mkU64(0x1ULL)));
3432 }
3433 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
dejanjc3fee0d2013-07-25 09:08:03 +00003434
dejanj781f1bd2013-10-23 14:05:15 +00003435 /* Repeat previous steps for the rounded value. */
3436 assign(t10, binop(Iop_CmpNE32,
3437 unop(Iop_64HIto32,
3438 mkexpr(t9)),
3439 mkU32(0)));
3440 assign(t11, binop(Iop_CmpNE32,
3441 binop(Iop_And32,
3442 unop(Iop_64to32,
3443 mkexpr(t9)),
3444 mkU32(0x80000000)),
3445 mkU32(0)));
dejanjc3fee0d2013-07-25 09:08:03 +00003446
dejanj781f1bd2013-10-23 14:05:15 +00003447 assign(t12, binop(Iop_CmpNE32,
3448 unop(Iop_64HIto32,
3449 mkexpr(t9)),
3450 mkU32(0xffffffff)));
3451 assign(t13, binop(Iop_CmpNE32,
3452 binop(Iop_And32,
3453 unop(Iop_64to32,
3454 mkexpr(t9)),
3455 mkU32(0x80000000)),
3456 mkU32(0x80000000)));
3457
3458 assign(t14, binop(Iop_And32,
3459 binop(Iop_Or32,
3460 unop(Iop_1Sto32, mkexpr(t10)),
3461 unop(Iop_1Sto32, mkexpr(t11))),
3462 binop(Iop_Or32,
3463 unop(Iop_1Sto32, mkexpr(t12)),
3464 unop(Iop_1Sto32, mkexpr(t13)))));
3465 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
3466 mkexpr(t14),
3467 mkU32(0)),
3468 binop(Iop_Or32,
3469 getDSPControl(),
3470 mkU32(0x00800000)),
3471 getDSPControl()));
3472 if (0 == rs) {
3473 putIReg(rt, unop(Iop_64to32, mkexpr(t0)));
3474 } else {
3475 putIReg(rt, unop(Iop_64to32, mkexpr(t1)));
3476 }
dejanjc3fee0d2013-07-25 09:08:03 +00003477 break;
3478 }
3479 case 0x1: { /* EXTRV.W */
3480 DIP("extrv.w r%d, ac%d, r%d", rt, ac, rs);
3481 vassert(!mode64);
3482 t0 = newTemp(Ity_I64);
3483 t1 = newTemp(Ity_I64);
3484 t2 = newTemp(Ity_I32);
dejanj781f1bd2013-10-23 14:05:15 +00003485 t3 = newTemp(Ity_I1);
dejanjc3fee0d2013-07-25 09:08:03 +00003486 t4 = newTemp(Ity_I1);
dejanj781f1bd2013-10-23 14:05:15 +00003487 t5 = newTemp(Ity_I1);
3488 t6 = newTemp(Ity_I1);
3489 t7 = newTemp(Ity_I32);
3490 t8 = newTemp(Ity_I64);
3491 t9 = newTemp(Ity_I64);
3492 t10 = newTemp(Ity_I1);
3493 t11 = newTemp(Ity_I1);
3494 t12 = newTemp(Ity_I1);
3495 t13 = newTemp(Ity_I1);
3496 t14 = newTemp(Ity_I32);
3497 t15 = newTemp(Ity_I8);
dejanjc3fee0d2013-07-25 09:08:03 +00003498
dejanj781f1bd2013-10-23 14:05:15 +00003499 assign(t15, unop(Iop_32to8,
3500 binop(Iop_And32,
3501 getIReg(rs),
3502 mkU32(0x1f))));
dejanjc3fee0d2013-07-25 09:08:03 +00003503 assign(t0, getAcc(ac));
dejanj781f1bd2013-10-23 14:05:15 +00003504 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));
3505 putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
3506 unop(Iop_8Uto32,
3507 mkexpr(t15)),
3508 mkU32(0)),
3509 unop(Iop_64to32, mkexpr(t0)),
3510 unop(Iop_64to32, mkexpr(t1))));
dejanjc3fee0d2013-07-25 09:08:03 +00003511
dejanj781f1bd2013-10-23 14:05:15 +00003512 /* Check if bits 63..31 of the result in t1 aren't 0. */
3513 assign(t3, binop(Iop_CmpNE32,
3514 unop(Iop_64HIto32,
3515 mkexpr(t1)),
3516 mkU32(0)));
dejanjc3fee0d2013-07-25 09:08:03 +00003517 assign(t4, binop(Iop_CmpNE32,
dejanj781f1bd2013-10-23 14:05:15 +00003518 binop(Iop_And32,
3519 unop(Iop_64to32,
3520 mkexpr(t1)),
3521 mkU32(0x80000000)),
3522 mkU32(0)));
3523 /* Check if bits 63..31 of the result in t1 aren't
3524 0x1ffffffff. */
3525 assign(t5, binop(Iop_CmpNE32,
3526 unop(Iop_64HIto32,
3527 mkexpr(t1)),
dejanjc3fee0d2013-07-25 09:08:03 +00003528 mkU32(0xffffffff)));
dejanj781f1bd2013-10-23 14:05:15 +00003529 assign(t6, binop(Iop_CmpNE32,
3530 binop(Iop_And32,
3531 unop(Iop_64to32,
3532 mkexpr(t1)),
3533 mkU32(0x80000000)),
3534 mkU32(0x80000000)));
3535 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
3536 control register. */
3537 assign(t7, binop(Iop_And32,
3538 binop(Iop_Or32,
3539 unop(Iop_1Sto32, mkexpr(t3)),
3540 unop(Iop_1Sto32, mkexpr(t4))),
3541 binop(Iop_Or32,
3542 unop(Iop_1Sto32, mkexpr(t5)),
3543 unop(Iop_1Sto32, mkexpr(t6)))));
dejanjc3fee0d2013-07-25 09:08:03 +00003544 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
dejanj781f1bd2013-10-23 14:05:15 +00003545 mkexpr(t7),
3546 mkU32(0)),
3547 binop(Iop_Or32,
3548 getDSPControl(),
3549 mkU32(0x00800000)),
3550 getDSPControl()));
3551
3552 /* If the last discarded bit is 1, there would be carry
3553 when rounding, otherwise there wouldn't. We use that
3554 fact and just add the value of the last discarded bit
3555 to the least sifgnificant bit of the shifted value
3556 from acc. */
3557 assign(t8,
3558 IRExpr_ITE(binop(Iop_CmpEQ32,
3559 unop(Iop_8Uto32,
3560 mkexpr(t15)),
3561 mkU32(0)),
3562 mkU64(0x0ULL),
3563 binop(Iop_And64,
3564 binop(Iop_Shr64,
3565 mkexpr(t0),
3566 unop(Iop_32to8,
3567 binop(Iop_Sub32,
3568 unop(Iop_8Uto32,
3569 mkexpr(t15)),
3570 mkU32(1)))),
3571 mkU64(0x1ULL))));
3572
3573 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
3574
3575 /* Repeat previous steps for the rounded value. */
3576 assign(t10, binop(Iop_CmpNE32,
3577 unop(Iop_64HIto32,
3578 mkexpr(t9)),
3579 mkU32(0)));
3580 assign(t11, binop(Iop_CmpNE32,
3581 binop(Iop_And32,
3582 unop(Iop_64to32,
3583 mkexpr(t9)),
3584 mkU32(0x80000000)),
3585 mkU32(0)));
3586
3587 assign(t12, binop(Iop_CmpNE32,
3588 unop(Iop_64HIto32,
3589 mkexpr(t9)),
3590 mkU32(0xffffffff)));
3591 assign(t13, binop(Iop_CmpNE32,
3592 binop(Iop_And32,
3593 unop(Iop_64to32,
3594 mkexpr(t9)),
3595 mkU32(0x80000000)),
3596 mkU32(0x80000000)));
3597
3598 assign(t14, binop(Iop_And32,
3599 binop(Iop_Or32,
3600 unop(Iop_1Sto32, mkexpr(t10)),
3601 unop(Iop_1Sto32, mkexpr(t11))),
3602 binop(Iop_Or32,
3603 unop(Iop_1Sto32, mkexpr(t12)),
3604 unop(Iop_1Sto32, mkexpr(t13)))));
3605 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
3606 mkexpr(t14),
3607 mkU32(0)),
3608 binop(Iop_Or32,
3609 getDSPControl(),
3610 mkU32(0x00800000)),
3611 getDSPControl()));
dejanjc3fee0d2013-07-25 09:08:03 +00003612 break;
3613 }
3614 case 0x2: { /* EXTP */
3615 DIP("extp r%d, ac%d, %d", rt, ac, rs);
3616 vassert(!mode64);
3617 t0 = newTemp(Ity_I64);
3618 t1 = newTemp(Ity_I32);
3619 t2 = newTemp(Ity_I1);
3620 t3 = newTemp(Ity_I1);
3621 t4 = newTemp(Ity_I8);
3622 t5 = newTemp(Ity_I64);
3623 t6 = newTemp(Ity_I64);
3624 t7 = newTemp(Ity_I32);
3625
3626 assign(t0, getAcc(ac));
3627 /* Extract pos field of DSPControl register. */
3628 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
3629
3630 /* Check if (pos - size) >= 0 [size <= pos]
3631 if (pos < size)
3632 put 1 to EFI field of DSPControl register
3633 else
3634 extract bits from acc and put 0 to EFI field of
3635 DSPCtrl */
3636 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));
3637
3638 putDSPControl(IRExpr_ITE(mkexpr(t2),
3639 binop(Iop_Or32,
3640 binop(Iop_And32,
3641 getDSPControl(),
3642 mkU32(0xffffbfff)),
3643 mkU32(0x4000)),
3644 binop(Iop_And32,
3645 getDSPControl(),
3646 mkU32(0xffffbfff))));
3647
3648 /* If pos <= 31, shift right the value from the acc
3649 (pos-size) times and take (size+1) bits from the least
3650 significant positions. Otherwise, shift left the value
3651 (63-pos) times, take (size+1) bits from the most
3652 significant positions and shift right (31-size) times.*/
3653 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
3654
3655 assign(t4,
3656 IRExpr_ITE(mkexpr(t3),
3657 unop(Iop_32to8,
3658 binop(Iop_Sub32,
3659 mkexpr(t1), mkU32(rs))),
3660 unop(Iop_32to8,
3661 binop(Iop_Sub32,
3662 mkU32(63), mkexpr(t1)))));
3663
3664 assign(t5, IRExpr_ITE(mkexpr(t3),
3665 binop(Iop_Shr64,
3666 mkexpr(t0), mkexpr(t4)),
3667 binop(Iop_Shl64,
3668 mkexpr(t0), mkexpr(t4))));
3669
3670 /* t6 holds a mask for bit extraction */
3671 assign(t6,
3672 IRExpr_ITE(mkexpr(t3),
3673 unop(Iop_Not64,
3674 binop(Iop_Shl64,
3675 mkU64(0xffffffffffffffffULL),
3676 mkU8(rs+1))),
3677 unop(Iop_Not64,
3678 binop(Iop_Shr64,
3679 mkU64(0xffffffffffffffffULL),
3680 mkU8(rs+1)))));
3681
3682 assign(t7, IRExpr_ITE(mkexpr(t3),
3683 unop(Iop_64to32,
3684 binop(Iop_And64,
3685 mkexpr(t5),
3686 mkexpr(t6))),
3687 binop(Iop_Shr32,
3688 unop(Iop_64HIto32,
3689 binop(Iop_And64,
3690 mkexpr(t5),
3691 mkexpr(t6))),
3692 mkU8(31-rs))));
3693
3694 putIReg(rt, mkexpr(t7));
3695 break;
3696 }
3697 case 0x3: { /* EXTPV */
3698 DIP("extpv r%d, ac%d, r%d", rt, ac, rs);
3699 vassert(!mode64);
3700 t0 = newTemp(Ity_I64);
3701 t1 = newTemp(Ity_I32);
3702 t2 = newTemp(Ity_I1);
3703 t3 = newTemp(Ity_I1);
3704 t4 = newTemp(Ity_I8);
3705 t5 = newTemp(Ity_I64);
3706 t6 = newTemp(Ity_I64);
3707 t7 = newTemp(Ity_I32);
3708 t8 = newTemp(Ity_I32);
3709
3710 assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
3711 assign(t0, getAcc(ac));
3712 /* Extract pos field of DSPControl register. */
3713 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
3714
3715 /* Check if (pos - size) >= 0 [size <= pos]
3716 if (pos < size)
3717 put 1 to EFI field of DSPControl register
3718 else
3719 extract bits from acc and put 0 to EFI field of
3720 DSPCtrl */
3721 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));
3722
3723 putDSPControl(IRExpr_ITE(mkexpr(t2),
3724 binop(Iop_Or32,
3725 binop(Iop_And32,
3726 getDSPControl(),
3727 mkU32(0xffffbfff)),
3728 mkU32(0x4000)),
3729 binop(Iop_And32,
3730 getDSPControl(),
3731 mkU32(0xffffbfff))));
3732
3733 /* If pos <= 31, shift right the value from the acc
3734 (pos-size) times and take (size+1) bits from the least
3735 significant positions. Otherwise, shift left the value
3736 (63-pos) times, take (size+1) bits from the most
3737 significant positions and shift right (31-size)
3738 times. */
3739 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
3740
3741 assign(t4,
3742 IRExpr_ITE(mkexpr(t3),
3743 unop(Iop_32to8,
3744 binop(Iop_Sub32,
3745 mkexpr(t1), mkexpr(t8))),
3746 unop(Iop_32to8,
3747 binop(Iop_Sub32,
3748 mkU32(63), mkexpr(t1)))));
3749
3750 assign(t5, IRExpr_ITE(mkexpr(t3),
3751 binop(Iop_Shr64,
3752 mkexpr(t0), mkexpr(t4)),
3753 binop(Iop_Shl64,
3754 mkexpr(t0), mkexpr(t4))));
3755
3756 /* t6 holds a mask for bit extraction. */
3757 assign(t6,
3758 IRExpr_ITE(mkexpr(t3),
3759 unop(Iop_Not64,
3760 binop(Iop_Shl64,
3761 mkU64(0xffffffffffffffffULL),
3762 unop(Iop_32to8,
3763 binop(Iop_Add32,
3764 mkexpr(t8),
3765 mkU32(1))))),
3766 unop(Iop_Not64,
3767 binop(Iop_Shr64,
3768 mkU64(0xffffffffffffffffULL),
3769 unop(Iop_32to8,
3770 binop(Iop_Add32,
3771 mkexpr(t8),
3772 mkU32(1)))))));
3773
3774 assign(t7, IRExpr_ITE(mkexpr(t3),
3775 unop(Iop_64to32,
3776 binop(Iop_And64,
3777 mkexpr(t5),
3778 mkexpr(t6))),
3779 binop(Iop_Shr32,
3780 unop(Iop_64HIto32,
3781 binop(Iop_And64,
3782 mkexpr(t5),
3783 mkexpr(t6))),
3784 unop(Iop_32to8,
3785 binop(Iop_Sub32,
3786 mkU32(31),
3787 mkexpr(t8))))));
3788
3789 putIReg(rt, mkexpr(t7));
3790 break;
3791 }
3792 case 0x4: { /* EXTR_R.W */
3793 DIP("extr_r.w r%d, ac%d, %d", rt, ac, rs);
3794 vassert(!mode64);
3795 t0 = newTemp(Ity_I64);
3796 t1 = newTemp(Ity_I64);
3797 t2 = newTemp(Ity_I32);
dejanj781f1bd2013-10-23 14:05:15 +00003798 t3 = newTemp(Ity_I1);
3799 t4 = newTemp(Ity_I1);
3800 t5 = newTemp(Ity_I1);
3801 t6 = newTemp(Ity_I1);
3802 t7 = newTemp(Ity_I32);
3803 t8 = newTemp(Ity_I64);
3804 t9 = newTemp(Ity_I64);
3805 t10 = newTemp(Ity_I1);
3806 t11 = newTemp(Ity_I1);
3807 t12 = newTemp(Ity_I1);
3808 t13 = newTemp(Ity_I1);
3809 t14 = newTemp(Ity_I32);
3810 t15 = newTemp(Ity_I64);
3811 t16 = newTemp(Ity_I1);
dejanjc3fee0d2013-07-25 09:08:03 +00003812
3813 assign(t0, getAcc(ac));
dejanj781f1bd2013-10-23 14:05:15 +00003814 assign(t16, binop(Iop_CmpEQ32,
3815 mkU32(rs),
3816 mkU32(0)));
3817 assign(t1, IRExpr_ITE(mkexpr(t16),
3818 mkexpr(t0),
3819 binop(Iop_Sar64,
3820 mkexpr(t0),
3821 mkU8(rs))));
3822 /* If the last discarded bit is 1, there would be carry
3823 when rounding, otherwise there wouldn't. We use that
3824 fact and just add the value of the last discarded bit
3825 to the least significant bit of the shifted value
3826 from acc. */
3827 assign(t15, binop(Iop_Shr64,
3828 mkexpr(t0),
3829 unop(Iop_32to8,
3830 binop(Iop_Sub32,
3831 binop(Iop_And32,
3832 mkU32(rs),
3833 mkU32(0x1f)),
3834 mkU32(1)))));
dejanjc3fee0d2013-07-25 09:08:03 +00003835
dejanj781f1bd2013-10-23 14:05:15 +00003836 assign(t8,
3837 IRExpr_ITE(mkexpr(t16),
3838 mkU64(0x0ULL),
3839 binop(Iop_And64,
3840 mkexpr(t15),
3841 mkU64(0x0000000000000001ULL))));
3842 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
3843 putIReg(rt, unop(Iop_64to32, mkexpr(t9)));
dejanjc3fee0d2013-07-25 09:08:03 +00003844
dejanj781f1bd2013-10-23 14:05:15 +00003845 /* Check if bits 63..31 of the result in t1 aren't 0. */
3846 assign(t3, binop(Iop_CmpNE32,
3847 unop(Iop_64HIto32,
3848 mkexpr(t1)),
3849 mkU32(0)));
3850 assign(t4, binop(Iop_CmpNE32,
3851 binop(Iop_And32,
3852 unop(Iop_64to32,
3853 mkexpr(t1)),
3854 mkU32(0x80000000)),
3855 mkU32(0)));
dejanjc3fee0d2013-07-25 09:08:03 +00003856
dejanj781f1bd2013-10-23 14:05:15 +00003857 /* Check if bits 63..31 of the result in t1 aren't
3858 0x1ffffffff. */
3859 assign(t5, binop(Iop_CmpNE32,
3860 unop(Iop_64HIto32,
3861 mkexpr(t1)),
3862 mkU32(0xffffffff)));
3863 assign(t6, binop(Iop_CmpNE32,
3864 binop(Iop_And32,
3865 unop(Iop_64to32,
3866 mkexpr(t1)),
3867 mkU32(0x80000000)),
3868 mkU32(0x80000000)));
3869 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
3870 control register. */
3871 assign(t7, binop(Iop_And32,
3872 binop(Iop_Or32,
3873 unop(Iop_1Sto32, mkexpr(t3)),
3874 unop(Iop_1Sto32, mkexpr(t4))),
3875 binop(Iop_Or32,
3876 unop(Iop_1Sto32, mkexpr(t5)),
3877 unop(Iop_1Sto32, mkexpr(t6)))));
3878 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
3879 mkexpr(t7),
3880 mkU32(0)),
3881 binop(Iop_Or32,
3882 getDSPControl(),
3883 mkU32(0x00800000)),
3884 getDSPControl()));
dejanjc3fee0d2013-07-25 09:08:03 +00003885
dejanj781f1bd2013-10-23 14:05:15 +00003886 /* Repeat previous steps for the rounded value. */
3887 assign(t10, binop(Iop_CmpNE32,
3888 unop(Iop_64HIto32,
3889 mkexpr(t9)),
3890 mkU32(0)));
3891 assign(t11, binop(Iop_CmpNE32,
3892 binop(Iop_And32,
3893 unop(Iop_64to32,
3894 mkexpr(t9)),
3895 mkU32(0x80000000)),
3896 mkU32(0)));
dejanjc3fee0d2013-07-25 09:08:03 +00003897
dejanj781f1bd2013-10-23 14:05:15 +00003898 assign(t12, binop(Iop_CmpNE32,
3899 unop(Iop_64HIto32,
3900 mkexpr(t9)),
3901 mkU32(0xffffffff)));
3902 assign(t13, binop(Iop_CmpNE32,
3903 binop(Iop_And32,
3904 unop(Iop_64to32,
3905 mkexpr(t9)),
3906 mkU32(0x80000000)),
3907 mkU32(0x80000000)));
3908
3909 assign(t14, binop(Iop_And32,
3910 binop(Iop_Or32,
3911 unop(Iop_1Sto32, mkexpr(t10)),
3912 unop(Iop_1Sto32, mkexpr(t11))),
3913 binop(Iop_Or32,
3914 unop(Iop_1Sto32, mkexpr(t12)),
3915 unop(Iop_1Sto32, mkexpr(t13)))));
3916 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
3917 mkexpr(t14),
3918 mkU32(0)),
3919 binop(Iop_Or32,
3920 getDSPControl(),
3921 mkU32(0x00800000)),
3922 getDSPControl()));
dejanjc3fee0d2013-07-25 09:08:03 +00003923 break;
3924 }
3925 case 0x5: { /* EXTRV_R.W */
3926 DIP("extrv_r.w r%d, ac%d, r%d", rt, ac, rs);
3927 vassert(!mode64);
3928 t0 = newTemp(Ity_I64);
3929 t1 = newTemp(Ity_I64);
3930 t2 = newTemp(Ity_I32);
dejanj781f1bd2013-10-23 14:05:15 +00003931 t3 = newTemp(Ity_I1);
3932 t4 = newTemp(Ity_I1);
3933 t5 = newTemp(Ity_I1);
3934 t6 = newTemp(Ity_I1);
3935 t7 = newTemp(Ity_I32);
3936 t8 = newTemp(Ity_I64);
3937 t9 = newTemp(Ity_I64);
3938 t10 = newTemp(Ity_I1);
3939 t11 = newTemp(Ity_I1);
3940 t12 = newTemp(Ity_I1);
3941 t13 = newTemp(Ity_I1);
3942 t14 = newTemp(Ity_I32);
3943 t15 = newTemp(Ity_I8);
dejanjc3fee0d2013-07-25 09:08:03 +00003944
dejanj781f1bd2013-10-23 14:05:15 +00003945 assign(t15, unop(Iop_32to8,
3946 binop(Iop_And32,
3947 getIReg(rs),
3948 mkU32(0x1f))));
dejanjc3fee0d2013-07-25 09:08:03 +00003949 assign(t0, getAcc(ac));
dejanj781f1bd2013-10-23 14:05:15 +00003950 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));
dejanjc3fee0d2013-07-25 09:08:03 +00003951
dejanj781f1bd2013-10-23 14:05:15 +00003952 /* Check if bits 63..31 of the result in t1 aren't 0. */
3953 assign(t3, binop(Iop_CmpNE32,
3954 unop(Iop_64HIto32,
3955 mkexpr(t1)),
3956 mkU32(0)));
3957 assign(t4, binop(Iop_CmpNE32,
3958 binop(Iop_And32,
3959 unop(Iop_64to32,
3960 mkexpr(t1)),
3961 mkU32(0x80000000)),
3962 mkU32(0)));
3963 /* Check if bits 63..31 of the result in t1 aren't
3964 0x1ffffffff. */
3965 assign(t5, binop(Iop_CmpNE32,
3966 unop(Iop_64HIto32,
3967 mkexpr(t1)),
3968 mkU32(0xffffffff)));
3969 assign(t6, binop(Iop_CmpNE32,
3970 binop(Iop_And32,
3971 unop(Iop_64to32,
3972 mkexpr(t1)),
3973 mkU32(0x80000000)),
3974 mkU32(0x80000000)));
3975 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
3976 control register. */
3977 assign(t7, binop(Iop_And32,
3978 binop(Iop_Or32,
3979 unop(Iop_1Sto32, mkexpr(t3)),
3980 unop(Iop_1Sto32, mkexpr(t4))),
3981 binop(Iop_Or32,
3982 unop(Iop_1Sto32, mkexpr(t5)),
3983 unop(Iop_1Sto32, mkexpr(t6)))));
3984 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
3985 mkexpr(t7),
3986 mkU32(0)),
3987 binop(Iop_Or32,
3988 getDSPControl(),
3989 mkU32(0x00800000)),
3990 getDSPControl()));
dejanjc3fee0d2013-07-25 09:08:03 +00003991
dejanjc3fee0d2013-07-25 09:08:03 +00003992 /* If the last discarded bit is 1, there would be carry
3993 when rounding, otherwise there wouldn't. We use that
dejanj781f1bd2013-10-23 14:05:15 +00003994 fact and just add the value of the last discarded bit
3995 to the least sifgnificant bit of the shifted value
3996 from acc. */
3997 assign(t8,
3998 IRExpr_ITE(binop(Iop_CmpEQ32,
3999 unop(Iop_8Uto32,
4000 mkexpr(t15)),
4001 mkU32(0)),
4002 mkU64(0x0ULL),
4003 binop(Iop_And64,
4004 binop(Iop_Shr64,
4005 mkexpr(t0),
4006 unop(Iop_32to8,
4007 binop(Iop_Sub32,
4008 unop(Iop_8Uto32,
4009 mkexpr(t15)),
4010 mkU32(1)))),
4011 mkU64(0x1ULL))));
dejanjc3fee0d2013-07-25 09:08:03 +00004012
dejanj781f1bd2013-10-23 14:05:15 +00004013 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
4014 /* Put rounded value in destination register. */
4015 putIReg(rt, unop(Iop_64to32, mkexpr(t9)));
dejanjc3fee0d2013-07-25 09:08:03 +00004016
dejanj781f1bd2013-10-23 14:05:15 +00004017 /* Repeat previous steps for the rounded value. */
4018 assign(t10, binop(Iop_CmpNE32,
4019 unop(Iop_64HIto32,
4020 mkexpr(t9)),
4021 mkU32(0)));
4022 assign(t11, binop(Iop_CmpNE32,
4023 binop(Iop_And32,
4024 unop(Iop_64to32,
4025 mkexpr(t9)),
4026 mkU32(0x80000000)),
4027 mkU32(0)));
4028
4029 assign(t12, binop(Iop_CmpNE32,
4030 unop(Iop_64HIto32,
4031 mkexpr(t9)),
4032 mkU32(0xffffffff)));
4033 assign(t13, binop(Iop_CmpNE32,
4034 binop(Iop_And32,
4035 unop(Iop_64to32,
4036 mkexpr(t9)),
4037 mkU32(0x80000000)),
4038 mkU32(0x80000000)));
4039
4040 assign(t14, binop(Iop_And32,
4041 binop(Iop_Or32,
4042 unop(Iop_1Sto32, mkexpr(t10)),
4043 unop(Iop_1Sto32, mkexpr(t11))),
4044 binop(Iop_Or32,
4045 unop(Iop_1Sto32, mkexpr(t12)),
4046 unop(Iop_1Sto32, mkexpr(t13)))));
4047 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4048 mkexpr(t14),
4049 mkU32(0)),
4050 binop(Iop_Or32,
4051 getDSPControl(),
4052 mkU32(0x00800000)),
4053 getDSPControl()));
dejanjc3fee0d2013-07-25 09:08:03 +00004054 break;
4055 }
4056 case 0x6: { /* EXTR_RS.W */
4057 DIP("extr_rs.w r%d, ac%d, %d", rt, ac, rs);
4058 vassert(!mode64);
4059 t0 = newTemp(Ity_I64);
4060 t1 = newTemp(Ity_I64);
dejanj781f1bd2013-10-23 14:05:15 +00004061 t2 = newTemp(Ity_I32);
4062 t3 = newTemp(Ity_I1);
4063 t4 = newTemp(Ity_I1);
4064 t5 = newTemp(Ity_I1);
4065 t6 = newTemp(Ity_I1);
4066 t7 = newTemp(Ity_I32);
4067 t8 = newTemp(Ity_I64);
4068 t9 = newTemp(Ity_I64);
4069 t10 = newTemp(Ity_I1);
4070 t11 = newTemp(Ity_I1);
4071 t12 = newTemp(Ity_I1);
4072 t13 = newTemp(Ity_I1);
4073 t14 = newTemp(Ity_I32);
4074 t16 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +00004075
dejanj781f1bd2013-10-23 14:05:15 +00004076 assign(t0, getAcc(ac));
4077 if (0 == rs) {
4078 assign(t1, mkexpr(t0));
4079 } else {
dejanjc3fee0d2013-07-25 09:08:03 +00004080 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
dejanj781f1bd2013-10-23 14:05:15 +00004081 }
4082
4083 /* Check if bits 63..31 of the result in t1 aren't 0. */
4084 assign(t3, binop(Iop_CmpNE32,
4085 unop(Iop_64HIto32,
4086 mkexpr(t1)),
4087 mkU32(0)));
4088 assign(t4, binop(Iop_CmpNE32,
4089 binop(Iop_And32,
4090 unop(Iop_64to32,
4091 mkexpr(t1)),
4092 mkU32(0x80000000)),
4093 mkU32(0)));
4094 /* Check if bits 63..31 of the result in t1 aren't
4095 0x1ffffffff. */
4096 assign(t5, binop(Iop_CmpNE32,
4097 unop(Iop_64HIto32,
4098 mkexpr(t1)),
4099 mkU32(0xffffffff)));
4100 assign(t6, binop(Iop_CmpNE32,
4101 binop(Iop_And32,
4102 unop(Iop_64to32,
4103 mkexpr(t1)),
4104 mkU32(0x80000000)),
4105 mkU32(0x80000000)));
4106 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
4107 control register. */
4108 assign(t7, binop(Iop_And32,
4109 binop(Iop_Or32,
4110 unop(Iop_1Sto32, mkexpr(t3)),
4111 unop(Iop_1Sto32, mkexpr(t4))),
4112 binop(Iop_Or32,
4113 unop(Iop_1Sto32, mkexpr(t5)),
4114 unop(Iop_1Sto32, mkexpr(t6)))));
4115 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4116 mkexpr(t7),
4117 mkU32(0)),
dejanjc3fee0d2013-07-25 09:08:03 +00004118 binop(Iop_Or32,
4119 getDSPControl(),
4120 mkU32(0x00800000)),
4121 getDSPControl()));
dejanj781f1bd2013-10-23 14:05:15 +00004122
4123 /* If the last discarded bit is 1, there would be carry
4124 when rounding, otherwise there wouldn't. We use that
4125 fact and just add the value of the last discarded bit
4126 to the least sifgnificant bit of the shifted value
4127 from acc. */
4128 if (0 == rs) {
4129 assign(t8, mkU64(0x0ULL));
dejanjc3fee0d2013-07-25 09:08:03 +00004130 } else {
dejanj781f1bd2013-10-23 14:05:15 +00004131 assign(t8, binop(Iop_And64,
4132 binop(Iop_Shr64,
4133 mkexpr(t0),
4134 mkU8(rs-1)),
4135 mkU64(0x1ULL)));
dejanjc3fee0d2013-07-25 09:08:03 +00004136 }
dejanj781f1bd2013-10-23 14:05:15 +00004137
4138 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
4139
4140 /* Repeat previous steps for the rounded value. */
4141 assign(t10, binop(Iop_CmpNE32,
4142 unop(Iop_64HIto32,
4143 mkexpr(t9)),
4144 mkU32(0)));
4145 assign(t11, binop(Iop_CmpNE32,
4146 binop(Iop_And32,
4147 unop(Iop_64to32,
4148 mkexpr(t9)),
4149 mkU32(0x80000000)),
4150 mkU32(0)));
4151
4152 assign(t12, binop(Iop_CmpNE32,
4153 unop(Iop_64HIto32,
4154 mkexpr(t9)),
4155 mkU32(0xffffffff)));
4156 assign(t13, binop(Iop_CmpNE32,
4157 binop(Iop_And32,
4158 unop(Iop_64to32,
4159 mkexpr(t9)),
4160 mkU32(0x80000000)),
4161 mkU32(0x80000000)));
4162
4163 assign(t14, binop(Iop_And32,
4164 binop(Iop_Or32,
4165 unop(Iop_1Sto32, mkexpr(t10)),
4166 unop(Iop_1Sto32, mkexpr(t11))),
4167 binop(Iop_Or32,
4168 unop(Iop_1Sto32, mkexpr(t12)),
4169 unop(Iop_1Sto32, mkexpr(t13)))));
4170 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4171 mkexpr(t14),
4172 mkU32(0)),
4173 binop(Iop_Or32,
4174 getDSPControl(),
4175 mkU32(0x00800000)),
4176 getDSPControl()));
4177
4178 assign(t16, binop(Iop_And32,
4179 unop(Iop_64HIto32,
4180 mkexpr(t9)),
4181 mkU32(0x80000000)));
4182 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
4183 mkexpr(t14),
4184 mkU32(0)),
4185 IRExpr_ITE(binop(Iop_CmpEQ32,
4186 mkexpr(t16),
4187 mkU32(0)),
4188 mkU32(0x7fffffff),
4189 mkU32(0x80000000)),
4190 unop(Iop_64to32, mkexpr(t9))));
dejanjc3fee0d2013-07-25 09:08:03 +00004191 break;
4192 }
4193 case 0x7: { /* EXTRV_RS.W */
4194 DIP("extrv_rs.w r%d, ac%d, r%d", rt, ac, rs);
4195 vassert(!mode64);
4196 t0 = newTemp(Ity_I64);
4197 t1 = newTemp(Ity_I64);
4198 t2 = newTemp(Ity_I32);
dejanj781f1bd2013-10-23 14:05:15 +00004199 t3 = newTemp(Ity_I1);
4200 t4 = newTemp(Ity_I1);
4201 t5 = newTemp(Ity_I1);
4202 t6 = newTemp(Ity_I1);
dejanjc3fee0d2013-07-25 09:08:03 +00004203 t7 = newTemp(Ity_I32);
dejanj781f1bd2013-10-23 14:05:15 +00004204 t8 = newTemp(Ity_I64);
4205 t9 = newTemp(Ity_I64);
4206 t10 = newTemp(Ity_I1);
4207 t11 = newTemp(Ity_I1);
4208 t12 = newTemp(Ity_I1);
4209 t13 = newTemp(Ity_I1);
4210 t14 = newTemp(Ity_I32);
4211 t15 = newTemp(Ity_I32);
4212 t16 = newTemp(Ity_I32);
4213 t17 = newTemp(Ity_I1);
dejanjc3fee0d2013-07-25 09:08:03 +00004214
dejanj781f1bd2013-10-23 14:05:15 +00004215 assign(t15, binop(Iop_And32,
4216 getIReg(rs),
4217 mkU32(0x1f)));
4218 assign(t17, binop(Iop_CmpEQ32,
4219 mkexpr(t15),
4220 mkU32(0)));
dejanjc3fee0d2013-07-25 09:08:03 +00004221 assign(t0, getAcc(ac));
dejanj781f1bd2013-10-23 14:05:15 +00004222 assign(t1, IRExpr_ITE(mkexpr(t17),
4223 mkexpr(t0),
4224 binop(Iop_Sar64,
4225 mkexpr(t0),
4226 unop(Iop_32to8,
4227 mkexpr(t15)))));
dejanjc3fee0d2013-07-25 09:08:03 +00004228
dejanj781f1bd2013-10-23 14:05:15 +00004229 /* Check if bits 63..31 of the result in t1 aren't 0. */
4230 assign(t3, binop(Iop_CmpNE32,
4231 unop(Iop_64HIto32,
4232 mkexpr(t1)),
4233 mkU32(0)));
4234 assign(t4, binop(Iop_CmpNE32,
4235 binop(Iop_And32,
4236 unop(Iop_64to32,
4237 mkexpr(t1)),
4238 mkU32(0x80000000)),
4239 mkU32(0)));
4240 /* Check if bits 63..31 of the result in t1 aren't
4241 0x1ffffffff. */
4242 assign(t5, binop(Iop_CmpNE32,
4243 unop(Iop_64HIto32,
4244 mkexpr(t1)),
4245 mkU32(0xffffffff)));
4246 assign(t6, binop(Iop_CmpNE32,
4247 binop(Iop_And32,
4248 unop(Iop_64to32,
4249 mkexpr(t1)),
4250 mkU32(0x80000000)),
4251 mkU32(0x80000000)));
4252 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
4253 control register. */
4254 assign(t7, binop(Iop_And32,
4255 binop(Iop_Or32,
4256 unop(Iop_1Sto32, mkexpr(t3)),
4257 unop(Iop_1Sto32, mkexpr(t4))),
4258 binop(Iop_Or32,
4259 unop(Iop_1Sto32, mkexpr(t5)),
4260 unop(Iop_1Sto32, mkexpr(t6)))));
4261 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4262 mkexpr(t7),
4263 mkU32(0)),
4264 binop(Iop_Or32,
4265 getDSPControl(),
4266 mkU32(0x00800000)),
4267 getDSPControl()));
dejanjc3fee0d2013-07-25 09:08:03 +00004268
dejanjc3fee0d2013-07-25 09:08:03 +00004269 /* If the last discarded bit is 1, there would be carry
4270 when rounding, otherwise there wouldn't. We use that
dejanj781f1bd2013-10-23 14:05:15 +00004271 fact and just add the value of the last discarded bit
4272 to the least sifgnificant bit of the shifted value
4273 from acc. */
4274 assign(t8,
4275 IRExpr_ITE(mkexpr(t17),
4276 mkU64(0x0ULL),
4277 binop(Iop_And64,
4278 binop(Iop_Shr64,
4279 mkexpr(t0),
4280 unop(Iop_32to8,
4281 binop(Iop_Sub32,
4282 mkexpr(t15),
4283 mkU32(1)))),
4284 mkU64(0x1ULL))));
dejanjc3fee0d2013-07-25 09:08:03 +00004285
dejanj781f1bd2013-10-23 14:05:15 +00004286 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
dejanjc3fee0d2013-07-25 09:08:03 +00004287
dejanj781f1bd2013-10-23 14:05:15 +00004288 /* Repeat previous steps for the rounded value. */
4289 assign(t10, binop(Iop_CmpNE32,
4290 unop(Iop_64HIto32,
4291 mkexpr(t9)),
4292 mkU32(0)));
4293 assign(t11, binop(Iop_CmpNE32,
4294 binop(Iop_And32,
4295 unop(Iop_64to32,
4296 mkexpr(t9)),
4297 mkU32(0x80000000)),
4298 mkU32(0)));
4299
4300 assign(t12, binop(Iop_CmpNE32,
4301 unop(Iop_64HIto32,
4302 mkexpr(t9)),
4303 mkU32(0xffffffff)));
4304 assign(t13, binop(Iop_CmpNE32,
4305 binop(Iop_And32,
4306 unop(Iop_64to32,
4307 mkexpr(t9)),
4308 mkU32(0x80000000)),
4309 mkU32(0x80000000)));
4310
4311 assign(t14, binop(Iop_And32,
4312 binop(Iop_Or32,
4313 unop(Iop_1Sto32, mkexpr(t10)),
4314 unop(Iop_1Sto32, mkexpr(t11))),
4315 binop(Iop_Or32,
4316 unop(Iop_1Sto32, mkexpr(t12)),
4317 unop(Iop_1Sto32, mkexpr(t13)))));
dejanjc3fee0d2013-07-25 09:08:03 +00004318 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
dejanj781f1bd2013-10-23 14:05:15 +00004319 mkexpr(t14),
4320 mkU32(0)),
4321 binop(Iop_Or32,
4322 getDSPControl(),
4323 mkU32(0x00800000)),
dejanjc3fee0d2013-07-25 09:08:03 +00004324 getDSPControl()));
dejanj781f1bd2013-10-23 14:05:15 +00004325
4326 assign(t16, binop(Iop_And32,
4327 unop(Iop_64HIto32,
4328 mkexpr(t9)),
4329 mkU32(0x80000000)));
4330 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
4331 mkexpr(t14),
4332 mkU32(0)),
4333 IRExpr_ITE(binop(Iop_CmpEQ32,
4334 mkexpr(t16),
4335 mkU32(0)),
4336 mkU32(0x7fffffff),
dejanjc3fee0d2013-07-25 09:08:03 +00004337 mkU32(0x80000000)),
dejanj781f1bd2013-10-23 14:05:15 +00004338 unop(Iop_64to32, mkexpr(t9))));
dejanjc3fee0d2013-07-25 09:08:03 +00004339 break;
4340 }
4341 case 0xA: { /* EXTPDP */
4342 DIP("extpdp r%d, ac%d, %d", rt, ac, rs);
4343 vassert(!mode64);
4344 t0 = newTemp(Ity_I64);
4345 t1 = newTemp(Ity_I32);
4346 t2 = newTemp(Ity_I1);
4347 t3 = newTemp(Ity_I1);
4348 t4 = newTemp(Ity_I8);
4349 t5 = newTemp(Ity_I64);
4350 t6 = newTemp(Ity_I64);
4351 t7 = newTemp(Ity_I32);
4352 t8 = newTemp(Ity_I32);
4353
4354 assign(t0, getAcc(ac));
4355 /* Extract pos field of DSPControl register. */
4356 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
4357
4358 /* Check if (pos - size) >= 0 [size <= pos]
4359 if (pos < size)
4360 put 1 to EFI field of DSPControl register
4361 else
4362 extract bits from acc and put 0 to EFI field of
4363 DSPCtrl */
4364 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));
4365
4366 assign(t8, binop(Iop_Or32,
4367 binop(Iop_And32,
4368 getDSPControl(),
4369 mkU32(0xffffbfc0)),
4370 binop(Iop_And32,
4371 binop(Iop_Sub32,
4372 binop(Iop_And32,
4373 getDSPControl(),
4374 mkU32(0x3f)),
4375 mkU32(rs+1)),
4376 mkU32(0x3f))));
4377 putDSPControl(IRExpr_ITE(mkexpr(t2),
4378 binop(Iop_Or32,
4379 binop(Iop_And32,
4380 getDSPControl(),
4381 mkU32(0xffffbfff)),
4382 mkU32(0x4000)),
4383 mkexpr(t8)));
4384
4385 /* If pos <= 31, shift right the value from the acc
4386 (pos-size) times and take (size+1) bits from the least
4387 significant positions. Otherwise, shift left the value
4388 (63-pos) times, take (size+1) bits from the most
4389 significant positions and shift right (31-size) times.
4390 */
4391 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
4392
4393 assign(t4,
4394 IRExpr_ITE(mkexpr(t3),
4395 unop(Iop_32to8,
4396 binop(Iop_Sub32,
4397 mkexpr(t1), mkU32(rs))),
4398 unop(Iop_32to8,
4399 binop(Iop_Sub32,
4400 mkU32(63), mkexpr(t1)))));
4401
4402 assign(t5, IRExpr_ITE(mkexpr(t3),
4403 binop(Iop_Shr64,
4404 mkexpr(t0), mkexpr(t4)),
4405 binop(Iop_Shl64,
4406 mkexpr(t0), mkexpr(t4))));
4407
4408 /* t6 holds a mask for bit extraction. */
4409 assign(t6,
4410 IRExpr_ITE(mkexpr(t3),
4411 unop(Iop_Not64,
4412 binop(Iop_Shl64,
4413 mkU64(0xffffffffffffffffULL),
4414 mkU8(rs+1))),
4415 unop(Iop_Not64,
4416 binop(Iop_Shr64,
4417 mkU64(0xffffffffffffffffULL),
4418 mkU8(rs+1)))));
4419
4420 assign(t7, IRExpr_ITE(mkexpr(t3),
4421 unop(Iop_64to32,
4422 binop(Iop_And64,
4423 mkexpr(t5),
4424 mkexpr(t6))),
4425 binop(Iop_Shr32,
4426 unop(Iop_64HIto32,
4427 binop(Iop_And64,
4428 mkexpr(t5),
4429 mkexpr(t6))),
4430 mkU8(31-rs))));
4431
4432 putIReg(rt, mkexpr(t7));
4433 break;
4434 }
4435 case 0xB: { /* EXTPDPV */
4436 DIP("extpdpv r%d, ac%d, r%d", rt, ac, rs);
4437 vassert(!mode64);
4438 t0 = newTemp(Ity_I64);
4439 t1 = newTemp(Ity_I32);
4440 t2 = newTemp(Ity_I1);
4441 t3 = newTemp(Ity_I1);
4442 t4 = newTemp(Ity_I8);
4443 t5 = newTemp(Ity_I64);
4444 t6 = newTemp(Ity_I64);
4445 t7 = newTemp(Ity_I32);
4446 t8 = newTemp(Ity_I32);
4447 t9 = newTemp(Ity_I32);
4448
4449 assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
4450 assign(t0, getAcc(ac));
4451 /* Extract pos field of DSPControl register. */
4452 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
4453
4454 /* Check if (pos - size) >= 0 [size <= pos]
4455 if (pos < size)
4456 put 1 to EFI field of DSPControl register
4457 else
4458 extract bits from acc and put 0 to EFI field of
4459 DSPCtrl */
4460 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));
4461
4462 assign(t9, binop(Iop_Or32,
4463 binop(Iop_And32,
4464 getDSPControl(),
4465 mkU32(0xffffbfc0)),
4466 binop(Iop_And32,
4467 binop(Iop_Sub32,
4468 binop(Iop_And32,
4469 getDSPControl(),
4470 mkU32(0x3f)),
4471 binop(Iop_Add32,
4472 mkexpr(t8),
4473 mkU32(0x1))),
4474 mkU32(0x3f))));
4475 putDSPControl(IRExpr_ITE(mkexpr(t2),
4476 binop(Iop_Or32,
4477 binop(Iop_And32,
4478 getDSPControl(),
4479 mkU32(0xffffbfff)),
4480 mkU32(0x4000)),
4481 mkexpr(t9)));
4482
4483 /* If pos <= 31, shift right the value from the acc
4484 (pos-size) times and take (size+1) bits from the least
4485 significant positions. Otherwise, shift left the value
4486 (63-pos) times, take (size+1) bits from the most
4487 significant positions and shift right (31-size) times.
4488 */
4489 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
4490
4491 assign(t4,
4492 IRExpr_ITE(mkexpr(t3),
4493 unop(Iop_32to8,
4494 binop(Iop_Sub32,
4495 mkexpr(t1), mkexpr(t8))),
4496 unop(Iop_32to8,
4497 binop(Iop_Sub32,
4498 mkU32(63), mkexpr(t1)))));
4499
4500 assign(t5, IRExpr_ITE(mkexpr(t3),
4501 binop(Iop_Shr64,
4502 mkexpr(t0), mkexpr(t4)),
4503 binop(Iop_Shl64,
4504 mkexpr(t0), mkexpr(t4))));
4505
4506 /* t6 holds a mask for bit extraction. */
4507 assign(t6,
4508 IRExpr_ITE(mkexpr(t3),
4509 unop(Iop_Not64,
4510 binop(Iop_Shl64,
4511 mkU64(0xffffffffffffffffULL),
4512 unop(Iop_32to8,
4513 binop(Iop_Add32,
4514 mkexpr(t8),
4515 mkU32(1))))),
4516 unop(Iop_Not64,
4517 binop(Iop_Shr64,
4518 mkU64(0xffffffffffffffffULL),
4519 unop(Iop_32to8,
4520 binop(Iop_Add32,
4521 mkexpr(t8),
4522 mkU32(1)))))));
4523
4524 assign(t7, IRExpr_ITE(mkexpr(t3),
4525 unop(Iop_64to32,
4526 binop(Iop_And64,
4527 mkexpr(t5),
4528 mkexpr(t6))),
4529 binop(Iop_Shr32,
4530 unop(Iop_64HIto32,
4531 binop(Iop_And64,
4532 mkexpr(t5),
4533 mkexpr(t6))),
4534 unop(Iop_32to8,
4535 binop(Iop_Sub32,
4536 mkU32(31),
4537 mkexpr(t8))))));
4538
4539 putIReg(rt, mkexpr(t7));
4540 break;
4541 }
4542 case 0xE: { /* EXTR_S.H */
4543 DIP("extr_s.h r%d, ac%d, %d", rt, ac, rs);
4544 vassert(!mode64);
4545 t0 = newTemp(Ity_I64);
4546 t1 = newTemp(Ity_I64);
4547 t2 = newTemp(Ity_I32);
4548 t3 = newTemp(Ity_I64);
4549 t4 = newTemp(Ity_I32);
4550 t5 = newTemp(Ity_I32);
4551 t6 = newTemp(Ity_I64);
4552 t7 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +00004553 t9 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +00004554
4555 assign(t0, getAcc(ac));
4556
4557 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
4558
4559 assign(t2, binop(Iop_Or32,
4560 getDSPControl(), mkU32(0x00800000)));
4561
dejanj781f1bd2013-10-23 14:05:15 +00004562 assign(t9, binop(Iop_And32,
4563 unop(Iop_64to32,
4564 mkexpr(t1)),
4565 mkU32(0x80000000)));
dejanjc3fee0d2013-07-25 09:08:03 +00004566 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4567 mkexpr(t9),
4568 binop(Iop_And32,
4569 unop(Iop_64HIto32,
4570 mkexpr(t0)),
4571 mkU32(0x80000000))),
4572 mkexpr(t2),
4573 getDSPControl()));
4574
4575 /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
4576 1. subtract 0x7fff from t1
4577 2. if the resulting number is positive (sign bit = 0)
4578 and any of the other bits is 1, the value is > 0. */
4579 assign(t3, binop(Iop_Sub64,
4580 mkexpr(t1),
4581 mkU64(0x0000000000007fffULL)));
dejanj781f1bd2013-10-23 14:05:15 +00004582 assign(t4, binop(Iop_And32,
4583 binop(Iop_Or32,
4584 unop(Iop_1Sto32,
4585 binop(Iop_CmpNE32,
4586 mkU32(0),
4587 binop(Iop_And32,
4588 unop(Iop_64HIto32,
4589 mkexpr(t3)),
4590 mkU32(0x7fffffff)))),
4591 unop(Iop_1Sto32,
4592 binop(Iop_CmpNE32,
4593 mkU32(0),
dejanjc3fee0d2013-07-25 09:08:03 +00004594 unop(Iop_64to32,
dejanj781f1bd2013-10-23 14:05:15 +00004595 mkexpr(t3))))),
4596 unop(Iop_1Sto32,
4597 binop(Iop_CmpEQ32,
4598 binop(Iop_And32,
4599 unop(Iop_64HIto32,
4600 mkexpr(t3)),
4601 mkU32(0x80000000)),
4602 mkU32(0)))));
4603 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4604 mkU32(0),
4605 mkexpr(t4)),
4606 binop(Iop_Or32,
4607 getDSPControl(),
4608 mkU32(0x00800000)),
4609 getDSPControl()));
dejanjc3fee0d2013-07-25 09:08:03 +00004610 /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
dejanj781f1bd2013-10-23 14:05:15 +00004611 1. subtract t1 from 0xffffffffffff8000
dejanjc3fee0d2013-07-25 09:08:03 +00004612 2. if the resulting number is positive (sign bit = 0)
4613 and any of the other bits is 1, the value is > 0 */
4614 assign(t6, binop(Iop_Sub64,
4615 mkU64(0xffffffffffff8000ULL),
4616 mkexpr(t1)));
dejanj781f1bd2013-10-23 14:05:15 +00004617 assign(t7, binop(Iop_And32,
4618 binop(Iop_Or32,
4619 unop(Iop_1Sto32,
4620 binop(Iop_CmpNE32,
4621 mkU32(0),
dejanjc3fee0d2013-07-25 09:08:03 +00004622 binop(Iop_And32,
4623 unop(Iop_64HIto32,
dejanj781f1bd2013-10-23 14:05:15 +00004624 mkexpr(t6)),
4625 mkU32(0x7fffffff)))),
4626 unop(Iop_1Sto32,
4627 binop(Iop_CmpNE32,
4628 mkU32(0),
4629 unop(Iop_64to32,
4630 mkexpr(t6))))),
4631 unop(Iop_1Sto32,
4632 binop(Iop_CmpEQ32,
4633 binop(Iop_And32,
4634 unop(Iop_64HIto32,
4635 mkexpr(t6)),
dejanjc3fee0d2013-07-25 09:08:03 +00004636 mkU32(0x80000000)),
dejanj781f1bd2013-10-23 14:05:15 +00004637 mkU32(0)))));
4638 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4639 mkU32(0),
4640 mkexpr(t7)),
4641 binop(Iop_Or32,
4642 getDSPControl(),
4643 mkU32(0x00800000)),
4644 getDSPControl()));
4645 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
4646 mkU32(0),
4647 mkexpr(t4)),
4648 mkU32(0x00007fff),
4649 IRExpr_ITE(binop(Iop_CmpNE32,
4650 mkU32(0),
4651 mkexpr(t7)),
4652 mkU32(0xffff8000),
4653 unop(Iop_64to32,
4654 mkexpr(t1)))));
dejanjc3fee0d2013-07-25 09:08:03 +00004655 break;
4656 }
4657 case 0xF: { /* EXTRV_S.H */
4658 DIP("extrv_s.h r%d, ac%d, %d", rt, ac, rs);
4659 vassert(!mode64);
4660 t0 = newTemp(Ity_I64);
4661 t1 = newTemp(Ity_I64);
4662 t2 = newTemp(Ity_I32);
4663 t3 = newTemp(Ity_I64);
4664 t4 = newTemp(Ity_I32);
4665 t5 = newTemp(Ity_I32);
4666 t6 = newTemp(Ity_I64);
4667 t7 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +00004668 t9 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +00004669
4670 assign(t0, getAcc(ac));
4671
4672 assign(t1, binop(Iop_Sar64,
4673 mkexpr(t0),
4674 unop(Iop_32to8,
4675 binop(Iop_And32,
4676 getIReg(rs),
4677 mkU32(0x1f)))));
4678
4679 assign(t2, binop(Iop_Or32,
4680 getDSPControl(), mkU32(0x00800000)));
4681
dejanj781f1bd2013-10-23 14:05:15 +00004682 assign(t9, binop(Iop_And32,
4683 unop(Iop_64to32,
4684 mkexpr(t1)),
4685 mkU32(0x80000000)));
dejanjc3fee0d2013-07-25 09:08:03 +00004686 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4687 mkexpr(t9),
4688 binop(Iop_And32,
4689 unop(Iop_64HIto32,
4690 mkexpr(t0)),
4691 mkU32(0x80000000))),
4692 mkexpr(t2),
4693 getDSPControl()));
4694
4695 /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
4696 1. subtract 0x7fff from t1
4697 2. if the resulting number is positive (sign bit = 0)
dejanj781f1bd2013-10-23 14:05:15 +00004698 and any of the other bits is 1, the value is > 0. */
dejanjc3fee0d2013-07-25 09:08:03 +00004699 assign(t3, binop(Iop_Sub64,
4700 mkexpr(t1),
4701 mkU64(0x0000000000007fffULL)));
dejanj781f1bd2013-10-23 14:05:15 +00004702 assign(t4, binop(Iop_And32,
4703 binop(Iop_Or32,
4704 unop(Iop_1Sto32,
4705 binop(Iop_CmpNE32,
4706 mkU32(0),
dejanjc3fee0d2013-07-25 09:08:03 +00004707 binop(Iop_And32,
4708 unop(Iop_64HIto32,
dejanj781f1bd2013-10-23 14:05:15 +00004709 mkexpr(t3)),
4710 mkU32(0x7fffffff)))),
4711 unop(Iop_1Sto32,
4712 binop(Iop_CmpNE32,
4713 mkU32(0),
4714 unop(Iop_64to32,
4715 mkexpr(t3))))),
4716 unop(Iop_1Sto32,
4717 binop(Iop_CmpEQ32,
4718 binop(Iop_And32,
4719 unop(Iop_64HIto32,
4720 mkexpr(t3)),
dejanjc3fee0d2013-07-25 09:08:03 +00004721 mkU32(0x80000000)),
dejanj781f1bd2013-10-23 14:05:15 +00004722 mkU32(0)))));
4723 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4724 mkU32(0),
4725 mkexpr(t4)),
4726 binop(Iop_Or32,
4727 getDSPControl(),
4728 mkU32(0x00800000)),
4729 getDSPControl()));
4730 /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
4731 1. subtract t1 from 0xffffffffffff8000
4732 2. if the resulting number is positive (sign bit = 0)
4733 and any of the other bits is 1, the value is > 0 */
4734 assign(t6, binop(Iop_Sub64,
4735 mkU64(0xffffffffffff8000ULL),
4736 mkexpr(t1)));
4737 assign(t7, binop(Iop_And32,
4738 binop(Iop_Or32,
4739 unop(Iop_1Sto32,
4740 binop(Iop_CmpNE32,
4741 mkU32(0),
4742 binop(Iop_And32,
4743 unop(Iop_64HIto32,
4744 mkexpr(t6)),
4745 mkU32(0x7fffffff)))),
4746 unop(Iop_1Sto32,
4747 binop(Iop_CmpNE32,
4748 mkU32(0),
4749 unop(Iop_64to32,
4750 mkexpr(t6))))),
4751 unop(Iop_1Sto32,
4752 binop(Iop_CmpEQ32,
4753 binop(Iop_And32,
4754 unop(Iop_64HIto32,
4755 mkexpr(t6)),
4756 mkU32(0x80000000)),
4757 mkU32(0)))));
4758 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4759 mkU32(0),
4760 mkexpr(t7)),
4761 binop(Iop_Or32,
4762 getDSPControl(),
4763 mkU32(0x00800000)),
4764 getDSPControl()));
4765 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
4766 mkU32(0),
4767 mkexpr(t4)),
4768 mkU32(0x00007fff),
4769 IRExpr_ITE(binop(Iop_CmpNE32,
4770 mkU32(0),
4771 mkexpr(t7)),
4772 mkU32(0xffff8000),
4773 unop(Iop_64to32,
4774 mkexpr(t1)))));
dejanjc3fee0d2013-07-25 09:08:03 +00004775 break;
4776 }
4777 case 0x12: { /* RDDSP*/
4778 DIP("rddsp r%d, mask 0x%x", rd, rddsp_mask);
4779 vassert(!mode64);
4780
4781 putIReg(rd, mkU32(0x0));
4782
florianbefee0b2013-08-03 20:39:32 +00004783 if ((rddsp_mask & 0x1) == 0x1) {
dejanjc3fee0d2013-07-25 09:08:03 +00004784 /* Read pos field (bits 5-0) of DSPControl register. */
4785 putIReg(rd, binop(Iop_Or32,
4786 getIReg(rd),
4787 binop(Iop_And32,
4788 getDSPControl(),
4789 mkU32(0x0000003F))));
4790 }
4791
florianbefee0b2013-08-03 20:39:32 +00004792 if ((rddsp_mask & 0x2) == 0x2) {
dejanjc3fee0d2013-07-25 09:08:03 +00004793 /* Read scount field (bits 12-7) of DSPControl
4794 register. */
4795 putIReg(rd, binop(Iop_Or32,
4796 getIReg(rd),
4797 binop(Iop_And32,
4798 getDSPControl(),
4799 mkU32(0x00001F80))));
4800 }
4801
florianbefee0b2013-08-03 20:39:32 +00004802 if ((rddsp_mask & 0x4) == 0x4) {
dejanjc3fee0d2013-07-25 09:08:03 +00004803 /* Read C field (bit 13) of DSPControl register. */
4804 putIReg(rd, binop(Iop_Or32,
4805 getIReg(rd),
4806 binop(Iop_And32,
4807 getDSPControl(),
4808 mkU32(0x00002000))));
4809 }
4810
florianbefee0b2013-08-03 20:39:32 +00004811 if ((rddsp_mask & 0x8) == 0x8) {
dejanjc3fee0d2013-07-25 09:08:03 +00004812 /* Read outflag field (bit s 23-16) of DSPControl
4813 register. */
4814 putIReg(rd, binop(Iop_Or32,
4815 getIReg(rd),
4816 binop(Iop_And32,
4817 getDSPControl(),
4818 mkU32(0x00FF0000))));
4819 }
4820
florianbefee0b2013-08-03 20:39:32 +00004821 if ((rddsp_mask & 0x10) == 0x10) {
dejanjc3fee0d2013-07-25 09:08:03 +00004822 /* Read ccond field (bits 31-24) of DSPControl
4823 register. */
4824 putIReg(rd, binop(Iop_Or32,
4825 getIReg(rd),
4826 binop(Iop_And32,
4827 getDSPControl(),
4828 mkU32(0xFF000000))));
4829 }
4830
florianbefee0b2013-08-03 20:39:32 +00004831 if ((rddsp_mask & 0x20) == 0x20) {
dejanjc3fee0d2013-07-25 09:08:03 +00004832 /* Read EFI field (bit 14) of DSPControl register. */
4833 putIReg(rd, binop(Iop_Or32,
4834 getIReg(rd),
4835 binop(Iop_And32,
4836 getDSPControl(),
4837 mkU32(0x00004000))));
4838 }
4839
florianbefee0b2013-08-03 20:39:32 +00004840 if ((rddsp_mask & 0x3f) == 0x3f) {
dejanjc3fee0d2013-07-25 09:08:03 +00004841 /* Read all fields of DSPControl register. */
4842 putIReg(rd, getDSPControl());
4843 }
4844 break;
4845 }
4846 case 0x13: { /* WRDSP */
4847 DIP("wrdsp r%d, mask 0x%x", rs, wrdsp_mask);
4848 vassert(!mode64);
4849
florianbefee0b2013-08-03 20:39:32 +00004850 if ((wrdsp_mask & 0x3f) == 0x3f) {
dejanjc3fee0d2013-07-25 09:08:03 +00004851 /* If mips64 put all fields of rs, except bit 15 and bit
4852 6, to DSPControl register, otherwise put all except
4853 bits 15, 6 and bits 31..28. */
4854 putDSPControl(mode64 ?
4855 binop(Iop_And32,
4856 getIReg(rs),
4857 mkU32(0xffff7fbf)) :
4858 binop(Iop_And32,
4859 getIReg(rs),
4860 mkU32(0x0fff7fbf)));
4861 } else {
florianbefee0b2013-08-03 20:39:32 +00004862 if ((wrdsp_mask & 0x1) == 0x1) {
dejanjc3fee0d2013-07-25 09:08:03 +00004863 /* Put bits 5-0 of rs to DSPControl register pos
4864 field. */
4865 putDSPControl(binop(Iop_Or32,
4866 binop(Iop_And32,
4867 getDSPControl(),
4868 mkU32(0xFFFF7F40)),
4869 binop(Iop_And32,
4870 getIReg(rs),
4871 mkU32(0x0000003F))));
4872 }
4873
florianbefee0b2013-08-03 20:39:32 +00004874 if ((wrdsp_mask & 0x2) == 0x2) {
dejanjc3fee0d2013-07-25 09:08:03 +00004875 /* Put bits 12-7 of rs to DSPControl scount field. */
4876 putDSPControl(binop(Iop_Or32,
4877 binop(Iop_And32,
4878 getDSPControl(),
4879 mkU32(0xFFFFE03F)),
4880 binop(Iop_And32,
4881 getIReg(rs),
4882 mkU32(0x00001F80))));
4883 }
4884
florianbefee0b2013-08-03 20:39:32 +00004885 if ((wrdsp_mask & 0x4) == 0x4) {
dejanjc3fee0d2013-07-25 09:08:03 +00004886 /* Put bit 13 of rs to DSPControl register C
4887 field. */
4888 putDSPControl(binop(Iop_Or32,
4889 binop(Iop_And32,
4890 getDSPControl(),
4891 mkU32(0xFFFF5FBF)),
4892 binop(Iop_And32,
4893 getIReg(rs),
4894 mkU32(0x00002000))));
4895 }
4896
florianbefee0b2013-08-03 20:39:32 +00004897 if ((wrdsp_mask & 0x8) == 0x8) {
dejanjc3fee0d2013-07-25 09:08:03 +00004898 /* Put bits 23-16 of rs to DSPControl reg outflag
4899 field. */
4900 putDSPControl(binop(Iop_Or32,
4901 binop(Iop_And32,
4902 getDSPControl(),
4903 mkU32(0xFF007FBF)),
4904 binop(Iop_And32,
4905 getIReg(rs),
4906 mkU32(0x00FF0000))));
4907 }
4908
florianbefee0b2013-08-03 20:39:32 +00004909 if ((wrdsp_mask & 0x10) == 0x10) {
dejanjc3fee0d2013-07-25 09:08:03 +00004910 /* Put bits 31-24 of rs to DSPControl reg ccond
4911 field. */
4912 putDSPControl(binop(Iop_Or32,
4913 binop(Iop_And32,
4914 getDSPControl(),
4915 mkU32(0x00FF7FBF)),
4916 binop(Iop_And32,
4917 getIReg(rs),
4918 mode64 ? mkU32(0xFF000000)
4919 : mkU32(0x0F000000))
4920 )
4921 );
4922 }
4923
florianbefee0b2013-08-03 20:39:32 +00004924 if ((wrdsp_mask & 0x20) == 0x20) {
dejanjc3fee0d2013-07-25 09:08:03 +00004925 /* Put bit 14 of rs to DSPControl register EFI
4926 field. */
4927 putDSPControl(binop(Iop_Or32,
4928 binop(Iop_And32,
4929 getDSPControl(),
4930 mkU32(0xFFFF3FBF)),
4931 binop(Iop_And32,
4932 getIReg(rs),
4933 mkU32(0x00004000))));
4934 }
4935 }
4936 break;
4937 }
4938 case 0x1A: { /* SHILO */
4939 DIP("shilo ac%d, %d", ac, shift);
4940 vassert(!mode64);
4941 t0 = newTemp(Ity_I64);
4942 t1 = newTemp(Ity_I64);
4943
4944 assign(t0, getAcc(ac));
4945
4946 putAcc(ac, mkexpr(t0));
4947
florianbefee0b2013-08-03 20:39:32 +00004948 if (0x20 == (shift & 0x3f)) {
dejanjc3fee0d2013-07-25 09:08:03 +00004949 putAcc(ac, binop(Iop_32HLto64,
4950 unop(Iop_64to32, mkexpr(t0)),
4951 mkU32(0x0)));
florianbefee0b2013-08-03 20:39:32 +00004952 } else if (0x20 == (shift & 0x20)) {
dejanjc3fee0d2013-07-25 09:08:03 +00004953 assign(t1, binop(Iop_Shl64,
4954 mkexpr(t0),
4955 unop(Iop_32to8,
4956 binop(Iop_Add32,
4957 unop(Iop_Not32,
4958 mkU32(shift)),
4959 mkU32(0x1)))));
4960
4961 putAcc(ac, mkexpr(t1));
4962 } else {
4963 assign(t1, binop(Iop_Shr64, mkexpr(t0), mkU8(shift)));
4964
4965 putAcc(ac, mkexpr(t1));
4966 }
4967 break;
4968 }
4969 case 0x1B: { /* SHILOV */
4970 DIP("shilov ac%d, r%d", ac, rs);
4971 vassert(!mode64);
4972 t0 = newTemp(Ity_I64);
dejanj781f1bd2013-10-23 14:05:15 +00004973 t1 = newTemp(Ity_I32);
4974 t2 = newTemp(Ity_I1);
4975 t3 = newTemp(Ity_I64);
dejanjc3fee0d2013-07-25 09:08:03 +00004976 t4 = newTemp(Ity_I64);
dejanjc3fee0d2013-07-25 09:08:03 +00004977
4978 assign(t0, getAcc(ac));
dejanj781f1bd2013-10-23 14:05:15 +00004979 assign(t1, binop(Iop_And32, getIReg(rs), mkU32(0x3f)));
4980 assign(t2, binop(Iop_CmpEQ32, mkexpr(t1), mkU32(0x20)));
4981 assign(t3, binop(Iop_Shl64,
dejanjc3fee0d2013-07-25 09:08:03 +00004982 mkexpr(t0),
4983 unop(Iop_32to8,
4984 binop(Iop_Add32,
4985 unop(Iop_Not32,
dejanj781f1bd2013-10-23 14:05:15 +00004986 mkexpr(t1)),
dejanjc3fee0d2013-07-25 09:08:03 +00004987 mkU32(0x1)))));
dejanj781f1bd2013-10-23 14:05:15 +00004988 assign(t4, binop(Iop_Shr64,
dejanjc3fee0d2013-07-25 09:08:03 +00004989 mkexpr(t0),
4990 unop(Iop_32to8,
dejanj781f1bd2013-10-23 14:05:15 +00004991 mkexpr(t1))));
4992
4993 putAcc(ac,
4994 IRExpr_ITE(mkexpr(t2),
4995 binop(Iop_32HLto64,
4996 unop(Iop_64to32, mkexpr(t0)),
4997 mkU32(0x0)),
4998 IRExpr_ITE(binop(Iop_CmpEQ32,
4999 binop(Iop_And32,
5000 mkexpr(t1),
5001 mkU32(0x20)),
5002 mkU32(0x20)),
5003 mkexpr(t3),
5004 mkexpr(t4))));
dejanjc3fee0d2013-07-25 09:08:03 +00005005 break;
5006 }
5007 case 0x1F: { /* MTHLIP */
5008 DIP("mthlip r%d, ac%d", rs, ac);
5009 vassert(!mode64);
5010 t0 = newTemp(Ity_I64);
5011 t1 = newTemp(Ity_I32);
5012 t2 = newTemp(Ity_I32);
5013 t3 = newTemp(Ity_I1);
5014
5015 assign(t0, getAcc(ac));
5016 putAcc(ac, binop(Iop_32HLto64,
5017 unop(Iop_64to32, mkexpr(t0)),
5018 getIReg(rs)));
5019 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
5020 putDSPControl(IRExpr_ITE(binop(Iop_CmpLE32U,
5021 mkU32(32),
5022 mkexpr(t1)),
5023 binop(Iop_Or32,
5024 binop(Iop_Sub32,
5025 mkexpr(t1),
5026 mkU32(32)),
5027 binop(Iop_And32,
5028 getDSPControl(),
5029 mkU32(0xffffffc0))),
5030 binop(Iop_Or32,
5031 binop(Iop_Add32,
5032 mkexpr(t1),
5033 mkU32(32)),
5034 binop(Iop_And32,
5035 getDSPControl(),
5036 mkU32(0xffffffc0)))));
5037 break;
5038 }
5039 default:
5040 return -1;
5041 }
5042 break; /* end of EXTR.W */
5043 }
5044 case 0xA: { /* LX */
5045 switch(sa) {
5046 case 0x0: { /* LWX */
5047 DIP("lwx r%d, r%d(r%d)", rd, rt, rs);
5048 vassert(!mode64);
5049 t0 = newTemp(Ity_I32);
5050
5051 assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
5052
5053 putIReg(rd, load(Ity_I32, mkexpr(t0)));
5054 break;
5055 }
5056 case 0x4: { /* LHX */
5057 DIP("lhx r%d, r%d(r%d)", rd, rt, rs);
5058 vassert(!mode64);
5059 t0 = newTemp(Ity_I32);
5060
5061 assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
5062
5063 putIReg(rd, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t0))));
5064 break;
5065 }
5066 case 0x6: { /* LBUX */
5067 DIP("lbux r%d, r%d(r%d)", rd, rt, rs);
5068 vassert(!mode64);
5069 t0 = newTemp(Ity_I32);
5070
5071 assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
5072
5073 putIReg(rd, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t0))));
5074 break;
5075 }
5076 default:
5077 return -1;
5078 }
5079 break; /* end of LX */
5080 }
5081 case 0xC: { /* INSV */
5082 switch(sa) {
5083 case 0x0: { /* INSV */
5084 DIP("insv r%d, r%d", rt, rs);
5085 vassert(!mode64);
5086
5087 t0 = newTemp(Ity_I32);
5088 t1 = newTemp(Ity_I32);
5089 t2 = newTemp(Ity_I8);
5090 t3 = newTemp(Ity_I8);
5091 t4 = newTemp(Ity_I32);
5092 t5 = newTemp(Ity_I1);
5093 t6 = newTemp(Ity_I32);
5094 t7 = newTemp(Ity_I32);
5095 t8 = newTemp(Ity_I32);
5096 t9 = newTemp(Ity_I32);
5097
5098 /* t0 <- pos field of DSPControl register. */
5099 assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
5100 /* t1 <- scount field of DSPControl register. */
5101 assign(t1, binop(Iop_Shr32,
5102 binop(Iop_And32,
5103 getDSPControl(),
5104 mkU32(0x1f80)),
5105 mkU8(7)));
5106
5107 assign(t2, unop(Iop_32to8,
5108 binop(Iop_Add32,
5109 mkexpr(t1),
5110 mkexpr(t0))));
5111
5112 /* 32-(pos+size) most significant bits of rt. */
5113 assign(t6, binop(Iop_Shl32,
5114 binop(Iop_Shr32,
5115 getIReg(rt),
5116 mkexpr(t2)),
5117 mkexpr(t2)));
5118
5119 assign(t3, unop(Iop_32to8,
5120 binop(Iop_Sub32,
5121 mkU32(32),
5122 mkexpr(t0))));
5123 /* Pos least significant bits of rt. */
5124 assign(t7, binop(Iop_Shr32,
5125 binop(Iop_Shl32,
5126 getIReg(rt),
5127 mkexpr(t3)),
5128 mkexpr(t3)));
5129
5130 /* Size least significant bits of rs,
5131 shifted to appropriate position. */
5132 assign(t8, binop(Iop_Shl32,
5133 binop(Iop_And32,
5134 getIReg(rs),
5135 unop(Iop_Not32,
5136 binop(Iop_Shl32,
5137 mkU32(0xffffffff),
5138 unop(Iop_32to8,
5139 mkexpr(t1))))),
5140 unop(Iop_32to8,
5141 mkexpr(t0))));
5142
5143 putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
5144 mkexpr(t0),
5145 mkU32(0)),
5146 IRExpr_ITE(binop(Iop_CmpEQ32,
5147 mkexpr(t1),
5148 mkU32(32)),
5149 getIReg(rs),
5150 binop(Iop_Or32,
5151 mkexpr(t6),
5152 mkexpr(t8))),
5153 IRExpr_ITE(binop(Iop_CmpEQ32,
5154 unop(Iop_8Uto32,
5155 mkexpr(t2)),
5156 mkU32(32)),
5157 binop(Iop_Or32,
5158 mkexpr(t7),
5159 mkexpr(t8)),
5160 binop(Iop_Or32,
5161 binop(Iop_Or32,
5162 mkexpr(t6),
5163 mkexpr(t7)),
5164 mkexpr(t8)))));
5165 break;
5166 }
5167 default:
5168 return -1;
5169 }
5170 break; /* enf of INSV */
5171 }
5172 case 0x10: { /* ADDU.QB */
5173 switch(sa) {
5174 case 0x00: { /* ADDU.QB */
5175 DIP("addu.qb r%d, r%d, r%d", rd, rs, rt);
5176 vassert(!mode64);
5177 t0 = newTemp(Ity_I32);
5178 t1 = newTemp(Ity_I1);
5179 t2 = newTemp(Ity_I32);
5180 t3 = newTemp(Ity_I1);
5181 t4 = newTemp(Ity_I32);
5182 t5 = newTemp(Ity_I1);
5183 t6 = newTemp(Ity_I32);
5184 t7 = newTemp(Ity_I1);
5185 t8 = newTemp(Ity_I32);
5186
5187 /* Add rightmost bytes of rs and rt. */
5188 assign(t0,
5189 binop(Iop_Add32,
5190 unop(Iop_8Uto32,
5191 unop(Iop_16to8,
5192 unop(Iop_32to16, getIReg(rs)))),
5193 unop(Iop_8Uto32,
5194 unop(Iop_16to8,
5195 unop(Iop_32to16, getIReg(rt))))));
5196 /* t1 will be 1 if there is overflow, 0 otherwise. */
5197 assign(t1, binop(Iop_CmpEQ32,
5198 binop(Iop_And32,
5199 mkexpr(t0),
5200 mkU32(0x00000100)),
5201 mkU32(0x00000100)));
5202
5203 /* Add bits 15-8 of rs and rt. */
5204 assign(t2,
5205 binop(Iop_Add32,
5206 unop(Iop_8Uto32,
5207 unop(Iop_16HIto8,
5208 unop(Iop_32to16, getIReg(rs)))),
5209 unop(Iop_8Uto32,
5210 unop(Iop_16HIto8,
5211 unop(Iop_32to16, getIReg(rt))))));
5212 /* t3 will be 1 if there is overflow, 0 otherwise. */
5213 assign(t3, binop(Iop_CmpEQ32,
5214 binop(Iop_And32,
5215 mkexpr(t2),
5216 mkU32(0x00000100)),
5217 mkU32(0x00000100)));
5218
5219 /* Add bits 15-8 of rs and rt. */
5220 assign(t4,
5221 binop(Iop_Add32,
5222 unop(Iop_8Uto32,
5223 unop(Iop_16to8,
5224 unop(Iop_32HIto16, getIReg(rs)))),
5225 unop(Iop_8Uto32,
5226 unop(Iop_16to8,
5227 unop(Iop_32HIto16, getIReg(rt))))));
5228 /* t5 will be 1 if there is overflow, 0 otherwise. */
5229 assign(t5, binop(Iop_CmpEQ32,
5230 binop(Iop_And32,
5231 mkexpr(t4),
5232 mkU32(0x00000100)),
5233 mkU32(0x00000100)));
5234
5235 /* Add bits 15-8 of rs and rt. */
5236 assign(t6,
5237 binop(Iop_Add32,
5238 unop(Iop_8Uto32,
5239 unop(Iop_16HIto8,
5240 unop(Iop_32HIto16, getIReg(rs)))),
5241 unop(Iop_8Uto32,
5242 unop(Iop_16HIto8,
5243 unop(Iop_32HIto16, getIReg(rt))))));
5244 /* t7 will be 1 if there is overflow, 0 otherwise. */
5245 assign(t7, binop(Iop_CmpEQ32,
5246 binop(Iop_And32,
5247 mkexpr(t6),
5248 mkU32(0x00000100)),
5249 mkU32(0x00000100)));
5250
5251 assign(t8,
5252 binop(Iop_Or32,
5253 binop(Iop_Or32,
5254 binop(Iop_Or32,
5255 unop(Iop_1Sto32, mkexpr(t7)),
5256 unop(Iop_1Sto32, mkexpr(t5))),
5257 unop(Iop_1Sto32, mkexpr(t3))),
5258 unop(Iop_1Sto32, mkexpr(t1))));
5259
5260 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
5261 mkexpr(t8),
5262 mkU32(0x0)),
5263 getDSPControl(),
5264 binop(Iop_Or32,
5265 getDSPControl(),
5266 mkU32(0x00100000))));
5267
5268 putIReg(rd, binop(Iop_16HLto32,
5269 binop(Iop_8HLto16,
5270 unop(Iop_32to8, mkexpr(t6)),
5271 unop(Iop_32to8, mkexpr(t4))),
5272 binop(Iop_8HLto16,
5273 unop(Iop_32to8, mkexpr(t2)),
5274 unop(Iop_32to8, mkexpr(t0)))));
5275 break;
5276 }
5277 case 0x1: { /* SUBU.QB */
5278 DIP("subu.qb r%d, r%d, r%d", rd, rs, rt);
5279 vassert(!mode64);
5280 t0 = newTemp(Ity_I32);
5281 t1 = newTemp(Ity_I1);
5282 t2 = newTemp(Ity_I32);
5283 t3 = newTemp(Ity_I1);
5284 t4 = newTemp(Ity_I32);
5285 t5 = newTemp(Ity_I1);
5286 t6 = newTemp(Ity_I32);
5287 t7 = newTemp(Ity_I1);
5288 t8 = newTemp(Ity_I32);
5289
5290 /* Subtract rightmost bytes of rs and rt. */
5291 assign(t0,
5292 binop(Iop_Sub32,
5293 unop(Iop_8Uto32,
5294 unop(Iop_16to8,
5295 unop(Iop_32to16, getIReg(rs)))),
5296 unop(Iop_8Uto32,
5297 unop(Iop_16to8,
5298 unop(Iop_32to16, getIReg(rt))))));
5299 /* t1 will be 1 if there is overflow, 0 otherwise. */
5300 assign(t1, binop(Iop_CmpEQ32,
5301 binop(Iop_And32,
5302 mkexpr(t0),
5303 mkU32(0x00000100)),
5304 mkU32(0x00000100)));
5305
5306 /* Subtract bits 15-8 of rs and rt. */
5307 assign(t2,
5308 binop(Iop_Sub32,
5309 unop(Iop_8Uto32,
5310 unop(Iop_16HIto8,
5311 unop(Iop_32to16, getIReg(rs)))),
5312 unop(Iop_8Uto32,
5313 unop(Iop_16HIto8,
5314 unop(Iop_32to16, getIReg(rt))))));
5315 /* t3 will be 1 if there is overflow, 0 otherwise. */
5316 assign(t3, binop(Iop_CmpEQ32,
5317 binop(Iop_And32,
5318 mkexpr(t2),
5319 mkU32(0x00000100)),
5320 mkU32(0x00000100)));
5321
5322 /* Subtract bits 15-8 of rs and rt. */
5323 assign(t4,
5324 binop(Iop_Sub32,
5325 unop(Iop_8Uto32,
5326 unop(Iop_16to8,
5327 unop(Iop_32HIto16, getIReg(rs)))),
5328 unop(Iop_8Uto32,
5329 unop(Iop_16to8,
5330 unop(Iop_32HIto16, getIReg(rt))))));
5331 /* t5 will be 1 if there is overflow, 0 otherwise. */
5332 assign(t5, binop(Iop_CmpEQ32,
5333 binop(Iop_And32,
5334 mkexpr(t4),
5335 mkU32(0x00000100)),
5336 mkU32(0x00000100)));
5337
5338 /* Subtract bits 15-8 of rs and rt. */
5339 assign(t6,
5340 binop(Iop_Sub32,
5341 unop(Iop_8Uto32,
5342 unop(Iop_16HIto8,
5343 unop(Iop_32HIto16, getIReg(rs)))),
5344 unop(Iop_8Uto32,
5345 unop(Iop_16HIto8,
5346 unop(Iop_32HIto16, getIReg(rt))))));
5347 /* t7 will be 1 if there is overflow, 0 otherwise. */
5348 assign(t7, binop(Iop_CmpEQ32,
5349 binop(Iop_And32,
5350 mkexpr(t6),
5351 mkU32(0x00000100)),
5352 mkU32(0x00000100)));
5353
5354 assign(t8, binop(Iop_Or32,
5355 binop(Iop_Or32,
5356 binop(Iop_Or32,
5357 unop(Iop_1Sto32, mkexpr(t7)),
5358 unop(Iop_1Sto32, mkexpr(t5))),
5359 unop(Iop_1Sto32, mkexpr(t3))),
5360 unop(Iop_1Sto32, mkexpr(t1))));
5361
5362 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
5363 mkexpr(t8),
5364 mkU32(0x0)),
5365 getDSPControl(),
5366 binop(Iop_Or32,
5367 getDSPControl(),
5368 mkU32(0x00100000))));
5369
5370 putIReg(rd, binop(Iop_16HLto32,
5371 binop(Iop_8HLto16,
5372 unop(Iop_32to8, mkexpr(t6)),
5373 unop(Iop_32to8, mkexpr(t4))),
5374 binop(Iop_8HLto16,
5375 unop(Iop_32to8, mkexpr(t2)),
5376 unop(Iop_32to8, mkexpr(t0)))));
5377 break;
5378 }
5379 case 0x04: { /* ADDU_S.QB */
5380 DIP("addu_s.qb r%d, r%d, r%d", rd, rs, rt);
5381 vassert(!mode64);
5382 t0 = newTemp(Ity_I32);
5383 t1 = newTemp(Ity_I1);
5384 t2 = newTemp(Ity_I8);
5385 t3 = newTemp(Ity_I32);
5386 t4 = newTemp(Ity_I1);
5387 t5 = newTemp(Ity_I8);
5388 t6 = newTemp(Ity_I32);
5389 t7 = newTemp(Ity_I1);
5390 t8 = newTemp(Ity_I8);
5391 t9 = newTemp(Ity_I32);
5392 t10 = newTemp(Ity_I1);
5393 t11 = newTemp(Ity_I8);
5394 t12 = newTemp(Ity_I32);
5395
5396 /* Add rightmost bytes of rs and rt. */
5397 assign(t0,
5398 binop(Iop_Add32,
5399 unop(Iop_8Uto32,
5400 unop(Iop_16to8,
5401 unop(Iop_32to16, getIReg(rs)))),
5402 unop(Iop_8Uto32,
5403 unop(Iop_16to8,
5404 unop(Iop_32to16, getIReg(rt))))));
5405 /* t1 will be 1 if there is overflow, 0 otherwise. */
5406 assign(t1, binop(Iop_CmpEQ32,
5407 binop(Iop_And32,
5408 mkexpr(t0),
5409 mkU32(0x00000100)),
5410 mkU32(0x00000100)));
5411 /* Saturate if necessary. */
5412 assign(t2, IRExpr_ITE(mkexpr(t1),
5413 mkU8(0xff),
5414 unop(Iop_32to8, mkexpr(t0))));
5415
5416 /* Add bits 15-8 of rs and rt. */
5417 assign(t3,
5418 binop(Iop_Add32,
5419 unop(Iop_8Uto32,
5420 unop(Iop_16HIto8,
5421 unop(Iop_32to16, getIReg(rs)))),
5422 unop(Iop_8Uto32,
5423 unop(Iop_16HIto8,
5424 unop(Iop_32to16, getIReg(rt))))));
5425 /* t4 will be 1 if there is overflow, 0 otherwise. */
5426 assign(t4, binop(Iop_CmpEQ32,
5427 binop(Iop_And32,
5428 mkexpr(t3),
5429 mkU32(0x00000100)),
5430 mkU32(0x00000100)));
5431 /* Saturate if necessary. */
5432 assign(t5, IRExpr_ITE(mkexpr(t4),
5433 mkU8(0xff),
5434 unop(Iop_32to8, mkexpr(t3))));
5435
5436 /* Add bits 15-8 of rs and rt. */
5437 assign(t6,
5438 binop(Iop_Add32,
5439 unop(Iop_8Uto32,
5440 unop(Iop_16to8,
5441 unop(Iop_32HIto16, getIReg(rs)))),
5442 unop(Iop_8Uto32,
5443 unop(Iop_16to8,
5444 unop(Iop_32HIto16, getIReg(rt))))));
5445 /* t7 will be 1 if there is overflow, 0 otherwise. */
5446 assign(t7, binop(Iop_CmpEQ32,
5447 binop(Iop_And32,
5448 mkexpr(t6),
5449 mkU32(0x00000100)),
5450 mkU32(0x00000100)));
5451 /* Saturate if necessary. */
5452 assign(t8, IRExpr_ITE(mkexpr(t7),
5453 mkU8(0xff),
5454 unop(Iop_32to8, mkexpr(t6))));
5455
5456 /* Add bits 15-8 of rs and rt. */
5457 assign(t9,
5458 binop(Iop_Add32,
5459 unop(Iop_8Uto32,
5460 unop(Iop_16HIto8,
5461 unop(Iop_32HIto16, getIReg(rs)))),
5462 unop(Iop_8Uto32,
5463 unop(Iop_16HIto8,
5464 unop(Iop_32HIto16, getIReg(rt))))));
5465 /* t10 will be 1 if there is overflow, 0 otherwise. */
5466 assign(t10, binop(Iop_CmpEQ32,
5467 binop(Iop_And32,
5468 mkexpr(t9),
5469 mkU32(0x00000100)),
5470 mkU32(0x00000100)));
5471 /* Saturate if necessary. */
5472 assign(t11, IRExpr_ITE(mkexpr(t10),
5473 mkU8(0xff),
5474 unop(Iop_32to8, mkexpr(t9))));
5475
5476 assign(t12,
5477 binop(Iop_Or32,
5478 binop(Iop_Or32,
5479 binop(Iop_Or32,
5480 unop(Iop_1Sto32, mkexpr(t10)),
5481 unop(Iop_1Sto32, mkexpr(t7))),
5482 unop(Iop_1Sto32, mkexpr(t4))),
5483 unop(Iop_1Sto32, mkexpr(t1))));
5484
5485 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
5486 mkexpr(t12),
5487 mkU32(0x0)),
5488 getDSPControl(),
5489 binop(Iop_Or32,
5490 getDSPControl(),
5491 mkU32(0x00100000))));
5492
5493 putIReg(rd,
5494 binop(Iop_16HLto32,
5495 binop(Iop_8HLto16, mkexpr(t11), mkexpr(t8)),
5496 binop(Iop_8HLto16, mkexpr(t5), mkexpr(t2))));
5497 break;
5498 }
5499 case 0x05: { /* SUBU_S.QB */
5500 DIP("subu_s.qb r%d, r%d, r%d", rd, rs, rt);
5501 vassert(!mode64);
5502 t1 = newTemp(Ity_I32);
5503 t2 = newTemp(Ity_I1);
5504 t3 = newTemp(Ity_I1);
5505 t4 = newTemp(Ity_I1);
5506 t5 = newTemp(Ity_I1);
5507 t6 = newTemp(Ity_I32);
5508 t7 = newTemp(Ity_I32);
5509 t8 = newTemp(Ity_I32);
5510 t9 = newTemp(Ity_I32);
5511
5512 /* Use C function to easily calculate the result
5513 and write it in the register more conveniently
5514 Underflow is checked using step by step subtraction. */
5515 assign(t1, binop(Iop_QSub8Ux4, getIReg(rs), getIReg(rt)));
5516
5517 /* Subtract each byte of rs and rt. */
5518 assign(t6,
5519 binop(Iop_Sub32,
5520 unop(Iop_8Uto32,
5521 unop(Iop_16to8,
5522 unop(Iop_32to16, getIReg(rs)))),
5523 unop(Iop_8Uto32,
5524 unop(Iop_16to8,
5525 unop(Iop_32to16, getIReg(rt))))));
5526 assign(t7,
5527 binop(Iop_Sub32,
5528 unop(Iop_8Uto32,
5529 unop(Iop_16HIto8,
5530 unop(Iop_32to16, getIReg(rs)))),
5531 unop(Iop_8Uto32,
5532 unop(Iop_16HIto8,
5533 unop(Iop_32to16, getIReg(rt))))));
5534 assign(t8,
5535 binop(Iop_Sub32,
5536 unop(Iop_8Uto32,
5537 unop(Iop_16to8,
5538 unop(Iop_32HIto16, getIReg(rs)))),
5539 unop(Iop_8Uto32,
5540 unop(Iop_16to8,
5541 unop(Iop_32HIto16, getIReg(rt))))));
5542 assign(t9,
5543 binop(Iop_Sub32,
5544 unop(Iop_8Uto32,
5545 unop(Iop_16HIto8,
5546 unop(Iop_32HIto16, getIReg(rs)))),
5547 unop(Iop_8Uto32,
5548 unop(Iop_16HIto8,
5549 unop(Iop_32HIto16, getIReg(rt))))));
5550
5551 /* Put 1 to bit 20 in DSPControl if there is underflow
5552 in either byte. */
5553 assign(t2, binop(Iop_CmpEQ32,
5554 binop(Iop_And32,
5555 mkexpr(t6),
5556 mkU32(0x00000100)),
5557 mkU32(0x00000100)));
5558 putDSPControl(IRExpr_ITE(mkexpr(t2),
5559 binop(Iop_Or32,
5560 getDSPControl(),
5561 mkU32(0x00100000)),
5562 getDSPControl()));
5563 assign(t3, binop(Iop_CmpEQ32,
5564 binop(Iop_And32,
5565 mkexpr(t7),
5566 mkU32(0x00000100)),
5567 mkU32(0x00000100)));
5568 putDSPControl(IRExpr_ITE(mkexpr(t3),
5569 binop(Iop_Or32,
5570 getDSPControl(),
5571 mkU32(0x00100000)),
5572 getDSPControl()));
5573 assign(t4, binop(Iop_CmpEQ32,
5574 binop(Iop_And32,
5575 mkexpr(t8),
5576 mkU32(0x00000100)),
5577 mkU32(0x00000100)));
5578 putDSPControl(IRExpr_ITE(mkexpr(t4),
5579 binop(Iop_Or32,
5580 getDSPControl(),
5581 mkU32(0x00100000)),
5582 getDSPControl()));
5583 assign(t5, binop(Iop_CmpEQ32,
5584 binop(Iop_And32,
5585 mkexpr(t9),
5586 mkU32(0x00000100)),
5587 mkU32(0x00000100)));
5588 putDSPControl(IRExpr_ITE(mkexpr(t5),
5589 binop(Iop_Or32,
5590 getDSPControl(),
5591 mkU32(0x00100000)),
5592 getDSPControl()));
5593 putIReg(rd, mkexpr(t1));
5594 break;
5595 }
5596 case 0x6: { /* MULEU_S.PH.QBL */
5597 DIP("muleu_s.ph.qbl r%d, r%d, r%d", rd, rs, rt);
5598 vassert(!mode64);
5599 t0 = newTemp(Ity_I32);
5600 t1 = newTemp(Ity_I32);
5601 t2 = newTemp(Ity_I1);
5602 t3 = newTemp(Ity_I1);
5603
5604 assign(t0,
5605 unop(Iop_64to32,
5606 binop(Iop_MullU32,
5607 unop(Iop_8Uto32,
5608 unop(Iop_16HIto8,
5609 unop(Iop_32HIto16,
5610 getIReg(rs)))),
5611 unop(Iop_16Uto32,
5612 unop(Iop_32HIto16, getIReg(rt))))));
5613 assign(t1,
5614 unop(Iop_64to32,
5615 binop(Iop_MullU32,
5616 unop(Iop_8Uto32,
5617 unop(Iop_16to8,
5618 unop(Iop_32HIto16,
5619 getIReg(rs)))),
5620 unop(Iop_16Uto32,
5621 unop(Iop_32to16, getIReg(rt))))));
5622
5623 assign(t2, binop(Iop_CmpNE32,
5624 mkU32(0x0),
5625 binop(Iop_And32,
5626 mkexpr(t0),
5627 mkU32(0x03ff0000))));
5628 assign(t3, binop(Iop_CmpNE32,
5629 mkU32(0x0),
5630 binop(Iop_And32,
5631 mkexpr(t1),
5632 mkU32(0x03ff0000))));
5633 putDSPControl(IRExpr_ITE(mkexpr(t2),
5634 binop(Iop_Or32,
5635 getDSPControl(),
5636 mkU32(0x200000)),
5637 IRExpr_ITE(mkexpr(t3),
5638 binop(Iop_Or32,
5639 getDSPControl(),
5640 mkU32(0x200000)),
5641 getDSPControl())));
5642 putIReg(rd,
5643 binop(Iop_16HLto32,
5644 IRExpr_ITE(mkexpr(t2),
5645 mkU16(0xffff),
5646 unop(Iop_32to16, mkexpr(t0))),
5647 IRExpr_ITE(mkexpr(t3),
5648 mkU16(0xffff),
5649 unop(Iop_32to16, mkexpr(t1)))));
5650 break;
5651 }
5652 case 0x7: { /* MULEU_S.PH.QBR */
5653 DIP("muleu_s.ph.qbr r%d, r%d, r%d", rd, rs, rt);
5654 vassert(!mode64);
5655 t0 = newTemp(Ity_I32);
5656 t1 = newTemp(Ity_I32);
5657 t2 = newTemp(Ity_I1);
5658 t3 = newTemp(Ity_I1);
5659
5660 assign(t0, unop(Iop_64to32,
5661 binop(Iop_MullU32,
5662 unop(Iop_8Uto32,
5663 unop(Iop_16HIto8,
5664 unop(Iop_32to16,
5665 getIReg(rs)))),
5666 unop(Iop_16Uto32,
5667 unop(Iop_32HIto16,
5668 getIReg(rt))))));
5669 assign(t1, unop(Iop_64to32,
5670 binop(Iop_MullU32,
5671 unop(Iop_8Uto32,
5672 unop(Iop_16to8,
5673 unop(Iop_32to16,
5674 getIReg(rs)))),
5675 unop(Iop_16Uto32,
5676 unop(Iop_32to16,
5677 getIReg(rt))))));
5678
5679 assign(t2, binop(Iop_CmpNE32,
5680 mkU32(0x0),
5681 binop(Iop_And32,
5682 mkexpr(t0),
5683 mkU32(0x03ff0000))));
5684 assign(t3, binop(Iop_CmpNE32,
5685 mkU32(0x0),
5686 binop(Iop_And32,
5687 mkexpr(t1),
5688 mkU32(0x03ff0000))));
5689 putDSPControl(IRExpr_ITE(mkexpr(t2),
5690 binop(Iop_Or32,
5691 getDSPControl(),
5692 mkU32(0x200000)),
5693 IRExpr_ITE(mkexpr(t3),
5694 binop(Iop_Or32,
5695 getDSPControl(),
5696 mkU32(0x200000)),
5697 getDSPControl())));
5698 putIReg(rd, binop(Iop_16HLto32,
5699 IRExpr_ITE(mkexpr(t2),
5700 mkU16(0xffff),
5701 unop(Iop_32to16,
5702 mkexpr(t0))),
5703 IRExpr_ITE(mkexpr(t3),
5704 mkU16(0xffff),
5705 unop(Iop_32to16,
5706 mkexpr(t1)))));
5707 break;
5708 }
5709 case 0x08: { /* ADDU.PH */
5710 DIP("addu.ph r%d, r%d, r%d", rd, rs, rt);
5711 vassert(!mode64);
5712 t0 = newTemp(Ity_I32);
5713 t1 = newTemp(Ity_I1);
5714 t2 = newTemp(Ity_I32);
5715 t3 = newTemp(Ity_I1);
5716
5717 /* Add lower halves. */
5718 assign(t0, binop(Iop_Add32,
5719 unop(Iop_16Uto32,
5720 unop(Iop_32to16, getIReg(rs))),
5721 unop(Iop_16Uto32,
5722 unop(Iop_32to16, getIReg(rt)))));
5723
5724 /* Detect overflow. */
5725 assign(t1, binop(Iop_CmpLT32U,
5726 unop(Iop_16Uto32,
5727 unop(Iop_32to16, mkexpr(t0))),
5728 unop(Iop_16Uto32,
5729 unop(Iop_32to16, getIReg(rs)))));
5730
5731 putDSPControl(IRExpr_ITE(mkexpr(t1),
5732 binop(Iop_Or32,
5733 getDSPControl(),
5734 mkU32(0x00100000)),
5735 getDSPControl()));
5736
5737 /* Add higher halves. */
5738 assign(t2, binop(Iop_Add32,
5739 unop(Iop_16Uto32,
5740 unop(Iop_32HIto16, getIReg(rs))),
5741 unop(Iop_16Uto32,
5742 unop(Iop_32HIto16, getIReg(rt)))));
5743
5744 /* Detect overflow. */
5745 assign(t3, binop(Iop_CmpLT32U,
5746 unop(Iop_16Uto32,
5747 unop(Iop_32to16, mkexpr(t2))),
5748 unop(Iop_16Uto32,
5749 unop(Iop_32HIto16,
5750 getIReg(rs)))));
5751
5752 putDSPControl(IRExpr_ITE(mkexpr(t3),
5753 binop(Iop_Or32,
5754 getDSPControl(),
5755 mkU32(0x00100000)),
5756 getDSPControl()));
5757
5758 putIReg(rd, binop(Iop_16HLto32,
5759 unop(Iop_32to16, mkexpr(t2)),
5760 unop(Iop_32to16, mkexpr(t0))));
5761 break;
5762 }
5763 case 0x9: { /* SUBU.PH */
5764 DIP("subu.ph r%d, r%d, r%d", rd, rs, rt);
5765 vassert(!mode64);
5766 t0 = newTemp(Ity_I32);
5767 t1 = newTemp(Ity_I1);
5768 t2 = newTemp(Ity_I32);
5769 t3 = newTemp(Ity_I1);
5770
5771 /* Substract lower halves. */
5772 assign(t0, binop(Iop_Sub32,
5773 unop(Iop_16Uto32,
5774 unop(Iop_32to16, getIReg(rs))),
5775 unop(Iop_16Uto32,
5776 unop(Iop_32to16, getIReg(rt)))));
5777
5778 /* Detect underflow. */
5779 assign(t1, binop(Iop_CmpNE32,
5780 binop(Iop_And32,
5781 mkexpr(t0),
5782 mkU32(0x00010000)),
5783 mkU32(0x0)));
5784
5785 putDSPControl(IRExpr_ITE(mkexpr(t1),
5786 binop(Iop_Or32,
5787 getDSPControl(),
5788 mkU32(0x00100000)),
5789 getDSPControl()));
5790
5791 /* Subtract higher halves. */
5792 assign(t2, binop(Iop_Sub32,
5793 unop(Iop_16Uto32,
5794 unop(Iop_32HIto16, getIReg(rs))),
5795 unop(Iop_16Uto32,
5796 unop(Iop_32HIto16, getIReg(rt)))));
5797
5798 /* Detect underflow. */
5799 assign(t3, binop(Iop_CmpNE32,
5800 binop(Iop_And32,
5801 mkexpr(t2),
5802 mkU32(0x00010000)),
5803 mkU32(0x0)));
5804
5805 putDSPControl(IRExpr_ITE(mkexpr(t3),
5806 binop(Iop_Or32,
5807 getDSPControl(),
5808 mkU32(0x00100000)),
5809 getDSPControl()));
5810
5811 putIReg(rd, binop(Iop_16HLto32,
5812 unop(Iop_32to16, mkexpr(t2)),
5813 unop(Iop_32to16, mkexpr(t0))));
5814 break;
5815 }
5816 case 0xA: { /* ADDQ.PH */
5817 DIP("addq.ph r%d, r%d, r%d", rd, rs, rt);
5818 vassert(!mode64);
5819 t0 = newTemp(Ity_I32);
5820 t1 = newTemp(Ity_I1);
5821 t2 = newTemp(Ity_I32);
5822 t3 = newTemp(Ity_I1);
5823 t6 = newTemp(Ity_I32);
5824 t7 = newTemp(Ity_I32);
5825
5826 /* Add lower halves. */
5827 assign(t0, binop(Iop_Add32,
5828 unop(Iop_16Sto32,
5829 unop(Iop_32to16, getIReg(rs))),
5830 unop(Iop_16Sto32,
5831 unop(Iop_32to16, getIReg(rt)))));
5832
5833 /* Bit 16 of the result. */
5834 assign(t6, binop(Iop_And32,
5835 unop(Iop_16Uto32,
5836 unop(Iop_32HIto16, mkexpr(t0))),
5837 mkU32(0x1)));
5838 /* Detect overflow. */
5839 assign(t1, binop(Iop_CmpNE32,
5840 binop(Iop_Shr32,
5841 binop(Iop_And32,
5842 mkexpr(t0),
5843 mkU32(0x8000)),
5844 mkU8(15)),
5845 mkexpr(t6)));
5846
5847 putDSPControl(IRExpr_ITE(mkexpr(t1),
5848 binop(Iop_Or32,
5849 getDSPControl(),
5850 mkU32(0x00100000)),
5851 getDSPControl()));
5852
5853 /* Add higher halves. */
5854 assign(t2, binop(Iop_Add32,
5855 unop(Iop_16Sto32,
5856 unop(Iop_32HIto16, getIReg(rs))),
5857 unop(Iop_16Sto32,
5858 unop(Iop_32HIto16, getIReg(rt)))));
5859
5860 /* Bit 16 of the result. */
5861 assign(t7, binop(Iop_And32,
5862 unop(Iop_16Uto32,
5863 unop(Iop_32HIto16, mkexpr(t2))),
5864 mkU32(0x1)));
5865 /* Detect overflow. */
5866 assign(t3, binop(Iop_CmpNE32,
5867 binop(Iop_Shr32,
5868 binop(Iop_And32,
5869 mkexpr(t2),
5870 mkU32(0x00008000)),
5871 mkU8(15)),
5872 mkexpr(t7)));
5873
5874 putDSPControl(IRExpr_ITE(mkexpr(t3),
5875 binop(Iop_Or32,
5876 getDSPControl(),
5877 mkU32(0x00100000)),
5878 getDSPControl()));
5879
5880 putIReg(rd, binop(Iop_16HLto32,
5881 unop(Iop_32to16, mkexpr(t2)),
5882 unop(Iop_32to16, mkexpr(t0))));
5883 break;
5884 }
5885 case 0xB: { /* SUBQ.PH */
5886 DIP("subq.ph r%d, r%d, r%d", rd, rs, rt);
5887 vassert(!mode64);
5888 t0 = newTemp(Ity_I32);
5889 t1 = newTemp(Ity_I1);
5890 t2 = newTemp(Ity_I32);
5891 t3 = newTemp(Ity_I1);
5892 t6 = newTemp(Ity_I32);
5893 t7 = newTemp(Ity_I32);
5894
5895 /* Subtract lower halves. */
5896 assign(t0, binop(Iop_Sub32,
5897 unop(Iop_16Sto32,
5898 unop(Iop_32to16, getIReg(rs))),
5899 unop(Iop_16Sto32,
5900 unop(Iop_32to16, getIReg(rt)))));
5901
5902 /* Bit 16 of the result. */
5903 assign(t6, binop(Iop_And32,
5904 unop(Iop_16Uto32,
5905 unop(Iop_32HIto16, mkexpr(t0))),
5906 mkU32(0x1)));
5907 /* Compare the signs of input value and the result. */
5908 assign(t1, binop(Iop_CmpNE32,
5909 binop(Iop_Shr32,
5910 binop(Iop_And32,
5911 mkexpr(t0),
5912 mkU32(0x8000)),
5913 mkU8(15)),
5914 mkexpr(t6)));
5915
5916 putDSPControl(IRExpr_ITE(mkexpr(t1),
5917 binop(Iop_Or32,
5918 getDSPControl(),
5919 mkU32(0x00100000)),
5920 getDSPControl()));
5921
5922 /* Subtract higher halves. */
5923 assign(t2, binop(Iop_Sub32,
5924 unop(Iop_16Sto32,
5925 unop(Iop_32HIto16, getIReg(rs))),
5926 unop(Iop_16Sto32,
5927 unop(Iop_32HIto16, getIReg(rt)))));
5928
5929 /* Bit 16 of the result. */
5930 assign(t7, binop(Iop_And32,
5931 unop(Iop_16Uto32,
5932 unop(Iop_32HIto16, mkexpr(t2))),
5933 mkU32(0x1)));
5934 /* Compare the signs of input value and the result. */
5935 assign(t3, binop(Iop_CmpNE32,
5936 binop(Iop_Shr32,
5937 binop(Iop_And32,
5938 mkexpr(t2),
5939 mkU32(0x00008000)),
5940 mkU8(15)),
5941 mkexpr(t7)));
5942
5943 putDSPControl(IRExpr_ITE(mkexpr(t3),
5944 binop(Iop_Or32,
5945 getDSPControl(),
5946 mkU32(0x00100000)),
5947 getDSPControl()));
5948
5949 putIReg(rd, binop(Iop_16HLto32,
5950 unop(Iop_32to16, mkexpr(t2)),
5951 unop(Iop_32to16, mkexpr(t0))));
5952 break;
5953 }
5954 case 0xC: { /* ADDU_S.PH */
5955 DIP("addu_s.ph r%d, r%d, r%d", rd, rs, rt);
5956 vassert(!mode64);
5957 t0 = newTemp(Ity_I32);
5958 t1 = newTemp(Ity_I1);
5959 t2 = newTemp(Ity_I32);
5960 t3 = newTemp(Ity_I1);
5961
5962 /* Add lower halves. */
5963 assign(t0, binop(Iop_Add32,
5964 unop(Iop_16Uto32,
5965 unop(Iop_32to16, getIReg(rs))),
5966 unop(Iop_16Uto32,
5967 unop(Iop_32to16, getIReg(rt)))));
5968
5969 /* Detect overflow. */
5970 assign(t1, binop(Iop_CmpLT32U,
5971 unop(Iop_16Uto32,
5972 unop(Iop_32to16, mkexpr(t0))),
5973 unop(Iop_16Uto32,
5974 unop(Iop_32to16, getIReg(rs)))));
5975
5976 putDSPControl(IRExpr_ITE(mkexpr(t1),
5977 binop(Iop_Or32,
5978 getDSPControl(),
5979 mkU32(0x00100000)),
5980 getDSPControl()));
5981
5982 /* Add higher halves. */
5983 assign(t2, binop(Iop_Add32,
5984 unop(Iop_16Uto32,
5985 unop(Iop_32HIto16, getIReg(rs))),
5986 unop(Iop_16Uto32,
5987 unop(Iop_32HIto16, getIReg(rt)))));
5988
5989 /* Detect overflow. */
5990 assign(t3, binop(Iop_CmpLT32U,
5991 unop(Iop_16Uto32,
5992 unop(Iop_32to16, mkexpr(t2))),
5993 unop(Iop_16Uto32,
5994 unop(Iop_32HIto16, getIReg(rs)))));
5995
5996 putDSPControl(IRExpr_ITE(mkexpr(t3),
5997 binop(Iop_Or32,
5998 getDSPControl(),
5999 mkU32(0x00100000)),
6000 getDSPControl()));
6001
6002 putIReg(rd, binop(Iop_16HLto32,
6003 IRExpr_ITE(mkexpr(t3),
6004 mkU16(0xffff),
6005 unop(Iop_32to16,
6006 mkexpr(t2))),
6007 IRExpr_ITE(mkexpr(t1),
6008 mkU16(0xffff),
6009 unop(Iop_32to16,
6010 mkexpr(t0)))));
6011 break;
6012 }
6013 case 0xD: { /* SUBU_S.PH */
6014 DIP("subu_s.ph r%d, r%d, r%d", rd, rs, rt);
6015 vassert(!mode64);
6016 t0 = newTemp(Ity_I32);
6017 t1 = newTemp(Ity_I1);
6018 t2 = newTemp(Ity_I32);
6019 t3 = newTemp(Ity_I1);
6020
6021 /* Subtract lower halves. */
6022 assign(t0, binop(Iop_Sub32,
6023 unop(Iop_16Uto32,
6024 unop(Iop_32to16, getIReg(rs))),
6025 unop(Iop_16Uto32,
6026 unop(Iop_32to16, getIReg(rt)))));
6027
6028 /* Detect underflow. */
6029 assign(t1, binop(Iop_CmpNE32,
6030 binop(Iop_And32,
6031 mkexpr(t0), mkU32(0x00010000)),
6032 mkU32(0x0)));
6033
6034 putDSPControl(IRExpr_ITE(mkexpr(t1),
6035 binop(Iop_Or32,
6036 getDSPControl(),
6037 mkU32(0x00100000)),
6038 getDSPControl()));
6039
6040 /* Subtract higher halves. */
6041 assign(t2, binop(Iop_Sub32,
6042 unop(Iop_16Uto32,
6043 unop(Iop_32HIto16, getIReg(rs))),
6044 unop(Iop_16Uto32,
6045 unop(Iop_32HIto16, getIReg(rt)))));
6046
6047 /* Detect underflow. */
6048 assign(t3, binop(Iop_CmpNE32,
6049 binop(Iop_And32,
6050 mkexpr(t2), mkU32(0x00010000)),
6051 mkU32(0x0)));
6052
6053 putDSPControl(IRExpr_ITE(mkexpr(t3),
6054 binop(Iop_Or32,
6055 getDSPControl(),
6056 mkU32(0x00100000)),
6057 getDSPControl()));
6058
6059 putIReg(rd,
6060 binop(Iop_16HLto32,
6061 IRExpr_ITE(mkexpr(t3),
6062 mkU16(0x0000),
6063 unop(Iop_32to16, mkexpr(t2))),
6064 IRExpr_ITE(mkexpr(t1),
6065 mkU16(0x0000),
6066 unop(Iop_32to16, mkexpr(t0)))));
6067 break;
6068 }
6069 case 0xE: { /* ADDQ_S.PH */
6070 DIP("addq_s.ph r%d r%d, r%d", rd, rs, rt);
6071 vassert(!mode64);
6072 t0 = newTemp(Ity_I32);
6073 t1 = newTemp(Ity_I1);
6074 t2 = newTemp(Ity_I32);
6075 t3 = newTemp(Ity_I1);
6076 t4 = newTemp(Ity_I16);
6077 t5 = newTemp(Ity_I16);
6078 t6 = newTemp(Ity_I32);
6079 t7 = newTemp(Ity_I32);
6080
6081 /* Add lower halves. */
6082 assign(t0, binop(Iop_Add32,
6083 unop(Iop_16Sto32,
6084 unop(Iop_32to16, getIReg(rs))),
6085 unop(Iop_16Sto32,
6086 unop(Iop_32to16, getIReg(rt)))));
6087
6088 /* Bit 16 of the result. */
6089 assign(t6, binop(Iop_And32,
6090 unop(Iop_16Uto32,
6091 unop(Iop_32HIto16, mkexpr(t0))),
6092 mkU32(0x1)));
6093 /* Detect overflow. */
6094 assign(t1, binop(Iop_CmpNE32,
6095 binop(Iop_Shr32,
6096 binop(Iop_And32,
6097 mkexpr(t0),
6098 mkU32(0x8000)),
6099 mkU8(15)),
6100 mkexpr(t6)));
6101
6102 putDSPControl(IRExpr_ITE(mkexpr(t1),
6103 binop(Iop_Or32,
6104 getDSPControl(),
6105 mkU32(0x00100000)),
6106 getDSPControl()));
6107 /* Saturate if needed. */
6108 assign(t4, IRExpr_ITE(mkexpr(t1),
6109 IRExpr_ITE(binop(Iop_CmpEQ32,
6110 mkexpr(t6),
6111 mkU32(0x0)),
6112 mkU16(0x7fff),
6113 mkU16(0x8000)),
6114 unop(Iop_32to16, mkexpr(t0))));
6115
6116 /* Add higher halves. */
6117 assign(t2, binop(Iop_Add32,
6118 unop(Iop_16Sto32,
6119 unop(Iop_32HIto16, getIReg(rs))),
6120 unop(Iop_16Sto32,
6121 unop(Iop_32HIto16, getIReg(rt)))));
6122
6123 /* Bit 16 of the result. */
6124 assign(t7, binop(Iop_And32,
6125 unop(Iop_16Uto32,
6126 unop(Iop_32HIto16, mkexpr(t2))),
6127 mkU32(0x1)));
6128 /* Detect overflow. */
6129 assign(t3, binop(Iop_CmpNE32,
6130 binop(Iop_Shr32,
6131 binop(Iop_And32,
6132 mkexpr(t2),
6133 mkU32(0x00008000)),
6134 mkU8(15)),
6135 mkexpr(t7)));
6136
6137 putDSPControl(IRExpr_ITE(mkexpr(t3),
6138 binop(Iop_Or32,
6139 getDSPControl(),
6140 mkU32(0x00100000)),
6141 getDSPControl()));
6142 /* Saturate if needed. */
6143 assign(t5, IRExpr_ITE(mkexpr(t3),
6144 IRExpr_ITE(binop(Iop_CmpEQ32,
6145 mkexpr(t7),
6146 mkU32(0x0)),
6147 mkU16(0x7fff),
6148 mkU16(0x8000)),
6149 unop(Iop_32to16, mkexpr(t2))));
6150
6151 putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
6152 break;
6153 }
6154 case 0xF: { /* SUBQ_S.PH */
6155 DIP("subq_s.ph r%d r%d, r%d", rd, rs, rt);
6156 vassert(!mode64);
6157 t0 = newTemp(Ity_I32);
6158 t1 = newTemp(Ity_I1);
6159 t2 = newTemp(Ity_I32);
6160 t3 = newTemp(Ity_I1);
6161 t4 = newTemp(Ity_I16);
6162 t5 = newTemp(Ity_I16);
6163 t6 = newTemp(Ity_I32);
6164 t7 = newTemp(Ity_I32);
6165
6166 /* Subtract lower halves. */
6167 assign(t0, binop(Iop_Sub32,
6168 unop(Iop_16Sto32,
6169 unop(Iop_32to16, getIReg(rs))),
6170 unop(Iop_16Sto32,
6171 unop(Iop_32to16, getIReg(rt)))));
6172
6173 /* Bit 16 of the result. */
6174 assign(t6, binop(Iop_And32,
6175 unop(Iop_16Uto32,
6176 unop(Iop_32HIto16, mkexpr(t0))),
6177 mkU32(0x1)));
6178 /* Detect overflow or underflow. */
6179 assign(t1, binop(Iop_CmpNE32,
6180 binop(Iop_Shr32,
6181 binop(Iop_And32,
6182 mkexpr(t0),
6183 mkU32(0x8000)),
6184 mkU8(15)),
6185 mkexpr(t6)));
6186
6187 putDSPControl(IRExpr_ITE(mkexpr(t1),
6188 binop(Iop_Or32,
6189 getDSPControl(),
6190 mkU32(0x00100000)),
6191 getDSPControl()));
6192 /* Saturate if needed. */
6193 assign(t4, IRExpr_ITE(mkexpr(t1),
6194 IRExpr_ITE(binop(Iop_CmpEQ32,
6195 mkexpr(t6),
6196 mkU32(0x0)),
6197 mkU16(0x7fff),
6198 mkU16(0x8000)),
6199 unop(Iop_32to16, mkexpr(t0))));
6200
6201 /* Subtract higher halves. */
6202 assign(t2, binop(Iop_Sub32,
6203 unop(Iop_16Sto32,
6204 unop(Iop_32HIto16, getIReg(rs))),
6205 unop(Iop_16Sto32,
6206 unop(Iop_32HIto16, getIReg(rt)))));
6207
6208 /* Bit 16 of the result. */
6209 assign(t7, binop(Iop_And32,
6210 unop(Iop_16Uto32,
6211 unop(Iop_32HIto16, mkexpr(t2))),
6212 mkU32(0x1)));
6213 /* Detect overflow or underflow. */
6214 assign(t3, binop(Iop_CmpNE32,
6215 binop(Iop_Shr32,
6216 binop(Iop_And32,
6217 mkexpr(t2),
6218 mkU32(0x00008000)),
6219 mkU8(15)),
6220 mkexpr(t7)));
6221
6222 putDSPControl(IRExpr_ITE(mkexpr(t3),
6223 binop(Iop_Or32,
6224 getDSPControl(),
6225 mkU32(0x00100000)),
6226 getDSPControl()));
6227 /* Saturate if needed. */
6228 assign(t5, IRExpr_ITE(mkexpr(t3),
6229 IRExpr_ITE(binop(Iop_CmpEQ32,
6230 mkexpr(t7),
6231 mkU32(0x0)),
6232 mkU16(0x7fff),
6233 mkU16(0x8000)),
6234 unop(Iop_32to16, mkexpr(t2))));
6235
6236 putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
6237 break;
6238 }
6239 case 0x10: { /* ADDSC */
6240 DIP("addsc r%d, r%d, r%d", rd, rs, rt);
6241 vassert(!mode64);
6242 t0 = newTemp(Ity_I64);
6243 t1 = newTemp(Ity_I1);
6244
6245 /* The carry bit result out of the addition operation is
6246 written to bit 13(the c field) of the DSPControl reg. */
6247 assign(t0, binop(Iop_Add64,
6248 unop(Iop_32Uto64, getIReg(rs)),
6249 unop(Iop_32Uto64, getIReg(rt))));
6250
6251 assign(t1, binop(Iop_CmpEQ32,
6252 binop(Iop_And32,
6253 unop(Iop_64HIto32, mkexpr(t0)),
6254 mkU32(0x1)),
6255 mkU32(0x1)));
6256 putDSPControl(IRExpr_ITE(mkexpr(t1),
6257 binop(Iop_Or32,
6258 getDSPControl(),
6259 mkU32(0x2000)),
6260 binop(Iop_And32,
6261 getDSPControl(),
6262 mkU32(0xffffdfff))));
6263
6264 putIReg(rd, unop(Iop_64to32, mkexpr(t0)));
6265 break;
6266 }
6267 case 0x11: { /* ADDWC */
6268 DIP("addwc r%d, r%d, r%d", rd, rs, rt);
6269 vassert(!mode64);
6270 t0 = newTemp(Ity_I32);
6271 t1 = newTemp(Ity_I64);
6272 t2 = newTemp(Ity_I32);
6273 t3 = newTemp(Ity_I32);
6274 t4 = newTemp(Ity_I1);
6275
6276 /* Get carry bit from DSPControl register. */
6277 assign(t0, binop(Iop_Shr32,
6278 binop(Iop_And32,
6279 getDSPControl(),
6280 mkU32(0x2000)),
6281 mkU8(0xd)));
6282 assign(t1, binop(Iop_Add64,
6283 unop(Iop_32Sto64, getIReg(rs)),
6284 unop(Iop_32Sto64,
6285 binop(Iop_Add32,
6286 getIReg(rt),
6287 mkexpr(t0)))));
6288
6289 /* Extract bits 32 and 31. */
6290 assign(t2, binop(Iop_And32,
6291 unop(Iop_64HIto32, mkexpr(t1)),
6292 mkU32(0x1)));
6293 assign(t3, binop(Iop_Shr32,
6294 binop(Iop_And32,
6295 unop(Iop_64to32, mkexpr(t1)),
6296 mkU32(0x80000000)),
6297 mkU8(31)));
6298 assign(t4, binop(Iop_CmpNE32, mkexpr(t2), mkexpr(t3)));
6299
6300 putDSPControl(IRExpr_ITE(mkexpr(t4),
6301 binop(Iop_Or32,
6302 getDSPControl(),
6303 mkU32(0x00100000)),
6304 getDSPControl()));
6305 putIReg(rd, unop(Iop_64to32, mkexpr(t1)));
6306 break;
6307 }
6308 case 0x12: { /* MODSUB */
6309 DIP("modsub r%d, r%d, r%d", rd, rs, rt);
6310 vassert(!mode64);
6311 t0 = newTemp(Ity_I32);
6312 t1 = newTemp(Ity_I32);
6313 t2 = newTemp(Ity_I32);
6314
6315 /* decr_7..0 */
6316 assign(t0,
6317 unop(Iop_8Uto32,
6318 unop(Iop_16to8,
6319 unop(Iop_32to16, getIReg(rt)))));
6320
6321 /* lastindex_15..0 */
6322 assign(t1,
6323 unop(Iop_16Uto32,
6324 binop(Iop_8HLto16,
6325 unop(Iop_16to8,
6326 unop(Iop_32HIto16, getIReg(rt))),
6327 unop(Iop_16HIto8,
6328 unop(Iop_32to16, getIReg(rt))))));
6329 /* temp_15..0 */
6330 assign(t2,
6331 IRExpr_ITE(binop(Iop_CmpEQ32,
6332 getIReg(rs),
6333 mkU32(0x00000000)),
6334 mkexpr(t1),
6335 binop(Iop_Sub32,
6336 getIReg(rs), mkexpr(t0))));
6337 putIReg(rd, mkexpr(t2));
6338 break;
6339 }
6340 case 0x14: { /* RADDU.W.QB */
6341 DIP("raddu.w.qb r%d, r%d", rd, rs);
6342 vassert(!mode64);
6343 putIReg(rd, binop(Iop_Add32,
6344 binop(Iop_Add32,
6345 unop(Iop_8Uto32,
6346 unop(Iop_16to8,
6347 unop(Iop_32to16,
6348 getIReg(rs)))),
6349 unop(Iop_8Uto32,
6350 unop(Iop_16HIto8,
6351 unop(Iop_32to16,
6352 getIReg(rs))))),
6353 binop(Iop_Add32,
6354 unop(Iop_8Uto32,
6355 unop(Iop_16to8,
6356 unop(Iop_32HIto16,
6357 getIReg(rs)))),
6358 unop(Iop_8Uto32,
6359 unop(Iop_16HIto8,
6360 unop(Iop_32HIto16,
6361 getIReg(rs)))))));
6362 break;
6363 }
6364 case 0x16: { /* ADDQ_S.W */
6365 DIP("addq_s.w r%d, r%d, r%d", rd, rs, rt);
6366 vassert(!mode64);
6367 t0 = newTemp(Ity_I64);
6368 t1 = newTemp(Ity_I1);
6369 t2 = newTemp(Ity_I32);
6370 t3 = newTemp(Ity_I32);
6371
6372 assign(t0, binop(Iop_Add64,
6373 unop(Iop_32Sto64, getIReg(rs)),
6374 unop(Iop_32Sto64, getIReg(rt))));
6375
6376 assign(t3, binop(Iop_And32,
6377 unop(Iop_64HIto32, mkexpr(t0)),
6378 mkU32(0x1)));
6379 assign(t1, binop(Iop_CmpNE32,
6380 binop(Iop_Shr32,
6381 binop(Iop_And32,
6382 unop(Iop_64to32, mkexpr(t0)),
6383 mkU32(0x80000000)),
6384 mkU8(31)),
6385 mkexpr(t3)));
6386
6387 putDSPControl(IRExpr_ITE(mkexpr(t1),
6388 binop(Iop_Or32,
6389 getDSPControl(),
6390 mkU32(0x00100000)),
6391 getDSPControl()));
6392
6393 putIReg(rd, IRExpr_ITE(mkexpr(t1),
6394 IRExpr_ITE(binop(Iop_CmpEQ32,
6395 mkexpr(t3),
6396 mkU32(0x0)),
6397 mkU32(0x7fffffff),
6398 mkU32(0x80000000)),
6399 unop(Iop_64to32, mkexpr(t0))));
6400 break;
6401 }
6402 case 0x17: { /* SUBQ_S.W */
6403 DIP("subq_s.w r%d, r%d, r%d", rd, rs, rt);
6404 vassert(!mode64);
6405 t0 = newTemp(Ity_I64);
6406 t1 = newTemp(Ity_I1);
6407 t2 = newTemp(Ity_I32);
6408 t3 = newTemp(Ity_I32);
6409
6410 assign(t0, binop(Iop_Sub64,
6411 unop(Iop_32Sto64, getIReg(rs)),
6412 unop(Iop_32Sto64, getIReg(rt))));
6413
6414 assign(t3, binop(Iop_And32,
6415 unop(Iop_64HIto32, mkexpr(t0)),
6416 mkU32(0x1)));
6417 assign(t1, binop(Iop_CmpNE32,
6418 binop(Iop_Shr32,
6419 binop(Iop_And32,
6420 unop(Iop_64to32, mkexpr(t0)),
6421 mkU32(0x80000000)),
6422 mkU8(31)),
6423 mkexpr(t3)));
6424
6425 putDSPControl(IRExpr_ITE(mkexpr(t1),
6426 binop(Iop_Or32,
6427 getDSPControl(),
6428 mkU32(0x00100000)),
6429 getDSPControl()));
6430
6431 putIReg(rd, IRExpr_ITE(mkexpr(t1),
6432 IRExpr_ITE(binop(Iop_CmpEQ32,
6433 mkexpr(t3),
6434 mkU32(0x0)),
6435 mkU32(0x7fffffff),
6436 mkU32(0x80000000)),
6437 unop(Iop_64to32, mkexpr(t0))));
6438 break;
6439 }
6440 case 0x1C: { /* MULEQ_S.W.PHL */
6441 DIP("muleq_s.w.phl r%d, r%d, r%d", rd, rs, rt);
6442 vassert(!mode64);
6443 t0 = newTemp(Ity_I32);
6444 t1 = newTemp(Ity_I1);
6445 t2 = newTemp(Ity_I1);
6446 t3 = newTemp(Ity_I32);
6447
6448 assign(t0,
6449 binop(Iop_Shl32,
6450 binop(Iop_Mul32,
6451 unop(Iop_16Sto32,
6452 unop(Iop_32HIto16, getIReg(rt))),
6453 unop(Iop_16Sto32,
6454 unop(Iop_32HIto16, getIReg(rs)))),
6455 mkU8(0x1)));
6456 assign(t1, binop(Iop_CmpEQ32,
6457 binop(Iop_And32,
6458 getIReg(rt),
6459 mkU32(0xffff0000)),
6460 mkU32(0x80000000)));
6461 assign(t2, binop(Iop_CmpEQ32,
6462 binop(Iop_And32,
6463 getIReg(rs),
6464 mkU32(0xffff0000)),
6465 mkU32(0x80000000)));
6466 assign(t3, IRExpr_ITE(mkexpr(t1),
6467 IRExpr_ITE(mkexpr(t2),
6468 binop(Iop_Or32,
6469 getDSPControl(),
6470 mkU32(0x00200000)),
6471 getDSPControl()),
6472 getDSPControl()));
6473 putDSPControl(mkexpr(t3));
6474
6475 putIReg(rd, IRExpr_ITE(mkexpr(t1),
6476 IRExpr_ITE(mkexpr(t2),
6477 mkU32(0x7fffffff),
6478 mkexpr(t0)),
6479 mkexpr(t0)));
6480 break;
6481 }
6482 case 0x1D: { /* MULEQ_S.W.PHR */
6483 DIP("muleq_s.w.phr r%d, r%d, r%d", rd, rs, rt);
6484 vassert(!mode64);
6485 t0 = newTemp(Ity_I32);
6486 t1 = newTemp(Ity_I1);
6487 t2 = newTemp(Ity_I1);
6488
6489 assign(t0,
6490 binop(Iop_Shl32,
6491 binop(Iop_Mul32,
6492 unop(Iop_16Sto32,
6493 unop(Iop_32to16, getIReg(rt))),
6494 unop(Iop_16Sto32,
6495 unop(Iop_32to16, getIReg(rs)))),
6496 mkU8(0x1)));
6497 assign(t1, binop(Iop_CmpEQ32,
6498 binop(Iop_And32,
6499 getIReg(rt),
6500 mkU32(0xffff)),
6501 mkU32(0x8000)));
6502 assign(t2, binop(Iop_CmpEQ32,
6503 binop(Iop_And32,
6504 getIReg(rs),
6505 mkU32(0xffff)),
6506 mkU32(0x8000)));
6507 putDSPControl(IRExpr_ITE(mkexpr(t1),
6508 IRExpr_ITE(mkexpr(t2),
6509 binop(Iop_Or32,
6510 getDSPControl(),
6511 mkU32(0x00200000)
6512 ),
6513 getDSPControl()),
6514 getDSPControl()));
6515 putIReg(rd, IRExpr_ITE(mkexpr(t1),
6516 IRExpr_ITE(mkexpr(t2),
6517 mkU32(0x7fffffff),
6518 mkexpr(t0)),
6519 mkexpr(t0)));
6520 break;
6521 }
6522 case 0x1E: { /* MULQ_S.PH */
6523 DIP("mulq_s.ph r%d, r%d, r%d", rd, rs, rt);
6524 vassert(!mode64);
6525 t0 = newTemp(Ity_I32);
6526 t1 = newTemp(Ity_I32);
6527 t2 = newTemp(Ity_I16);
6528 t3 = newTemp(Ity_I16);
6529 t5 = newTemp(Ity_I32);
6530 t6 = newTemp(Ity_I32);
6531 t7 = newTemp(Ity_I32);
6532 t8 = newTemp(Ity_I32);
6533
6534 assign(t5,
6535 unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rs))));
6536 assign(t6,
6537 unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
6538
6539 assign(t7,
6540 unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rs))));
6541 assign(t8,
6542 unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rt))));
6543
6544 assign(t0, binop(Iop_And32,
6545 unop(Iop_1Sto32,
6546 binop(Iop_CmpEQ32,
6547 binop(Iop_And32,
6548 mkexpr(t5),
6549 mkU32(0xffff)),
6550 mkU32(0x8000))),
6551 unop(Iop_1Sto32,
6552 binop(Iop_CmpEQ32,
6553 binop(Iop_And32,
6554 mkexpr(t6),
6555 mkU32(0xffff)),
6556 mkU32(0x8000)))));
6557 assign(t1, binop(Iop_And32,
6558 unop(Iop_1Sto32,
6559 binop(Iop_CmpEQ32,
6560 binop(Iop_And32,
6561 mkexpr(t7),
6562 mkU32(0xffff)),
6563 mkU32(0x8000))),
6564 unop(Iop_1Sto32,
6565 binop(Iop_CmpEQ32,
6566 binop(Iop_And32,
6567 mkexpr(t8),
6568 mkU32(0xffff)),
6569 mkU32(0x8000)))));
6570
6571 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
6572 binop(Iop_Or32,
6573 mkexpr(t0),
6574 mkexpr(t1)),
6575 mkU32(0x0)),
6576 getDSPControl(),
6577 binop(Iop_Or32,
6578 getDSPControl(),
6579 mkU32(0x200000))));
6580
6581 assign(t2, unop(Iop_32HIto16,
6582 binop(Iop_Shl32,
6583 unop(Iop_64to32,
6584 binop(Iop_MullS32,
6585 mkexpr(t7),
6586 mkexpr(t8))),
6587 mkU8(0x1))));
6588 assign(t3, unop(Iop_32HIto16,
6589 binop(Iop_Shl32,
6590 unop(Iop_64to32,
6591 binop(Iop_MullS32,
6592 mkexpr(t5),
6593 mkexpr(t6))),
6594 mkU8(0x1))));
6595 putIReg(rd, binop(Iop_16HLto32,
6596 IRExpr_ITE(binop(Iop_CmpEQ32,
6597 mkexpr(t1),
6598 mkU32(0x0)),
6599 mkexpr(t2),
6600 mkU16(0x7fff)),
6601 IRExpr_ITE(binop(Iop_CmpEQ32,
6602 mkexpr(t0),
6603 mkU32(0x0)),
6604 mkexpr(t3),
6605 mkU16(0x7fff))));
6606 break;
6607 }
6608 case 0x1F: { /* MULQ_RS.PH */
6609 DIP("mulq_rs.ph r%d, r%d, r%d", rd, rs, rt);
6610 vassert(!mode64);
6611 t0 = newTemp(Ity_I32);
6612 t1 = newTemp(Ity_I1);
6613 t2 = newTemp(Ity_I1);
6614 t3 = newTemp(Ity_I16);
6615 t4 = newTemp(Ity_I32);
6616 t5 = newTemp(Ity_I1);
6617 t6 = newTemp(Ity_I1);
6618 t7 = newTemp(Ity_I16);
6619
6620 /* Multiply and round lower halfwords. */
6621 assign(t0, binop(Iop_Add32,
6622 binop(Iop_Shl32,
6623 binop(Iop_Mul32,
6624 unop(Iop_16Sto32,
6625 unop(Iop_32to16,
6626 getIReg(rt))),
6627 unop(Iop_16Sto32,
6628 unop(Iop_32to16,
6629 getIReg(rs)))),
6630 mkU8(0x1)),
6631 mkU32(0x00008000)));
6632 assign(t1, binop(Iop_CmpEQ32,
6633 binop(Iop_And32,
6634 getIReg(rt), mkU32(0xffff)),
6635 mkU32(0x8000)));
6636 assign(t2, binop(Iop_CmpEQ32,
6637 binop(Iop_And32,
6638 getIReg(rs), mkU32(0xffff)),
6639 mkU32(0x8000)));
6640 putDSPControl(IRExpr_ITE(mkexpr(t1),
6641 IRExpr_ITE(mkexpr(t2),
6642 binop(Iop_Or32,
6643 getDSPControl(),
6644 mkU32(0x00200000)
6645 ),
6646 getDSPControl()),
6647 getDSPControl()));
6648 assign(t3, IRExpr_ITE(mkexpr(t1),
6649 IRExpr_ITE(mkexpr(t2),
6650 mkU16(0x7fff),
6651 unop(Iop_32HIto16,
6652 mkexpr(t0))),
6653 unop(Iop_32HIto16, mkexpr(t0))));
6654
6655 /* Multiply and round higher halfwords. */
6656 assign(t4, binop(Iop_Add32,
6657 binop(Iop_Shl32,
6658 binop(Iop_Mul32,
6659 unop(Iop_16Sto32,
6660 unop(Iop_32HIto16,
6661 getIReg(rt))),
6662 unop(Iop_16Sto32,
6663 unop(Iop_32HIto16,
6664 getIReg(rs)))),
6665 mkU8(0x1)),
6666 mkU32(0x00008000)));
6667 assign(t5, binop(Iop_CmpEQ32,
6668 binop(Iop_And32,
6669 getIReg(rt),
6670 mkU32(0xffff0000)),
6671 mkU32(0x80000000)));
6672 assign(t6, binop(Iop_CmpEQ32,
6673 binop(Iop_And32,
6674 getIReg(rs),
6675 mkU32(0xffff0000)),
6676 mkU32(0x80000000)));
6677 putDSPControl(IRExpr_ITE(mkexpr(t5),
6678 IRExpr_ITE(mkexpr(t6),
6679 binop(Iop_Or32,
6680 getDSPControl(),
6681 mkU32(0x00200000)),
6682 getDSPControl()),
6683 getDSPControl()));
6684 assign(t7, IRExpr_ITE(mkexpr(t5),
6685 IRExpr_ITE(mkexpr(t6),
6686 mkU16(0x7fff),
6687 unop(Iop_32HIto16,
6688 mkexpr(t4))),
6689 unop(Iop_32HIto16, mkexpr(t4))));
6690
6691 putIReg(rd, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3)));
6692 break;
6693 }
6694 default:
6695 return -1;
6696 }
6697 break; /* end of ADDU.QB */
6698 }
6699 case 0x11: { /* CMPU.EQ.QB */
6700 switch(sa) {
6701 case 0x0: { /* CMPU.EQ.QB */
6702 DIP("cmpu.eq.qb r%d, r%d", rs, rt);
6703 vassert(!mode64);
6704 t1 = newTemp(Ity_I1);
6705 t2 = newTemp(Ity_I1);
6706 t3 = newTemp(Ity_I1);
6707 t4 = newTemp(Ity_I1);
6708
6709 assign(t1,
6710 binop(Iop_CmpEQ32,
6711 binop(Iop_And32, getIReg(rs), mkU32(0xff)),
6712 binop(Iop_And32, getIReg(rt), mkU32(0xff))));
6713 putDSPControl(IRExpr_ITE(mkexpr(t1),
6714 binop(Iop_Or32,
6715 getDSPControl(),
6716 mkU32(0x01000000)),
6717 binop(Iop_And32,
6718 getDSPControl(),
6719 mkU32(0xfeffffff))));
6720
6721 assign(t2, binop(Iop_CmpEQ32,
6722 unop(Iop_8Uto32,
6723 unop(Iop_16HIto8,
6724 unop(Iop_32to16,
6725 getIReg(rs)))),
6726 unop(Iop_8Uto32,
6727 unop(Iop_16HIto8,
6728 unop(Iop_32to16,
6729 getIReg(rt))))));
6730 putDSPControl(IRExpr_ITE(mkexpr(t2),
6731 binop(Iop_Or32,
6732 getDSPControl(),
6733 mkU32(0x02000000)),
6734 binop(Iop_And32,
6735 getDSPControl(),
6736 mkU32(0xfdffffff))));
6737
6738 assign(t3, binop(Iop_CmpEQ32,
6739 unop(Iop_8Uto32,
6740 unop(Iop_16to8,
6741 unop(Iop_32HIto16,
6742 getIReg(rs)))),
6743 unop(Iop_8Uto32,
6744 unop(Iop_16to8,
6745 unop(Iop_32HIto16,
6746 getIReg(rt))))));
6747 putDSPControl(IRExpr_ITE(mkexpr(t3),
6748 binop(Iop_Or32,
6749 getDSPControl(),
6750 mkU32(0x04000000)),
6751 binop(Iop_And32,
6752 getDSPControl(),
6753 mkU32(0xfbffffff))));
6754
6755 assign(t4, binop(Iop_CmpEQ32,
6756 unop(Iop_8Uto32,
6757 unop(Iop_16HIto8,
6758 unop(Iop_32HIto16,
6759 getIReg(rs)))),
6760 unop(Iop_8Uto32,
6761 unop(Iop_16HIto8,
6762 unop(Iop_32HIto16,
6763 getIReg(rt))))));
6764 putDSPControl(IRExpr_ITE(mkexpr(t4),
6765 binop(Iop_Or32,
6766 getDSPControl(),
6767 mkU32(0x08000000)),
6768 binop(Iop_And32,
6769 getDSPControl(),
6770 mkU32(0xf7ffffff))));
6771 break;
6772 }
6773 case 0x1: { /* CMPU.LT.QB */
6774 DIP("cmpu.lt.qb r%d, r%d", rs, rt);
6775 vassert(!mode64);
6776 t1 = newTemp(Ity_I1);
6777 t2 = newTemp(Ity_I1);
6778 t3 = newTemp(Ity_I1);
6779 t4 = newTemp(Ity_I1);
6780
6781 assign(t1, binop(Iop_CmpLT32U,
6782 unop(Iop_8Uto32,
6783 unop(Iop_16to8,
6784 unop(Iop_32to16,
6785 getIReg(rs)))),
6786 unop(Iop_8Uto32,
6787 unop(Iop_16to8,
6788 unop(Iop_32to16,
6789 getIReg(rt))))));
6790 putDSPControl(IRExpr_ITE(mkexpr(t1),
6791 binop(Iop_Or32,
6792 getDSPControl(),
6793 mkU32(0x01000000)),
6794 binop(Iop_And32,
6795 getDSPControl(),
6796 mkU32(0xfeffffff))));
6797
6798 assign(t2, binop(Iop_CmpLT32U,
6799 unop(Iop_8Uto32,
6800 unop(Iop_16HIto8,
6801 unop(Iop_32to16,
6802 getIReg(rs)))),
6803 unop(Iop_8Uto32,
6804 unop(Iop_16HIto8,
6805 unop(Iop_32to16,
6806 getIReg(rt))))));
6807 putDSPControl(IRExpr_ITE(mkexpr(t2),
6808 binop(Iop_Or32,
6809 getDSPControl(),
6810 mkU32(0x02000000)),
6811 binop(Iop_And32,
6812 getDSPControl(),
6813 mkU32(0xfdffffff))));
6814
6815 assign(t3, binop(Iop_CmpLT32U,
6816 unop(Iop_8Uto32,
6817 unop(Iop_16to8,
6818 unop(Iop_32HIto16,
6819 getIReg(rs)))),
6820 unop(Iop_8Uto32,
6821 unop(Iop_16to8,
6822 unop(Iop_32HIto16,
6823 getIReg(rt))))));
6824 putDSPControl(IRExpr_ITE(mkexpr(t3),
6825 binop(Iop_Or32,
6826 getDSPControl(),
6827 mkU32(0x04000000)),
6828 binop(Iop_And32,
6829 getDSPControl(),
6830 mkU32(0xfbffffff))));
6831
6832 assign(t4, binop(Iop_CmpLT32U,
6833 unop(Iop_8Uto32,
6834 unop(Iop_16HIto8,
6835 unop(Iop_32HIto16,
6836 getIReg(rs)))),
6837 unop(Iop_8Uto32,
6838 unop(Iop_16HIto8,
6839 unop(Iop_32HIto16,
6840 getIReg(rt))))));
6841 putDSPControl(IRExpr_ITE(mkexpr(t4),
6842 binop(Iop_Or32,
6843 getDSPControl(),
6844 mkU32(0x08000000)),
6845 binop(Iop_And32,
6846 getDSPControl(),
6847 mkU32(0xf7ffffff))));
6848 break;
6849 }
6850 case 0x2: { /* CMPU.LE.QB */
6851 DIP("cmpu.le.qb r%d, r%d", rs, rt);
6852 vassert(!mode64);
6853 t1 = newTemp(Ity_I1);
6854 t2 = newTemp(Ity_I1);
6855 t3 = newTemp(Ity_I1);
6856 t4 = newTemp(Ity_I1);
6857
6858 assign(t1, binop(Iop_CmpLE32U,
6859 unop(Iop_8Uto32,
6860 unop(Iop_16to8,
6861 unop(Iop_32to16,
6862 getIReg(rs)))),
6863 unop(Iop_8Uto32,
6864 unop(Iop_16to8,
6865 unop(Iop_32to16,
6866 getIReg(rt))))));
6867 putDSPControl(IRExpr_ITE(mkexpr(t1),
6868 binop(Iop_Or32,
6869 getDSPControl(),
6870 mkU32(0x01000000)),
6871 binop(Iop_And32,
6872 getDSPControl(),
6873 mkU32(0xfeffffff))));
6874
6875 assign(t2, binop(Iop_CmpLE32U,
6876 unop(Iop_8Uto32,
6877 unop(Iop_16HIto8,
6878 unop(Iop_32to16,
6879 getIReg(rs)))),
6880 unop(Iop_8Uto32,
6881 unop(Iop_16HIto8,
6882 unop(Iop_32to16,
6883 getIReg(rt))))));
6884 putDSPControl(IRExpr_ITE(mkexpr(t2),
6885 binop(Iop_Or32,
6886 getDSPControl(),
6887 mkU32(0x02000000)),
6888 binop(Iop_And32,
6889 getDSPControl(),
6890 mkU32(0xfdffffff))));
6891
6892 assign(t3, binop(Iop_CmpLE32U,
6893 unop(Iop_8Uto32,
6894 unop(Iop_16to8,
6895 unop(Iop_32HIto16,
6896 getIReg(rs)))),
6897 unop(Iop_8Uto32,
6898 unop(Iop_16to8,
6899 unop(Iop_32HIto16,
6900 getIReg(rt))))));
6901 putDSPControl(IRExpr_ITE(mkexpr(t3),
6902 binop(Iop_Or32,
6903 getDSPControl(),
6904 mkU32(0x04000000)),
6905 binop(Iop_And32,
6906 getDSPControl(),
6907 mkU32(0xfbffffff))));
6908
6909 assign(t4, binop(Iop_CmpLE32U,
6910 unop(Iop_8Uto32,
6911 unop(Iop_16HIto8,
6912 unop(Iop_32HIto16,
6913 getIReg(rs)))),
6914 unop(Iop_8Uto32,
6915 unop(Iop_16HIto8,
6916 unop(Iop_32HIto16,
6917 getIReg(rt))))));
6918 putDSPControl(IRExpr_ITE(mkexpr(t4),
6919 binop(Iop_Or32,
6920 getDSPControl(),
6921 mkU32(0x08000000)),
6922 binop(Iop_And32,
6923 getDSPControl(),
6924 mkU32(0xf7ffffff))));
6925 break;
6926 }
6927 case 0x3: { /* PICK.QB */
6928 DIP("pick.qb r%d, r%d, r%d", rd, rs, rt);
6929 vassert(!mode64);
6930 t0 = newTemp(Ity_I32);
6931 t1 = newTemp(Ity_I8);
6932 t2 = newTemp(Ity_I8);
6933 t3 = newTemp(Ity_I8);
6934 t4 = newTemp(Ity_I8);
6935
6936 assign(t0, getDSPControl());
6937 assign(t1, IRExpr_ITE(binop(Iop_CmpNE32,
6938 binop(Iop_And32,
6939 mkexpr(t0),
6940 mkU32(0x01000000)),
6941 mkU32(0x0)),
6942 unop(Iop_16to8,
6943 unop(Iop_32to16,
6944 getIReg(rs))),
6945 unop(Iop_16to8,
6946 unop(Iop_32to16,
6947 getIReg(rt)))));
6948 assign(t2, IRExpr_ITE(binop(Iop_CmpNE32,
6949 binop(Iop_And32,
6950 mkexpr(t0),
6951 mkU32(0x02000000)),
6952 mkU32(0x0)),
6953 unop(Iop_16HIto8,
6954 unop(Iop_32to16, getIReg(rs))),
6955 unop(Iop_16HIto8,
6956 unop(Iop_32to16,
6957 getIReg(rt)))));
6958 assign(t3, IRExpr_ITE(binop(Iop_CmpNE32,
6959 binop(Iop_And32,
6960 mkexpr(t0),
6961 mkU32(0x04000000)),
6962 mkU32(0x0)),
6963 unop(Iop_16to8,
6964 unop(Iop_32HIto16,
6965 getIReg(rs))),
6966 unop(Iop_16to8,
6967 unop(Iop_32HIto16,
6968 getIReg(rt)))));
6969 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
6970 binop(Iop_And32,
6971 mkexpr(t0),
6972 mkU32(0x08000000)),
6973 mkU32(0x0)),
6974 unop(Iop_16HIto8,
6975 unop(Iop_32HIto16,
6976 getIReg(rs))),
6977 unop(Iop_16HIto8,
6978 unop(Iop_32HIto16,
6979 getIReg(rt)))));
6980 putIReg(rd,
6981 binop(Iop_16HLto32,
6982 binop(Iop_8HLto16, mkexpr(t4), mkexpr(t3)),
6983 binop(Iop_8HLto16, mkexpr(t2), mkexpr(t1))));
6984 break;
6985 }
6986 case 0x4: { /* CMPGU.EQ.QB */
6987 DIP("cmpgu.eq.qb r%d, r%d, r%d", rd, rs, rt);
6988 vassert(!mode64);
6989 t1 = newTemp(Ity_I1);
6990 t2 = newTemp(Ity_I1);
6991 t3 = newTemp(Ity_I1);
6992 t4 = newTemp(Ity_I1);
6993 t5 = newTemp(Ity_I32);
6994 t6 = newTemp(Ity_I32);
6995 t7 = newTemp(Ity_I32);
6996 t8 = newTemp(Ity_I32);
6997
6998 assign(t1, binop(Iop_CmpEQ32,
6999 unop(Iop_8Uto32,
7000 unop(Iop_16to8,
7001 unop(Iop_32to16, getIReg(rs)))),
7002 unop(Iop_8Uto32,
7003 unop(Iop_16to8,
7004 unop(Iop_32to16,
7005 getIReg(rt))))));
7006 assign(t5, IRExpr_ITE(mkexpr(t1),
7007 mkU32(0x00000001), mkU32(0)));
7008
7009 assign(t2, binop(Iop_CmpEQ32,
7010 unop(Iop_8Uto32,
7011 unop(Iop_16HIto8,
7012 unop(Iop_32to16, getIReg(rs)))),
7013 unop(Iop_8Uto32,
7014 unop(Iop_16HIto8,
7015 unop(Iop_32to16,
7016 getIReg(rt))))));
7017 assign(t6, IRExpr_ITE(mkexpr(t2),
7018 mkU32(0x00000002), mkU32(0)));
7019
7020 assign(t3, binop(Iop_CmpEQ32,
7021 unop(Iop_8Uto32,
7022 unop(Iop_16to8,
7023 unop(Iop_32HIto16,
7024 getIReg(rs)))),
7025 unop(Iop_8Uto32,
7026 unop(Iop_16to8,
7027 unop(Iop_32HIto16,
7028 getIReg(rt))))));
7029 assign(t7, IRExpr_ITE(mkexpr(t3),
7030 mkU32(0x00000004), mkU32(0)));
7031
7032 assign(t4, binop(Iop_CmpEQ32,
7033 unop(Iop_8Uto32,
7034 unop(Iop_16HIto8,
7035 unop(Iop_32HIto16,
7036 getIReg(rs)))),
7037 unop(Iop_8Uto32,
7038 unop(Iop_16HIto8,
7039 unop(Iop_32HIto16,
7040 getIReg(rt))))));
7041 assign(t8, IRExpr_ITE(mkexpr(t4),
7042 mkU32(0x00000008), mkU32(0)));
7043
7044 putIReg(rd, binop(Iop_Or32,
7045 binop(Iop_Or32,
7046 binop(Iop_Or32,
7047 mkexpr(t5), mkexpr(t6)),
7048 mkexpr(t7)),
7049 mkexpr(t8)));
7050 break;
7051 }
7052 case 0x5: { /* CMPGU.LT.QB */
7053 DIP("cmpgu.lt.qb r%d, r%d, r%d", rd, rs, rt);
7054 vassert(!mode64);
7055 t1 = newTemp(Ity_I1);
7056 t2 = newTemp(Ity_I1);
7057 t3 = newTemp(Ity_I1);
7058 t4 = newTemp(Ity_I1);
7059 t5 = newTemp(Ity_I32);
7060 t6 = newTemp(Ity_I32);
7061 t7 = newTemp(Ity_I32);
7062 t8 = newTemp(Ity_I32);
7063
7064 assign(t1, binop(Iop_CmpLT32U,
7065 unop(Iop_8Uto32,
7066 unop(Iop_16to8,
7067 unop(Iop_32to16, getIReg(rs)))),
7068 unop(Iop_8Uto32,
7069 unop(Iop_16to8,
7070 unop(Iop_32to16,
7071 getIReg(rt))))));
7072 assign(t5, IRExpr_ITE(mkexpr(t1),
7073 mkU32(0x00000001), mkU32(0)));
7074
7075 assign(t2, binop(Iop_CmpLT32U,
7076 unop(Iop_8Uto32,
7077 unop(Iop_16HIto8,
7078 unop(Iop_32to16, getIReg(rs)))),
7079 unop(Iop_8Uto32,
7080 unop(Iop_16HIto8,
7081 unop(Iop_32to16,
7082 getIReg(rt))))));
7083 assign(t6, IRExpr_ITE(mkexpr(t2),
7084 mkU32(0x00000002), mkU32(0)));
7085
7086 assign(t3, binop(Iop_CmpLT32U,
7087 unop(Iop_8Uto32,
7088 unop(Iop_16to8,
7089 unop(Iop_32HIto16,
7090 getIReg(rs)))),
7091 unop(Iop_8Uto32,
7092 unop(Iop_16to8,
7093 unop(Iop_32HIto16,
7094 getIReg(rt))))));
7095 assign(t7, IRExpr_ITE(mkexpr(t3),
7096 mkU32(0x00000004), mkU32(0)));
7097
7098 assign(t4, binop(Iop_CmpLT32U,
7099 unop(Iop_8Uto32,
7100 unop(Iop_16HIto8,
7101 unop(Iop_32HIto16,
7102 getIReg(rs)))),
7103 unop(Iop_8Uto32,
7104 unop(Iop_16HIto8,
7105 unop(Iop_32HIto16,
7106 getIReg(rt))))));
7107 assign(t8, IRExpr_ITE(mkexpr(t4),
7108 mkU32(0x00000008), mkU32(0)));
7109 putIReg(rd, binop(Iop_Or32,
7110 binop(Iop_Or32,
7111 binop(Iop_Or32,
7112 mkexpr(t5), mkexpr(t6)),
7113 mkexpr(t7)),
7114 mkexpr(t8)));
7115 break;
7116 }
7117 case 0x6: { /* CMPGU.LE.QB */
7118 DIP("cmpgu.le.qb r%d, r%d, r%d", rd, rs, rt);
7119 vassert(!mode64);
7120 t1 = newTemp(Ity_I1);
7121 t2 = newTemp(Ity_I1);
7122 t3 = newTemp(Ity_I1);
7123 t4 = newTemp(Ity_I1);
7124 t5 = newTemp(Ity_I32);
7125 t6 = newTemp(Ity_I32);
7126 t7 = newTemp(Ity_I32);
7127 t8 = newTemp(Ity_I32);
7128
7129 assign(t1, binop(Iop_CmpLE32U,
7130 unop(Iop_8Uto32,
7131 unop(Iop_16to8,
7132 unop(Iop_32to16, getIReg(rs)))),
7133 unop(Iop_8Uto32,
7134 unop(Iop_16to8,
7135 unop(Iop_32to16,
7136 getIReg(rt))))));
7137 assign(t5, IRExpr_ITE(mkexpr(t1),
7138 mkU32(0x00000001), mkU32(0)));
7139
7140 assign(t2, binop(Iop_CmpLE32U,
7141 unop(Iop_8Uto32,
7142 unop(Iop_16HIto8,
7143 unop(Iop_32to16, getIReg(rs)))),
7144 unop(Iop_8Uto32,
7145 unop(Iop_16HIto8,
7146 unop(Iop_32to16,
7147 getIReg(rt))))));
7148 assign(t6, IRExpr_ITE(mkexpr(t2),
7149 mkU32(0x00000002), mkU32(0)));
7150
7151 assign(t3, binop(Iop_CmpLE32U,
7152 unop(Iop_8Uto32,
7153 unop(Iop_16to8,
7154 unop(Iop_32HIto16,
7155 getIReg(rs)))),
7156 unop(Iop_8Uto32,
7157 unop(Iop_16to8,
7158 unop(Iop_32HIto16,
7159 getIReg(rt))))));
7160 assign(t7, IRExpr_ITE(mkexpr(t3),
7161 mkU32(0x00000004), mkU32(0)));
7162
7163 assign(t4, binop(Iop_CmpLE32U,
7164 unop(Iop_8Uto32,
7165 unop(Iop_16HIto8,
7166 unop(Iop_32HIto16,
7167 getIReg(rs)))),
7168 unop(Iop_8Uto32,
7169 unop(Iop_16HIto8,
7170 unop(Iop_32HIto16,
7171 getIReg(rt))))));
7172 assign(t8, IRExpr_ITE(mkexpr(t4),
7173 mkU32(0x00000008), mkU32(0)));
7174 putIReg(rd, binop(Iop_Or32,
7175 binop(Iop_Or32,
7176 binop(Iop_Or32,
7177 mkexpr(t5), mkexpr(t6)),
7178 mkexpr(t7)),
7179 mkexpr(t8)));
7180 break;
7181 }
7182 case 0x8: { /* CMP.EQ.PH */
7183 DIP("cmp.eq.ph r%d, r%d", rs, rt);
7184 vassert(!mode64);
7185 t1 = newTemp(Ity_I1);
7186 t2 = newTemp(Ity_I1);
7187
7188 assign(t1, binop(Iop_CmpEQ16,
7189 unop(Iop_32to16, getIReg(rs)),
7190 unop(Iop_32to16, getIReg(rt))));
7191 putDSPControl(IRExpr_ITE(mkexpr(t1),
7192 binop(Iop_Or32,
7193 getDSPControl(),
7194 mkU32(0x01000000)),
7195 binop(Iop_And32,
7196 getDSPControl(),
7197 mkU32(0xfeffffff))));
7198 assign(t2, binop(Iop_CmpEQ16,
7199 unop(Iop_32HIto16, getIReg(rs)),
7200 unop(Iop_32HIto16, getIReg(rt))));
7201 putDSPControl(IRExpr_ITE(mkexpr(t2),
7202 binop(Iop_Or32,
7203 getDSPControl(),
7204 mkU32(0x02000000)),
7205 binop(Iop_And32,
7206 getDSPControl(),
7207 mkU32(0xfdffffff))));
7208 break;
7209 }
7210 case 0x9: { /* CMP.LT.PH */
7211 DIP("cmp.lt.ph r%d, r%d", rs, rt);
7212 vassert(!mode64);
7213 t1 = newTemp(Ity_I1);
7214 t2 = newTemp(Ity_I1);
7215
7216 assign(t1, binop(Iop_CmpLT32S,
7217 unop(Iop_16Sto32,
7218 unop(Iop_32to16, getIReg(rs))),
7219 unop(Iop_16Sto32,
7220 unop(Iop_32to16, getIReg(rt)))));
7221 putDSPControl(IRExpr_ITE(mkexpr(t1),
7222 binop(Iop_Or32,
7223 getDSPControl(),
7224 mkU32(0x01000000)),
7225 binop(Iop_And32,
7226 getDSPControl(),
7227 mkU32(0xfeffffff))));
7228
7229 assign(t2, binop(Iop_CmpLT32S,
7230 unop(Iop_16Sto32,
7231 unop(Iop_32HIto16, getIReg(rs))),
7232 unop(Iop_16Sto32,
7233 unop(Iop_32HIto16, getIReg(rt)))));
7234 putDSPControl(IRExpr_ITE(mkexpr(t2),
7235 binop(Iop_Or32,
7236 getDSPControl(),
7237 mkU32(0x02000000)),
7238 binop(Iop_And32,
7239 getDSPControl(),
7240 mkU32(0xfdffffff))));
7241 break;
7242 }
7243 case 0xA: { /* CMP.LE.PH */
7244 DIP("cmp.le.ph r%d, r%d", rs, rt);
7245 vassert(!mode64);
7246 t1 = newTemp(Ity_I1);
7247 t2 = newTemp(Ity_I1);
7248
7249 assign(t1, binop(Iop_CmpLE32S,
7250 unop(Iop_16Sto32,
7251 unop(Iop_32to16, getIReg(rs))),
7252 unop(Iop_16Sto32,
7253 unop(Iop_32to16, getIReg(rt)))));
7254 putDSPControl(IRExpr_ITE(mkexpr(t1),
7255 binop(Iop_Or32,
7256 getDSPControl(),
7257 mkU32(0x01000000)),
7258 binop(Iop_And32,
7259 getDSPControl(),
7260 mkU32(0xfeffffff))));
7261
7262 assign(t2, binop(Iop_CmpLE32S,
7263 unop(Iop_16Sto32,
7264 unop(Iop_32HIto16, getIReg(rs))),
7265 unop(Iop_16Sto32,
7266 unop(Iop_32HIto16, getIReg(rt)))));
7267 putDSPControl(IRExpr_ITE(mkexpr(t2),
7268 binop(Iop_Or32,
7269 getDSPControl(),
7270 mkU32(0x02000000)),
7271 binop(Iop_And32,
7272 getDSPControl(),
7273 mkU32(0xfdffffff))));
7274 break;
7275 }
7276 case 0xB: { /* PICK.PH */
7277 DIP("pick.qb r%d, r%d, r%d", rd, rs, rt);
7278 vassert(!mode64);
7279 t0 = newTemp(Ity_I32);
7280 t1 = newTemp(Ity_I16);
7281 t2 = newTemp(Ity_I16);
7282
7283 assign(t0, getDSPControl());
7284
7285 assign(t1, IRExpr_ITE(binop(Iop_CmpNE32,
7286 binop(Iop_And32,
7287 mkexpr(t0),
7288 mkU32(0x01000000)),
7289 mkU32(0x0)),
7290 unop(Iop_32to16, getIReg(rs)),
7291 unop(Iop_32to16, getIReg(rt))));
7292
7293 assign(t2, IRExpr_ITE(binop(Iop_CmpNE32,
7294 binop(Iop_And32,
7295 mkexpr(t0),
7296 mkU32(0x02000000)),
7297 mkU32(0x0)),
7298 unop(Iop_32HIto16, getIReg(rs)),
7299 unop(Iop_32HIto16, getIReg(rt))));
7300
7301 putIReg(rd, binop(Iop_16HLto32, mkexpr(t2), mkexpr(t1)));
7302 break;
7303 }
7304 case 0xC: { /* PRECRQ.QB.PH */
7305 DIP("precrq.qb.ph r%d, r%d, %d", rd, rs, rt);
7306 vassert(!mode64);
7307 putIReg(rd,
7308 binop(Iop_16HLto32,
7309 binop(Iop_8HLto16,
7310 unop(Iop_16HIto8,
7311 unop(Iop_32HIto16, getIReg(rs))),
7312 unop(Iop_16HIto8,
7313 unop(Iop_32to16, getIReg(rs)))),
7314 binop(Iop_8HLto16,
7315 unop(Iop_16HIto8,
7316 unop(Iop_32HIto16, getIReg(rt))),
7317 unop(Iop_16HIto8,
7318 unop(Iop_32to16, getIReg(rt))))));
7319 break;
7320 }
7321 case 0xD: { /* PRECR.QB.PH */
7322 DIP("precr.qb.ph r%d, r%d, r%d", rd, rs, rt);
7323 vassert(!mode64);
7324
7325 putIReg(rd,
7326 binop(Iop_16HLto32,
7327 binop(Iop_8HLto16,
7328 unop(Iop_16to8,
7329 unop(Iop_32HIto16, getIReg(rs))),
7330 unop(Iop_16to8,
7331 unop(Iop_32to16, getIReg(rs)))),
7332 binop(Iop_8HLto16,
7333 unop(Iop_16to8,
7334 unop(Iop_32HIto16, getIReg(rt))),
7335 unop(Iop_16to8,
7336 unop(Iop_32to16, getIReg(rt))))));
7337 break;
7338 }
7339 case 0xF: { /* PRECRQU_S.QB.PH */
7340 DIP("precrqu_s.qb.ph r%d, r%d, %d", rd, rs, rt);
7341 vassert(!mode64);
7342 t0 = newTemp(Ity_I8);
7343 t1 = newTemp(Ity_I8);
7344 t2 = newTemp(Ity_I8);
7345 t3 = newTemp(Ity_I8);
7346 t4 = newTemp(Ity_I8);
7347 t5 = newTemp(Ity_I32);
7348 t6 = newTemp(Ity_I1);
7349 t7 = newTemp(Ity_I8);
7350 t8 = newTemp(Ity_I1);
7351 t9 = newTemp(Ity_I32);
7352 t10 = newTemp(Ity_I8);
7353 t11 = newTemp(Ity_I1);
7354 t12 = newTemp(Ity_I32);
7355 t13 = newTemp(Ity_I8);
7356 t14 = newTemp(Ity_I1);
7357 t15 = newTemp(Ity_I32);
7358
7359 assign(t4, IRExpr_ITE(binop(Iop_CmpLT32U,
7360 mkU32(0x7f80),
7361 binop(Iop_And32,
7362 unop(Iop_16Uto32,
7363 unop(Iop_32to16,
7364 getIReg(rs))),
7365 mkU32(0x7fff))),
7366 mkU8(0xff),
7367 unop(Iop_16HIto8,
7368 unop(Iop_32to16,
7369 binop(Iop_Shl32,
7370 getIReg(rs),
7371 mkU8(1))))));
7372 assign(t0, IRExpr_ITE(binop(Iop_CmpEQ32,
7373 binop(Iop_And32,
7374 unop(Iop_16Uto32,
7375 unop(Iop_32to16,
7376 getIReg(rs))),
7377 mkU32(0x00008000)),
7378 mkU32(0x0)),
7379 mkexpr(t4),
7380 mkU8(0x0)));
7381 assign(t5, binop(Iop_And32,
7382 unop(Iop_16Uto32,
7383 unop(Iop_32to16,
7384 getIReg(rs))),
7385 mkU32(0x00008000)));
7386 assign(t6, binop(Iop_CmpLT32U,
7387 mkU32(0x7f80),
7388 binop(Iop_And32,
7389 unop(Iop_16Uto32,
7390 unop(Iop_32to16,
7391 getIReg(rs))),
7392 mkU32(0x7fff))));
7393 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
7394 mkexpr(t5),
7395 mkU32(0x0)),
7396 IRExpr_ITE(mkexpr(t6),
7397 binop(Iop_Or32,
7398 getDSPControl(),
7399 mkU32(0x00400000)
7400 ),
7401 getDSPControl()),
7402 binop(Iop_Or32,
7403 getDSPControl(),
7404 mkU32(0x00400000))));
7405
7406 assign(t7, IRExpr_ITE(binop(Iop_CmpLT32U,
7407 mkU32(0x7f80),
7408 binop(Iop_And32,
7409 unop(Iop_16Uto32,
7410 unop(Iop_32HIto16,
7411 getIReg(rs))),
7412 mkU32(0x7fff))),
7413 mkU8(0xff),
7414 unop(Iop_16HIto8,
7415 unop(Iop_32HIto16,
7416 binop(Iop_Shl32,
7417 getIReg(rs),
7418 mkU8(1))))));
7419 assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32,
7420 binop(Iop_And32,
7421 unop(Iop_16Uto32,
7422 unop(Iop_32HIto16,
7423 getIReg(rs))),
7424 mkU32(0x00008000)),
7425 mkU32(0x0)),
7426 mkexpr(t7),
7427 mkU8(0x0)));
7428 assign(t8, binop(Iop_CmpEQ32,
7429 binop(Iop_And32,
7430 unop(Iop_16Uto32,
7431 unop(Iop_32HIto16,
7432 getIReg(rs))),
7433 mkU32(0x00008000)),
7434 mkU32(0x0)));
7435 assign(t9, IRExpr_ITE(binop(Iop_CmpLT32U,
7436 mkU32(0x7f80),
7437 binop(Iop_And32,
7438 unop(Iop_16Uto32,
7439 unop(Iop_32HIto16,
7440 getIReg(rs))),
7441 mkU32(0x7fff))),
7442 binop(Iop_Or32,
7443 getDSPControl(),
7444 mkU32(0x00400000)),
7445 getDSPControl()));
7446 putDSPControl(IRExpr_ITE(mkexpr(t8),
7447 mkexpr(t9),
7448 binop(Iop_Or32,
7449 getDSPControl(),
7450 mkU32(0x00400000))));
7451
7452 assign(t10, IRExpr_ITE(binop(Iop_CmpLT32U,
7453 mkU32(0x7f80),
7454 binop(Iop_And32,
7455 unop(Iop_16Uto32,
7456 unop(Iop_32to16,
7457 getIReg(rt))),
7458 mkU32(0x7fff))),
7459 mkU8(0xff),
7460 unop(Iop_16HIto8,
7461 unop(Iop_32to16,
7462 binop(Iop_Shl32,
7463 getIReg(rt),
7464 mkU8(1))))));
7465 assign(t2, IRExpr_ITE(binop(Iop_CmpEQ32,
7466 binop(Iop_And32,
7467 unop(Iop_16Uto32,
7468 unop(Iop_32to16,
7469 getIReg(rt))),
7470 mkU32(0x00008000)),
7471 mkU32(0x0)),
7472 mkexpr(t10),
7473 mkU8(0x0)));
7474 assign(t11, binop(Iop_CmpEQ32,
7475 binop(Iop_And32,
7476 unop(Iop_16Uto32,
7477 unop(Iop_32to16,
7478 getIReg(rt))),
7479 mkU32(0x00008000)),
7480 mkU32(0x0)));
7481 assign(t12, IRExpr_ITE(binop(Iop_CmpLT32U,
7482 mkU32(0x7f80),
7483 binop(Iop_And32,
7484 unop(Iop_16Uto32,
7485 unop(Iop_32to16,
7486 getIReg(rt))),
7487 mkU32(0x7fff))),
7488 binop(Iop_Or32,
7489 getDSPControl(),
7490 mkU32(0x00400000)),
7491 getDSPControl()));
7492 putDSPControl(IRExpr_ITE(mkexpr(t11),
7493 mkexpr(t12),
7494 binop(Iop_Or32,
7495 getDSPControl(),
7496 mkU32(0x00400000))));
7497
7498 assign(t13, IRExpr_ITE(binop(Iop_CmpLT32U,
7499 mkU32(0x7f80),
7500 binop(Iop_And32,
7501 unop(Iop_16Uto32,
7502 unop(Iop_32HIto16,
7503 getIReg(rt))),
7504 mkU32(0x7fff))),
7505 mkU8(0xff),
7506 unop(Iop_16HIto8,
7507 unop(Iop_32HIto16,
7508 binop(Iop_Shl32,
7509 getIReg(rt),
7510 mkU8(1))))));
7511 assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
7512 binop(Iop_And32,
7513 unop(Iop_16Uto32,
7514 unop(Iop_32HIto16,
7515 getIReg(rt))),
7516 mkU32(0x00008000)),
7517 mkU32(0x0)),
7518 mkexpr(t13),
7519 mkU8(0x0)));
7520 assign(t14, binop(Iop_CmpEQ32,
7521 binop(Iop_And32,
7522 unop(Iop_16Uto32,
7523 unop(Iop_32HIto16,
7524 getIReg(rt))),
7525 mkU32(0x00008000)),
7526 mkU32(0x0)));
7527 assign(t15, IRExpr_ITE(binop(Iop_CmpLT32U,
7528 mkU32(0x7f80),
7529 binop(Iop_And32,
7530 unop(Iop_16Uto32,
7531 unop(Iop_32HIto16,
7532 getIReg(rt))),
7533 mkU32(0x7fff))),
7534 binop(Iop_Or32,
7535 getDSPControl(),
7536 mkU32(0x00400000)),
7537 getDSPControl()));
7538 putDSPControl(IRExpr_ITE(mkexpr(t14),
7539 mkexpr(t15),
7540 binop(Iop_Or32,
7541 getDSPControl(),
7542 mkU32(0x00400000))));
7543
7544 putIReg(rd, binop(Iop_16HLto32,
7545 binop(Iop_8HLto16,
7546 mkexpr(t1), mkexpr(t0)),
7547 binop(Iop_8HLto16,
7548 mkexpr(t3), mkexpr(t2))));
7549 break;
7550 }
7551 case 0x14: { /* PRECRQ.PH.W */
7552 DIP("precrq.ph.w r%d, r%d, %d", rd, rs, rt);
7553 vassert(!mode64);
7554 putIReg(rd, binop(Iop_16HLto32,
7555 unop(Iop_32HIto16, getIReg(rs)),
7556 unop(Iop_32HIto16, getIReg(rt))));
7557 break;
7558 }
7559 case 0x15: { /* PRECRQ_RS.PH.W */
7560 DIP("precrq_rs.ph.w r%d, r%d, %d", rd, rs, rt);
7561 vassert(!mode64);
7562 t0 = newTemp(Ity_I64);
7563 t1 = newTemp(Ity_I1);
7564 t2 = newTemp(Ity_I32);
7565 t3 = newTemp(Ity_I64);
7566 t4 = newTemp(Ity_I1);
7567 t5 = newTemp(Ity_I32);
7568
7569 assign(t0, binop(Iop_Add64,
7570 binop(Iop_32HLto64,
7571 binop(Iop_Shr32,
7572 binop(Iop_And32,
7573 getIReg(rs),
7574 mkU32(0x80000000)),
7575 mkU8(31)),
7576 getIReg(rs)),
7577 mkU64(0x0000000000008000ULL)));
7578 assign(t1, binop(Iop_CmpNE32,
7579 binop(Iop_And32,
7580 unop(Iop_64HIto32, mkexpr(t0)),
7581 mkU32(0x1)),
7582 binop(Iop_And32,
7583 binop(Iop_Shr32,
7584 unop(Iop_64to32, mkexpr(t0)),
7585 mkU8(31)),
7586 mkU32(0x1))));
7587 assign(t2, IRExpr_ITE(mkexpr(t1),
7588 mkU32(0x7fffffff),
7589 unop(Iop_64to32, mkexpr(t0))));
7590 putDSPControl(IRExpr_ITE(mkexpr(t1),
7591 binop(Iop_Or32,
7592 getDSPControl(),
7593 mkU32(0x400000)),
7594 getDSPControl()));
7595 assign(t3, binop(Iop_Add64,
7596 binop(Iop_32HLto64,
7597 binop(Iop_Shr32,
7598 binop(Iop_And32,
7599 getIReg(rt),
7600 mkU32(0x80000000)),
7601 mkU8(31)),
7602 getIReg(rt)),
7603 mkU64(0x0000000000008000ULL)));
7604 assign(t4, binop(Iop_CmpNE32,
7605 binop(Iop_And32,
7606 unop(Iop_64HIto32, mkexpr(t3)),
7607 mkU32(0x1)),
7608 binop(Iop_And32,
7609 binop(Iop_Shr32,
7610 unop(Iop_64to32, mkexpr(t3)),
7611 mkU8(31)),
7612 mkU32(0x1))));
7613 assign(t5, IRExpr_ITE(mkexpr(t4),
7614 mkU32(0x7fffffff),
7615 unop(Iop_64to32, mkexpr(t3))));
7616 putDSPControl(IRExpr_ITE(mkexpr(t4),
7617 binop(Iop_Or32,
7618 getDSPControl(),
7619 mkU32(0x400000)),
7620 getDSPControl()));
7621 putIReg(rd, binop(Iop_16HLto32,
7622 unop(Iop_32HIto16, mkexpr(t2)),
7623 unop(Iop_32HIto16, mkexpr(t5))));
7624 break;
7625 }
7626 case 0x1E: { /* PRECR_SRA.PH.W */
7627 DIP("precr_sra.ph.w r%d, r%d, %d", rt, rs, rd);
7628 vassert(!mode64);
7629
7630 if (0 == rd) {
7631 putIReg(rt, binop(Iop_16HLto32,
7632 unop(Iop_32to16, getIReg(rt)),
7633 unop(Iop_32to16, getIReg(rs))));
7634 } else {
7635 putIReg(rt, binop(Iop_16HLto32,
7636 unop(Iop_32to16, binop(Iop_Sar32,
7637 getIReg(rt),
7638 mkU8(rd))),
7639 unop(Iop_32to16, binop(Iop_Sar32,
7640 getIReg(rs),
7641 mkU8(rd)))));
7642 }
7643 break;
7644 }
7645 case 0x1F: { /* PRECR_SRA_R.PH.W */
7646 DIP("precr_sra_r.ph.w r%d, r%d, %d", rt, rs, rd);
7647 vassert(!mode64);
7648
7649 t0 = newTemp(Ity_I32);
7650 t1 = newTemp(Ity_I32);
7651
7652 if (0 == rd) {
7653 putIReg(rt, binop(Iop_16HLto32,
7654 unop(Iop_32to16, getIReg(rt)),
7655 unop(Iop_32to16, getIReg(rs))));
7656 } else {
7657 assign(t0, binop(Iop_Shr32,
7658 binop(Iop_Add32,
7659 binop(Iop_Sar32,
7660 getIReg(rt),
7661 mkU8(rd-1)),
7662 mkU32(0x1)),
7663 mkU8(0x1)));
7664 assign(t1, binop(Iop_Shr32,
7665 binop(Iop_Add32,
7666 binop(Iop_Sar32,
7667 getIReg(rs),
7668 mkU8(rd-1)),
7669 mkU32(0x1)),
7670 mkU8(0x1)));
7671 putIReg(rt, binop(Iop_16HLto32,
7672 unop(Iop_32to16, mkexpr(t0)),
7673 unop(Iop_32to16, mkexpr(t1))));
7674 };
7675 break;
7676 }
7677 case 0xE: { /* PACKRL.PH */
7678 DIP("packrl.ph r%d, r%d, r%d", rd, rs, rt);
7679 vassert(!mode64);
7680
7681 putIReg(rd, binop(Iop_16HLto32,
7682 unop(Iop_32to16, getIReg(rs)),
7683 unop(Iop_32HIto16, getIReg(rt))));
7684 break;
7685 }
7686 case 0x18: { /* CMPGDU.EQ.QB */
7687 DIP("cmpgdu.eq.qb r%d, r%d, r%d", rd, rs, rt);
7688 vassert(!mode64);
7689 t1 = newTemp(Ity_I1);
7690 t2 = newTemp(Ity_I1);
7691 t3 = newTemp(Ity_I1);
7692 t4 = newTemp(Ity_I1);
7693 t5 = newTemp(Ity_I32);
7694 t6 = newTemp(Ity_I32);
7695 t7 = newTemp(Ity_I32);
7696 t8 = newTemp(Ity_I32);
7697
7698 assign(t1,
7699 binop(Iop_CmpEQ32,
7700 unop(Iop_8Uto32,
7701 unop(Iop_16to8,
7702 unop(Iop_32to16, getIReg(rs)))),
7703 unop(Iop_8Uto32,
7704 unop(Iop_16to8,
7705 unop(Iop_32to16, getIReg(rt))))));
7706 assign(t5, IRExpr_ITE(mkexpr(t1),
7707 mkU32(0x00000001), mkU32(0)));
7708 putDSPControl(IRExpr_ITE(mkexpr(t1),
7709 binop(Iop_Or32,
7710 getDSPControl(),
7711 mkU32(0x01000000)),
7712 binop(Iop_And32,
7713 getDSPControl(),
7714 mkU32(0xfeffffff))));
7715
7716 assign(t2, binop(Iop_CmpEQ32,
7717 unop(Iop_8Uto32,
7718 unop(Iop_16HIto8,
7719 unop(Iop_32to16, getIReg(rs)))),
7720 unop(Iop_8Uto32,
7721 unop(Iop_16HIto8,
7722 unop(Iop_32to16,
7723 getIReg(rt))))));
7724 assign(t6, IRExpr_ITE(mkexpr(t2),
7725 mkU32(0x00000002), mkU32(0)));
7726 putDSPControl(IRExpr_ITE(mkexpr(t2),
7727 binop(Iop_Or32,
7728 getDSPControl(),
7729 mkU32(0x02000000)),
7730 binop(Iop_And32,
7731 getDSPControl(),
7732 mkU32(0xfdffffff))));
7733
7734 assign(t3, binop(Iop_CmpEQ32,
7735 unop(Iop_8Uto32,
7736 unop(Iop_16to8,
7737 unop(Iop_32HIto16,
7738 getIReg(rs)))),
7739 unop(Iop_8Uto32,
7740 unop(Iop_16to8,
7741 unop(Iop_32HIto16,
7742 getIReg(rt))))));
7743 assign(t7, IRExpr_ITE(mkexpr(t3),
7744 mkU32(0x00000004), mkU32(0)));
7745 putDSPControl(IRExpr_ITE(mkexpr(t3),
7746 binop(Iop_Or32,
7747 getDSPControl(),
7748 mkU32(0x04000000)),
7749 binop(Iop_And32,
7750 getDSPControl(),
7751 mkU32(0xfbffffff))));
7752
7753 assign(t4, binop(Iop_CmpEQ32,
7754 unop(Iop_8Uto32,
7755 unop(Iop_16HIto8,
7756 unop(Iop_32HIto16,
7757 getIReg(rs)))),
7758 unop(Iop_8Uto32,
7759 unop(Iop_16HIto8,
7760 unop(Iop_32HIto16,
7761 getIReg(rt))))));
7762 assign(t8, IRExpr_ITE(mkexpr(t4),
7763 mkU32(0x00000008), mkU32(0)));
7764 putDSPControl(IRExpr_ITE(mkexpr(t4),
7765 binop(Iop_Or32,
7766 getDSPControl(),
7767 mkU32(0x08000000)),
7768 binop(Iop_And32,
7769 getDSPControl(),
7770 mkU32(0xf7ffffff))));
7771
7772 putIReg(rd, binop(Iop_Or32,
7773 binop(Iop_Or32,
7774 binop(Iop_Or32,
7775 mkexpr(t5), mkexpr(t6)),
7776 mkexpr(t7)),
7777 mkexpr(t8)));
7778 break;
7779 }
7780 case 0x19: { /* CMPGDU.LT.QB */
7781 DIP("cmpgdu.lt.qb r%d, r%d, r%d", rd, rs, rt);
7782 vassert(!mode64);
7783 t1 = newTemp(Ity_I1);
7784 t2 = newTemp(Ity_I1);
7785 t3 = newTemp(Ity_I1);
7786 t4 = newTemp(Ity_I1);
7787 t5 = newTemp(Ity_I32);
7788 t6 = newTemp(Ity_I32);
7789 t7 = newTemp(Ity_I32);
7790 t8 = newTemp(Ity_I32);
7791
7792 assign(t1, binop(Iop_CmpLT32U,
7793 unop(Iop_8Uto32,
7794 unop(Iop_16to8,
7795 unop(Iop_32to16, getIReg(rs)))),
7796 unop(Iop_8Uto32,
7797 unop(Iop_16to8,
7798 unop(Iop_32to16,
7799 getIReg(rt))))));
7800 assign(t5, IRExpr_ITE(mkexpr(t1),
7801 mkU32(0x00000001), mkU32(0)));
7802 putDSPControl(IRExpr_ITE(mkexpr(t1),
7803 binop(Iop_Or32,
7804 getDSPControl(),
7805 mkU32(0x01000000)),
7806 binop(Iop_And32,
7807 getDSPControl(),
7808 mkU32(0xfeffffff))));
7809
7810 assign(t2, binop(Iop_CmpLT32U,
7811 unop(Iop_8Uto32,
7812 unop(Iop_16HIto8,
7813 unop(Iop_32to16, getIReg(rs)))),
7814 unop(Iop_8Uto32,
7815 unop(Iop_16HIto8,
7816 unop(Iop_32to16,
7817 getIReg(rt))))));
7818 assign(t6, IRExpr_ITE(mkexpr(t2),
7819 mkU32(0x00000002), mkU32(0)));
7820 putDSPControl(IRExpr_ITE(mkexpr(t2),
7821 binop(Iop_Or32,
7822 getDSPControl(),
7823 mkU32(0x02000000)),
7824 binop(Iop_And32,
7825 getDSPControl(),
7826 mkU32(0xfdffffff))));
7827
7828 assign(t3, binop(Iop_CmpLT32U,
7829 unop(Iop_8Uto32,
7830 unop(Iop_16to8,
7831 unop(Iop_32HIto16,
7832 getIReg(rs)))),
7833 unop(Iop_8Uto32,
7834 unop(Iop_16to8,
7835 unop(Iop_32HIto16,
7836 getIReg(rt))))));
7837 assign(t7, IRExpr_ITE(mkexpr(t3),
7838 mkU32(0x00000004), mkU32(0)));
7839 putDSPControl(IRExpr_ITE(mkexpr(t3),
7840 binop(Iop_Or32,
7841 getDSPControl(),
7842 mkU32(0x04000000)),
7843 binop(Iop_And32,
7844 getDSPControl(),
7845 mkU32(0xfbffffff))));
7846
7847 assign(t4, binop(Iop_CmpLT32U,
7848 unop(Iop_8Uto32,
7849 unop(Iop_16HIto8,
7850 unop(Iop_32HIto16,
7851 getIReg(rs)))),
7852 unop(Iop_8Uto32,
7853 unop(Iop_16HIto8,
7854 unop(Iop_32HIto16,
7855 getIReg(rt))))));
7856 assign(t8, IRExpr_ITE(mkexpr(t4),
7857 mkU32(0x00000008), mkU32(0)));
7858 putDSPControl(IRExpr_ITE(mkexpr(t4),
7859 binop(Iop_Or32,
7860 getDSPControl(),
7861 mkU32(0x08000000)),
7862 binop(Iop_And32,
7863 getDSPControl(),
7864 mkU32(0xf7ffffff))));
7865
7866 putIReg(rd, binop(Iop_Or32,
7867 binop(Iop_Or32,
7868 binop(Iop_Or32,
7869 mkexpr(t5), mkexpr(t6)),
7870 mkexpr(t7)),
7871 mkexpr(t8)));
7872 break;
7873 }
7874 case 0x1A: { /* CMPGDU.LE.QB */
7875 DIP("cmpgdu.le.qb r%d, r%d, r%d", rd, rs, rt);
7876 vassert(!mode64);
7877 t1 = newTemp(Ity_I1);
7878 t2 = newTemp(Ity_I1);
7879 t3 = newTemp(Ity_I1);
7880 t4 = newTemp(Ity_I1);
7881 t5 = newTemp(Ity_I32);
7882 t6 = newTemp(Ity_I32);
7883 t7 = newTemp(Ity_I32);
7884 t8 = newTemp(Ity_I32);
7885
7886 assign(t1, binop(Iop_CmpLE32U,
7887 unop(Iop_8Uto32,
7888 unop(Iop_16to8,
7889 unop(Iop_32to16, getIReg(rs)))),
7890 unop(Iop_8Uto32,
7891 unop(Iop_16to8,
7892 unop(Iop_32to16,
7893 getIReg(rt))))));
7894 assign(t5, IRExpr_ITE(mkexpr(t1),
7895 mkU32(0x00000001),
7896 mkU32(0)));
7897 putDSPControl(IRExpr_ITE(mkexpr(t1),
7898 binop(Iop_Or32,
7899 getDSPControl(),
7900 mkU32(0x01000000)),
7901 binop(Iop_And32,
7902 getDSPControl(),
7903 mkU32(0xfeffffff))));
7904
7905 assign(t2, binop(Iop_CmpLE32U,
7906 unop(Iop_8Uto32,
7907 unop(Iop_16HIto8,
7908 unop(Iop_32to16, getIReg(rs)))),
7909 unop(Iop_8Uto32,
7910 unop(Iop_16HIto8,
7911 unop(Iop_32to16,
7912 getIReg(rt))))));
7913 assign(t6, IRExpr_ITE(mkexpr(t2),
7914 mkU32(0x00000002), mkU32(0)));
7915 putDSPControl(IRExpr_ITE(mkexpr(t2),
7916 binop(Iop_Or32,
7917 getDSPControl(),
7918 mkU32(0x02000000)),
7919 binop(Iop_And32,
7920 getDSPControl(),
7921 mkU32(0xfdffffff))));
7922
7923 assign(t3, binop(Iop_CmpLE32U,
7924 unop(Iop_8Uto32,
7925 unop(Iop_16to8,
7926 unop(Iop_32HIto16,
7927 getIReg(rs)))),
7928 unop(Iop_8Uto32,
7929 unop(Iop_16to8,
7930 unop(Iop_32HIto16,
7931 getIReg(rt))))));
7932 assign(t7, IRExpr_ITE(mkexpr(t3),
7933 mkU32(0x00000004), mkU32(0)));
7934 putDSPControl(IRExpr_ITE(mkexpr(t3),
7935 binop(Iop_Or32,
7936 getDSPControl(),
7937 mkU32(0x04000000)),
7938 binop(Iop_And32,
7939 getDSPControl(),
7940 mkU32(0xfbffffff))));
7941
7942 assign(t4, binop(Iop_CmpLE32U,
7943 unop(Iop_8Uto32,
7944 unop(Iop_16HIto8,
7945 unop(Iop_32HIto16,
7946 getIReg(rs)))),
7947 unop(Iop_8Uto32,
7948 unop(Iop_16HIto8,
7949 unop(Iop_32HIto16,
7950 getIReg(rt))))));
7951 assign(t8, IRExpr_ITE(mkexpr(t4),
7952 mkU32(0x00000008), mkU32(0)));
7953 putDSPControl(IRExpr_ITE(mkexpr(t4),
7954 binop(Iop_Or32,
7955 getDSPControl(),
7956 mkU32(0x08000000)),
7957 binop(Iop_And32,
7958 getDSPControl(),
7959 mkU32(0xf7ffffff))));
7960
7961 putIReg(rd, binop(Iop_Or32,
7962 binop(Iop_Or32,
7963 binop(Iop_Or32,
7964 mkexpr(t5), mkexpr(t6)),
7965 mkexpr(t7)),
7966 mkexpr(t8)));
7967 break;
7968 }
7969 default:
7970 return -1;
7971 }
7972 break; /* end of CMPU.EQ.QB */
7973 }
7974 case 0x13: { /* SHLL.QB */
7975 switch(sa) {
7976 case 0x0: { /* SHLL.QB */
7977 DIP("shll.qb r%d, r%d, %d", rd, rt, rs);
7978 vassert(!mode64);
7979 t0 = newTemp(Ity_I32);
7980 t1 = newTemp(Ity_I1);
7981 t2 = newTemp(Ity_I1);
dejanj781f1bd2013-10-23 14:05:15 +00007982 t3 = newTemp(Ity_I32);
7983 t4 = newTemp(Ity_I1);
7984 t5 = newTemp(Ity_I1);
7985 t6 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +00007986 t7 = newTemp(Ity_I1);
7987 t8 = newTemp(Ity_I1);
dejanj781f1bd2013-10-23 14:05:15 +00007988 t9 = newTemp(Ity_I1);
7989 t10 = newTemp(Ity_I1);
dejanjc3fee0d2013-07-25 09:08:03 +00007990
7991 if (0 == rs) {
7992 putIReg(rd, getIReg(rt));
7993 } else {
dejanj781f1bd2013-10-23 14:05:15 +00007994 /* Shift bits 7..0 and 23..16. */
dejanjc3fee0d2013-07-25 09:08:03 +00007995 assign(t0, binop(Iop_Shl32,
dejanj781f1bd2013-10-23 14:05:15 +00007996 binop(Iop_And32,
7997 getIReg(rt),
7998 mkU32(0x00ff00ff)),
7999 mkU8(rs)));
dejanjc3fee0d2013-07-25 09:08:03 +00008000 assign(t1, binop(Iop_CmpNE32,
dejanj781f1bd2013-10-23 14:05:15 +00008001 binop(Iop_And32,
8002 mkexpr(t0),
8003 mkU32(0xff000000)),
8004 mkU32(0x00000000)));
dejanjc3fee0d2013-07-25 09:08:03 +00008005 assign(t2, binop(Iop_CmpNE32,
dejanj781f1bd2013-10-23 14:05:15 +00008006 binop(Iop_And32,
8007 mkexpr(t0),
8008 mkU32(0xff000000)),
8009 mkU32(0xff000000)));
dejanjc3fee0d2013-07-25 09:08:03 +00008010 assign(t7, binop(Iop_CmpNE32,
dejanj781f1bd2013-10-23 14:05:15 +00008011 binop(Iop_And32,
8012 mkexpr(t0),
8013 mkU32(0x0000ff00)),
8014 mkU32(0x00000000)));
8015 assign(t8, binop(Iop_CmpNE32,
8016 binop(Iop_And32,
8017 mkexpr(t0),
8018 mkU32(0x0000ff00)),
8019 mkU32(0x000ff00)));
8020 /* Shift bits 15..8 and 31..24. */
8021 assign(t3, binop(Iop_Shl32,
8022 binop(Iop_Shr32,
dejanjc3fee0d2013-07-25 09:08:03 +00008023 binop(Iop_And32,
dejanj781f1bd2013-10-23 14:05:15 +00008024 getIReg(rt),
8025 mkU32(0xff00ff00)),
8026 mkU8(8)),
8027 mkU8(rs)));
8028 assign(t4, binop(Iop_CmpNE32,
8029 binop(Iop_And32,
8030 mkexpr(t3),
8031 mkU32(0xff000000)),
8032 mkU32(0x00000000)));
8033 assign(t5, binop(Iop_CmpNE32,
8034 binop(Iop_And32,
8035 mkexpr(t3),
8036 mkU32(0xff000000)),
8037 mkU32(0xff000000)));
8038 assign(t9, binop(Iop_CmpNE32,
8039 binop(Iop_And32,
8040 mkexpr(t3),
8041 mkU32(0x0000ff00)),
8042 mkU32(0x00000000)));
8043 assign(t10, binop(Iop_CmpNE32,
8044 binop(Iop_And32,
8045 mkexpr(t3),
8046 mkU32(0x0000ff00)),
8047 mkU32(0x0000ff00)));
dejanjc3fee0d2013-07-25 09:08:03 +00008048
dejanj781f1bd2013-10-23 14:05:15 +00008049 assign(t6, binop(Iop_Or32,
8050 binop(Iop_Or32,
dejanjc3fee0d2013-07-25 09:08:03 +00008051 binop(Iop_And32,
dejanj781f1bd2013-10-23 14:05:15 +00008052 unop(Iop_1Uto32,
8053 mkexpr(t1)),
8054 unop(Iop_1Uto32,
8055 mkexpr(t2))),
8056 binop(Iop_And32,
8057 unop(Iop_1Uto32,
8058 mkexpr(t7)),
8059 unop(Iop_1Uto32,
8060 mkexpr(t8)))),
8061 binop(Iop_Or32,
8062 binop(Iop_And32,
8063 unop(Iop_1Uto32,
8064 mkexpr(t4)),
8065 unop(Iop_1Uto32,
8066 mkexpr(t5))),
8067 binop(Iop_And32,
8068 unop(Iop_1Uto32,
8069 mkexpr(t9)),
8070 unop(Iop_1Uto32,
8071 mkexpr(t10))))));
dejanjc3fee0d2013-07-25 09:08:03 +00008072
dejanj781f1bd2013-10-23 14:05:15 +00008073 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
8074 mkexpr(t6),
8075 mkU32(0x0)),
8076 binop(Iop_Or32,
8077 getDSPControl(),
8078 mkU32(0x400000)),
dejanjc3fee0d2013-07-25 09:08:03 +00008079 getDSPControl()));
dejanj781f1bd2013-10-23 14:05:15 +00008080 putIReg(rd, binop(Iop_Or32,
8081 binop(Iop_Shl32,
8082 binop(Iop_And32,
8083 mkexpr(t3),
8084 mkU32(0x00ff00ff)),
8085 mkU8(8)),
8086 binop(Iop_And32,
8087 mkexpr(t0),
8088 mkU32(0x00ff00ff))));
dejanjc3fee0d2013-07-25 09:08:03 +00008089 }
8090 break;
8091 }
8092 case 0x3: { /* SHRL.QB */
8093 DIP("shrl.qb r%d, r%d, %d", rd, rt, rs);
8094 vassert(!mode64);
8095 t0 = newTemp(Ity_I32);
8096 t1 = newTemp(Ity_I8);
8097 t2 = newTemp(Ity_I32);
8098 t3 = newTemp(Ity_I8);
8099 t4 = newTemp(Ity_I32);
8100 t5 = newTemp(Ity_I8);
8101 t6 = newTemp(Ity_I32);
8102 t7 = newTemp(Ity_I8);
8103 t9 = newTemp(Ity_I32);
8104
8105 assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7)));
8106 assign(t0, unop(Iop_8Uto32,
8107 unop(Iop_16to8,
8108 unop(Iop_32to16, getIReg(rt)))));
8109 assign(t1, unop(Iop_32to8,
8110 binop(Iop_Shr32,
8111 mkexpr(t0),
8112 unop(Iop_32to8, mkexpr(t9)))));
8113
8114 assign(t2, unop(Iop_8Uto32,
8115 unop(Iop_16HIto8,
8116 unop(Iop_32to16, getIReg(rt)))));
8117 assign(t3, unop(Iop_32to8,
8118 binop(Iop_Shr32,
8119 mkexpr(t2),
8120 unop(Iop_32to8, mkexpr(t9)))));
8121
8122 assign(t4, unop(Iop_8Uto32,
8123 unop(Iop_16to8,
8124 unop(Iop_32HIto16, getIReg(rt)))));
8125 assign(t5, unop(Iop_32to8,
8126 binop(Iop_Shr32,
8127 mkexpr(t4),
8128 unop(Iop_32to8, mkexpr(t9)))));
8129
8130 assign(t6, unop(Iop_8Uto32,
8131 unop(Iop_16HIto8,
8132 unop(Iop_32HIto16, getIReg(rt)))));
8133 assign(t7, unop(Iop_32to8,
8134 binop(Iop_Shr32,
8135 mkexpr(t6),
8136 unop(Iop_32to8, mkexpr(t9)))));
8137 putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
8138 mkexpr(t9),
8139 mkU32(0x0)),
8140 getIReg(rt),
8141 binop(Iop_16HLto32,
8142 binop(Iop_8HLto16,
8143 mkexpr(t7),
8144 mkexpr(t5)),
8145 binop(Iop_8HLto16,
8146 mkexpr(t3),
8147 mkexpr(t1)))));
8148 break;
8149 }
8150 case 0x2: { /* SHLLV.QB */
8151 DIP("shllv.qb r%d, r%d, r%d", rd, rt, rs);
8152 vassert(!mode64);
8153 t0 = newTemp(Ity_I32);
8154 t1 = newTemp(Ity_I1);
8155 t2 = newTemp(Ity_I1);
dejanj781f1bd2013-10-23 14:05:15 +00008156 t3 = newTemp(Ity_I32);
8157 t4 = newTemp(Ity_I1);
8158 t5 = newTemp(Ity_I1);
8159 t6 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +00008160 t7 = newTemp(Ity_I1);
8161 t8 = newTemp(Ity_I1);
dejanj781f1bd2013-10-23 14:05:15 +00008162 t9 = newTemp(Ity_I1);
8163 t10 = newTemp(Ity_I1);
8164 t11 = newTemp(Ity_I8);
dejanjc3fee0d2013-07-25 09:08:03 +00008165
dejanj781f1bd2013-10-23 14:05:15 +00008166 assign(t11, unop(Iop_32to8,
8167 binop(Iop_And32,
8168 getIReg(rs),
8169 mkU32(0x7))));
8170 /* Shift bits 7..0 and 23..16. */
dejanjc3fee0d2013-07-25 09:08:03 +00008171 assign(t0, binop(Iop_Shl32,
dejanj781f1bd2013-10-23 14:05:15 +00008172 binop(Iop_And32,
dejanjc3fee0d2013-07-25 09:08:03 +00008173 getIReg(rt),
dejanj781f1bd2013-10-23 14:05:15 +00008174 mkU32(0x00ff00ff)),
8175 mkexpr(t11)));
8176 assign(t1, binop(Iop_CmpNE32,
8177 binop(Iop_And32,
8178 mkexpr(t0),
8179 mkU32(0xff000000)),
8180 mkU32(0x00000000)));
8181 assign(t2, binop(Iop_CmpNE32,
8182 binop(Iop_And32,
8183 mkexpr(t0),
8184 mkU32(0xff000000)),
8185 mkU32(0xff000000)));
8186 assign(t7, binop(Iop_CmpNE32,
8187 binop(Iop_And32,
8188 mkexpr(t0),
8189 mkU32(0x0000ff00)),
8190 mkU32(0x00000000)));
8191 assign(t8, binop(Iop_CmpNE32,
8192 binop(Iop_And32,
8193 mkexpr(t0),
8194 mkU32(0x0000ff00)),
8195 mkU32(0x000ff00)));
8196 /* Shift bits 15..8 and 31..24. */
8197 assign(t3, binop(Iop_Shl32,
8198 binop(Iop_Shr32,
8199 binop(Iop_And32,
8200 getIReg(rt),
8201 mkU32(0xff00ff00)),
8202 mkU8(8)),
8203 mkexpr(t11)));
8204 assign(t4, binop(Iop_CmpNE32,
8205 binop(Iop_And32,
8206 mkexpr(t3),
8207 mkU32(0xff000000)),
8208 mkU32(0x00000000)));
8209 assign(t5, binop(Iop_CmpNE32,
8210 binop(Iop_And32,
8211 mkexpr(t3),
8212 mkU32(0xff000000)),
8213 mkU32(0xff000000)));
8214 assign(t9, binop(Iop_CmpNE32,
8215 binop(Iop_And32,
8216 mkexpr(t3),
8217 mkU32(0x0000ff00)),
8218 mkU32(0x00000000)));
8219 assign(t10, binop(Iop_CmpNE32,
8220 binop(Iop_And32,
8221 mkexpr(t3),
8222 mkU32(0x0000ff00)),
8223 mkU32(0x0000ff00)));
8224
8225 assign(t6, binop(Iop_Or32,
8226 binop(Iop_Or32,
8227 binop(Iop_And32,
8228 unop(Iop_1Uto32,
8229 mkexpr(t1)),
8230 unop(Iop_1Uto32,
8231 mkexpr(t2))),
8232 binop(Iop_And32,
8233 unop(Iop_1Uto32,
8234 mkexpr(t7)),
8235 unop(Iop_1Uto32,
8236 mkexpr(t8)))),
8237 binop(Iop_Or32,
8238 binop(Iop_And32,
8239 unop(Iop_1Uto32,
8240 mkexpr(t4)),
8241 unop(Iop_1Uto32,
8242 mkexpr(t5))),
8243 binop(Iop_And32,
8244 unop(Iop_1Uto32,
8245 mkexpr(t9)),
8246 unop(Iop_1Uto32,
8247 mkexpr(t10))))));
8248
8249 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
8250 mkexpr(t6),
8251 mkU32(0x0)),
8252 binop(Iop_Or32,
8253 getDSPControl(),
8254 mkU32(0x400000)),
8255 getDSPControl()));
8256 putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
8257 unop(Iop_8Uto32, mkexpr(t11)),
8258 mkU32(0)),
8259 getIReg(rt),
8260 binop(Iop_Or32,
8261 binop(Iop_Shl32,
8262 binop(Iop_And32,
8263 mkexpr(t3),
8264 mkU32(0xff00ff)),
8265 mkU8(8)),
8266 binop(Iop_And32,
8267 mkexpr(t0),
8268 mkU32(0x00ff00ff)))));
dejanjc3fee0d2013-07-25 09:08:03 +00008269 break;
8270 }
8271 case 0x1: { /* SHRLV.QB */
8272 DIP("shrlv.qb r%d, r%d, r%d", rd, rt, rs);
8273 vassert(!mode64);
8274 t0 = newTemp(Ity_I8);
8275 t1 = newTemp(Ity_I8);
8276 t2 = newTemp(Ity_I8);
8277 t3 = newTemp(Ity_I8);
8278
8279 assign(t0, unop(Iop_32to8,
8280 binop(Iop_Shr32,
8281 unop(Iop_8Uto32,
8282 unop(Iop_32to8, getIReg(rt))),
8283 mkU8(rs))));
8284 assign(t1, unop(Iop_32to8,
8285 binop(Iop_Shr32,
8286 unop(Iop_8Uto32,
8287 unop(Iop_16HIto8,
8288 unop(Iop_32to16,
8289 getIReg(rt)))),
8290 mkU8(rs))));
8291 assign(t2, unop(Iop_32to8,
8292 binop(Iop_Shr32,
8293 unop(Iop_8Uto32,
8294 unop(Iop_16to8,
8295 unop(Iop_32HIto16,
8296 getIReg(rt)))),
8297 mkU8(rs))));
8298 assign(t3, unop(Iop_32to8,
8299 binop(Iop_Shr32,
8300 unop(Iop_8Uto32,
8301 unop(Iop_16HIto8,
8302 unop(Iop_32HIto16,
8303 getIReg(rt)))),
8304 mkU8(rs))));
8305 putIReg(rd,
8306 binop(Iop_16HLto32,
8307 binop(Iop_8HLto16, mkexpr(t3), mkexpr(t2)),
8308 binop(Iop_8HLto16, mkexpr(t1), mkexpr(t0))));
8309 break;
8310 }
8311 case 0x4: { /* SHRA.QB */
8312 DIP("shra.qb r%d, r%d, %d", rd, rt, rs);
8313 vassert(!mode64);
8314 t0 = newTemp(Ity_I32);
8315 t1 = newTemp(Ity_I32);
8316 t2 = newTemp(Ity_I32);
8317 t3 = newTemp(Ity_I32);
8318 t4 = newTemp(Ity_I32);
8319 t5 = newTemp(Ity_I32);
8320 t6 = newTemp(Ity_I32);
8321 t7 = newTemp(Ity_I32);
8322 t8 = newTemp(Ity_I32);
8323 t9 = newTemp(Ity_I32);
8324 t10 = newTemp(Ity_I32);
8325 t11 = newTemp(Ity_I32);
8326
8327 /* ========== GPR[rt]_31..24 ========== */
8328 assign(t1,
8329 unop(Iop_8Uto32,
8330 unop(Iop_16HIto8,
8331 unop(Iop_32HIto16, getIReg(rt)))));
8332 assign(t2,
8333 binop(Iop_Shr32, mkexpr(t1), mkU8(rs)));
8334 /* tempD_7..0 */
8335 assign(t0,
8336 binop(Iop_Or32,
8337 mkexpr(t2),
8338 binop(Iop_Shl32,
8339 IRExpr_ITE(binop(Iop_CmpEQ32,
8340 binop(Iop_And32,
8341 mkexpr(t1),
8342 mkU32(0x00000080)
8343 ),
8344 mkU32(0x00000080)),
8345 mkU32(0xFFFFFFFF),
8346 mkU32(0x00000000)),
8347 binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
8348
8349 /* ========== GPR[rt]_23..16 ========== */
8350 assign(t4,
8351 unop(Iop_8Uto32,
8352 unop(Iop_16to8,
8353 unop(Iop_32HIto16, getIReg(rt)))));
8354 assign(t5, binop(Iop_Shr32, mkexpr(t4), mkU8(rs)));
8355 /* tempC_7..0 */
8356 assign(t3,
8357 binop(Iop_Or32,
8358 mkexpr(t5),
8359 binop(Iop_Shl32,
8360 IRExpr_ITE(binop(Iop_CmpEQ32,
8361 binop(Iop_And32,
8362 mkexpr(t4),
8363 mkU32(0x00000080)
8364 ),
8365 mkU32(0x00000080)),
8366 mkU32(0xFFFFFFFF),
8367 mkU32(0x00000000)),
8368 binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
8369
8370 /* ========== GPR[rt]_15..8 ========== */
8371 assign(t7,
8372 unop(Iop_8Uto32,
8373 unop(Iop_16HIto8,
8374 unop(Iop_32to16, getIReg(rt)))));
8375 assign(t8, binop(Iop_Shr32, mkexpr(t7), mkU8(rs)));
8376 /* tempB_7..0 */
8377 assign(t6,
8378 binop(Iop_Or32,
8379 mkexpr(t8),
8380 binop(Iop_Shl32,
8381 IRExpr_ITE(binop(Iop_CmpEQ32,
8382 binop(Iop_And32,
8383 mkexpr(t7),
8384 mkU32(0x00000080)
8385 ),
8386 mkU32(0x00000080)),
8387 mkU32(0xFFFFFFFF),
8388 mkU32(0x00000000)),
8389 binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
8390
8391 /* ========== GPR[rt]_7..0 ========== */
8392 assign(t10,
8393 unop(Iop_8Uto32,
8394 unop(Iop_16to8,
8395 unop(Iop_32to16, getIReg(rt)))));
8396 assign(t11, binop(Iop_Shr32, mkexpr(t10), mkU8(rs)));
8397 /* tempB_7..0 */
8398 assign(t9,
8399 binop(Iop_Or32,
8400 mkexpr(t11),
8401 binop(Iop_Shl32,
8402 IRExpr_ITE(binop(Iop_CmpEQ32,
8403 binop(Iop_And32,
8404 mkexpr(t10),
8405 mkU32(0x00000080)
8406 ),
8407 mkU32(0x00000080)),
8408 mkU32(0xFFFFFFFF),
8409 mkU32(0x00000000)),
8410 binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
8411
8412 putIReg(rd,
8413 binop(Iop_16HLto32,
8414 binop(Iop_8HLto16,
8415 unop(Iop_32to8, mkexpr(t0)),
8416 unop(Iop_32to8, mkexpr(t3))),
8417 binop(Iop_8HLto16,
8418 unop(Iop_32to8, mkexpr(t6)),
8419 unop(Iop_32to8, mkexpr(t9)))));
8420 break;
8421 }
8422 case 0x5: { /* SHRA_R.QB */
8423 DIP("shra_r.qb r%d, r%d, %d", rd, rt, rs);
8424 vassert(!mode64);
8425 t0 = newTemp(Ity_I32);
8426 t1 = newTemp(Ity_I8);
8427 t2 = newTemp(Ity_I32);
8428 t3 = newTemp(Ity_I8);
8429 t4 = newTemp(Ity_I32);
8430 t5 = newTemp(Ity_I8);
8431 t6 = newTemp(Ity_I32);
8432 t7 = newTemp(Ity_I8);
8433
8434 if (0 == rs) {
8435 putIReg(rd, getIReg(rt));
8436 } else {
8437 assign(t0, unop(Iop_8Sto32,
8438 unop(Iop_16to8,
8439 unop(Iop_32to16, getIReg(rt)))));
8440 assign(t1, unop(Iop_32to8,
8441 binop(Iop_Sar32,
8442 binop(Iop_Add32,
8443 mkexpr(t0),
8444 binop(Iop_Shl32,
8445 mkU32(0x1),
8446 mkU8(rs-1))),
8447 mkU8(rs))));
8448
8449 assign(t2, unop(Iop_8Sto32,
8450 unop(Iop_16HIto8,
8451 unop(Iop_32to16, getIReg(rt)))));
8452 assign(t3, unop(Iop_32to8,
8453 binop(Iop_Sar32,
8454 binop(Iop_Add32,
8455 mkexpr(t2),
8456 binop(Iop_Shl32,
8457 mkU32(0x1),
8458 mkU8(rs-1))),
8459 mkU8(rs))));
8460
8461 assign(t4, unop(Iop_8Sto32,
8462 unop(Iop_16to8,
8463 unop(Iop_32HIto16, getIReg(rt)))));
8464 assign(t5, unop(Iop_32to8,
8465 binop(Iop_Sar32,
8466 binop(Iop_Add32,
8467 mkexpr(t4),
8468 binop(Iop_Shl32,
8469 mkU32(0x1),
8470 mkU8(rs-1))),
8471 mkU8(rs))));
8472
8473 assign(t6, unop(Iop_8Sto32,
8474 unop(Iop_16HIto8,
8475 unop(Iop_32HIto16, getIReg(rt)))));
8476 assign(t7, unop(Iop_32to8,
8477 binop(Iop_Sar32,
8478 binop(Iop_Add32,
8479 mkexpr(t6),
8480 binop(Iop_Shl32,
8481 mkU32(0x1),
8482 mkU8(rs-1))),
8483 mkU8(rs))));
8484 putIReg(rd, binop(Iop_16HLto32,
8485 binop(Iop_8HLto16,
8486 mkexpr(t7), mkexpr(t5)),
8487 binop(Iop_8HLto16,
8488 mkexpr(t3), mkexpr(t1))));
8489 }
8490 break;
8491 }
8492 case 0x6: { /* SHRAV.QB */
8493 DIP("shrav.qb r%d, r%d, %d", rd, rt, rs);
8494 vassert(!mode64);
8495
8496 t0 = newTemp(Ity_I32);
8497 t1 = newTemp(Ity_I32);
8498 t2 = newTemp(Ity_I32);
8499
8500 t3 = newTemp(Ity_I32);
8501 t4 = newTemp(Ity_I32);
8502 t5 = newTemp(Ity_I32);
8503
8504 t6 = newTemp(Ity_I32);
8505 t7 = newTemp(Ity_I32);
8506 t8 = newTemp(Ity_I32);
8507
8508 t9 = newTemp(Ity_I32);
8509 t10 = newTemp(Ity_I32);
8510 t11 = newTemp(Ity_I32);
8511
8512 /* ========== GPR[rt]_31..24 ========== */
8513 assign(t1,
8514 unop(Iop_8Uto32,
8515 unop(Iop_16HIto8,
8516 unop(Iop_32HIto16, getIReg(rt)))));
8517 assign(t2,
8518 binop(Iop_Shr32,
8519 mkexpr(t1),
8520 unop(Iop_32to8, binop(Iop_And32,
8521 getIReg(rs),
8522 mkU32(0x7)))));
8523 /* tempD_7..0 */
8524 assign(t0,
8525 binop(Iop_Or32,
8526 mkexpr(t2),
8527 binop(Iop_Shl32,
8528 IRExpr_ITE(binop(Iop_CmpEQ32,
8529 binop(Iop_And32,
8530 mkexpr(t1),
8531 mkU32(0x00000080)
8532 ),
8533 mkU32(0x00000080)),
8534 mkU32(0xFFFFFFFF),
8535 mkU32(0x00000000)),
8536 binop(Iop_Sub8,
8537 mkU8(0x8),
8538 unop(Iop_32to8, binop(Iop_And32,
8539 getIReg(rs),
8540 mkU32(0x7)))
8541 ))));
8542
8543 /* ========== GPR[rt]_23..16 ========== */
8544 assign(t4,
8545 unop(Iop_8Uto32,
8546 unop(Iop_16to8,
8547 unop(Iop_32HIto16, getIReg(rt)))));
8548 assign(t5,
8549 binop(Iop_Shr32,
8550 mkexpr(t4),
8551 unop(Iop_32to8, binop(Iop_And32,
8552 getIReg(rs),
8553 mkU32(0x7)))));
8554 /* tempC_7..0 */
8555 assign(t3,
8556 binop(Iop_Or32,
8557 mkexpr(t5),
8558 binop(Iop_Shl32,
8559 IRExpr_ITE(binop(Iop_CmpEQ32,
8560 binop(Iop_And32,
8561 mkexpr(t4),
8562 mkU32(0x00000080)
8563 ),
8564 mkU32(0x00000080)),
8565 mkU32(0xFFFFFFFF),
8566 mkU32(0x00000000)),
8567 binop(Iop_Sub8,
8568 mkU8(0x8),
8569 unop(Iop_32to8, binop(Iop_And32,
8570 getIReg(rs),
8571 mkU32(0x7)))
8572 ))));
8573
8574 /* ========== GPR[rt]_15..8 ========== */
8575 assign(t7,
8576 unop(Iop_8Uto32,
8577 unop(Iop_16HIto8,
8578 unop(Iop_32to16, getIReg(rt)))));
8579 assign(t8,
8580 binop(Iop_Shr32,
8581 mkexpr(t7),
8582 unop(Iop_32to8, binop(Iop_And32,
8583 getIReg(rs),
8584 mkU32(0x7)))));
8585 /* tempB_7..0 */
8586 assign(t6,
8587 binop(Iop_Or32,
8588 mkexpr(t8),
8589 binop(Iop_Shl32,
8590 IRExpr_ITE(binop(Iop_CmpEQ32,
8591 binop(Iop_And32,
8592 mkexpr(t7),
8593 mkU32(0x00000080)
8594 ),
8595 mkU32(0x00000080)),
8596 mkU32(0xFFFFFFFF),
8597 mkU32(0x00000000)),
8598 binop(Iop_Sub8,
8599 mkU8(0x8),
8600 unop(Iop_32to8, binop(Iop_And32,
8601 getIReg(rs),
8602 mkU32(0x7)))
8603 ))));
8604
8605 /* ========== GPR[rt]_7..0 ========== */
8606 assign(t10,
8607 unop(Iop_8Uto32,
8608 unop(Iop_16to8,
8609 unop(Iop_32to16, getIReg(rt)))));
8610 assign(t11,
8611 binop(Iop_Shr32,
8612 mkexpr(t10),
8613 unop(Iop_32to8, binop(Iop_And32,
8614 getIReg(rs),
8615 mkU32(0x7)))));
8616 /* tempB_7..0 */
8617 assign(t9,
8618 binop(Iop_Or32,
8619 mkexpr(t11),
8620 binop(Iop_Shl32,
8621 IRExpr_ITE(binop(Iop_CmpEQ32,
8622 binop(Iop_And32,
8623 mkexpr(t10),
8624 mkU32(0x00000080)
8625 ),
8626 mkU32(0x00000080)),
8627 mkU32(0xFFFFFFFF),
8628 mkU32(0x00000000)),
8629 binop(Iop_Sub8,
8630 mkU8(0x8),
8631 unop(Iop_32to8, binop(Iop_And32,
8632 getIReg(rs),
8633 mkU32(0x7)))
8634 ))));
8635
8636 putIReg(rd,
8637 binop(Iop_16HLto32,
8638 binop(Iop_8HLto16,
8639 unop(Iop_32to8,
8640 IRExpr_ITE(binop(Iop_CmpEQ32,
8641 binop(Iop_And32,
8642 mkU32(rs),
8643 mkU32(0x7)
8644 ),
8645 mkU32(0x0)),
8646 mkexpr(t1),
8647 mkexpr(t0))),
8648 unop(Iop_32to8,
8649 IRExpr_ITE(binop(Iop_CmpEQ32,
8650 binop(Iop_And32,
8651 mkU32(rs),
8652 mkU32(0x7)
8653 ),
8654 mkU32(0x0)),
8655 mkexpr(t2),
8656 mkexpr(t3)))),
8657 binop(Iop_8HLto16,
8658 unop(Iop_32to8,
8659 IRExpr_ITE(binop(Iop_CmpEQ32,
8660 binop(Iop_And32,
8661 mkU32(rs),
8662 mkU32(0x7)
8663 ),
8664 mkU32(0x0)),
8665 mkexpr(t5),
8666 mkexpr(t6))),
8667 unop(Iop_32to8,
8668 IRExpr_ITE(binop(Iop_CmpEQ32,
8669 binop(Iop_And32,
8670 mkU32(rs),
8671 mkU32(0x7)
8672 ),
8673 mkU32(0x0)),
8674 mkexpr(t8),
8675 mkexpr(t9))))));
8676 break;
8677 }
8678 case 0x7: { /* SHRAV_R.QB */
8679 DIP("shrav_r.qb r%d, r%d, r%d", rd, rt, rs);
8680 vassert(!mode64);
8681 t0 = newTemp(Ity_I32);
8682 t1 = newTemp(Ity_I8);
8683 t2 = newTemp(Ity_I32);
8684 t3 = newTemp(Ity_I8);
8685 t4 = newTemp(Ity_I32);
8686 t5 = newTemp(Ity_I8);
8687 t6 = newTemp(Ity_I32);
8688 t7 = newTemp(Ity_I8);
8689 t8 = newTemp(Ity_I8);
8690 t9 = newTemp(Ity_I32);
8691
8692 assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7)));
8693 assign(t8, unop(Iop_32to8,
8694 binop(Iop_Sub32, mkexpr(t9), mkU32(0x1))));
8695 assign(t0, unop(Iop_8Sto32,
8696 unop(Iop_16to8,
8697 unop(Iop_32to16, getIReg(rt)))));
8698 assign(t1, unop(Iop_32to8,
8699 binop(Iop_Sar32,
8700 binop(Iop_Add32,
8701 mkexpr(t0),
8702 binop(Iop_Shl32,
8703 mkU32(0x1),
8704 mkexpr(t8))),
8705 unop(Iop_32to8,
8706 mkexpr(t9)))));
8707
8708 assign(t2, unop(Iop_8Sto32,
8709 unop(Iop_16HIto8,
8710 unop(Iop_32to16, getIReg(rt)))));
8711 assign(t3, unop(Iop_32to8,
8712 binop(Iop_Sar32,
8713 binop(Iop_Add32,
8714 mkexpr(t2),
8715 binop(Iop_Shl32,
8716 mkU32(0x1),
8717 mkexpr(t8))),
8718 unop(Iop_32to8, mkexpr(t9)))));
8719
8720 assign(t4, unop(Iop_8Sto32,
8721 unop(Iop_16to8,
8722 unop(Iop_32HIto16, getIReg(rt)))));
8723 assign(t5, unop(Iop_32to8,
8724 binop(Iop_Sar32,
8725 binop(Iop_Add32,
8726 mkexpr(t4),
8727 binop(Iop_Shl32,
8728 mkU32(0x1),
8729 mkexpr(t8))),
8730 unop(Iop_32to8, mkexpr(t9)))));
8731
8732 assign(t6, unop(Iop_8Sto32,
8733 unop(Iop_16HIto8,
8734 unop(Iop_32HIto16, getIReg(rt)))));
8735 assign(t7, unop(Iop_32to8,
8736 binop(Iop_Sar32,
8737 binop(Iop_Add32,
8738 mkexpr(t6),
8739 binop(Iop_Shl32,
8740 mkU32(0x1),
8741 mkexpr(t8))),
8742 unop(Iop_32to8, mkexpr(t9)))));
8743 putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
8744 mkexpr(t9),
8745 mkU32(0x0)),
8746 getIReg(rt),
8747 binop(Iop_16HLto32,
8748 binop(Iop_8HLto16,
8749 mkexpr(t7),
8750 mkexpr(t5)),
8751 binop(Iop_8HLto16,
8752 mkexpr(t3),
8753 mkexpr(t1)))));
8754 break;
8755 }
8756 case 0x8: { /* SHLL.PH */
8757 DIP("shll.ph r%d, r%d, %d", rd, rt, rs);
8758 vassert(!mode64);
8759 t0 = newTemp(Ity_I32);
8760 t1 = newTemp(Ity_I32);
8761 t2 = newTemp(Ity_I32);
8762 t3 = newTemp(Ity_I32);
dejanj781f1bd2013-10-23 14:05:15 +00008763 t4 = newTemp(Ity_I32);
8764 t5 = newTemp(Ity_I32);
8765 t6 = newTemp(Ity_I32);
8766 t7 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +00008767
8768 if (0 == rs) {
8769 putIReg(rd, getIReg(rt));
8770 } else {
8771 /* Shift lower 16 bits. */
8772 assign(t0, binop(Iop_Shl32,
8773 unop(Iop_16Sto32,
8774 unop(Iop_32to16, getIReg(rt))),
8775 mkU8(rs)));
8776
dejanj781f1bd2013-10-23 14:05:15 +00008777 assign(t1, unop(Iop_1Uto32,
8778 binop(Iop_CmpNE32,
8779 binop(Iop_Sar32,
8780 mkexpr(t0),
8781 mkU8(16)),
8782 mkU32(0))));
8783 assign(t2, unop(Iop_1Uto32,
8784 binop(Iop_CmpNE32,
8785 binop(Iop_Sar32,
8786 mkexpr(t0),
8787 mkU8(16)),
8788 mkU32(0xffffffff))));
8789 assign(t3, binop(Iop_And32,
8790 mkexpr(t1),
8791 mkexpr(t2)));
8792 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
8793 mkexpr(t3),
8794 mkU32(0x1)),
8795 binop(Iop_Or32,
8796 getDSPControl(),
8797 mkU32(0x400000)),
dejanjc3fee0d2013-07-25 09:08:03 +00008798 getDSPControl()));
8799 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
8800 binop(Iop_And32,
8801 getIReg(rt),
8802 mkU32(0x00008000)),
8803 binop(Iop_And32,
8804 mkexpr(t0),
8805 mkU32(0x00008000))
8806 ),
8807 getDSPControl(),
8808 binop(Iop_Or32,
8809 getDSPControl(),
8810 mkU32(0x400000))));
8811 /* Shift higher 16 bits. */
dejanj781f1bd2013-10-23 14:05:15 +00008812 assign(t4, binop(Iop_Shl32,
dejanjc3fee0d2013-07-25 09:08:03 +00008813 unop(Iop_16Sto32,
8814 unop(Iop_32HIto16, getIReg(rt))),
8815 mkU8(rs)));
8816
dejanj781f1bd2013-10-23 14:05:15 +00008817 assign(t5, unop(Iop_1Uto32,
8818 binop(Iop_CmpNE32,
8819 binop(Iop_Sar32,
8820 mkexpr(t4),
8821 mkU8(16)),
8822 mkU32(0))));
8823 assign(t6, unop(Iop_1Uto32,
8824 binop(Iop_CmpNE32,
8825 binop(Iop_Sar32,
8826 mkexpr(t4),
8827 mkU8(16)),
8828 mkU32(0xffffffff))));
8829 assign(t7, binop(Iop_And32,
8830 mkexpr(t5),
8831 mkexpr(t6)));
8832 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
8833 mkexpr(t7),
8834 mkU32(0x1)),
8835 binop(Iop_Or32,
8836 getDSPControl(),
8837 mkU32(0x400000)),
8838 getDSPControl()));
8839 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
8840 mkexpr(t7),
8841 mkU32(0x1)),
8842 binop(Iop_Or32,
8843 getDSPControl(),
8844 mkU32(0x400000)),
8845 getDSPControl()));
8846 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
8847 binop(Iop_And32,
8848 getIReg(rt),
8849 mkU32(0x80000000)),
8850 binop(Iop_Shl32,
8851 binop(Iop_And32,
8852 mkexpr(t4),
8853 mkU32(0x00008000)),
8854 mkU8(16))
8855 ),
dejanjc3fee0d2013-07-25 09:08:03 +00008856 getDSPControl(),
8857 binop(Iop_Or32,
8858 getDSPControl(),
8859 mkU32(0x400000))));
dejanjc3fee0d2013-07-25 09:08:03 +00008860 putIReg(rd, binop(Iop_16HLto32,
dejanj781f1bd2013-10-23 14:05:15 +00008861 unop(Iop_32to16, mkexpr(t4)),
dejanjc3fee0d2013-07-25 09:08:03 +00008862 unop(Iop_32to16, mkexpr(t0))));
8863 }
8864 break;
8865 }
8866 case 0x9: { /* SHRA.PH */
8867 DIP("shra.ph r%d, r%d, %d", rd, rt, rs);
8868 vassert(!mode64);
8869 t0 = newTemp(Ity_I32);
8870 t1 = newTemp(Ity_I32);
8871 if (0 == rs) {
8872 putIReg(rd, getIReg(rt));
8873 } else {
8874 assign(t0, binop(Iop_Sar32,
8875 unop(Iop_16Sto32,
8876 unop(Iop_32to16, getIReg(rt))),
8877 mkU8(rs)));
8878 assign(t1, binop(Iop_Sar32,
8879 unop(Iop_16Sto32,
8880 unop(Iop_32HIto16, getIReg(rt))),
8881 mkU8(rs)));
8882 putIReg(rd, binop(Iop_16HLto32,
8883 unop(Iop_32to16, mkexpr(t1)),
8884 unop(Iop_32to16, mkexpr(t0))));
8885 }
8886 break;
8887 }
8888 case 0xA: { /* SHLLV.PH */
8889 DIP("shllv.ph r%d, r%d, r%d", rd, rt, rs);
8890 vassert(!mode64);
8891 t0 = newTemp(Ity_I32);
8892 t2 = newTemp(Ity_I32);
8893 t3 = newTemp(Ity_I1);
8894 t4 = newTemp(Ity_I1);
8895 t5 = newTemp(Ity_I32);
8896 t6 = newTemp(Ity_I32);
8897 t7 = newTemp(Ity_I1);
8898 t8 = newTemp(Ity_I1);
8899 t9 = newTemp(Ity_I32);
8900 t10 = newTemp(Ity_I32);
8901 t11 = newTemp(Ity_I32);
8902 t12 = newTemp(Ity_I1);
8903 t13 = newTemp(Ity_I1);
8904
8905 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
8906
8907 /* Shift lower 16 bits. */
8908 assign(t2, binop(Iop_Shl32,
8909 unop(Iop_16Sto32,
8910 unop(Iop_32to16, getIReg(rt))),
8911 unop(Iop_32to8, mkexpr(t0))));
8912
8913 assign(t3, binop(Iop_CmpNE32,
8914 unop(Iop_16Sto32,
8915 unop(Iop_32HIto16, mkexpr(t2))),
8916 mkU32(0x00000000)));
8917 assign(t4, binop(Iop_CmpNE32,
8918 unop(Iop_16Sto32,
8919 unop(Iop_32HIto16, mkexpr(t2))),
8920 mkU32(0xffffffff)));
8921 assign(t10, binop(Iop_And32,
8922 unop(Iop_1Sto32, mkexpr(t3)),
8923 unop(Iop_1Sto32, mkexpr(t4))));
8924 assign(t5, binop(Iop_Shr32,
8925 binop(Iop_And32,
8926 getIReg(rt),
8927 mkU32(0x00008000)),
8928 mkU8(15)));
8929 assign(t12, binop(Iop_CmpEQ32,
8930 mkexpr(t5),
8931 binop(Iop_Shr32,
8932 binop(Iop_And32,
8933 mkexpr(t2),
8934 mkU32(0x00008000)),
8935 mkU8(15))));
8936
8937 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
8938 mkexpr(t10),
8939 mkU32(0x0)),
8940 binop(Iop_Or32,
8941 getDSPControl(),
8942 mkU32(0x400000)),
8943 IRExpr_ITE(mkexpr(t12),
8944 getDSPControl(),
8945 binop(Iop_Or32,
8946 getDSPControl(),
8947 mkU32(0x400000)))
8948 ));
8949 /* Shift higher 16 bits. */
8950 assign(t6, binop(Iop_Shl32,
8951 unop(Iop_16Sto32,
8952 unop(Iop_32HIto16, getIReg(rt))),
8953 unop(Iop_32to8, mkexpr(t0))));
8954
8955 assign(t7, binop(Iop_CmpNE32,
8956 unop(Iop_16Sto32,
8957 unop(Iop_32HIto16, mkexpr(t6))),
8958 mkU32(0x00000000)));
8959 assign(t8, binop(Iop_CmpNE32,
8960 unop(Iop_16Sto32,
8961 unop(Iop_32HIto16, mkexpr(t6))),
8962 mkU32(0xffffffff)));
8963 assign(t11, binop(Iop_And32,
8964 unop(Iop_1Sto32, mkexpr(t7)),
8965 unop(Iop_1Sto32, mkexpr(t8))));
8966
8967 assign(t9, binop(Iop_Shr32,
8968 binop(Iop_And32,
8969 getIReg(rt),
8970 mkU32(0x80000000)),
8971 mkU8(31)));
8972 assign(t13, binop(Iop_CmpEQ32,
8973 mkexpr(t9),
8974 binop(Iop_Shr32,
8975 binop(Iop_And32,
8976 mkexpr(t6),
8977 mkU32(0x00008000)),
8978 mkU8(15))));
8979
8980 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
8981 mkexpr(t11),
8982 mkU32(0x0)),
8983 binop(Iop_Or32,
8984 getDSPControl(),
8985 mkU32(0x400000)),
8986 IRExpr_ITE(mkexpr(t13),
8987 getDSPControl(),
8988 binop(Iop_Or32,
8989 getDSPControl(),
8990 mkU32(0x400000)))
8991 ));
8992
8993 putIReg(rd, binop(Iop_16HLto32,
8994 unop(Iop_32to16, mkexpr(t6)),
8995 unop(Iop_32to16, mkexpr(t2))));
8996 break;
8997 }
8998 case 0xB: { /* SHRAV.PH */
8999 DIP("shrav.ph r%d, r%d, r%d", rd, rt, rs);
9000 vassert(!mode64);
9001 t0 = newTemp(Ity_I32);
9002 t1 = newTemp(Ity_I1);
9003 t2 = newTemp(Ity_I32);
9004 t3 = newTemp(Ity_I32);
9005
9006 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
9007 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
9008 assign(t2, binop(Iop_Sar32,
9009 unop(Iop_16Sto32,
9010 unop(Iop_32to16, getIReg(rt))),
9011 unop(Iop_32to8, mkexpr(t0))));
9012 assign(t3, binop(Iop_Sar32,
9013 unop(Iop_16Sto32,
9014 unop(Iop_32HIto16, getIReg(rt))),
9015 unop(Iop_32to8, mkexpr(t0))));
9016 putIReg(rd,
9017 binop(Iop_16HLto32,
9018 IRExpr_ITE(mkexpr(t1),
9019 unop(Iop_32HIto16, getIReg(rt)),
9020 unop(Iop_32to16, mkexpr(t3))),
9021 IRExpr_ITE(mkexpr(t1),
9022 unop(Iop_32to16, getIReg(rt)),
9023 unop(Iop_32to16, mkexpr(t2)))));
9024 break;
9025 }
9026 case 0xC: { /* SHLL_S.PH */
9027 DIP("shll_s.ph r%d, r%d, %d", rd, rt, rs);
9028 vassert(!mode64);
9029 t0 = newTemp(Ity_I32);
dejanj781f1bd2013-10-23 14:05:15 +00009030 t1 = newTemp(Ity_I32);
9031 t2 = newTemp(Ity_I32);
9032 t3 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +00009033 t4 = newTemp(Ity_I32);
dejanj781f1bd2013-10-23 14:05:15 +00009034 t5 = newTemp(Ity_I32);
9035 t6 = newTemp(Ity_I32);
9036 t7 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +00009037 t8 = newTemp(Ity_I32);
9038 t9 = newTemp(Ity_I32);
dejanj781f1bd2013-10-23 14:05:15 +00009039 t10 = newTemp(Ity_I32);
9040 t11 = newTemp(Ity_I32);
9041 t12 = newTemp(Ity_I32);
9042 t13 = newTemp(Ity_I32);
9043 t14 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +00009044
9045 if (0 == rs) {
9046 putIReg(rd, getIReg(rt));
9047 } else {
9048 /* Shift lower 16 bits. */
9049 assign(t0, binop(Iop_Shl32,
9050 unop(Iop_16Sto32,
9051 unop(Iop_32to16, getIReg(rt))),
9052 mkU8(rs)));
9053
dejanj781f1bd2013-10-23 14:05:15 +00009054 assign(t1, unop(Iop_1Uto32,
9055 binop(Iop_CmpNE32,
9056 binop(Iop_Sar32,
9057 mkexpr(t0),
9058 mkU8(16)),
9059 mkU32(0))));
9060 assign(t2, unop(Iop_1Uto32,
9061 binop(Iop_CmpNE32,
9062 binop(Iop_Sar32,
9063 mkexpr(t0),
9064 mkU8(16)),
9065 mkU32(0xffffffff))));
9066 assign(t3, binop(Iop_And32,
9067 mkexpr(t1),
9068 mkexpr(t2)));
9069 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9070 mkexpr(t3),
9071 mkU32(0x1)),
9072 binop(Iop_Or32,
9073 getDSPControl(),
9074 mkU32(0x400000)),
9075 getDSPControl()));
dejanjc3fee0d2013-07-25 09:08:03 +00009076 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9077 binop(Iop_And32,
9078 getIReg(rt),
9079 mkU32(0x00008000)),
9080 binop(Iop_And32,
dejanj781f1bd2013-10-23 14:05:15 +00009081 mkexpr(t0),
9082 mkU32(0x00008000))
9083 ),
dejanjc3fee0d2013-07-25 09:08:03 +00009084 getDSPControl(),
9085 binop(Iop_Or32,
9086 getDSPControl(),
9087 mkU32(0x400000))));
dejanj781f1bd2013-10-23 14:05:15 +00009088 assign(t8,
9089 IRExpr_ITE(binop(Iop_CmpEQ32,
9090 mkexpr(t3),
9091 mkU32(0x1)),
9092 IRExpr_ITE(binop(Iop_CmpEQ32,
9093 binop(Iop_And32,
9094 getIReg(rt),
9095 mkU32(0x8000)),
9096 mkU32(0)),
9097 mkU32(0x00007fff),
9098 mkU32(0x00008000)),
9099 binop(Iop_And32,
9100 mkexpr(t0),
9101 mkU32(0x0000ffff))));
9102 assign(t10,
9103 IRExpr_ITE(binop(Iop_CmpEQ32,
9104 binop(Iop_And32,
9105 getIReg(rt),
9106 mkU32(0x00008000)),
9107 binop(Iop_And32,
9108 mkexpr(t0),
9109 mkU32(0x00008000))),
9110 mkexpr(t8),
9111 IRExpr_ITE(binop(Iop_CmpEQ32,
9112 binop(Iop_And32,
9113 getIReg(rt),
9114 mkU32(0x8000)),
9115 mkU32(0)),
9116 mkU32(0x00007fff),
9117 mkU32(0x00008000))));
dejanjc3fee0d2013-07-25 09:08:03 +00009118 /* Shift higher 16 bits. */
9119 assign(t4, binop(Iop_Shl32,
9120 unop(Iop_16Sto32,
9121 unop(Iop_32HIto16, getIReg(rt))),
9122 mkU8(rs)));
9123
dejanj781f1bd2013-10-23 14:05:15 +00009124 assign(t5, unop(Iop_1Uto32,
9125 binop(Iop_CmpNE32,
9126 binop(Iop_Sar32,
9127 mkexpr(t4),
9128 mkU8(16)),
9129 mkU32(0))));
9130 assign(t6, unop(Iop_1Uto32,
9131 binop(Iop_CmpNE32,
9132 binop(Iop_Sar32,
9133 mkexpr(t4),
9134 mkU8(16)),
9135 mkU32(0xffffffff))));
9136 assign(t7, binop(Iop_And32,
9137 mkexpr(t5),
9138 mkexpr(t6)));
9139 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9140 mkexpr(t7),
9141 mkU32(0x1)),
9142 binop(Iop_Or32,
9143 getDSPControl(),
9144 mkU32(0x400000)),
dejanjc3fee0d2013-07-25 09:08:03 +00009145 getDSPControl()));
dejanj781f1bd2013-10-23 14:05:15 +00009146 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9147 mkexpr(t7),
9148 mkU32(0x1)),
9149 binop(Iop_Or32,
9150 getDSPControl(),
9151 mkU32(0x400000)),
9152 getDSPControl()));
9153 assign(t12, binop(Iop_Shl32,
9154 binop(Iop_And32,
9155 mkexpr(t4),
9156 mkU32(0x8000)),
9157 mkU8(16)));
9158 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9159 binop(Iop_And32,
9160 getIReg(rt),
9161 mkU32(0x80000000)),
9162 mkexpr(t12)),
dejanjc3fee0d2013-07-25 09:08:03 +00009163 getDSPControl(),
9164 binop(Iop_Or32,
9165 getDSPControl(),
9166 mkU32(0x400000))));
dejanj781f1bd2013-10-23 14:05:15 +00009167 assign(t13, IRExpr_ITE(binop(Iop_CmpEQ32,
9168 binop(Iop_And32,
9169 getIReg(rt),
9170 mkU32(0x80000000)),
9171 mkU32(0)),
9172 mkU32(0x7fff0000),
9173 mkU32(0x80000000)));
9174 assign(t9,
9175 IRExpr_ITE(binop(Iop_CmpEQ32,
9176 mkexpr(t7),
9177 mkU32(0x1)),
9178 mkexpr(t13),
9179 binop(Iop_Shl32,
9180 binop(Iop_And32,
9181 mkexpr(t4),
9182 mkU32(0x0000ffff)),
9183 mkU8(16))));
9184 assign(t14, IRExpr_ITE(binop(Iop_CmpEQ32,
9185 binop(Iop_And32,
9186 getIReg(rt),
9187 mkU32(0x80000000)),
9188 mkU32(0)),
9189 mkU32(0x7fff0000),
9190 mkU32(0x80000000)));
9191 assign(t11,
9192 IRExpr_ITE(binop(Iop_CmpEQ32,
9193 binop(Iop_And32,
9194 getIReg(rt),
9195 mkU32(0x80000000)),
9196 binop(Iop_Shl32,
9197 binop(Iop_And32,
9198 mkexpr(t4),
9199 mkU32(0x00008000)),
9200 mkU8(16))),
9201 mkexpr(t9),
9202 mkexpr(t14)));
9203 putIReg(rd, binop(Iop_Or32,
9204 mkexpr(t10),
9205 mkexpr(t11)));
dejanjc3fee0d2013-07-25 09:08:03 +00009206 }
9207 break;
9208 }
9209 case 0xD: { /* SHRA_R.PH */
9210 DIP("shra.ph r%d, r%d, %d", rd, rt, rs);
9211 vassert(!mode64);
9212 t0 = newTemp(Ity_I32);
9213 t1 = newTemp(Ity_I32);
9214 if (0 == rs) {
9215 putIReg(rd, getIReg(rt));
9216 } else {
9217 assign(t0, binop(Iop_Sar32,
9218 binop(Iop_Add32,
9219 unop(Iop_16Sto32,
9220 unop(Iop_32to16,
9221 getIReg(rt))),
9222 binop(Iop_Shl32,
9223 mkU32(0x1),
9224 mkU8(rs-1))),
9225 mkU8(rs)));
9226 assign(t1, binop(Iop_Sar32,
9227 binop(Iop_Add32,
9228 unop(Iop_16Sto32,
9229 unop(Iop_32HIto16,
9230 getIReg(rt))),
9231 binop(Iop_Shl32,
9232 mkU32(0x1),
9233 mkU8(rs-1))),
9234 mkU8(rs)));
9235 putIReg(rd, binop(Iop_16HLto32,
9236 unop(Iop_32to16, mkexpr(t1)),
9237 unop(Iop_32to16, mkexpr(t0))));
9238 }
9239 break;
9240 }
9241 case 0xE: { /* SHLLV_S.PH */
9242 DIP("shllv_s.ph r%d, r%d, r%d", rd, rt, rs);
9243 vassert(!mode64);
9244 t0 = newTemp(Ity_I32);
9245 t2 = newTemp(Ity_I32);
9246 t3 = newTemp(Ity_I1);
9247 t4 = newTemp(Ity_I1);
9248 t5 = newTemp(Ity_I32);
9249 t6 = newTemp(Ity_I32);
9250 t7 = newTemp(Ity_I1);
9251 t8 = newTemp(Ity_I1);
9252 t9 = newTemp(Ity_I32);
9253 t10 = newTemp(Ity_I32);
9254 t11 = newTemp(Ity_I32);
9255 t12 = newTemp(Ity_I1);
9256 t13 = newTemp(Ity_I1);
9257 t14 = newTemp(Ity_I16);
9258 t15 = newTemp(Ity_I16);
9259 t16 = newTemp(Ity_I16);
9260 t17 = newTemp(Ity_I16);
9261
9262 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
9263
9264 /* Shift lower 16 bits. */
9265 assign(t2, binop(Iop_Shl32,
9266 unop(Iop_16Sto32,
9267 unop(Iop_32to16, getIReg(rt))),
9268 unop(Iop_32to8, mkexpr(t0))));
9269
9270 assign(t3, binop(Iop_CmpNE32,
9271 unop(Iop_16Sto32,
9272 unop(Iop_32HIto16, mkexpr(t2))),
9273 mkU32(0x00000000)));
9274 assign(t4, binop(Iop_CmpNE32,
9275 unop(Iop_16Sto32,
9276 unop(Iop_32HIto16, mkexpr(t2))),
9277 mkU32(0xffffffff)));
9278 assign(t10, binop(Iop_And32,
9279 unop(Iop_1Sto32, mkexpr(t3)),
9280 unop(Iop_1Sto32, mkexpr(t4))));
9281 assign(t5, binop(Iop_Shr32,
9282 binop(Iop_And32,
9283 getIReg(rt),
9284 mkU32(0x00008000)),
9285 mkU8(15)));
9286 assign(t12, binop(Iop_CmpEQ32,
9287 mkexpr(t5),
9288 binop(Iop_Shr32,
9289 binop(Iop_And32,
9290 mkexpr(t2),
9291 mkU32(0x00008000)),
9292 mkU8(15))));
9293
9294 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
9295 mkexpr(t10),
9296 mkU32(0x0)),
9297 binop(Iop_Or32,
9298 getDSPControl(),
9299 mkU32(0x400000)),
9300 IRExpr_ITE(mkexpr(t12),
9301 getDSPControl(),
9302 binop(Iop_Or32,
9303 getDSPControl(),
9304 mkU32(0x400000)))
9305 ));
9306 assign(t14, IRExpr_ITE(binop(Iop_CmpNE32,
9307 mkexpr(t5),
9308 mkU32(0x0)),
9309 mkU16(0x8000),
9310 mkU16(0x7fff)));
9311 assign(t15, IRExpr_ITE(binop(Iop_CmpNE32,
9312 mkexpr(t10),
9313 mkU32(0x0)),
9314 mkexpr(t14),
9315 IRExpr_ITE(mkexpr(t12),
9316 unop(Iop_32to16,
9317 mkexpr(t2)),
9318 mkexpr(t14))));
9319 /* Shift higher 16 bits. */
9320 assign(t6, binop(Iop_Shl32,
9321 unop(Iop_16Sto32,
9322 unop(Iop_32HIto16, getIReg(rt))),
9323 unop(Iop_32to8, mkexpr(t0))));
9324
9325 assign(t7, binop(Iop_CmpNE32,
9326 unop(Iop_16Sto32,
9327 unop(Iop_32HIto16, mkexpr(t6))),
9328 mkU32(0x00000000)));
9329 assign(t8, binop(Iop_CmpNE32,
9330 unop(Iop_16Sto32,
9331 unop(Iop_32HIto16, mkexpr(t6))),
9332 mkU32(0xffffffff)));
9333 assign(t11, binop(Iop_And32,
9334 unop(Iop_1Sto32, mkexpr(t7)),
9335 unop(Iop_1Sto32, mkexpr(t8))));
9336
9337 assign(t9, binop(Iop_Shr32,
9338 binop(Iop_And32,
9339 getIReg(rt),
9340 mkU32(0x80000000)),
9341 mkU8(31)));
9342 assign(t13, binop(Iop_CmpEQ32,
9343 mkexpr(t9),
9344 binop(Iop_Shr32,
9345 binop(Iop_And32,
9346 mkexpr(t6),
9347 mkU32(0x00008000)),
9348 mkU8(15))));
9349
9350 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
9351 mkexpr(t11),
9352 mkU32(0x0)),
9353 binop(Iop_Or32,
9354 getDSPControl(),
9355 mkU32(0x400000)),
9356 IRExpr_ITE(mkexpr(t13),
9357 getDSPControl(),
9358 binop(Iop_Or32,
9359 getDSPControl(),
9360 mkU32(0x400000)))
9361 ));
9362
9363 assign(t16, IRExpr_ITE(binop(Iop_CmpNE32,
9364 mkexpr(t9),
9365 mkU32(0x0)),
9366 mkU16(0x8000),
9367 mkU16(0x7fff)));
9368 assign(t17, IRExpr_ITE(binop(Iop_CmpNE32,
9369 mkexpr(t11),
9370 mkU32(0x0)),
9371 mkexpr(t16),
9372 IRExpr_ITE(mkexpr(t13),
9373 unop(Iop_32to16,
9374 mkexpr(t6)),
9375 mkexpr(t16))));
9376
9377 putIReg(rd, binop(Iop_16HLto32, mkexpr(t17), mkexpr(t15)));
9378 break;
9379 }
9380 case 0xF: { /* SHRAV_R.PH */
9381 DIP("shrav_r.ph r%d, r%d, r%d", rd, rt, rs);
9382 vassert(!mode64);
9383 t0 = newTemp(Ity_I32);
9384 t1 = newTemp(Ity_I1);
9385 t2 = newTemp(Ity_I8);
9386 t3 = newTemp(Ity_I32);
9387 t4 = newTemp(Ity_I32);
9388
9389 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
9390 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
9391 assign(t2, unop(Iop_32to8,
9392 binop(Iop_Sub32, mkexpr(t0), mkU32(1))));
9393
9394 assign(t3, binop(Iop_Sar32,
9395 binop(Iop_Add32,
9396 unop(Iop_16Sto32,
9397 unop(Iop_32to16, getIReg(rt))),
9398 binop(Iop_Shl32,
9399 mkU32(0x1),
9400 mkexpr(t2))),
9401 unop(Iop_32to8, mkexpr(t0))));
9402 assign(t4, binop(Iop_Sar32,
9403 binop(Iop_Add32,
9404 unop(Iop_16Sto32,
9405 unop(Iop_32HIto16,
9406 getIReg(rt))),
9407 binop(Iop_Shl32,
9408 mkU32(0x1),
9409 mkexpr(t2))),
9410 unop(Iop_32to8, mkexpr(t0))));
9411
9412 putIReg(rd, binop(Iop_16HLto32,
9413 IRExpr_ITE(mkexpr(t1),
9414 unop(Iop_32HIto16,
9415 getIReg(rt)),
9416 unop(Iop_32to16,
9417 mkexpr(t4))),
9418 IRExpr_ITE(mkexpr(t1),
9419 unop(Iop_32to16, getIReg(rt)),
9420 unop(Iop_32to16,
9421 mkexpr(t3)))));
9422 break;
9423 }
9424 case 0x14: { /* SHLL_S.W */
9425 DIP("shll_s.w r%d, r%d, %d", rd, rt, rs);
9426 vassert(!mode64);
9427 t0 = newTemp(Ity_I32);
9428 t1 = newTemp(Ity_I32);
9429 t2 = newTemp(Ity_I32);
9430 t3 = newTemp(Ity_I32);
9431 t4 = newTemp(Ity_I32);
9432 t5 = newTemp(Ity_I32);
9433
9434 if (0 == rs) {
9435 putIReg(rd, getIReg(rt));
9436 } else {
9437 /* t0-bits that will be discarded, sign extended to
9438 32bits. */
9439 assign(t0, binop(Iop_Sar32,
9440 binop(Iop_And32,
9441 getIReg(rt),
9442 binop(Iop_Sar32,
9443 mkU32(0x80000000),
9444 mkU8(rs-1))),
9445 mkU8(32-rs)));
9446
9447 assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32,
9448 binop(Iop_And32,
9449 getIReg(rt),
9450 mkU32(0x80000000)),
9451 mkU32(0x0)),
9452 mkU32(0x7fffffff),
9453 mkU32(0x80000000)));
9454
9455 assign(t2, binop(Iop_Shl32, getIReg(rt), mkU8(rs)));
9456 assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
9457 binop(Iop_And32,
9458 getIReg(rt),
9459 mkU32(0x80000000)),
9460 binop(Iop_And32,
9461 mkexpr(t2),
9462 mkU32(0x80000000))),
9463 mkexpr(t2),
9464 mkexpr(t1)));
9465
9466 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
9467 mkexpr(t0),
9468 mkU32(0x0)),
9469 IRExpr_ITE(binop(Iop_CmpNE32,
9470 mkexpr(t0),
9471 mkU32(0xffffffff)
9472 ),
9473 mkexpr(t1),
9474 mkexpr(t3)),
9475 mkexpr(t3)));
9476 assign(t5, IRExpr_ITE(binop(Iop_CmpNE32,
9477 mkexpr(t0),
9478 mkU32(0xffffffff)),
9479 binop(Iop_Or32,
9480 getDSPControl(),
9481 mkU32(0x400000)),
9482 getDSPControl()));
9483 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
9484 mkexpr(t0),
9485 mkU32(0x0)),
9486 mkexpr(t5),
9487 getDSPControl()));
9488 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9489 binop(Iop_And32,
9490 getIReg(rt),
9491 mkU32(0x80000000)),
9492 binop(Iop_And32,
9493 mkexpr(t2),
9494 mkU32(0x80000000))
9495 ),
9496 getDSPControl(),
9497 binop(Iop_Or32,
9498 getDSPControl(),
9499 mkU32(0x400000))));
9500 putIReg(rd, mkexpr(t4));
9501 }
9502 break;
9503 }
9504 case 0x15: { /* SHRA_R.W */
9505 DIP("shra_r.w r%d, r%d, %d", rd, rt, rs);
9506 vassert(!mode64);
9507 if (0 == rs) {
9508 putIReg(rd, getIReg(rt));
9509 } else {
9510 putIReg(rd, binop(Iop_Add32,
9511 binop(Iop_Sar32,
9512 getIReg(rt), mkU8(rs)),
9513 binop(Iop_Shr32,
9514 binop(Iop_And32,
9515 getIReg(rt),
9516 binop(Iop_Shl32,
9517 mkU32(0x1),
9518 mkU8(rs-1))),
9519 mkU8(rs-1))));
9520 }
9521 break;
9522 }
9523 case 0x16: { /* SHLLV_S.W */
9524 DIP("shllv_s.w r%d, r%d, r%d", rd, rt, rs);
9525 vassert(!mode64);
9526 t0 = newTemp(Ity_I32);
9527 t1 = newTemp(Ity_I1);
9528 t2 = newTemp(Ity_I32);
9529 t3 = newTemp(Ity_I64);
9530 t4 = newTemp(Ity_I1);
9531 t5 = newTemp(Ity_I1);
9532 t6 = newTemp(Ity_I32);
9533 t7 = newTemp(Ity_I1);
9534 t8 = newTemp(Ity_I32);
9535
9536 /* Check if shift amount is zero. */
9537 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
9538 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
9539
9540 /* t2 = sign of the input value. */
9541 assign(t2, binop(Iop_Shr32,
9542 binop(Iop_And32,
9543 getIReg(rt),
9544 mkU32(0x80000000)),
9545 mkU8(31)));
9546 /* Shift left input value and check for overflow. */
9547 assign(t3, binop(Iop_Shl64,
9548 unop(Iop_32Sto64, getIReg(rt)),
9549 unop(Iop_32to8, mkexpr(t0))));
9550 assign(t4, binop(Iop_CmpNE32,
9551 unop(Iop_64HIto32, mkexpr(t3)),
9552 mkU32(0x00000000)));
9553 assign(t5, binop(Iop_CmpNE32,
9554 unop(Iop_64HIto32, mkexpr(t3)),
9555 mkU32(0xffffffff)));
9556 assign(t6, binop(Iop_And32,
9557 unop(Iop_1Uto32, mkexpr(t4)),
9558 unop(Iop_1Uto32, mkexpr(t5))));
9559 assign(t7, binop(Iop_CmpEQ32,
9560 binop(Iop_Shr32,
9561 binop(Iop_And32,
9562 getIReg(rt),
9563 mkU32(0x80000000)),
9564 mkU8(31)),
9565 binop(Iop_Shr32,
9566 binop(Iop_And32,
9567 unop(Iop_64to32, mkexpr(t3)),
9568 mkU32(0x80000000)),
9569 mkU8(31))));
9570
9571 putDSPControl(IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)),
9572 binop(Iop_Or32,
9573 getDSPControl(),
9574 mkU32(0x400000)),
9575 IRExpr_ITE(mkexpr(t7),
9576 getDSPControl(),
9577 binop(Iop_Or32,
9578 getDSPControl(),
9579 mkU32(0x400000)))
9580 ));
9581
9582 assign(t8, IRExpr_ITE(unop(Iop_32to1,
9583 mkexpr(t2)),
9584 mkU32(0x80000000),
9585 mkU32(0x7fffffff)));
9586 putIReg(rd, IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)),
9587 IRExpr_ITE(unop(Iop_32to1,
9588 mkexpr(t2)),
9589 mkU32(0x80000000),
9590 mkU32(0x7fffffff)),
9591 IRExpr_ITE(mkexpr(t7),
9592 unop(Iop_64to32,
9593 mkexpr(t3)),
9594 mkexpr(t8))));
9595 break;
9596 }
9597 case 0x17: { /* SHRAV_R.W */
9598 DIP("shrav_r.w r%d, r%d, r%d", rd, rt, rs);
9599 vassert(!mode64);
9600 t0 = newTemp(Ity_I32);
9601 t1 = newTemp(Ity_I1);
9602 t2 = newTemp(Ity_I8);
9603 t3 = newTemp(Ity_I32);
9604
9605 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
9606 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
9607 assign(t2, unop(Iop_32to8,
9608 binop(Iop_Sub32, mkexpr(t0), mkU32(1))));
9609
9610 putIReg(rd, IRExpr_ITE(mkexpr(t1),
9611 getIReg(rt),
9612 binop(Iop_Sar32,
9613 binop(Iop_Add32,
9614 binop(Iop_Sar32,
9615 getIReg(rt),
9616 mkexpr(t2)),
9617 mkU32(0x1)),
9618 mkU8(1))));
9619 break;
9620 }
9621 case 0x19: { /* SHRL.PH */
9622 DIP("shrl.ph r%d, r%d, %d", rd, rt, rs);
9623 vassert(!mode64);
9624 t0 = newTemp(Ity_I32);
9625 t1 = newTemp(Ity_I32);
9626 assign(t0, binop(Iop_Shr32,
9627 unop(Iop_16Uto32,
9628 unop(Iop_32to16, getIReg(rt))),
9629 mkU8(rs)));
9630 assign(t1, binop(Iop_Shr32,
9631 unop(Iop_16Uto32,
9632 unop(Iop_32HIto16, getIReg(rt))),
9633 mkU8(rs)));
9634 putIReg(rd, binop(Iop_16HLto32,
9635 unop(Iop_32to16, mkexpr(t1)),
9636 unop(Iop_32to16, mkexpr(t0))));
9637 break;
9638 }
9639 case 0x1B: { /* SHRLV.PH */
9640 DIP("shrlv.ph r%d, r%d, r%d", rd, rt, rs);
9641 vassert(!mode64);
9642 t0 = newTemp(Ity_I32);
9643 t1 = newTemp(Ity_I1);
9644 t2 = newTemp(Ity_I32);
9645 t3 = newTemp(Ity_I32);
9646 t4 = newTemp(Ity_I16);
9647 t5 = newTemp(Ity_I16);
9648
9649 /* Get shift amount from lower 5 bits of rs
9650 and check if it is zero. */
9651 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
9652 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
9653
9654 assign(t2, binop(Iop_Shr32,
9655 unop(Iop_16Uto32,
9656 unop(Iop_32to16, getIReg(rt))),
9657 unop(Iop_32to8, mkexpr(t0))));
9658 assign(t3, binop(Iop_Shr32,
9659 unop(Iop_16Uto32,
9660 unop(Iop_32HIto16, getIReg(rt))),
9661 unop(Iop_32to8, mkexpr(t0))));
9662
9663 assign(t4, IRExpr_ITE(mkexpr(t1),
9664 unop(Iop_32HIto16, getIReg(rt)),
9665 unop(Iop_32to16, mkexpr(t3))));
9666 assign(t5, IRExpr_ITE(mkexpr(t1),
9667 unop(Iop_32to16, getIReg(rt)),
9668 unop(Iop_32to16, mkexpr(t2))));
9669 putIReg(rd, binop(Iop_16HLto32, mkexpr(t4), mkexpr(t5)));
9670 break;
9671 }
9672 default:
9673 return -1;
9674 }
9675 break; /* end of SHLL.QB */
9676 }
9677 case 0x18: { /* ADDUH.QB/MUL.PH */
9678 switch(sa) {
9679 case 0x00: { /* ADDUH.QB */
9680 DIP("adduh.qb r%d, r%d, r%d", rd, rs, rt);
9681 vassert(!mode64);
9682 t0 = newTemp(Ity_I32);
9683
9684 assign(t0, binop(Iop_HAdd8Ux4, getIReg(rs), getIReg(rt)));
9685
9686 putIReg(rd, mkexpr(t0));
9687 break;
9688 }
9689 case 0x1: { /* SUBUH.QB */
9690 DIP("subuh.qb r%d, r%d, r%d", rd, rs, rt);
9691 vassert(!mode64);
9692 t0 = newTemp(Ity_I32);
9693
9694 assign(t0, binop(Iop_HSub8Ux4, getIReg(rs), getIReg(rt)));
9695
9696 putIReg(rd, mkexpr(t0));
9697 break;
9698 }
9699 case 0x02: { /* ADDUH_R.QB */
9700 DIP("adduh_r.qb r%d, r%d, r%d", rd, rs, rt);
9701 vassert(!mode64);
9702 t0 = newTemp(Ity_I32);
9703 t1 = newTemp(Ity_I32);
9704 t2 = newTemp(Ity_I8);
9705 t3 = newTemp(Ity_I32);
9706 t4 = newTemp(Ity_I32);
9707 t5 = newTemp(Ity_I8);
9708 t6 = newTemp(Ity_I32);
9709 t7 = newTemp(Ity_I32);
9710 t8 = newTemp(Ity_I8);
9711 t9 = newTemp(Ity_I32);
9712 t10 = newTemp(Ity_I32);
9713 t11 = newTemp(Ity_I8);
9714
9715 /* Extract input bytes, add values, add 1 and half the
9716 result. */
9717 assign(t0, unop(Iop_8Uto32,
9718 unop(Iop_16to8,
9719 unop(Iop_32to16, getIReg(rs)))));
9720 assign(t1, unop(Iop_8Uto32,
9721 unop(Iop_16to8,
9722 unop(Iop_32to16, getIReg(rt)))));
9723 assign(t2, unop(Iop_16to8,
9724 unop(Iop_32to16,
9725 binop(Iop_Shr32,
9726 binop(Iop_Add32,
9727 binop(Iop_Add32,
9728 mkexpr(t0),
9729 mkexpr(t1)),
9730 mkU32(0x00000001)),
9731 mkU8(0x01)))));
9732
9733 assign(t3, unop(Iop_8Uto32,
9734 unop(Iop_16HIto8,
9735 unop(Iop_32to16, getIReg(rs)))));
9736 assign(t4, unop(Iop_8Uto32,
9737 unop(Iop_16HIto8,
9738 unop(Iop_32to16, getIReg(rt)))));
9739 assign(t5, unop(Iop_16to8,
9740 unop(Iop_32to16,
9741 binop(Iop_Shr32,
9742 binop(Iop_Add32,
9743 binop(Iop_Add32,
9744 mkexpr(t3),
9745 mkexpr(t4)),
9746 mkU32(0x00000001)),
9747 mkU8(0x01)))));
9748
9749 assign(t6, unop(Iop_8Uto32,
9750 unop(Iop_16to8,
9751 unop(Iop_32HIto16, getIReg(rs)))));
9752 assign(t7, unop(Iop_8Uto32,
9753 unop(Iop_16to8,
9754 unop(Iop_32HIto16, getIReg(rt)))));
9755 assign(t8, unop(Iop_16to8,
9756 unop(Iop_32to16,
9757 binop(Iop_Shr32,
9758 binop(Iop_Add32,
9759 binop(Iop_Add32,
9760 mkexpr(t7),
9761 mkexpr(t6)),
9762 mkU32(0x00000001)),
9763 mkU8(0x01)))));
9764
9765 assign(t9, unop(Iop_8Uto32,
9766 unop(Iop_16HIto8,
9767 unop(Iop_32HIto16, getIReg(rs)))));
9768 assign(t10, unop(Iop_8Uto32,
9769 unop(Iop_16HIto8,
9770 unop(Iop_32HIto16, getIReg(rt)))));
9771 assign(t11, unop(Iop_16to8,
9772 unop(Iop_32to16,
9773 binop(Iop_Shr32,
9774 binop(Iop_Add32,
9775 binop(Iop_Add32,
9776 mkexpr(t9),
9777 mkexpr(t10)),
9778 mkU32(0x00000001)),
9779 mkU8(0x01)))));
9780
9781 putIReg(rd, binop(Iop_16HLto32,
9782 binop(Iop_8HLto16,
9783 mkexpr(t11), mkexpr(t8)),
9784 binop(Iop_8HLto16,
9785 mkexpr(t5), mkexpr(t2))));
9786 break;
9787 }
9788 case 0x3: { /* SUBUH_R.QB */
9789 DIP("subuh_r.qb r%d, r%d, r%d", rd, rs, rt);
9790 vassert(!mode64);
9791 t1 = newTemp(Ity_I32);
9792 t2 = newTemp(Ity_I32);
9793 t3 = newTemp(Ity_I32);
9794 t4 = newTemp(Ity_I32);
9795 t5 = newTemp(Ity_I32);
9796 t6 = newTemp(Ity_I32);
9797 t7 = newTemp(Ity_I32);
9798 t8 = newTemp(Ity_I32);
9799 t9 = newTemp(Ity_I8);
9800 t10 = newTemp(Ity_I8);
9801 t11 = newTemp(Ity_I8);
9802 t12 = newTemp(Ity_I8);
9803
9804 /* Extract each byte of rs and rt. */
9805 assign(t1, unop(Iop_8Uto32,
9806 unop(Iop_16to8,
9807 unop(Iop_32to16, getIReg(rs)))));
9808 assign(t2, unop(Iop_8Uto32,
9809 unop(Iop_16HIto8,
9810 unop(Iop_32to16, getIReg(rs)))));
9811 assign(t3, unop(Iop_8Uto32,
9812 unop(Iop_16to8,
9813 unop(Iop_32HIto16, getIReg(rs)))));
9814 assign(t4, unop(Iop_8Uto32,
9815 unop(Iop_16HIto8,
9816 unop(Iop_32HIto16, getIReg(rs)))));
9817
9818 assign(t5, unop(Iop_8Uto32,
9819 unop(Iop_16to8,
9820 unop(Iop_32to16, getIReg(rt)))));
9821 assign(t6, unop(Iop_8Uto32,
9822 unop(Iop_16HIto8,
9823 unop(Iop_32to16, getIReg(rt)))));
9824 assign(t7, unop(Iop_8Uto32,
9825 unop(Iop_16to8,
9826 unop(Iop_32HIto16, getIReg(rt)))));
9827 assign(t8, unop(Iop_8Uto32,
9828 unop(Iop_16HIto8,
9829 unop(Iop_32HIto16, getIReg(rt)))));
9830
9831 /* Add 1 to each resulting byte and half the results. */
9832 assign(t9, unop(Iop_16to8,
9833 unop(Iop_32to16,
9834 binop(Iop_Shr32,
9835 binop(Iop_Add32,
9836 binop(Iop_Sub32,
9837 mkexpr(t1),
9838 mkexpr(t5)),
9839 mkU32(0x00000001)),
9840 mkU8(0x01)))));
9841 assign(t10, unop(Iop_16to8,
9842 unop(Iop_32to16,
9843 binop(Iop_Shr32,
9844 binop(Iop_Add32,
9845 binop(Iop_Sub32,
9846 mkexpr(t2),
9847 mkexpr(t6)),
9848 mkU32(0x00000001)),
9849 mkU8(0x01)))));
9850 assign(t11, unop(Iop_16to8,
9851 unop(Iop_32to16,
9852 binop(Iop_Shr32,
9853 binop(Iop_Add32,
9854 binop(Iop_Sub32,
9855 mkexpr(t3),
9856 mkexpr(t7)),
9857 mkU32(0x00000001)),
9858 mkU8(0x01)))));
9859 assign(t12, unop(Iop_16to8,
9860 unop(Iop_32to16,
9861 binop(Iop_Shr32,
9862 binop(Iop_Add32,
9863 binop(Iop_Sub32,
9864 mkexpr(t4),
9865 mkexpr(t8)),
9866 mkU32(0x00000001)),
9867 mkU8(0x01)))));
9868
9869 putIReg(rd, binop(Iop_16HLto32,
9870 binop(Iop_8HLto16,
9871 mkexpr(t12), mkexpr(t11)),
9872 binop(Iop_8HLto16,
9873 mkexpr(t10), mkexpr(t9))));
9874 break;
9875 }
9876 case 0x8: { /* ADDQH.PH */
9877 DIP("addqh.ph r%d, r%d, r%d", rd, rs, rt);
9878 vassert(!mode64);
9879 t0 = newTemp(Ity_I32);
9880 t1 = newTemp(Ity_I16);
9881 t2 = newTemp(Ity_I32);
9882 t3 = newTemp(Ity_I16);
9883
9884 /* Add lower halfs of rs and rt
9885 and right shift the result by 1. */
9886 assign(t0, binop(Iop_Add32,
9887 unop(Iop_16Sto32,
9888 unop(Iop_32to16, getIReg(rs))),
9889 unop(Iop_16Sto32,
9890 unop(Iop_32to16, getIReg(rt)))));
9891 assign(t1, unop(Iop_32to16,
9892 binop(Iop_Shr32,
9893 binop(Iop_And32,
9894 mkexpr(t0),
9895 mkU32(0x0001fffe)),
9896 mkU8(0x1))));
9897 /* Add higher halfs of rs and rt
9898 and right shift the result by 1. */
9899 assign(t2, binop(Iop_Add32,
9900 unop(Iop_16Sto32,
9901 unop(Iop_32HIto16, getIReg(rs))),
9902 unop(Iop_16Sto32,
9903 unop(Iop_32HIto16, getIReg(rt)))));
9904 assign(t3, unop(Iop_32to16,
9905 binop(Iop_Shr32,
9906 binop(Iop_And32,
9907 mkexpr(t2),
9908 mkU32(0x0001fffe)),
9909 mkU8(0x1))));
9910 putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
9911 break;
9912 }
9913 case 0x9: { /* SUBQH.PH */
9914 DIP("subqh.ph r%d, r%d, r%d", rd, rs, rt);
9915 vassert(!mode64);
9916
9917 putIReg(rd, binop(Iop_HSub16Sx2,
9918 getIReg(rs), getIReg(rt)));
9919 break;
9920 }
9921 case 0xA: {/* ADDQH_R.PH */
9922 DIP("addqh_r.ph r%d, r%d, r%d", rd, rs, rt);
9923 vassert(!mode64);
9924 t0 = newTemp(Ity_I32);
9925 t1 = newTemp(Ity_I16);
9926 t2 = newTemp(Ity_I32);
9927 t3 = newTemp(Ity_I16);
9928
9929 /* Add lower halfs of rs and rt, add 1
9930 and right shift the result by 1. */
9931 assign(t0, binop(Iop_Add32,
9932 unop(Iop_16Sto32,
9933 unop(Iop_32to16, getIReg(rs))),
9934 unop(Iop_16Sto32,
9935 unop(Iop_32to16, getIReg(rt)))));
9936 assign(t1, unop(Iop_32to16,
9937 binop(Iop_Shr32,
9938 binop(Iop_And32,
9939 binop(Iop_Add32,
9940 mkexpr(t0),
9941 mkU32(0x1)),
9942 mkU32(0x0001fffe)),
9943 mkU8(0x1))));
9944 /* Add higher halfs of rs and rt, add 1
9945 and right shift the result by 1. */
9946 assign(t2, binop(Iop_Add32,
9947 unop(Iop_16Sto32,
9948 unop(Iop_32HIto16, getIReg(rs))),
9949 unop(Iop_16Sto32,
9950 unop(Iop_32HIto16, getIReg(rt)))));
9951 assign(t3, unop(Iop_32to16,
9952 binop(Iop_Shr32,
9953 binop(Iop_And32,
9954 binop(Iop_Add32,
9955 mkexpr(t2),
9956 mkU32(0x1)),
9957 mkU32(0x0001fffe)),
9958 mkU8(0x1))));
9959
9960 putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
9961 break;
9962 }
9963 case 0xB: { /* SUBQH_R.PH */
9964 DIP("subqh_r.ph r%d, r%d, r%d", rd, rs, rt);
9965 vassert(!mode64);
9966 t0 = newTemp(Ity_I32);
9967 t1 = newTemp(Ity_I16);
9968 t2 = newTemp(Ity_I32);
9969 t3 = newTemp(Ity_I16);
9970
9971 /* Sub lower halfs of rs and rt, add 1
9972 and right shift the result by 1. */
9973 assign(t0, binop(Iop_Sub32,
9974 unop(Iop_16Sto32,
9975 unop(Iop_32to16, getIReg(rs))),
9976 unop(Iop_16Sto32,
9977 unop(Iop_32to16, getIReg(rt)))));
9978 assign(t1, unop(Iop_32to16,
9979 binop(Iop_Shr32,
9980 binop(Iop_And32,
9981 binop(Iop_Add32,
9982 mkexpr(t0),
9983 mkU32(0x1)),
9984 mkU32(0x0001fffe)),
9985 mkU8(0x1))));
9986 /* Sub higher halfs of rs and rt, add 1
9987 and right shift the result by 1. */
9988 assign(t2, binop(Iop_Sub32,
9989 unop(Iop_16Sto32,
9990 unop(Iop_32HIto16, getIReg(rs))),
9991 unop(Iop_16Sto32,
9992 unop(Iop_32HIto16, getIReg(rt)))));
9993 assign(t3, unop(Iop_32to16,
9994 binop(Iop_Shr32,
9995 binop(Iop_And32,
9996 binop(Iop_Add32,
9997 mkexpr(t2),
9998 mkU32(0x1)),
9999 mkU32(0x0001fffe)),
10000 mkU8(0x1))));
10001
10002 putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
10003 break;
10004 }
10005 case 0xC: { /* MUL.PH */
10006 DIP("mul.ph r%d, r%d, r%d", rd, rs, rt);
10007 vassert(!mode64);
10008 t0 = newTemp(Ity_I32);
10009 t1 = newTemp(Ity_I32);
10010 t2 = newTemp(Ity_I32);
10011
10012 assign(t0,
10013 binop(Iop_Mul32,
10014 unop(Iop_16Sto32,
10015 unop(Iop_32HIto16, getIReg(rs))),
10016 unop(Iop_16Sto32,
10017 unop(Iop_32HIto16, getIReg(rt)))));
10018 /* DSP Control flag. */
10019 putDSPControl(IRExpr_ITE(unop(Iop_Not1,
10020 binop(Iop_CmpLE32S,
10021 mkexpr(t0),
10022 mkU32(0x7FFF))),
10023 binop(Iop_Or32,
10024 getDSPControl(),
10025 mkU32(0x00200000)),
10026 IRExpr_ITE(binop(Iop_CmpLT32S,
10027 mkexpr(t0),
10028 mkU32(0xFFFF8000)
10029 ),
10030 binop(Iop_Or32,
10031 getDSPControl(),
10032 mkU32(0x00200000)
10033 ),
10034 getDSPControl())));
10035
10036 assign(t1,
10037 binop(Iop_Mul32,
10038 unop(Iop_16Sto32,
10039 unop(Iop_32to16, getIReg(rs))),
10040 unop(Iop_16Sto32,
10041 unop(Iop_32to16, getIReg(rt)))));
10042 /* DSP Control flag. */
10043 putDSPControl(IRExpr_ITE(unop(Iop_Not1,
10044 binop(Iop_CmpLE32S,
10045 mkexpr(t1),
10046 mkU32(0x7FFF))),
10047 binop(Iop_Or32,
10048 getDSPControl(),
10049 mkU32(0x00200000)),
10050 IRExpr_ITE(binop(Iop_CmpLT32S,
10051 mkexpr(t1),
10052 mkU32(0xFFFF8000)
10053 ),
10054 binop(Iop_Or32,
10055 getDSPControl(),
10056 mkU32(0x00200000)
10057 ),
10058 getDSPControl())));
10059
10060 assign(t2, binop(Iop_16HLto32,
10061 unop(Iop_32to16, mkexpr(t0)),
10062 unop(Iop_32to16, mkexpr(t1))));
10063 putIReg(rd, mkexpr(t2));
10064 break;
10065 }
10066 case 0xE: { /* MUL_S.PH */
10067 DIP("mul_s.ph r%d r%d, r%d", rd, rs, rt);
10068 vassert(!mode64);
10069
10070 t0 = newTemp(Ity_I32);
10071 t1 = newTemp(Ity_I32);
10072 t2 = newTemp(Ity_I32);
10073 t3 = newTemp(Ity_I32);
10074 t4 = newTemp(Ity_I32);
10075
10076 /* t0 - signed intermediate result. */
10077 assign(t0,
10078 binop(Iop_Mul32,
10079 unop(Iop_16Sto32,
10080 unop(Iop_32HIto16, getIReg(rs))),
10081 unop(Iop_16Sto32,
10082 unop(Iop_32HIto16, getIReg(rt)))));
10083
10084 assign(t1,
10085 IRExpr_ITE(unop(Iop_Not1,
10086 binop(Iop_CmpLE32S,
10087 mkexpr(t0),
10088 mkU32(0x7FFF))),
10089 mkU32(0x00007FFF),
10090 IRExpr_ITE(binop(Iop_CmpLT32S,
10091 mkexpr(t0),
10092 mkU32(0xFFFF8000)),
10093 mkU32(0xFFFF8000),
10094 mkexpr(t0))));
10095
10096 /* DSP Control flag. */
10097 putDSPControl(IRExpr_ITE(unop(Iop_Not1,
10098 binop(Iop_CmpLE32S,
10099 mkexpr(t0),
10100 mkU32(0x7FFF))),
10101 binop(Iop_Or32,
10102 getDSPControl(),
10103 mkU32(0x00200000)),
10104 IRExpr_ITE(binop(Iop_CmpLT32S,
10105 mkexpr(t0),
10106 mkU32(0xFFFF8000)
10107 ),
10108 binop(Iop_Or32,
10109 getDSPControl(),
10110 mkU32(0x00200000)
10111 ),
10112 getDSPControl())));
10113
10114 /* t2 - signed intermediate result. */
10115 assign(t2, binop(Iop_Mul32,
10116 unop(Iop_16Sto32,
10117 unop(Iop_32to16, getIReg(rs))),
10118 unop(Iop_16Sto32,
10119 unop(Iop_32to16, getIReg(rt)))));
10120
10121 assign(t3, IRExpr_ITE(unop(Iop_Not1,
10122 binop(Iop_CmpLE32S,
10123 mkexpr(t2),
10124 mkU32(0x7FFF))),
10125 mkU32(0x00007FFF),
10126 IRExpr_ITE(binop(Iop_CmpLT32S,
10127 mkexpr(t2),
10128 mkU32(0xFFFF8000)),
10129 mkU32(0xFFFF8000),
10130 mkexpr(t2))));
10131
10132 /* DSP Control flag. */
10133 putDSPControl(IRExpr_ITE(unop(Iop_Not1,
10134 binop(Iop_CmpLE32S,
10135 mkexpr(t2),
10136 mkU32(0x7FFF))),
10137 binop(Iop_Or32,
10138 getDSPControl(),
10139 mkU32(0x00200000)),
10140 IRExpr_ITE(binop(Iop_CmpLT32S,
10141 mkexpr(t2),
10142 mkU32(0xFFFF8000)
10143 ),
10144 binop(Iop_Or32,
10145 getDSPControl(),
10146 mkU32(0x00200000)
10147 ),
10148 getDSPControl())));
10149
10150 assign(t4, binop(Iop_16HLto32,
10151 unop(Iop_32to16, mkexpr(t1)),
10152 unop(Iop_32to16, mkexpr(t3))));
10153 putIReg(rd, mkexpr(t4));
10154 break;
10155 }
10156 case 0x10: { /* ADDQH.W */
10157 DIP("addqh.w r%d, r%d, r%d", rd, rs, rt);
10158 vassert(!mode64);
10159 t0 = newTemp(Ity_I64);
10160 t1 = newTemp(Ity_I64);
10161
10162 assign(t0, binop(Iop_Add64,
10163 unop(Iop_32Sto64, getIReg(rs)),
10164 unop(Iop_32Sto64, getIReg(rt))));
10165 assign(t1, binop(Iop_And64,
10166 mkexpr(t0),
10167 mkU64(0x00000001fffffffeULL)));
10168 putIReg(rd, unop(Iop_64to32,
10169 binop(Iop_Shr64, mkexpr(t1), mkU8(0x1))));
10170 break;
10171 }
10172 case 0x11: { /* SUBQH.W */
10173 DIP("subqh.w r%d, r%d, r%d", rd, rs, rt);
10174 vassert(!mode64);
10175 t0 = newTemp(Ity_I64);
10176 t1 = newTemp(Ity_I64);
10177
10178 assign(t0, binop(Iop_Sub64,
10179 unop(Iop_32Sto64, getIReg(rs)),
10180 unop(Iop_32Sto64, getIReg(rt))));
10181 assign(t1, binop(Iop_And64,
10182 mkexpr(t0),
10183 mkU64(0x00000001fffffffeULL)));
10184 putIReg(rd, unop(Iop_64to32,
10185 binop(Iop_Shr64, mkexpr(t1), mkU8(0x1))));
10186 break;
10187 }
10188 case 0x12: { /* ADDQH_R.W */
10189 DIP("addqh_r.w r%d, r%d, r%d", rd, rs, rt);
10190 vassert(!mode64);
10191 t0 = newTemp(Ity_I64);
10192 t1 = newTemp(Ity_I64);
10193 t2 = newTemp(Ity_I64);
10194
10195 assign(t0, binop(Iop_Add64,
10196 unop(Iop_32Sto64, getIReg(rs)),
10197 unop(Iop_32Sto64, getIReg(rt))));
10198 assign(t1, binop(Iop_Add64,
10199 mkexpr(t0),
10200 mkU64(0x0000000000000001ULL)));
10201 assign(t2, binop(Iop_And64,
10202 mkexpr(t1),
10203 mkU64(0x00000001fffffffeULL)));
10204 putIReg(rd, unop(Iop_64to32,
10205 binop(Iop_Shr64, mkexpr(t2), mkU8(0x1))));
10206 break;
10207 }
10208 case 0x13: { /* SUBQH_R.W */
10209 DIP("subqh_r.w r%d, r%d, r%d", rd, rs, rt);
10210 vassert(!mode64);
10211 t0 = newTemp(Ity_I64);
10212 t1 = newTemp(Ity_I64);
10213 t2 = newTemp(Ity_I64);
10214
10215 assign(t0, binop(Iop_Sub64,
10216 unop(Iop_32Sto64, getIReg(rs)),
10217 unop(Iop_32Sto64, getIReg(rt))));
10218 assign(t1, binop(Iop_Add64,
10219 mkexpr(t0),
10220 mkU64(0x0000000000000001ULL)));
10221 assign(t2, binop(Iop_And64,
10222 mkexpr(t1),
10223 mkU64(0x00000001fffffffeULL)));
10224 putIReg(rd, unop(Iop_64to32,
10225 binop(Iop_Shr64, mkexpr(t2), mkU8(0x1))));
10226 break;
10227 }
10228 case 0x16: { /* MULQ_S.W */
10229 DIP("mulq_s.w r%d, r%d, r%d", rd, rs, rt);
10230 vassert(!mode64);
10231 t0 = newTemp(Ity_I64);
10232 t1 = newTemp(Ity_I1);
10233 t2 = newTemp(Ity_I1);
10234
10235 assign(t0, binop(Iop_Shl64,
10236 binop(Iop_MullS32,
10237 getIReg(rt), getIReg(rs)),
10238 mkU8(0x1)));
10239 assign(t1, binop(Iop_CmpEQ32,
10240 getIReg(rt), mkU32(0x80000000)));
10241 assign(t2, binop(Iop_CmpEQ32,
10242 getIReg(rs), mkU32(0x80000000)));
10243
10244 putDSPControl(IRExpr_ITE(mkexpr(t1),
10245 IRExpr_ITE(mkexpr(t2),
10246 binop(Iop_Or32,
10247 getDSPControl(),
10248 mkU32(0x00200000)
10249 ),
10250 getDSPControl()),
10251 getDSPControl()));
10252 putIReg(rd, IRExpr_ITE(mkexpr(t1),
10253 IRExpr_ITE(mkexpr(t2),
10254 mkU32(0x7fffffff),
10255 unop(Iop_64HIto32,
10256 mkexpr(t0))),
10257 unop(Iop_64HIto32, mkexpr(t0))));
10258 break;
10259 }
10260 case 0x17: { /* MULQ_RS.W */
10261 DIP("mulq_rs.w r%d, r%d, r%d", rd, rs, rt);
10262 vassert(!mode64);
10263 t0 = newTemp(Ity_I64);
10264 t1 = newTemp(Ity_I1);
10265 t2 = newTemp(Ity_I1);
10266
10267 assign(t0, binop(Iop_Add64,
10268 binop(Iop_Shl64,
10269 binop(Iop_MullS32,
10270 getIReg(rt),
10271 getIReg(rs)),
10272 mkU8(0x1)),
10273 mkU64(0x0000000080000000ULL)));
10274 assign(t1,
10275 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000)));
10276 assign(t2,
10277 binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x80000000)));
10278 putDSPControl(IRExpr_ITE(mkexpr(t1),
10279 IRExpr_ITE(mkexpr(t2),
10280 binop(Iop_Or32,
10281 getDSPControl(),
10282 mkU32(0x00200000)
10283 ),
10284 getDSPControl()),
10285 getDSPControl()));
10286 putIReg(rd, IRExpr_ITE(mkexpr(t1),
10287 IRExpr_ITE(mkexpr(t2),
10288 mkU32(0x7fffffff),
10289 unop(Iop_64HIto32,
10290 mkexpr(t0))),
10291 unop(Iop_64HIto32, mkexpr(t0))));
10292 break;
10293 }
10294 default:
10295 return -1;
10296 }
10297 break; /* end of ADDUH.QB/MUL.PH */
10298 }
10299 case 0x30: { /* DPAQ.W.PH */
10300 switch(sa) {
10301 case 0x0: { /* DPA.W.PH */
10302 DIP("dpa.w.ph ac%d, r%d, r%d", ac, rs, rt);
10303 vassert(!mode64);
10304
10305 t0 = newTemp(Ity_I64);
10306 t1 = newTemp(Ity_I64);
10307 t2 = newTemp(Ity_I64);
10308
10309 assign(t0,
10310 unop(Iop_32Sto64,
10311 binop(Iop_Mul32,
10312 unop(Iop_16Sto32,
10313 unop(Iop_32HIto16, getIReg(rs))),
10314 unop(Iop_16Sto32,
10315 unop(Iop_32HIto16, getIReg(rt))))));
10316 assign(t1,
10317 unop(Iop_32Sto64,
10318 binop(Iop_Mul32,
10319 unop(Iop_16Sto32,
10320 unop(Iop_32to16, getIReg(rs))),
10321 unop(Iop_16Sto32,
10322 unop(Iop_32to16, getIReg(rt))))));
10323 assign(t2,
10324 binop(Iop_Add64,
10325 getAcc(ac),
10326 binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
10327 putAcc(ac, mkexpr(t2));
10328 break;
10329 }
10330 case 0x1: { /* DPS.W.PH */
10331 DIP("dps.w.ph ac%d, r%d, r%d", ac, rs, rt);
10332 vassert(!mode64);
10333
10334 t0 = newTemp(Ity_I64);
10335 t1 = newTemp(Ity_I64);
10336 t2 = newTemp(Ity_I64);
10337
10338 assign(t0,
10339 unop(Iop_32Sto64,
10340 binop(Iop_Mul32,
10341 unop(Iop_16Sto32,
10342 unop(Iop_32HIto16, getIReg(rs))),
10343 unop(Iop_16Sto32,
10344 unop(Iop_32HIto16, getIReg(rt))))));
10345 assign(t1,
10346 unop(Iop_32Sto64,
10347 binop(Iop_Mul32,
10348 unop(Iop_16Sto32,
10349 unop(Iop_32to16, getIReg(rs))),
10350 unop(Iop_16Sto32,
10351 unop(Iop_32to16, getIReg(rt))))));
10352 assign(t2,
10353 binop(Iop_Sub64,
10354 getAcc(ac),
10355 binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
10356 putAcc(ac, mkexpr(t2));
10357 break;
10358 }
10359 case 0x2: { /* MULSA.W.PH */
10360 DIP("mulsa.w.ph ac%d, r%d, r%d", ac, rs, rt);
10361 vassert(!mode64);
10362 t0 = newTemp(Ity_I32);
10363 t1 = newTemp(Ity_I32);
10364 t2 = newTemp(Ity_I32);
10365 t3 = newTemp(Ity_I1);
10366 t4 = newTemp(Ity_I64);
10367
10368 assign(t4, getAcc(ac));
10369 assign(t0, binop(Iop_Mul32,
10370 unop(Iop_16Sto32,
10371 unop(Iop_32to16, getIReg(rt))),
10372 unop(Iop_16Sto32,
10373 unop(Iop_32to16, getIReg(rs)))));
10374 assign(t1, binop(Iop_Mul32,
10375 unop(Iop_16Sto32,
10376 unop(Iop_32HIto16, getIReg(rt))),
10377 unop(Iop_16Sto32,
10378 unop(Iop_32HIto16, getIReg(rs)))));
10379 assign(t2, binop(Iop_Sub32, mkexpr(t1), mkexpr(t0)));
10380 putAcc(ac, binop(Iop_Add64,
10381 mkexpr(t4),
10382 unop(Iop_32Sto64, mkexpr(t2))));
10383 break;
10384 }
10385 case 0x3: { /* DPAU.H.QBL */
10386 DIP("dpau.h.qbl ac%d, r%d, r%d", ac, rs, rt);
10387 vassert(!mode64);
10388 t0 = newTemp(Ity_I32);
10389 t1 = newTemp(Ity_I32);
10390 t2 = newTemp(Ity_I64);
10391 t3 = newTemp(Ity_I64);
10392
10393 assign(t0,
10394 binop(Iop_Mul32,
10395 unop(Iop_8Uto32,
10396 unop(Iop_16HIto8,
10397 unop(Iop_32HIto16, getIReg(rs)))),
10398 unop(Iop_8Uto32,
10399 unop(Iop_16HIto8,
10400 unop(Iop_32HIto16, getIReg(rt))))));
10401 assign(t1,
10402 binop(Iop_Mul32,
10403 unop(Iop_8Uto32,
10404 unop(Iop_16to8,
10405 unop(Iop_32HIto16, getIReg(rs)))),
10406 unop(Iop_8Uto32,
10407 unop(Iop_16to8,
10408 unop(Iop_32HIto16, getIReg(rt))))));
10409 assign(t2,
10410 unop(Iop_32Uto64,
10411 binop(Iop_Add32,
10412 mkexpr(t0),
10413 mkexpr(t1))));
10414 assign(t3,
10415 binop(Iop_Add64, getAcc(ac), mkexpr(t2)));
10416 putAcc(ac, mkexpr(t3));
10417 break;
10418 }
10419 case 0x4: { /* DPAQ_S.W.PH */
10420 DIP("dpaq_s.w.ph ac%d, r%d, r%d", ac, rs, rt);
10421 vassert(!mode64);
10422 t0 = newTemp(Ity_I64);
10423 t1 = newTemp(Ity_I64);
10424 t2 = newTemp(Ity_I1);
10425 t3 = newTemp(Ity_I1);
10426 t4 = newTemp(Ity_I64);
10427 t5 = newTemp(Ity_I64);
10428 t6 = newTemp(Ity_I1);
10429 t7 = newTemp(Ity_I1);
10430 t8 = newTemp(Ity_I64);
10431 t9 = newTemp(Ity_I64);
10432
10433 assign(t0, getAcc(ac));
10434
10435 assign(t1, binop(Iop_Shl64,
10436 binop(Iop_MullS32,
10437 unop(Iop_16Sto32,
10438 unop(Iop_32HIto16,
10439 getIReg(rs))),
10440 unop(Iop_16Sto32,
10441 unop(Iop_32HIto16,
10442 getIReg(rt)))),
10443 mkU8(0x1)));
10444 assign(t2, binop(Iop_CmpEQ32,
10445 unop(Iop_16Uto32,
10446 unop(Iop_32HIto16, getIReg(rs))),
10447 mkU32(0x00008000)));
10448 assign(t3, binop(Iop_CmpEQ32,
10449 unop(Iop_16Uto32,
10450 unop(Iop_32HIto16, getIReg(rt))),
10451 mkU32(0x00008000)));
10452 assign(t4,
10453 IRExpr_ITE(mkexpr(t2),
10454 IRExpr_ITE(mkexpr(t3),
10455 mkU64(0x000000007fffffffULL),
10456 mkexpr(t1)),
10457 mkexpr(t1)));
10458
10459 putDSPControl(IRExpr_ITE(mkexpr(t2),
10460 IRExpr_ITE(mkexpr(t3),
10461 binop(Iop_Or32,
10462 getDSPControl(),
10463 binop(Iop_Shl32,
10464 mkU32(0x1),
10465 mkU8(ac+16)
10466 )
10467 ),
10468 getDSPControl()),
10469 getDSPControl()));
10470
10471 assign(t5, binop(Iop_Shl64,
10472 binop(Iop_MullS32,
10473 unop(Iop_16Sto32,
10474 unop(Iop_32to16, getIReg(rs))),
10475 unop(Iop_16Sto32,
10476 unop(Iop_32to16, getIReg(rt)))
10477 ),
10478 mkU8(0x1)));
10479 assign(t6, binop(Iop_CmpEQ32,
10480 unop(Iop_16Uto32,
10481 unop(Iop_32to16, getIReg(rs))),
10482 mkU32(0x00008000)));
10483 assign(t7, binop(Iop_CmpEQ32,
10484 unop(Iop_16Uto32,
10485 unop(Iop_32to16, getIReg(rt))),
10486 mkU32(0x00008000)));
10487 assign(t8,
10488 IRExpr_ITE(mkexpr(t6),
10489 IRExpr_ITE(mkexpr(t7),
10490 mkU64(0x000000007fffffffULL),
10491 mkexpr(t5)),
10492 mkexpr(t5)));
10493
10494 putDSPControl(IRExpr_ITE(mkexpr(t6),
10495 IRExpr_ITE(mkexpr(t7),
10496 binop(Iop_Or32,
10497 getDSPControl(),
10498 binop(Iop_Shl32,
10499 mkU32(0x1),
10500 mkU8(ac+16)
10501 )
10502 ),
10503 getDSPControl()),
10504 getDSPControl()));
10505
10506 assign(t9, binop(Iop_Add64,
10507 binop(Iop_Add64, mkexpr(t4), mkexpr(t8)),
10508 mkexpr(t0)));
10509 putAcc(ac, mkexpr(t9));
10510 break;
10511 }
10512 case 0x5: { /* DPSQ_S.W.PH */
10513 DIP("dpsq_s.w.ph ac%d r%d, r%d", ac, rs, rt);
10514 vassert(!mode64);
10515 t0 = newTemp(Ity_I64);
10516 t1 = newTemp(Ity_I64);
10517 t2 = newTemp(Ity_I1);
10518 t3 = newTemp(Ity_I1);
10519 t4 = newTemp(Ity_I64);
10520 t5 = newTemp(Ity_I64);
10521 t6 = newTemp(Ity_I1);
10522 t7 = newTemp(Ity_I1);
10523 t8 = newTemp(Ity_I64);
10524 t9 = newTemp(Ity_I64);
10525
10526 assign(t0, getAcc(ac));
10527
10528 assign(t1, binop(Iop_Shl64,
10529 binop(Iop_MullS32,
10530 unop(Iop_16Sto32,
10531 unop(Iop_32HIto16,
10532 getIReg(rs))),
10533 unop(Iop_16Sto32,
10534 unop(Iop_32HIto16,
10535 getIReg(rt)))),
10536 mkU8(0x1)));
10537 assign(t2, binop(Iop_CmpEQ32,
10538 unop(Iop_16Uto32,
10539 unop(Iop_32HIto16, getIReg(rs))),
10540 mkU32(0x00008000)));
10541 assign(t3, binop(Iop_CmpEQ32,
10542 unop(Iop_16Uto32,
10543 unop(Iop_32HIto16, getIReg(rt))),
10544 mkU32(0x00008000)));
10545 assign(t4,
10546 IRExpr_ITE(mkexpr(t2),
10547 IRExpr_ITE(mkexpr(t3),
10548 mkU64(0x000000007fffffffULL),
10549 mkexpr(t1)),
10550 mkexpr(t1)));
10551
10552 putDSPControl(IRExpr_ITE(mkexpr(t2),
10553 IRExpr_ITE(mkexpr(t3),
10554 binop(Iop_Or32,
10555 getDSPControl(),
10556 binop(Iop_Shl32,
10557 mkU32(0x1),
10558 mkU8(ac+16)
10559 )
10560 ),
10561 getDSPControl()),
10562 getDSPControl()));
10563
10564 assign(t5,
10565 binop(Iop_Shl64,
10566 binop(Iop_MullS32,
10567 unop(Iop_16Sto32,
10568 unop(Iop_32to16, getIReg(rs))),
10569 unop(Iop_16Sto32,
10570 unop(Iop_32to16, getIReg(rt)))),
10571 mkU8(0x1)));
10572 assign(t6, binop(Iop_CmpEQ32,
10573 unop(Iop_16Uto32,
10574 unop(Iop_32to16, getIReg(rs))),
10575 mkU32(0x00008000)));
10576 assign(t7, binop(Iop_CmpEQ32,
10577 unop(Iop_16Uto32,
10578 unop(Iop_32to16, getIReg(rt))),
10579 mkU32(0x00008000)));
10580 assign(t8,
10581 IRExpr_ITE(mkexpr(t6),
10582 IRExpr_ITE(mkexpr(t7),
10583 mkU64(0x000000007fffffffULL),
10584 mkexpr(t5)),
10585 mkexpr(t5)));
10586
10587 putDSPControl(IRExpr_ITE(mkexpr(t6),
10588 IRExpr_ITE(mkexpr(t7),
10589 binop(Iop_Or32,
10590 getDSPControl(),
10591 binop(Iop_Shl32,
10592 mkU32(0x1),
10593 mkU8(ac+16)
10594 )
10595 ),
10596 getDSPControl()),
10597 getDSPControl()));
10598
10599 assign(t9,
10600 binop(Iop_Sub64,
10601 mkexpr(t0),
10602 binop(Iop_Add64, mkexpr(t4), mkexpr(t8))));
10603 putAcc(ac, mkexpr(t9));
10604 break;
10605 }
10606 case 0x6: { /* MULSAQ_S.W.PH */
10607 DIP("mulsaq_s.w.ph ac%d r%d, r%d", ac, rs, rt);
10608 vassert(!mode64);
10609
10610 t0 = newTemp(Ity_I32);
10611 t1 = newTemp(Ity_I32);
10612 t2 = newTemp(Ity_I32);
10613 t3 = newTemp(Ity_I32);
10614 t4 = newTemp(Ity_I32);
10615 t5 = newTemp(Ity_I32);
10616 t6 = newTemp(Ity_I64);
10617 t7 = newTemp(Ity_I64);
10618 t8 = newTemp(Ity_I32);
10619 t9 = newTemp(Ity_I32);
10620
10621 assign(t0, unop(Iop_16Sto32,
10622 unop(Iop_32HIto16, getIReg(rs))));
10623 assign(t1, unop(Iop_16Sto32,
10624 unop(Iop_32HIto16, getIReg(rt))));
10625
10626 assign(t8, binop(Iop_And32,
10627 unop(Iop_1Sto32,
10628 binop(Iop_CmpEQ32,
10629 unop(Iop_16Uto32,
10630 unop(Iop_32HIto16,
10631 getIReg(rs))),
10632 mkU32(0x8000))),
10633 unop(Iop_1Sto32,
10634 binop(Iop_CmpEQ32,
10635 unop(Iop_16Uto32,
10636 unop(Iop_32HIto16,
10637 getIReg(rt))),
10638 mkU32(0x8000)))));
10639 /* DSPControl_outflag:16+acc <- 1 */
10640 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
10641 mkexpr(t8),
10642 mkU32(0x0)),
10643 binop(Iop_Or32,
10644 getDSPControl(),
10645 binop(Iop_Shl32,
10646 mkU32(0x00010000),
10647 mkU8(ac))),
10648 getDSPControl()));
10649
10650 /* tempB_31..0 */
10651 assign(t2,
10652 IRExpr_ITE(binop(Iop_CmpNE32,
10653 mkexpr(t8), mkU32(0x0)),
10654 mkU32(0x7FFFFFFF),
10655 binop(Iop_Shl32,
10656 binop(Iop_Mul32,
10657 mkexpr(t0), mkexpr(t1)),
10658 mkU8(1))));
10659
10660 assign(t3, unop(Iop_16Sto32,
10661 unop(Iop_32to16, getIReg(rs))));
10662 assign(t4, unop(Iop_16Sto32,
10663 unop(Iop_32to16, getIReg(rt))));
10664
10665 assign(t9, binop(Iop_And32,
10666 unop(Iop_1Sto32,
10667 binop(Iop_CmpEQ32,
10668 unop(Iop_16Uto32,
10669 unop(Iop_32to16,
10670 getIReg(rs))),
10671 mkU32(0x8000))),
10672 unop(Iop_1Sto32,
10673 binop(Iop_CmpEQ32,
10674 unop(Iop_16Uto32,
10675 unop(Iop_32to16,
10676 getIReg(rt))),
10677 mkU32(0x8000)))));
10678 /* DSPControl_outflag:16+acc <- 1 */
10679 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
10680 mkexpr(t9),
10681 mkU32(0x0)),
10682 binop(Iop_Or32,
10683 getDSPControl(),
10684 binop(Iop_Shl32,
10685 mkU32(0x00010000),
10686 mkU8(ac))),
10687 getDSPControl()));
10688 /* tempA_31..0 */
10689 assign(t5,
10690 IRExpr_ITE(binop(Iop_CmpNE32,
10691 mkexpr(t9),
10692 mkU32(0x0)),
10693 mkU32(0x7FFFFFFF),
10694 binop(Iop_Shl32,
10695 binop(Iop_Mul32,
10696 mkexpr(t3),
10697 mkexpr(t4)),
10698 mkU8(1))));
10699 /* dotp_63..0 */
10700 assign(t6,
10701 binop(Iop_Sub64,
10702 unop(Iop_32Sto64, mkexpr(t2)),
10703 unop(Iop_32Sto64, mkexpr(t5))));
10704 /* tempC_63..0 */
10705 assign(t7, binop(Iop_Add64, getAcc(ac), mkexpr(t6)));
10706
10707 putAcc(ac, mkexpr(t7));
10708 break;
10709 }
10710 case 0x7: { /* DPAU.H.QBR */
10711 DIP("dpau.h.qbr ac%d, r%d, r%d", ac, rs, rt);
10712 vassert(!mode64);
10713 t0 = newTemp(Ity_I32);
10714 t1 = newTemp(Ity_I32);
10715 t2 = newTemp(Ity_I64);
10716 t3 = newTemp(Ity_I64);
10717
10718 assign(t0,
10719 binop(Iop_Mul32,
10720 unop(Iop_8Uto32,
10721 unop(Iop_16HIto8,
10722 unop(Iop_32to16, getIReg(rs)))),
10723 unop(Iop_8Uto32,
10724 unop(Iop_16HIto8,
10725 unop(Iop_32to16, getIReg(rt))))));
10726 assign(t1,
10727 binop(Iop_Mul32,
10728 unop(Iop_8Uto32,
10729 unop(Iop_16to8,
10730 unop(Iop_32to16, getIReg(rs)))),
10731 unop(Iop_8Uto32,
10732 unop(Iop_16to8,
10733 unop(Iop_32to16, getIReg(rt))))));
10734 assign(t2, unop(Iop_32Uto64,
10735 binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
10736 assign(t3, binop(Iop_Add64, getAcc(ac), mkexpr(t2)));
10737 putAcc(ac, mkexpr(t3));
10738 break;
10739 }
10740 case 0x8: { /* DPAX.W.PH */
10741 DIP("dpax.w.ph ac%d, r%d, r%d", ac, rs, rt);
10742 vassert(!mode64);
10743 t0 = newTemp(Ity_I64);
10744 t1 = newTemp(Ity_I64);
10745 t2 = newTemp(Ity_I64);
10746
10747 assign(t0,
10748 unop(Iop_32Sto64,
10749 binop(Iop_Mul32,
10750 unop(Iop_16Sto32,
10751 unop(Iop_32HIto16, getIReg(rs))),
10752 unop(Iop_16Sto32,
10753 unop(Iop_32to16, getIReg(rt))))));
10754 assign(t1,
10755 unop(Iop_32Sto64,
10756 binop(Iop_Mul32,
10757 unop(Iop_16Sto32,
10758 unop(Iop_32to16, getIReg(rs))),
10759 unop(Iop_16Sto32,
10760 unop(Iop_32HIto16, getIReg(rt))))));
10761 assign(t2,
10762 binop(Iop_Add64,
10763 getAcc(ac),
10764 binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
10765 putAcc(ac, mkexpr(t2));
10766 break;
10767 }
10768 case 0x9: { /* DPSX.W.PH */
10769 DIP("dpsx.w.ph ac%d r%d, r%d", ac, rs, rt);
10770 vassert(!mode64);
10771
10772 t0 = newTemp(Ity_I64);
10773 t1 = newTemp(Ity_I64);
10774 t2 = newTemp(Ity_I64);
10775
10776 assign(t0,
10777 unop(Iop_32Sto64,
10778 binop(Iop_Mul32,
10779 unop(Iop_16Sto32,
10780 unop(Iop_32HIto16, getIReg(rs))),
10781 unop(Iop_16Sto32,
10782 unop(Iop_32to16, getIReg(rt))))));
10783 assign(t1,
10784 unop(Iop_32Sto64,
10785 binop(Iop_Mul32,
10786 unop(Iop_16Sto32,
10787 unop(Iop_32to16, getIReg(rs))),
10788 unop(Iop_16Sto32,
10789 unop(Iop_32HIto16, getIReg(rt))))));
10790 assign(t2,
10791 binop(Iop_Sub64,
10792 getAcc(ac),
10793 binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
10794 putAcc(ac, mkexpr(t2));
10795 break;
10796 }
10797 case 0xB: { /* DPSU.H.QBL */
10798 DIP("dpsu.h.qbl ac%d, r%d, r%d", ac, rs, rt);
10799 vassert(!mode64);
10800
10801 t0 = newTemp(Ity_I32);
10802 t1 = newTemp(Ity_I32);
10803 t2 = newTemp(Ity_I64);
10804 t3 = newTemp(Ity_I64);
10805
10806 assign(t0,
10807 binop(Iop_Mul32,
10808 unop(Iop_8Uto32,
10809 unop(Iop_16HIto8,
10810 unop(Iop_32HIto16, getIReg(rs)))),
10811 unop(Iop_8Uto32,
10812 unop(Iop_16HIto8,
10813 unop(Iop_32HIto16, getIReg(rt))))));
10814 assign(t1,
10815 binop(Iop_Mul32,
10816 unop(Iop_8Uto32,
10817 unop(Iop_16to8,
10818 unop(Iop_32HIto16, getIReg(rs)))),
10819 unop(Iop_8Uto32,
10820 unop(Iop_16to8,
10821 unop(Iop_32HIto16, getIReg(rt))))));
10822 assign(t2,
10823 unop(Iop_32Uto64,
10824 binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
10825 assign(t3,
10826 binop(Iop_Sub64, getAcc(ac), mkexpr(t2)));
10827 putAcc(ac, mkexpr(t3));
10828 break;
10829 }
10830 case 0xC: { /* DPAQ_SA.L.W */
10831 DIP("dpaq_sa.l.w ac%d, r%d, r%d", ac, rs, rt);
10832 vassert(!mode64);
10833 t0 = newTemp(Ity_I64);
10834 t1 = newTemp(Ity_I64);
10835 t2 = newTemp(Ity_I1);
10836 t3 = newTemp(Ity_I1);
10837 t4 = newTemp(Ity_I64);
10838 t5 = newTemp(Ity_I64);
10839 t6 = newTemp(Ity_I64);
10840 t7 = newTemp(Ity_I64);
10841 t8 = newTemp(Ity_I1);
10842 t9 = newTemp(Ity_I1);
10843
10844 assign(t0, getAcc(ac));
10845
10846 assign(t1, binop(Iop_Shl64,
10847 binop(Iop_MullS32,
10848 getIReg(rs), getIReg(rt)),
10849 mkU8(0x1)));
10850
10851 assign(t2, binop(Iop_CmpEQ32,
10852 getIReg(rs),
10853 mkU32(0x80000000)));
10854 assign(t3, binop(Iop_CmpEQ32,
10855 getIReg(rt),
10856 mkU32(0x80000000)));
10857
10858 assign(t4,
10859 IRExpr_ITE(mkexpr(t2),
10860 IRExpr_ITE(mkexpr(t3),
10861 mkU64(0x7fffffffffffffffULL),
10862 mkexpr(t1)),
10863 mkexpr(t1)));
10864
10865 putDSPControl(IRExpr_ITE(mkexpr(t2),
10866 IRExpr_ITE(mkexpr(t3),
10867 binop(Iop_Or32,
10868 getDSPControl(),
10869 binop(Iop_Shl32,
10870 mkU32(0x1),
10871 mkU8(ac+16)
10872 )
10873 ),
10874 getDSPControl()),
10875 getDSPControl()));
10876
10877 assign(t5, binop(Iop_Add64,
10878 unop(Iop_32Uto64,
10879 unop(Iop_64to32, mkexpr(t0))),
10880 unop(Iop_32Uto64,
10881 unop(Iop_64to32, mkexpr(t4)))));
10882 assign(t6,
10883 binop(Iop_Add64,
10884 binop(Iop_Add64,
10885 unop(Iop_32Sto64,
10886 unop(Iop_64HIto32, mkexpr(t0))),
10887 unop(Iop_32Sto64,
10888 unop(Iop_64HIto32, mkexpr(t4)))),
10889 unop(Iop_32Uto64,
10890 binop(Iop_And32,
10891 unop(Iop_64HIto32, mkexpr(t5)),
10892 mkU32(0x1)))));
10893 assign(t7, binop(Iop_32HLto64,
10894 unop(Iop_64to32, mkexpr(t6)),
10895 unop(Iop_64to32, mkexpr(t5))));
10896 assign(t8, binop(Iop_CmpEQ32,
10897 binop(Iop_Shr32,
10898 binop(Iop_And32,
10899 unop(Iop_64to32, mkexpr(t6)),
10900 mkU32(0x80000000)),
10901 mkU8(31)),
10902 binop(Iop_And32,
10903 unop(Iop_64HIto32, mkexpr(t6)),
10904 mkU32(0x00000001))));
10905 assign(t9, binop(Iop_CmpEQ32,
10906 binop(Iop_And32,
10907 unop(Iop_64HIto32,
10908 mkexpr(t6)),
10909 mkU32(0x00000001)),
10910 mkU32(0x1)));
10911 putDSPControl(IRExpr_ITE(mkexpr(t8),
10912 getDSPControl(),
10913 binop(Iop_Or32,
10914 getDSPControl(),
10915 binop(Iop_Shl32,
10916 mkU32(0x1),
10917 mkU8(ac+16)))));
10918 putAcc(ac,
10919 IRExpr_ITE(mkexpr(t8),
10920 mkexpr(t7),
10921 IRExpr_ITE(mkexpr(t9),
10922 mkU64(0x8000000000000000ULL),
10923 mkU64(0x7fffffffffffffffULL)))
10924 );
10925 break;
10926 }
10927 case 0xD: { /* DPSQ_SA.L.W */
10928 DIP("dpsq_sa.l.w ac%d, r%d, r%d", ac, rs, rt);
10929 vassert(!mode64);
10930 t0 = newTemp(Ity_I64);
10931 t1 = newTemp(Ity_I64);
10932 t2 = newTemp(Ity_I1);
10933 t3 = newTemp(Ity_I1);
10934 t4 = newTemp(Ity_I64);
10935 t5 = newTemp(Ity_I64);
10936 t6 = newTemp(Ity_I64);
10937 t7 = newTemp(Ity_I64);
10938 t8 = newTemp(Ity_I1);
10939 t9 = newTemp(Ity_I1);
10940
10941 assign(t0, getAcc(ac));
10942
10943 assign(t1, binop(Iop_Shl64,
10944 binop(Iop_MullS32,
10945 getIReg(rs), getIReg(rt)),
10946 mkU8(0x1)));
10947
10948 assign(t2, binop(Iop_CmpEQ32,
10949 getIReg(rs),
10950 mkU32(0x80000000)));
10951 assign(t3, binop(Iop_CmpEQ32,
10952 getIReg(rt),
10953 mkU32(0x80000000)));
10954
10955 assign(t4,
10956 IRExpr_ITE(mkexpr(t2),
10957 IRExpr_ITE(mkexpr(t3),
10958 mkU64(0x7fffffffffffffffULL),
10959 mkexpr(t1)),
10960 mkexpr(t1)));
10961
10962 putDSPControl(IRExpr_ITE(mkexpr(t2),
10963 IRExpr_ITE(mkexpr(t3),
10964 binop(Iop_Or32,
10965 getDSPControl(),
10966 binop(Iop_Shl32,
10967 mkU32(0x1),
10968 mkU8(ac+16)
10969 )
10970 ),
10971 getDSPControl()),
10972 getDSPControl()));
10973
10974 assign(t5, binop(Iop_Sub64,
10975 unop(Iop_32Uto64,
10976 unop(Iop_64to32, mkexpr(t0))),
10977 unop(Iop_32Uto64,
10978 unop(Iop_64to32, mkexpr(t4)))));
10979 assign(t6, binop(Iop_Sub64,
10980 binop(Iop_Add64,
10981 unop(Iop_32Sto64,
10982 unop(Iop_64HIto32, mkexpr(t0))
10983 ),
10984 unop(Iop_32Sto64,
10985 unop(Iop_1Sto32,
10986 binop(Iop_CmpLT32U,
10987 unop(Iop_64to32,
10988 mkexpr(t0)),
10989 unop(Iop_64to32,
10990 mkexpr(t4)))))),
10991 unop(Iop_32Sto64,
10992 unop(Iop_64HIto32, mkexpr(t4)))));
10993 assign(t7, binop(Iop_32HLto64,
10994 unop(Iop_64to32, mkexpr(t6)),
10995 unop(Iop_64to32, mkexpr(t5))));
10996 assign(t8, binop(Iop_CmpEQ32,
10997 binop(Iop_Shr32,
10998 binop(Iop_And32,
10999 unop(Iop_64to32, mkexpr(t6)),
11000 mkU32(0x80000000)),
11001 mkU8(31)),
11002 binop(Iop_And32,
11003 unop(Iop_64HIto32, mkexpr(t6)),
11004 mkU32(0x00000001))));
11005 assign(t9, binop(Iop_CmpEQ32,
11006 binop(Iop_And32,
11007 unop(Iop_64HIto32, mkexpr(t6)),
11008 mkU32(0x00000001)),
11009 mkU32(0x1)));
11010 putDSPControl(IRExpr_ITE(mkexpr(t8),
11011 getDSPControl(),
11012 binop(Iop_Or32,
11013 getDSPControl(),
11014 binop(Iop_Shl32,
11015 mkU32(0x1),
11016 mkU8(ac+16)))));
11017 putAcc(ac,
11018 IRExpr_ITE(mkexpr(t8),
11019 mkexpr(t7),
11020 IRExpr_ITE(mkexpr(t9),
11021 mkU64(0x8000000000000000ULL),
11022 mkU64(0x7fffffffffffffffULL)))
11023 );
11024 break;
11025 }
11026 case 0xF: { /* DPSU.H.QBR */
11027 DIP("dpsu.h.qbr ac%d r%d, r%d", ac, rs, rt);
11028 vassert(!mode64);
11029
11030 t0 = newTemp(Ity_I32);
11031 t1 = newTemp(Ity_I32);
11032 t2 = newTemp(Ity_I64);
11033 t3 = newTemp(Ity_I64);
11034
11035 assign(t0,
11036 binop(Iop_Mul32,
11037 unop(Iop_8Uto32,
11038 unop(Iop_16HIto8,
11039 unop(Iop_32to16, getIReg(rs)))),
11040 unop(Iop_8Uto32,
11041 unop(Iop_16HIto8,
11042 unop(Iop_32to16, getIReg(rt))))));
11043 assign(t1,
11044 binop(Iop_Mul32,
11045 unop(Iop_8Uto32,
11046 unop(Iop_16to8,
11047 unop(Iop_32to16, getIReg(rs)))),
11048 unop(Iop_8Uto32,
11049 unop(Iop_16to8,
11050 unop(Iop_32to16, getIReg(rt))))));
11051 assign(t2, unop(Iop_32Uto64,
11052 binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
11053 assign(t3, binop(Iop_Sub64, getAcc(ac), mkexpr(t2)));
11054 putAcc(ac, mkexpr(t3));
11055
11056 break;
11057 }
11058 case 0x10: { /* MAQ_SA.W.PHL */
11059 DIP("maq_sa.w.phl ac%d, r%d, r%d", ac, rs, rt);
11060 vassert(!mode64);
11061 t0 = newTemp(Ity_I64);
11062 t1 = newTemp(Ity_I64);
11063 t2 = newTemp(Ity_I1);
11064 t3 = newTemp(Ity_I1);
11065 t4 = newTemp(Ity_I64);
11066 t5 = newTemp(Ity_I64);
11067 t6 = newTemp(Ity_I1);
11068 t7 = newTemp(Ity_I64);
11069
11070 assign(t0, getAcc(ac));
11071 assign(t1, unop(Iop_32Sto64,
11072 binop(Iop_Shl32,
11073 binop(Iop_Mul32,
11074 unop(Iop_16Sto32,
11075 unop(Iop_32HIto16,
11076 getIReg(rs))),
11077 unop(Iop_16Sto32,
11078 unop(Iop_32HIto16,
11079 getIReg(rt)))),
11080 mkU8(0x1))));
11081
11082 /* If both input arguments are equal 0x8000, saturate
11083 intermediate product and write to DSPControl register.
11084 */
11085 assign(t2, binop(Iop_CmpEQ32,
11086 unop(Iop_16Uto32,
11087 unop(Iop_32HIto16, getIReg(rs))),
11088 mkU32(0x00008000)));
11089 assign(t3, binop(Iop_CmpEQ32,
11090 unop(Iop_16Uto32,
11091 unop(Iop_32HIto16, getIReg(rt))),
11092 mkU32(0x00008000)));
11093
11094 assign(t4,
11095 IRExpr_ITE(mkexpr(t2),
11096 IRExpr_ITE(mkexpr(t3),
11097 mkU64(0x000000007fffffffULL),
11098 mkexpr(t1)),
11099 mkexpr(t1)));
11100
11101 putDSPControl(IRExpr_ITE(mkexpr(t2),
11102 IRExpr_ITE(mkexpr(t3),
11103 binop(Iop_Or32,
11104 getDSPControl(),
11105 binop(Iop_Shl32,
11106 mkU32(0x1),
11107 mkU8(ac+16)
11108 )
11109 ),
11110 getDSPControl()),
11111 getDSPControl()));
11112 /* Add intermediate product and value in the
11113 accumulator. */
11114 assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4)));
11115
11116 /* Compare bits 31 and 32 of the value in t5. */
11117 assign(t6, binop(Iop_CmpEQ32,
11118 binop(Iop_Shr32,
11119 binop(Iop_And32,
11120 unop(Iop_64to32, mkexpr(t5)),
11121 mkU32(0x80000000)),
11122 mkU8(31)),
11123 binop(Iop_And32,
11124 unop(Iop_64HIto32, mkexpr(t5)),
11125 mkU32(1))));
11126 putDSPControl(IRExpr_ITE(mkexpr(t6),
11127 getDSPControl(),
11128 binop(Iop_Or32,
11129 getDSPControl(),
11130 binop(Iop_Shl32,
11131 mkU32(0x1),
11132 mkU8(ac+16)))));
11133 assign(t7,
11134 IRExpr_ITE(mkexpr(t6),
11135 mkexpr(t5),
11136 IRExpr_ITE(binop(Iop_CmpEQ32,
11137 binop(Iop_And32,
11138 unop(Iop_64HIto32,
11139 mkexpr(t5)),
11140 mkU32(1)),
11141 mkU32(0x0)),
11142 mkU64(0x000000007fffffffULL),
11143 mkU64(0xffffffff80000000ULL)))
11144 );
11145 putAcc(ac, mkexpr(t7));
11146 break;
11147 }
11148 case 0x12: { /* MAQ_SA.W.PHR */
11149 DIP("maq_sa.w.phr ac%d, r%d, r%d", ac, rs, rt);
11150 vassert(!mode64);
11151 t0 = newTemp(Ity_I64);
11152 t1 = newTemp(Ity_I64);
11153 t2 = newTemp(Ity_I1);
11154 t3 = newTemp(Ity_I1);
11155 t4 = newTemp(Ity_I64);
11156 t5 = newTemp(Ity_I64);
11157 t6 = newTemp(Ity_I1);
11158 t7 = newTemp(Ity_I64);
11159
11160 assign(t0, getAcc(ac));
11161 assign(t1, unop(Iop_32Sto64,
11162 binop(Iop_Shl32,
11163 binop(Iop_Mul32,
11164 unop(Iop_16Sto32,
11165 unop(Iop_32to16,
11166 getIReg(rs))),
11167 unop(Iop_16Sto32,
11168 unop(Iop_32to16,
11169 getIReg(rt)))),
11170 mkU8(0x1))));
11171
11172 /* If both input arguments are equal 0x8000, saturate
11173 intermediate product and write to DSPControl
11174 register. */
11175 assign(t2, binop(Iop_CmpEQ32,
11176 unop(Iop_16Uto32,
11177 unop(Iop_32to16, getIReg(rs))),
11178 mkU32(0x00008000)));
11179 assign(t3, binop(Iop_CmpEQ32,
11180 unop(Iop_16Uto32,
11181 unop(Iop_32to16, getIReg(rt))),
11182 mkU32(0x00008000)));
11183
11184 assign(t4,
11185 IRExpr_ITE(mkexpr(t2),
11186 IRExpr_ITE(mkexpr(t3),
11187 mkU64(0x000000007fffffffULL),
11188 mkexpr(t1)),
11189 mkexpr(t1)));
11190
11191 putDSPControl(IRExpr_ITE(mkexpr(t2),
11192 IRExpr_ITE(mkexpr(t3),
11193 binop(Iop_Or32,
11194 getDSPControl(),
11195 binop(Iop_Shl32,
11196 mkU32(0x1),
11197 mkU8(ac+16)
11198 )
11199 ),
11200 getDSPControl()),
11201 getDSPControl()));
11202 /* Add intermediate product and value in the
11203 accumulator. */
11204 assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4)));
11205
11206 /* Compare bits 31 and 32 of the value in t5. */
11207 assign(t6, binop(Iop_CmpEQ32,
11208 binop(Iop_Shr32,
11209 binop(Iop_And32,
11210 unop(Iop_64to32, mkexpr(t5)),
11211 mkU32(0x80000000)),
11212 mkU8(31)),
11213 binop(Iop_And32,
11214 unop(Iop_64HIto32, mkexpr(t5)),
11215 mkU32(1))));
11216 putDSPControl(IRExpr_ITE(mkexpr(t6),
11217 getDSPControl(),
11218 binop(Iop_Or32,
11219 getDSPControl(),
11220 binop(Iop_Shl32,
11221 mkU32(0x1),
11222 mkU8(ac+16)))));
11223 assign(t7,
11224 IRExpr_ITE(mkexpr(t6),
11225 mkexpr(t5),
11226 IRExpr_ITE(binop(Iop_CmpEQ32,
11227 binop(Iop_And32,
11228 unop(Iop_64HIto32,
11229 mkexpr(t5)),
11230 mkU32(1)),
11231 mkU32(0x0)),
11232 mkU64(0x000000007fffffffULL),
11233 mkU64(0xffffffff80000000ULL)))
11234 );
11235 putAcc(ac, mkexpr(t7));
11236 break;
11237 }
11238 case 0x14: { /* MAQ_S.W.PHL */
11239 DIP("maq_s.w.phl ac%d, r%d, r%d", ac, rs, rt);
11240 vassert(!mode64);
11241 t0 = newTemp(Ity_I32);
11242 t1 = newTemp(Ity_I32);
11243 t2 = newTemp(Ity_I32);
11244 t3 = newTemp(Ity_I1);
11245 t4 = newTemp(Ity_I32);
11246 t5 = newTemp(Ity_I64);
11247
11248 assign(t5, getAcc(ac));
11249
11250 assign(t0, unop(Iop_16Sto32,
11251 unop(Iop_32HIto16, getIReg(rs))));
11252 assign(t1, unop(Iop_16Sto32,
11253 unop(Iop_32HIto16, getIReg(rt))));
11254
11255 assign(t2, binop(Iop_And32,
11256 unop(Iop_1Sto32,
11257 binop(Iop_CmpEQ32,
11258 binop(Iop_And32,
11259 mkexpr(t0),
11260 mkU32(0xffff)),
11261 mkU32(0x8000))),
11262 unop(Iop_1Sto32,
11263 binop(Iop_CmpEQ32,
11264 binop(Iop_And32,
11265 mkexpr(t1),
11266 mkU32(0xffff)),
11267 mkU32(0x8000)))));
11268
11269 assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0)));
11270
11271 putDSPControl(IRExpr_ITE(mkexpr(t3),
11272 getDSPControl(),
11273 binop(Iop_Or32,
11274 getDSPControl(),
11275 binop(Iop_Shl32,
11276 mkU32(0x1),
11277 mkU8(ac+16)))));
11278
11279 assign(t4, unop(Iop_64to32,
11280 binop(Iop_MullS32,
11281 mkexpr(t0), mkexpr(t1))));
11282 putAcc(ac, IRExpr_ITE(mkexpr(t3),
11283 binop(Iop_Add64,
11284 unop(Iop_32Sto64,
11285 binop(Iop_Shl32,
11286 mkexpr(t4),
11287 mkU8(0x1))),
11288 mkexpr(t5)),
11289 binop(Iop_Add64,
11290 mkexpr(t5),
11291 unop(Iop_32Sto64,
11292 mkU32(0x7fffffff)))));
11293 break;
11294 }
11295 case 0x16: { /* MAQ_S.W.PHR */
11296 DIP("maq_s.w.phr ac%d, r%d, r%d", ac, rs, rt);
11297 vassert(!mode64);
11298 t0 = newTemp(Ity_I32);
11299 t1 = newTemp(Ity_I32);
11300 t2 = newTemp(Ity_I32);
11301 t3 = newTemp(Ity_I1);
11302 t4 = newTemp(Ity_I32);
11303 t5 = newTemp(Ity_I64);
11304
11305 assign(t5, getAcc(ac));
11306
11307 assign(t0, unop(Iop_16Sto32,
11308 unop(Iop_32to16, getIReg(rs))));
11309 assign(t1, unop(Iop_16Sto32,
11310 unop(Iop_32to16, getIReg(rt))));
11311
11312 assign(t2, binop(Iop_And32,
11313 unop(Iop_1Sto32,
11314 binop(Iop_CmpEQ32,
11315 binop(Iop_And32,
11316 mkexpr(t0),
11317 mkU32(0xffff)),
11318 mkU32(0x8000))),
11319 unop(Iop_1Sto32,
11320 binop(Iop_CmpEQ32,
11321 binop(Iop_And32,
11322 mkexpr(t1),
11323 mkU32(0xffff)),
11324 mkU32(0x8000)))));
11325
11326 assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0)));
11327
11328 putDSPControl(IRExpr_ITE(mkexpr(t3),
11329 getDSPControl(),
11330 binop(Iop_Or32,
11331 getDSPControl(),
11332 binop(Iop_Shl32,
11333 mkU32(0x1),
11334 mkU8(ac+16)))));
11335
11336 assign(t4, unop(Iop_64to32,
11337 binop(Iop_MullS32,
11338 mkexpr(t0), mkexpr(t1))));
11339 putAcc(ac, IRExpr_ITE(mkexpr(t3),
11340 binop(Iop_Add64,
11341 unop(Iop_32Sto64,
11342 binop(Iop_Shl32,
11343 mkexpr(t4),
11344 mkU8(0x1))),
11345 mkexpr(t5)),
11346 binop(Iop_Add64,
11347 mkexpr(t5),
11348 unop(Iop_32Sto64,
11349 mkU32(0x7fffffff)))));
11350 break;
11351 }
11352 case 0x18: { /* DPAQX_S.W.PH */
11353 DIP("dpaqx_s.w.ph ac%d, r%d, r%d", ac, rs, rt);
11354 vassert(!mode64);
11355 t0 = newTemp(Ity_I64);
11356 t1 = newTemp(Ity_I64);
11357 t2 = newTemp(Ity_I1);
11358 t3 = newTemp(Ity_I1);
11359 t4 = newTemp(Ity_I64);
11360 t5 = newTemp(Ity_I64);
11361 t6 = newTemp(Ity_I1);
11362 t7 = newTemp(Ity_I1);
11363 t8 = newTemp(Ity_I64);
11364 t9 = newTemp(Ity_I64);
11365
11366 assign(t0, getAcc(ac));
11367
11368 assign(t1, binop(Iop_Shl64,
11369 binop(Iop_MullS32,
11370 unop(Iop_16Sto32,
11371 unop(Iop_32HIto16,
11372 getIReg(rs))),
11373 unop(Iop_16Sto32,
11374 unop(Iop_32to16,
11375 getIReg(rt)))),
11376 mkU8(0x1)));
11377 assign(t2, binop(Iop_CmpEQ32,
11378 unop(Iop_16Uto32,
11379 unop(Iop_32HIto16, getIReg(rs))),
11380 mkU32(0x00008000)));
11381 assign(t3, binop(Iop_CmpEQ32,
11382 unop(Iop_16Uto32,
11383 unop(Iop_32to16, getIReg(rt))),
11384 mkU32(0x00008000)));
11385 assign(t4,
11386 IRExpr_ITE(mkexpr(t2),
11387 IRExpr_ITE(mkexpr(t3),
11388 mkU64(0x000000007fffffffULL),
11389 mkexpr(t1)),
11390 mkexpr(t1)));
11391
11392 putDSPControl(IRExpr_ITE(mkexpr(t2),
11393 IRExpr_ITE(mkexpr(t3),
11394 binop(Iop_Or32,
11395 getDSPControl(),
11396 binop(Iop_Shl32,
11397 mkU32(0x1),
11398 mkU8(ac+16))),
11399 getDSPControl()),
11400 getDSPControl()));
11401
11402 assign(t5, binop(Iop_Shl64,
11403 binop(Iop_MullS32,
11404 unop(Iop_16Sto32,
11405 unop(Iop_32to16,
11406 getIReg(rs))),
11407 unop(Iop_16Sto32,
11408 unop(Iop_32HIto16,
11409 getIReg(rt)))),
11410 mkU8(0x1)));
11411 assign(t6, binop(Iop_CmpEQ32,
11412 unop(Iop_16Uto32,
11413 unop(Iop_32to16, getIReg(rs))),
11414 mkU32(0x00008000)));
11415 assign(t7, binop(Iop_CmpEQ32,
11416 unop(Iop_16Uto32,
11417 unop(Iop_32HIto16, getIReg(rt))),
11418 mkU32(0x00008000)));
11419 assign(t8,
11420 IRExpr_ITE(mkexpr(t6),
11421 IRExpr_ITE(mkexpr(t7),
11422 mkU64(0x000000007fffffffULL),
11423 mkexpr(t5)),
11424 mkexpr(t5)));
11425
11426 putDSPControl(IRExpr_ITE(mkexpr(t6),
11427 IRExpr_ITE(mkexpr(t7),
11428 binop(Iop_Or32,
11429 getDSPControl(),
11430 binop(Iop_Shl32,
11431 mkU32(0x1),
11432 mkU8(ac+16)
11433 )
11434 ),
11435 getDSPControl()),
11436 getDSPControl()));
11437
11438 assign(t9, binop(Iop_Add64,
11439 binop(Iop_Add64, mkexpr(t4), mkexpr(t8)),
11440 mkexpr(t0)));
11441 putAcc(ac, mkexpr(t9));
11442 break;
11443 }
11444 case 0x19: { /* DPSQX_S.W.PH */
11445 DIP("dpsqx_s.w.ph ac%d, r%d, r%d", ac, rs, rt);
11446 vassert(!mode64);
11447 t0 = newTemp(Ity_I64);
11448 t1 = newTemp(Ity_I64);
11449 t2 = newTemp(Ity_I1);
11450 t3 = newTemp(Ity_I1);
11451 t4 = newTemp(Ity_I64);
11452 t5 = newTemp(Ity_I64);
11453 t6 = newTemp(Ity_I1);
11454 t7 = newTemp(Ity_I1);
11455 t8 = newTemp(Ity_I64);
11456 t9 = newTemp(Ity_I64);
11457
11458 assign(t0, getAcc(ac));
11459
11460 assign(t1, binop(Iop_Shl64,
11461 binop(Iop_MullS32,
11462 unop(Iop_16Sto32,
11463 unop(Iop_32HIto16,
11464 getIReg(rs))),
11465 unop(Iop_16Sto32,
11466 unop(Iop_32to16,
11467 getIReg(rt)))),
11468 mkU8(0x1)));
11469 assign(t2, binop(Iop_CmpEQ32,
11470 unop(Iop_16Uto32,
11471 unop(Iop_32HIto16, getIReg(rs))),
11472 mkU32(0x00008000)));
11473 assign(t3, binop(Iop_CmpEQ32,
11474 unop(Iop_16Uto32,
11475 unop(Iop_32to16, getIReg(rt))),
11476 mkU32(0x00008000)));
11477 assign(t4,
11478 IRExpr_ITE(mkexpr(t2),
11479 IRExpr_ITE(mkexpr(t3),
11480 mkU64(0x000000007fffffffULL),
11481 mkexpr(t1)),
11482 mkexpr(t1)));
11483
11484 putDSPControl(IRExpr_ITE(mkexpr(t2),
11485 IRExpr_ITE(mkexpr(t3),
11486 binop(Iop_Or32,
11487 getDSPControl(),
11488 binop(Iop_Shl32,
11489 mkU32(0x1),
11490 mkU8(ac+16)
11491 )
11492 ),
11493 getDSPControl()),
11494 getDSPControl()));
11495
11496 assign(t5, binop(Iop_Shl64,
11497 binop(Iop_MullS32,
11498 unop(Iop_16Sto32,
11499 unop(Iop_32to16,
11500 getIReg(rs))),
11501 unop(Iop_16Sto32,
11502 unop(Iop_32HIto16,
11503 getIReg(rt)))),
11504 mkU8(0x1)));
11505 assign(t6, binop(Iop_CmpEQ32,
11506 unop(Iop_16Uto32,
11507 unop(Iop_32to16, getIReg(rs))),
11508 mkU32(0x00008000)));
11509 assign(t7, binop(Iop_CmpEQ32,
11510 unop(Iop_16Uto32,
11511 unop(Iop_32HIto16, getIReg(rt))),
11512 mkU32(0x00008000)));
11513 assign(t8,
11514 IRExpr_ITE(mkexpr(t6),
11515 IRExpr_ITE(mkexpr(t7),
11516 mkU64(0x000000007fffffffULL),
11517 mkexpr(t5)),
11518 mkexpr(t5)));
11519
11520 putDSPControl(IRExpr_ITE(mkexpr(t6),
11521 IRExpr_ITE(mkexpr(t7),
11522 binop(Iop_Or32,
11523 getDSPControl(),
11524 binop(Iop_Shl32,
11525 mkU32(0x1),
11526 mkU8(ac+16)
11527 )
11528 ),
11529 getDSPControl()),
11530 getDSPControl()));
11531
11532 assign(t9, binop(Iop_Sub64,
11533 mkexpr(t0),
11534 binop(Iop_Add64, mkexpr(t4), mkexpr(t8))));
11535 putAcc(ac, mkexpr(t9));
11536 break;
11537 }
11538 case 0x1A: { /* DPAQX_SA.W.PH */
11539 DIP("dpaqx_sa.w.ph ac%d, r%d, r%d", ac, rs, rt);
11540 vassert(!mode64);
11541 t0 = newTemp(Ity_I64);
11542 t1 = newTemp(Ity_I64);
11543 t2 = newTemp(Ity_I1);
11544 t3 = newTemp(Ity_I1);
11545 t4 = newTemp(Ity_I64);
11546 t5 = newTemp(Ity_I64);
11547 t6 = newTemp(Ity_I1);
11548 t7 = newTemp(Ity_I1);
11549 t8 = newTemp(Ity_I64);
11550 t9 = newTemp(Ity_I64);
11551 t10 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +000011552
11553 assign(t0, getAcc(ac));
dejanj781f1bd2013-10-23 14:05:15 +000011554 /* Calculate the first cross dot product and saturate if
dejanjc3fee0d2013-07-25 09:08:03 +000011555 needed. */
11556 assign(t1, unop(Iop_32Sto64,
11557 binop(Iop_Shl32,
11558 binop(Iop_Mul32,
11559 unop(Iop_16Sto32,
11560 unop(Iop_32HIto16,
11561 getIReg(rs))),
11562 unop(Iop_16Sto32,
11563 unop(Iop_32to16,
11564 getIReg(rt)))),
11565 mkU8(0x1))));
11566
11567 /* If both input arguments are equal 0x8000, saturate
11568 intermediate product and write to DSPControl
11569 register. */
11570 assign(t2, binop(Iop_CmpEQ32,
11571 unop(Iop_16Uto32,
11572 unop(Iop_32HIto16, getIReg(rs))),
11573 mkU32(0x00008000)));
11574 assign(t3, binop(Iop_CmpEQ32,
11575 unop(Iop_16Uto32,
11576 unop(Iop_32to16, getIReg(rt))),
11577 mkU32(0x00008000)));
11578
dejanj781f1bd2013-10-23 14:05:15 +000011579 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
11580 binop(Iop_And32,
11581 unop(Iop_1Sto32,
11582 mkexpr(t2)),
11583 unop(Iop_1Sto32,
11584 mkexpr(t3))),
11585 mkU32(0)),
11586 mkU64(0x000000007fffffffULL),
11587 mkexpr(t1)));
dejanjc3fee0d2013-07-25 09:08:03 +000011588
dejanj781f1bd2013-10-23 14:05:15 +000011589 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
11590 binop(Iop_And32,
11591 unop(Iop_1Sto32,
11592 mkexpr(t2)),
11593 unop(Iop_1Sto32,
11594 mkexpr(t3))),
11595 mkU32(0)),
11596 binop(Iop_Or32,
11597 getDSPControl(),
11598 binop(Iop_Shl32,
11599 mkU32(0x1),
11600 mkU8(ac+16))),
dejanjc3fee0d2013-07-25 09:08:03 +000011601 getDSPControl()));
11602 /* Calculate second cross dot product and saturate if
11603 needed. */
11604 assign(t5, unop(Iop_32Sto64,
11605 binop(Iop_Shl32,
11606 binop(Iop_Mul32,
11607 unop(Iop_16Sto32,
11608 unop(Iop_32to16,
11609 getIReg(rs))),
11610 unop(Iop_16Sto32,
11611 unop(Iop_32HIto16,
11612 getIReg(rt)))),
11613 mkU8(0x1))));
11614
11615 /* If both input arguments are equal 0x8000, saturate
11616 intermediate product and write to DSPControl
11617 register. */
11618 assign(t6, binop(Iop_CmpEQ32,
11619 unop(Iop_16Uto32,
11620 unop(Iop_32to16, getIReg(rs))),
11621 mkU32(0x00008000)));
11622 assign(t7, binop(Iop_CmpEQ32,
11623 unop(Iop_16Uto32,
11624 unop(Iop_32HIto16, getIReg(rt))),
11625 mkU32(0x00008000)));
11626
dejanj781f1bd2013-10-23 14:05:15 +000011627 assign(t8, IRExpr_ITE(binop(Iop_CmpNE32,
11628 binop(Iop_And32,
11629 unop(Iop_1Sto32,
11630 mkexpr(t6)),
11631 unop(Iop_1Sto32,
11632 mkexpr(t7))),
11633 mkU32(0)),
11634 mkU64(0x000000007fffffffULL),
11635 mkexpr(t5)));
dejanjc3fee0d2013-07-25 09:08:03 +000011636
dejanj781f1bd2013-10-23 14:05:15 +000011637 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
11638 binop(Iop_And32,
11639 unop(Iop_1Sto32,
11640 mkexpr(t6)),
11641 unop(Iop_1Sto32,
11642 mkexpr(t7))),
11643 mkU32(0)),
11644 binop(Iop_Or32,
11645 getDSPControl(),
11646 binop(Iop_Shl32,
11647 mkU32(0x1),
11648 mkU8(ac+16))),
dejanjc3fee0d2013-07-25 09:08:03 +000011649 getDSPControl()));
dejanj781f1bd2013-10-23 14:05:15 +000011650 /* Subtract intermediate products from value in the
dejanjc3fee0d2013-07-25 09:08:03 +000011651 accumulator. */
dejanj781f1bd2013-10-23 14:05:15 +000011652 assign(t9,
11653 binop(Iop_Add64,
11654 mkexpr(t0),
11655 binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));
dejanjc3fee0d2013-07-25 09:08:03 +000011656
11657 putAcc(ac,
11658 IRExpr_ITE(binop(Iop_CmpEQ32,
11659 binop(Iop_And32,
11660 unop(Iop_64HIto32,
11661 mkexpr(t9)),
11662 mkU32(0x80000000)),
11663 mkU32(0x0)),
11664 IRExpr_ITE(binop(Iop_CmpNE32,
11665 unop(Iop_64HIto32,
11666 binop(Iop_Shl64,
11667 mkexpr(t9),
11668 mkU8(1))),
11669 mkU32(0x0)),
11670 mkU64(0x000000007fffffffULL),
11671 mkexpr(t9)),
11672 IRExpr_ITE(binop(Iop_CmpNE32,
11673 unop(Iop_64HIto32,
11674 binop(Iop_Shl64,
11675 mkexpr(t9),
11676 mkU8(1))),
11677 mkU32(0xffffffff)),
11678 mkU64(0xffffffff80000000ULL),
11679 mkexpr(t9))));
dejanj781f1bd2013-10-23 14:05:15 +000011680 assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32,
11681 unop(Iop_64to32,
11682 mkexpr(t9)),
11683 unop(Iop_64to32,
11684 getAcc(ac))),
11685 getDSPControl(),
11686 binop(Iop_Or32,
11687 getDSPControl(),
11688 binop(Iop_Shl32,
11689 mkU32(0x1),
11690 mkU8(ac+16)))));
dejanjc3fee0d2013-07-25 09:08:03 +000011691 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
dejanj781f1bd2013-10-23 14:05:15 +000011692 unop(Iop_64HIto32,
11693 mkexpr(t9)),
11694 unop(Iop_64HIto32,
11695 getAcc(ac))),
dejanjc3fee0d2013-07-25 09:08:03 +000011696 mkexpr(t10),
dejanj781f1bd2013-10-23 14:05:15 +000011697 binop(Iop_Or32,
11698 getDSPControl(),
11699 binop(Iop_Shl32,
11700 mkU32(0x1),
11701 mkU8(ac+16)))));
dejanjc3fee0d2013-07-25 09:08:03 +000011702 break;
11703 }
11704 case 0x1B: { /* DPSQX_SA.W.PH */
11705 DIP("dpsqx_sa.w.ph ac%d, r%d, r%d", ac, rs, rt);
11706 vassert(!mode64);
11707 t0 = newTemp(Ity_I64);
11708 t1 = newTemp(Ity_I64);
11709 t2 = newTemp(Ity_I1);
11710 t3 = newTemp(Ity_I1);
11711 t4 = newTemp(Ity_I64);
11712 t5 = newTemp(Ity_I64);
11713 t6 = newTemp(Ity_I1);
11714 t7 = newTemp(Ity_I1);
11715 t8 = newTemp(Ity_I64);
11716 t9 = newTemp(Ity_I64);
11717 t10 = newTemp(Ity_I32);
dejanjc3fee0d2013-07-25 09:08:03 +000011718
11719 assign(t0, getAcc(ac));
dejanj781f1bd2013-10-23 14:05:15 +000011720 /* Calculate the first cross dot product and saturate if
dejanjc3fee0d2013-07-25 09:08:03 +000011721 needed. */
11722 assign(t1, unop(Iop_32Sto64,
11723 binop(Iop_Shl32,
11724 binop(Iop_Mul32,
11725 unop(Iop_16Sto32,
11726 unop(Iop_32HIto16,
11727 getIReg(rs))),
11728 unop(Iop_16Sto32,
11729 unop(Iop_32to16,
11730 getIReg(rt)))),
11731 mkU8(0x1))));
11732
11733 /* If both input arguments are equal 0x8000, saturate
11734 intermediate product and write to DSPControl
11735 register. */
11736 assign(t2, binop(Iop_CmpEQ32,
11737 unop(Iop_16Uto32,
11738 unop(Iop_32HIto16, getIReg(rs))),
11739 mkU32(0x00008000)));
11740 assign(t3, binop(Iop_CmpEQ32,
11741 unop(Iop_16Uto32,
11742 unop(Iop_32to16, getIReg(rt))),
11743 mkU32(0x00008000)));
11744
dejanj781f1bd2013-10-23 14:05:15 +000011745 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
11746 binop(Iop_And32,
11747 unop(Iop_1Sto32,
11748 mkexpr(t2)),
11749 unop(Iop_1Sto32,
11750 mkexpr(t3))),
11751 mkU32(0)),
11752 mkU64(0x000000007fffffffULL),
11753 mkexpr(t1)));
dejanjc3fee0d2013-07-25 09:08:03 +000011754
dejanj781f1bd2013-10-23 14:05:15 +000011755 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
11756 binop(Iop_And32,
11757 unop(Iop_1Sto32,
11758 mkexpr(t2)),
11759 unop(Iop_1Sto32,
11760 mkexpr(t3))),
11761 mkU32(0)),
11762 binop(Iop_Or32,
11763 getDSPControl(),
11764 binop(Iop_Shl32,
11765 mkU32(0x1),
11766 mkU8(ac+16))),
dejanjc3fee0d2013-07-25 09:08:03 +000011767 getDSPControl()));
11768 /* Calculate second cross dot product and saturate if
11769 needed. */
11770 assign(t5, unop(Iop_32Sto64,
11771 binop(Iop_Shl32,
11772 binop(Iop_Mul32,
11773 unop(Iop_16Sto32,
11774 unop(Iop_32to16,
11775 getIReg(rs))),
11776 unop(Iop_16Sto32,
11777 unop(Iop_32HIto16,
11778 getIReg(rt)))),
11779 mkU8(0x1))));
11780
11781 /* If both input arguments are equal 0x8000, saturate
11782 intermediate product and write to DSPControl
11783 register. */
11784 assign(t6, binop(Iop_CmpEQ32,
dejanj781f1bd2013-10-23 14:05:15 +000011785 unop(Iop_16Uto32,
11786 unop(Iop_32to16, getIReg(rs))),
dejanjc3fee0d2013-07-25 09:08:03 +000011787 mkU32(0x00008000)));
11788 assign(t7, binop(Iop_CmpEQ32,
dejanj781f1bd2013-10-23 14:05:15 +000011789 unop(Iop_16Uto32,
11790 unop(Iop_32HIto16, getIReg(rt))),
11791 mkU32(0x00008000)));
dejanjc3fee0d2013-07-25 09:08:03 +000011792
dejanj781f1bd2013-10-23 14:05:15 +000011793 assign(t8, IRExpr_ITE(binop(Iop_CmpNE32,
11794 binop(Iop_And32,
11795 unop(Iop_1Sto32,
11796 mkexpr(t6)),
11797 unop(Iop_1Sto32,
11798 mkexpr(t7))),
11799 mkU32(0)),
11800 mkU64(0x000000007fffffffULL),
11801 mkexpr(t5)));
dejanjc3fee0d2013-07-25 09:08:03 +000011802
dejanj781f1bd2013-10-23 14:05:15 +000011803 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
11804 binop(Iop_And32,
11805 unop(Iop_1Sto32,
11806 mkexpr(t6)),
11807 unop(Iop_1Sto32,
11808 mkexpr(t7))),
11809 mkU32(0)),
11810 binop(Iop_Or32,
11811 getDSPControl(),
11812 binop(Iop_Shl32,
11813 mkU32(0x1),
11814 mkU8(ac+16))),
dejanjc3fee0d2013-07-25 09:08:03 +000011815 getDSPControl()));
11816 /* Subtract intermediate products from value in the
11817 accumulator. */
11818 assign(t9,
11819 binop(Iop_Sub64,
11820 mkexpr(t0),
11821 binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));
11822
11823 putAcc(ac,
11824 IRExpr_ITE(binop(Iop_CmpEQ32,
11825 binop(Iop_And32,
11826 unop(Iop_64HIto32,
11827 mkexpr(t9)),
11828 mkU32(0x80000000)),
11829 mkU32(0x0)),
11830 IRExpr_ITE(binop(Iop_CmpNE32,
11831 unop(Iop_64HIto32,
11832 binop(Iop_Shl64,
11833 mkexpr(t9),
11834 mkU8(1))),
11835 mkU32(0x0)),
11836 mkU64(0x000000007fffffffULL),
11837 mkexpr(t9)),
11838 IRExpr_ITE(binop(Iop_CmpNE32,
11839 unop(Iop_64HIto32,
11840 binop(Iop_Shl64,
11841 mkexpr(t9),
11842 mkU8(1))),
11843 mkU32(0xffffffff)),
11844 mkU64(0xffffffff80000000ULL),
11845 mkexpr(t9))));
dejanj781f1bd2013-10-23 14:05:15 +000011846 assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32,
11847 unop(Iop_64to32,
11848 mkexpr(t9)),
11849 unop(Iop_64to32,
11850 getAcc(ac))),
11851 getDSPControl(),
11852 binop(Iop_Or32,
11853 getDSPControl(),
11854 binop(Iop_Shl32,
11855 mkU32(0x1),
11856 mkU8(ac+16)))));
dejanjc3fee0d2013-07-25 09:08:03 +000011857 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
dejanj781f1bd2013-10-23 14:05:15 +000011858 unop(Iop_64HIto32,
11859 mkexpr(t9)),
11860 unop(Iop_64HIto32,
11861 getAcc(ac))),
dejanjc3fee0d2013-07-25 09:08:03 +000011862 mkexpr(t10),
dejanj781f1bd2013-10-23 14:05:15 +000011863 binop(Iop_Or32,
11864 getDSPControl(),
11865 binop(Iop_Shl32,
11866 mkU32(0x1),
11867 mkU8(ac+16)))));
dejanjc3fee0d2013-07-25 09:08:03 +000011868 break;
11869 }
11870 default:
11871 return -1;
11872 }
11873 break; /* end of DPAQ.W.PH */
11874 }
11875 case 0x31: { /* APPEND */
11876 switch(sa) {
11877 case 0x0: { /* APPEND */
11878 DIP("append r%d, r%d, %d", rt, rs, rd);
11879 vassert(!mode64);
11880 t1 = newTemp(Ity_I32);
11881 t2 = newTemp(Ity_I32);
11882 t3 = newTemp(Ity_I32);
11883
11884 assign(t1, binop(Iop_Shl32, getIReg(rt), mkU8(rd)));
11885
11886 if (31 == rd) {
11887 putIReg(rt, binop(Iop_Or32,
11888 mkexpr(t1),
11889 binop(Iop_And32,
11890 getIReg(rs),
11891 mkU32(0x7fffffff))));
11892 } else if (1 == rd) {
11893 putIReg(rt,
11894 binop(Iop_Or32,
11895 mkexpr(t1),
11896 binop(Iop_And32,
11897 getIReg(rs), mkU32(0x1))));
11898 } else {
11899 assign(t2,
11900 unop(Iop_Not32,
11901 binop(Iop_Shl32,
11902 mkU32(0xffffffff), mkU8(rd))));
11903
11904 putIReg(rt, binop(Iop_Or32,
11905 mkexpr(t1),
11906 binop(Iop_And32,
11907 getIReg(rs), mkexpr(t2))));
11908 }
11909 break;
11910 }
11911 case 0x1: { /* PREPEND */
11912 DIP("prepend r%d, r%d, %d", rt, rs, rd);
11913 vassert(!mode64);
11914 t1 = newTemp(Ity_I32);
11915 t2 = newTemp(Ity_I32);
11916 t3 = newTemp(Ity_I32);
11917
11918 if (0 != rd) {
11919 assign(t1, binop(Iop_Shr32, getIReg(rt), mkU8(rd)));
11920
11921 if (31 == rd) {
11922 putIReg(rt, binop(Iop_Or32,
11923 mkexpr(t1),
11924 binop(Iop_Shl32,
11925 binop(Iop_And32,
11926 getIReg(rs),
11927 mkU32(0x7fffffff)),
11928 mkU8(1))));
11929 } else if (1 == rd) {
11930 putIReg(rt, binop(Iop_Or32,
11931 mkexpr(t1),
11932 binop(Iop_Shl32,
11933 binop(Iop_And32,
11934 getIReg(rs),
11935 mkU32(0x1)),
11936 mkU8(31))));
11937 } else {
11938 assign(t2, binop(Iop_Add32, mkU32(rd), mkU32(0x1)));
11939
11940 assign(t3, unop(Iop_Not32,
11941 binop(Iop_Shl32,
11942 mkU32(0xffffffff),
11943 unop(Iop_32to8, mkexpr(t2)))));
11944
11945 putIReg(rt, binop(Iop_Or32,
11946 mkexpr(t1),
11947 binop(Iop_Shl32,
11948 binop(Iop_And32,
11949 getIReg(rs),
11950 mkexpr(t3)),
11951 mkU8(32-rd))));
11952 }
11953 }
11954 break;
11955 }
11956 case 0x10: { /* BALIGN */
11957 DIP("balign r%d, r%d, %d", rt, rs, rd);
11958 vassert(!mode64);
11959 t1 = newTemp(Ity_I32);
11960 t2 = newTemp(Ity_I32);
11961 t3 = newTemp(Ity_I32);
11962
11963 if ((2 != rd) && (0 != rd)) {
11964 assign(t1, binop(Iop_Shl32,
11965 binop(Iop_And32,
11966 mkU32(rd), mkU32(0x3)),
11967 mkU8(0x3)));
11968 assign(t2, binop(Iop_Shl32,
11969 getIReg(rt),
11970 unop(Iop_32to8, mkexpr(t1))));
11971 assign(t3, binop(Iop_Shr32,
11972 getIReg(rs),
11973 unop(Iop_32to8,
11974 binop(Iop_Shl32,
11975 binop(Iop_Sub32,
11976 mkU32(0x4),
11977 binop(Iop_And32,
11978 mkU32(rd),
11979 mkU32(0x3))),
11980 mkU8(0x3)))));
11981 putIReg(rt, binop(Iop_Or32, mkexpr(t2), mkexpr(t3)));
11982 }
11983 break;
11984 }
11985 default:
11986 return -1;
11987 }
11988 break; /* end of APPEND */
11989 }
11990 default:
11991 return -1;
11992 }
11993 break;
11994 }
11995 default:
11996 return -1;
11997 }
11998 return 0;
11999}
12000
12001/*------------------------------------------------------------*/
petarj0c30de82013-04-19 12:35:00 +000012002/*--- Disassemble a single instruction ---*/
sewardj362cf842012-06-07 08:59:53 +000012003/*------------------------------------------------------------*/
12004
petarjb92a9542013-02-27 22:57:17 +000012005/* Disassemble a single instruction into IR. The instruction is
sewardj362cf842012-06-07 08:59:53 +000012006 located in host memory at guest_instr, and has guest IP of
12007 guest_PC_curr_instr, which will have been set before the call
12008 here. */
12009
12010static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
12011 Addr64),
12012 Bool resteerCisOk,
12013 void* callback_opaque,
12014 Long delta64,
12015 VexArchInfo* archinfo,
sewardj442e51a2012-12-06 18:08:04 +000012016 VexAbiInfo* abiinfo,
12017 Bool sigill_diag )
sewardj362cf842012-06-07 08:59:53 +000012018{
petarjccd78cd2013-05-31 15:09:56 +000012019 IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7;
dejanjc3fee0d2013-07-25 09:08:03 +000012020
sewardj362cf842012-06-07 08:59:53 +000012021 UInt opcode, cins, rs, rt, rd, sa, ft, fs, fd, fmt, tf, nd, function,
12022 trap_code, imm, instr_index, p, msb, lsb, size, rot, sel;
dejanjc3fee0d2013-07-25 09:08:03 +000012023 /* Additional variables for instruction fields in DSP ASE insructions */
12024 UInt ac;
sewardj362cf842012-06-07 08:59:53 +000012025
12026 DisResult dres;
12027
12028 static IRExpr *lastn = NULL; /* last jump addr */
12029 static IRStmt *bstmt = NULL; /* branch (Exit) stmt */
12030
12031 /* The running delta */
12032 Int delta = (Int) delta64;
12033
12034 /* Holds eip at the start of the insn, so that we can print
12035 consistent error messages for unimplemented insns. */
12036 Int delta_start = delta;
12037
12038 /* Are we in a delay slot ? */
12039 Bool delay_slot_branch, likely_delay_slot, delay_slot_jump;
12040
12041 /* Set result defaults. */
12042 dres.whatNext = Dis_Continue;
12043 dres.len = 0;
12044 dres.continueAt = 0;
12045 dres.jk_StopHere = Ijk_INVALID;
12046
12047 delay_slot_branch = likely_delay_slot = delay_slot_jump = False;
12048
florian8462d112014-09-24 15:18:09 +000012049 const UChar *code = guest_code + delta;
sewardj362cf842012-06-07 08:59:53 +000012050 cins = getUInt(code);
petarj1fb1e342013-04-27 02:18:11 +000012051 DIP("\t0x%lx:\t0x%08x\t", (long)guest_PC_curr_instr, cins);
sewardj362cf842012-06-07 08:59:53 +000012052
12053 if (delta != 0) {
12054 if (branch_or_jump(guest_code + delta - 4)) {
12055 if (lastn == NULL && bstmt == NULL) {
petarj1fb1e342013-04-27 02:18:11 +000012056 vassert(0);
sewardj362cf842012-06-07 08:59:53 +000012057 } else {
12058 dres.whatNext = Dis_StopHere;
sewardj362cf842012-06-07 08:59:53 +000012059 if (lastn != NULL) {
sewardj362cf842012-06-07 08:59:53 +000012060 delay_slot_jump = True;
12061 } else if (bstmt != NULL) {
sewardj362cf842012-06-07 08:59:53 +000012062 delay_slot_branch = True;
12063 }
sewardj362cf842012-06-07 08:59:53 +000012064 }
12065 }
12066
12067 if (branch_or_link_likely(guest_code + delta - 4)) {
12068 likely_delay_slot = True;
12069 }
12070 }
12071
12072 /* Spot "Special" instructions (see comment at top of file). */
12073 {
dejanjc3fee0d2013-07-25 09:08:03 +000012074 /* Spot the 16-byte preamble:
sewardj362cf842012-06-07 08:59:53 +000012075 ****mips32****
12076 "srl $0, $0, 13
12077 "srl $0, $0, 29
12078 "srl $0, $0, 3
petarjb92a9542013-02-27 22:57:17 +000012079 "srl $0, $0, 19
12080
12081 ****mips64****
12082 dsll $0, $0, 3
12083 dsll $0, $0, 13
12084 dsll $0, $0, 29
12085 dsll $0, $0, 19 */
12086
12087 UInt word1 = mode64 ? 0xF8 : 0x342;
12088 UInt word2 = mode64 ? 0x378 : 0x742;
12089 UInt word3 = mode64 ? 0x778 : 0xC2;
12090 UInt word4 = mode64 ? 0x4F8 : 0x4C2;
sewardj362cf842012-06-07 08:59:53 +000012091 if (getUInt(code + 0) == word1 && getUInt(code + 4) == word2 &&
12092 getUInt(code + 8) == word3 && getUInt(code + 12) == word4) {
petarjb92a9542013-02-27 22:57:17 +000012093 /* Got a "Special" instruction preamble. Which one is it? */
12094 if (getUInt(code + 16) == 0x01ad6825 /* or $13, $13, $13 */ ) {
12095 /* $11 = client_request ( $12 ) */
petarj1fb1e342013-04-27 02:18:11 +000012096 DIP("$11 = client_request ( $12 )");
petarjb92a9542013-02-27 22:57:17 +000012097 if (mode64)
12098 putPC(mkU64(guest_PC_curr_instr + 20));
12099 else
12100 putPC(mkU32(guest_PC_curr_instr + 20));
sewardj362cf842012-06-07 08:59:53 +000012101 dres.jk_StopHere = Ijk_ClientReq;
12102 dres.whatNext = Dis_StopHere;
12103
12104 goto decode_success;
petarjb92a9542013-02-27 22:57:17 +000012105 } else if (getUInt(code + 16) == 0x01ce7025 /* or $14, $14, $14 */ ) {
12106 /* $11 = guest_NRADDR */
petarj1fb1e342013-04-27 02:18:11 +000012107 DIP("$11 = guest_NRADDR");
sewardj362cf842012-06-07 08:59:53 +000012108 dres.len = 20;
12109 delta += 20;
petarjb92a9542013-02-27 22:57:17 +000012110 if (mode64)
12111 putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS64State,
12112 guest_NRADDR), Ity_I64));
12113 else
12114 putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State,
12115 guest_NRADDR), Ity_I32));
sewardj362cf842012-06-07 08:59:53 +000012116 goto decode_success;
petarjb92a9542013-02-27 22:57:17 +000012117 } else if (getUInt(code + 16) == 0x01ef7825 /* or $15, $15, $15 */ ) {
12118 /* branch-and-link-to-noredir $25 */
petarj1fb1e342013-04-27 02:18:11 +000012119 DIP("branch-and-link-to-noredir $25");
petarjb92a9542013-02-27 22:57:17 +000012120 if (mode64)
12121 putIReg(31, mkU64(guest_PC_curr_instr + 20));
12122 else
12123 putIReg(31, mkU32(guest_PC_curr_instr + 20));
sewardj362cf842012-06-07 08:59:53 +000012124 putPC(getIReg(25));
12125 dres.jk_StopHere = Ijk_NoRedir;
12126 dres.whatNext = Dis_StopHere;
12127 goto decode_success;
petarjb92a9542013-02-27 22:57:17 +000012128 } else if (getUInt(code + 16) == 0x016b5825 /* or $11,$11,$11 */ ) {
florian2245ce92012-08-28 16:49:30 +000012129 /* IR injection */
petarj1fb1e342013-04-27 02:18:11 +000012130 DIP("IR injection");
florian2245ce92012-08-28 16:49:30 +000012131#if defined (_MIPSEL)
12132 vex_inject_ir(irsb, Iend_LE);
12133#elif defined (_MIPSEB)
12134 vex_inject_ir(irsb, Iend_BE);
12135#endif
petarjb92a9542013-02-27 22:57:17 +000012136 if (mode64) {
sewardj05f5e012014-05-04 10:52:11 +000012137 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMSTART),
petarjb92a9542013-02-27 22:57:17 +000012138 mkU64(guest_PC_curr_instr)));
sewardj05f5e012014-05-04 10:52:11 +000012139 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMLEN),
petarjb92a9542013-02-27 22:57:17 +000012140 mkU64(20)));
florian2245ce92012-08-28 16:49:30 +000012141
petarjb92a9542013-02-27 22:57:17 +000012142 putPC(mkU64(guest_PC_curr_instr + 20));
12143 } else {
sewardj05f5e012014-05-04 10:52:11 +000012144 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMSTART),
petarjb92a9542013-02-27 22:57:17 +000012145 mkU32(guest_PC_curr_instr)));
sewardj05f5e012014-05-04 10:52:11 +000012146 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMLEN),
petarjb92a9542013-02-27 22:57:17 +000012147 mkU32(20)));
12148
12149 putPC(mkU32(guest_PC_curr_instr + 20));
12150 }
florian2245ce92012-08-28 16:49:30 +000012151 dres.whatNext = Dis_StopHere;
sewardj05f5e012014-05-04 10:52:11 +000012152 dres.jk_StopHere = Ijk_InvalICache;
florian2245ce92012-08-28 16:49:30 +000012153 dres.len = 20;
12154 delta += 20;
12155 goto decode_success;
sewardj362cf842012-06-07 08:59:53 +000012156 }
12157
12158 /* We don't know what it is. Set opc1/opc2 so decode_failure
12159 can print the insn following the Special-insn preamble. */
12160 delta += 16;
12161 goto decode_failure;
12162 /*NOTREACHED*/}
12163 }
12164
12165 opcode = get_opcode(cins);
12166 imm = get_imm(cins);
12167 rs = get_rs(cins);
12168 rt = get_rt(cins);
12169 rd = get_rd(cins);
12170 sa = get_sa(cins);
12171 fs = get_fs(cins);
12172 fd = get_fd(cins);
12173 ft = get_ft(cins);
12174 tf = get_tf(cins);
12175 nd = get_nd(cins);
12176 sel = get_sel(cins);
12177 fmt = get_fmt(cins);
12178 instr_index = get_instr_index(cins);
12179 trap_code = get_code(cins);
12180 function = get_function(cins);
12181 IRType ty = mode64 ? Ity_I64 : Ity_I32;
dejanj0e006f22014-02-19 11:56:29 +000012182 IRType tyF = fp_mode64 ? Ity_F64 : Ity_F32;
sewardj362cf842012-06-07 08:59:53 +000012183
dejanjc3fee0d2013-07-25 09:08:03 +000012184 ac = get_acNo(cins);
12185
sewardj362cf842012-06-07 08:59:53 +000012186 switch (opcode) {
12187
12188 case 0x03: /* JAL */
petarjc5b8bb72012-07-16 14:25:05 +000012189 DIP("jal 0x%x", instr_index);
petarjb92a9542013-02-27 22:57:17 +000012190 if (mode64) {
12191 putIReg(31, mkU64(guest_PC_curr_instr + 8));
12192 t0 = newTemp(ty);
petarjfdb2a4c2013-03-02 02:37:01 +000012193 assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
petarjb92a9542013-02-27 22:57:17 +000012194 (instr_index << 2)));
12195 } else {
12196 putIReg(31, mkU32(guest_PC_curr_instr + 8));
12197 t0 = newTemp(ty);
12198 assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
12199 (instr_index << 2)));
12200 }
sewardj362cf842012-06-07 08:59:53 +000012201 lastn = mkexpr(t0);
12202 break;
12203 case 0x02: /* J */
petarjc5b8bb72012-07-16 14:25:05 +000012204 DIP("j 0x%x", instr_index);
sewardj362cf842012-06-07 08:59:53 +000012205 t0 = newTemp(ty);
petarjb92a9542013-02-27 22:57:17 +000012206 if (mode64)
petarjfdb2a4c2013-03-02 02:37:01 +000012207 assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
petarjb92a9542013-02-27 22:57:17 +000012208 (instr_index << 2)));
12209 else
12210 assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
12211 (instr_index << 2)));
sewardj362cf842012-06-07 08:59:53 +000012212 lastn = mkexpr(t0);
12213 break;
12214
dejanj0e006f22014-02-19 11:56:29 +000012215 case 0x11: { /* COP1 */
12216 if (fmt == 0x3 && fd == 0 && function == 0) { /* MFHC1 */
12217 DIP("mfhc1 r%d, f%d", rt, fs);
12218 if (fp_mode64) {
12219 t0 = newTemp(Ity_I64);
12220 t1 = newTemp(Ity_I32);
12221 assign(t0, unop(Iop_ReinterpF64asI64, getDReg(fs)));
12222 assign(t1, unop(Iop_64HIto32, mkexpr(t0)));
12223 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
sewardj362cf842012-06-07 08:59:53 +000012224 } else {
dejanj0e006f22014-02-19 11:56:29 +000012225 ILLEGAL_INSTRUCTON;
12226 }
12227 break;
12228 } else if (fmt == 0x7 && fd == 0 && function == 0) { /* MTHC1 */
12229 DIP("mthc1 r%d, f%d", rt, fs);
12230 if (fp_mode64) {
12231 t0 = newTemp(Ity_I64);
12232 assign(t0, binop(Iop_32HLto64, getIReg(rt),
12233 unop(Iop_ReinterpF32asI32,
12234 getLoFromF64(Ity_F64 /* 32FPR mode. */,
12235 getDReg(fs)))));
12236 putDReg(fs, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
12237 } else {
12238 ILLEGAL_INSTRUCTON;
12239 }
12240 break;
12241 } else if (fmt == 0x8) { /* BC */
12242 /* FcConditionalCode(bc1_cc) */
12243 UInt bc1_cc = get_bc1_cc(cins);
12244 t1 = newTemp(Ity_I1);
12245 t2 = newTemp(Ity_I32);
12246 t3 = newTemp(Ity_I1);
sewardj362cf842012-06-07 08:59:53 +000012247
dejanj0e006f22014-02-19 11:56:29 +000012248 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(bc1_cc)));
12249 assign(t2, IRExpr_ITE(mkexpr(t1),
12250 binop(Iop_And32,
12251 binop(Iop_Shr32, getFCSR(), mkU8(23)),
12252 mkU32(0x1)),
12253 binop(Iop_And32,
12254 binop(Iop_Shr32, getFCSR(),
12255 mkU8(24 + bc1_cc)),
12256 mkU32(0x1))));
12257
12258 if (tf == 1 && nd == 0) {
12259 /* branch on true */
12260 DIP("bc1t %d, %d", bc1_cc, imm);
12261 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
12262 dis_branch(False, mkexpr(t3), imm, &bstmt);
12263 break;
12264 } else if (tf == 0 && nd == 0) {
12265 /* branch on false */
12266 DIP("bc1f %d, %d", bc1_cc, imm);
12267 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
12268 dis_branch(False, mkexpr(t3), imm, &bstmt);
12269 break;
12270 } else if (nd == 1 && tf == 0) {
12271 DIP("bc1fl %d, %d", bc1_cc, imm);
12272 lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2),
12273 mkU32(0x0)), imm);
12274 break;
12275 } else if (nd == 1 && tf == 1) {
12276 DIP("bc1tl %d, %d", bc1_cc, imm);
12277 lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2),
12278 mkU32(0x0)), imm);
12279 break;
12280 } else
12281 goto decode_failure;
12282 } else {
12283 switch (function) {
12284 case 0x4: { /* SQRT.fmt */
12285 switch (fmt) {
12286 case 0x10: { /* S */
12287 IRExpr *rm = get_IR_roundingmode();
12288 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_SqrtF32, rm,
12289 getLoFromF64(tyF, getFReg(fs)))));
sewardj362cf842012-06-07 08:59:53 +000012290 break;
dejanj0e006f22014-02-19 11:56:29 +000012291 }
12292 case 0x11: { /* D */
12293 IRExpr *rm = get_IR_roundingmode();
12294 putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs)));
sewardj362cf842012-06-07 08:59:53 +000012295 break;
12296 }
dejanj0e006f22014-02-19 11:56:29 +000012297 default:
12298 goto decode_failure;
12299 }
sewardj362cf842012-06-07 08:59:53 +000012300 }
12301 break;
petarjb92a9542013-02-27 22:57:17 +000012302 case 0x5: /* abs.fmt */
sewardj362cf842012-06-07 08:59:53 +000012303 switch (fmt) {
dejanj0e006f22014-02-19 11:56:29 +000012304 case 0x10: /* S */
12305 DIP("abs.s f%d, f%d", fd, fs);
12306 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32,
12307 getLoFromF64(tyF, getFReg(fs)))));
12308 break;
12309 case 0x11: /* D */
12310 DIP("abs.d f%d, f%d", fd, fs);
12311 putDReg(fd, unop(Iop_AbsF64, getDReg(fs)));
12312 break;
12313 default:
12314 goto decode_failure;
sewardj362cf842012-06-07 08:59:53 +000012315 }
petarjb92a9542013-02-27 22:57:17 +000012316 break; /* case 0x5 */
sewardj362cf842012-06-07 08:59:53 +000012317
petarjb92a9542013-02-27 22:57:17 +000012318 case 0x02: /* MUL.fmt */
sewardj362cf842012-06-07 08:59:53 +000012319 switch (fmt) {
dejanj0e006f22014-02-19 11:56:29 +000012320 case 0x11: { /* D */
sewardj362cf842012-06-07 08:59:53 +000012321 DIP("mul.d f%d, f%d, f%d", fd, fs, ft);
12322 IRExpr *rm = get_IR_roundingmode();
12323 putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs),
12324 getDReg(ft)));
12325 break;
12326 }
dejanj0e006f22014-02-19 11:56:29 +000012327 case 0x10: { /* S */
sewardj362cf842012-06-07 08:59:53 +000012328 DIP("mul.s f%d, f%d, f%d", fd, fs, ft);
12329 IRExpr *rm = get_IR_roundingmode();
12330 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm,
12331 getLoFromF64(tyF, getFReg(fs)),
12332 getLoFromF64(tyF, getFReg(ft)))));
12333 break;
12334 }
dejanj0e006f22014-02-19 11:56:29 +000012335 default:
12336 goto decode_failure;
sewardj362cf842012-06-07 08:59:53 +000012337 }
petarjb92a9542013-02-27 22:57:17 +000012338 break; /* MUL.fmt */
sewardj362cf842012-06-07 08:59:53 +000012339
petarjb92a9542013-02-27 22:57:17 +000012340 case 0x03: /* DIV.fmt */
sewardj362cf842012-06-07 08:59:53 +000012341 switch (fmt) {
dejanj0e006f22014-02-19 11:56:29 +000012342 case 0x11: { /* D */
sewardj362cf842012-06-07 08:59:53 +000012343 DIP("div.d f%d, f%d, f%d", fd, fs, ft);
12344 IRExpr *rm = get_IR_roundingmode();
12345 putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs),
12346 getDReg(ft)));
12347 break;
12348 }
dejanj0e006f22014-02-19 11:56:29 +000012349 case 0x10: { /* S */
sewardj362cf842012-06-07 08:59:53 +000012350 DIP("div.s f%d, f%d, f%d", fd, fs, ft);
dejanj41833222013-11-14 15:44:42 +000012351 calculateFCSR(fs, ft, DIVS, False, 2);
sewardj362cf842012-06-07 08:59:53 +000012352 IRExpr *rm = get_IR_roundingmode();
12353 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
12354 getLoFromF64(tyF, getFReg(fs)),
12355 getLoFromF64(tyF, getFReg(ft)))));
12356 break;
12357 }
dejanj0e006f22014-02-19 11:56:29 +000012358 default:
12359 goto decode_failure;
sewardj362cf842012-06-07 08:59:53 +000012360 }
petarjb92a9542013-02-27 22:57:17 +000012361 break; /* DIV.fmt */
sewardj362cf842012-06-07 08:59:53 +000012362
petarjb92a9542013-02-27 22:57:17 +000012363 case 0x01: /* SUB.fmt */
sewardj362cf842012-06-07 08:59:53 +000012364 switch (fmt) {
dejanj41833222013-11-14 15:44:42 +000012365 case 0x11: { /* D */
sewardj362cf842012-06-07 08:59:53 +000012366 DIP("sub.d f%d, f%d, f%d", fd, fs, ft);
dejanj41833222013-11-14 15:44:42 +000012367 calculateFCSR(fs, ft, SUBD, False, 2);
sewardj362cf842012-06-07 08:59:53 +000012368 IRExpr *rm = get_IR_roundingmode();
petarjb92a9542013-02-27 22:57:17 +000012369 putDReg(fd, triop(Iop_SubF64, rm, getDReg(fs),
12370 getDReg(ft)));
sewardj362cf842012-06-07 08:59:53 +000012371 break;
12372 }
dejanj41833222013-11-14 15:44:42 +000012373 case 0x10: { /* S */
sewardj362cf842012-06-07 08:59:53 +000012374 DIP("sub.s f%d, f%d, f%d", fd, fs, ft);
dejanj41833222013-11-14 15:44:42 +000012375 calculateFCSR(fs, ft, SUBS, True, 2);
sewardj362cf842012-06-07 08:59:53 +000012376 IRExpr *rm = get_IR_roundingmode();
12377 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm,
12378 getLoFromF64(tyF, getFReg(fs)),
12379 getLoFromF64(tyF, getFReg(ft)))));
12380 break;
12381 }
dejanj41833222013-11-14 15:44:42 +000012382 default:
12383 goto decode_failure;
sewardj362cf842012-06-07 08:59:53 +000012384 }
petarjb92a9542013-02-27 22:57:17 +000012385 break; /* SUB.fmt */
sewardj362cf842012-06-07 08:59:53 +000012386
petarjb92a9542013-02-27 22:57:17 +000012387 case 0x06: /* MOV.fmt */
sewardj362cf842012-06-07 08:59:53 +000012388 switch (fmt) {
petarjb92a9542013-02-27 22:57:17 +000012389 case 0x11: /* D */
12390 DIP("mov.d f%d, f%d", fd, fs);
dejanj0e006f22014-02-19 11:56:29 +000012391 if (fp_mode64) {
12392 putDReg(fd, getDReg(fs));
petarjb92a9542013-02-27 22:57:17 +000012393 } else {
12394 putFReg(fd, getFReg(fs));
12395 putFReg(fd + 1, getFReg(fs + 1));
12396 }
12397 break;
12398 case 0x10: /* S */
12399 DIP("mov.s f%d, f%d", fd, fs);
12400 putFReg(fd, getFReg(fs));
12401 break;
12402 default:
12403 goto decode_failure;
sewardj362cf842012-06-07 08:59:53 +000012404 }
petarjb92a9542013-02-27 22:57:17 +000012405 break; /* MOV.fmt */
sewardj362cf842012-06-07 08:59:53 +000012406
petarjb92a9542013-02-27 22:57:17 +000012407 case 0x7: /* neg.fmt */
sewardj362cf842012-06-07 08:59:53 +000012408 switch (fmt) {
petarjb92a9542013-02-27 22:57:17 +000012409 case 0x10: /* S */
12410 DIP("neg.s f%d, f%d", fd, fs);
12411 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32,
12412 getLoFromF64(tyF, getFReg(fs)))));
12413 break;
12414 case 0x11: /* D */
12415 DIP("neg.d f%d, f%d", fd, fs);
12416 putDReg(fd, unop(Iop_NegF64, getDReg(fs)));
12417 break;
12418 default:
12419 goto decode_failure;
sewardj362cf842012-06-07 08:59:53 +000012420 }
petarjb92a9542013-02-27 22:57:17 +000012421 break; /* case 0x7 */
sewardj362cf842012-06-07 08:59:53 +000012422
petarjb92a9542013-02-27 22:57:17 +000012423 case 0x08: /* ROUND.L.fmt */
sewardj362cf842012-06-07 08:59:53 +000012424 switch (fmt) {
petarjb92a9542013-02-27 22:57:17 +000012425 case 0x10: /* S */
petarj1fb1e342013-04-27 02:18:11 +000012426 DIP("round.l.s f%d, f%d", fd, fs);
dejanj0e006f22014-02-19 11:56:29 +000012427 if (fp_mode64) {
12428 calculateFCSR(fs, 0, ROUNDLS, True, 1);
12429 t0 = newTemp(Ity_I64);
petarjb92a9542013-02-27 22:57:17 +000012430
dejanj0e006f22014-02-19 11:56:29 +000012431 assign(t0, binop(Iop_F32toI64S, mkU32(0x0),
12432 getLoFromF64(Ity_F64, getFReg(fs))));
petarjb92a9542013-02-27 22:57:17 +000012433
dejanj0e006f22014-02-19 11:56:29 +000012434 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
12435 } else {
12436 ILLEGAL_INSTRUCTON;
12437 }
12438 break;
petarjb92a9542013-02-27 22:57:17 +000012439 case 0x11: /* D */
petarj1fb1e342013-04-27 02:18:11 +000012440 DIP("round.l.d f%d, f%d", fd, fs);
dejanj0e006f22014-02-19 11:56:29 +000012441 if (fp_mode64) {
12442 calculateFCSR(fs, 0, ROUNDLD, False, 1);
12443 putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x0),
12444 getDReg(fs)));
12445 } else {
12446 ILLEGAL_INSTRUCTON;
12447 }
petarjb92a9542013-02-27 22:57:17 +000012448 break;
12449 default:
12450 goto decode_failure;
12451
12452 }
12453 break; /* ROUND.L.fmt */
12454
12455 case 0x09: /* TRUNC.L.fmt */
12456 switch (fmt) {
12457 case 0x10: /* S */
petarj1fb1e342013-04-27 02:18:11 +000012458 DIP("trunc.l.s f%d, f%d", fd, fs);
dejanj0e006f22014-02-19 11:56:29 +000012459 if (fp_mode64) {
12460 calculateFCSR(fs, 0, TRUNCLS, True, 1);
12461 t0 = newTemp(Ity_I64);
12462 assign(t0, binop(Iop_F32toI64S, mkU32(0x3),
12463 getLoFromF64(Ity_F64, getFReg(fs))));
petarjb92a9542013-02-27 22:57:17 +000012464
dejanj0e006f22014-02-19 11:56:29 +000012465 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
12466 } else {
12467 ILLEGAL_INSTRUCTON;
12468 }
petarjb92a9542013-02-27 22:57:17 +000012469 break;
12470 case 0x11: /* D */
petarj1fb1e342013-04-27 02:18:11 +000012471 DIP("trunc.l.d f%d, f%d", fd, fs);
dejanj0e006f22014-02-19 11:56:29 +000012472 if (fp_mode64) {
12473 calculateFCSR(fs, 0, TRUNCLD, False, 1);
12474 putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x3),
12475 getDReg(fs)));
12476 } else {
12477 ILLEGAL_INSTRUCTON;
12478 }
petarjb92a9542013-02-27 22:57:17 +000012479 break;
12480 default:
12481 goto decode_failure;
12482 }
12483 break; /* TRUNC.L.fmt */
12484
12485 case 0x15: /* RECIP.fmt */
12486 switch (fmt) {
12487 case 0x10: { /* S */
petarj1fb1e342013-04-27 02:18:11 +000012488 DIP("recip.s f%d, f%d", fd, fs);
sewardj362cf842012-06-07 08:59:53 +000012489 IRExpr *rm = get_IR_roundingmode();
12490 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32,
12491 rm, unop(Iop_ReinterpI32asF32,
petarj0c30de82013-04-19 12:35:00 +000012492 mkU32(ONE_SINGLE)), getLoFromF64(tyF,
sewardj362cf842012-06-07 08:59:53 +000012493 getFReg(fs)))));
12494 break;
12495 }
petarjb92a9542013-02-27 22:57:17 +000012496 case 0x11: { /* D */
petarj1fb1e342013-04-27 02:18:11 +000012497 DIP("recip.d f%d, f%d", fd, fs);
sewardj590875f2012-10-26 08:00:59 +000012498 IRExpr *rm = get_IR_roundingmode();
petarj0c30de82013-04-19 12:35:00 +000012499 /* putDReg(fd, 1.0/getDreg(fs)); */
petarjbe927ba2012-09-09 01:10:59 +000012500 putDReg(fd, triop(Iop_DivF64, rm,
12501 unop(Iop_ReinterpI64asF64,
petarj0c30de82013-04-19 12:35:00 +000012502 mkU64(ONE_DOUBLE)), getDReg(fs)));
sewardj362cf842012-06-07 08:59:53 +000012503 break;
12504 }
12505 default:
12506 goto decode_failure;
12507
12508 }
petarjb92a9542013-02-27 22:57:17 +000012509 break; /* case 0x15 */
sewardj362cf842012-06-07 08:59:53 +000012510
petarjb92a9542013-02-27 22:57:17 +000012511 case 0x13: /* MOVN.fmt */
sewardj362cf842012-06-07 08:59:53 +000012512 switch (fmt) {
petarjb92a9542013-02-27 22:57:17 +000012513 case 0x10: /* S */
sewardj362cf842012-06-07 08:59:53 +000012514 DIP("movn.s f%d, f%d, r%d", fd, fs, rt);
sewardj362cf842012-06-07 08:59:53 +000012515 t1 = newTemp(Ity_F64);
12516 t2 = newTemp(Ity_F64);
petarjd4564182013-01-29 15:42:29 +000012517 t3 = newTemp(Ity_I1);
sewardj362cf842012-06-07 08:59:53 +000012518 t4 = newTemp(Ity_F64);
petarjb92a9542013-02-27 22:57:17 +000012519 if (mode64) {
12520 assign(t1, getFReg(fs));
12521 assign(t2, getFReg(fd));
12522 assign(t3, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
12523 } else {
dejanj0e006f22014-02-19 11:56:29 +000012524 if (fp_mode64) {
12525 assign(t1, getFReg(fs));
12526 assign(t2, getFReg(fd));
12527 assign(t3, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
12528 } else {
12529 assign(t1, unop(Iop_F32toF64, getFReg(fs)));
12530 assign(t2, unop(Iop_F32toF64, getFReg(fd)));
12531 assign(t3, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
12532 }
petarjb92a9542013-02-27 22:57:17 +000012533 }
sewardj362cf842012-06-07 08:59:53 +000012534
petarjd4564182013-01-29 15:42:29 +000012535 assign(t4, IRExpr_ITE(mkexpr(t3), mkexpr(t1), mkexpr(t2)));
dejanj0e006f22014-02-19 11:56:29 +000012536 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000012537 IRTemp f = newTemp(Ity_F64);
12538 IRTemp fd_hi = newTemp(Ity_I32);
12539 t5 = newTemp(Ity_I64);
12540 assign(f, getFReg(fd));
12541 assign(fd_hi, unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
12542 mkexpr(f))));
sewardj362cf842012-06-07 08:59:53 +000012543
dejanj0e006f22014-02-19 11:56:29 +000012544 assign(t5, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
petarjb92a9542013-02-27 22:57:17 +000012545 unop(Iop_ReinterpF64asI64, mkexpr(t4))), True));
12546
12547 putFReg(fd, unop (Iop_ReinterpI64asF64, mkexpr(t5)));
12548 } else
12549 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
12550 mkexpr(t4)));
sewardj362cf842012-06-07 08:59:53 +000012551 break;
petarjb92a9542013-02-27 22:57:17 +000012552 case 0x11: /* D */
sewardj362cf842012-06-07 08:59:53 +000012553 DIP("movn.d f%d, f%d, r%d", fd, fs, rt);
12554
petarjd4564182013-01-29 15:42:29 +000012555 t3 = newTemp(Ity_I1);
sewardj362cf842012-06-07 08:59:53 +000012556 t4 = newTemp(Ity_F64);
12557
petarjb92a9542013-02-27 22:57:17 +000012558 if (mode64)
12559 assign(t3, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
12560 else
12561 assign(t3, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
12562
petarjd4564182013-01-29 15:42:29 +000012563 putDReg(fd, IRExpr_ITE(mkexpr(t3), getDReg(fs), getDReg(fd)));
sewardj362cf842012-06-07 08:59:53 +000012564 break;
12565 default:
12566 goto decode_failure;
12567 }
petarjb92a9542013-02-27 22:57:17 +000012568 break; /* MOVN.fmt */
sewardj362cf842012-06-07 08:59:53 +000012569
petarjb92a9542013-02-27 22:57:17 +000012570 case 0x12: /* MOVZ.fmt */
sewardj362cf842012-06-07 08:59:53 +000012571 switch (fmt) {
petarjb92a9542013-02-27 22:57:17 +000012572 case 0x10: /* S */
sewardj362cf842012-06-07 08:59:53 +000012573 DIP("movz.s f%d, f%d, r%d", fd, fs, rt);
12574
12575 t1 = newTemp(Ity_F64);
12576 t2 = newTemp(Ity_F64);
petarjd4564182013-01-29 15:42:29 +000012577 t3 = newTemp(Ity_I1);
sewardj362cf842012-06-07 08:59:53 +000012578 t4 = newTemp(Ity_F64);
dejanj0e006f22014-02-19 11:56:29 +000012579 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000012580 assign(t1, getFReg(fs));
12581 assign(t2, getFReg(fd));
dejanj0e006f22014-02-19 11:56:29 +000012582 if (mode64)
12583 assign(t3, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
12584 else
12585 assign(t3, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
petarjb92a9542013-02-27 22:57:17 +000012586 } else {
12587 assign(t1, unop(Iop_F32toF64, getFReg(fs)));
12588 assign(t2, unop(Iop_F32toF64, getFReg(fd)));
12589 assign(t3, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
12590 }
petarjd4564182013-01-29 15:42:29 +000012591 assign(t4, IRExpr_ITE(mkexpr(t3), mkexpr(t1), mkexpr(t2)));
sewardj362cf842012-06-07 08:59:53 +000012592
dejanj0e006f22014-02-19 11:56:29 +000012593 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000012594 IRTemp f = newTemp(Ity_F64);
12595 IRTemp fd_hi = newTemp(Ity_I32);
12596 t7 = newTemp(Ity_I64);
12597 assign(f, getFReg(fd));
12598 assign(fd_hi, unop(Iop_64HIto32,
12599 unop(Iop_ReinterpF64asI64, mkexpr(f))));
dejanj0e006f22014-02-19 11:56:29 +000012600 assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
petarjb92a9542013-02-27 22:57:17 +000012601 unop(Iop_ReinterpF64asI64, mkexpr(t4))), True));
12602
12603 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
12604 } else
12605 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
12606 mkexpr(t4)));
sewardj362cf842012-06-07 08:59:53 +000012607
12608 break;
petarjb92a9542013-02-27 22:57:17 +000012609 case 0x11: /* D */
sewardj362cf842012-06-07 08:59:53 +000012610 DIP("movz.d f%d, f%d, r%d", fd, fs, rt);
petarjd4564182013-01-29 15:42:29 +000012611 t3 = newTemp(Ity_I1);
sewardj362cf842012-06-07 08:59:53 +000012612 t4 = newTemp(Ity_F64);
petarjb92a9542013-02-27 22:57:17 +000012613 if (mode64)
12614 assign(t3, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
12615 else
12616 assign(t3, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
sewardj362cf842012-06-07 08:59:53 +000012617
petarjd4564182013-01-29 15:42:29 +000012618 putDReg(fd, IRExpr_ITE(mkexpr(t3), getDReg(fs), getDReg(fd)));
sewardj362cf842012-06-07 08:59:53 +000012619 break;
12620 default:
12621 goto decode_failure;
12622 }
petarjb92a9542013-02-27 22:57:17 +000012623 break; /* MOVZ.fmt */
sewardj362cf842012-06-07 08:59:53 +000012624
petarjb92a9542013-02-27 22:57:17 +000012625 case 0x11: /* MOVT.fmt */
sewardj362cf842012-06-07 08:59:53 +000012626 if (tf == 1) {
12627 UInt mov_cc = get_mov_cc(cins);
petarjb92a9542013-02-27 22:57:17 +000012628 switch (fmt) { /* MOVCF = 010001 */
12629 case 0x11: /* D */
sewardj362cf842012-06-07 08:59:53 +000012630 DIP("movt.d f%d, f%d, %d", fd, fs, mov_cc);
petarjd4564182013-01-29 15:42:29 +000012631 t1 = newTemp(Ity_I1);
sewardj362cf842012-06-07 08:59:53 +000012632 t2 = newTemp(Ity_I32);
petarjd4564182013-01-29 15:42:29 +000012633 t3 = newTemp(Ity_I1);
sewardj362cf842012-06-07 08:59:53 +000012634 t4 = newTemp(Ity_F64);
12635
petarjd4564182013-01-29 15:42:29 +000012636 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
12637 assign(t2, IRExpr_ITE(mkexpr(t1),
florian99dd03e2013-01-29 03:56:06 +000012638 binop(Iop_And32,
12639 binop(Iop_Shr32, getFCSR(),
12640 mkU8(23)),
12641 mkU32(0x1)),
12642 binop(Iop_And32,
12643 binop(Iop_Shr32, getFCSR(),
12644 mkU8(24 + mov_cc)),
12645 mkU32(0x1))
12646 ));
sewardj362cf842012-06-07 08:59:53 +000012647
petarjd4564182013-01-29 15:42:29 +000012648 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
12649 assign(t4, IRExpr_ITE(mkexpr(t3),
florian99dd03e2013-01-29 03:56:06 +000012650 getDReg(fs), getDReg(fd)));
sewardj362cf842012-06-07 08:59:53 +000012651 putDReg(fd, mkexpr(t4));
12652 break;
petarjb92a9542013-02-27 22:57:17 +000012653 case 0x10: /* S */
12654 DIP("movt.s f%d, f%d, %d", fd, fs, mov_cc);
12655 t1 = newTemp(Ity_I1);
12656 t2 = newTemp(Ity_I32);
12657 t3 = newTemp(Ity_I1);
12658 t4 = newTemp(Ity_F64);
12659 t5 = newTemp(Ity_F64);
12660 t6 = newTemp(Ity_F64);
12661 t7 = newTemp(Ity_I64);
sewardj362cf842012-06-07 08:59:53 +000012662
dejanj0e006f22014-02-19 11:56:29 +000012663 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000012664 assign(t5, getFReg(fs));
12665 assign(t6, getFReg(fd));
12666 } else {
sewardj362cf842012-06-07 08:59:53 +000012667 assign(t5, unop(Iop_F32toF64, getFReg(fs)));
12668 assign(t6, unop(Iop_F32toF64, getFReg(fd)));
petarjb92a9542013-02-27 22:57:17 +000012669 }
sewardj362cf842012-06-07 08:59:53 +000012670
petarjb92a9542013-02-27 22:57:17 +000012671 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
12672 assign(t2, IRExpr_ITE(mkexpr(t1),
12673 binop(Iop_And32,
12674 binop(Iop_Shr32, getFCSR(),
12675 mkU8(23)),
12676 mkU32(0x1)),
12677 binop(Iop_And32,
12678 binop(Iop_Shr32, getFCSR(),
12679 mkU8(24 + mov_cc)),
12680 mkU32(0x1))
12681 ));
sewardj362cf842012-06-07 08:59:53 +000012682
petarjb92a9542013-02-27 22:57:17 +000012683 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
12684 assign(t4, IRExpr_ITE(mkexpr(t3),
12685 mkexpr(t5), mkexpr(t6)));
12686
dejanj0e006f22014-02-19 11:56:29 +000012687 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000012688 IRTemp f = newTemp(Ity_F64);
12689 IRTemp fd_hi = newTemp(Ity_I32);
12690 assign(f, getFReg(fd));
12691 assign(fd_hi, unop(Iop_64HIto32,
12692 unop(Iop_ReinterpF64asI64, mkexpr(f))));
dejanj0e006f22014-02-19 11:56:29 +000012693 assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
petarjb92a9542013-02-27 22:57:17 +000012694 unop(Iop_ReinterpF64asI64, mkexpr(t4))),
12695 True));
12696
12697 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
12698 } else
sewardj362cf842012-06-07 08:59:53 +000012699 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
12700 mkexpr(t4)));
petarjb92a9542013-02-27 22:57:17 +000012701 break;
12702 default:
12703 goto decode_failure;
12704 }
12705 } else if (tf == 0) /* movf.fmt */
12706 {
12707 UInt mov_cc = get_mov_cc(cins);
12708 switch (fmt) /* MOVCF = 010001 */
12709 {
12710 case 0x11: /* D */
12711 DIP("movf.d f%d, f%d, %d", fd, fs, mov_cc);
12712 t1 = newTemp(Ity_I1);
12713 t2 = newTemp(Ity_I32);
12714 t3 = newTemp(Ity_I1);
12715 t4 = newTemp(Ity_F64);
12716
12717 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
12718 assign(t2, IRExpr_ITE(mkexpr(t1),
12719 binop(Iop_And32,
12720 binop(Iop_Shr32, getFCSR(),
12721 mkU8(23)),
12722 mkU32(0x1)),
12723 binop(Iop_And32,
12724 binop(Iop_Shr32, getFCSR(),
12725 mkU8(24 + mov_cc)),
12726 mkU32(0x1))
12727 ));
12728
12729 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
12730 assign(t4, IRExpr_ITE(mkexpr(t3),
12731 getDReg(fs), getDReg(fd)));
12732 putDReg(fd, mkexpr(t4));
12733 break;
12734 case 0x10: /* S */
12735 DIP("movf.s f%d, f%d, %d", fd, fs, mov_cc);
12736 t1 = newTemp(Ity_I1);
12737 t2 = newTemp(Ity_I32);
12738 t3 = newTemp(Ity_I1);
12739 t4 = newTemp(Ity_F64);
12740 t5 = newTemp(Ity_F64);
12741 t6 = newTemp(Ity_F64);
12742
dejanj0e006f22014-02-19 11:56:29 +000012743 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000012744 assign(t5, getFReg(fs));
12745 assign(t6, getFReg(fd));
12746 } else {
12747 assign(t5, unop(Iop_F32toF64, getFReg(fs)));
12748 assign(t6, unop(Iop_F32toF64, getFReg(fd)));
sewardj362cf842012-06-07 08:59:53 +000012749 }
petarjb92a9542013-02-27 22:57:17 +000012750
12751 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
12752 assign(t2, IRExpr_ITE(mkexpr(t1),
12753 binop(Iop_And32,
12754 binop(Iop_Shr32, getFCSR(),
12755 mkU8(23)),
12756 mkU32(0x1)),
12757 binop(Iop_And32,
12758 binop(Iop_Shr32, getFCSR(),
12759 mkU8(24 + mov_cc)),
12760 mkU32(0x1))
12761 ));
12762
12763 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
12764 assign(t4, IRExpr_ITE(mkexpr(t3),
12765 mkexpr(t5), mkexpr(t6)));
12766
dejanj0e006f22014-02-19 11:56:29 +000012767 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000012768 IRTemp f = newTemp(Ity_F64);
12769 IRTemp fd_hi = newTemp(Ity_I32);
12770 t7 = newTemp(Ity_I64);
12771 assign(f, getFReg(fd));
12772 assign(fd_hi, unop(Iop_64HIto32,
12773 unop(Iop_ReinterpF64asI64, mkexpr(f))));
dejanj0e006f22014-02-19 11:56:29 +000012774 assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
petarjb92a9542013-02-27 22:57:17 +000012775 unop(Iop_ReinterpF64asI64, mkexpr(t4))),
12776 True));
12777
12778 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
12779 } else
12780 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
12781 mkexpr(t4)));
sewardj362cf842012-06-07 08:59:53 +000012782 break;
12783 default:
12784 goto decode_failure;
12785 }
12786 }
12787
petarjb92a9542013-02-27 22:57:17 +000012788 break; /* MOVT.fmt */
sewardj362cf842012-06-07 08:59:53 +000012789
petarjb92a9542013-02-27 22:57:17 +000012790 case 0x0: /* add.fmt */
sewardj362cf842012-06-07 08:59:53 +000012791 switch (fmt) {
dejanj41833222013-11-14 15:44:42 +000012792 case 0x10: { /* S */
12793 DIP("add.s f%d, f%d, f%d", fd, fs, ft);
12794 calculateFCSR(fs, ft, ADDS, True, 2);
12795 IRExpr *rm = get_IR_roundingmode();
12796 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm,
12797 getLoFromF64(tyF, getFReg(fs)),
12798 getLoFromF64(tyF, getFReg(ft)))));
12799 break;
12800 }
petarjb92a9542013-02-27 22:57:17 +000012801 case 0x11: { /* D */
petarj1fb1e342013-04-27 02:18:11 +000012802 DIP("add.d f%d, f%d, f%d", fd, fs, ft);
dejanj41833222013-11-14 15:44:42 +000012803 calculateFCSR(fs, ft, ADDD, False, 2);
petarjb92a9542013-02-27 22:57:17 +000012804 IRExpr *rm = get_IR_roundingmode();
12805 putDReg(fd, triop(Iop_AddF64, rm, getDReg(fs), getDReg(ft)));
12806 break;
12807 }
sewardj362cf842012-06-07 08:59:53 +000012808
petarjb92a9542013-02-27 22:57:17 +000012809 case 0x4: /* MTC1 (Move Word to Floating Point) */
sewardj362cf842012-06-07 08:59:53 +000012810 DIP("mtc1 r%d, f%d", rt, fs);
dejanj0e006f22014-02-19 11:56:29 +000012811 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000012812 t0 = newTemp(Ity_I32);
12813 t1 = newTemp(Ity_F32);
dejanj0e006f22014-02-19 11:56:29 +000012814 assign(t0, mkNarrowTo32(ty, getIReg(rt)));
petarjb92a9542013-02-27 22:57:17 +000012815 assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
12816
12817 putFReg(fs, mkWidenFromF32(tyF, mkexpr(t1)));
12818 } else
12819 putFReg(fs, unop(Iop_ReinterpI32asF32, getIReg(rt)));
sewardj362cf842012-06-07 08:59:53 +000012820 break;
12821
petarjb92a9542013-02-27 22:57:17 +000012822 case 0x5: /* Doubleword Move to Floating Point DMTC1; MIPS64 */
12823 DIP("dmtc1 r%d, f%d", rt, fs);
12824 vassert(mode64);
12825 putFReg(fs, unop(Iop_ReinterpI64asF64, getIReg(rt)));
12826 break;
12827
12828 case 0x0: /* MFC1 */
sewardj362cf842012-06-07 08:59:53 +000012829 DIP("mfc1 r%d, f%d", rt, fs);
dejanj0e006f22014-02-19 11:56:29 +000012830 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000012831 t0 = newTemp(Ity_I64);
12832 t1 = newTemp(Ity_I32);
12833 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
12834 assign(t1, unop(Iop_64to32, mkexpr(t0)));
12835 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
12836 } else
12837 putIReg(rt, unop(Iop_ReinterpF32asI32, getFReg(fs)));
sewardj362cf842012-06-07 08:59:53 +000012838 break;
12839
petarjb92a9542013-02-27 22:57:17 +000012840 case 0x1: /* Doubleword Move from Floating Point DMFC1;
12841 MIPS64 */
12842 DIP("dmfc1 r%d, f%d", rt, fs);
12843 putIReg(rt, unop(Iop_ReinterpF64asI64, getFReg(fs)));
12844 break;
12845
12846 case 0x6: /* CTC1 */
sewardj362cf842012-06-07 08:59:53 +000012847 DIP("ctc1 r%d, f%d", rt, fs);
12848 t0 = newTemp(Ity_I32);
12849 t1 = newTemp(Ity_I32);
12850 t2 = newTemp(Ity_I32);
12851 t3 = newTemp(Ity_I32);
12852 t4 = newTemp(Ity_I32);
12853 t5 = newTemp(Ity_I32);
12854 t6 = newTemp(Ity_I32);
12855 assign(t0, mkNarrowTo32(ty, getIReg(rt)));
petarjb92a9542013-02-27 22:57:17 +000012856 if (fs == 25) { /* FCCR */
sewardj362cf842012-06-07 08:59:53 +000012857 assign(t1, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
12858 mkU32(0x000000FE)), mkU8(24)));
12859 assign(t2, binop(Iop_And32, mkexpr(t0),
12860 mkU32(0x01000000)));
12861 assign(t3, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
12862 mkU32(0x00000001)), mkU8(23)));
12863 assign(t4, binop(Iop_And32, mkexpr(t0),
12864 mkU32(0x007FFFFF)));
12865 putFCSR(binop(Iop_Or32, binop(Iop_Or32, mkexpr(t1),
12866 mkexpr(t2)), binop(Iop_Or32, mkexpr(t3),
12867 mkexpr(t4))));
petarjb92a9542013-02-27 22:57:17 +000012868 } else if (fs == 26) { /* FEXR */
sewardj362cf842012-06-07 08:59:53 +000012869 assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFFFC0000)));
12870 assign(t2, binop(Iop_And32, mkexpr(t0),
12871 mkU32(0x0003F000)));
12872 assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00000F80)));
12873 assign(t4, binop(Iop_And32, mkexpr(t0),
12874 mkU32(0x0000007C)));
12875 assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x00000003)));
12876 putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
12877 mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
12878 mkexpr(t3), mkexpr(t4))), mkexpr(t5)));
12879 } else if (fs == 28) {
12880 assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFE000000)));
12881 assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
12882 mkU32(0x00000002)), mkU8(22)));
12883 assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00FFF000)));
12884 assign(t4, binop(Iop_And32, mkexpr(t0),
12885 mkU32(0x00000F80)));
12886 assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x0000007C)));
12887 assign(t6, binop(Iop_And32, mkexpr(t0),
12888 mkU32(0x00000003)));
12889 putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
12890 mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
12891 mkexpr(t3), mkexpr(t4))), binop(Iop_Or32,
12892 mkexpr(t5), mkexpr(t6))));
12893 } else if (fs == 31) {
12894 putFCSR(mkexpr(t0));
12895 }
12896 break;
petarjb92a9542013-02-27 22:57:17 +000012897 case 0x2: /* CFC1 */
sewardj362cf842012-06-07 08:59:53 +000012898 DIP("cfc1 r%d, f%d", rt, fs);
12899 t0 = newTemp(Ity_I32);
12900 t1 = newTemp(Ity_I32);
12901 t2 = newTemp(Ity_I32);
12902 t3 = newTemp(Ity_I32);
12903 t4 = newTemp(Ity_I32);
12904 t5 = newTemp(Ity_I32);
12905 t6 = newTemp(Ity_I32);
12906 assign(t0, getFCSR());
12907 if (fs == 0) {
12908 putIReg(rt, mkWidenFrom32(ty,
12909 IRExpr_Get(offsetof(VexGuestMIPS32State,
12910 guest_FIR),
12911 Ity_I32),
12912 False));
12913 } else if (fs == 25) {
12914 assign(t1, mkU32(0x000000FF));
12915 assign(t2, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
12916 mkU32(0xFE000000)), mkU8(25)));
12917 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
12918 mkU32(0x00800000)), mkU8(23)));
12919 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
12920 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
12921 mkexpr(t3)), False));
12922 } else if (fs == 26) {
12923 assign(t1, mkU32(0xFFFFF07C));
12924 assign(t2, binop(Iop_And32, mkexpr(t0),
12925 mkU32(0x0003F000)));
12926 assign(t3, binop(Iop_And32, mkexpr(t0),
12927 mkU32(0x0000007C)));
12928 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
12929 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
12930 mkexpr(t3)), False));
12931 } else if (fs == 28) {
12932 assign(t1, mkU32(0x00000F87));
12933 assign(t2, binop(Iop_And32, mkexpr(t0),
12934 mkU32(0x00000F83)));
12935 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
12936 mkU32(0x01000000)), mkU8(22)));
12937 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
12938 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
12939 mkexpr(t3)), False));
12940 } else if (fs == 31) {
12941 putIReg(rt, mkWidenFrom32(ty, getFCSR(), False));
12942 }
12943 break;
12944 default:
12945 goto decode_failure;
12946 }
petarjb92a9542013-02-27 22:57:17 +000012947 break;
sewardj362cf842012-06-07 08:59:53 +000012948
petarjb92a9542013-02-27 22:57:17 +000012949 case 0x21: /* CVT.D */
sewardj362cf842012-06-07 08:59:53 +000012950 switch (fmt) {
petarjb92a9542013-02-27 22:57:17 +000012951 case 0x10: /* S */
12952 DIP("cvt.d.s f%d, f%d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000012953 calculateFCSR(fs, 0, CVTDS, True, 1);
dejanj0e006f22014-02-19 11:56:29 +000012954 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000012955 t0 = newTemp(Ity_I64);
12956 t1 = newTemp(Ity_I32);
12957 t3 = newTemp(Ity_F32);
12958 t4 = newTemp(Ity_F32);
12959 /* get lo half of FPR */
12960 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
sewardj362cf842012-06-07 08:59:53 +000012961
petarjb92a9542013-02-27 22:57:17 +000012962 assign(t1, unop(Iop_64to32, mkexpr(t0)));
12963
12964 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1)));
12965
12966 putFReg(fd, unop(Iop_F32toF64, mkexpr(t3)));
dejanj8007ea62013-09-18 10:06:13 +000012967 } else
petarjb92a9542013-02-27 22:57:17 +000012968 putDReg(fd, unop(Iop_F32toF64, getFReg(fs)));
dejanj8007ea62013-09-18 10:06:13 +000012969 break;
petarjb92a9542013-02-27 22:57:17 +000012970
12971 case 0x14:
petarj1fb1e342013-04-27 02:18:11 +000012972 DIP("cvt.d.w %d, %d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000012973 calculateFCSR(fs, 0, CVTDW, True, 1);
dejanj0e006f22014-02-19 11:56:29 +000012974 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000012975 t0 = newTemp(Ity_I64);
12976 t1 = newTemp(Ity_I32);
12977 t3 = newTemp(Ity_F32);
12978 t4 = newTemp(Ity_F32);
12979 /* get lo half of FPR */
12980 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
12981
12982 assign(t1, unop(Iop_64to32, mkexpr(t0)));
12983 putDReg(fd,unop(Iop_I32StoF64, mkexpr(t1)));
12984 break;
12985 } else {
12986 t0 = newTemp(Ity_I32);
12987 assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
12988 putDReg(fd, unop(Iop_I32StoF64, mkexpr(t0)));
12989 break;
12990 }
12991
12992 case 0x15: { /* L */
dejanj0e006f22014-02-19 11:56:29 +000012993 if (fp_mode64) {
petarj1fb1e342013-04-27 02:18:11 +000012994 DIP("cvt.d.l %d, %d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000012995 calculateFCSR(fs, 0, CVTDL, False, 1);
petarjb92a9542013-02-27 22:57:17 +000012996 t0 = newTemp(Ity_I64);
12997 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
12998
12999 putFReg(fd, binop(Iop_I64StoF64,
13000 get_IR_roundingmode(), mkexpr(t0)));
13001 break;
13002 } else
13003 goto decode_failure;
sewardj362cf842012-06-07 08:59:53 +000013004 }
petarjb92a9542013-02-27 22:57:17 +000013005 default:
13006 goto decode_failure;
sewardj362cf842012-06-07 08:59:53 +000013007 }
petarjb92a9542013-02-27 22:57:17 +000013008 break; /* CVT.D */
sewardj362cf842012-06-07 08:59:53 +000013009
petarjb92a9542013-02-27 22:57:17 +000013010 case 0x20: /* cvt.s */
sewardj362cf842012-06-07 08:59:53 +000013011 switch (fmt) {
petarjb92a9542013-02-27 22:57:17 +000013012 case 0x14: /* W */
petarj1fb1e342013-04-27 02:18:11 +000013013 DIP("cvt.s.w %d, %d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000013014 calculateFCSR(fs, 0, CVTSW, True, 1);
dejanj0e006f22014-02-19 11:56:29 +000013015 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000013016 t0 = newTemp(Ity_I64);
13017 t1 = newTemp(Ity_I32);
13018 t3 = newTemp(Ity_F32);
13019 t4 = newTemp(Ity_F32);
13020 /* get lo half of FPR */
13021 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
sewardj362cf842012-06-07 08:59:53 +000013022
petarjb92a9542013-02-27 22:57:17 +000013023 assign(t1, unop(Iop_64to32, mkexpr(t0)));
13024 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I32StoF32,
13025 get_IR_roundingmode(), mkexpr(t1))));
petarjb92a9542013-02-27 22:57:17 +000013026 } else {
13027 t0 = newTemp(Ity_I32);
13028 assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
13029 putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(),
13030 mkexpr(t0)));
dejanj8007ea62013-09-18 10:06:13 +000013031 }
13032 break;
sewardj362cf842012-06-07 08:59:53 +000013033
petarjb92a9542013-02-27 22:57:17 +000013034 case 0x11: /* D */
petarj1fb1e342013-04-27 02:18:11 +000013035 DIP("cvt.s.d %d, %d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000013036 calculateFCSR(fs, 0, CVTSD, False, 1);
dejanj0e006f22014-02-19 11:56:29 +000013037 t0 = newTemp(Ity_F32);
13038 assign(t0, binop(Iop_F64toF32, get_IR_roundingmode(),
13039 getDReg(fs)));
13040 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t0)));
petarjb92a9542013-02-27 22:57:17 +000013041 break;
13042
13043 case 0x15: /* L */
petarj1fb1e342013-04-27 02:18:11 +000013044 DIP("cvt.s.l %d, %d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000013045 calculateFCSR(fs, 0, CVTSL, False, 1);
petarjb92a9542013-02-27 22:57:17 +000013046 t0 = newTemp(Ity_I64);
13047 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
13048
13049 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I64StoF32,
13050 get_IR_roundingmode(), mkexpr(t0))));
13051 break;
13052
13053 default:
13054 goto decode_failure;
sewardj362cf842012-06-07 08:59:53 +000013055 }
petarjb92a9542013-02-27 22:57:17 +000013056 break; /* cvt.s */
sewardj362cf842012-06-07 08:59:53 +000013057
petarjb92a9542013-02-27 22:57:17 +000013058 case 0x24: /* cvt.w */
sewardj362cf842012-06-07 08:59:53 +000013059 switch (fmt) {
petarjb92a9542013-02-27 22:57:17 +000013060 case 0x10: /* S */
petarj1fb1e342013-04-27 02:18:11 +000013061 DIP("cvt.w.s %d, %d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000013062 calculateFCSR(fs, 0, CVTWS, True, 1);
dejanj0e006f22014-02-19 11:56:29 +000013063 putFReg(fd,
13064 mkWidenFromF32(tyF,
13065 binop(Iop_RoundF32toInt,
13066 get_IR_roundingmode(),
13067 getLoFromF64(tyF, getFReg(fs))))
13068 );
sewardj362cf842012-06-07 08:59:53 +000013069 break;
13070
13071 case 0x11:
petarj1fb1e342013-04-27 02:18:11 +000013072 DIP("cvt.w.d %d, %d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000013073 calculateFCSR(fs, 0, CVTWD, False, 1);
dejanj0e006f22014-02-19 11:56:29 +000013074 t0 = newTemp(Ity_I32);
13075 t1 = newTemp(Ity_F32);
13076 assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(),
13077 getDReg(fs)));
13078 assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
13079 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
sewardj362cf842012-06-07 08:59:53 +000013080 break;
13081
13082 default:
13083 goto decode_failure;
13084
13085 }
13086 break;
13087
petarjb92a9542013-02-27 22:57:17 +000013088 case 0x25: /* cvt.l */
sewardj362cf842012-06-07 08:59:53 +000013089 switch (fmt) {
petarjb92a9542013-02-27 22:57:17 +000013090 case 0x10: /* S */
petarj1fb1e342013-04-27 02:18:11 +000013091 DIP("cvt.l.s %d, %d", fd, fs);
dejanj0e006f22014-02-19 11:56:29 +000013092 if (fp_mode64) {
13093 calculateFCSR(fs, 0, CVTLS, True, 1);
13094 t0 = newTemp(Ity_I64);
sewardj362cf842012-06-07 08:59:53 +000013095
dejanj0e006f22014-02-19 11:56:29 +000013096 assign(t0, binop(Iop_F32toI64S, get_IR_roundingmode(),
13097 getLoFromF64(tyF, getFReg(fs))));
sewardj362cf842012-06-07 08:59:53 +000013098
dejanj0e006f22014-02-19 11:56:29 +000013099 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
13100 } else {
13101 ILLEGAL_INSTRUCTON;
13102 }
petarjb92a9542013-02-27 22:57:17 +000013103 break;
sewardj362cf842012-06-07 08:59:53 +000013104
petarjb92a9542013-02-27 22:57:17 +000013105 case 0x11: { /* D */
petarj1fb1e342013-04-27 02:18:11 +000013106 DIP("cvt.l.d %d, %d", fd, fs);
dejanj0e006f22014-02-19 11:56:29 +000013107 if (fp_mode64) {
13108 calculateFCSR(fs, 0, CVTLD, False, 1);
13109 putDReg(fd, binop(Iop_RoundF64toInt,
13110 get_IR_roundingmode(), getDReg(fs)));
13111 } else {
13112 ILLEGAL_INSTRUCTON;
13113 }
petarjb92a9542013-02-27 22:57:17 +000013114 break;
13115 }
sewardj362cf842012-06-07 08:59:53 +000013116
petarjb92a9542013-02-27 22:57:17 +000013117 default:
13118 goto decode_failure;
sewardj362cf842012-06-07 08:59:53 +000013119 }
13120 break;
petarjb92a9542013-02-27 22:57:17 +000013121
13122 case 0x0B: /* FLOOR.L.fmt */
sewardj362cf842012-06-07 08:59:53 +000013123 switch (fmt) {
petarjb92a9542013-02-27 22:57:17 +000013124 case 0x10: /* S */
petarj1fb1e342013-04-27 02:18:11 +000013125 DIP("floor.l.s %d, %d", fd, fs);
dejanj0e006f22014-02-19 11:56:29 +000013126 if (fp_mode64) {
13127 calculateFCSR(fs, 0, FLOORLS, True, 1);
13128 t0 = newTemp(Ity_I64);
sewardj362cf842012-06-07 08:59:53 +000013129
dejanj0e006f22014-02-19 11:56:29 +000013130 assign(t0, binop(Iop_F32toI64S, mkU32(0x1),
13131 getLoFromF64(tyF, getFReg(fs))));
sewardj362cf842012-06-07 08:59:53 +000013132
dejanj0e006f22014-02-19 11:56:29 +000013133 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
13134 } else {
13135 ILLEGAL_INSTRUCTON;
13136 }
petarjb92a9542013-02-27 22:57:17 +000013137 break;
sewardj362cf842012-06-07 08:59:53 +000013138
petarjb92a9542013-02-27 22:57:17 +000013139 case 0x11: /* D */
petarj1fb1e342013-04-27 02:18:11 +000013140 DIP("floor.l.d %d, %d", fd, fs);
dejanj0e006f22014-02-19 11:56:29 +000013141 if (fp_mode64) {
13142 calculateFCSR(fs, 0, FLOORLD, False, 1);
13143 putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x1),
13144 getDReg(fs)));
13145 } else {
13146 ILLEGAL_INSTRUCTON;
13147 }
petarjb92a9542013-02-27 22:57:17 +000013148 break;
13149 default:
13150 goto decode_failure;
sewardj362cf842012-06-07 08:59:53 +000013151 }
13152 break;
petarjb92a9542013-02-27 22:57:17 +000013153
13154 case 0x0C: /* ROUND.W.fmt */
sewardj362cf842012-06-07 08:59:53 +000013155 switch (fmt) {
petarjb92a9542013-02-27 22:57:17 +000013156 case 0x10: /* S */
petarj1fb1e342013-04-27 02:18:11 +000013157 DIP("round.w.s f%d, f%d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000013158 calculateFCSR(fs, 0, ROUNDWS, True, 1);
dejanj0e006f22014-02-19 11:56:29 +000013159 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000013160 t0 = newTemp(Ity_I64);
13161 t1 = newTemp(Ity_I32);
13162 t3 = newTemp(Ity_F32);
13163 t4 = newTemp(Ity_F32);
13164 /* get lo half of FPR */
13165 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
sewardj362cf842012-06-07 08:59:53 +000013166
petarjb92a9542013-02-27 22:57:17 +000013167 assign(t1, unop(Iop_64to32, mkexpr(t0)));
sewardj362cf842012-06-07 08:59:53 +000013168
petarjb92a9542013-02-27 22:57:17 +000013169 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1)));
sewardj362cf842012-06-07 08:59:53 +000013170
petarjb92a9542013-02-27 22:57:17 +000013171 assign(t4, binop(Iop_RoundF32toInt, mkU32(0x0),
13172 mkexpr(t3)));
13173
13174 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4)));
dejanj8007ea62013-09-18 10:06:13 +000013175 } else
petarjb92a9542013-02-27 22:57:17 +000013176 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x0),
13177 getFReg(fs)));
dejanj8007ea62013-09-18 10:06:13 +000013178 break;
petarjb92a9542013-02-27 22:57:17 +000013179
13180 case 0x11: /* D */
petarj1fb1e342013-04-27 02:18:11 +000013181 DIP("round.w.d f%d, f%d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000013182 calculateFCSR(fs, 0, ROUNDWD, False, 1);
dejanj0e006f22014-02-19 11:56:29 +000013183 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000013184 t0 = newTemp(Ity_I32);
13185 assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
13186 getDReg(fs)));
13187 putFReg(fd, mkWidenFromF32(tyF,
13188 unop(Iop_ReinterpI32asF32, mkexpr(t0))));
petarjb92a9542013-02-27 22:57:17 +000013189 } else {
13190 t0 = newTemp(Ity_I32);
13191
13192 assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
13193 getDReg(fs)));
13194
13195 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
petarjb92a9542013-02-27 22:57:17 +000013196 }
dejanj8007ea62013-09-18 10:06:13 +000013197 break;
petarjb92a9542013-02-27 22:57:17 +000013198 default:
13199 goto decode_failure;
13200
13201 }
13202 break; /* ROUND.W.fmt */
13203
13204 case 0x0F: /* FLOOR.W.fmt */
13205 switch (fmt) {
13206 case 0x10: /* S */
petarj1fb1e342013-04-27 02:18:11 +000013207 DIP("floor.w.s f%d, f%d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000013208 calculateFCSR(fs, 0, FLOORWS, True, 1);
dejanj0e006f22014-02-19 11:56:29 +000013209 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000013210 t0 = newTemp(Ity_I64);
13211 t1 = newTemp(Ity_I32);
13212 t3 = newTemp(Ity_F32);
13213 t4 = newTemp(Ity_F32);
13214 /* get lo half of FPR */
13215 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
13216
13217 assign(t1, unop(Iop_64to32, mkexpr(t0)));
13218
13219 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1)));
13220
13221 assign(t4, binop(Iop_RoundF32toInt, mkU32(0x1),
13222 mkexpr(t3)));
13223
13224 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4)));
dejanj8007ea62013-09-18 10:06:13 +000013225 } else
petarjb92a9542013-02-27 22:57:17 +000013226 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x1),
13227 getFReg(fs)));
dejanj8007ea62013-09-18 10:06:13 +000013228 break;
petarjb92a9542013-02-27 22:57:17 +000013229
13230 case 0x11: /* D */
petarj1fb1e342013-04-27 02:18:11 +000013231 DIP("floor.w.d f%d, f%d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000013232 calculateFCSR(fs, 0, FLOORWD, False, 1);
dejanj0e006f22014-02-19 11:56:29 +000013233 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000013234 t0 = newTemp(Ity_I32);
13235 assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
13236 getDReg(fs)));
13237 putFReg(fd, mkWidenFromF32(tyF,
13238 unop(Iop_ReinterpI32asF32, mkexpr(t0))));
13239 break;
13240 } else {
13241 t0 = newTemp(Ity_I32);
13242
13243 assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
13244 getDReg(fs)));
13245
13246 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
13247 break;
13248 }
13249 default:
13250 goto decode_failure;
13251
13252 }
13253 break; /* FLOOR.W.fmt */
13254
13255 case 0x0D: /* TRUNC.W */
13256 switch (fmt) {
13257 case 0x10: /* S */
petarj1fb1e342013-04-27 02:18:11 +000013258 DIP("trunc.w.s %d, %d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000013259 calculateFCSR(fs, 0, TRUNCWS, True, 1);
dejanj0e006f22014-02-19 11:56:29 +000013260 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000013261 t0 = newTemp(Ity_I64);
13262 t1 = newTemp(Ity_I32);
13263 t3 = newTemp(Ity_F32);
13264 t4 = newTemp(Ity_F32);
13265 /* get lo half of FPR */
13266 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
13267
13268 assign(t1, unop(Iop_64to32, mkexpr(t0)));
13269
13270 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1)));
13271
13272 assign(t4, binop(Iop_RoundF32toInt, mkU32(0x3),
13273 mkexpr(t3)));
13274
13275 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4)));
dejanj8007ea62013-09-18 10:06:13 +000013276 } else
petarjb92a9542013-02-27 22:57:17 +000013277 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x3),
13278 getFReg(fs)));
13279 break;
petarjb92a9542013-02-27 22:57:17 +000013280 case 0x11: /* D */
petarj1fb1e342013-04-27 02:18:11 +000013281 DIP("trunc.w.d %d, %d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000013282 calculateFCSR(fs, 0, TRUNCWD, False, 1);
dejanj0e006f22014-02-19 11:56:29 +000013283 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000013284 t0 = newTemp(Ity_I32);
13285
13286 assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
13287 getFReg(fs)));
13288
13289 putFReg(fd, mkWidenFromF32(tyF,
13290 unop(Iop_ReinterpI32asF32, mkexpr(t0))));
petarjb92a9542013-02-27 22:57:17 +000013291 } else {
13292 t0 = newTemp(Ity_I32);
13293
13294 assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
13295 getDReg(fs)));
13296
13297 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
petarjb92a9542013-02-27 22:57:17 +000013298 }
dejanj8007ea62013-09-18 10:06:13 +000013299 break;
petarjb92a9542013-02-27 22:57:17 +000013300 default:
13301 goto decode_failure;
sewardj362cf842012-06-07 08:59:53 +000013302
13303 }
13304 break;
13305
petarjb92a9542013-02-27 22:57:17 +000013306 case 0x0E: /* CEIL.W.fmt */
sewardj362cf842012-06-07 08:59:53 +000013307 switch (fmt) {
petarjb92a9542013-02-27 22:57:17 +000013308 case 0x10: /* S */
petarj1fb1e342013-04-27 02:18:11 +000013309 DIP("ceil.w.s %d, %d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000013310 calculateFCSR(fs, 0, CEILWS, True, 1);
dejanj0e006f22014-02-19 11:56:29 +000013311 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000013312 t0 = newTemp(Ity_I64);
13313 t1 = newTemp(Ity_I32);
13314 t3 = newTemp(Ity_F32);
13315 t4 = newTemp(Ity_F32);
13316 /* get lo half of FPR */
13317 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
13318
13319 assign(t1, unop(Iop_64to32, mkexpr(t0)));
13320
13321 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1)));
13322
13323 assign(t4, binop(Iop_RoundF32toInt, mkU32(0x2),
13324 mkexpr(t3)));
13325
13326 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4)));
13327 } else
13328 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x2),
13329 getFReg(fs)));
13330 break;
13331
13332 case 0x11: /* D */
petarj1fb1e342013-04-27 02:18:11 +000013333 DIP("ceil.w.d %d, %d", fd, fs);
dejanj41833222013-11-14 15:44:42 +000013334 calculateFCSR(fs, 0, CEILWD, False, 1);
dejanj0e006f22014-02-19 11:56:29 +000013335 if (!fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000013336 t0 = newTemp(Ity_I32);
13337 assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
13338 getDReg(fs)));
13339 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
petarjb92a9542013-02-27 22:57:17 +000013340 } else {
13341 t0 = newTemp(Ity_I32);
13342 assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
13343 getDReg(fs)));
13344 putFReg(fd, mkWidenFromF32(tyF,
13345 unop(Iop_ReinterpI32asF32, mkexpr(t0))));
petarjb92a9542013-02-27 22:57:17 +000013346 }
dejanj8007ea62013-09-18 10:06:13 +000013347 break;
petarjb92a9542013-02-27 22:57:17 +000013348 default:
13349 goto decode_failure;
13350
13351 }
13352 break;
13353
13354 case 0x0A: /* CEIL.L.fmt */
13355 switch (fmt) {
13356 case 0x10: /* S */
petarj1fb1e342013-04-27 02:18:11 +000013357 DIP("ceil.l.s %d, %d", fd, fs);
dejanj0e006f22014-02-19 11:56:29 +000013358 if (fp_mode64) {
13359 calculateFCSR(fs, 0, CEILLS, True, 1);
13360 t0 = newTemp(Ity_I64);
petarjb92a9542013-02-27 22:57:17 +000013361
dejanj0e006f22014-02-19 11:56:29 +000013362 assign(t0, binop(Iop_F32toI64S, mkU32(0x2),
13363 getLoFromF64(tyF, getFReg(fs))));
petarjb92a9542013-02-27 22:57:17 +000013364
dejanj0e006f22014-02-19 11:56:29 +000013365 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
13366 } else {
13367 ILLEGAL_INSTRUCTON;
13368 }
petarjb92a9542013-02-27 22:57:17 +000013369 break;
13370
13371 case 0x11: /* D */
petarj1fb1e342013-04-27 02:18:11 +000013372 DIP("ceil.l.d %d, %d", fd, fs);
dejanj0e006f22014-02-19 11:56:29 +000013373 if (fp_mode64) {
13374 calculateFCSR(fs, 0, CEILLD, False, 1);
petarj830ef702014-10-09 01:01:57 +000013375 putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x2),
13376 getDReg(fs)));
dejanj0e006f22014-02-19 11:56:29 +000013377 } else {
13378 ILLEGAL_INSTRUCTON;
13379 }
petarjb92a9542013-02-27 22:57:17 +000013380 break;
13381
13382 default:
13383 goto decode_failure;
13384
13385 }
13386 break;
13387
13388 case 0x16: /* RSQRT.fmt */
13389 switch (fmt) {
13390 case 0x10: { /* S */
petarj1fb1e342013-04-27 02:18:11 +000013391 DIP("rsqrt.s %d, %d", fd, fs);
sewardj362cf842012-06-07 08:59:53 +000013392 IRExpr *rm = get_IR_roundingmode();
13393 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
petarj0c30de82013-04-19 12:35:00 +000013394 unop(Iop_ReinterpI32asF32, mkU32(ONE_SINGLE)),
sewardj362cf842012-06-07 08:59:53 +000013395 binop(Iop_SqrtF32, rm, getLoFromF64(tyF,
13396 getFReg(fs))))));
13397 break;
13398 }
petarjb92a9542013-02-27 22:57:17 +000013399 case 0x11: { /* D */
petarj1fb1e342013-04-27 02:18:11 +000013400 DIP("rsqrt.d %d, %d", fd, fs);
sewardj362cf842012-06-07 08:59:53 +000013401 IRExpr *rm = get_IR_roundingmode();
13402 putDReg(fd, triop(Iop_DivF64, rm,
13403 unop(Iop_ReinterpI64asF64,
petarj0c30de82013-04-19 12:35:00 +000013404 mkU64(ONE_DOUBLE)),
sewardj362cf842012-06-07 08:59:53 +000013405 binop(Iop_SqrtF64, rm, getDReg(fs))));
13406 break;
13407 }
petarjb92a9542013-02-27 22:57:17 +000013408 default:
13409 goto decode_failure;
sewardj362cf842012-06-07 08:59:53 +000013410
13411 }
13412 break;
13413
13414 default:
13415 if (dis_instr_CCondFmt(cins))
13416 break;
13417 goto decode_failure;
13418
13419 }
13420
13421 }
13422 }
petarjb92a9542013-02-27 22:57:17 +000013423 break; /* COP1 */
13424 case 0x10: /* COP0 */
13425 if (rs == 0) { /* MFC0 */
sewardj362cf842012-06-07 08:59:53 +000013426 DIP("mfc0 r%d, r%d, %d", rt, rd, sel);
sewardj362cf842012-06-07 08:59:53 +000013427 IRTemp val = newTemp(Ity_I32);
florian90419562013-08-15 20:54:52 +000013428 IRExpr** args = mkIRExprVec_3 (IRExpr_BBPTR(), mkU32(rd), mkU32(sel));
sewardj362cf842012-06-07 08:59:53 +000013429 IRDirty *d = unsafeIRDirty_1_N(val,
13430 0,
13431 "mips32_dirtyhelper_mfc0",
13432 &mips32_dirtyhelper_mfc0,
13433 args);
sewardj362cf842012-06-07 08:59:53 +000013434 stmt(IRStmt_Dirty(d));
13435 putIReg(rt, mkexpr(val));
petarjb92a9542013-02-27 22:57:17 +000013436 } else if (rs == 1) {
13437 /* Doubleword Move from Coprocessor 0 - DMFC0; MIPS64 */
13438 DIP("dmfc0 r%d, r%d, %d", rt, rd, sel);
13439 IRTemp val = newTemp(Ity_I64);
florian90419562013-08-15 20:54:52 +000013440 IRExpr** args = mkIRExprVec_3 (IRExpr_BBPTR(), mkU64(rd), mkU64(sel));
petarjb92a9542013-02-27 22:57:17 +000013441 IRDirty *d = unsafeIRDirty_1_N(val,
13442 0,
13443 "mips64_dirtyhelper_dmfc0",
13444 &mips64_dirtyhelper_dmfc0,
13445 args);
13446 stmt(IRStmt_Dirty(d));
13447 putDReg(rt, mkexpr(val));
sewardj362cf842012-06-07 08:59:53 +000013448 } else
13449 goto decode_failure;
13450 break;
sewardj362cf842012-06-07 08:59:53 +000013451
petarjb92a9542013-02-27 22:57:17 +000013452 case 0x31: /* LWC1 */
13453 /* Load Word to Floating Point - LWC1 (MIPS32) */
sewardj362cf842012-06-07 08:59:53 +000013454 DIP("lwc1 f%d, %d(r%d)", ft, imm, rs);
dejanj0e006f22014-02-19 11:56:29 +000013455 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000013456 t1 = newTemp(Ity_F32);
13457 t2 = newTemp(Ity_I64);
dejanj0e006f22014-02-19 11:56:29 +000013458 if (mode64) {
13459 t0 = newTemp(Ity_I64);
13460 /* new LO */
13461 assign(t0, binop(Iop_Add64, getIReg(rs),
13462 mkU64(extend_s_16to64(imm))));
13463 } else {
13464 t0 = newTemp(Ity_I32);
13465 /* new LO */
13466 assign(t0, binop(Iop_Add32, getIReg(rs),
13467 mkU32(extend_s_16to32(imm))));
13468 }
petarjb92a9542013-02-27 22:57:17 +000013469 assign(t1, load(Ity_F32, mkexpr(t0)));
dejanj0e006f22014-02-19 11:56:29 +000013470 assign(t2, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
13471 mkexpr(t1)), True));
13472 putDReg(ft, unop(Iop_ReinterpI64asF64, mkexpr(t2)));
petarjb92a9542013-02-27 22:57:17 +000013473 } else {
13474 t0 = newTemp(Ity_I32);
13475 assign(t0, binop(Iop_Add32, getIReg(rs),
13476 mkU32(extend_s_16to32(imm))));
13477 putFReg(ft, load(Ity_F32, mkexpr(t0)));
13478 }
sewardj362cf842012-06-07 08:59:53 +000013479 break;
13480
petarjb92a9542013-02-27 22:57:17 +000013481 case 0x39: /* SWC1 */
petarj1fb1e342013-04-27 02:18:11 +000013482 DIP("swc1 f%d, %d(r%d)", ft, imm, rs);
dejanj0e006f22014-02-19 11:56:29 +000013483 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000013484 t0 = newTemp(Ity_I64);
13485 t2 = newTemp(Ity_I32);
13486 LOAD_STORE_PATTERN;
13487 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(ft)));
13488 assign(t2, unop(Iop_64to32, mkexpr(t0)));
13489 store(mkexpr(t1), unop(Iop_ReinterpI32asF32, mkexpr(t2)));
13490 } else {
13491 LOAD_STORE_PATTERN;
13492 store(mkexpr(t1), getFReg(ft));
13493 }
sewardj362cf842012-06-07 08:59:53 +000013494 break;
13495
petarjb92a9542013-02-27 22:57:17 +000013496 case 0x33: /* PREF */
petarjc5b8bb72012-07-16 14:25:05 +000013497 DIP("pref");
sewardj362cf842012-06-07 08:59:53 +000013498 break;
13499
13500 case 0x35:
13501 /* Load Doubleword to Floating Point - LDC1 (MIPS32) */
petarjb92a9542013-02-27 22:57:17 +000013502 DIP("ldc1 f%d, %d(%d)", rt, imm, rs);
dejanj0e006f22014-02-19 11:56:29 +000013503 LOAD_STORE_PATTERN;
13504 putDReg(ft, load(Ity_F64, mkexpr(t1)));
sewardj362cf842012-06-07 08:59:53 +000013505 break;
13506
13507 case 0x3D:
13508 /* Store Doubleword from Floating Point - SDC1 */
sewardj362cf842012-06-07 08:59:53 +000013509 DIP("sdc1 f%d, %d(%d)", ft, imm, rs);
dejanj0e006f22014-02-19 11:56:29 +000013510 LOAD_STORE_PATTERN;
13511 store(mkexpr(t1), getDReg(ft));
sewardj362cf842012-06-07 08:59:53 +000013512 break;
13513
petarjb92a9542013-02-27 22:57:17 +000013514 case 0x23: /* LW */
sewardj362cf842012-06-07 08:59:53 +000013515 DIP("lw r%d, %d(r%d)", rt, imm, rs);
13516 LOAD_STORE_PATTERN;
13517 putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
13518 break;
13519
petarjb92a9542013-02-27 22:57:17 +000013520 case 0x20: /* LB */
petarjc5b8bb72012-07-16 14:25:05 +000013521 DIP("lb r%d, %d(r%d)", rt, imm, rs);
sewardj362cf842012-06-07 08:59:53 +000013522 LOAD_STORE_PATTERN;
petarjb92a9542013-02-27 22:57:17 +000013523 if (mode64)
13524 putIReg(rt, unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
13525 else
13526 putIReg(rt, unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
sewardj362cf842012-06-07 08:59:53 +000013527 break;
13528
petarjb92a9542013-02-27 22:57:17 +000013529 case 0x24: /* LBU */
petarjc5b8bb72012-07-16 14:25:05 +000013530 DIP("lbu r%d, %d(r%d)", rt, imm, rs);
sewardj362cf842012-06-07 08:59:53 +000013531 LOAD_STORE_PATTERN;
petarjb92a9542013-02-27 22:57:17 +000013532 if (mode64)
13533 putIReg(rt, unop(Iop_8Uto64, load(Ity_I8, mkexpr(t1))));
13534 else
13535 putIReg(rt, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t1))));
sewardj362cf842012-06-07 08:59:53 +000013536 break;
13537
petarjb92a9542013-02-27 22:57:17 +000013538 case 0x21: /* LH */
petarjc5b8bb72012-07-16 14:25:05 +000013539 DIP("lh r%d, %d(r%d)", rt, imm, rs);
sewardj362cf842012-06-07 08:59:53 +000013540 LOAD_STORE_PATTERN;
petarjb92a9542013-02-27 22:57:17 +000013541 if (mode64)
13542 putIReg(rt, unop(Iop_16Sto64, load(Ity_I16, mkexpr(t1))));
13543 else
13544 putIReg(rt, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t1))));
sewardj362cf842012-06-07 08:59:53 +000013545 break;
13546
petarjb92a9542013-02-27 22:57:17 +000013547 case 0x25: /* LHU */
petarjc5b8bb72012-07-16 14:25:05 +000013548 DIP("lhu r%d, %d(r%d)", rt, imm, rs);
sewardj362cf842012-06-07 08:59:53 +000013549 LOAD_STORE_PATTERN;
petarjb92a9542013-02-27 22:57:17 +000013550 if (mode64)
13551 putIReg(rt, unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
13552 else
13553 putIReg(rt, unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
sewardj362cf842012-06-07 08:59:53 +000013554 break;
13555
petarjb92a9542013-02-27 22:57:17 +000013556 case 0x0F: /* LUI */
sewardj362cf842012-06-07 08:59:53 +000013557 p = (imm << 16);
petarj1fb1e342013-04-27 02:18:11 +000013558 DIP("lui r%d, imm: 0x%x", rt, imm);
petarjb92a9542013-02-27 22:57:17 +000013559 if (mode64)
13560 putIReg(rt, mkU64(extend_s_32to64(p)));
13561 else
13562 putIReg(rt, mkU32(p));
sewardj362cf842012-06-07 08:59:53 +000013563 break;
13564
petarjb92a9542013-02-27 22:57:17 +000013565 case 0x13: /* COP1X */
sewardj362cf842012-06-07 08:59:53 +000013566 switch (function) {
petarjb92a9542013-02-27 22:57:17 +000013567 case 0x0: { /* LWXC1 */
sewardj362cf842012-06-07 08:59:53 +000013568 /* Load Word Indexed to Floating Point - LWXC1 (MIPS32r2) */
petarj1fb1e342013-04-27 02:18:11 +000013569 DIP("lwxc1 f%d, r%d(r%d)", fd, rt, rs);
dejanj0e006f22014-02-19 11:56:29 +000013570 if (fp_mode64) {
petarjb92a9542013-02-27 22:57:17 +000013571 t0 = newTemp(Ity_I64);
13572 t1 = newTemp(Ity_I32);
petarjb92a9542013-02-27 22:57:17 +000013573 t3 = newTemp(Ity_F32);
13574 t4 = newTemp(Ity_I64);
13575
dejanj0e006f22014-02-19 11:56:29 +000013576 t2 = newTemp(ty);
petarjb92a9542013-02-27 22:57:17 +000013577 /* new LO */
dejanj0e006f22014-02-19 11:56:29 +000013578 assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
13579 getIReg(rt)));
petarjb92a9542013-02-27 22:57:17 +000013580 assign(t3, load(Ity_F32, mkexpr(t2)));
13581
dejanj0e006f22014-02-19 11:56:29 +000013582 assign(t4, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
13583 mkexpr(t3)), True));
petarjb92a9542013-02-27 22:57:17 +000013584
13585 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t4)));
13586 } else {
13587 t0 = newTemp(Ity_I32);
13588 assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
13589 putFReg(fd, load(Ity_F32, mkexpr(t0)));
13590 }
sewardj362cf842012-06-07 08:59:53 +000013591 break;
13592 }
13593
petarjb92a9542013-02-27 22:57:17 +000013594 case 0x1: { /* LDXC1 */
dejanjc3fee0d2013-07-25 09:08:03 +000013595 /* Load Doubleword Indexed to Floating Point
petarjb92a9542013-02-27 22:57:17 +000013596 LDXC1 (MIPS32r2 and MIPS64) */
dejanj0e006f22014-02-19 11:56:29 +000013597 if (fp_mode64) {
petarj1fb1e342013-04-27 02:18:11 +000013598 DIP("ldxc1 f%d, r%d(r%d)", fd, rt, rs);
dejanj0e006f22014-02-19 11:56:29 +000013599 t0 = newTemp(ty);
13600 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
13601 getIReg(rt)));
petarjb92a9542013-02-27 22:57:17 +000013602 putFReg(fd, load(Ity_F64, mkexpr(t0)));
13603 break;
13604 } else {
13605 t0 = newTemp(Ity_I32);
13606 assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
sewardj362cf842012-06-07 08:59:53 +000013607
petarjb92a9542013-02-27 22:57:17 +000013608 t1 = newTemp(Ity_I32);
13609 assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4)));
sewardj362cf842012-06-07 08:59:53 +000013610
13611#if defined (_MIPSEL)
petarjb92a9542013-02-27 22:57:17 +000013612 putFReg(fd, load(Ity_F32, mkexpr(t0)));
13613 putFReg(fd + 1, load(Ity_F32, mkexpr(t1)));
sewardj362cf842012-06-07 08:59:53 +000013614#elif defined (_MIPSEB)
petarjb92a9542013-02-27 22:57:17 +000013615 putFReg(fd + 1, load(Ity_F32, mkexpr(t0)));
13616 putFReg(fd, load(Ity_F32, mkexpr(t1)));
sewardj362cf842012-06-07 08:59:53 +000013617#endif
petarjb92a9542013-02-27 22:57:17 +000013618 break;
13619 }
sewardj362cf842012-06-07 08:59:53 +000013620 }
13621
petarjb92a9542013-02-27 22:57:17 +000013622 case 0x5: /* Load Doubleword Indexed Unaligned to Floating Point - LUXC1;
13623 MIPS32r2 */
petarj1fb1e342013-04-27 02:18:11 +000013624 DIP("luxc1 f%d, r%d(r%d)", fd, rt, rs);
sewardj362cf842012-06-07 08:59:53 +000013625 t0 = newTemp(Ity_I64);
13626 t1 = newTemp(Ity_I64);
13627 assign(t0, binop(Iop_Add64, getIReg(rs), getIReg(rt)));
petarjb92a9542013-02-27 22:57:17 +000013628 assign(t1, binop(Iop_And64, mkexpr(t0),
13629 mkU64(0xfffffffffffffff8ULL)));
sewardj362cf842012-06-07 08:59:53 +000013630 putFReg(fd, load(Ity_F64, mkexpr(t1)));
13631 break;
13632
petarjb92a9542013-02-27 22:57:17 +000013633 case 0x8: { /* Store Word Indexed from Floating Point - SWXC1 */
sewardj362cf842012-06-07 08:59:53 +000013634 DIP("swxc1 f%d, r%d(r%d)", ft, rt, rs);
dejanj0e006f22014-02-19 11:56:29 +000013635 if (fp_mode64) {
13636 t0 = newTemp(ty);
13637 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
13638 getIReg(rt)));
petarjb92a9542013-02-27 22:57:17 +000013639 store(mkexpr(t0), getLoFromF64(tyF, getFReg(fs)));
13640
13641 } else {
13642 t0 = newTemp(Ity_I32);
13643 assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
13644
13645 store(mkexpr(t0), getFReg(fs));
13646 }
sewardj362cf842012-06-07 08:59:53 +000013647 break;
13648 }
petarjb92a9542013-02-27 22:57:17 +000013649 case 0x9: { /* Store Doubleword Indexed from Floating Point - SDXC1 */
13650 DIP("sdc1 f%d, %d(%d)", ft, imm, rs);
dejanj0e006f22014-02-19 11:56:29 +000013651 if (fp_mode64) {
13652 t0 = newTemp(ty);
13653 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
13654 getIReg(rt)));
petarjb92a9542013-02-27 22:57:17 +000013655 store(mkexpr(t0), getFReg(fs));
13656 } else {
13657 t0 = newTemp(Ity_I32);
13658 assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt)));
sewardj362cf842012-06-07 08:59:53 +000013659
petarjb92a9542013-02-27 22:57:17 +000013660 t1 = newTemp(Ity_I32);
13661 assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4)));
sewardj362cf842012-06-07 08:59:53 +000013662
13663#if defined (_MIPSEL)
petarjb92a9542013-02-27 22:57:17 +000013664 store(mkexpr(t0), getFReg(fs));
13665 store(mkexpr(t1), getFReg(fs + 1));
sewardj362cf842012-06-07 08:59:53 +000013666#elif defined (_MIPSEB)
petarjb92a9542013-02-27 22:57:17 +000013667 store(mkexpr(t0), getFReg(fs + 1));
13668 store(mkexpr(t1), getFReg(fs));
sewardj362cf842012-06-07 08:59:53 +000013669#endif
petarjb92a9542013-02-27 22:57:17 +000013670 }
sewardj362cf842012-06-07 08:59:53 +000013671 break;
13672 }
dejanjc3fee0d2013-07-25 09:08:03 +000013673 case 0xD: /* Store Doubleword Indexed Unaligned from Floating Point -
petarjb92a9542013-02-27 22:57:17 +000013674 SUXC1; MIPS64 MIPS32r2 */
petarj1fb1e342013-04-27 02:18:11 +000013675 DIP("suxc1 f%d, r%d(r%d)", fd, rt, rs);
petarjb92a9542013-02-27 22:57:17 +000013676 t0 = newTemp(Ity_I64);
13677 t1 = newTemp(Ity_I64);
13678 assign(t0, binop(Iop_Add64, getIReg(rs), getIReg(rt)));
petarjfdb2a4c2013-03-02 02:37:01 +000013679 assign(t1, binop(Iop_And64, mkexpr(t0), mkU64(0xfffffffffffffff8ULL)));
petarjb92a9542013-02-27 22:57:17 +000013680 store(mkexpr(t1), getFReg(fs));
13681 break;
13682
sewardj362cf842012-06-07 08:59:53 +000013683 case 0x0F: {
13684 DIP("prefx");
13685 break;
13686 }
petarjb92a9542013-02-27 22:57:17 +000013687 case 0x20: { /* MADD.S */
13688 DIP("madd.s f%d, f%d, f%d, f%d", fd, fmt, fs, ft);
sewardj362cf842012-06-07 08:59:53 +000013689 IRExpr *rm = get_IR_roundingmode();
13690 t1 = newTemp(Ity_F32);
petarjb92a9542013-02-27 22:57:17 +000013691 assign(t1, qop(Iop_MAddF32, rm,
13692 getLoFromF64(tyF, getFReg(fmt)),
13693 getLoFromF64(tyF, getFReg(fs)),
13694 getLoFromF64(tyF, getFReg(ft))));
13695 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
13696 break; /* MADD.S */
sewardj362cf842012-06-07 08:59:53 +000013697 }
petarjb92a9542013-02-27 22:57:17 +000013698 case 0x21: { /* MADD.D */
13699 DIP("madd.d f%d, f%d, f%d, f%d", fd, fmt, fs, ft);
sewardj362cf842012-06-07 08:59:53 +000013700 IRExpr *rm = get_IR_roundingmode();
petarjb92a9542013-02-27 22:57:17 +000013701 putDReg(fd, qop(Iop_MAddF64, rm, getDReg(fmt), getDReg(fs),
13702 getDReg(ft)));
13703 break; /* MADD.D */
sewardj362cf842012-06-07 08:59:53 +000013704 }
petarjb92a9542013-02-27 22:57:17 +000013705 case 0x28: { /* MSUB.S */
13706 DIP("msub.s f%d, f%d, f%d, f%d", fd, fmt, fs, ft);
sewardj362cf842012-06-07 08:59:53 +000013707 IRExpr *rm = get_IR_roundingmode();
13708 t1 = newTemp(Ity_F32);
petarjb92a9542013-02-27 22:57:17 +000013709 assign(t1, qop(Iop_MSubF32, rm,
13710 getLoFromF64(tyF, getFReg(fmt)),
13711 getLoFromF64(tyF, getFReg(fs)),
13712 getLoFromF64(tyF, getFReg(ft))));
13713 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
13714 break; /* MSUB.S */
sewardj362cf842012-06-07 08:59:53 +000013715 }
petarjb92a9542013-02-27 22:57:17 +000013716 case 0x29: { /* MSUB.D */
13717 DIP("msub.d f%d, f%d, f%d, f%d", fd, fmt, fs, ft);
sewardj362cf842012-06-07 08:59:53 +000013718 IRExpr *rm = get_IR_roundingmode();
petarjb92a9542013-02-27 22:57:17 +000013719 putDReg(fd, qop(Iop_MSubF64, rm, getDReg(fmt), getDReg(fs),
13720 getDReg(ft)));
13721 break; /* MSUB.D */
sewardj362cf842012-06-07 08:59:53 +000013722 }
petarjb92a9542013-02-27 22:57:17 +000013723 case 0x30: { /* NMADD.S */
13724 DIP("nmadd.s f%d, f%d, f%d, f%d", fd, fmt, fs, ft);
sewardj362cf842012-06-07 08:59:53 +000013725 IRExpr *rm = get_IR_roundingmode();
13726 t1 = newTemp(Ity_F32);
petarjb92a9542013-02-27 22:57:17 +000013727 assign(t1, qop(Iop_MAddF32, rm,
13728 getLoFromF64(tyF, getFReg(fmt)),
13729 getLoFromF64(tyF, getFReg(fs)),
13730 getLoFromF64(tyF, getFReg(ft))));
sewardj362cf842012-06-07 08:59:53 +000013731
petarjb92a9542013-02-27 22:57:17 +000013732 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
13733 break; /* NMADD.S */
sewardj362cf842012-06-07 08:59:53 +000013734 }
petarjb92a9542013-02-27 22:57:17 +000013735 case 0x31: { /* NMADD.D */
13736 DIP("nmadd.d f%d, f%d, f%d, f%d", fd, fmt, fs, ft);
sewardj362cf842012-06-07 08:59:53 +000013737 IRExpr *rm = get_IR_roundingmode();
13738 t1 = newTemp(Ity_F64);
petarjb92a9542013-02-27 22:57:17 +000013739 assign(t1, qop(Iop_MAddF64, rm, getDReg(fmt), getDReg(fs),
13740 getDReg(ft)));
13741 putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
13742 break; /* NMADD.D */
sewardj362cf842012-06-07 08:59:53 +000013743 }
petarjb92a9542013-02-27 22:57:17 +000013744 case 0x38: { /* NMSUBB.S */
13745 DIP("nmsub.s f%d, f%d, f%d, f%d", fd, fmt, fs, ft);
sewardj362cf842012-06-07 08:59:53 +000013746 IRExpr *rm = get_IR_roundingmode();
13747 t1 = newTemp(Ity_F32);
petarjb92a9542013-02-27 22:57:17 +000013748 assign(t1, qop(Iop_MSubF32, rm,
13749 getLoFromF64(tyF, getFReg(fmt)),
13750 getLoFromF64(tyF, getFReg(fs)),
13751 getLoFromF64(tyF, getFReg(ft))));
sewardj362cf842012-06-07 08:59:53 +000013752
petarjb92a9542013-02-27 22:57:17 +000013753 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
13754 break; /* NMSUBB.S */
sewardj362cf842012-06-07 08:59:53 +000013755 }
petarjb92a9542013-02-27 22:57:17 +000013756 case 0x39: { /* NMSUBB.D */
13757 DIP("nmsub.d f%d, f%d, f%d, f%d", fd, fmt, fs, ft);
sewardj362cf842012-06-07 08:59:53 +000013758 IRExpr *rm = get_IR_roundingmode();
13759 t1 = newTemp(Ity_F64);
petarjb92a9542013-02-27 22:57:17 +000013760 assign(t1, qop(Iop_MSubF64, rm, getDReg(fmt), getDReg(fs),
13761 getDReg(ft)));
13762 putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
13763 break; /* NMSUBB.D */
sewardj362cf842012-06-07 08:59:53 +000013764 }
13765
13766 default:
13767 goto decode_failure;
13768 }
13769 break;
13770
petarjb92a9542013-02-27 22:57:17 +000013771 case 0x22: /* LWL */
petarjc5b8bb72012-07-16 14:25:05 +000013772 DIP("lwl r%d, %d(r%d)", rt, imm, rs);
petarjb92a9542013-02-27 22:57:17 +000013773 if (mode64) {
13774 /* t1 = addr */
petarj0c30de82013-04-19 12:35:00 +000013775 t1 = newTemp(Ity_I64);
petarjb92a9542013-02-27 22:57:17 +000013776#if defined (_MIPSEL)
petarjb92a9542013-02-27 22:57:17 +000013777 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
petarjb92a9542013-02-27 22:57:17 +000013778 /* t2 = word addr */
13779 /* t4 = addr mod 4 */
13780 LWX_SWX_PATTERN64;
13781
13782 /* t3 = word content - shifted */
13783 t3 = newTemp(Ity_I32);
13784 assign(t3, binop(Iop_Shl32, mkNarrowTo32(ty, load(Ity_I64,
13785 mkexpr(t2))), narrowTo(Ity_I8, binop(Iop_Shl32,
13786 binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)), mkU8(3)))));
13787
petarj0c30de82013-04-19 12:35:00 +000013788 /* rt content - adjusted */
petarjb92a9542013-02-27 22:57:17 +000013789 t5 = newTemp(Ity_I32);
dejanje3a103f2013-09-02 15:35:58 +000013790 assign(t5, binop(Iop_And32,
13791 mkNarrowTo32(ty, getIReg(rt)),
13792 binop(Iop_Shr32,
13793 mkU32(0x00FFFFFF),
13794 narrowTo(Ity_I8, binop(Iop_Mul32,
13795 mkU32(0x08),
13796 mkexpr(t4))))));
petarjb92a9542013-02-27 22:57:17 +000013797
13798 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
13799 mkexpr(t3)), True));
petarj0c30de82013-04-19 12:35:00 +000013800#elif defined (_MIPSEB)
13801 assign(t1, binop(Iop_Xor64, mkU64(0x3),
13802 binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))));
13803 /* t2 = word addr */
13804 /* t4 = addr mod 4 */
13805 LWX_SWX_PATTERN64;
13806
13807 /* t3 = word content - shifted */
13808 t3 = newTemp(Ity_I32);
13809 assign(t3, binop(Iop_Shl32, unop(Iop_64HIto32, load(Ity_I64,
13810 mkexpr(t2))), narrowTo(Ity_I8, binop(Iop_Shl32,
13811 binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)), mkU8(3)))));
13812
13813 /* rt content - adjusted */
13814 t5 = newTemp(Ity_I32);
dejanje3a103f2013-09-02 15:35:58 +000013815 assign(t5, binop(Iop_And32,
13816 mkNarrowTo32(ty, getIReg(rt)),
13817 binop(Iop_Shr32,
13818 mkU32(0x00FFFFFF),
13819 narrowTo(Ity_I8, binop(Iop_Mul32,
13820 mkU32(0x08),
13821 mkexpr(t4))))));
petarj0c30de82013-04-19 12:35:00 +000013822
13823 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
13824 mkexpr(t3)), True));
13825#endif
petarjb92a9542013-02-27 22:57:17 +000013826 } else {
sewardj362cf842012-06-07 08:59:53 +000013827 /* t1 = addr */
13828 t1 = newTemp(Ity_I32);
13829#if defined (_MIPSEL)
13830 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
13831#elif defined (_MIPSEB)
13832 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
13833 mkU32(extend_s_16to32(imm)))));
13834#endif
13835
13836 /* t2 = word addr */
dejanje3a103f2013-09-02 15:35:58 +000013837 /* t4 = addr mod 4 */
sewardj362cf842012-06-07 08:59:53 +000013838 LWX_SWX_PATTERN;
13839
13840 /* t3 = word content - shifted */
13841 t3 = newTemp(Ity_I32);
13842 assign(t3, binop(Iop_Shl32, load(Ity_I32, mkexpr(t2)), narrowTo(Ity_I8,
13843 binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)),
13844 mkU8(3)))));
13845
13846 /* rt content - adjusted */
13847 t5 = newTemp(Ity_I32);
dejanje3a103f2013-09-02 15:35:58 +000013848 assign(t5, binop(Iop_And32,
13849 getIReg(rt),
13850 binop(Iop_Shr32,
13851 mkU32(0x00FFFFFF),
13852 narrowTo(Ity_I8, binop(Iop_Mul32,
13853 mkU32(0x08),
13854 mkexpr(t4))))));
sewardj362cf842012-06-07 08:59:53 +000013855
13856 putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
13857 }
13858 break;
13859
petarjb92a9542013-02-27 22:57:17 +000013860 case 0x26: /* LWR */
petarjc5b8bb72012-07-16 14:25:05 +000013861 DIP("lwr r%d, %d(r%d)", rt, imm, rs);
petarjb92a9542013-02-27 22:57:17 +000013862 if (mode64) {
13863 /* t1 = addr */
petarj0c30de82013-04-19 12:35:00 +000013864 t1 = newTemp(Ity_I64);
petarjb92a9542013-02-27 22:57:17 +000013865#if defined (_MIPSEL)
petarjb92a9542013-02-27 22:57:17 +000013866 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
petarjb92a9542013-02-27 22:57:17 +000013867 /* t2 = word addr */
petarj0c30de82013-04-19 12:35:00 +000013868 /* t4 = addr mod 8 */
petarjb92a9542013-02-27 22:57:17 +000013869 LWX_SWX_PATTERN64;
13870
13871 /* t3 = word content - shifted */
13872 t3 = newTemp(Ity_I32);
13873 assign(t3, binop(Iop_Shr32, mkNarrowTo32(ty, load(Ity_I64,mkexpr(t2))),
13874 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(3)))));
13875
13876 /* rt content - adjusted */
13877 t5 = newTemp(Ity_I32);
13878 assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
13879 unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF),
13880 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
13881
13882 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
13883 mkexpr(t3)), True));
petarj0c30de82013-04-19 12:35:00 +000013884#elif defined (_MIPSEB)
13885 assign(t1, binop(Iop_Xor64, mkU64(0x3), binop(Iop_Add64, getIReg(rs),
13886 mkU64(extend_s_16to64(imm)))));
13887 /* t2 = word addr */
13888 /* t4 = addr mod 4 */
13889 LWX_SWX_PATTERN64;
13890
13891 /* t3 = word content - shifted */
13892 t3 = newTemp(Ity_I32);
13893 assign(t3, binop(Iop_Shr32, unop(Iop_64HIto32, load(Ity_I64,mkexpr(t2))),
13894 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(3)))));
13895
13896 /* rt content - adjusted */
13897 t5 = newTemp(Ity_I32);
dejanje3a103f2013-09-02 15:35:58 +000013898 assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
petarj0c30de82013-04-19 12:35:00 +000013899 unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF),
13900 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
13901
13902 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
13903 mkexpr(t3)), True));
13904#endif
13905
petarjb92a9542013-02-27 22:57:17 +000013906 } else {
sewardj362cf842012-06-07 08:59:53 +000013907 /* t1 = addr */
13908 t1 = newTemp(Ity_I32);
13909#if defined (_MIPSEL)
13910 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
13911#elif defined (_MIPSEB)
13912 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
13913 mkU32(extend_s_16to32(imm)))));
13914#endif
13915
13916 /* t2 = word addr */
13917 /* t4 = addr mod 4 */
13918 LWX_SWX_PATTERN;
13919
13920 /* t3 = word content - shifted */
13921 t3 = newTemp(Ity_I32);
13922 assign(t3, binop(Iop_Shr32, load(Ity_I32, mkexpr(t2)),
13923 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4),
13924 mkU8(3)))));
13925
13926 /* rt content - adjusted */
13927 t5 = newTemp(Ity_I32);
13928 assign(t5, binop(Iop_And32, getIReg(rt), unop(Iop_Not32,
13929 binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
13930 binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
13931
13932 putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
13933 }
13934 break;
13935
petarjb92a9542013-02-27 22:57:17 +000013936 case 0x2B: /* SW */
sewardj362cf842012-06-07 08:59:53 +000013937 DIP("sw r%d, %d(r%d)", rt, imm, rs);
13938 LOAD_STORE_PATTERN;
13939 store(mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)));
13940 break;
13941
petarjb92a9542013-02-27 22:57:17 +000013942 case 0x2C: { /* SDL rt, offset(base) MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +000013943 DIP("sdl r%u, %d(r%u)", rt, (Int) imm, rs);
petarjccd78cd2013-05-31 15:09:56 +000013944 vassert(mode64);
13945 IRTemp A_byte = newTemp(Ity_I8);
13946 IRTemp B_byte = newTemp(Ity_I8);
13947 IRTemp C_byte = newTemp(Ity_I8);
13948 IRTemp D_byte = newTemp(Ity_I8);
13949 IRTemp E_byte = newTemp(Ity_I8);
13950 IRTemp F_byte = newTemp(Ity_I8);
13951 IRTemp G_byte = newTemp(Ity_I8);
13952 IRTemp H_byte = newTemp(Ity_I8);
13953 IRTemp B_pos = newTemp(Ity_I64);
13954 IRTemp C_pos = newTemp(Ity_I64);
13955 IRTemp D_pos = newTemp(Ity_I64);
13956 IRTemp E_pos = newTemp(Ity_I64);
13957 IRTemp F_pos = newTemp(Ity_I64);
13958 IRTemp G_pos = newTemp(Ity_I64);
13959
13960 /* H byte */
13961 assign(H_byte, getByteFromReg(rt, 0));
13962 /* G byte */
13963 assign(G_byte, getByteFromReg(rt, 1));
13964 /* F byte */
13965 assign(F_byte, getByteFromReg(rt, 2));
13966 /* E byte */
13967 assign(E_byte, getByteFromReg(rt, 3));
13968 /* D byte */
13969 assign(D_byte, getByteFromReg(rt, 4));
13970 /* C byte */
13971 assign(C_byte, getByteFromReg(rt, 5));
13972 /* B byte */
13973 assign(B_byte, getByteFromReg(rt, 6));
13974 /* A byte */
13975 assign(A_byte, getByteFromReg(rt, 7));
13976
petarjb92a9542013-02-27 22:57:17 +000013977 /* t1 = addr */
petarjb92a9542013-02-27 22:57:17 +000013978 t1 = newTemp(Ity_I64);
13979 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
petarjb92a9542013-02-27 22:57:17 +000013980
13981 /* t2 = word addr */
petarjccd78cd2013-05-31 15:09:56 +000013982 t2 = newTemp(Ity_I64);
13983 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
petarjb92a9542013-02-27 22:57:17 +000013984
petarjccd78cd2013-05-31 15:09:56 +000013985 /* t3 = addr mod 7 */
petarjb92a9542013-02-27 22:57:17 +000013986 t3 = newTemp(Ity_I64);
petarjccd78cd2013-05-31 15:09:56 +000013987 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
petarjb92a9542013-02-27 22:57:17 +000013988
petarjccd78cd2013-05-31 15:09:56 +000013989#if defined (_MIPSEL)
13990 /* Calculate X_byte position. */
13991 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x1)),
13992 mkU64(0x0),
13993 mkU64(0x1)));
petarjb92a9542013-02-27 22:57:17 +000013994
petarjccd78cd2013-05-31 15:09:56 +000013995 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x2)),
13996 mkU64(0x0),
13997 mkU64(0x2)));
petarjb92a9542013-02-27 22:57:17 +000013998
petarjccd78cd2013-05-31 15:09:56 +000013999 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
14000 mkU64(0x0),
14001 mkU64(0x3)));
14002
14003 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
14004 mkU64(0x0),
14005 mkU64(0x4)));
14006
14007 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
14008 mkU64(0x0),
14009 mkU64(0x5)));
14010
14011 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
14012 mkU64(0x1),
14013 mkU64(0x0)));
14014
14015 /* Store X_byte on the right place. */
14016 store(mkexpr(t2), mkexpr(H_byte));
14017 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
14018 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
14019 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
14020 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
14021 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
14022 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
14023 store(mkexpr(t1), mkexpr(A_byte));
14024
petarj70a26062013-06-09 16:46:14 +000014025#else /* _MIPSEB */
petarjccd78cd2013-05-31 15:09:56 +000014026 /* Calculate X_byte position. */
14027 assign(B_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
14028 mkU64(0x0),
14029 mkU64(0x1)));
14030
14031 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x6)),
14032 mkU64(0x2),
14033 mkU64(0x0)));
14034
14035 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
14036 mkU64(0x3),
14037 mkU64(0x0)));
14038
14039 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
14040 mkU64(0x4),
14041 mkU64(0x0)));
dejanjc3fee0d2013-07-25 09:08:03 +000014042
petarjccd78cd2013-05-31 15:09:56 +000014043 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
14044 mkU64(0x5),
14045 mkU64(0x0)));
14046
14047 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
14048 mkU64(0x6),
14049 mkU64(0x7)));
14050
14051 /* Store X_byte on the right place. */
14052 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(H_byte));
14053 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
14054 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
14055 store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
14056 store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
14057 store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
14058 store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
14059 store(mkexpr(t1), mkexpr(A_byte));
14060#endif
14061
petarjb92a9542013-02-27 22:57:17 +000014062 break;
14063 }
14064
14065 case 0x2D: {
14066 /* SDR rt, offset(base) - MIPS64 */
14067 vassert(mode64);
petarj1fb1e342013-04-27 02:18:11 +000014068 DIP("sdr r%u, %d(r%u)", rt, imm, rs);
petarjccd78cd2013-05-31 15:09:56 +000014069 IRTemp A_byte = newTemp(Ity_I8);
14070 IRTemp B_byte = newTemp(Ity_I8);
14071 IRTemp C_byte = newTemp(Ity_I8);
14072 IRTemp D_byte = newTemp(Ity_I8);
14073 IRTemp E_byte = newTemp(Ity_I8);
14074 IRTemp F_byte = newTemp(Ity_I8);
14075 IRTemp G_byte = newTemp(Ity_I8);
14076 IRTemp H_byte = newTemp(Ity_I8);
14077 IRTemp B_pos = newTemp(Ity_I64);
14078 IRTemp C_pos = newTemp(Ity_I64);
14079 IRTemp D_pos = newTemp(Ity_I64);
14080 IRTemp E_pos = newTemp(Ity_I64);
14081 IRTemp F_pos = newTemp(Ity_I64);
14082 IRTemp G_pos = newTemp(Ity_I64);
14083
14084 /* H byte */
14085 assign(H_byte, getByteFromReg(rt, 0));
14086 /* G byte */
14087 assign(G_byte, getByteFromReg(rt, 1));
14088 /* F byte */
14089 assign(F_byte, getByteFromReg(rt, 2));
14090 /* E byte */
14091 assign(E_byte, getByteFromReg(rt, 3));
14092 /* D byte */
14093 assign(D_byte, getByteFromReg(rt, 4));
14094 /* C byte */
14095 assign(C_byte, getByteFromReg(rt, 5));
14096 /* B byte */
14097 assign(B_byte, getByteFromReg(rt, 6));
14098 /* A byte */
14099 assign(A_byte, getByteFromReg(rt, 7));
14100
petarjb92a9542013-02-27 22:57:17 +000014101 /* t1 = addr */
petarjb92a9542013-02-27 22:57:17 +000014102 t1 = newTemp(Ity_I64);
14103 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
petarjb92a9542013-02-27 22:57:17 +000014104
14105 /* t2 = word addr */
petarjccd78cd2013-05-31 15:09:56 +000014106 t2 = newTemp(Ity_I64);
14107 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
petarjb92a9542013-02-27 22:57:17 +000014108
petarjccd78cd2013-05-31 15:09:56 +000014109 /* t3 = addr mod 7 */
petarjb92a9542013-02-27 22:57:17 +000014110 t3 = newTemp(Ity_I64);
petarjccd78cd2013-05-31 15:09:56 +000014111 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
petarjb92a9542013-02-27 22:57:17 +000014112
petarjccd78cd2013-05-31 15:09:56 +000014113#if defined (_MIPSEL)
14114 /* Calculate X_byte position. */
14115 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
14116 mkU64(0x0),
14117 mkU64(0x6)));
petarjb92a9542013-02-27 22:57:17 +000014118
petarjccd78cd2013-05-31 15:09:56 +000014119 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
14120 mkU64(0x0),
14121 mkU64(0x5)));
14122
14123 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
14124 mkU64(0x0),
14125 mkU64(0x4)));
14126
14127 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
14128 mkU64(0x0),
14129 mkU64(0x3)));
14130
14131 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
14132 mkU64(0x0),
14133 mkU64(0x2)));
14134
14135 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
14136 mkU64(0x0),
14137 mkU64(0x1)));
14138
14139 /* Store X_byte on the right place. */
14140 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(A_byte));
14141 store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
14142 store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
14143 store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
14144 store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
14145 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
14146 store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
14147 store(mkexpr(t1), mkexpr(H_byte));
14148
petarj70a26062013-06-09 16:46:14 +000014149#else /* _MIPSEB */
petarjccd78cd2013-05-31 15:09:56 +000014150 /* Calculate X_byte position. */
14151 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
14152 mkU64(0x6),
14153 mkU64(0x0)));
14154
14155 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
14156 mkU64(0x5),
14157 mkU64(0x0)));
14158
14159 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
14160 mkU64(0x4),
14161 mkU64(0x0)));
14162
14163 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
14164 mkU64(0x3),
14165 mkU64(0x0)));
14166
14167 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
14168 mkU64(0x2),
14169 mkU64(0x0)));
14170
14171 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
14172 mkU64(0x0),
14173 mkU64(0x1)));
14174
14175 /* Store X_byte on the right place. */
14176 store(mkexpr(t2), mkexpr(A_byte));
14177 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
14178 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
14179 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
14180 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
14181 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
14182 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
14183 store(mkexpr(t1), mkexpr(H_byte));
14184#endif
14185 break;
petarjb92a9542013-02-27 22:57:17 +000014186 }
14187
14188 case 0x28: /* SB */
petarjc5b8bb72012-07-16 14:25:05 +000014189 DIP("sb r%d, %d(r%d)", rt, imm, rs);
sewardj362cf842012-06-07 08:59:53 +000014190 LOAD_STORE_PATTERN;
14191 store(mkexpr(t1), narrowTo(Ity_I8, getIReg(rt)));
14192 break;
14193
petarjb92a9542013-02-27 22:57:17 +000014194 case 0x29: /* SH */
petarjc5b8bb72012-07-16 14:25:05 +000014195 DIP("sh r%d, %d(r%d)", rt, imm, rs);
sewardj362cf842012-06-07 08:59:53 +000014196 LOAD_STORE_PATTERN;
14197 store(mkexpr(t1), narrowTo(Ity_I16, getIReg(rt)));
14198 break;
14199
petarjb92a9542013-02-27 22:57:17 +000014200 case 0x2A: /* SWL */
petarjc5b8bb72012-07-16 14:25:05 +000014201 DIP("swl r%d, %d(r%d)", rt, imm, rs);
petarjb92a9542013-02-27 22:57:17 +000014202 if (mode64) {
petarjccd78cd2013-05-31 15:09:56 +000014203 IRTemp E_byte = newTemp(Ity_I8);
14204 IRTemp F_byte = newTemp(Ity_I8);
14205 IRTemp G_byte = newTemp(Ity_I8);
14206 IRTemp H_byte = newTemp(Ity_I8);
14207 IRTemp F_pos = newTemp(Ity_I64);
14208 IRTemp G_pos = newTemp(Ity_I64);
14209
14210 /* H byte */
14211 assign(H_byte, getByteFromReg(rt, 0));
14212 /* G byte */
14213 assign(G_byte, getByteFromReg(rt, 1));
14214 /* F byte */
14215 assign(F_byte, getByteFromReg(rt, 2));
14216 /* E byte */
14217 assign(E_byte, getByteFromReg(rt, 3));
14218
14219 /* t1 = addr */
petarjb92a9542013-02-27 22:57:17 +000014220 t1 = newTemp(Ity_I64);
14221 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
petarjccd78cd2013-05-31 15:09:56 +000014222
petarjb92a9542013-02-27 22:57:17 +000014223 /* t2 = word addr */
petarjccd78cd2013-05-31 15:09:56 +000014224 t2 = newTemp(Ity_I64);
14225 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
petarjb92a9542013-02-27 22:57:17 +000014226
petarjccd78cd2013-05-31 15:09:56 +000014227 /* t3 = addr mod 4 */
14228 t3 = newTemp(Ity_I64);
14229 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
petarjb92a9542013-02-27 22:57:17 +000014230
petarjccd78cd2013-05-31 15:09:56 +000014231#if defined (_MIPSEL)
14232 /* Calculate X_byte position. */
14233 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
14234 mkU64(0x0),
14235 mkU64(0x1)));
petarjb92a9542013-02-27 22:57:17 +000014236
petarjccd78cd2013-05-31 15:09:56 +000014237 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
14238 mkU64(0x1),
14239 mkU64(0x0)));
petarjb92a9542013-02-27 22:57:17 +000014240
petarjccd78cd2013-05-31 15:09:56 +000014241 /* Store X_byte on the right place. */
14242 store(mkexpr(t2), mkexpr(H_byte));
14243 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
14244 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
14245 store(mkexpr(t1), mkexpr(E_byte));
14246
petarj70a26062013-06-09 16:46:14 +000014247#else /* _MIPSEB */
petarjccd78cd2013-05-31 15:09:56 +000014248 /* Calculate X_byte position. */
14249 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
14250 mkU64(0x0),
14251 mkU64(0x1)));
14252
14253 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
14254 mkU64(0x2),
14255 mkU64(0x3)));
14256
14257 store(binop(Iop_Add64, mkexpr(t2), mkU64(3)), mkexpr(H_byte));
14258 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
14259 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
14260 store(mkexpr(t1), mkexpr(E_byte));
14261
14262#endif
petarjb92a9542013-02-27 22:57:17 +000014263 } else {
petarjccd78cd2013-05-31 15:09:56 +000014264 IRTemp E_byte = newTemp(Ity_I8);
14265 IRTemp F_byte = newTemp(Ity_I8);
14266 IRTemp G_byte = newTemp(Ity_I8);
14267 IRTemp H_byte = newTemp(Ity_I8);
14268 IRTemp F_pos = newTemp(Ity_I32);
14269 IRTemp G_pos = newTemp(Ity_I32);
14270
14271 /* H byte */
14272 assign(H_byte, getByteFromReg(rt, 0));
14273 /* G byte */
14274 assign(G_byte, getByteFromReg(rt, 1));
14275 /* F byte */
14276 assign(F_byte, getByteFromReg(rt, 2));
14277 /* E byte */
14278 assign(E_byte, getByteFromReg(rt, 3));
14279
sewardj362cf842012-06-07 08:59:53 +000014280 /* t1 = addr */
14281 t1 = newTemp(Ity_I32);
sewardj362cf842012-06-07 08:59:53 +000014282 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
petarjccd78cd2013-05-31 15:09:56 +000014283
sewardj362cf842012-06-07 08:59:53 +000014284 /* t2 = word addr */
petarjccd78cd2013-05-31 15:09:56 +000014285 t2 = newTemp(Ity_I32);
14286 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
sewardj362cf842012-06-07 08:59:53 +000014287
petarjccd78cd2013-05-31 15:09:56 +000014288 /* t3 = addr mod 4 */
sewardj362cf842012-06-07 08:59:53 +000014289 t3 = newTemp(Ity_I32);
petarjccd78cd2013-05-31 15:09:56 +000014290 assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
sewardj362cf842012-06-07 08:59:53 +000014291
petarjccd78cd2013-05-31 15:09:56 +000014292#if defined (_MIPSEL)
14293 /* Calculate X_byte position. */
14294 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
14295 mkU32(0x0),
14296 mkU32(0x1)));
sewardj362cf842012-06-07 08:59:53 +000014297
petarjccd78cd2013-05-31 15:09:56 +000014298 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
14299 mkU32(0x1),
14300 mkU32(0x0)));
sewardj362cf842012-06-07 08:59:53 +000014301
petarjccd78cd2013-05-31 15:09:56 +000014302 /* Store X_byte on the right place. */
14303 store(mkexpr(t2), mkexpr(H_byte));
14304 store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
14305 store(binop(Iop_Sub32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
14306 store(mkexpr(t1), mkexpr(E_byte));
14307
petarj70a26062013-06-09 16:46:14 +000014308#else /* _MIPSEB */
petarjccd78cd2013-05-31 15:09:56 +000014309 /* Calculate X_byte position. */
14310 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
14311 mkU32(0x0),
14312 mkU32(0x1)));
14313
14314 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
14315 mkU32(0x2),
14316 mkU32(0x3)));
14317
14318 store(binop(Iop_Add32, mkexpr(t2), mkU32(3)), mkexpr(H_byte));
14319 store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
14320 store(binop(Iop_Add32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
14321 store(mkexpr(t1), mkexpr(E_byte));
14322
14323#endif
sewardj362cf842012-06-07 08:59:53 +000014324 }
14325 break;
14326
petarjb92a9542013-02-27 22:57:17 +000014327 case 0x2E: /* SWR */
petarjc5b8bb72012-07-16 14:25:05 +000014328 DIP("swr r%d, %d(r%d)", rt, imm, rs);
petarjb92a9542013-02-27 22:57:17 +000014329 if (mode64) {
petarjccd78cd2013-05-31 15:09:56 +000014330 IRTemp E_byte = newTemp(Ity_I8);
14331 IRTemp F_byte = newTemp(Ity_I8);
14332 IRTemp G_byte = newTemp(Ity_I8);
14333 IRTemp H_byte = newTemp(Ity_I8);
14334 IRTemp F_pos = newTemp(Ity_I64);
14335 IRTemp G_pos = newTemp(Ity_I64);
14336
14337 /* H byte */
14338 assign(H_byte, getByteFromReg(rt, 0));
14339 /* G byte */
14340 assign(G_byte, getByteFromReg(rt, 1));
14341 /* F byte */
14342 assign(F_byte, getByteFromReg(rt, 2));
14343 /* E byte */
14344 assign(E_byte, getByteFromReg(rt, 3));
14345
petarjb92a9542013-02-27 22:57:17 +000014346 /* t1 = addr */
petarjb92a9542013-02-27 22:57:17 +000014347 t1 = newTemp(Ity_I64);
14348 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
petarjb92a9542013-02-27 22:57:17 +000014349
14350 /* t2 = word addr */
petarjccd78cd2013-05-31 15:09:56 +000014351 t2 = newTemp(Ity_I64);
14352 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
petarjb92a9542013-02-27 22:57:17 +000014353
petarjccd78cd2013-05-31 15:09:56 +000014354 /* t3 = addr mod 4 */
14355 t3 = newTemp(Ity_I64);
14356 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
petarjb92a9542013-02-27 22:57:17 +000014357
petarjccd78cd2013-05-31 15:09:56 +000014358#if defined (_MIPSEL)
14359 /* Calculate X_byte position. */
14360 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
14361 mkU64(0x2),
14362 mkU64(0x3)));
petarjb92a9542013-02-27 22:57:17 +000014363
petarjccd78cd2013-05-31 15:09:56 +000014364 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
14365 mkU64(0x0),
14366 mkU64(0x1)));
14367
14368 /* Store X_byte on the right place. */
14369 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x3)), mkexpr(E_byte));
14370 store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
14371 store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
14372 store(mkexpr(t1), mkexpr(H_byte));
14373
petarj70a26062013-06-09 16:46:14 +000014374#else /* _MIPSEB */
petarjccd78cd2013-05-31 15:09:56 +000014375 /* Calculate X_byte position. */
14376 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
14377 mkU64(0x1),
14378 mkU64(0x0)));
14379
14380 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
14381 mkU64(0x0),
14382 mkU64(0x1)));
14383
14384 /* Store X_byte on the right place. */
14385 store(mkexpr(t2), mkexpr(E_byte));
14386 store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
14387 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
14388 store(mkexpr(t1), mkexpr(H_byte));
14389#endif
petarjb92a9542013-02-27 22:57:17 +000014390 } else {
petarjccd78cd2013-05-31 15:09:56 +000014391 IRTemp E_byte = newTemp(Ity_I8);
14392 IRTemp F_byte = newTemp(Ity_I8);
14393 IRTemp G_byte = newTemp(Ity_I8);
14394 IRTemp H_byte = newTemp(Ity_I8);
14395 IRTemp F_pos = newTemp(Ity_I32);
14396 IRTemp G_pos = newTemp(Ity_I32);
14397
14398 /* H byte */
14399 assign(H_byte, getByteFromReg(rt, 0));
14400 /* G byte */
14401 assign(G_byte, getByteFromReg(rt, 1));
14402 /* F byte */
14403 assign(F_byte, getByteFromReg(rt, 2));
14404 /* E byte */
14405 assign(E_byte, getByteFromReg(rt, 3));
14406
sewardj362cf842012-06-07 08:59:53 +000014407 /* t1 = addr */
14408 t1 = newTemp(Ity_I32);
sewardj362cf842012-06-07 08:59:53 +000014409 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
sewardj362cf842012-06-07 08:59:53 +000014410
14411 /* t2 = word addr */
petarjccd78cd2013-05-31 15:09:56 +000014412 t2 = newTemp(Ity_I32);
14413 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
sewardj362cf842012-06-07 08:59:53 +000014414
petarjccd78cd2013-05-31 15:09:56 +000014415 /* t3 = addr mod 4 */
sewardj362cf842012-06-07 08:59:53 +000014416 t3 = newTemp(Ity_I32);
petarjccd78cd2013-05-31 15:09:56 +000014417 assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
sewardj362cf842012-06-07 08:59:53 +000014418
petarjccd78cd2013-05-31 15:09:56 +000014419#if defined (_MIPSEL)
14420 /* Calculate X_byte position. */
14421 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
14422 mkU32(0x2),
14423 mkU32(0x3)));
sewardj362cf842012-06-07 08:59:53 +000014424
petarjccd78cd2013-05-31 15:09:56 +000014425 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
14426 mkU32(0x0),
14427 mkU32(0x1)));
14428
14429 /* Store X_byte on the right place. */
14430 store(binop(Iop_Add32, mkexpr(t2), mkU32(0x3)), mkexpr(E_byte));
14431 store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
14432 store(binop(Iop_Add32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
14433 store(mkexpr(t1), mkexpr(H_byte));
14434
petarj70a26062013-06-09 16:46:14 +000014435#else /* _MIPSEB */
petarjccd78cd2013-05-31 15:09:56 +000014436 /* Calculate X_byte position. */
14437 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
14438 mkU32(0x1),
14439 mkU32(0x0)));
14440
14441 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
14442 mkU32(0x0),
14443 mkU32(0x1)));
14444
14445 /* Store X_byte on the right place. */
14446 store(mkexpr(t2), mkexpr(E_byte));
14447 store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
14448 store(binop(Iop_Sub32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
14449 store(mkexpr(t1), mkexpr(H_byte));
14450#endif
sewardj362cf842012-06-07 08:59:53 +000014451 }
14452 break;
14453
petarjb92a9542013-02-27 22:57:17 +000014454 case 0x1C: /* Special2 */
sewardj362cf842012-06-07 08:59:53 +000014455 switch (function) {
dejanj6ced72b2014-06-04 11:28:07 +000014456 /* Cavium Specific instructions */
14457 case 0x03: case 0x32: case 0x33: /* DMUL, CINS , CINS32 */
14458 case 0x3A: case 0x3B: case 0x2B: /* EXT, EXT32, SNE */
14459 /* CVM Compare Instructions */
14460 case 0x2A: case 0x2E: case 0x2F: /* SEQ, SEQI, SNEI */
14461 /* CPU Load, Store, Memory, and Control Instructions */
14462 case 0x18: case 0x19: /* SAA, SAAD */
14463 case 0x1F: /* LAA, LAAD, LAI, LAID */
14464 case 0x28: case 0x2C: case 0x2D: /* BADDU, POP, DPOP */
14465 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
14466 if (dis_instr_CVM(cins))
14467 break;
14468 goto decode_failure;
14469 } else {
14470 goto decode_failure;
14471 }
petarj5cc3b452013-09-18 02:17:43 +000014472 break;
petarjb92a9542013-02-27 22:57:17 +000014473
dejanj6ced72b2014-06-04 11:28:07 +000014474 case 0x02: { /* MUL */
14475 DIP("mul r%d, r%d, r%d", rd, rs, rt);
14476 if (mode64) {
14477 IRTemp tmpRs32 = newTemp(Ity_I32);
14478 IRTemp tmpRt32 = newTemp(Ity_I32);
14479 IRTemp tmpRes = newTemp(Ity_I32);
14480
14481 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
14482 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
14483 assign(tmpRes, binop(Iop_Mul32,
14484 mkexpr(tmpRs32), mkexpr(tmpRt32)));
14485 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpRes), True));
14486 } else
14487 putIReg(rd, binop(Iop_Mul32, getIReg(rs), getIReg(rt)));
14488 break;
14489 }
sewardj362cf842012-06-07 08:59:53 +000014490
dejanjc3fee0d2013-07-25 09:08:03 +000014491 case 0x00: { /* MADD */
14492 if (mode64) {
14493 DIP("madd r%d, r%d", rs, rt);
14494 t1 = newTemp(Ity_I32);
14495 t2 = newTemp(Ity_I32);
14496 t3 = newTemp(Ity_I64);
14497 t4 = newTemp(Ity_I64);
14498 t5 = newTemp(Ity_I64);
14499 t6 = newTemp(Ity_I32);
sewardj362cf842012-06-07 08:59:53 +000014500
dejanjc3fee0d2013-07-25 09:08:03 +000014501 assign(t1, mkNarrowTo32(ty, getHI()));
14502 assign(t2, mkNarrowTo32(ty, getLO()));
sewardj362cf842012-06-07 08:59:53 +000014503
dejanjc3fee0d2013-07-25 09:08:03 +000014504 assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
14505 mkNarrowTo32(ty, getIReg(rt))));
sewardj362cf842012-06-07 08:59:53 +000014506
dejanjc3fee0d2013-07-25 09:08:03 +000014507 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
14508 assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
sewardj362cf842012-06-07 08:59:53 +000014509
dejanjc3fee0d2013-07-25 09:08:03 +000014510 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
14511 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
14512 } else {
14513 if ( (1 <= ac) && ( 3 >= ac) ) {
petarjbc7d6f42013-09-16 18:11:59 +000014514 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000014515 /* If DSP is present -> DSP ASE MADD */
14516 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
14517 if (0 != retVal ) {
14518 goto decode_failure_dsp;
14519 }
14520 break;
14521 } else {
14522 goto decode_failure_dsp;
14523 }
14524 } else {
14525 DIP("madd r%d, r%d", rs, rt);
14526 t1 = newTemp(Ity_I32);
14527 t2 = newTemp(Ity_I32);
14528 t3 = newTemp(Ity_I64);
14529 t4 = newTemp(Ity_I32);
14530 t5 = newTemp(Ity_I32);
14531 t6 = newTemp(Ity_I32);
sewardj362cf842012-06-07 08:59:53 +000014532
dejanjc3fee0d2013-07-25 09:08:03 +000014533 assign(t1, getHI());
14534 assign(t2, getLO());
petarjb92a9542013-02-27 22:57:17 +000014535
dejanjc3fee0d2013-07-25 09:08:03 +000014536 assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
petarjb92a9542013-02-27 22:57:17 +000014537
dejanjc3fee0d2013-07-25 09:08:03 +000014538 assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
14539 mkexpr(t3))));
petarjb92a9542013-02-27 22:57:17 +000014540
dejanjc3fee0d2013-07-25 09:08:03 +000014541 assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
14542 unop(Iop_64to32, mkexpr(t3)))));
14543 assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
petarjb92a9542013-02-27 22:57:17 +000014544
dejanjc3fee0d2013-07-25 09:08:03 +000014545 putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
14546 mkexpr(t3))));
14547 putLO(mkexpr(t4));
14548 break;
14549 }
14550 }
14551 break;
petarjb92a9542013-02-27 22:57:17 +000014552 }
sewardj362cf842012-06-07 08:59:53 +000014553
petarjb92a9542013-02-27 22:57:17 +000014554 case 0x01: { /* MADDU */
petarjb92a9542013-02-27 22:57:17 +000014555 if (mode64) {
dejanjc3fee0d2013-07-25 09:08:03 +000014556 DIP("maddu r%d, r%d", rs, rt);
petarjb92a9542013-02-27 22:57:17 +000014557 t1 = newTemp(Ity_I32);
14558 t2 = newTemp(Ity_I32);
14559 t3 = newTemp(Ity_I64);
14560 t4 = newTemp(Ity_I64);
14561 t5 = newTemp(Ity_I64);
14562 t6 = newTemp(Ity_I32);
sewardj362cf842012-06-07 08:59:53 +000014563
petarjb92a9542013-02-27 22:57:17 +000014564 assign(t1, mkNarrowTo32(ty, getHI()));
14565 assign(t2, mkNarrowTo32(ty, getLO()));
sewardj362cf842012-06-07 08:59:53 +000014566
petarjb92a9542013-02-27 22:57:17 +000014567 assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
14568 mkNarrowTo32(ty, getIReg(rt))));
sewardj362cf842012-06-07 08:59:53 +000014569
petarjb92a9542013-02-27 22:57:17 +000014570 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
14571 assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
sewardj362cf842012-06-07 08:59:53 +000014572
petarjb92a9542013-02-27 22:57:17 +000014573 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
14574 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
14575 } else {
dejanjc3fee0d2013-07-25 09:08:03 +000014576 if ( (1 <= ac) && ( 3 >= ac) ) {
petarjbc7d6f42013-09-16 18:11:59 +000014577 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000014578 /* If DSP is present -> DSP ASE MADDU */
14579 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
14580 if (0 != retVal ) {
14581 goto decode_failure_dsp;
14582 }
14583 break;
14584 } else {
14585 goto decode_failure_dsp;
14586 }
14587 } else {
14588 DIP("maddu r%d, r%d", rs, rt);
14589 t1 = newTemp(Ity_I32);
14590 t2 = newTemp(Ity_I32);
14591 t3 = newTemp(Ity_I64);
14592 t4 = newTemp(Ity_I32);
14593 t5 = newTemp(Ity_I32);
14594 t6 = newTemp(Ity_I32);
petarjb92a9542013-02-27 22:57:17 +000014595
dejanjc3fee0d2013-07-25 09:08:03 +000014596 assign(t1, getHI());
14597 assign(t2, getLO());
petarjb92a9542013-02-27 22:57:17 +000014598
dejanjc3fee0d2013-07-25 09:08:03 +000014599 assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
petarjb92a9542013-02-27 22:57:17 +000014600
dejanjc3fee0d2013-07-25 09:08:03 +000014601 assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
14602 mkexpr(t3))));
14603 assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
14604 unop(Iop_64to32, mkexpr(t3)))));
14605 assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
petarjb92a9542013-02-27 22:57:17 +000014606
dejanjc3fee0d2013-07-25 09:08:03 +000014607 putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
14608 mkexpr(t3))));
14609 putLO(mkexpr(t4));
14610 break;
14611 }
petarjb92a9542013-02-27 22:57:17 +000014612 }
sewardj362cf842012-06-07 08:59:53 +000014613 break;
14614 }
14615
petarjb92a9542013-02-27 22:57:17 +000014616 case 0x04: { /* MSUB */
petarjb92a9542013-02-27 22:57:17 +000014617 if (mode64) {
dejanjc3fee0d2013-07-25 09:08:03 +000014618 DIP("msub r%d, r%d", rs, rt);
petarjb92a9542013-02-27 22:57:17 +000014619 t1 = newTemp(Ity_I32);
14620 t2 = newTemp(Ity_I32);
14621 t3 = newTemp(Ity_I64);
14622 t4 = newTemp(Ity_I64);
14623 t5 = newTemp(Ity_I64);
14624 t6 = newTemp(Ity_I32);
sewardj362cf842012-06-07 08:59:53 +000014625
petarjb92a9542013-02-27 22:57:17 +000014626 assign(t1, mkNarrowTo32(ty, getHI()));
14627 assign(t2, mkNarrowTo32(ty, getLO()));
sewardj362cf842012-06-07 08:59:53 +000014628
petarjb92a9542013-02-27 22:57:17 +000014629 assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
14630 mkNarrowTo32(ty, getIReg(rt))));
sewardj362cf842012-06-07 08:59:53 +000014631
petarjb92a9542013-02-27 22:57:17 +000014632 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
14633 assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
sewardj362cf842012-06-07 08:59:53 +000014634
petarjb92a9542013-02-27 22:57:17 +000014635 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
14636 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
14637 } else {
dejanjc3fee0d2013-07-25 09:08:03 +000014638 if ( (1 <= ac) && ( 3 >= ac) ) {
petarjbc7d6f42013-09-16 18:11:59 +000014639 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000014640 /* If DSP is present -> DSP ASE MSUB */
14641 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
14642 if (0 != retVal ) {
14643 goto decode_failure_dsp;
14644 }
14645 break;
14646 } else {
14647 goto decode_failure_dsp;
14648 }
14649 } else {
14650 DIP("msub r%d, r%d", rs, rt);
14651 t1 = newTemp(Ity_I32);
14652 t2 = newTemp(Ity_I32);
14653 t3 = newTemp(Ity_I64);
14654 t4 = newTemp(Ity_I32);
14655 t5 = newTemp(Ity_I1);
14656 t6 = newTemp(Ity_I32);
sewardj362cf842012-06-07 08:59:53 +000014657
dejanjc3fee0d2013-07-25 09:08:03 +000014658 assign(t1, getHI());
14659 assign(t2, getLO());
petarjb92a9542013-02-27 22:57:17 +000014660
dejanjc3fee0d2013-07-25 09:08:03 +000014661 assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
14662 assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */
petarjb92a9542013-02-27 22:57:17 +000014663
dejanjc3fee0d2013-07-25 09:08:03 +000014664 /* if lo<lo(mul) hi = hi - 1 */
14665 assign(t5, binop(Iop_CmpLT32U,
14666 mkexpr(t2),
14667 mkexpr(t4)));
petarjb92a9542013-02-27 22:57:17 +000014668
dejanjc3fee0d2013-07-25 09:08:03 +000014669 assign(t6, IRExpr_ITE(mkexpr(t5),
14670 binop(Iop_Sub32, mkexpr(t1), mkU32(0x1)),
14671 mkexpr(t1)));
petarjb92a9542013-02-27 22:57:17 +000014672
dejanjc3fee0d2013-07-25 09:08:03 +000014673 putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
14674 mkexpr(t3))));
14675 putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
14676 break;
14677 }
petarjb92a9542013-02-27 22:57:17 +000014678 }
sewardj362cf842012-06-07 08:59:53 +000014679 break;
14680 }
14681
dejanjc3fee0d2013-07-25 09:08:03 +000014682 case 0x05: { /* MSUBU */
petarjb92a9542013-02-27 22:57:17 +000014683 if (mode64) {
dejanjc3fee0d2013-07-25 09:08:03 +000014684 DIP("msubu r%d, r%d", rs, rt);
petarjb92a9542013-02-27 22:57:17 +000014685 t1 = newTemp(Ity_I32);
14686 t2 = newTemp(Ity_I32);
14687 t3 = newTemp(Ity_I64);
14688 t4 = newTemp(Ity_I64);
14689 t5 = newTemp(Ity_I64);
14690 t6 = newTemp(Ity_I32);
14691
14692 assign(t1, mkNarrowTo32(ty, getHI()));
14693 assign(t2, mkNarrowTo32(ty, getLO()));
14694
14695 assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
14696 mkNarrowTo32(ty, getIReg(rt))));
14697
14698 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
14699 assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
14700
14701 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
14702 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
14703 } else {
dejanjc3fee0d2013-07-25 09:08:03 +000014704 if ( (1 <= ac) && ( 3 >= ac) ) {
petarjbc7d6f42013-09-16 18:11:59 +000014705 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000014706 /* If DSP is present -> DSP ASE MSUBU */
14707 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
14708 if (0 != retVal ) {
14709 goto decode_failure_dsp;
14710 }
14711 break;
14712 } else {
14713 goto decode_failure_dsp;
14714 }
14715 } else {
14716 DIP("msubu r%d, r%d", rs, rt);
14717 t1 = newTemp(Ity_I32);
14718 t2 = newTemp(Ity_I32);
14719 t3 = newTemp(Ity_I64);
14720 t4 = newTemp(Ity_I32);
14721 t5 = newTemp(Ity_I1);
14722 t6 = newTemp(Ity_I32);
petarjb92a9542013-02-27 22:57:17 +000014723
dejanjc3fee0d2013-07-25 09:08:03 +000014724 assign(t1, getHI());
14725 assign(t2, getLO());
petarjb92a9542013-02-27 22:57:17 +000014726
dejanjc3fee0d2013-07-25 09:08:03 +000014727 assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
14728 assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */
petarjb92a9542013-02-27 22:57:17 +000014729
dejanjc3fee0d2013-07-25 09:08:03 +000014730 /* if lo<lo(mul) hi = hi - 1 */
14731 assign(t5, binop(Iop_CmpLT32U,
14732 mkexpr(t2),
14733 mkexpr(t4)));
petarjb92a9542013-02-27 22:57:17 +000014734
dejanjc3fee0d2013-07-25 09:08:03 +000014735 assign(t6, IRExpr_ITE(mkexpr(t5),
14736 binop(Iop_Sub32,
14737 mkexpr(t1),
14738 mkU32(0x1)),
14739 mkexpr(t1)));
petarjb92a9542013-02-27 22:57:17 +000014740
dejanjc3fee0d2013-07-25 09:08:03 +000014741 putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
14742 mkexpr(t3))));
14743 putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
14744 break;
14745 }
petarjb92a9542013-02-27 22:57:17 +000014746 }
14747 break;
14748 }
14749
14750 case 0x6: /* dmul MIPS64 - Netlogic */
petarj1fb1e342013-04-27 02:18:11 +000014751 DIP("dmul r%u, r%u, r%u", rd, rs, rt);
petarjb92a9542013-02-27 22:57:17 +000014752 t0 = newTemp(Ity_I128);
14753
14754 assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
14755
14756 putIReg(rd, unop(Iop_128to64, mkexpr(t0)));
14757 break;
14758
14759 case 0x10: /* LDADDW - Swap Word - Netlogic */
petarj1fb1e342013-04-27 02:18:11 +000014760 DIP("ldaddw r%u, r%u", rt, rs);
petarjb92a9542013-02-27 22:57:17 +000014761 t0 = newTemp(Ity_I32);
sewardj362cf842012-06-07 08:59:53 +000014762 t1 = newTemp(Ity_I32);
14763 t2 = newTemp(Ity_I32);
14764 t3 = newTemp(Ity_I64);
14765 t4 = newTemp(Ity_I32);
petarjb92a9542013-02-27 22:57:17 +000014766 t5 = newTemp(Ity_I32);
sewardj362cf842012-06-07 08:59:53 +000014767 t6 = newTemp(Ity_I32);
14768
petarjb92a9542013-02-27 22:57:17 +000014769 /* v = GPR[rt] */
14770 assign(t0, mkNarrowTo32(ty, getIReg(rt)));
sewardj362cf842012-06-07 08:59:53 +000014771
petarjb92a9542013-02-27 22:57:17 +000014772 /* GPR[rt] = memory[base]; */
14773 assign(t1, load(Ity_I32, getIReg(rs)));
14774 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
sewardj362cf842012-06-07 08:59:53 +000014775
petarjb92a9542013-02-27 22:57:17 +000014776 /* memory[base] = memory[base] + v; */
14777 store(getIReg(rs), binop(Iop_Add32, mkexpr(t0), mkexpr(t1)));
sewardj362cf842012-06-07 08:59:53 +000014778 break;
sewardj362cf842012-06-07 08:59:53 +000014779
petarjb92a9542013-02-27 22:57:17 +000014780 case 0x12: /* LDADDD - Swap Word - Netlogic */
petarj1fb1e342013-04-27 02:18:11 +000014781 DIP("ldaddw r%u, r%u", rt, rs);
petarjb92a9542013-02-27 22:57:17 +000014782 t0 = newTemp(Ity_I64);
14783 t1 = newTemp(Ity_I64);
14784
14785 /* v = GPR[rt] */
14786 assign(t0, getIReg(rt));
14787
14788 /* GPR[rt] = memory[base]; */
14789 assign(t1, load(Ity_I64, getIReg(rs)));
14790 putIReg(rt, mkexpr(t1));
14791
14792 /* memory[base] = memory[base] + v; */
14793 store(getIReg(rs), binop(Iop_Add64, mkexpr(t0), mkexpr(t1)));
14794 break;
14795
14796 case 0x14: /* SWAPW - Swap Word - Netlogic */
petarj1fb1e342013-04-27 02:18:11 +000014797 DIP("swapw r%u, r%u", rt, rs);
petarjb92a9542013-02-27 22:57:17 +000014798 t0 = newTemp(Ity_I32);
14799 t1 = newTemp(Ity_I32);
14800 assign(t0, mkNarrowTo32(ty, getIReg(rt)));
14801 assign(t1, load(Ity_I32, getIReg(rs)));
14802 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
14803 store(getIReg(rs), mkexpr(t0));
14804 break;
14805
14806 case 0x16: /* SWAPD - Swap Double - Netlogic */
petarj1fb1e342013-04-27 02:18:11 +000014807 DIP("swapw r%u, r%u", rt, rs);
petarjb92a9542013-02-27 22:57:17 +000014808 t0 = newTemp(Ity_I64);
14809 t1 = newTemp(Ity_I64);
14810 assign(t0, getIReg(rt));
14811 assign(t1, load(Ity_I64, getIReg(rs)));
14812 putIReg(rt, mkexpr(t1));
14813 store(getIReg(rs), mkexpr(t0));
14814 break;
14815
14816 case 0x20: { /* CLZ */
sewardj362cf842012-06-07 08:59:53 +000014817 DIP("clz r%d, r%d", rd, rs);
petarjb92a9542013-02-27 22:57:17 +000014818 if (mode64) {
14819 IRTemp tmpClz32 = newTemp(Ity_I32);
14820 IRTemp tmpRs32 = newTemp(Ity_I32);
14821
14822 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
14823 assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32)));
14824 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True));
14825 } else {
14826 t1 = newTemp(Ity_I1);
14827 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0)));
14828 putIReg(rd, IRExpr_ITE(mkexpr(t1),
14829 mkU32(0x00000020),
14830 unop(Iop_Clz32, getIReg(rs))));
14831 }
sewardj362cf842012-06-07 08:59:53 +000014832 break;
14833 }
14834
petarjb92a9542013-02-27 22:57:17 +000014835 case 0x21: { /* CLO */
sewardj362cf842012-06-07 08:59:53 +000014836 DIP("clo r%d, r%d", rd, rs);
petarjb92a9542013-02-27 22:57:17 +000014837 if (mode64) {
14838 IRTemp tmpClo32 = newTemp(Ity_I32);
14839 IRTemp tmpRs32 = newTemp(Ity_I32);
14840 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
14841
14842 t1 = newTemp(Ity_I1);
14843 assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff)));
14844 assign(tmpClo32, IRExpr_ITE(mkexpr(t1),
14845 mkU32(0x00000020),
14846 unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32)))));
14847
14848 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True));
14849 break;
14850 } else {
14851 t1 = newTemp(Ity_I1);
14852 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff)));
14853 putIReg(rd, IRExpr_ITE(mkexpr(t1),
14854 mkU32(0x00000020),
14855 unop(Iop_Clz32,
14856 unop(Iop_Not32, getIReg(rs)))));
14857 break;
14858 }
sewardj362cf842012-06-07 08:59:53 +000014859 }
14860
petarjb92a9542013-02-27 22:57:17 +000014861 case 0x24: /* Count Leading Zeros in Doubleword - DCLZ; MIPS64 */
14862 DIP("dclz r%d, r%d", rd, rs);
14863 t1 = newTemp(Ity_I1);
14864 assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0)));
14865 putIReg(rd, IRExpr_ITE(mkexpr(t1),
14866 mkU64(0x00000040),
14867 unop(Iop_Clz64, getIReg(rs))));
14868 break;
14869
14870 case 0x25: /* Count Leading Ones in Doubleword - DCLO; MIPS64 */
14871 DIP("dclo r%d, r%d", rd, rs);
14872 t1 = newTemp(Ity_I1);
14873 assign(t1, binop(Iop_CmpEQ64, getIReg(rs),
petarjfdb2a4c2013-03-02 02:37:01 +000014874 mkU64(0xffffffffffffffffULL)));
petarjb92a9542013-02-27 22:57:17 +000014875 putIReg(rd, IRExpr_ITE(mkexpr(t1),
14876 mkU64(0x40),
14877 unop(Iop_Clz64, unop(Iop_Not64,
14878 getIReg(rs)))));
14879 break;
14880
sewardj362cf842012-06-07 08:59:53 +000014881 default:
14882 goto decode_failure;
14883 }
14884 break;
14885
petarjb92a9542013-02-27 22:57:17 +000014886 case 0x1F: /* Special3 */
sewardj362cf842012-06-07 08:59:53 +000014887 switch (function) {
petarjb92a9542013-02-27 22:57:17 +000014888 case 0x01: {
14889 /* Doubleword Extract Bit Field - DEXTM; MIPS64r2 */
14890 msb = get_msb(cins);
14891 lsb = get_lsb(cins);
14892 size = msb + 1;
14893 UInt srcPos = lsb;
14894 UInt dstSz = msb + 33;
14895 t1 = newTemp(Ity_I64);
petarj1fb1e342013-04-27 02:18:11 +000014896 DIP("dextm r%u, r%u, %d, %d", rt, rs, lsb, msb + 1);
petarjb92a9542013-02-27 22:57:17 +000014897
14898 UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */
14899 UChar rsAmt = 64 - dstSz; /* right shift amount; */
14900
14901 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
14902 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
14903
14904 break;
14905 }
14906 case 0x02: {
14907 /* Doubleword Extract Bit Field Upper - DEXTU; MIPS64r2 */
14908 msb = get_msb(cins);
14909 lsb = get_lsb(cins);
14910 size = msb + 1;
14911 UInt srcPos = lsb + 32;
14912 UInt dstSz = msb + 1;
petarj1fb1e342013-04-27 02:18:11 +000014913 DIP("dextu r%u, r%u, %d, %d", rt, rs, srcPos, dstSz);
petarjb92a9542013-02-27 22:57:17 +000014914 t1 = newTemp(Ity_I64);
petarjb92a9542013-02-27 22:57:17 +000014915
14916 vassert(srcPos >= 32 && srcPos < 64);
14917 vassert(dstSz > 0 && dstSz <= 32);
14918 vassert((srcPos + dstSz) > 32 && (srcPos + dstSz) <= 64);
14919
14920 UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */
14921 UChar rsAmt = 64 - dstSz; /* right shift amount; */
14922
14923 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
14924 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
14925 break;
14926 }
14927 case 0x05: {
14928 /* Doubleword Insert Bit Field Middle - DINSM; MIPS64r2 */
14929 msb = get_msb(cins);
14930 lsb = get_lsb(cins);
14931 size = msb + 1;
14932 UInt dstPos = lsb;
14933 UInt srcSz = msb - lsb + 33;
14934 t1 = newTemp(ty);
14935 t2 = newTemp(ty);
14936 t3 = newTemp(ty);
14937 t4 = newTemp(ty);
14938 IRTemp tmpT1 = newTemp(ty);
14939 IRTemp tmpT2 = newTemp(ty);
14940 IRTemp tmpT3 = newTemp(ty);
14941 IRTemp tmpT4 = newTemp(ty);
14942 IRTemp tmpT5 = newTemp(ty);
14943 IRTemp tmpT6 = newTemp(ty);
14944 IRTemp tmpT7 = newTemp(ty);
14945 IRTemp tmpRs = newTemp(ty);
14946 IRTemp tmpRt = newTemp(ty);
14947 IRTemp tmpRd = newTemp(ty);
14948
14949 assign(tmpRs, getIReg(rs));
14950 assign(tmpRt, getIReg(rt));
petarj1fb1e342013-04-27 02:18:11 +000014951 DIP("dinsm r%u, r%u, %d, %d", rt, rs, lsb, msb);
petarjb92a9542013-02-27 22:57:17 +000014952
14953 UChar lsAmt = dstPos + srcSz - 1; /* left shift amount; */
14954 UChar rsAmt = dstPos + srcSz - 1; /* right shift amount; */
14955
14956 assign(t1, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
14957 assign(tmpT1, binop(Iop_Shr64, mkexpr(t1), mkU8(1)));
14958 assign(t2, binop(Iop_Shl64, mkexpr(tmpT1), mkU8(lsAmt)));
14959 assign(tmpT2, binop(Iop_Shl64, mkexpr(t2), mkU8(1)));
14960
14961 lsAmt = 63 - dstPos; /* left shift amount; */
14962 rsAmt = 63 - dstPos; /* right shift amount; */
14963
14964 assign(t3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
14965 assign(tmpT3, binop(Iop_Shl64, mkexpr(t3), mkU8(1)));
14966 assign(t4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
14967 assign(tmpT4, binop(Iop_Shr64, mkexpr(t4), mkU8(1)));
14968
14969 /* extract size from src register */
14970 lsAmt = 64 - srcSz; /* left shift amount; */
14971 rsAmt = 64 - (lsb + srcSz); /* right shift amount; */
14972
14973 assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
14974 assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(rsAmt)));
14975
14976 assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT4)));
14977 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT7)));
14978 putIReg(rt, mkexpr(tmpRd));
14979 break;
14980 }
14981 case 0x06: {
14982 /* Doubleword Insert Bit Field Upper - DINSU; MIPS64r2 */
14983 msb = get_msb(cins);
14984 lsb = get_lsb(cins);
14985 size = msb + 1;
14986 UInt dstPos = lsb + 32;
14987 UInt srcSz = msb - lsb + 1;
14988 IRTemp tmpT1 = newTemp(ty);
14989 IRTemp tmpT2 = newTemp(ty);
14990 IRTemp tmpT3 = newTemp(ty);
14991 IRTemp tmpT4 = newTemp(ty);
14992 IRTemp tmpT5 = newTemp(ty);
14993 IRTemp tmpT6 = newTemp(ty);
14994 IRTemp tmpT7 = newTemp(ty);
14995 IRTemp tmpT8 = newTemp(ty);
14996 IRTemp tmpT9 = newTemp(ty);
14997 IRTemp tmpRs = newTemp(ty);
14998 IRTemp tmpRt = newTemp(ty);
14999 IRTemp tmpRd = newTemp(ty);
15000
15001 assign(tmpRs, getIReg(rs));
15002 assign(tmpRt, getIReg(rt));
petarj1fb1e342013-04-27 02:18:11 +000015003 DIP("dinsu r%u, r%u, %d, %d", rt, rs, lsb, msb);
petarjb92a9542013-02-27 22:57:17 +000015004
15005 UChar lsAmt = 64 - srcSz; /* left shift amount; */
15006 UChar rsAmt = 64 - (dstPos + srcSz); /* right shift amount; */
15007 assign(tmpT1, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
15008 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
15009
15010 lsAmt = 64 - dstPos; /* left shift amount; */
15011 rsAmt = 64 - dstPos; /* right shift amount; */
15012 assign(tmpT3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
15013 assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
15014
15015 lsAmt = dstPos; /* left shift amount; */
15016 rsAmt = srcSz; /* right shift amount; */
15017 assign(tmpT5, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
15018 assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(lsAmt)));
15019
15020 assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpT6), mkU8(rsAmt)));
15021 assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(lsAmt)));
15022
15023 assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT4)));
15024 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT9)));
15025 putIReg(rt, mkexpr(tmpRd));
15026 break;
15027 }
15028 case 0x07: {
15029 /* Doubleword Insert Bit Field - DINS; MIPS64r2 */
15030 IRTemp tmp1 = newTemp(ty);
15031 IRTemp tmpT1 = newTemp(ty);
15032 IRTemp tmpT2 = newTemp(ty);
15033 IRTemp tmpT3 = newTemp(ty);
15034 IRTemp tmpT4 = newTemp(ty);
15035 IRTemp tmpT5 = newTemp(ty);
15036 IRTemp tmpT6 = newTemp(ty);
15037 IRTemp tmpT7 = newTemp(ty);
15038 IRTemp tmpT8 = newTemp(ty);
15039 IRTemp tmpT9 = newTemp(ty);
15040 IRTemp tmp = newTemp(ty);
15041 IRTemp tmpRs = newTemp(ty);
15042 IRTemp tmpRt = newTemp(ty);
15043 IRTemp tmpRd = newTemp(ty);
15044
15045 assign(tmpRs, getIReg(rs));
15046 assign(tmpRt, getIReg(rt));
15047
15048 msb = get_msb(cins);
15049 lsb = get_lsb(cins);
15050 size = msb + 1;
petarj1fb1e342013-04-27 02:18:11 +000015051 DIP("dins r%u, r%u, %d, %d", rt, rs, lsb,
petarjb92a9542013-02-27 22:57:17 +000015052 msb - lsb + 1);
15053 UChar lsAmt = 63 - lsb; /* left shift amount; */
15054 UChar rsAmt = 63 - lsb; /* right shift amount; */
15055 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
15056 assign(tmpT1, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
15057 assign(tmp1, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
15058 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmp1), mkU8(1)));
15059
15060 lsAmt = msb; /* left shift amount; */
15061 rsAmt = 1; /*right shift amount; */
15062 assign(tmpT3, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
15063 assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(lsAmt)));
15064 assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpT4), mkU8(rsAmt)));
15065 assign(tmpT6, binop(Iop_Shl64, mkexpr(tmpT5), mkU8(lsAmt)));
15066
15067 lsAmt = 64 - (msb - lsb + 1); /* left shift amount; */
15068 rsAmt = 64 - (msb + 1); /* right shift amount; */
15069 assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
15070 assign(tmpT8, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(rsAmt)));
15071
15072 assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT8)));
15073 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT9)));
15074 putIReg(rt, mkexpr(tmpRd));
15075 break;
15076 }
15077 case 0x24: /* DBSHFL */
15078 lsb = get_lsb(cins);
15079 IRTemp tmpRs = newTemp(ty);
15080 IRTemp tmpRt = newTemp(ty);
15081 IRTemp tmpRd = newTemp(ty);
15082 assign(tmpRs, getIReg(rs));
15083 assign(tmpRt, getIReg(rt));
15084 switch (lsb) {
15085 case 0x02: { /* DSBH */
petarj1fb1e342013-04-27 02:18:11 +000015086 DIP("dsbh r%u, r%u", rd, rt);
petarjb92a9542013-02-27 22:57:17 +000015087 IRTemp tmpT1 = newTemp(ty);
15088 IRTemp tmpT2 = newTemp(ty);
15089 IRTemp tmpT3 = newTemp(ty);
15090 IRTemp tmpT4 = newTemp(ty);
15091 IRTemp tmpT5 = newTemp(Ity_I64);
15092 IRTemp tmpT6 = newTemp(ty);
petarjb92a9542013-02-27 22:57:17 +000015093 assign(tmpT5, mkU64(0xFF00FF00FF00FF00ULL));
15094 assign(tmpT6, mkU64(0x00FF00FF00FF00FFULL));
15095 assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
15096 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(8)));
15097 assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
15098 assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(8)));
15099 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
15100 putIReg(rd, mkexpr(tmpRd));
15101 break;
15102 }
15103 case 0x05: { /* DSHD */
petarj1fb1e342013-04-27 02:18:11 +000015104 DIP("dshd r%u, r%u\n", rd, rt);
petarjb92a9542013-02-27 22:57:17 +000015105 IRTemp tmpT1 = newTemp(ty);
15106 IRTemp tmpT2 = newTemp(ty);
15107 IRTemp tmpT3 = newTemp(ty);
15108 IRTemp tmpT4 = newTemp(ty);
15109 IRTemp tmpT5 = newTemp(Ity_I64);
15110 IRTemp tmpT6 = newTemp(ty);
15111 IRTemp tmpT7 = newTemp(ty);
15112 IRTemp tmpT8 = newTemp(ty);
15113 IRTemp tmpT9 = newTemp(ty);
petarjb92a9542013-02-27 22:57:17 +000015114 assign(tmpT5, mkU64(0xFFFF0000FFFF0000ULL));
15115 assign(tmpT6, mkU64(0x0000FFFF0000FFFFULL));
15116 assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
15117 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(16)));
15118 assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
15119 assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(16)));
15120 assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
15121 assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(32)));
15122 assign(tmpT9, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(32)));
15123 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT9)));
15124 putIReg(rd, mkexpr(tmpRd));
15125 break;
15126 }
15127 default:
15128 vex_printf("\nop6o10 = %d", lsb);
15129 goto decode_failure;;
15130 }
15131 break;
15132 case 0x3B: { /* RDHWR */
petarj0c30de82013-04-19 12:35:00 +000015133 DIP("rdhwr r%d, r%d", rt, rd);
sewardj362cf842012-06-07 08:59:53 +000015134 if (rd == 29) {
15135 putIReg(rt, getULR());
petarjb92a9542013-02-27 22:57:17 +000015136#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2))
15137 } else if (rd == 1) {
dejanja445f1b2013-10-22 08:52:46 +000015138 if (mode64) {
15139 IRTemp val = newTemp(Ity_I64);
15140 IRExpr** args = mkIRExprVec_2 (mkU64(rt), mkU64(rd));
15141 IRDirty *d = unsafeIRDirty_1_N(val,
15142 0,
15143 "mips64_dirtyhelper_rdhwr",
15144 &mips64_dirtyhelper_rdhwr,
15145 args);
15146 stmt(IRStmt_Dirty(d));
15147 putIReg(rt, mkexpr(val));
15148 } else {
15149 IRTemp val = newTemp(Ity_I32);
15150 IRExpr** args = mkIRExprVec_2 (mkU32(rt), mkU32(rd));
15151 IRDirty *d = unsafeIRDirty_1_N(val,
15152 0,
15153 "mips32_dirtyhelper_rdhwr",
15154 &mips32_dirtyhelper_rdhwr,
15155 args);
15156 stmt(IRStmt_Dirty(d));
15157 putIReg(rt, mkexpr(val));
15158 }
petarjb92a9542013-02-27 22:57:17 +000015159#endif
sewardj362cf842012-06-07 08:59:53 +000015160 } else
15161 goto decode_failure;
15162 break;
15163 }
petarjb92a9542013-02-27 22:57:17 +000015164 case 0x04: /* INS */
15165 msb = get_msb(cins);
sewardj362cf842012-06-07 08:59:53 +000015166 lsb = get_lsb(cins);
sewardj362cf842012-06-07 08:59:53 +000015167 size = msb - lsb + 1;
petarj1fb1e342013-04-27 02:18:11 +000015168 DIP("ins size:%d msb:%d lsb:%d", size, msb, lsb);
sewardj362cf842012-06-07 08:59:53 +000015169
15170 vassert(lsb + size <= 32);
15171 vassert(lsb + size > 0);
15172
petarjb92a9542013-02-27 22:57:17 +000015173 /* put size bits from rs at the pos in temporary */
sewardj362cf842012-06-07 08:59:53 +000015174 t0 = newTemp(Ity_I32);
15175 t3 = newTemp(Ity_I32);
petarjb92a9542013-02-27 22:57:17 +000015176 /* shift left for 32 - size to clear leading bits and get zeros
15177 at the end */
15178 assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
15179 mkU8(32 - size)));
15180 /* now set it at pos */
sewardj362cf842012-06-07 08:59:53 +000015181 t1 = newTemp(Ity_I32);
15182 assign(t1, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size - lsb)));
15183
15184 if (lsb > 0) {
15185 t2 = newTemp(Ity_I32);
petarjb92a9542013-02-27 22:57:17 +000015186 /* clear everything but lower pos bits from rt */
15187 assign(t2, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rt)),
15188 mkU8(32 - lsb)));
sewardj362cf842012-06-07 08:59:53 +000015189 assign(t3, binop(Iop_Shr32, mkexpr(t2), mkU8(32 - lsb)));
dejanjc3fee0d2013-07-25 09:08:03 +000015190 } else
petarjbc3af3c2013-04-27 01:15:48 +000015191 assign(t3, mkU32(0));
sewardj362cf842012-06-07 08:59:53 +000015192
15193 if (msb < 31) {
15194 t4 = newTemp(Ity_I32);
petarjb92a9542013-02-27 22:57:17 +000015195 /* clear everything but upper msb + 1 bits from rt */
15196 assign(t4, binop(Iop_Shr32, mkNarrowTo32(ty, getIReg(rt)),
15197 mkU8(msb + 1)));
sewardj362cf842012-06-07 08:59:53 +000015198 t5 = newTemp(Ity_I32);
15199 assign(t5, binop(Iop_Shl32, mkexpr(t4), mkU8(msb + 1)));
15200
petarjb92a9542013-02-27 22:57:17 +000015201 /* now combine these registers */
sewardj362cf842012-06-07 08:59:53 +000015202 if (lsb > 0) {
15203 t6 = newTemp(Ity_I32);
15204 assign(t6, binop(Iop_Or32, mkexpr(t5), mkexpr(t1)));
petarjb92a9542013-02-27 22:57:17 +000015205 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t6),
petarjbc3af3c2013-04-27 01:15:48 +000015206 mkexpr(t3)), True));
sewardj362cf842012-06-07 08:59:53 +000015207 } else {
petarjb92a9542013-02-27 22:57:17 +000015208 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
petarjbc3af3c2013-04-27 01:15:48 +000015209 mkexpr(t5)), True));
sewardj362cf842012-06-07 08:59:53 +000015210 }
petarjb92a9542013-02-27 22:57:17 +000015211 } else {
15212 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
petarjbc3af3c2013-04-27 01:15:48 +000015213 mkexpr(t3)), True));
sewardj362cf842012-06-07 08:59:53 +000015214 }
15215 break;
15216
petarjb92a9542013-02-27 22:57:17 +000015217 case 0x00: /* EXT */
15218 msb = get_msb(cins);
sewardj362cf842012-06-07 08:59:53 +000015219 lsb = get_lsb(cins);
15220 size = msb + 1;
15221 DIP("ext size:%d msb:%d lsb:%d", size, msb, lsb);
15222 vassert(lsb + size <= 32);
15223 vassert(lsb + size > 0);
petarjb92a9542013-02-27 22:57:17 +000015224 /* put size bits from rs at the top of in temporary */
sewardj362cf842012-06-07 08:59:53 +000015225 if (lsb + size < 32) {
15226 t0 = newTemp(Ity_I32);
petarjb92a9542013-02-27 22:57:17 +000015227 assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
15228 mkU8(32 - lsb - size)));
sewardj362cf842012-06-07 08:59:53 +000015229
petarjb92a9542013-02-27 22:57:17 +000015230 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32, mkexpr(t0),
15231 mkU8(32 - size)), True));
15232 } else {
15233 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32,
15234 mkNarrowTo32(ty, getIReg(rs)),
15235 mkU8(32 - size)), True));
sewardj362cf842012-06-07 08:59:53 +000015236 }
15237 break;
15238
petarjb92a9542013-02-27 22:57:17 +000015239 case 0x03: /* Doubleword Extract Bit Field - DEXT; MIPS64r2 */
15240 msb = get_msb(cins);
15241 lsb = get_lsb(cins);
15242 size = msb + 1;
petarj1fb1e342013-04-27 02:18:11 +000015243 DIP("dext r%u, r%u, %d, %d", rt, rs, lsb, msb + 1);
petarjb92a9542013-02-27 22:57:17 +000015244 t1 = newTemp(Ity_I64);
petarjb92a9542013-02-27 22:57:17 +000015245 vassert(lsb >= 0 && lsb < 32);
15246 vassert(size > 0 && size <= 32);
15247 vassert((lsb + size) > 0 && (lsb + size) <= 63);
sewardj362cf842012-06-07 08:59:53 +000015248
petarjb92a9542013-02-27 22:57:17 +000015249 UChar lsAmt = 63 - (lsb + msb); /* left shift amount; */
15250 UChar rsAmt = 63 - msb; /* right shift amount; */
sewardj362cf842012-06-07 08:59:53 +000015251
petarjb92a9542013-02-27 22:57:17 +000015252 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
15253 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
sewardj362cf842012-06-07 08:59:53 +000015254
petarjb92a9542013-02-27 22:57:17 +000015255 break;
15256
15257 case 0x20: /* BSHFL */
15258 switch (sa) {
15259 case 0x02: /* WSBH */
15260 DIP("wsbh r%d, r%d", rd, rt);
15261 t0 = newTemp(Ity_I32);
15262 t1 = newTemp(Ity_I32);
15263 t2 = newTemp(Ity_I32);
15264 t3 = newTemp(Ity_I32);
15265 assign(t0, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
15266 getIReg(rt)), mkU32(0x00FF0000)),
15267 mkU8(0x8)));
15268 assign(t1, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
15269 getIReg(rt)), mkU32(0xFF000000)), mkU8(0x8)));
15270 assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
15271 getIReg(rt)), mkU32(0x000000FF)), mkU8(0x8)));
15272 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
15273 getIReg(rt)), mkU32(0x0000FF00)), mkU8(0x8)));
15274 putIReg(rd, mkWidenFrom32(ty, binop(Iop_Or32, binop(Iop_Or32,
15275 mkexpr(t0), mkexpr(t1)),
15276 binop(Iop_Or32, mkexpr(t2),
15277 mkexpr(t3))), True));
15278 break;
15279
15280 case 0x10: /* SEB */
petarj1fb1e342013-04-27 02:18:11 +000015281 DIP("seb r%d, r%d", rd, rt);
15282 if (mode64)
petarjb92a9542013-02-27 22:57:17 +000015283 putIReg(rd, unop(Iop_8Sto64, unop(Iop_64to8, getIReg(rt))));
15284 else
15285 putIReg(rd, unop(Iop_8Sto32, unop(Iop_32to8, getIReg(rt))));
15286 break;
15287
15288 case 0x18: /* SEH */
petarj1fb1e342013-04-27 02:18:11 +000015289 DIP("seh r%d, r%d", rd, rt);
petarjb92a9542013-02-27 22:57:17 +000015290 if (mode64)
15291 putIReg(rd, unop(Iop_16Sto64, unop(Iop_64to16, getIReg(rt))));
15292 else
15293 putIReg(rd, unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
15294 break;
15295
15296 default:
15297 goto decode_failure;
15298
15299 }
15300 break; /* BSHFL */
sewardj362cf842012-06-07 08:59:53 +000015301
petarjd20794a2014-01-31 12:14:20 +000015302 /* --- MIPS32(r2) DSP ASE(r2) / Cavium Specfic (LX) instructions --- */
dejanjc3fee0d2013-07-25 09:08:03 +000015303 case 0xA: /* LX */
petarjd20794a2014-01-31 12:14:20 +000015304 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
15305 if (dis_instr_CVM(cins))
15306 break;
15307 goto decode_failure;
15308 }
dejanjc3fee0d2013-07-25 09:08:03 +000015309 case 0xC: /* INSV */
15310 case 0x38: { /* EXTR.W */
petarjbc7d6f42013-09-16 18:11:59 +000015311 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015312 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15313 if (0 != retVal ) {
15314 goto decode_failure_dsp;
15315 }
15316 break;
15317 } else {
15318 goto decode_failure_dsp;
15319 }
15320 break;
sewardj362cf842012-06-07 08:59:53 +000015321 }
dejanjc3fee0d2013-07-25 09:08:03 +000015322 case 0x10: { /* ADDU.QB */
15323 switch(sa) {
15324 case 0xC: /* SUBU_S.PH */
15325 case 0xD: /* ADDU_S.PH */
15326 case 0x1E: { /* MULQ_S.PH */
petarjbc7d6f42013-09-16 18:11:59 +000015327 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015328 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15329 if (0 != retVal ) {
15330 goto decode_failure_dsp;
15331 }
15332 break;
15333 } else {
15334 goto decode_failure_dsp;
15335 }
15336 break;
15337 }
15338 default: {
petarjbc7d6f42013-09-16 18:11:59 +000015339 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015340 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15341 if (0 != retVal ) {
15342 goto decode_failure_dsp;
15343 }
15344 break;
15345 } else {
15346 goto decode_failure_dsp;
15347 }
15348 break;
15349 }
15350 }
15351 break;
15352 }
15353 case 0x11: { /* CMPU.EQ.QB */
15354 switch(sa) {
15355 case 0x18: /* CMPGDU.EQ.QB */
15356 case 0x19: /* CMPGDU.LT.QB */
15357 case 0x1A: /* CMPGDU.LE.QB */
15358 case 0x0D: /* PRECR.QB.PH */
15359 case 0x1E: /* PRECR_SRA.PH.W */
15360 case 0x1F: { /* PRECR_SRA_R.PH.W */
petarjbc7d6f42013-09-16 18:11:59 +000015361 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015362 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15363 if (0 != retVal ) {
15364 goto decode_failure_dsp;
15365 }
15366 break;
15367 } else {
15368 goto decode_failure_dsp;
15369 }
15370 break;
15371 }
15372 default: {
petarjbc7d6f42013-09-16 18:11:59 +000015373 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015374 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15375 if (0 != retVal ) {
15376 goto decode_failure_dsp;
15377 }
15378 break;
15379 } else {
15380 goto decode_failure_dsp;
15381 }
15382 break;
15383 }
15384 }
15385 break;
15386 }
15387 case 0x12: { /* ABSQ_S.PH */
15388 switch(sa){
15389 case 0x1: { /* ABSQ_S.QB */
petarjbc7d6f42013-09-16 18:11:59 +000015390 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015391 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15392 if (0 != retVal ) {
15393 goto decode_failure_dsp;
15394 }
15395 break;
15396 } else {
15397 goto decode_failure_dsp;
15398 }
15399 break;
15400 }
15401 default: {
petarjbc7d6f42013-09-16 18:11:59 +000015402 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015403 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15404 if (0 != retVal ) {
15405 goto decode_failure_dsp;
15406 }
15407 break;
15408 } else {
15409 goto decode_failure_dsp;
15410 }
15411 break;
15412 }
15413 }
15414 break;
15415 }
15416 case 0x13: { /* SHLL.QB */
15417 switch(sa) {
15418 case 0x04: /* SHRA.QB */
15419 case 0x05: /* SHRA_R.QB */
15420 case 0x06: /* SHRAV.QB */
15421 case 0x07: /* SHRAV_R.QB */
15422 case 0x19: /* SHLR.PH */
15423 case 0x1B: { /* SHLRV.PH */
petarjbc7d6f42013-09-16 18:11:59 +000015424 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015425 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15426 if (0 != retVal ) {
15427 goto decode_failure_dsp;
15428 }
15429 break;
15430 } else {
15431 goto decode_failure_dsp;
15432 }
15433 break;
15434 }
15435 default: {
petarjbc7d6f42013-09-16 18:11:59 +000015436 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015437 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15438 if (0 != retVal ) {
15439 goto decode_failure_dsp;
15440 }
15441 break;
15442 } else {
15443 goto decode_failure_dsp;
15444 }
15445 break;
15446 }
15447 }
15448 break;
15449 }
15450 case 0x30: { /* DPAQ.W.PH */
15451 switch(sa) {
15452 case 0x0: /* DPA.W.PH */
15453 case 0x18: /* DPAQX_S.W.PH */
15454 case 0x1A: /* DPAQX_SA.W.PH */
15455 case 0x8: /* DPAX.W.PH */
15456 case 0x1: /* DPS.W.PH */
15457 case 0x19: /* DPSQX_S.W.PH */
15458 case 0x1B: /* DPSQX_SA.W.PH */
15459 case 0x9: /* DPSX.W.PH */
15460 case 0x2: { /* MULSA.W.PH */
petarjbc7d6f42013-09-16 18:11:59 +000015461 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015462 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15463 if (0 != retVal ) {
15464 goto decode_failure_dsp;
15465 }
15466 break;
15467 } else {
15468 goto decode_failure_dsp;
15469 }
15470 break;
15471 }
15472 default: {
petarjbc7d6f42013-09-16 18:11:59 +000015473 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015474 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15475 if (0 != retVal ) {
15476 goto decode_failure_dsp;
15477 }
15478 break;
15479 } else {
15480 goto decode_failure_dsp;
15481 }
15482 break;
15483 }
15484 }
15485 break;
15486 }
15487 case 0x18: /* ADDUH.QB/MUL.PH */
15488 case 0x31: { /* APPEND */
petarjbc7d6f42013-09-16 18:11:59 +000015489 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015490 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15491 if (0 != retVal ) {
15492 goto decode_failure_dsp;
15493 }
15494 break;
15495 } else {
15496 goto decode_failure_dsp;
15497 }
15498 }
15499 default:
15500 goto decode_failure;
15501
15502 }
petarjb92a9542013-02-27 22:57:17 +000015503 break; /* Special3 */
sewardj362cf842012-06-07 08:59:53 +000015504
15505 case 0x3B:
petarjbc7d6f42013-09-16 18:11:59 +000015506 if (0x3B == function &&
15507 (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) {
petarjb92a9542013-02-27 22:57:17 +000015508 /*RDHWR*/
15509 DIP("rdhwr r%d, r%d", rt, rd);
15510 if (rd == 29) {
15511 putIReg(rt, getULR());
15512 } else
15513 goto decode_failure;
15514 break;
sewardj362cf842012-06-07 08:59:53 +000015515 } else {
15516 goto decode_failure;
15517 }
15518
petarjb92a9542013-02-27 22:57:17 +000015519 case 0x00: /* Special */
sewardj362cf842012-06-07 08:59:53 +000015520
15521 switch (function) {
15522 case 0x1: {
15523 UInt mov_cc = get_mov_cc(cins);
petarjb92a9542013-02-27 22:57:17 +000015524 if (tf == 0) { /* MOVF */
sewardj362cf842012-06-07 08:59:53 +000015525 DIP("movf r%d, r%d, %d", rd, rs, mov_cc);
petarjb92a9542013-02-27 22:57:17 +000015526 t1 = newTemp(Ity_I1);
15527 t2 = newTemp(Ity_I32);
15528 t3 = newTemp(Ity_I1);
sewardj362cf842012-06-07 08:59:53 +000015529
petarjb92a9542013-02-27 22:57:17 +000015530 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
15531 assign(t2, IRExpr_ITE(mkexpr(t1),
15532 binop(Iop_And32,
15533 binop(Iop_Shr32, getFCSR(),
15534 mkU8(23)),
15535 mkU32(0x1)),
15536 binop(Iop_And32,
15537 binop(Iop_Shr32, getFCSR(),
15538 mkU8(24 + mov_cc)),
15539 mkU32(0x1))
15540 ));
15541 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
15542 putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
15543 } else if (tf == 1) { /* MOVT */
petarjc5b8bb72012-07-16 14:25:05 +000015544 DIP("movt r%d, r%d, %d", rd, rs, mov_cc);
petarjb92a9542013-02-27 22:57:17 +000015545 t1 = newTemp(Ity_I1);
15546 t2 = newTemp(Ity_I32);
15547 t3 = newTemp(Ity_I1);
sewardj362cf842012-06-07 08:59:53 +000015548
petarjb92a9542013-02-27 22:57:17 +000015549 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
15550 assign(t2, IRExpr_ITE(mkexpr(t1),
15551 binop(Iop_And32,
15552 binop(Iop_Shr32, getFCSR(),
15553 mkU8(23)),
15554 mkU32(0x1)),
15555 binop(Iop_And32,
15556 binop(Iop_Shr32, getFCSR(),
15557 mkU8(24 + mov_cc)),
15558 mkU32(0x1))
15559 ));
15560 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
15561 putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
sewardj362cf842012-06-07 08:59:53 +000015562 }
15563 break;
15564 }
petarjb92a9542013-02-27 22:57:17 +000015565 case 0x0A: { /* MOVZ */
petarjc5b8bb72012-07-16 14:25:05 +000015566 DIP("movz r%d, r%d, r%d", rd, rs, rt);
sewardj362cf842012-06-07 08:59:53 +000015567 t1 = newTemp(ty);
15568 t2 = newTemp(ty);
petarjb92a9542013-02-27 22:57:17 +000015569 if (mode64) {
15570 assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
15571 getIReg(rt), mkU64(0x0)))));
15572 assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
15573 getIReg(rt), mkU64(0x0)))));
15574 putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
15575 mkexpr(t1)), binop(Iop_And64, getIReg(rd),mkexpr(t2))));
15576 } else {
sewardj362cf842012-06-07 08:59:53 +000015577 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
15578 mkU32(0x0))));
15579 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
15580 mkU32(0x0))));
15581 putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
15582 mkexpr(t1)), binop(Iop_And32, getIReg(rd),
15583 mkexpr(t2))));
15584 }
15585 break;
15586 }
15587
petarjb92a9542013-02-27 22:57:17 +000015588 case 0x0B: { /* MOVN */
petarjc5b8bb72012-07-16 14:25:05 +000015589 DIP("movn r%d, r%d, r%d", rd, rs, rt);
sewardj362cf842012-06-07 08:59:53 +000015590 t1 = newTemp(ty);
15591 t2 = newTemp(ty);
petarjb92a9542013-02-27 22:57:17 +000015592 if (mode64) {
15593 assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
15594 getIReg(rt), mkU64(0x0)))));
15595 assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
15596 getIReg(rt), mkU64(0x0)))));
15597 putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
15598 mkexpr(t2)), binop(Iop_And64, getIReg(rd),
15599 mkexpr(t1))));
15600 } else {
sewardj362cf842012-06-07 08:59:53 +000015601 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
15602 mkU32(0x0))));
15603 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
15604 mkU32(0x0))));
15605 putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
15606 mkexpr(t2)), binop(Iop_And32, getIReg(rd),
15607 mkexpr(t1))));
15608 }
15609 break;
15610 }
15611
dejanjc3fee0d2013-07-25 09:08:03 +000015612 case 0x18: { /* MULT */
15613 if ( (1 <= ac) && ( 3 >= ac) ) {
petarjbc7d6f42013-09-16 18:11:59 +000015614 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015615 /* If DSP is present -> DSP ASE MULT */
15616 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15617 if (0 != retVal ) {
15618 goto decode_failure_dsp;
15619 }
15620 break;
15621 } else {
15622 goto decode_failure_dsp;
15623 }
15624 } else {
15625 DIP("mult r%d, r%d", rs, rt);
15626 t2 = newTemp(Ity_I64);
sewardj362cf842012-06-07 08:59:53 +000015627
dejanjc3fee0d2013-07-25 09:08:03 +000015628 assign(t2, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
15629 mkNarrowTo32(ty, getIReg(rt))));
sewardj362cf842012-06-07 08:59:53 +000015630
dejanjc3fee0d2013-07-25 09:08:03 +000015631 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
15632 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
15633 break;
15634 }
15635 }
15636 case 0x19: { /* MULTU */
15637 if ( (1 <= ac) && ( 3 >= ac) ) {
petarjbc7d6f42013-09-16 18:11:59 +000015638 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015639 /* If DSP is present -> DSP ASE MULTU */
15640 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15641 if (0 != retVal ) {
15642 goto decode_failure_dsp;
15643 }
15644 break;
15645 } else {
15646 goto decode_failure_dsp;
15647 }
15648 } else {
15649 DIP("multu r%d, r%d", rs, rt);
15650 t2 = newTemp(Ity_I64);
sewardj362cf842012-06-07 08:59:53 +000015651
dejanjc3fee0d2013-07-25 09:08:03 +000015652 assign(t2, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
15653 mkNarrowTo32(ty, getIReg(rt))));
sewardj362cf842012-06-07 08:59:53 +000015654
dejanjc3fee0d2013-07-25 09:08:03 +000015655 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
15656 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
15657 break;
15658 }
15659 }
petarjb92a9542013-02-27 22:57:17 +000015660 case 0x20: { /* ADD */
petarjc5b8bb72012-07-16 14:25:05 +000015661 DIP("add r%d, r%d, r%d", rd, rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015662 IRTemp tmpRs32 = newTemp(Ity_I32);
15663 IRTemp tmpRt32 = newTemp(Ity_I32);
15664
15665 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
15666 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
15667
petarja6a19862012-10-19 14:55:58 +000015668 t0 = newTemp(Ity_I32);
15669 t1 = newTemp(Ity_I32);
15670 t2 = newTemp(Ity_I32);
15671 t3 = newTemp(Ity_I32);
15672 t4 = newTemp(Ity_I32);
15673 /* dst = src0 + src1
dejanjc3fee0d2013-07-25 09:08:03 +000015674 if (sign(src0 ) != sign(src1 ))
petarjb92a9542013-02-27 22:57:17 +000015675 goto no overflow;
dejanjc3fee0d2013-07-25 09:08:03 +000015676 if (sign(dst) == sign(src0 ))
petarjb92a9542013-02-27 22:57:17 +000015677 goto no overflow;
15678 we have overflow! */
sewardj362cf842012-06-07 08:59:53 +000015679
petarjb92a9542013-02-27 22:57:17 +000015680 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
15681 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
petarja6a19862012-10-19 14:55:58 +000015682 assign(t2, unop(Iop_1Uto32,
15683 binop(Iop_CmpEQ32,
15684 binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
15685 mkU32(0x80000000))));
15686
petarjb92a9542013-02-27 22:57:17 +000015687 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
petarja6a19862012-10-19 14:55:58 +000015688 assign(t4, unop(Iop_1Uto32,
15689 binop(Iop_CmpNE32,
15690 binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
15691 mkU32(0x80000000))));
petarjb92a9542013-02-27 22:57:17 +000015692
petarja6a19862012-10-19 14:55:58 +000015693 stmt(IRStmt_Exit(binop(Iop_CmpEQ32,
15694 binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
15695 mkU32(0)),
15696 Ijk_SigFPE_IntOvf,
petarjb92a9542013-02-27 22:57:17 +000015697 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
15698 IRConst_U32(guest_PC_curr_instr + 4),
15699 OFFB_PC));
petarja6a19862012-10-19 14:55:58 +000015700
petarjb92a9542013-02-27 22:57:17 +000015701 putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True));
sewardj362cf842012-06-07 08:59:53 +000015702 break;
petarjb92a9542013-02-27 22:57:17 +000015703 }
sewardj362cf842012-06-07 08:59:53 +000015704 case 0x1A: /* DIV */
petarjc5b8bb72012-07-16 14:25:05 +000015705 DIP("div r%d, r%d", rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015706 if (mode64) {
15707 t2 = newTemp(Ity_I64);
15708
15709 assign(t2, binop(Iop_DivModS64to32,
15710 getIReg(rs), mkNarrowTo32(ty, getIReg(rt))));
15711
15712 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
15713 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
15714 } else {
sewardj362cf842012-06-07 08:59:53 +000015715 t1 = newTemp(Ity_I64);
15716 t2 = newTemp(Ity_I64);
15717
15718 assign(t1, unop(Iop_32Sto64, getIReg(rs)));
15719 assign(t2, binop(Iop_DivModS64to32, mkexpr(t1), getIReg(rt)));
15720
15721 putHI(unop(Iop_64HIto32, mkexpr(t2)));
15722 putLO(unop(Iop_64to32, mkexpr(t2)));
15723 }
15724 break;
15725
15726 case 0x1B: /* DIVU */
petarjc5b8bb72012-07-16 14:25:05 +000015727 DIP("divu r%d, r%d", rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015728 if (mode64) {
15729 t2 = newTemp(Ity_I64);
15730
15731 assign(t2, binop(Iop_DivModU64to32,
15732 getIReg(rs), mkNarrowTo32(ty, getIReg(rt))));
15733
15734 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
15735 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
15736 } else {
sewardj362cf842012-06-07 08:59:53 +000015737 t1 = newTemp(Ity_I64);
15738 t2 = newTemp(Ity_I64);
15739 assign(t1, unop(Iop_32Uto64, getIReg(rs)));
15740 assign(t2, binop(Iop_DivModU64to32, mkexpr(t1), getIReg(rt)));
15741 putHI(unop(Iop_64HIto32, mkexpr(t2)));
15742 putLO(unop(Iop_64to32, mkexpr(t2)));
15743 }
15744 break;
15745
petarjb92a9542013-02-27 22:57:17 +000015746 case 0x1C: /* Doubleword Multiply - DMULT; MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +000015747 DIP("dmult r%u, r%u", rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015748 t0 = newTemp(Ity_I128);
15749
15750 assign(t0, binop(Iop_MullS64, getIReg(rs), getIReg(rt)));
15751
15752 putHI(unop(Iop_128HIto64, mkexpr(t0)));
15753 putLO(unop(Iop_128to64, mkexpr(t0)));
15754 break;
15755
15756 case 0x1D: /* Doubleword Multiply Unsigned - DMULTU; MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +000015757 DIP("dmultu r%u, r%u", rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015758 t0 = newTemp(Ity_I128);
15759
15760 assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
15761
15762 putHI(unop(Iop_128HIto64, mkexpr(t0)));
15763 putLO(unop(Iop_128to64, mkexpr(t0)));
15764 break;
15765
15766 case 0x1E: /* Doubleword Divide DDIV; MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +000015767 DIP("ddiv r%u, r%u", rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015768 t1 = newTemp(Ity_I128);
15769
15770 assign(t1, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt)));
15771
15772 putHI(unop(Iop_128HIto64, mkexpr(t1)));
15773 putLO(unop(Iop_128to64, mkexpr(t1)));
15774 break;
15775
15776 case 0x1F: /* Doubleword Divide Unsigned DDIVU; MIPS64 check this */
petarj1fb1e342013-04-27 02:18:11 +000015777 DIP("ddivu r%u, r%u", rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015778 t1 = newTemp(Ity_I128);
15779 t2 = newTemp(Ity_I128);
15780
15781 assign(t1, binop(Iop_64HLto128, mkU64(0), getIReg(rs)));
15782
15783 assign(t2, binop(Iop_DivModU128to64, mkexpr(t1), getIReg(rt)));
15784
15785 putHI(unop(Iop_128HIto64, mkexpr(t2)));
15786 putLO(unop(Iop_128to64, mkexpr(t2)));
15787 break;
15788
dejanjc3fee0d2013-07-25 09:08:03 +000015789 case 0x10: { /* MFHI */
petarjbc7d6f42013-09-16 18:11:59 +000015790 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015791 /* If DSP is present -> DSP ASE MFHI */
15792 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15793 if (0 != retVal ) {
15794 goto decode_failure;
15795 }
15796 break;
15797 } else {
15798 DIP("mfhi r%d", rd);
15799 putIReg(rd, getHI());
15800 break;
15801 }
15802 }
sewardj362cf842012-06-07 08:59:53 +000015803
dejanjc3fee0d2013-07-25 09:08:03 +000015804 case 0x11: { /* MTHI */
petarjbc7d6f42013-09-16 18:11:59 +000015805 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015806 /* If DSP is present -> DSP ASE MTHI */
15807 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15808 if (0 != retVal ) {
15809 goto decode_failure;
15810 }
15811 break;
15812 } else {
15813 DIP("mthi r%d", rs);
15814 putHI(getIReg(rs));
15815 break;
15816 }
15817 }
sewardj362cf842012-06-07 08:59:53 +000015818
dejanjc3fee0d2013-07-25 09:08:03 +000015819 case 0x12: { /* MFLO */
petarjbc7d6f42013-09-16 18:11:59 +000015820 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015821 /* If DSP is present -> DSP ASE MFLO */
15822 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15823 if (0 != retVal ) {
15824 goto decode_failure;
15825 }
15826 break;
15827 } else {
15828 DIP("mflo r%d", rd);
15829 putIReg(rd, getLO());
15830 break;
15831 }
15832 }
sewardj362cf842012-06-07 08:59:53 +000015833
dejanjc3fee0d2013-07-25 09:08:03 +000015834 case 0x13: { /* MTLO */
petarjbc7d6f42013-09-16 18:11:59 +000015835 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +000015836 /* If DSP is present -> DSP ASE MTLO */
15837 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
15838 if (0 != retVal ) {
15839 goto decode_failure;
15840 }
15841 break;
15842 } else {
15843 DIP("mtlo r%d", rs);
15844 putLO(getIReg(rs));
15845 break;
15846 }
15847 }
sewardj362cf842012-06-07 08:59:53 +000015848
15849 case 0x21: /* ADDU */
petarjc5b8bb72012-07-16 14:25:05 +000015850 DIP("addu r%d, r%d, r%d", rd, rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015851 if (mode64) {
15852 ALU_PATTERN64(Iop_Add32);
15853 } else {
15854 ALU_PATTERN(Iop_Add32);
15855 }
sewardj362cf842012-06-07 08:59:53 +000015856 break;
15857
petarjb92a9542013-02-27 22:57:17 +000015858 case 0x22: { /* SUB */
petarjc5b8bb72012-07-16 14:25:05 +000015859 DIP("sub r%d, r%d, r%d", rd, rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015860 IRTemp tmpRs32 = newTemp(Ity_I32);
15861 IRTemp tmpRt32 = newTemp(Ity_I32);
15862
15863 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
15864 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
petarja6a19862012-10-19 14:55:58 +000015865 t0 = newTemp(Ity_I32);
15866 t1 = newTemp(Ity_I32);
15867 t2 = newTemp(Ity_I32);
15868 t3 = newTemp(Ity_I32);
15869 t4 = newTemp(Ity_I32);
15870 t5 = newTemp(Ity_I32);
15871 /* dst = src0 + (-1 * src1)
petarjb92a9542013-02-27 22:57:17 +000015872 if(sign(src0 ) != sign((-1 * src1) ))
15873 goto no overflow;
15874 if(sign(dst) == sign(src0 ))
15875 goto no overflow;
15876 we have overflow! */
petarja6a19862012-10-19 14:55:58 +000015877
petarjb92a9542013-02-27 22:57:17 +000015878 assign(t5, binop(Iop_Mul32, mkexpr(tmpRt32), mkU32(-1)));
15879 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(t5)));
15880 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(t5)));
15881 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
15882 mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
petarja6a19862012-10-19 14:55:58 +000015883
petarjb92a9542013-02-27 22:57:17 +000015884 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
15885 assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
15886 mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
petarja6a19862012-10-19 14:55:58 +000015887
petarjb92a9542013-02-27 22:57:17 +000015888 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
15889 mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
15890 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
15891 IRConst_U32(guest_PC_curr_instr + 4),
15892 OFFB_PC));
petarja6a19862012-10-19 14:55:58 +000015893
petarjb92a9542013-02-27 22:57:17 +000015894 putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True));
sewardj362cf842012-06-07 08:59:53 +000015895 break;
petarjb92a9542013-02-27 22:57:17 +000015896 }
sewardj362cf842012-06-07 08:59:53 +000015897 case 0x23: /* SUBU */
petarjc5b8bb72012-07-16 14:25:05 +000015898 DIP("subu r%d, r%d, r%d", rd, rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015899 if (mode64) {
15900 ALU_PATTERN64(Iop_Sub32);
15901 } else {
15902 ALU_PATTERN(Iop_Sub32);
15903 }
sewardj362cf842012-06-07 08:59:53 +000015904 break;
15905
15906 case 0x24: /* AND */
petarjc5b8bb72012-07-16 14:25:05 +000015907 DIP("and r%d, r%d, r%d", rd, rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015908 if (mode64) {
15909 ALU_PATTERN(Iop_And64);
15910 } else {
15911 ALU_PATTERN(Iop_And32);
15912 }
sewardj362cf842012-06-07 08:59:53 +000015913 break;
15914
15915 case 0x25: /* OR */
15916 DIP("or r%d, r%d, r%d", rd, rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015917 if (mode64) {
15918 ALU_PATTERN(Iop_Or64);
15919 } else {
15920 ALU_PATTERN(Iop_Or32);
15921 }
sewardj362cf842012-06-07 08:59:53 +000015922 break;
15923
15924 case 0x26: /* XOR */
petarjc5b8bb72012-07-16 14:25:05 +000015925 DIP("xor r%d, r%d, r%d", rd, rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015926 if (mode64) {
15927 ALU_PATTERN(Iop_Xor64);
15928 } else {
15929 ALU_PATTERN(Iop_Xor32);
15930 }
sewardj362cf842012-06-07 08:59:53 +000015931 break;
15932
15933 case 0x27: /* NOR */
petarjc5b8bb72012-07-16 14:25:05 +000015934 DIP("nor r%d, r%d, r%d", rd, rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015935 if (mode64)
15936 putIReg(rd, unop(Iop_Not64, binop(Iop_Or64, getIReg(rs),
15937 getIReg(rt))));
15938 else
15939 putIReg(rd, unop(Iop_Not32, binop(Iop_Or32, getIReg(rs),
15940 getIReg(rt))));
sewardj362cf842012-06-07 08:59:53 +000015941 break;
15942
15943 case 0x08: /* JR */
15944 DIP("jr r%d", rs);
15945 t0 = newTemp(ty);
15946 assign(t0, getIReg(rs));
15947 lastn = mkexpr(t0);
15948 break;
15949
15950 case 0x09: /* JALR */
15951 DIP("jalr r%d r%d", rd, rs);
petarjb92a9542013-02-27 22:57:17 +000015952 if (mode64) {
15953 putIReg(rd, mkU64(guest_PC_curr_instr + 8));
15954 t0 = newTemp(Ity_I64);
15955 assign(t0, getIReg(rs));
15956 lastn = mkexpr(t0);
15957 } else {
15958 putIReg(rd, mkU32(guest_PC_curr_instr + 8));
15959 t0 = newTemp(Ity_I32);
15960 assign(t0, getIReg(rs));
15961 lastn = mkexpr(t0);
15962 }
sewardj362cf842012-06-07 08:59:53 +000015963 break;
15964
15965 case 0x0C: /* SYSCALL */
15966 DIP("syscall");
petarjb92a9542013-02-27 22:57:17 +000015967 if (mode64)
15968 putPC(mkU64(guest_PC_curr_instr + 4));
15969 else
15970 putPC(mkU32(guest_PC_curr_instr + 4));
sewardj362cf842012-06-07 08:59:53 +000015971 dres.jk_StopHere = Ijk_Sys_syscall;
15972 dres.whatNext = Dis_StopHere;
15973 break;
15974
15975 case 0x2A: /* SLT */
petarjc5b8bb72012-07-16 14:25:05 +000015976 DIP("slt r%d, r%d, r%d", rd, rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015977 if (mode64)
15978 putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
15979 getIReg(rt))));
15980 else
15981 putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
15982 getIReg(rt))));
sewardj362cf842012-06-07 08:59:53 +000015983 break;
15984
15985 case 0x2B: /* SLTU */
petarjc5b8bb72012-07-16 14:25:05 +000015986 DIP("sltu r%d, r%d, r%d", rd, rs, rt);
petarjb92a9542013-02-27 22:57:17 +000015987 if (mode64)
15988 putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
15989 getIReg(rt))));
15990 else
15991 putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
15992 getIReg(rt))));
sewardj362cf842012-06-07 08:59:53 +000015993 break;
15994
petarjb92a9542013-02-27 22:57:17 +000015995 case 0x00: { /* SLL */
petarjc5b8bb72012-07-16 14:25:05 +000015996 DIP("sll r%d, r%d, %d", rd, rt, sa);
petarjb92a9542013-02-27 22:57:17 +000015997 IRTemp tmpRt32 = newTemp(Ity_I32);
15998 IRTemp tmpSh32 = newTemp(Ity_I32);
15999 IRTemp tmpRd = newTemp(Ity_I64);
16000 if (mode64) {
16001 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
16002 assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkU8(sa)));
16003 assign(tmpRd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
16004 putIReg(rd, mkexpr(tmpRd));
16005 } else
16006 SXX_PATTERN(Iop_Shl32);
sewardj362cf842012-06-07 08:59:53 +000016007 break;
petarjb92a9542013-02-27 22:57:17 +000016008 }
sewardj362cf842012-06-07 08:59:53 +000016009
petarjb92a9542013-02-27 22:57:17 +000016010 case 0x04: { /* SLLV */
petarjc5b8bb72012-07-16 14:25:05 +000016011 DIP("sllv r%d, r%d, r%d", rd, rt, rs);
petarjb92a9542013-02-27 22:57:17 +000016012 if (mode64) {
16013 IRTemp tmpRs8 = newTemp(Ity_I8);
16014 IRTemp tmpRt32 = newTemp(Ity_I32);
16015 IRTemp tmpSh32 = newTemp(Ity_I32);
16016 IRTemp tmp = newTemp(ty);
16017 assign(tmp, binop(mkSzOp(ty, Iop_And8), getIReg(rs),
16018 mkSzImm(ty, 31)));
16019 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
16020 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
16021 assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkexpr(tmpRs8)));
16022 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
16023 } else {
16024 SXXV_PATTERN(Iop_Shl32);
16025 }
sewardj362cf842012-06-07 08:59:53 +000016026 break;
petarjb92a9542013-02-27 22:57:17 +000016027 }
sewardj362cf842012-06-07 08:59:53 +000016028
16029 case 0x03: /* SRA */
petarjc5b8bb72012-07-16 14:25:05 +000016030 DIP("sra r%d, r%d, %d", rd, rt, sa);
petarjb92a9542013-02-27 22:57:17 +000016031 if (mode64) {
16032 IRTemp tmpRt32 = newTemp(Ity_I32);
16033 IRTemp tmpSh32 = newTemp(Ity_I32);
16034
16035 t1 = newTemp(Ity_I64);
16036 t2 = newTemp(Ity_I64);
16037 t3 = newTemp(Ity_I64);
16038
16039 assign(t1, binop(Iop_And64, getIReg(rt), /* hi */
petarjfdb2a4c2013-03-02 02:37:01 +000016040 mkU64(0xFFFFFFFF00000000ULL)));
petarjb92a9542013-02-27 22:57:17 +000016041
16042 assign(t2, binop(Iop_Sar64, mkexpr(t1), mkU8(sa)));
16043
16044 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
16045 assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkU8(sa)));
16046
16047 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
16048 } else {
16049 SXX_PATTERN(Iop_Sar32);
16050 }
sewardj362cf842012-06-07 08:59:53 +000016051 break;
16052
16053 case 0x07: /* SRAV */
petarjc5b8bb72012-07-16 14:25:05 +000016054 DIP("srav r%d, r%d, r%d", rd, rt, rs);
petarjb92a9542013-02-27 22:57:17 +000016055 if (mode64) {
16056 IRTemp tmpRt32 = newTemp(Ity_I32);
16057 IRTemp tmpSh32 = newTemp(Ity_I32);
16058
16059 t1 = newTemp(Ity_I64);
16060 t2 = newTemp(Ity_I64);
16061 t3 = newTemp(Ity_I64);
16062 t4 = newTemp(Ity_I8);
16063
16064 assign(t4, unop(Iop_32to8, binop(Iop_And32,
16065 mkNarrowTo32(ty, getIReg(rs)), mkU32(0x0000001F))));
16066
16067 assign(t1, binop(Iop_And64, getIReg(rt), /* hi */
petarjfdb2a4c2013-03-02 02:37:01 +000016068 mkU64(0xFFFFFFFF00000000ULL)));
petarjb92a9542013-02-27 22:57:17 +000016069
16070 assign(t2, binop(Iop_Sar64, mkexpr(t1), mkexpr(t4)));
16071
16072 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
16073 assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkexpr(t4)));
16074
16075 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
16076 } else {
16077 SXXV_PATTERN(Iop_Sar32);
16078 }
sewardj362cf842012-06-07 08:59:53 +000016079 break;
16080
16081 case 0x02: { /* SRL */
16082 rot = get_rot(cins);
16083 if (rot) {
petarjc5b8bb72012-07-16 14:25:05 +000016084 DIP("rotr r%d, r%d, %d", rd, rt, sa);
sewardj362cf842012-06-07 08:59:53 +000016085 putIReg(rd, mkWidenFrom32(ty, genROR32(mkNarrowTo32(ty,
petarjb92a9542013-02-27 22:57:17 +000016086 getIReg(rt)), sa), True));
sewardj362cf842012-06-07 08:59:53 +000016087 } else {
petarjc5b8bb72012-07-16 14:25:05 +000016088 DIP("srl r%d, r%d, %d", rd, rt, sa);
petarjb92a9542013-02-27 22:57:17 +000016089 if (mode64) {
16090 IRTemp tmpSh32 = newTemp(Ity_I32);
16091 IRTemp tmpRt32 = newTemp(Ity_I32);
16092
16093 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
16094 assign(tmpSh32, binop(Iop_Shr32, mkexpr(tmpRt32), mkU8(sa)));
16095 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
16096 } else {
16097 SXX_PATTERN(Iop_Shr32);
16098 }
sewardj362cf842012-06-07 08:59:53 +000016099 }
16100 break;
16101 }
16102
16103 case 0x06: {
16104 rot = get_rotv(cins);
16105 if (rot) {
petarjc5b8bb72012-07-16 14:25:05 +000016106 DIP("rotrv r%d, r%d, r%d", rd, rt, rs);
sewardj362cf842012-06-07 08:59:53 +000016107 putIReg(rd, mkWidenFrom32(ty, genRORV32(mkNarrowTo32(ty,
petarjb92a9542013-02-27 22:57:17 +000016108 getIReg(rt)), mkNarrowTo32(ty, getIReg(rs))), True));
sewardj362cf842012-06-07 08:59:53 +000016109 break;
petarjb92a9542013-02-27 22:57:17 +000016110 } else { /* SRLV */
petarjc5b8bb72012-07-16 14:25:05 +000016111 DIP("srlv r%d, r%d, r%d", rd, rt, rs);
petarjb92a9542013-02-27 22:57:17 +000016112 if (mode64) {
16113 SXXV_PATTERN64(Iop_Shr32);
16114 } else {
16115 SXXV_PATTERN(Iop_Shr32);
16116 }
sewardj362cf842012-06-07 08:59:53 +000016117 break;
16118 }
dejanjc3fee0d2013-07-25 09:08:03 +000016119 }
sewardj362cf842012-06-07 08:59:53 +000016120
16121 case 0x0D: /* BREAK */
petarj1fb1e342013-04-27 02:18:11 +000016122 DIP("break 0x%x", trap_code);
petarjb92a9542013-02-27 22:57:17 +000016123 if (mode64)
16124 jmp_lit64(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
16125 else
16126 jmp_lit32(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
sewardj362cf842012-06-07 08:59:53 +000016127 vassert(dres.whatNext == Dis_StopHere);
16128 break;
16129
petarjb92a9542013-02-27 22:57:17 +000016130 case 0x30: { /* TGE */
16131 DIP("tge r%d, r%d %d", rs, rt, trap_code);
16132 if (mode64) {
16133 if (trap_code == 7)
16134 stmt (IRStmt_Exit (unop (Iop_Not1,
16135 binop (Iop_CmpLT64S,
16136 getIReg (rs),
16137 getIReg (rt))),
16138 Ijk_SigFPE_IntDiv,
16139 IRConst_U64(guest_PC_curr_instr + 4),
16140 OFFB_PC));
16141 else if (trap_code == 6)
16142 stmt (IRStmt_Exit (unop (Iop_Not1,
16143 binop (Iop_CmpLT64S,
16144 getIReg (rs),
16145 getIReg (rt))),
16146 Ijk_SigFPE_IntOvf,
16147 IRConst_U64(guest_PC_curr_instr + 4),
16148 OFFB_PC));
16149 else
16150 stmt (IRStmt_Exit (unop (Iop_Not1,
16151 binop (Iop_CmpLT64S,
16152 getIReg (rs),
16153 getIReg (rt))),
16154 Ijk_SigTRAP,
16155 IRConst_U64(guest_PC_curr_instr + 4),
16156 OFFB_PC));
16157 } else {
16158 if (trap_code == 7)
16159 stmt (IRStmt_Exit (unop (Iop_Not1,
16160 binop (Iop_CmpLT32S,
16161 getIReg (rs),
16162 getIReg (rt))),
16163 Ijk_SigFPE_IntDiv,
16164 IRConst_U32(guest_PC_curr_instr + 4),
16165 OFFB_PC));
16166 else if (trap_code == 6)
16167 stmt (IRStmt_Exit (unop (Iop_Not1,
16168 binop (Iop_CmpLT32S,
16169 getIReg (rs),
16170 getIReg (rt))),
16171 Ijk_SigFPE_IntOvf,
16172 IRConst_U32(guest_PC_curr_instr + 4),
16173 OFFB_PC));
16174 else
16175 stmt (IRStmt_Exit (unop (Iop_Not1,
16176 binop (Iop_CmpLT32S,
16177 getIReg (rs),
16178 getIReg (rt))),
16179 Ijk_SigTRAP,
16180 IRConst_U32(guest_PC_curr_instr + 4),
16181 OFFB_PC));
16182 }
sewardj362cf842012-06-07 08:59:53 +000016183 break;
16184 }
petarjb92a9542013-02-27 22:57:17 +000016185 case 0x31: { /* TGEU */
16186 DIP("tgeu r%d, r%d %d", rs, rt, trap_code);
16187 if (mode64) {
16188 if (trap_code == 7)
16189 stmt (IRStmt_Exit (unop (Iop_Not1,
16190 binop (Iop_CmpLT64U,
16191 getIReg (rs),
16192 getIReg (rt))),
16193 Ijk_SigFPE_IntDiv,
16194 IRConst_U64(guest_PC_curr_instr + 4),
16195 OFFB_PC));
16196 else if (trap_code == 6)
16197 stmt (IRStmt_Exit (unop (Iop_Not1,
16198 binop (Iop_CmpLT64U,
16199 getIReg (rs),
16200 getIReg (rt))),
16201 Ijk_SigFPE_IntOvf,
16202 IRConst_U64(guest_PC_curr_instr + 4),
16203 OFFB_PC));
16204 else
16205 stmt (IRStmt_Exit (unop (Iop_Not1,
16206 binop (Iop_CmpLT64U,
16207 getIReg (rs),
16208 getIReg (rt))),
16209 Ijk_SigTRAP,
16210 IRConst_U64(guest_PC_curr_instr + 4),
16211 OFFB_PC));
16212 } else {
16213 if (trap_code == 7)
16214 stmt (IRStmt_Exit (unop (Iop_Not1,
16215 binop (Iop_CmpLT32U,
16216 getIReg (rs),
16217 getIReg (rt))),
16218 Ijk_SigFPE_IntDiv,
16219 IRConst_U32(guest_PC_curr_instr + 4),
16220 OFFB_PC));
16221 else if (trap_code == 6)
16222 stmt (IRStmt_Exit (unop (Iop_Not1,
16223 binop (Iop_CmpLT32U,
16224 getIReg (rs),
16225 getIReg (rt))),
16226 Ijk_SigFPE_IntOvf,
16227 IRConst_U32(guest_PC_curr_instr + 4),
16228 OFFB_PC));
16229 else
16230 stmt (IRStmt_Exit (unop (Iop_Not1,
16231 binop (Iop_CmpLT32U,
16232 getIReg (rs),
16233 getIReg (rt))),
16234 Ijk_SigTRAP,
16235 IRConst_U32(guest_PC_curr_instr + 4),
16236 OFFB_PC));
16237 }
sewardj362cf842012-06-07 08:59:53 +000016238 break;
16239 }
petarjb92a9542013-02-27 22:57:17 +000016240 case 0x32: { /* TLT */
16241 DIP("tlt r%d, r%d %d", rs, rt, trap_code);
16242 if (mode64) {
16243 if (trap_code == 7)
16244 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
16245 getIReg(rt)), Ijk_SigFPE_IntDiv,
16246 IRConst_U64(guest_PC_curr_instr + 4),
16247 OFFB_PC));
16248 else if (trap_code == 6)
16249 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
16250 getIReg(rt)), Ijk_SigFPE_IntOvf,
16251 IRConst_U64(guest_PC_curr_instr + 4),
16252 OFFB_PC));
16253 else
16254 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
16255 getIReg(rt)), Ijk_SigTRAP,
16256 IRConst_U64(guest_PC_curr_instr + 4),
16257 OFFB_PC));
16258 } else {
16259 if (trap_code == 7)
16260 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
16261 getIReg(rt)), Ijk_SigFPE_IntDiv,
16262 IRConst_U32(guest_PC_curr_instr + 4),
16263 OFFB_PC));
16264 else if (trap_code == 6)
16265 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
16266 getIReg(rt)), Ijk_SigFPE_IntOvf,
16267 IRConst_U32(guest_PC_curr_instr + 4),
16268 OFFB_PC));
16269 else
16270 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
16271 getIReg(rt)), Ijk_SigTRAP,
16272 IRConst_U32(guest_PC_curr_instr + 4),
16273 OFFB_PC));
16274 }
sewardj362cf842012-06-07 08:59:53 +000016275 break;
16276 }
petarjb92a9542013-02-27 22:57:17 +000016277 case 0x33: { /* TLTU */
16278 DIP("tltu r%d, r%d %d", rs, rt, trap_code);
16279 if (mode64) {
16280 if (trap_code == 7)
16281 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
16282 getIReg(rt)), Ijk_SigFPE_IntDiv,
16283 IRConst_U64(guest_PC_curr_instr + 4),
16284 OFFB_PC));
16285 else if (trap_code == 6)
16286 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
16287 getIReg(rt)), Ijk_SigFPE_IntOvf,
16288 IRConst_U64(guest_PC_curr_instr + 4),
16289 OFFB_PC));
16290 else
16291 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
16292 getIReg(rt)), Ijk_SigTRAP,
16293 IRConst_U64(guest_PC_curr_instr + 4),
16294 OFFB_PC));
16295 } else {
16296 if (trap_code == 7)
16297 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
16298 getIReg(rt)), Ijk_SigFPE_IntDiv,
16299 IRConst_U32(guest_PC_curr_instr + 4),
16300 OFFB_PC));
16301 else if (trap_code == 6)
16302 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
16303 getIReg(rt)), Ijk_SigFPE_IntOvf,
16304 IRConst_U32(guest_PC_curr_instr + 4),
16305 OFFB_PC));
16306 else
16307 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
16308 getIReg (rt)), Ijk_SigTRAP,
16309 IRConst_U32(guest_PC_curr_instr + 4),
16310 OFFB_PC));
16311 }
sewardj362cf842012-06-07 08:59:53 +000016312 break;
16313 }
petarjb92a9542013-02-27 22:57:17 +000016314 case 0x34: { /* TEQ */
16315 DIP("teq r%d, r%d, %d", rs, rt, trap_code);
16316 if (mode64) {
16317 if (trap_code == 7)
16318 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
16319 getIReg(rt)), Ijk_SigFPE_IntDiv,
16320 IRConst_U64(guest_PC_curr_instr + 4),
16321 OFFB_PC));
16322 else if (trap_code == 6)
16323 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
16324 getIReg(rt)), Ijk_SigFPE_IntOvf,
16325 IRConst_U64(guest_PC_curr_instr + 4),
16326 OFFB_PC));
16327 else
16328 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
16329 getIReg(rt)), Ijk_SigTRAP,
16330 IRConst_U64(guest_PC_curr_instr + 4),
16331 OFFB_PC));
16332 } else {
16333 if (trap_code == 7)
16334 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
16335 getIReg(rt)), Ijk_SigFPE_IntDiv,
16336 IRConst_U32(guest_PC_curr_instr + 4),
16337 OFFB_PC));
16338 else if (trap_code == 6)
16339 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
16340 getIReg(rt)), Ijk_SigFPE_IntOvf,
16341 IRConst_U32(guest_PC_curr_instr + 4),
16342 OFFB_PC));
16343 else
16344 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
16345 getIReg(rt)), Ijk_SigTRAP,
16346 IRConst_U32(guest_PC_curr_instr + 4),
16347 OFFB_PC));
16348 }
sewardj362cf842012-06-07 08:59:53 +000016349 break;
16350 }
petarjb92a9542013-02-27 22:57:17 +000016351 case 0x36: { /* TNE */
16352 DIP("tne r%d, r%d %d", rs, rt, trap_code);
16353 if (mode64) {
16354 if (trap_code == 7)
16355 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
16356 getIReg(rt)), Ijk_SigFPE_IntDiv,
16357 IRConst_U64(guest_PC_curr_instr + 4),
16358 OFFB_PC));
16359 else if (trap_code == 6)
16360 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
16361 getIReg(rt)), Ijk_SigFPE_IntOvf,
16362 IRConst_U64(guest_PC_curr_instr + 4),
16363 OFFB_PC));
16364 else
16365 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
16366 getIReg(rt)), Ijk_SigTRAP,
16367 IRConst_U64(guest_PC_curr_instr + 4),
16368 OFFB_PC));
16369 } else {
16370 if (trap_code == 7)
16371 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
16372 getIReg(rt)), Ijk_SigFPE_IntDiv,
16373 IRConst_U32(guest_PC_curr_instr + 4),
16374 OFFB_PC));
16375 else if (trap_code == 6)
16376 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
16377 getIReg(rt)), Ijk_SigFPE_IntOvf,
16378 IRConst_U32(guest_PC_curr_instr + 4),
16379 OFFB_PC));
16380 else
16381 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
16382 getIReg(rt)), Ijk_SigTRAP,
16383 IRConst_U32(guest_PC_curr_instr + 4),
16384 OFFB_PC));
16385 }
sewardj362cf842012-06-07 08:59:53 +000016386 break;
16387 }
petarjb92a9542013-02-27 22:57:17 +000016388 case 0x14:
16389 case 0x16:
16390 case 0x17: /* DSLLV, DROTRV:DSRLV, DSRAV */
16391 case 0x38:
16392 case 0x3A:
16393 case 0x3B: /* DSLL, DROTL:DSRL, DSRA */
16394 case 0x3C:
16395 case 0x3E:
16396 case 0x3F: /* DSLL32, DROTR32:DSRL32, DSRA32 */
16397 if (dis_instr_shrt(cins))
16398 break;
16399 goto decode_failure;
16400
sewardj74142b82013-08-08 10:28:59 +000016401 case 0x0F: /* SYNC */
petarj1fb1e342013-04-27 02:18:11 +000016402 DIP("sync 0x%x", sel);
sewardj74142b82013-08-08 10:28:59 +000016403 /* Just ignore it. */
sewardj362cf842012-06-07 08:59:53 +000016404 break;
sewardj362cf842012-06-07 08:59:53 +000016405
petarjb92a9542013-02-27 22:57:17 +000016406 case 0x2C: { /* Doubleword Add - DADD; MIPS64 */
16407 DIP("dadd r%d, r%d, r%d", rd, rs, rt);
petarjb92a9542013-02-27 22:57:17 +000016408 IRTemp tmpRs64 = newTemp(Ity_I64);
16409 IRTemp tmpRt64 = newTemp(Ity_I64);
16410
16411 assign(tmpRs64, getIReg(rs));
16412 assign(tmpRt64, getIReg(rt));
16413
16414 t0 = newTemp(Ity_I64);
16415 t1 = newTemp(Ity_I64);
16416 t2 = newTemp(Ity_I64);
16417 t3 = newTemp(Ity_I64);
16418 t4 = newTemp(Ity_I64);
16419 /* dst = src0 + src1
16420 if(sign(src0 ) != sign(src1 ))
16421 goto no overflow;
16422 if(sign(dst) == sign(src0 ))
16423 goto no overflow;
16424 we have overflow! */
16425
16426 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
16427 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
16428 assign(t2, unop(Iop_1Uto64,
16429 binop(Iop_CmpEQ64,
16430 binop(Iop_And64, mkexpr(t1),
petarjfdb2a4c2013-03-02 02:37:01 +000016431 mkU64(0x8000000000000000ULL)),
16432 mkU64(0x8000000000000000ULL))));
petarjb92a9542013-02-27 22:57:17 +000016433
16434 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
16435 assign(t4, unop(Iop_1Uto64,
16436 binop(Iop_CmpNE64,
16437 binop(Iop_And64, mkexpr(t3),
petarjfdb2a4c2013-03-02 02:37:01 +000016438 mkU64(0x8000000000000000ULL)),
16439 mkU64(0x8000000000000000ULL))));
petarjb92a9542013-02-27 22:57:17 +000016440
16441 stmt(IRStmt_Exit(binop(Iop_CmpEQ64,
16442 binop(Iop_Or64, mkexpr(t2), mkexpr(t4)),
16443 mkU64(0)),
16444 Ijk_SigFPE_IntOvf,
16445 IRConst_U64(guest_PC_curr_instr + 4),
16446 OFFB_PC));
16447
16448 putIReg(rd, mkexpr(t0));
16449 break;
16450 }
16451
16452 case 0x2D: /* Doubleword Add Unsigned - DADDU; MIPS64 */
16453 DIP("daddu r%d, r%d, r%d", rd, rs, rt);
16454 ALU_PATTERN(Iop_Add64);
16455 break;
16456
16457 case 0x2E: { /* Doubleword Subtract - DSUB; MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +000016458 DIP("dsub r%u, r%u, r%u", rd, rs, rt);
petarjb92a9542013-02-27 22:57:17 +000016459 IRTemp tmpRs64 = newTemp(Ity_I64);
16460 IRTemp tmpRt64 = newTemp(Ity_I64);
16461
16462 assign(tmpRs64, getIReg(rs));
16463 assign(tmpRt64, getIReg(rt));
16464 t0 = newTemp(Ity_I64);
16465 t1 = newTemp(Ity_I64);
16466 t2 = newTemp(Ity_I64);
16467 t3 = newTemp(Ity_I64);
16468 t4 = newTemp(Ity_I64);
16469 t5 = newTemp(Ity_I64);
16470 /* dst = src0 + (-1 * src1)
16471 if(sign(src0 ) != sign((-1 * src1) ))
16472 goto no overflow;
16473 if(sign(dst) == sign(src0 ))
16474 goto no overflow;
16475 we have overflow! */
16476
petarjfdb2a4c2013-03-02 02:37:01 +000016477 assign(t5, binop(Iop_Mul64,
16478 mkexpr(tmpRt64),
16479 mkU64(0xffffffffffffffffULL)));
petarjb92a9542013-02-27 22:57:17 +000016480 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(t5)));
16481 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(t5)));
petarjfdb2a4c2013-03-02 02:37:01 +000016482 assign(t2, unop(Iop_1Sto64,
16483 binop(Iop_CmpEQ64,
16484 binop(Iop_And64,
16485 mkexpr(t1),
16486 mkU64(0x8000000000000000ULL)),
16487 mkU64(0x8000000000000000ULL))));
petarjb92a9542013-02-27 22:57:17 +000016488
16489 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
petarjfdb2a4c2013-03-02 02:37:01 +000016490 assign(t4, unop(Iop_1Sto64,
16491 binop(Iop_CmpNE64,
16492 binop(Iop_And64,
16493 mkexpr(t3),
16494 mkU64(0x8000000000000000ULL)),
16495 mkU64(0x8000000000000000ULL))));
petarjb92a9542013-02-27 22:57:17 +000016496
16497 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
16498 mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
16499 IRConst_U64(guest_PC_curr_instr + 4),
16500 OFFB_PC));
16501
16502 putIReg(rd, binop(Iop_Sub64, getIReg(rs), getIReg(rt)));
16503 break;
16504 }
16505
16506 case 0x2F: /* Doubleword Subtract Unsigned - DSUBU; MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +000016507 DIP("dsub r%u, r%u,r%u", rd, rt, rt);
petarjb92a9542013-02-27 22:57:17 +000016508 ALU_PATTERN(Iop_Sub64);
16509 break;
16510
sewardj362cf842012-06-07 08:59:53 +000016511 default:
16512 goto decode_failure;
16513 }
16514 break;
16515
petarjb92a9542013-02-27 22:57:17 +000016516 case 0x01: /* Regimm */
sewardj362cf842012-06-07 08:59:53 +000016517
16518 switch (rt) {
sewardj362cf842012-06-07 08:59:53 +000016519 case 0x00: /* BLTZ */
petarjc5b8bb72012-07-16 14:25:05 +000016520 DIP("bltz r%d, %d", rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016521 if (mode64) {
16522 if (!dis_instr_branch(cins, &dres, resteerOkFn,
16523 callback_opaque, &bstmt))
16524 goto decode_failure;
16525 } else
16526 dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
16527 mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
16528 break;
16529
16530 case 0x01: /* BGEZ */
16531 DIP("bgez r%d, %d", rs, imm);
16532 if (mode64) {
16533 if (!dis_instr_branch(cins, &dres, resteerOkFn,
16534 callback_opaque, &bstmt))
16535 goto decode_failure;
16536 } else
16537 dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
16538 mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
sewardj362cf842012-06-07 08:59:53 +000016539 break;
16540
16541 case 0x02: /* BLTZL */
petarjc5b8bb72012-07-16 14:25:05 +000016542 DIP("bltzl r%d, %d", rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016543 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
petarjfdb2a4c2013-03-02 02:37:01 +000016544 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
16545 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
16546 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
16547 imm);
petarjb92a9542013-02-27 22:57:17 +000016548 break;
16549
16550 case 0x03: /* BGEZL */
16551 DIP("bgezl r%d, %d", rs, imm);
16552 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
petarjfdb2a4c2013-03-02 02:37:01 +000016553 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
16554 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
16555 mode64 ? mkU64(0x0) : mkU32(0x0)), imm);
sewardj362cf842012-06-07 08:59:53 +000016556 break;
16557
16558 case 0x10: /* BLTZAL */
petarjc5b8bb72012-07-16 14:25:05 +000016559 DIP("bltzal r%d, %d", rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016560 if (mode64) {
16561 if (!dis_instr_branch(cins, &dres, resteerOkFn,
16562 callback_opaque, &bstmt))
16563 goto decode_failure;
16564 } else
16565 dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
16566 mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
sewardj362cf842012-06-07 08:59:53 +000016567 break;
16568
16569 case 0x12: /* BLTZALL */
petarjc5b8bb72012-07-16 14:25:05 +000016570 DIP("bltzall r%d, %d", rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016571 putIReg(31, mode64 ? mkU64(guest_PC_curr_instr + 8) :
16572 mkU32(guest_PC_curr_instr + 8));
16573 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
petarjfdb2a4c2013-03-02 02:37:01 +000016574 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
16575 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
16576 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
16577 imm);
sewardj362cf842012-06-07 08:59:53 +000016578 break;
16579
16580 case 0x11: /* BGEZAL */
petarjc5b8bb72012-07-16 14:25:05 +000016581 DIP("bgezal r%d, %d", rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016582 if (mode64) {
16583 if (!dis_instr_branch(cins, &dres, resteerOkFn,
16584 callback_opaque, &bstmt))
16585 goto decode_failure;
16586 } else
16587 dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
16588 mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
sewardj362cf842012-06-07 08:59:53 +000016589 break;
16590
16591 case 0x13: /* BGEZALL */
petarjc5b8bb72012-07-16 14:25:05 +000016592 DIP("bgezall r%d, %d", rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016593 if (mode64) {
16594 putIReg(31, mkU64(guest_PC_curr_instr + 8));
petarjfdb2a4c2013-03-02 02:37:01 +000016595 lastn = dis_branch_likely(binop(Iop_CmpNE64,
16596 binop(Iop_And64,
16597 getIReg(rs),
16598 mkU64(0x8000000000000000ULL)),
16599 mkU64(0x0)),
16600 imm);
petarjb92a9542013-02-27 22:57:17 +000016601 } else {
16602 putIReg(31, mkU32(guest_PC_curr_instr + 8));
16603 lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
16604 getIReg(rs), mkU32(0x80000000)),
16605 mkU32(0x0)), imm);
16606 }
sewardj362cf842012-06-07 08:59:53 +000016607 break;
16608
petarjb92a9542013-02-27 22:57:17 +000016609 case 0x08: /* TGEI */
16610 DIP("tgei r%d, %d %d", rs, imm, trap_code);
16611 if (mode64) {
16612 stmt (IRStmt_Exit (unop (Iop_Not1,
16613 binop (Iop_CmpLT64S,
16614 getIReg (rs),
16615 mkU64 (extend_s_16to64 (imm)))),
16616 Ijk_SigTRAP,
16617 IRConst_U64(guest_PC_curr_instr + 4),
16618 OFFB_PC));
16619 } else {
16620 stmt (IRStmt_Exit (unop (Iop_Not1,
16621 binop (Iop_CmpLT32S,
16622 getIReg (rs),
16623 mkU32 (extend_s_16to32 (imm)))),
16624 Ijk_SigTRAP,
16625 IRConst_U32(guest_PC_curr_instr + 4),
16626 OFFB_PC));
16627 }
sewardj362cf842012-06-07 08:59:53 +000016628 break;
petarjb92a9542013-02-27 22:57:17 +000016629
16630 case 0x09: { /* TGEIU */
16631 DIP("tgeiu r%d, %d %d", rs, imm, trap_code);
16632 if (mode64) {
16633 stmt (IRStmt_Exit (unop (Iop_Not1,
16634 binop (Iop_CmpLT64U,
16635 getIReg (rs),
16636 mkU64 (extend_s_16to64 (imm)))),
16637 Ijk_SigTRAP,
16638 IRConst_U64(guest_PC_curr_instr + 4),
16639 OFFB_PC));
16640 } else {
16641 stmt (IRStmt_Exit (unop (Iop_Not1,
16642 binop (Iop_CmpLT32U,
16643 getIReg (rs),
16644 mkU32 (extend_s_16to32 (imm)))),
16645 Ijk_SigTRAP,
16646 IRConst_U32(guest_PC_curr_instr + 4),
16647 OFFB_PC));
16648 }
sewardj362cf842012-06-07 08:59:53 +000016649 break;
16650 }
dejanjc3fee0d2013-07-25 09:08:03 +000016651 case 0x0A: { /* TLTI */
petarjb92a9542013-02-27 22:57:17 +000016652 DIP("tlti r%d, %d %d", rs, imm, trap_code);
16653 if (mode64) {
16654 stmt (IRStmt_Exit (binop (Iop_CmpLT64S, getIReg (rs),
16655 mkU64 (extend_s_16to64 (imm))),
16656 Ijk_SigTRAP,
16657 IRConst_U64(guest_PC_curr_instr + 4),
16658 OFFB_PC));
16659 } else {
16660 stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs),
16661 mkU32 (extend_s_16to32 (imm))),
16662 Ijk_SigTRAP,
16663 IRConst_U32(guest_PC_curr_instr + 4),
16664 OFFB_PC));
16665 }
sewardj362cf842012-06-07 08:59:53 +000016666 break;
16667 }
petarjb92a9542013-02-27 22:57:17 +000016668 case 0x0B: { /* TLTIU */
16669 DIP("tltiu r%d, %d %d", rs, imm, trap_code);
16670 if (mode64) {
16671 stmt (IRStmt_Exit (binop (Iop_CmpLT64U, getIReg (rs),
16672 mkU64 (extend_s_16to64 (imm))),
16673 Ijk_SigTRAP,
16674 IRConst_U64(guest_PC_curr_instr + 4),
16675 OFFB_PC));
16676 } else {
16677 stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs),
16678 mkU32 (extend_s_16to32 (imm))),
16679 Ijk_SigTRAP,
16680 IRConst_U32(guest_PC_curr_instr + 4),
16681 OFFB_PC));
16682 }
sewardj362cf842012-06-07 08:59:53 +000016683 break;
16684 }
petarjb92a9542013-02-27 22:57:17 +000016685 case 0x0C: { /* TEQI */
16686 DIP("teqi r%d, %d %d", rs, imm, trap_code);
16687 if (mode64) {
16688 stmt (IRStmt_Exit (binop (Iop_CmpEQ64, getIReg (rs),
16689 mkU64 (extend_s_16to64 (imm))),
16690 Ijk_SigTRAP,
16691 IRConst_U64(guest_PC_curr_instr + 4),
16692 OFFB_PC));
16693 } else {
16694 stmt (IRStmt_Exit (binop (Iop_CmpEQ32, getIReg (rs),
16695 mkU32 (extend_s_16to32 (imm))),
16696 Ijk_SigTRAP,
16697 IRConst_U32(guest_PC_curr_instr + 4),
16698 OFFB_PC));
16699 }
sewardj362cf842012-06-07 08:59:53 +000016700 break;
16701 }
petarjb92a9542013-02-27 22:57:17 +000016702 case 0x0E: { /* TNEI */
16703 DIP("tnei r%d, %d %d", rs, imm, trap_code);
16704 if (mode64) {
16705 stmt (IRStmt_Exit (binop (Iop_CmpNE64, getIReg (rs),
16706 mkU64 (extend_s_16to64 (imm))),
16707 Ijk_SigTRAP,
16708 IRConst_U64(guest_PC_curr_instr + 4),
16709 OFFB_PC));
16710 } else {
16711 stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs),
16712 mkU32 (extend_s_16to32 (imm))),
16713 Ijk_SigTRAP,
16714 IRConst_U32(guest_PC_curr_instr + 4),
16715 OFFB_PC));
16716 }
sewardj362cf842012-06-07 08:59:53 +000016717 break;
16718 }
dejanjc3fee0d2013-07-25 09:08:03 +000016719 case 0x1C: { /* BPOSGE32 */
16720 DIP("bposge32 %d", imm);
16721 vassert(!mode64);
16722 t0 = newTemp(Ity_I32);
16723 /* Get pos field from DSPControl register. */
16724 assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
16725 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLT32U, mkexpr(t0),
16726 mkU32(32))), imm, &bstmt);
16727 }
sewardj362cf842012-06-07 08:59:53 +000016728 case 0x1F:
petarjb92a9542013-02-27 22:57:17 +000016729 /* SYNCI */
16730 /* Just ignore it */
16731 break;
sewardj362cf842012-06-07 08:59:53 +000016732
16733 default:
16734 goto decode_failure;
16735 }
16736 break;
16737
16738 case 0x04:
petarjc5b8bb72012-07-16 14:25:05 +000016739 DIP("beq r%d, r%d, %d", rs, rt, imm);
petarjb92a9542013-02-27 22:57:17 +000016740 if (mode64)
16741 dis_branch(False, binop(Iop_CmpEQ64, getIReg(rs), getIReg(rt)),
16742 imm, &bstmt);
16743 else
16744 dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)),
16745 imm, &bstmt);
sewardj362cf842012-06-07 08:59:53 +000016746 break;
16747
16748 case 0x14:
petarjc5b8bb72012-07-16 14:25:05 +000016749 DIP("beql r%d, r%d, %d", rs, rt, imm);
petarjb92a9542013-02-27 22:57:17 +000016750 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
16751 getIReg(rs), getIReg(rt)), imm);
sewardj362cf842012-06-07 08:59:53 +000016752 break;
16753
16754 case 0x05:
petarjc5b8bb72012-07-16 14:25:05 +000016755 DIP("bne r%d, r%d, %d", rs, rt, imm);
petarjb92a9542013-02-27 22:57:17 +000016756 if (mode64)
16757 dis_branch(False, binop(Iop_CmpNE64, getIReg(rs), getIReg(rt)),
16758 imm, &bstmt);
16759 else
16760 dis_branch(False, binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)),
16761 imm, &bstmt);
sewardj362cf842012-06-07 08:59:53 +000016762 break;
16763
16764 case 0x15:
petarjc5b8bb72012-07-16 14:25:05 +000016765 DIP("bnel r%d, r%d, %d", rs, rt, imm);
petarjb92a9542013-02-27 22:57:17 +000016766 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpEQ64 : Iop_CmpEQ32,
16767 getIReg(rs), getIReg(rt)), imm);
sewardj362cf842012-06-07 08:59:53 +000016768 break;
16769
petarjb92a9542013-02-27 22:57:17 +000016770 case 0x07: /* BGTZ */
petarjc5b8bb72012-07-16 14:25:05 +000016771 DIP("bgtz r%d, %d", rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016772 if (mode64)
16773 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE64S, getIReg(rs),
16774 mkU64(0x00))), imm, &bstmt);
16775 else
16776 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE32S, getIReg(rs),
16777 mkU32(0x00))), imm, &bstmt);
sewardj362cf842012-06-07 08:59:53 +000016778 break;
16779
petarjb92a9542013-02-27 22:57:17 +000016780 case 0x17: /* BGTZL */
petarjc5b8bb72012-07-16 14:25:05 +000016781 DIP("bgtzl r%d, %d", rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016782 if (mode64)
16783 lastn = dis_branch_likely(binop(Iop_CmpLE64S, getIReg(rs),
16784 mkU64(0x00)), imm);
16785 else
16786 lastn = dis_branch_likely(binop(Iop_CmpLE32S, getIReg(rs),
16787 mkU32(0x00)), imm);
sewardj362cf842012-06-07 08:59:53 +000016788 break;
16789
petarjb92a9542013-02-27 22:57:17 +000016790 case 0x06: /* BLEZ */
petarjc5b8bb72012-07-16 14:25:05 +000016791 DIP("blez r%d, %d", rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016792 if (mode64)
16793 dis_branch(False, binop(Iop_CmpLE64S, getIReg(rs), mkU64(0x0)),
16794 imm, &bstmt);
16795 else
16796 dis_branch(False,binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x0)), imm,
16797 &bstmt);
sewardj362cf842012-06-07 08:59:53 +000016798 break;
16799
petarjb92a9542013-02-27 22:57:17 +000016800 case 0x16: /* BLEZL */
petarjc5b8bb72012-07-16 14:25:05 +000016801 DIP("blezl r%d, %d", rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016802 lastn = dis_branch_likely(unop(Iop_Not1, (binop(mode64 ? Iop_CmpLE64S :
16803 Iop_CmpLE32S, getIReg(rs), mode64 ?
16804 mkU64(0x0) : mkU32(0x0)))), imm);
sewardj362cf842012-06-07 08:59:53 +000016805 break;
16806
petarjb92a9542013-02-27 22:57:17 +000016807 case 0x08: { /* ADDI */
sewardj362cf842012-06-07 08:59:53 +000016808 DIP("addi r%d, r%d, %d", rt, rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016809 IRTemp tmpRs32 = newTemp(Ity_I32);
16810 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
16811
petarja6a19862012-10-19 14:55:58 +000016812 t0 = newTemp(Ity_I32);
16813 t1 = newTemp(Ity_I32);
16814 t2 = newTemp(Ity_I32);
16815 t3 = newTemp(Ity_I32);
16816 t4 = newTemp(Ity_I32);
16817 /* dst = src0 + sign(imm)
petarjb92a9542013-02-27 22:57:17 +000016818 if(sign(src0 ) != sign(imm ))
16819 goto no overflow;
16820 if(sign(dst) == sign(src0 ))
16821 goto no overflow;
16822 we have overflow! */
petarja6a19862012-10-19 14:55:58 +000016823
petarjb92a9542013-02-27 22:57:17 +000016824 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32),
16825 mkU32(extend_s_16to32(imm))));
16826 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32),
16827 mkU32(extend_s_16to32(imm))));
16828 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
16829 mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
petarja6a19862012-10-19 14:55:58 +000016830
petarjb92a9542013-02-27 22:57:17 +000016831 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
16832 assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
16833 mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
petarja6a19862012-10-19 14:55:58 +000016834
petarjb92a9542013-02-27 22:57:17 +000016835 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
16836 mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
16837 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
16838 IRConst_U32(guest_PC_curr_instr + 4),
16839 OFFB_PC));
petarja6a19862012-10-19 14:55:58 +000016840
petarjb92a9542013-02-27 22:57:17 +000016841 putIReg(rt, mkWidenFrom32(ty, mkexpr(t0), True));
sewardj362cf842012-06-07 08:59:53 +000016842 break;
petarjb92a9542013-02-27 22:57:17 +000016843 }
16844 case 0x09: /* ADDIU */
sewardj362cf842012-06-07 08:59:53 +000016845 DIP("addiu r%d, r%d, %d", rt, rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016846 if (mode64) {
16847 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Add32,
16848 mkNarrowTo32(ty, getIReg(rs)),mkU32(extend_s_16to32(imm))),
16849 True));
16850 } else
16851 putIReg(rt, binop(Iop_Add32, getIReg(rs),mkU32(extend_s_16to32(imm))));
sewardj362cf842012-06-07 08:59:53 +000016852 break;
16853
petarjb92a9542013-02-27 22:57:17 +000016854 case 0x0C: /* ANDI */
petarjc5b8bb72012-07-16 14:25:05 +000016855 DIP("andi r%d, r%d, %d", rt, rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016856 if (mode64) {
16857 ALUI_PATTERN64(Iop_And64);
16858 } else {
16859 ALUI_PATTERN(Iop_And32);
16860 }
sewardj362cf842012-06-07 08:59:53 +000016861 break;
16862
petarjb92a9542013-02-27 22:57:17 +000016863 case 0x0E: /* XORI */
petarjc5b8bb72012-07-16 14:25:05 +000016864 DIP("xori r%d, r%d, %d", rt, rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016865 if (mode64) {
16866 ALUI_PATTERN64(Iop_Xor64);
16867 } else {
16868 ALUI_PATTERN(Iop_Xor32);
16869 }
sewardj362cf842012-06-07 08:59:53 +000016870 break;
16871
petarjb92a9542013-02-27 22:57:17 +000016872 case 0x0D: /* ORI */
petarjc5b8bb72012-07-16 14:25:05 +000016873 DIP("ori r%d, r%d, %d", rt, rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016874 if (mode64) {
16875 ALUI_PATTERN64(Iop_Or64);
16876 } else {
16877 ALUI_PATTERN(Iop_Or32);
16878 }
sewardj362cf842012-06-07 08:59:53 +000016879 break;
16880
petarjb92a9542013-02-27 22:57:17 +000016881 case 0x0A: /* SLTI */
petarjc5b8bb72012-07-16 14:25:05 +000016882 DIP("slti r%d, r%d, %d", rt, rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016883 if (mode64)
16884 putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
16885 mkU64(extend_s_16to64(imm)))));
16886 else
16887 putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
16888 mkU32(extend_s_16to32(imm)))));
sewardj362cf842012-06-07 08:59:53 +000016889 break;
16890
petarjb92a9542013-02-27 22:57:17 +000016891 case 0x0B: /* SLTIU */
petarjc5b8bb72012-07-16 14:25:05 +000016892 DIP("sltiu r%d, r%d, %d", rt, rs, imm);
petarjb92a9542013-02-27 22:57:17 +000016893 if (mode64)
16894 putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
16895 mkU64(extend_s_16to64(imm)))));
16896 else
16897 putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
16898 mkU32(extend_s_16to32(imm)))));
sewardj362cf842012-06-07 08:59:53 +000016899 break;
16900
petarjb92a9542013-02-27 22:57:17 +000016901 case 0x18: { /* Doubleword Add Immidiate - DADD; MIPS64 */
16902 DIP("daddi r%d, r%d, %d", rt, rs, imm);
16903 IRTemp tmpRs64 = newTemp(Ity_I64);
16904 assign(tmpRs64, getIReg(rs));
16905
16906 t0 = newTemp(Ity_I64);
16907 t1 = newTemp(Ity_I64);
16908 t2 = newTemp(Ity_I64);
16909 t3 = newTemp(Ity_I64);
16910 t4 = newTemp(Ity_I64);
16911 /* dst = src0 + sign(imm)
16912 if(sign(src0 ) != sign(imm ))
16913 goto no overflow;
16914 if(sign(dst) == sign(src0 ))
16915 goto no overflow;
16916 we have overflow! */
16917
16918 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64),
16919 mkU64(extend_s_16to64(imm))));
16920 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64),
16921 mkU64(extend_s_16to64(imm))));
16922 assign(t2, unop(Iop_1Sto64, binop(Iop_CmpEQ64, binop(Iop_And64,
petarjfdb2a4c2013-03-02 02:37:01 +000016923 mkexpr(t1), mkU64(0x8000000000000000ULL)),
16924 mkU64(0x8000000000000000ULL))));
petarjb92a9542013-02-27 22:57:17 +000016925
16926 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
16927 assign(t4, unop(Iop_1Sto64, binop(Iop_CmpNE64, binop(Iop_And64,
petarjfdb2a4c2013-03-02 02:37:01 +000016928 mkexpr(t3), mkU64(0x8000000000000000ULL)),
16929 mkU64(0x8000000000000000ULL))));
petarjb92a9542013-02-27 22:57:17 +000016930
16931 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
16932 mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
16933 IRConst_U64(guest_PC_curr_instr + 4),
16934 OFFB_PC));
16935
16936 putIReg(rt, mkexpr(t0));
16937 break;
16938 }
16939
16940 case 0x19: /* Doubleword Add Immidiate Unsigned - DADDIU; MIPS64 */
16941 DIP("daddiu r%d, r%d, %d", rt, rs, imm);
16942 putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
16943 break;
16944
16945 case 0x1A: {
16946 /* Load Doubleword Left - LDL; MIPS64 */
16947 vassert(mode64);
petarj1fb1e342013-04-27 02:18:11 +000016948 DIP("ldl r%u, %d(r%u)", rt, imm, rs);
petarjb92a9542013-02-27 22:57:17 +000016949 /* t1 = addr */
16950#if defined (_MIPSEL)
16951 t1 = newTemp(Ity_I64);
16952 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
16953#elif defined (_MIPSEB)
16954 t1 = newTemp(Ity_I64);
16955 assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
16956 mkU64(extend_s_16to64(imm)))));
16957#endif
16958 /* t2 = word addr */
petarj0c30de82013-04-19 12:35:00 +000016959 /* t4 = addr mod 8 */
petarjb92a9542013-02-27 22:57:17 +000016960 LWX_SWX_PATTERN64_1;
16961
16962 /* t3 = word content - shifted */
16963 t3 = newTemp(Ity_I64);
16964 assign(t3, binop(Iop_Shl64, load(Ity_I64, mkexpr(t2)),
16965 narrowTo(Ity_I8, binop(Iop_Shl64, binop(Iop_Sub64, mkU64(0x07),
16966 mkexpr(t4)), mkU8(3)))));
16967
16968 /* rt content - adjusted */
16969 t5 = newTemp(Ity_I64);
16970 t6 = newTemp(Ity_I64);
16971 t7 = newTemp(Ity_I64);
petarjb92a9542013-02-27 22:57:17 +000016972
16973 assign(t5, binop(Iop_Mul64, mkexpr(t4), mkU64(0x8)));
16974
petarjfdb2a4c2013-03-02 02:37:01 +000016975 assign(t6, binop(Iop_Shr64, mkU64(0x00FFFFFFFFFFFFFFULL),
petarjb92a9542013-02-27 22:57:17 +000016976 narrowTo(Ity_I8, mkexpr(t5))));
16977
16978 assign(t7, binop(Iop_And64, getIReg(rt), mkexpr(t6)));
16979
16980 putIReg(rt, binop(Iop_Or64, mkexpr(t7), mkexpr(t3)));
16981 break;
16982 }
16983
16984 case 0x1B: {
16985 /* Load Doubleword Right - LDR; MIPS64 */
16986 vassert(mode64);
petarj1fb1e342013-04-27 02:18:11 +000016987 DIP("ldr r%u,%d(r%u)", rt, imm, rs);
petarjb92a9542013-02-27 22:57:17 +000016988 /* t1 = addr */
16989#if defined (_MIPSEL)
16990 t1 = newTemp(Ity_I64);
16991 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
16992#elif defined (_MIPSEB)
16993 t1 = newTemp(Ity_I64);
petarj0c30de82013-04-19 12:35:00 +000016994 assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
petarjb92a9542013-02-27 22:57:17 +000016995 mkU64(extend_s_16to64(imm)))));
16996#endif
16997 /* t2 = word addr */
petarj0c30de82013-04-19 12:35:00 +000016998 /* t4 = addr mod 8 */
petarjb92a9542013-02-27 22:57:17 +000016999 LWX_SWX_PATTERN64_1;
17000
17001 /* t3 = word content - shifted */
17002 t3 = newTemp(Ity_I64);
17003 assign(t3, binop(Iop_Shr64, load(Ity_I64, mkexpr(t2)),
17004 narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(3)))));
17005
17006 /* rt content - adjusted */
17007 t5 = newTemp(Ity_I64);
17008 assign(t5, binop(Iop_And64, getIReg(rt), unop(Iop_Not64,
petarjfdb2a4c2013-03-02 02:37:01 +000017009 binop(Iop_Shr64, mkU64(0xFFFFFFFFFFFFFFFFULL),
petarjb92a9542013-02-27 22:57:17 +000017010 narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(0x3)))))));
17011
17012 putIReg(rt, binop(Iop_Or64, mkexpr(t5), mkexpr(t3)));
17013 break;
17014 }
17015
17016 case 0x27: /* Load Word unsigned - LWU; MIPS64 */
petarj1fb1e342013-04-27 02:18:11 +000017017 DIP("lwu r%u,%d(r%u)", rt, imm, rs);
petarjb92a9542013-02-27 22:57:17 +000017018 LOAD_STORE_PATTERN;
17019
17020 putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), False));
17021 break;
17022
17023 case 0x30: /* LL / LWC0 */
sewardj362cf842012-06-07 08:59:53 +000017024 DIP("ll r%d, %d(r%d)", rt, imm, rs);
17025 LOAD_STORE_PATTERN;
17026
17027 t2 = newTemp(Ity_I32);
17028#if defined (_MIPSEL)
petarj1fb1e342013-04-27 02:18:11 +000017029 stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), NULL /* this is a load */ ));
sewardj362cf842012-06-07 08:59:53 +000017030#elif defined (_MIPSEB)
petarj1fb1e342013-04-27 02:18:11 +000017031 stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), NULL /* this is a load */ ));
sewardj362cf842012-06-07 08:59:53 +000017032#endif
petarjb92a9542013-02-27 22:57:17 +000017033 if (mode64)
17034 putIReg(rt, unop(Iop_32Sto64, mkexpr(t2)));
17035 else
17036 putIReg(rt, mkexpr(t2));
17037 break;
17038
17039 case 0x34: /* Load Linked Doubleword - LLD; MIPS64 */
17040 DIP("lld r%d, %d(r%d)", rt, imm, rs);
17041 LOAD_STORE_PATTERN;
17042
17043 t2 = newTemp(Ity_I64);
17044#if defined (_MIPSEL)
17045 stmt(IRStmt_LLSC
petarj1fb1e342013-04-27 02:18:11 +000017046 (Iend_LE, t2, mkexpr(t1), NULL /* this is a load */ ));
petarjb92a9542013-02-27 22:57:17 +000017047#elif defined (_MIPSEB)
17048 stmt(IRStmt_LLSC
petarj1fb1e342013-04-27 02:18:11 +000017049 (Iend_BE, t2, mkexpr(t1), NULL /* this is a load */ ));
petarjb92a9542013-02-27 22:57:17 +000017050#endif
sewardj362cf842012-06-07 08:59:53 +000017051
17052 putIReg(rt, mkexpr(t2));
17053 break;
17054
petarj1fb1e342013-04-27 02:18:11 +000017055 case 0x38: /* SC / SWC0 */
petarjc5b8bb72012-07-16 14:25:05 +000017056 DIP("sc r%d, %d(r%d)", rt, imm, rs);
sewardj362cf842012-06-07 08:59:53 +000017057 LOAD_STORE_PATTERN;
17058
17059 t2 = newTemp(Ity_I1);
17060#if defined (_MIPSEL)
17061 stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt))));
17062#elif defined (_MIPSEB)
17063 stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt))));
17064#endif
17065
petarjb92a9542013-02-27 22:57:17 +000017066 putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32, mkexpr(t2)));
sewardj362cf842012-06-07 08:59:53 +000017067 break;
17068
petarjb92a9542013-02-27 22:57:17 +000017069 case 0x3C: /* Store Conditional Doubleword - SCD; MIPS64 */
17070 DIP("sdc r%d, %d(r%d)", rt, imm, rs);
17071 LOAD_STORE_PATTERN;
17072
17073 t2 = newTemp(Ity_I1);
17074#if defined (_MIPSEL)
17075 stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), getIReg(rt)));
17076#elif defined (_MIPSEB)
17077 stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), getIReg(rt)));
17078#endif
17079
17080 putIReg(rt, unop(Iop_1Uto64, mkexpr(t2)));
17081 break;
17082
petarj1fb1e342013-04-27 02:18:11 +000017083 case 0x37: /* Load Doubleword - LD; MIPS64 */
17084 DIP("ld r%u, %d(r%u)", rt, imm, rs);
petarjb92a9542013-02-27 22:57:17 +000017085 LOAD_STORE_PATTERN;
17086 putIReg(rt, load(Ity_I64, mkexpr(t1)));
17087 break;
17088
petarj1fb1e342013-04-27 02:18:11 +000017089 case 0x3F: /* Store Doubleword - SD; MIPS64 */
17090 DIP("sd r%u, %d(r%u)", rt, imm, rs);
petarjb92a9542013-02-27 22:57:17 +000017091 LOAD_STORE_PATTERN;
petarjb92a9542013-02-27 22:57:17 +000017092 store(mkexpr(t1), getIReg(rt));
17093 break;
17094
petarja90baf72014-09-03 14:39:56 +000017095 case 0x32: /* Branch on Bit Clear - BBIT0; Cavium OCTEON */
17096 /* Cavium Specific instructions. */
17097 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
17098 DIP("bbit0 r%d, 0x%x, %x", rs, rt, imm);
17099 t0 = newTemp(Ity_I32);
17100 t1 = newTemp(Ity_I32);
17101 assign(t0, mkU32(0x1));
17102 assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
17103 dis_branch(False, binop(Iop_CmpEQ32,
17104 binop(Iop_And32,
17105 mkexpr(t1),
17106 mkNarrowTo32(ty, getIReg(rs))),
17107 mkU32(0x0)),
17108 imm, &bstmt);
17109 break;
17110 } else {
17111 goto decode_failure;
17112 }
17113
petarj166d6452014-11-26 23:47:08 +000017114 case 0x36: /* Branch on Bit Clear Plus 32 - BBIT032; Cavium OCTEON */
17115 /* Cavium Specific instructions. */
17116 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
17117 DIP("bbit032 r%d, 0x%x, %x", rs, rt, imm);
17118 t0 = newTemp(Ity_I64);
17119 t1 = newTemp(Ity_I8); /* Shift. */
17120 t2 = newTemp(Ity_I64);
17121 assign(t0, mkU64(0x1));
17122 assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
17123 assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
17124 dis_branch(False, binop(Iop_CmpEQ64,
17125 binop(Iop_And64,
17126 mkexpr(t2),
17127 getIReg(rs)),
17128 mkU64(0x0)),
17129 imm, &bstmt);
17130 break;
17131 } else {
17132 goto decode_failure;
17133 }
17134
petarja90baf72014-09-03 14:39:56 +000017135 case 0x3A: /* Branch on Bit Set - BBIT1; Cavium OCTEON */
17136 /* Cavium Specific instructions. */
17137 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
17138 DIP("bbit1 r%d, 0x%x, %x", rs, rt, imm);
17139 t0 = newTemp(Ity_I32);
17140 t1 = newTemp(Ity_I32);
17141 assign(t0, mkU32(0x1));
17142 assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
17143 dis_branch(False, binop(Iop_CmpNE32,
17144 binop(Iop_And32,
17145 mkexpr(t1),
17146 mkNarrowTo32(ty, getIReg(rs))),
17147 mkU32(0x0)),
17148 imm, &bstmt);
17149 break;
17150 } else {
17151 goto decode_failure;
17152 }
17153
petarj166d6452014-11-26 23:47:08 +000017154 case 0x3E: /* Branch on Bit Set Plus 32 - BBIT132; Cavium OCTEON */
17155 /* Cavium Specific instructions. */
17156 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
17157 DIP("bbit132 r%d, 0x%x, %x", rs, rt, imm);
17158 t0 = newTemp(Ity_I64);
17159 t1 = newTemp(Ity_I8); /* Shift. */
17160 t2 = newTemp(Ity_I64);
17161 assign(t0, mkU64(0x1));
17162 assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
17163 assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
17164 dis_branch(False, binop(Iop_CmpNE64,
17165 binop(Iop_And64,
17166 mkexpr(t2),
17167 getIReg(rs)),
17168 mkU64(0x0)),
17169 imm, &bstmt);
17170 break;
17171 } else {
17172 goto decode_failure;
17173 }
17174
petarja90baf72014-09-03 14:39:56 +000017175 default:
17176 goto decode_failure;
17177
dejanjc3fee0d2013-07-25 09:08:03 +000017178 decode_failure_dsp:
17179 vex_printf("Error occured while trying to decode MIPS32 DSP "
dejanj0e006f22014-02-19 11:56:29 +000017180 "instruction.\nYour platform probably doesn't support "
17181 "MIPS32 DSP ASE.\n");
petarjb92a9542013-02-27 22:57:17 +000017182 decode_failure:
sewardj362cf842012-06-07 08:59:53 +000017183 /* All decode failures end up here. */
sewardj442e51a2012-12-06 18:08:04 +000017184 if (sigill_diag)
17185 vex_printf("vex mips->IR: unhandled instruction bytes: "
17186 "0x%x 0x%x 0x%x 0x%x\n",
17187 (Int) getIByte(delta_start + 0),
17188 (Int) getIByte(delta_start + 1),
17189 (Int) getIByte(delta_start + 2),
17190 (Int) getIByte(delta_start + 3));
sewardj362cf842012-06-07 08:59:53 +000017191
17192 /* Tell the dispatcher that this insn cannot be decoded, and so has
17193 not been executed, and (is currently) the next to be executed.
17194 EIP should be up-to-date since it made so at the start bnezof each
17195 insn, but nevertheless be paranoid and update it again right
17196 now. */
petarjb92a9542013-02-27 22:57:17 +000017197 if (mode64) {
17198 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_PC),
17199 mkU64(guest_PC_curr_instr)));
17200 jmp_lit64(&dres, Ijk_NoDecode, guest_PC_curr_instr);
17201 } else {
17202 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_PC),
17203 mkU32(guest_PC_curr_instr)));
17204 jmp_lit32(&dres, Ijk_NoDecode, guest_PC_curr_instr);
17205 }
sewardj362cf842012-06-07 08:59:53 +000017206 dres.whatNext = Dis_StopHere;
17207 dres.len = 0;
17208 return dres;
petarjb92a9542013-02-27 22:57:17 +000017209 } /* switch (opc) for the main (primary) opcode switch. */
sewardj362cf842012-06-07 08:59:53 +000017210
17211 /* All MIPS insn have 4 bytes */
17212
17213 if (delay_slot_branch) {
17214 delay_slot_branch = False;
17215 stmt(bstmt);
17216 bstmt = NULL;
petarjb92a9542013-02-27 22:57:17 +000017217 if (mode64)
17218 putPC(mkU64(guest_PC_curr_instr + 4));
17219 else
17220 putPC(mkU32(guest_PC_curr_instr + 4));
sewardj362cf842012-06-07 08:59:53 +000017221 dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
17222 Ijk_Call : Ijk_Boring;
17223 }
17224
17225 if (likely_delay_slot) {
17226 dres.jk_StopHere = Ijk_Boring;
17227 dres.whatNext = Dis_StopHere;
17228 putPC(lastn);
17229 lastn = NULL;
17230 }
17231 if (delay_slot_jump) {
17232 putPC(lastn);
17233 lastn = NULL;
17234 dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
17235 Ijk_Call : Ijk_Boring;
17236 }
17237
17238 decode_success:
17239 /* All decode successes end up here. */
17240 switch (dres.whatNext) {
17241 case Dis_Continue:
petarjb92a9542013-02-27 22:57:17 +000017242 if (mode64)
17243 putPC(mkU64(guest_PC_curr_instr + 4));
17244 else
17245 putPC(mkU32(guest_PC_curr_instr + 4));
sewardj362cf842012-06-07 08:59:53 +000017246 break;
17247 case Dis_ResteerU:
17248 case Dis_ResteerC:
17249 putPC(mkU32(dres.continueAt));
17250 break;
17251 case Dis_StopHere:
17252 break;
17253 default:
17254 vassert(0);
17255 break;
17256 }
17257
dejanjc3fee0d2013-07-25 09:08:03 +000017258 /* On MIPS we need to check if the last instruction in block is branch or
17259 jump. */
petarjf94ebbd2013-01-20 18:16:45 +000017260 if (((vex_control.guest_max_insns - 1) == (delta + 4) / 4)
17261 && (dres.whatNext != Dis_StopHere))
sewardj362cf842012-06-07 08:59:53 +000017262 if (branch_or_jump(guest_code + delta + 4)) {
17263 dres.whatNext = Dis_StopHere;
17264 dres.jk_StopHere = Ijk_Boring;
petarjb92a9542013-02-27 22:57:17 +000017265 if (mode64)
17266 putPC(mkU64(guest_PC_curr_instr + 4));
17267 else
17268 putPC(mkU32(guest_PC_curr_instr + 4));
petarjf94ebbd2013-01-20 18:16:45 +000017269 }
sewardj362cf842012-06-07 08:59:53 +000017270 dres.len = 4;
17271
17272 DIP("\n");
17273
17274 return dres;
17275
17276}
17277
17278/*------------------------------------------------------------*/
17279/*--- Top-level fn ---*/
17280/*------------------------------------------------------------*/
17281
17282/* Disassemble a single instruction into IR. The instruction
17283 is located in host memory at &guest_code[delta]. */
petarjb92a9542013-02-27 22:57:17 +000017284DisResult disInstr_MIPS( IRSB* irsb_IN,
17285 Bool (*resteerOkFn) ( void *, Addr64 ),
17286 Bool resteerCisOk,
17287 void* callback_opaque,
florian8462d112014-09-24 15:18:09 +000017288 const UChar* guest_code_IN,
petarjb92a9542013-02-27 22:57:17 +000017289 Long delta,
17290 Addr64 guest_IP,
17291 VexArch guest_arch,
17292 VexArchInfo* archinfo,
17293 VexAbiInfo* abiinfo,
sewardj9b769162014-07-24 12:42:03 +000017294 VexEndness host_endness_IN,
petarjb92a9542013-02-27 22:57:17 +000017295 Bool sigill_diag_IN )
sewardj362cf842012-06-07 08:59:53 +000017296{
17297 DisResult dres;
sewardj362cf842012-06-07 08:59:53 +000017298 /* Set globals (see top of this file) */
petarjb92a9542013-02-27 22:57:17 +000017299 vassert(guest_arch == VexArchMIPS32 || guest_arch == VexArchMIPS64);
sewardj362cf842012-06-07 08:59:53 +000017300
17301 mode64 = guest_arch != VexArchMIPS32;
dejanj0e006f22014-02-19 11:56:29 +000017302#if (__mips_fpr==64)
17303 fp_mode64 = ((VEX_MIPS_REV(archinfo->hwcaps) == VEX_PRID_CPU_32FPR)
17304 || guest_arch == VexArchMIPS64);
17305#endif
sewardj362cf842012-06-07 08:59:53 +000017306
17307 guest_code = guest_code_IN;
17308 irsb = irsb_IN;
sewardj9b769162014-07-24 12:42:03 +000017309 host_endness = host_endness_IN;
petarjb92a9542013-02-27 22:57:17 +000017310#if defined(VGP_mips32_linux)
17311 guest_PC_curr_instr = (Addr32)guest_IP;
17312#elif defined(VGP_mips64_linux)
17313 guest_PC_curr_instr = (Addr64)guest_IP;
17314#endif
sewardj362cf842012-06-07 08:59:53 +000017315
17316 dres = disInstr_MIPS_WRK(resteerOkFn, resteerCisOk, callback_opaque,
sewardj442e51a2012-12-06 18:08:04 +000017317 delta, archinfo, abiinfo, sigill_diag_IN);
sewardj362cf842012-06-07 08:59:53 +000017318
17319 return dres;
17320}
17321
17322/*--------------------------------------------------------------------*/
17323/*--- end guest_mips_toIR.c ---*/
17324/*--------------------------------------------------------------------*/