Rename some int<->fp conversion IROps for consistency. No functional change. n...
[valgrind.git] / VEX / priv / guest_mips_toIR.c
blobf8ef88fe63526b4b35572e1e208983bf07cabd9b
2 /*--------------------------------------------------------------------*/
3 /*--- begin guest_mips_toIR.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2010-2017 RT-RK
11 mips-valgrind@rt-rk.com
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.
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.
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.
28 The GNU General Public License is contained in the file COPYING.
31 /* Translates MIPS code to IR. */
33 #include "libvex_basictypes.h"
34 #include "libvex_ir.h"
35 #include "libvex.h"
36 #include "libvex_guest_mips32.h"
37 #include "libvex_guest_mips64.h"
39 #include "main_util.h"
40 #include "main_globals.h"
41 #include "guest_generic_bb_to_IR.h"
42 #include "guest_mips_defs.h"
44 /*------------------------------------------------------------*/
45 /*--- Globals ---*/
46 /*------------------------------------------------------------*/
48 /* These are set at the start of the translation of a instruction, so
49 that we don't have to pass them around endlessly. CONST means does
50 not change during translation of the instruction. */
52 /* 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. */
55 static VexEndness host_endness;
57 /* Pointer to the guest code area. */
58 static const UChar *guest_code;
60 /* CONST: The guest address for the instruction currently being
61 translated. */
62 #if defined(VGP_mips32_linux)
63 static Addr32 guest_PC_curr_instr;
64 #else
65 static Addr64 guest_PC_curr_instr;
66 #endif
68 /* MOD: The IRSB* into which we're generating code. */
69 static IRSB *irsb;
71 /* Is our guest binary 32 or 64bit? Set at each call to
72 disInstr_MIPS below. */
73 static Bool mode64 = False;
75 /* CPU has FPU and 32 dbl. prec. FP registers. */
76 static Bool fp_mode64 = False;
78 /* FPU works in FRE mode */
79 static Bool fp_mode64_fre = False;
81 /* CPU has MSA unit */
82 static Bool has_msa = False;
84 /* Define 1.0 in single and double precision. */
85 #define ONE_SINGLE 0x3F800000
86 #define ONE_DOUBLE 0x3FF0000000000000ULL
88 /*------------------------------------------------------------*/
89 /*--- Debugging output ---*/
90 /*------------------------------------------------------------*/
92 #define DIP(format, args...) \
93 if (vex_traceflags & VEX_TRACE_FE) \
94 vex_printf(format, ## args)
96 /*------------------------------------------------------------*/
97 /*--- Helper bits and pieces for deconstructing the ---*/
98 /*--- mips insn stream. ---*/
99 /*------------------------------------------------------------*/
101 /* ---------------- Integer registers ---------------- */
103 static UInt integerGuestRegOffset(UInt iregNo)
105 /* Do we care about endianness here? We do if sub-parts of integer
106 registers are accessed, but I don't think that ever happens on
107 MIPS. */
108 UInt ret;
109 if (!mode64)
110 switch (iregNo) {
111 case 0:
112 ret = offsetof(VexGuestMIPS32State, guest_r0); break;
113 case 1:
114 ret = offsetof(VexGuestMIPS32State, guest_r1); break;
115 case 2:
116 ret = offsetof(VexGuestMIPS32State, guest_r2); break;
117 case 3:
118 ret = offsetof(VexGuestMIPS32State, guest_r3); break;
119 case 4:
120 ret = offsetof(VexGuestMIPS32State, guest_r4); break;
121 case 5:
122 ret = offsetof(VexGuestMIPS32State, guest_r5); break;
123 case 6:
124 ret = offsetof(VexGuestMIPS32State, guest_r6); break;
125 case 7:
126 ret = offsetof(VexGuestMIPS32State, guest_r7); break;
127 case 8:
128 ret = offsetof(VexGuestMIPS32State, guest_r8); break;
129 case 9:
130 ret = offsetof(VexGuestMIPS32State, guest_r9); break;
131 case 10:
132 ret = offsetof(VexGuestMIPS32State, guest_r10); break;
133 case 11:
134 ret = offsetof(VexGuestMIPS32State, guest_r11); break;
135 case 12:
136 ret = offsetof(VexGuestMIPS32State, guest_r12); break;
137 case 13:
138 ret = offsetof(VexGuestMIPS32State, guest_r13); break;
139 case 14:
140 ret = offsetof(VexGuestMIPS32State, guest_r14); break;
141 case 15:
142 ret = offsetof(VexGuestMIPS32State, guest_r15); break;
143 case 16:
144 ret = offsetof(VexGuestMIPS32State, guest_r16); break;
145 case 17:
146 ret = offsetof(VexGuestMIPS32State, guest_r17); break;
147 case 18:
148 ret = offsetof(VexGuestMIPS32State, guest_r18); break;
149 case 19:
150 ret = offsetof(VexGuestMIPS32State, guest_r19); break;
151 case 20:
152 ret = offsetof(VexGuestMIPS32State, guest_r20); break;
153 case 21:
154 ret = offsetof(VexGuestMIPS32State, guest_r21); break;
155 case 22:
156 ret = offsetof(VexGuestMIPS32State, guest_r22); break;
157 case 23:
158 ret = offsetof(VexGuestMIPS32State, guest_r23); break;
159 case 24:
160 ret = offsetof(VexGuestMIPS32State, guest_r24); break;
161 case 25:
162 ret = offsetof(VexGuestMIPS32State, guest_r25); break;
163 case 26:
164 ret = offsetof(VexGuestMIPS32State, guest_r26); break;
165 case 27:
166 ret = offsetof(VexGuestMIPS32State, guest_r27); break;
167 case 28:
168 ret = offsetof(VexGuestMIPS32State, guest_r28); break;
169 case 29:
170 ret = offsetof(VexGuestMIPS32State, guest_r29); break;
171 case 30:
172 ret = offsetof(VexGuestMIPS32State, guest_r30); break;
173 case 31:
174 ret = offsetof(VexGuestMIPS32State, guest_r31); break;
175 default:
176 vassert(0);
177 break;
179 else
180 switch (iregNo) {
181 case 0:
182 ret = offsetof(VexGuestMIPS64State, guest_r0); break;
183 case 1:
184 ret = offsetof(VexGuestMIPS64State, guest_r1); break;
185 case 2:
186 ret = offsetof(VexGuestMIPS64State, guest_r2); break;
187 case 3:
188 ret = offsetof(VexGuestMIPS64State, guest_r3); break;
189 case 4:
190 ret = offsetof(VexGuestMIPS64State, guest_r4); break;
191 case 5:
192 ret = offsetof(VexGuestMIPS64State, guest_r5); break;
193 case 6:
194 ret = offsetof(VexGuestMIPS64State, guest_r6); break;
195 case 7:
196 ret = offsetof(VexGuestMIPS64State, guest_r7); break;
197 case 8:
198 ret = offsetof(VexGuestMIPS64State, guest_r8); break;
199 case 9:
200 ret = offsetof(VexGuestMIPS64State, guest_r9); break;
201 case 10:
202 ret = offsetof(VexGuestMIPS64State, guest_r10); break;
203 case 11:
204 ret = offsetof(VexGuestMIPS64State, guest_r11); break;
205 case 12:
206 ret = offsetof(VexGuestMIPS64State, guest_r12); break;
207 case 13:
208 ret = offsetof(VexGuestMIPS64State, guest_r13); break;
209 case 14:
210 ret = offsetof(VexGuestMIPS64State, guest_r14); break;
211 case 15:
212 ret = offsetof(VexGuestMIPS64State, guest_r15); break;
213 case 16:
214 ret = offsetof(VexGuestMIPS64State, guest_r16); break;
215 case 17:
216 ret = offsetof(VexGuestMIPS64State, guest_r17); break;
217 case 18:
218 ret = offsetof(VexGuestMIPS64State, guest_r18); break;
219 case 19:
220 ret = offsetof(VexGuestMIPS64State, guest_r19); break;
221 case 20:
222 ret = offsetof(VexGuestMIPS64State, guest_r20); break;
223 case 21:
224 ret = offsetof(VexGuestMIPS64State, guest_r21); break;
225 case 22:
226 ret = offsetof(VexGuestMIPS64State, guest_r22); break;
227 case 23:
228 ret = offsetof(VexGuestMIPS64State, guest_r23); break;
229 case 24:
230 ret = offsetof(VexGuestMIPS64State, guest_r24); break;
231 case 25:
232 ret = offsetof(VexGuestMIPS64State, guest_r25); break;
233 case 26:
234 ret = offsetof(VexGuestMIPS64State, guest_r26); break;
235 case 27:
236 ret = offsetof(VexGuestMIPS64State, guest_r27); break;
237 case 28:
238 ret = offsetof(VexGuestMIPS64State, guest_r28); break;
239 case 29:
240 ret = offsetof(VexGuestMIPS64State, guest_r29); break;
241 case 30:
242 ret = offsetof(VexGuestMIPS64State, guest_r30); break;
243 case 31:
244 ret = offsetof(VexGuestMIPS64State, guest_r31); break;
245 default:
246 vassert(0);
247 break;
249 return ret;
252 #if defined(VGP_mips32_linux)
253 #define OFFB_PC offsetof(VexGuestMIPS32State, guest_PC)
254 #else
255 #define OFFB_PC offsetof(VexGuestMIPS64State, guest_PC)
256 #endif
258 /* ---------------- Floating point registers ---------------- */
260 static UInt floatGuestRegOffset(UInt fregNo)
262 vassert(fregNo < 32);
263 UInt ret;
264 if (!mode64)
265 switch (fregNo) {
266 case 0:
267 ret = offsetof(VexGuestMIPS32State, guest_f0); break;
268 case 1:
269 ret = offsetof(VexGuestMIPS32State, guest_f1); break;
270 case 2:
271 ret = offsetof(VexGuestMIPS32State, guest_f2); break;
272 case 3:
273 ret = offsetof(VexGuestMIPS32State, guest_f3); break;
274 case 4:
275 ret = offsetof(VexGuestMIPS32State, guest_f4); break;
276 case 5:
277 ret = offsetof(VexGuestMIPS32State, guest_f5); break;
278 case 6:
279 ret = offsetof(VexGuestMIPS32State, guest_f6); break;
280 case 7:
281 ret = offsetof(VexGuestMIPS32State, guest_f7); break;
282 case 8:
283 ret = offsetof(VexGuestMIPS32State, guest_f8); break;
284 case 9:
285 ret = offsetof(VexGuestMIPS32State, guest_f9); break;
286 case 10:
287 ret = offsetof(VexGuestMIPS32State, guest_f10); break;
288 case 11:
289 ret = offsetof(VexGuestMIPS32State, guest_f11); break;
290 case 12:
291 ret = offsetof(VexGuestMIPS32State, guest_f12); break;
292 case 13:
293 ret = offsetof(VexGuestMIPS32State, guest_f13); break;
294 case 14:
295 ret = offsetof(VexGuestMIPS32State, guest_f14); break;
296 case 15:
297 ret = offsetof(VexGuestMIPS32State, guest_f15); break;
298 case 16:
299 ret = offsetof(VexGuestMIPS32State, guest_f16); break;
300 case 17:
301 ret = offsetof(VexGuestMIPS32State, guest_f17); break;
302 case 18:
303 ret = offsetof(VexGuestMIPS32State, guest_f18); break;
304 case 19:
305 ret = offsetof(VexGuestMIPS32State, guest_f19); break;
306 case 20:
307 ret = offsetof(VexGuestMIPS32State, guest_f20); break;
308 case 21:
309 ret = offsetof(VexGuestMIPS32State, guest_f21); break;
310 case 22:
311 ret = offsetof(VexGuestMIPS32State, guest_f22); break;
312 case 23:
313 ret = offsetof(VexGuestMIPS32State, guest_f23); break;
314 case 24:
315 ret = offsetof(VexGuestMIPS32State, guest_f24); break;
316 case 25:
317 ret = offsetof(VexGuestMIPS32State, guest_f25); break;
318 case 26:
319 ret = offsetof(VexGuestMIPS32State, guest_f26); break;
320 case 27:
321 ret = offsetof(VexGuestMIPS32State, guest_f27); break;
322 case 28:
323 ret = offsetof(VexGuestMIPS32State, guest_f28); break;
324 case 29:
325 ret = offsetof(VexGuestMIPS32State, guest_f29); break;
326 case 30:
327 ret = offsetof(VexGuestMIPS32State, guest_f30); break;
328 case 31:
329 ret = offsetof(VexGuestMIPS32State, guest_f31); break;
330 default:
331 vassert(0);
332 break;
334 else
335 switch (fregNo) {
336 case 0:
337 ret = offsetof(VexGuestMIPS64State, guest_f0); break;
338 case 1:
339 ret = offsetof(VexGuestMIPS64State, guest_f1); break;
340 case 2:
341 ret = offsetof(VexGuestMIPS64State, guest_f2); break;
342 case 3:
343 ret = offsetof(VexGuestMIPS64State, guest_f3); break;
344 case 4:
345 ret = offsetof(VexGuestMIPS64State, guest_f4); break;
346 case 5:
347 ret = offsetof(VexGuestMIPS64State, guest_f5); break;
348 case 6:
349 ret = offsetof(VexGuestMIPS64State, guest_f6); break;
350 case 7:
351 ret = offsetof(VexGuestMIPS64State, guest_f7); break;
352 case 8:
353 ret = offsetof(VexGuestMIPS64State, guest_f8); break;
354 case 9:
355 ret = offsetof(VexGuestMIPS64State, guest_f9); break;
356 case 10:
357 ret = offsetof(VexGuestMIPS64State, guest_f10); break;
358 case 11:
359 ret = offsetof(VexGuestMIPS64State, guest_f11); break;
360 case 12:
361 ret = offsetof(VexGuestMIPS64State, guest_f12); break;
362 case 13:
363 ret = offsetof(VexGuestMIPS64State, guest_f13); break;
364 case 14:
365 ret = offsetof(VexGuestMIPS64State, guest_f14); break;
366 case 15:
367 ret = offsetof(VexGuestMIPS64State, guest_f15); break;
368 case 16:
369 ret = offsetof(VexGuestMIPS64State, guest_f16); break;
370 case 17:
371 ret = offsetof(VexGuestMIPS64State, guest_f17); break;
372 case 18:
373 ret = offsetof(VexGuestMIPS64State, guest_f18); break;
374 case 19:
375 ret = offsetof(VexGuestMIPS64State, guest_f19); break;
376 case 20:
377 ret = offsetof(VexGuestMIPS64State, guest_f20); break;
378 case 21:
379 ret = offsetof(VexGuestMIPS64State, guest_f21); break;
380 case 22:
381 ret = offsetof(VexGuestMIPS64State, guest_f22); break;
382 case 23:
383 ret = offsetof(VexGuestMIPS64State, guest_f23); break;
384 case 24:
385 ret = offsetof(VexGuestMIPS64State, guest_f24); break;
386 case 25:
387 ret = offsetof(VexGuestMIPS64State, guest_f25); break;
388 case 26:
389 ret = offsetof(VexGuestMIPS64State, guest_f26); break;
390 case 27:
391 ret = offsetof(VexGuestMIPS64State, guest_f27); break;
392 case 28:
393 ret = offsetof(VexGuestMIPS64State, guest_f28); break;
394 case 29:
395 ret = offsetof(VexGuestMIPS64State, guest_f29); break;
396 case 30:
397 ret = offsetof(VexGuestMIPS64State, guest_f30); break;
398 case 31:
399 ret = offsetof(VexGuestMIPS64State, guest_f31); break;
400 default:
401 vassert(0);
402 break;
404 return ret;
407 /* ---------------- MIPS32 DSP ASE(r2) accumulators ---------------- */
409 static UInt accumulatorGuestRegOffset(UInt acNo)
411 vassert(!mode64);
412 vassert(acNo <= 3);
413 UInt ret;
414 switch (acNo) {
415 case 0:
416 ret = offsetof(VexGuestMIPS32State, guest_ac0); break;
417 case 1:
418 ret = offsetof(VexGuestMIPS32State, guest_ac1); break;
419 case 2:
420 ret = offsetof(VexGuestMIPS32State, guest_ac2); break;
421 case 3:
422 ret = offsetof(VexGuestMIPS32State, guest_ac3); break;
423 default:
424 vassert(0);
425 break;
427 return ret;
430 /* ---------------- MIPS32 MSA registers ---------------- */
432 static UInt msaGuestRegOffset(UInt msaRegNo) {
433 vassert(msaRegNo <= 31);
434 UInt ret;
436 if (mode64) {
437 switch (msaRegNo) {
438 case 0:
439 ret = offsetof(VexGuestMIPS64State, guest_w0);
440 break;
442 case 1:
443 ret = offsetof(VexGuestMIPS64State, guest_w1);
444 break;
446 case 2:
447 ret = offsetof(VexGuestMIPS64State, guest_w2);
448 break;
450 case 3:
451 ret = offsetof(VexGuestMIPS64State, guest_w3);
452 break;
454 case 4:
455 ret = offsetof(VexGuestMIPS64State, guest_w4);
456 break;
458 case 5:
459 ret = offsetof(VexGuestMIPS64State, guest_w5);
460 break;
462 case 6:
463 ret = offsetof(VexGuestMIPS64State, guest_w6);
464 break;
466 case 7:
467 ret = offsetof(VexGuestMIPS64State, guest_w7);
468 break;
470 case 8:
471 ret = offsetof(VexGuestMIPS64State, guest_w8);
472 break;
474 case 9:
475 ret = offsetof(VexGuestMIPS64State, guest_w9);
476 break;
478 case 10:
479 ret = offsetof(VexGuestMIPS64State, guest_w10);
480 break;
482 case 11:
483 ret = offsetof(VexGuestMIPS64State, guest_w11);
484 break;
486 case 12:
487 ret = offsetof(VexGuestMIPS64State, guest_w12);
488 break;
490 case 13:
491 ret = offsetof(VexGuestMIPS64State, guest_w13);
492 break;
494 case 14:
495 ret = offsetof(VexGuestMIPS64State, guest_w14);
496 break;
498 case 15:
499 ret = offsetof(VexGuestMIPS64State, guest_w15);
500 break;
502 case 16:
503 ret = offsetof(VexGuestMIPS64State, guest_w16);
504 break;
506 case 17:
507 ret = offsetof(VexGuestMIPS64State, guest_w17);
508 break;
510 case 18:
511 ret = offsetof(VexGuestMIPS64State, guest_w18);
512 break;
514 case 19:
515 ret = offsetof(VexGuestMIPS64State, guest_w19);
516 break;
518 case 20:
519 ret = offsetof(VexGuestMIPS64State, guest_w20);
520 break;
522 case 21:
523 ret = offsetof(VexGuestMIPS64State, guest_w21);
524 break;
526 case 22:
527 ret = offsetof(VexGuestMIPS64State, guest_w22);
528 break;
530 case 23:
531 ret = offsetof(VexGuestMIPS64State, guest_w23);
532 break;
534 case 24:
535 ret = offsetof(VexGuestMIPS64State, guest_w24);
536 break;
538 case 25:
539 ret = offsetof(VexGuestMIPS64State, guest_w25);
540 break;
542 case 26:
543 ret = offsetof(VexGuestMIPS64State, guest_w26);
544 break;
546 case 27:
547 ret = offsetof(VexGuestMIPS64State, guest_w27);
548 break;
550 case 28:
551 ret = offsetof(VexGuestMIPS64State, guest_w28);
552 break;
554 case 29:
555 ret = offsetof(VexGuestMIPS64State, guest_w29);
556 break;
558 case 30:
559 ret = offsetof(VexGuestMIPS64State, guest_w30);
560 break;
562 case 31:
563 ret = offsetof(VexGuestMIPS64State, guest_w31);
564 break;
566 default:
567 vassert(0);
568 break;
570 } else {
571 switch (msaRegNo) {
572 case 0:
573 ret = offsetof(VexGuestMIPS32State, guest_w0);
574 break;
576 case 1:
577 ret = offsetof(VexGuestMIPS32State, guest_w1);
578 break;
580 case 2:
581 ret = offsetof(VexGuestMIPS32State, guest_w2);
582 break;
584 case 3:
585 ret = offsetof(VexGuestMIPS32State, guest_w3);
586 break;
588 case 4:
589 ret = offsetof(VexGuestMIPS32State, guest_w4);
590 break;
592 case 5:
593 ret = offsetof(VexGuestMIPS32State, guest_w5);
594 break;
596 case 6:
597 ret = offsetof(VexGuestMIPS32State, guest_w6);
598 break;
600 case 7:
601 ret = offsetof(VexGuestMIPS32State, guest_w7);
602 break;
604 case 8:
605 ret = offsetof(VexGuestMIPS32State, guest_w8);
606 break;
608 case 9:
609 ret = offsetof(VexGuestMIPS32State, guest_w9);
610 break;
612 case 10:
613 ret = offsetof(VexGuestMIPS32State, guest_w10);
614 break;
616 case 11:
617 ret = offsetof(VexGuestMIPS32State, guest_w11);
618 break;
620 case 12:
621 ret = offsetof(VexGuestMIPS32State, guest_w12);
622 break;
624 case 13:
625 ret = offsetof(VexGuestMIPS32State, guest_w13);
626 break;
628 case 14:
629 ret = offsetof(VexGuestMIPS32State, guest_w14);
630 break;
632 case 15:
633 ret = offsetof(VexGuestMIPS32State, guest_w15);
634 break;
636 case 16:
637 ret = offsetof(VexGuestMIPS32State, guest_w16);
638 break;
640 case 17:
641 ret = offsetof(VexGuestMIPS32State, guest_w17);
642 break;
644 case 18:
645 ret = offsetof(VexGuestMIPS32State, guest_w18);
646 break;
648 case 19:
649 ret = offsetof(VexGuestMIPS32State, guest_w19);
650 break;
652 case 20:
653 ret = offsetof(VexGuestMIPS32State, guest_w20);
654 break;
656 case 21:
657 ret = offsetof(VexGuestMIPS32State, guest_w21);
658 break;
660 case 22:
661 ret = offsetof(VexGuestMIPS32State, guest_w22);
662 break;
664 case 23:
665 ret = offsetof(VexGuestMIPS32State, guest_w23);
666 break;
668 case 24:
669 ret = offsetof(VexGuestMIPS32State, guest_w24);
670 break;
672 case 25:
673 ret = offsetof(VexGuestMIPS32State, guest_w25);
674 break;
676 case 26:
677 ret = offsetof(VexGuestMIPS32State, guest_w26);
678 break;
680 case 27:
681 ret = offsetof(VexGuestMIPS32State, guest_w27);
682 break;
684 case 28:
685 ret = offsetof(VexGuestMIPS32State, guest_w28);
686 break;
688 case 29:
689 ret = offsetof(VexGuestMIPS32State, guest_w29);
690 break;
692 case 30:
693 ret = offsetof(VexGuestMIPS32State, guest_w30);
694 break;
696 case 31:
697 ret = offsetof(VexGuestMIPS32State, guest_w31);
698 break;
700 default:
701 vassert(0);
702 break;
706 return ret;
710 /* Do a endian load of a 32-bit word, regardless of the endianness of the
711 underlying host. */
712 static inline UInt getUInt(const UChar * p)
714 UInt w = 0;
715 #if defined (_MIPSEL)
716 w = (w << 8) | p[3];
717 w = (w << 8) | p[2];
718 w = (w << 8) | p[1];
719 w = (w << 8) | p[0];
720 #elif defined (_MIPSEB)
721 w = (w << 8) | p[0];
722 w = (w << 8) | p[1];
723 w = (w << 8) | p[2];
724 w = (w << 8) | p[3];
725 #endif
726 return w;
729 #define BITS2(_b1,_b0) \
730 (((_b1) << 1) | (_b0))
732 #define BITS3(_b2,_b1,_b0) \
733 (((_b2) << 2) | ((_b1) << 1) | (_b0))
735 #define BITS4(_b3,_b2,_b1,_b0) \
736 (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
738 #define BITS5(_b4,_b3,_b2,_b1,_b0) \
739 (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0)))
741 #define BITS6(_b5,_b4,_b3,_b2,_b1,_b0) \
742 ((BITS2((_b5),(_b4)) << 4) \
743 | BITS4((_b3),(_b2),(_b1),(_b0)))
745 #define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
746 ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
747 | BITS4((_b3),(_b2),(_b1),(_b0)))
749 #define LOAD_STORE_PATTERN \
750 t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
751 if(!mode64) \
752 assign(t1, binop(Iop_Add32, getIReg(rs), \
753 mkU32(extend_s_16to32(imm)))); \
754 else \
755 assign(t1, binop(Iop_Add64, getIReg(rs), \
756 mkU64(extend_s_16to64(imm)))); \
758 #define LOAD_STORE_PATTERN_MSA(imm) \
759 t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
760 if (!mode64) \
761 assign(t1, binop(Iop_Add32, getIReg(ws), \
762 mkU32(extend_s_10to32(imm)))); \
763 else \
764 assign(t1, binop(Iop_Add64, getIReg(ws), \
765 mkU64(extend_s_10to64(imm)))); \
767 #define LOADX_STORE_PATTERN \
768 t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
769 if(!mode64) \
770 assign(t1, binop(Iop_Add32, getIReg(regRs), getIReg(regRt))); \
771 else \
772 assign(t1, binop(Iop_Add64, getIReg(regRs), getIReg(regRt)));
774 #define LWX_SWX_PATTERN64 \
775 t2 = newTemp(Ity_I64); \
776 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); \
777 t4 = newTemp(Ity_I32); \
778 assign(t4, mkNarrowTo32( ty, binop(Iop_And64, \
779 mkexpr(t1), mkU64(0x3))));
781 #define LWX_SWX_PATTERN64_1 \
782 t2 = newTemp(Ity_I64); \
783 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); \
784 t4 = newTemp(Ity_I64); \
785 assign(t4, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
787 #define LWX_SWX_PATTERN \
788 t2 = newTemp(Ity_I32); \
789 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \
790 t4 = newTemp(Ity_I32); \
791 assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003)))
793 #define SXXV_PATTERN(op) \
794 putIReg(rd, binop(op, \
795 getIReg(rt), \
796 unop(Iop_32to8, \
797 binop(Iop_And32, \
798 getIReg(rs), \
799 mkU32(0x0000001F) \
805 #define SXXV_PATTERN64(op) \
806 putIReg(rd, mkWidenFrom32(ty, binop(op, \
807 mkNarrowTo32(ty, getIReg(rt)), \
808 unop(Iop_32to8, \
809 binop(Iop_And32, \
810 mkNarrowTo32(ty, getIReg(rs)), \
811 mkU32(0x0000001F) \
814 ), True \
817 #define SXX_PATTERN(op) \
818 putIReg(rd, binop(op, getIReg(rt), mkU8(sa)));
820 #define ALU_PATTERN(op) \
821 putIReg(rd, binop(op, getIReg(rs), getIReg(rt)));
823 #define ALUI_PATTERN(op) \
824 putIReg(rt, binop(op, getIReg(rs), mkU32(imm)));
826 #define ALUI_PATTERN64(op) \
827 putIReg(rt, binop(op, getIReg(rs), mkU64(imm)));
829 #define ALU_PATTERN64(op) \
830 putIReg(rd, mkWidenFrom32(ty, binop(op, \
831 mkNarrowTo32(ty, getIReg(rs)), \
832 mkNarrowTo32(ty, getIReg(rt))), True));
834 #define FP_CONDITIONAL_CODE \
835 t3 = newTemp(Ity_I32); \
836 assign(t3, binop(Iop_And32, \
837 IRExpr_ITE( binop(Iop_CmpEQ32, mkU32(cc), mkU32(0)), \
838 binop(Iop_Shr32, getFCSR(), mkU8(23)), \
839 binop(Iop_Shr32, getFCSR(), mkU8(24+cc))), \
840 mkU32(0x1)));
842 #define ILLEGAL_INSTRUCTON \
843 putPC(mkU32(guest_PC_curr_instr + 4)); \
844 dres.jk_StopHere = Ijk_SigILL; \
845 dres.whatNext = Dis_StopHere;
847 #define LLADDR_INVALID \
848 (mode64 ? mkU64(0xFFFFFFFFFFFFFFFFULL) : mkU32(0xFFFFFFFF))
850 /*------------------------------------------------------------*/
851 /*--- Field helpers ---*/
852 /*------------------------------------------------------------*/
854 static UInt get_opcode(UInt mipsins)
856 return (0xFC000000 & mipsins) >> 26;
859 static UInt get_rs(UInt mipsins)
861 return (0x03E00000 & mipsins) >> 21;
864 static UInt get_rt(UInt mipsins)
866 return (0x001F0000 & mipsins) >> 16;
869 static UInt get_imm(UInt mipsins)
871 return (0x0000FFFF & mipsins);
874 static UInt get_instr_index(UInt mipsins)
876 return (0x03FFFFFF & mipsins);
879 static UInt get_rd(UInt mipsins)
881 return (0x0000F800 & mipsins) >> 11;
884 static UInt get_sa(UInt mipsins)
886 return (0x000007C0 & mipsins) >> 6;
889 static UInt get_function(UInt mipsins)
891 return (0x0000003F & mipsins);
894 static UInt get_ft(UInt mipsins)
896 return (0x001F0000 & mipsins) >> 16;
899 static UInt get_fs(UInt mipsins)
901 return (0x0000F800 & mipsins) >> 11;
904 static UInt get_fd(UInt mipsins)
906 return (0x000007C0 & mipsins) >> 6;
909 static UInt get_mov_cc(UInt mipsins)
911 return (0x001C0000 & mipsins) >> 18;
914 static UInt get_bc1_cc(UInt mipsins)
916 return (0x001C0000 & mipsins) >> 18;
919 static UInt get_fpc_cc(UInt mipsins)
921 return (0x00000700 & mipsins) >> 8;
924 static UInt get_tf(UInt mipsins)
926 return (0x00010000 & mipsins) >> 16;
929 static UInt get_nd(UInt mipsins)
931 return (0x00020000 & mipsins) >> 17;
934 static UInt get_fmt(UInt mipsins)
936 return (0x03E00000 & mipsins) >> 21;
939 static UInt get_FC(UInt mipsins)
941 return (0x000000F0 & mipsins) >> 4;
944 static UInt get_cond(UInt mipsins)
946 return (0x0000000F & mipsins);
949 /* for break & syscall */
950 static UInt get_code(UInt mipsins)
952 return (0xFFC0 & mipsins) >> 6;
955 static UInt get_lsb(UInt mipsins)
957 return (0x7C0 & mipsins) >> 6;
960 static UInt get_msb(UInt mipsins)
962 return (0x0000F800 & mipsins) >> 11;
965 static UInt get_rot(UInt mipsins)
967 return (0x00200000 & mipsins) >> 21;
970 static UInt get_rotv(UInt mipsins)
972 return (0x00000040 & mipsins) >> 6;
975 static UInt get_sel(UInt mipsins)
977 return (0x00000007 & mipsins);
980 /* Get acc number for all MIPS32 DSP ASE(r2) instructions that use them,
981 except for MFHI and MFLO. */
982 static UInt get_acNo(UInt mipsins)
984 return (0x00001800 & mipsins) >> 11;
987 /* Get accumulator number for MIPS32 DSP ASEr2 MFHI and MFLO instructions. */
988 static UInt get_acNo_mfhilo(UInt mipsins)
990 return (0x00600000 & mipsins) >> 21;
993 /* Get mask field (helper function for wrdsp instruction). */
994 static UInt get_wrdspMask(UInt mipsins)
996 return (0x001ff800 & mipsins) >> 11;
999 /* Get mask field (helper function for rddsp instruction). */
1000 static UInt get_rddspMask(UInt mipsins)
1002 return (0x03ff0000 & mipsins) >> 16;
1005 /* Get shift field (helper function for DSP ASE instructions). */
1006 static UInt get_shift(UInt mipsins)
1008 return (0x03f00000 & mipsins) >> 20;
1011 /* Get immediate field for DSP ASE instructions. */
1012 static UInt get_dspImm(UInt mipsins)
1014 return (0x03ff0000 & mipsins) >> 16;
1017 static Bool branch_or_jump(const UChar * addr)
1019 UInt fmt;
1020 UInt cins = getUInt(addr);
1022 UInt opcode = get_opcode(cins);
1023 UInt rt = get_rt(cins);
1024 UInt function = get_function(cins);
1026 /* bgtz, blez, bne, beq, jal */
1027 if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04
1028 || opcode == 0x03 || opcode == 0x02) {
1029 return True;
1032 /* bgez */
1033 if (opcode == 0x01 && rt == 0x01) {
1034 return True;
1037 /* bgezal */
1038 if (opcode == 0x01 && rt == 0x11) {
1039 return True;
1042 /* bltzal */
1043 if (opcode == 0x01 && rt == 0x10) {
1044 return True;
1047 /* bltz */
1048 if (opcode == 0x01 && rt == 0x00) {
1049 return True;
1052 /* jalr */
1053 if (opcode == 0x00 && function == 0x09) {
1054 return True;
1057 /* jr */
1058 if (opcode == 0x00 && function == 0x08) {
1059 return True;
1062 if (opcode == 0x11) {
1063 /* bc1f & bc1t */
1064 fmt = get_fmt(cins);
1065 if (fmt == 0x08) {
1066 return True;
1069 /* MSA branches */
1070 /* bnz.df, bz.df */
1071 if (fmt >= 0x18) {
1072 return True;
1074 /* bnz.v */
1075 if (fmt == 0x0f) {
1076 return True;
1078 /* bz.v */
1079 if (fmt == 0x0b) {
1080 return True;
1083 /* R6 branches */
1084 /* bc1eqz */
1085 if (fmt == 0x09) {
1086 return True;
1089 /* bc1nez */
1090 if (fmt == 0x0D) {
1091 return True;
1095 /* bposge32 */
1096 if (opcode == 0x01 && rt == 0x1c) {
1097 return True;
1100 /* Cavium Specific instructions. */
1101 if (opcode == 0x32 || opcode == 0x3A || opcode == 0x36 || opcode == 0x3E) {
1102 /* BBIT0, BBIT1, BBIT032, BBIT132 */
1103 return True;
1106 return False;
1109 static Bool is_Branch_or_Jump_and_Link(const UChar * addr)
1111 UInt cins = getUInt(addr);
1113 UInt opcode = get_opcode(cins);
1114 UInt rt = get_rt(cins);
1115 UInt function = get_function(cins);
1117 /* jal */
1118 if (opcode == 0x02) {
1119 return True;
1122 /* bgezal or bal(r6) */
1123 if (opcode == 0x01 && rt == 0x11) {
1124 return True;
1127 /* bltzal */
1128 if (opcode == 0x01 && rt == 0x10) {
1129 return True;
1132 /* jalr */
1133 if (opcode == 0x00 && function == 0x09) {
1134 return True;
1137 return False;
1140 static Bool branch_or_link_likely(const UChar * addr)
1142 UInt cins = getUInt(addr);
1143 UInt opcode = get_opcode(cins);
1144 UInt rt = get_rt(cins);
1146 /* bgtzl, blezl, bnel, beql */
1147 if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14)
1148 return True;
1150 /* bgezl */
1151 if (opcode == 0x01 && rt == 0x03)
1152 return True;
1154 /* bgezall */
1155 if (opcode == 0x01 && rt == 0x13)
1156 return True;
1158 /* bltzall */
1159 if (opcode == 0x01 && rt == 0x12)
1160 return True;
1162 /* bltzl */
1163 if (opcode == 0x01 && rt == 0x02)
1164 return True;
1166 return False;
1169 /*------------------------------------------------------------*/
1170 /*--- Helper bits and pieces for creating IR fragments. ---*/
1171 /*------------------------------------------------------------*/
1173 static IRExpr *mkU8(UInt i)
1175 vassert(i < 256);
1176 return IRExpr_Const(IRConst_U8((UChar) i));
1179 /* Create an expression node for a 16-bit integer constant. */
1180 static IRExpr *mkU16(UInt i)
1182 return IRExpr_Const(IRConst_U16(i));
1185 /* Create an expression node for a 32-bit integer constant. */
1186 static IRExpr *mkU32(UInt i)
1188 return IRExpr_Const(IRConst_U32(i));
1191 /* Create an expression node for a 64-bit integer constant. */
1192 static IRExpr *mkU64(ULong i)
1194 return IRExpr_Const(IRConst_U64(i));
1197 static IRExpr *mkexpr(IRTemp tmp)
1199 return IRExpr_RdTmp(tmp);
1202 static IRExpr *unop(IROp op, IRExpr * a)
1204 return IRExpr_Unop(op, a);
1207 static IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2)
1209 return IRExpr_Binop(op, a1, a2);
1212 static IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3)
1214 return IRExpr_Triop(op, a1, a2, a3);
1217 static IRExpr *qop ( IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3,
1218 IRExpr * a4 )
1220 return IRExpr_Qop(op, a1, a2, a3, a4);
1223 static IRExpr *load(IRType ty, IRExpr * addr)
1225 IRExpr *load1 = NULL;
1226 #if defined (_MIPSEL)
1227 load1 = IRExpr_Load(Iend_LE, ty, addr);
1228 #elif defined (_MIPSEB)
1229 load1 = IRExpr_Load(Iend_BE, ty, addr);
1230 #endif
1231 return load1;
1234 /* Add a statement to the list held by "irsb". */
1235 static void stmt(IRStmt * st)
1237 addStmtToIRSB(irsb, st);
1240 static void assign(IRTemp dst, IRExpr * e)
1242 stmt(IRStmt_WrTmp(dst, e));
1245 static void store(IRExpr * addr, IRExpr * data)
1247 #if defined (_MIPSEL)
1248 stmt(IRStmt_Store(Iend_LE, addr, data));
1249 #elif defined (_MIPSEB)
1250 stmt(IRStmt_Store(Iend_BE, addr, data));
1251 #endif
1254 /* Generate a new temporary of the given type. */
1255 static IRTemp newTemp(IRType ty)
1257 vassert(isPlausibleIRType(ty));
1258 return newIRTemp(irsb->tyenv, ty);
1261 /* Generate an expression for SRC rotated right by ROT. */
1262 static IRExpr *genROR32(IRExpr * src, Int rot)
1264 vassert(rot >= 0 && rot < 32);
1265 if (rot == 0)
1266 return src;
1267 return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)),
1268 binop(Iop_Shr32, src, mkU8(rot)));
1271 static IRExpr *genRORV32(IRExpr * src, IRExpr * rs)
1273 IRTemp t0 = newTemp(Ity_I8);
1274 IRTemp t1 = newTemp(Ity_I8);
1276 assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F))));
1277 assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0)));
1278 return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)),
1279 binop(Iop_Shr32, src, mkexpr(t0)));
1283 static UShort extend_s_9to16(UInt x)
1285 return (UShort) ((((Int) x) << 23) >> 23);
1288 static UShort extend_s_10to16(UInt x)
1290 return (UShort) ((((Int) x) << 22) >> 22);
1293 static UInt extend_s_10to32(UInt x)
1295 return (UInt)((((Int) x) << 22) >> 22);
1298 static ULong extend_s_10to64(UInt x)
1300 return (ULong)((((Long) x) << 54) >> 54);
1303 static UInt extend_s_16to32(UInt x)
1305 return (UInt) ((((Int) x) << 16) >> 16);
1308 static UInt extend_s_18to32(UInt x)
1310 return (UInt) ((((Int) x) << 14) >> 14);
1313 static UInt extend_s_19to32(UInt x)
1315 return (UInt) ((((Int) x) << 13) >> 13);
1318 static UInt extend_s_23to32(UInt x)
1320 return (UInt) ((((Int) x) << 9) >> 9);
1323 static UInt extend_s_26to32(UInt x)
1325 return (UInt) ((((Int) x) << 6) >> 6);
1328 static ULong extend_s_16to64 ( UInt x )
1330 return (ULong) ((((Long) x) << 48) >> 48);
1333 static ULong extend_s_18to64 ( UInt x )
1335 return (ULong) ((((Long) x) << 46) >> 46);
1338 static ULong extend_s_19to64(UInt x)
1340 return (ULong) ((((Long) x) << 45) >> 45);
1343 static ULong extend_s_23to64(UInt x)
1345 return (ULong) ((((Long) x) << 41) >> 41);
1348 static ULong extend_s_26to64(UInt x)
1350 return (ULong) ((((Long) x) << 38) >> 38);
1353 static ULong extend_s_32to64 ( UInt x )
1355 return (ULong) ((((Long) x) << 32) >> 32);
1358 static void jmp_lit32 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr32 d32 )
1360 vassert(dres->whatNext == Dis_Continue);
1361 vassert(dres->len == 0);
1362 vassert(dres->continueAt == 0);
1363 vassert(dres->jk_StopHere == Ijk_INVALID);
1364 dres->whatNext = Dis_StopHere;
1365 dres->jk_StopHere = kind;
1366 stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) );
1369 static void jmp_lit64 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr64 d64 )
1371 vassert(dres->whatNext == Dis_Continue);
1372 vassert(dres->len == 0);
1373 vassert(dres->continueAt == 0);
1374 vassert(dres->jk_StopHere == Ijk_INVALID);
1375 dres->whatNext = Dis_StopHere;
1376 dres->jk_StopHere = kind;
1377 stmt(IRStmt_Put(OFFB_PC, mkU64(d64)));
1380 /* Get value from accumulator (helper function for MIPS32 DSP ASE instructions).
1381 This function should be called before any other operation if widening
1382 multiplications are used. */
1383 static IRExpr *getAcc(UInt acNo)
1385 vassert(!mode64);
1386 vassert(acNo <= 3);
1387 return IRExpr_Get(accumulatorGuestRegOffset(acNo), Ity_I64);
1390 /* Get value from DSPControl register (helper function for MIPS32 DSP ASE
1391 instructions). */
1392 static IRExpr *getDSPControl(void)
1394 vassert(!mode64);
1395 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_DSPControl), Ity_I32);
1398 /* Put value to DSPControl register. Expression e is written to DSPControl as
1399 is. If only certain bits of DSPControl need to be changed, it should be done
1400 before calling putDSPControl(). It could be done by reading DSPControl and
1401 ORing it with appropriate mask. */
1402 static void putDSPControl(IRExpr * e)
1404 vassert(!mode64);
1405 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_DSPControl), e));
1408 /* Fetch a byte from the guest insn stream. */
1409 static UChar getIByte(Int delta)
1411 return guest_code[delta];
1414 static IRExpr *getIReg(UInt iregNo)
1416 if (0 == iregNo) {
1417 return mode64 ? mkU64(0x0) : mkU32(0x0);
1418 } else {
1419 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1420 vassert(iregNo < 32);
1421 return IRExpr_Get(integerGuestRegOffset(iregNo), ty);
1426 static IRExpr *getWReg(UInt wregNo) {
1427 vassert(wregNo <= 31);
1428 return IRExpr_Get(msaGuestRegOffset(wregNo), Ity_V128);
1431 static IRExpr *getHI(void)
1433 if (mode64)
1434 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_HI), Ity_I64);
1435 else
1436 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32);
1439 static IRExpr *getLO(void)
1441 if (mode64)
1442 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LO), Ity_I64);
1443 else
1444 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32);
1447 static IRExpr *getFCSR(void)
1449 if (mode64)
1450 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_FCSR), Ity_I32);
1451 else
1452 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32);
1455 static IRExpr *getLLaddr(void)
1457 if (mode64)
1458 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLaddr), Ity_I64);
1459 else
1460 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLaddr), Ity_I32);
1463 static IRExpr *getLLdata(void)
1465 if (mode64)
1466 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLdata), Ity_I64);
1467 else
1468 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLdata), Ity_I32);
1471 static IRExpr *getMSACSR(void) {
1472 if (mode64)
1473 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_MSACSR), Ity_I32);
1474 else
1475 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_MSACSR), Ity_I32);
1478 /* Get byte from register reg, byte pos from 0 to 3 (or 7 for MIPS64) . */
1479 static IRExpr *getByteFromReg(UInt reg, UInt byte_pos)
1481 UInt pos = byte_pos * 8;
1482 if (mode64)
1483 return unop(Iop_64to8, binop(Iop_And64,
1484 binop(Iop_Shr64, getIReg(reg), mkU8(pos)),
1485 mkU64(0xFF)));
1486 else
1487 return unop(Iop_32to8, binop(Iop_And32,
1488 binop(Iop_Shr32, getIReg(reg), mkU8(pos)),
1489 mkU32(0xFF)));
1492 static void putFCSR(IRExpr * e)
1494 if (mode64)
1495 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_FCSR), e));
1496 else
1497 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
1500 static void putLLaddr(IRExpr * e)
1502 if (mode64)
1503 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLaddr), e));
1504 else
1505 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLaddr), e));
1508 static void putLLdata(IRExpr * e)
1510 if (mode64)
1511 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLdata), e));
1512 else
1513 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLdata), e));
1516 static void putMSACSR(IRExpr * e) {
1517 if (mode64)
1518 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_MSACSR), e));
1519 else
1520 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_MSACSR), e));
1523 /* fs - fpu source register number.
1524 inst - fpu instruction that needs to be executed.
1525 sz32 - size of source register.
1526 opN - number of operads:
1527 1 - unary operation.
1528 2 - binary operation. */
1529 static void calculateFCSR(UInt fs, UInt ft, UInt inst, Bool sz32, UInt opN)
1531 IRDirty *d;
1532 IRTemp fcsr = newTemp(Ity_I32);
1533 /* IRExpr_GSPTR() => Need to pass pointer to guest state to helper. */
1534 if (fp_mode64)
1535 d = unsafeIRDirty_1_N(fcsr, 0,
1536 "mips_dirtyhelper_calculate_FCSR_fp64",
1537 &mips_dirtyhelper_calculate_FCSR_fp64,
1538 mkIRExprVec_4(IRExpr_GSPTR(),
1539 mkU32(fs),
1540 mkU32(ft),
1541 mkU32(inst)));
1542 else
1543 d = unsafeIRDirty_1_N(fcsr, 0,
1544 "mips_dirtyhelper_calculate_FCSR_fp32",
1545 &mips_dirtyhelper_calculate_FCSR_fp32,
1546 mkIRExprVec_4(IRExpr_GSPTR(),
1547 mkU32(fs),
1548 mkU32(ft),
1549 mkU32(inst)));
1551 if (opN == 1) { /* Unary operation. */
1552 /* Declare we're reading guest state. */
1553 if (sz32 || fp_mode64)
1554 d->nFxState = 2;
1555 else
1556 d->nFxState = 3;
1557 vex_bzero(&d->fxState, sizeof(d->fxState));
1559 d->fxState[0].fx = Ifx_Read; /* read */
1560 if (mode64)
1561 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
1562 else
1563 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
1564 d->fxState[0].size = sizeof(UInt);
1565 d->fxState[1].fx = Ifx_Read; /* read */
1566 d->fxState[1].offset = floatGuestRegOffset(fs);
1567 d->fxState[1].size = sizeof(ULong);
1569 if (!(sz32 || fp_mode64)) {
1570 d->fxState[2].fx = Ifx_Read; /* read */
1571 d->fxState[2].offset = floatGuestRegOffset(fs+1);
1572 d->fxState[2].size = sizeof(ULong);
1574 } else if (opN == 2) { /* Binary operation. */
1575 /* Declare we're reading guest state. */
1576 if (sz32 || fp_mode64)
1577 d->nFxState = 3;
1578 else
1579 d->nFxState = 5;
1580 vex_bzero(&d->fxState, sizeof(d->fxState));
1582 d->fxState[0].fx = Ifx_Read; /* read */
1583 if (mode64)
1584 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
1585 else
1586 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
1587 d->fxState[0].size = sizeof(UInt);
1588 d->fxState[1].fx = Ifx_Read; /* read */
1589 d->fxState[1].offset = floatGuestRegOffset(fs);
1590 d->fxState[1].size = sizeof(ULong);
1591 d->fxState[2].fx = Ifx_Read; /* read */
1592 d->fxState[2].offset = floatGuestRegOffset(ft);
1593 d->fxState[2].size = sizeof(ULong);
1595 if (!(sz32 || fp_mode64)) {
1596 d->fxState[3].fx = Ifx_Read; /* read */
1597 d->fxState[3].offset = floatGuestRegOffset(fs+1);
1598 d->fxState[3].size = sizeof(ULong);
1599 d->fxState[4].fx = Ifx_Read; /* read */
1600 d->fxState[4].offset = floatGuestRegOffset(ft+1);
1601 d->fxState[4].size = sizeof(ULong);
1605 stmt(IRStmt_Dirty(d));
1607 putFCSR(mkexpr(fcsr));
1610 /* ws, wt - source MSA register numbers.
1611 inst - MSA fp instruction that needs to be executed.
1612 opN - number of operads:
1613 1 - unary operation.
1614 2 - binary operation. */
1615 static void calculateMSACSR(UInt ws, UInt wt, UInt inst, UInt opN) {
1616 IRDirty *d;
1617 IRTemp msacsr = newTemp(Ity_I32);
1618 /* IRExpr_BBPTR() => Need to pass pointer to guest state to helper. */
1619 d = unsafeIRDirty_1_N(msacsr, 0,
1620 "mips_dirtyhelper_calculate_MSACSR",
1621 &mips_dirtyhelper_calculate_MSACSR,
1622 mkIRExprVec_4(IRExpr_GSPTR(),
1623 mkU32(ws),
1624 mkU32(wt),
1625 mkU32(inst)));
1627 if (opN == 1) { /* Unary operation. */
1628 /* Declare we're reading guest state. */
1629 d->nFxState = 2;
1630 vex_bzero(&d->fxState, sizeof(d->fxState));
1631 d->fxState[0].fx = Ifx_Read; /* read */
1633 if (mode64)
1634 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_MSACSR);
1635 else
1636 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_MSACSR);
1638 d->fxState[0].size = sizeof(UInt);
1639 d->fxState[1].fx = Ifx_Read; /* read */
1640 d->fxState[1].offset = msaGuestRegOffset(ws);
1641 d->fxState[1].size = sizeof(ULong);
1642 } else if (opN == 2) { /* Binary operation. */
1643 /* Declare we're reading guest state. */
1644 d->nFxState = 3;
1645 vex_bzero(&d->fxState, sizeof(d->fxState));
1646 d->fxState[0].fx = Ifx_Read; /* read */
1648 if (mode64)
1649 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_MSACSR);
1650 else
1651 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_MSACSR);
1653 d->fxState[0].size = sizeof(UInt);
1654 d->fxState[1].fx = Ifx_Read; /* read */
1655 d->fxState[1].offset = msaGuestRegOffset(ws);
1656 d->fxState[1].size = sizeof(ULong);
1657 d->fxState[2].fx = Ifx_Read; /* read */
1658 d->fxState[2].offset = msaGuestRegOffset(wt);
1659 d->fxState[2].size = sizeof(ULong);
1662 stmt(IRStmt_Dirty(d));
1663 putMSACSR(mkexpr(msacsr));
1666 static IRExpr *getULR(void)
1668 if (mode64)
1669 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_ULR), Ity_I64);
1670 else
1671 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32);
1674 static void putIReg(UInt archreg, IRExpr * e)
1676 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1677 vassert(archreg < 32);
1678 vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
1679 if (archreg != 0)
1680 stmt(IRStmt_Put(integerGuestRegOffset(archreg), e));
1683 static void putWReg(UInt wregNo, IRExpr * e) {
1684 vassert(wregNo <= 31);
1685 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1686 stmt(IRStmt_Put(msaGuestRegOffset(wregNo), e));
1687 stmt(IRStmt_Put(floatGuestRegOffset(wregNo),
1688 unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, e))));
1691 static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src)
1693 vassert(ty == Ity_I32 || ty == Ity_I64);
1694 return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
1697 static void putLO(IRExpr * e)
1699 if (mode64) {
1700 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LO), e));
1701 } else {
1702 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e));
1703 /* Add value to lower 32 bits of ac0 to maintain compatibility between
1704 regular MIPS32 instruction set and MIPS DSP ASE. Keep higher 32bits
1705 unchanged. */
1706 IRTemp t_lo = newTemp(Ity_I32);
1707 IRTemp t_hi = newTemp(Ity_I32);
1708 assign(t_lo, e);
1709 assign(t_hi, unop(Iop_64HIto32, getAcc(0)));
1710 stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
1711 binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
1715 static void putHI(IRExpr * e)
1717 if (mode64) {
1718 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_HI), e));
1719 } else {
1720 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e));
1721 /* Add value to higher 32 bits of ac0 to maintain compatibility between
1722 regular MIPS32 instruction set and MIPS DSP ASE. Keep lower 32bits
1723 unchanged. */
1724 IRTemp t_lo = newTemp(Ity_I32);
1725 IRTemp t_hi = newTemp(Ity_I32);
1726 assign(t_hi, e);
1727 assign(t_lo, unop(Iop_64to32, getAcc(0)));
1728 stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
1729 binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
1733 /* Put value to accumulator(helper function for MIPS32 DSP ASE instructions). */
1734 static void putAcc(UInt acNo, IRExpr * e)
1736 vassert(!mode64);
1737 vassert(acNo <= 3);
1738 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64);
1739 stmt(IRStmt_Put(accumulatorGuestRegOffset(acNo), e));
1740 /* If acNo = 0, split value to HI and LO regs in order to maintain compatibility
1741 between MIPS32 and MIPS DSP ASE insn sets. */
1742 if (0 == acNo) {
1743 putLO(unop(Iop_64to32, e));
1744 putHI(unop(Iop_64HIto32, e));
1748 static IRExpr *mkNarrowTo8 ( IRType ty, IRExpr * src )
1750 vassert(ty == Ity_I32 || ty == Ity_I64);
1751 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
1754 static IRExpr *mkNarrowTo16 ( IRType ty, IRExpr * src )
1756 vassert(ty == Ity_I32 || ty == Ity_I64);
1757 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
1760 static void putPC(IRExpr * e)
1762 stmt(IRStmt_Put(OFFB_PC, e));
1765 static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined)
1767 vassert(ty == Ity_I32 || ty == Ity_I64);
1768 if (ty == Ity_I32)
1769 return src;
1770 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
1773 /* Narrow 8/16/32 bit int expr to 8/16/32. Clearly only some
1774 of these combinations make sense. */
1775 static IRExpr *narrowTo(IRType dst_ty, IRExpr * e)
1777 IRType src_ty = typeOfIRExpr(irsb->tyenv, e);
1778 if (src_ty == dst_ty)
1779 return e;
1780 if (src_ty == Ity_I32 && dst_ty == Ity_I16)
1781 return unop(Iop_32to16, e);
1782 if (src_ty == Ity_I32 && dst_ty == Ity_I8)
1783 return unop(Iop_32to8, e);
1784 if (src_ty == Ity_I64 && dst_ty == Ity_I8) {
1785 vassert(mode64);
1786 return unop(Iop_64to8, e);
1788 if (src_ty == Ity_I64 && dst_ty == Ity_I16) {
1789 vassert(mode64);
1790 return unop(Iop_64to16, e);
1792 vpanic("narrowTo(mips)");
1793 return 0;
1796 static IRExpr *getLoFromF64(IRType ty, IRExpr * src)
1798 vassert(ty == Ity_F32 || ty == Ity_F64);
1799 if (ty == Ity_F64) {
1800 IRTemp t0, t1;
1801 t0 = newTemp(Ity_I64);
1802 t1 = newTemp(Ity_I32);
1803 assign(t0, unop(Iop_ReinterpF64asI64, src));
1804 assign(t1, unop(Iop_64to32, mkexpr(t0)));
1805 return unop(Iop_ReinterpI32asF32, mkexpr(t1));
1806 } else
1807 return src;
1810 static inline IRExpr *getHiFromF64(IRExpr * src)
1812 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_F64);
1813 return unop(Iop_ReinterpI32asF32, unop(Iop_64HIto32,
1814 unop(Iop_ReinterpF64asI64, src)));
1817 static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src)
1819 vassert(ty == Ity_F32 || ty == Ity_F64);
1820 if (ty == Ity_F64) {
1821 IRTemp t0 = newTemp(Ity_I32);
1822 IRTemp t1 = newTemp(Ity_I64);
1823 assign(t0, unop(Iop_ReinterpF32asI32, src));
1824 assign(t1, binop(Iop_32HLto64, mkU32(0x0), mkexpr(t0)));
1825 return unop(Iop_ReinterpI64asF64, mkexpr(t1));
1826 } else
1827 return src;
1830 /* Convenience function to move to next instruction on condition. */
1831 static void mips_next_insn_if(IRExpr *condition) {
1832 vassert(typeOfIRExpr(irsb->tyenv, condition) == Ity_I1);
1834 stmt(IRStmt_Exit(condition, Ijk_Boring,
1835 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
1836 IRConst_U32(guest_PC_curr_instr + 4),
1837 OFFB_PC));
1840 static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm)
1842 ULong branch_offset;
1843 IRTemp t0;
1845 /* PC = PC + (SignExtend(signed_immed_24) << 2)
1846 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
1847 is added to the address of the instruction following
1848 the branch (not the branch itself), in the branch delay slot, to form
1849 a PC-relative effective target address. */
1850 if (mode64)
1851 branch_offset = extend_s_18to64(imm << 2);
1852 else
1853 branch_offset = extend_s_18to32(imm << 2);
1855 t0 = newTemp(Ity_I1);
1856 assign(t0, guard);
1858 if (mode64)
1859 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
1860 IRConst_U64(guest_PC_curr_instr + 8), OFFB_PC));
1861 else
1862 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
1863 IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC));
1865 irsb->jumpkind = Ijk_Boring;
1867 if (mode64)
1868 return mkU64(guest_PC_curr_instr + 4 + branch_offset);
1869 else
1870 return mkU32(guest_PC_curr_instr + 4 + branch_offset);
1873 static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set)
1875 ULong branch_offset;
1876 IRTemp t0;
1878 if (link) { /* LR (GPR31) = addr of the 2nd instr after branch instr */
1879 if (mode64)
1880 putIReg(31, mkU64(guest_PC_curr_instr + 8));
1881 else
1882 putIReg(31, mkU32(guest_PC_curr_instr + 8));
1885 /* PC = PC + (SignExtend(signed_immed_24) << 2)
1886 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
1887 is added to the address of the instruction following
1888 the branch (not the branch itself), in the branch delay slot, to form
1889 a PC-relative effective target address. */
1891 if (mode64)
1892 branch_offset = extend_s_18to64(imm << 2);
1893 else
1894 branch_offset = extend_s_18to32(imm << 2);
1896 t0 = newTemp(Ity_I1);
1897 assign(t0, guard);
1898 if (mode64)
1899 *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
1900 IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
1901 OFFB_PC);
1902 else
1903 *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
1904 IRConst_U32(guest_PC_curr_instr + 4 +
1905 (UInt) branch_offset), OFFB_PC);
1908 static void dis_branch_compact(Bool link, IRExpr * guard, UInt imm,
1909 DisResult *dres)
1911 ULong branch_offset;
1912 IRTemp t0;
1914 if (link) { /* LR (GPR31) = addr of the instr after branch instr */
1915 if (mode64)
1916 putIReg(31, mkU64(guest_PC_curr_instr + 4));
1917 else
1918 putIReg(31, mkU32(guest_PC_curr_instr + 4));
1919 dres->jk_StopHere = Ijk_Call;
1920 } else {
1921 dres->jk_StopHere = Ijk_Boring;
1924 dres->whatNext = Dis_StopHere;
1926 /* PC = PC + (SignExtend(signed_immed_24) << 2)
1927 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
1928 is added to the address of the instruction following
1929 the branch (not the branch itself), in the branch delay slot, to form
1930 a PC-relative effective target address. */
1932 if (mode64)
1933 branch_offset = extend_s_18to64(imm << 2);
1934 else
1935 branch_offset = extend_s_18to32(imm << 2);
1937 t0 = newTemp(Ity_I1);
1938 assign(t0, guard);
1940 if (mode64) {
1941 stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
1942 IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
1943 OFFB_PC));
1944 putPC(mkU64(guest_PC_curr_instr + 4));
1945 } else {
1946 stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
1947 IRConst_U32(guest_PC_curr_instr + 4 +
1948 (UInt) branch_offset), OFFB_PC));
1949 putPC(mkU32(guest_PC_curr_instr + 4));
1953 static IRExpr *getFReg(UInt fregNo)
1955 vassert(fregNo < 32);
1956 IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
1957 return IRExpr_Get(floatGuestRegOffset(fregNo), ty);
1960 static IRExpr *getDReg(UInt dregNo)
1962 vassert(dregNo < 32);
1963 if (fp_mode64) {
1964 return IRExpr_Get(floatGuestRegOffset(dregNo), Ity_F64);
1965 } else {
1966 /* Read a floating point register pair and combine their contents into a
1967 64-bit value */
1968 IRTemp t0 = newTemp(Ity_F32);
1969 IRTemp t1 = newTemp(Ity_F32);
1970 IRTemp t2 = newTemp(Ity_F64);
1971 IRTemp t3 = newTemp(Ity_I32);
1972 IRTemp t4 = newTemp(Ity_I32);
1973 IRTemp t5 = newTemp(Ity_I64);
1975 assign(t0, getFReg(dregNo & (~1)));
1976 assign(t1, getFReg(dregNo | 1));
1978 assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
1979 assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
1980 assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3)));
1981 assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5)));
1983 return mkexpr(t2);
1987 static void putFReg(UInt dregNo, IRExpr * e)
1989 vassert(dregNo < 32);
1990 IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
1991 vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
1993 if (fp_mode64_fre) {
1994 IRTemp t0 = newTemp(Ity_F32);
1995 assign(t0, getLoFromF64(ty, e));
1996 #if defined (_MIPSEL)
1997 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), mkexpr(t0)));
1998 if (dregNo & 1)
1999 stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0)));
2000 #else
2001 stmt(IRStmt_Put(floatGuestRegOffset(dregNo) + 4, mkexpr(t0)));
2002 if (dregNo & 1)
2003 stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0)));
2004 #endif
2005 } else {
2006 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
2009 if (has_msa && fp_mode64) {
2010 stmt(IRStmt_Put(msaGuestRegOffset(dregNo),
2011 binop(Iop_64HLtoV128,
2012 unop(Iop_ReinterpF64asI64, e),
2013 unop(Iop_ReinterpF64asI64, e))));
2017 static void putDReg(UInt dregNo, IRExpr * e)
2019 if (fp_mode64) {
2020 vassert(dregNo < 32);
2021 IRType ty = Ity_F64;
2022 vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
2023 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
2024 if (fp_mode64_fre) {
2025 IRTemp t0 = newTemp(Ity_F32);
2026 if (dregNo & 1) {
2027 assign(t0, getLoFromF64(ty, e));
2028 #if defined (_MIPSEL)
2029 stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0)));
2030 #else
2031 stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0)));
2032 #endif
2033 } else {
2034 assign(t0, getHiFromF64(e));
2035 #if defined (_MIPSEL)
2036 stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1), mkexpr(t0)));
2037 #else
2038 stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1) + 4, mkexpr(t0)));
2039 #endif
2042 if (has_msa)
2043 stmt(IRStmt_Put(msaGuestRegOffset(dregNo),
2044 binop(Iop_64HLtoV128,
2045 unop(Iop_ReinterpF64asI64, e),
2046 unop(Iop_ReinterpF64asI64, e))));
2047 } else {
2048 vassert(dregNo < 32);
2049 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
2050 IRTemp t1 = newTemp(Ity_F64);
2051 IRTemp t4 = newTemp(Ity_I32);
2052 IRTemp t5 = newTemp(Ity_I32);
2053 IRTemp t6 = newTemp(Ity_I64);
2054 assign(t1, e);
2055 assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1)));
2056 assign(t4, unop(Iop_64HIto32, mkexpr(t6))); /* hi */
2057 assign(t5, unop(Iop_64to32, mkexpr(t6))); /* lo */
2058 putFReg(dregNo & (~1), unop(Iop_ReinterpI32asF32, mkexpr(t5)));
2059 putFReg(dregNo | 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
2063 static void setFPUCondCode(IRExpr * e, UInt cc)
2065 if (cc == 0) {
2066 putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF)));
2067 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23))));
2068 } else {
2069 putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32,
2070 binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc)))));
2071 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc))));
2075 static IRExpr* get_IR_roundingmode ( void )
2078 rounding mode | MIPS | IR
2079 ------------------------
2080 to nearest | 00 | 00
2081 to zero | 01 | 11
2082 to +infinity | 10 | 10
2083 to -infinity | 11 | 01
2085 IRTemp rm_MIPS = newTemp(Ity_I32);
2086 /* Last two bits in FCSR are rounding mode. */
2088 if (mode64)
2089 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
2090 guest_FCSR), Ity_I32), mkU32(3)));
2091 else
2092 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
2093 guest_FCSR), Ity_I32), mkU32(3)));
2095 /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
2097 return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
2098 binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
2101 static IRExpr* get_IR_roundingmode_MSA ( void ) {
2103 rounding mode | MIPS | IR
2104 ------------------------
2105 to nearest | 00 | 00
2106 to zero | 01 | 11
2107 to +infinity | 10 | 10
2108 to -infinity | 11 | 01
2110 IRTemp rm_MIPS = newTemp(Ity_I32);
2111 /* Last two bits in MSACSR are rounding mode. */
2113 if (mode64)
2114 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
2115 guest_MSACSR), Ity_I32), mkU32(3)));
2116 else
2117 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
2118 guest_MSACSR), Ity_I32), mkU32(3)));
2120 /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
2121 return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
2122 binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
2125 /* sz, ULong -> IRExpr */
2126 static IRExpr *mkSzImm ( IRType ty, ULong imm64 )
2128 vassert(ty == Ity_I32 || ty == Ity_I64);
2129 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt) imm64);
2132 static IRConst *mkSzConst ( IRType ty, ULong imm64 )
2134 vassert(ty == Ity_I32 || ty == Ity_I64);
2135 return (ty == Ity_I64 ? IRConst_U64(imm64) : IRConst_U32((UInt) imm64));
2138 /* Make sure we get valid 32 and 64bit addresses */
2139 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
2141 vassert(ty == Ity_I32 || ty == Ity_I64);
2142 return (ty == Ity_I64 ? (Addr64) addr :
2143 (Addr64) extend_s_32to64(toUInt(addr)));
2146 /* Shift and Rotate instructions for MIPS64 */
2147 static Bool dis_instr_shrt ( UInt theInstr )
2149 UInt opc2 = get_function(theInstr);
2150 UChar regRs = get_rs(theInstr);
2151 UChar regRt = get_rt(theInstr);
2152 UChar regRd = get_rd(theInstr);
2153 UChar uImmsa = get_sa(theInstr);
2154 Long sImmsa = extend_s_16to64(uImmsa);
2155 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2156 IRTemp tmp = newTemp(ty);
2157 IRTemp tmpOr = newTemp(ty);
2158 IRTemp tmpRt = newTemp(ty);
2159 IRTemp tmpRs = newTemp(ty);
2160 IRTemp tmpRd = newTemp(ty);
2162 assign(tmpRs, getIReg(regRs));
2163 assign(tmpRt, getIReg(regRt));
2165 switch (opc2) {
2166 case 0x3A:
2167 if ((regRs & 0x01) == 0) {
2168 /* Doubleword Shift Right Logical - DSRL; MIPS64 */
2169 DIP("dsrl r%u, r%u, %lld", regRd, regRt, sImmsa);
2170 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
2171 putIReg(regRd, mkexpr(tmpRd));
2172 } else if ((regRs & 0x01) == 1) {
2173 /* Doubleword Rotate Right - DROTR; MIPS64r2 */
2174 vassert(mode64);
2175 DIP("drotr r%u, r%u, %lld", regRd, regRt, sImmsa);
2176 IRTemp tmpL = newTemp(ty);
2177 IRTemp tmpR = newTemp(ty);
2178 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
2179 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(63 - uImmsa)));
2180 assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
2181 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
2182 putIReg(regRd, mkexpr(tmpRd));
2183 } else
2184 return False;
2185 break;
2187 case 0x3E:
2188 if ((regRs & 0x01) == 0) {
2189 /* Doubleword Shift Right Logical Plus 32 - DSRL32; MIPS64 */
2190 DIP("dsrl32 r%u, r%u, %lld", regRd, regRt, sImmsa + 32);
2191 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
2192 putIReg(regRd, mkexpr(tmpRd));
2193 } else if ((regRs & 0x01) == 1) {
2194 /* Doubleword Rotate Right Plus 32 - DROTR32; MIPS64r2 */
2195 DIP("drotr32 r%u, r%u, %lld", regRd, regRt, sImmsa);
2196 vassert(mode64);
2197 IRTemp tmpL = newTemp(ty);
2198 IRTemp tmpR = newTemp(ty);
2199 /* (tmpRt >> sa) | (tmpRt << (64 - sa)) */
2200 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
2201 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt),
2202 mkU8(63 - (uImmsa + 32))));
2203 assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
2204 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
2205 putIReg(regRd, mkexpr(tmpRd));
2206 } else
2207 return False;
2208 break;
2210 case 0x16:
2211 if ((uImmsa & 0x01) == 0) {
2212 /* Doubleword Shift Right Logical Variable - DSRLV; MIPS64 */
2213 DIP("dsrlv r%u, r%u, r%u", regRd, regRt, regRs);
2214 IRTemp tmpRs8 = newTemp(Ity_I8);
2215 /* s = tmpRs[5..0] */
2216 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkU64(63)));
2217 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
2218 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
2219 putIReg(regRd, mkexpr(tmpRd));
2220 } else if ((uImmsa & 0x01) == 1) {
2221 /* Doubleword Rotate Right Variable - DROTRV; MIPS64r2 */
2222 DIP("drotrv r%u, r%u, r%u", regRd, regRt, regRs);
2223 IRTemp tmpL = newTemp(ty);
2224 IRTemp tmpR = newTemp(ty);
2225 IRTemp tmpRs8 = newTemp(Ity_I8);
2226 IRTemp tmpLs8 = newTemp(Ity_I8);
2227 IRTemp tmp64 = newTemp(ty);
2228 /* s = tmpRs[5...0]
2229 m = 64 - s
2230 (tmpRt << s) | (tmpRt >> m) */
2232 assign(tmp64, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
2233 assign(tmp, binop(Iop_Sub64, mkU64(63), mkexpr(tmp64)));
2235 assign(tmpLs8, mkNarrowTo8(ty, mkexpr(tmp)));
2236 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp64)));
2238 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
2239 assign(tmpL, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpLs8)));
2240 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpL), mkU8(1)));
2241 assign(tmpOr, binop(Iop_Or64, mkexpr(tmpRd), mkexpr(tmpR)));
2243 putIReg(regRd, mkexpr(tmpOr));
2244 } else
2245 return False;
2246 break;
2248 case 0x38: /* Doubleword Shift Left Logical - DSLL; MIPS64 */
2249 DIP("dsll r%u, r%u, %lld", regRd, regRt, sImmsa);
2250 vassert(mode64);
2251 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa)));
2252 putIReg(regRd, mkexpr(tmpRd));
2253 break;
2255 case 0x3C: /* Doubleword Shift Left Logical Plus 32 - DSLL32; MIPS64 */
2256 DIP("dsll32 r%u, r%u, %lld", regRd, regRt, sImmsa);
2257 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
2258 putIReg(regRd, mkexpr(tmpRd));
2259 break;
2261 case 0x14: { /* Doubleword Shift Left Logical Variable - DSLLV; MIPS64 */
2262 DIP("dsllv r%u, r%u, r%u", regRd, regRt, regRs);
2263 IRTemp tmpRs8 = newTemp(Ity_I8);
2265 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
2266 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
2267 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpRs8)));
2268 putIReg(regRd, mkexpr(tmpRd));
2269 break;
2272 case 0x3B: /* Doubleword Shift Right Arithmetic - DSRA; MIPS64 */
2273 DIP("dsra r%u, r%u, %lld", regRd, regRt, sImmsa);
2274 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa)));
2275 putIReg(regRd, mkexpr(tmpRd));
2276 break;
2278 case 0x3F: /* Doubleword Shift Right Arithmetic Plus 32 - DSRA32;
2279 MIPS64 */
2280 DIP("dsra32 r%u, r%u, %lld", regRd, regRt, sImmsa);
2281 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
2282 putIReg(regRd, mkexpr(tmpRd));
2283 break;
2285 case 0x17: { /* Doubleword Shift Right Arithmetic Variable - DSRAV;
2286 MIPS64 */
2287 DIP("dsrav r%u, r%u, r%u", regRd, regRt, regRs);
2288 IRTemp tmpRs8 = newTemp(Ity_I8);
2289 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
2290 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
2291 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkexpr(tmpRs8)));
2292 putIReg(regRd, mkexpr(tmpRd));
2293 break;
2297 default:
2298 return False;
2301 return True;
2304 static IROp mkSzOp ( IRType ty, IROp op8 )
2306 Int adj;
2307 vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
2308 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8
2309 || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
2310 || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
2311 || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || op8 == Iop_Not8);
2312 adj = ty == Ity_I8 ? 0 : (ty == Ity_I16 ? 1 : (ty == Ity_I32 ? 2 : 3));
2313 return adj + op8;
2316 /*********************************************************/
2317 /*--- Floating Point Compare ---*/
2318 /*********************************************************/
2319 /* Function that returns a string that represent mips cond
2320 mnemonic for the input code. */
2321 static const HChar* showCondCode(UInt code) {
2322 const HChar* ret;
2323 switch (code) {
2324 case 0: ret = "f"; break;
2325 case 1: ret = "un"; break;
2326 case 2: ret = "eq"; break;
2327 case 3: ret = "ueq"; break;
2328 case 4: ret = "olt"; break;
2329 case 5: ret = "ult"; break;
2330 case 6: ret = "ole"; break;
2331 case 7: ret = "ule"; break;
2332 case 8: ret = "sf"; break;
2333 case 9: ret = "ngle"; break;
2334 case 10: ret = "seq"; break;
2335 case 11: ret = "ngl"; break;
2336 case 12: ret = "lt"; break;
2337 case 13: ret = "nge"; break;
2338 case 14: ret = "le"; break;
2339 case 15: ret = "ngt"; break;
2340 default: vpanic("showCondCode"); break;
2342 return ret;
2345 static Bool dis_instr_CCondFmt ( UInt cins )
2347 IRTemp t0, t1, t2, t3, tmp5, tmp6;
2348 IRTemp ccIR = newTemp(Ity_I32);
2349 IRTemp ccMIPS = newTemp(Ity_I32);
2350 UInt FC = get_FC(cins);
2351 UInt fmt = get_fmt(cins);
2352 UInt fs = get_fs(cins);
2353 UInt ft = get_ft(cins);
2354 UInt cond = get_cond(cins);
2356 if (FC == 0x3) { /* C.cond.fmt */
2357 UInt fpc_cc = get_fpc_cc(cins);
2358 switch (fmt) {
2359 case 0x10: { /* C.cond.S */
2360 DIP("c.%s.s %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft);
2361 if (fp_mode64) {
2362 t0 = newTemp(Ity_I32);
2363 t1 = newTemp(Ity_I32);
2364 t2 = newTemp(Ity_I32);
2365 t3 = newTemp(Ity_I32);
2367 tmp5 = newTemp(Ity_F64);
2368 tmp6 = newTemp(Ity_F64);
2370 assign(tmp5, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
2371 getFReg(fs))));
2372 assign(tmp6, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
2373 getFReg(ft))));
2375 assign(ccIR, binop(Iop_CmpF64, mkexpr(tmp5), mkexpr(tmp6)));
2376 putHI(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32,
2377 mkexpr(ccIR), True));
2378 /* Map compare result from IR to MIPS
2379 FP cmp result | MIPS | IR
2380 --------------------------
2381 UN | 0x1 | 0x45
2382 EQ | 0x2 | 0x40
2383 GT | 0x4 | 0x00
2384 LT | 0x8 | 0x01
2387 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
2388 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
2389 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
2390 binop(Iop_Shr32, mkexpr(ccIR),mkU8(5))),mkU32(2)),
2391 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
2392 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
2393 mkU32(1))))));
2394 putLO(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32,
2395 mkexpr(ccMIPS), True));
2397 /* UN */
2398 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
2399 /* EQ */
2400 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
2401 mkU8(0x1)), mkU32(0x1)));
2402 /* NGT */
2403 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
2404 mkexpr(ccMIPS), mkU8(0x2))),mkU32(0x1)));
2405 /* LT */
2406 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
2407 mkU8(0x3)), mkU32(0x1)));
2408 switch (cond) {
2409 case 0x0:
2410 setFPUCondCode(mkU32(0), fpc_cc);
2411 break;
2412 case 0x1:
2413 setFPUCondCode(mkexpr(t0), fpc_cc);
2414 break;
2415 case 0x2:
2416 setFPUCondCode(mkexpr(t1), fpc_cc);
2417 break;
2418 case 0x3:
2419 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2420 fpc_cc);
2421 break;
2422 case 0x4:
2423 setFPUCondCode(mkexpr(t3), fpc_cc);
2424 break;
2425 case 0x5:
2426 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2427 fpc_cc);
2428 break;
2429 case 0x6:
2430 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2431 fpc_cc);
2432 break;
2433 case 0x7:
2434 setFPUCondCode(mkexpr(t2), fpc_cc);
2435 break;
2436 case 0x8:
2437 setFPUCondCode(mkU32(0), fpc_cc);
2438 break;
2439 case 0x9:
2440 setFPUCondCode(mkexpr(t0), fpc_cc);
2441 break;
2442 case 0xA:
2443 setFPUCondCode(mkexpr(t1), fpc_cc);
2444 break;
2445 case 0xB:
2446 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2447 fpc_cc);
2448 break;
2449 case 0xC:
2450 setFPUCondCode(mkexpr(t3), fpc_cc);
2451 break;
2452 case 0xD:
2453 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2454 fpc_cc);
2455 break;
2456 case 0xE:
2457 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2458 fpc_cc);
2459 break;
2460 case 0xF:
2461 setFPUCondCode(mkexpr(t2), fpc_cc);
2462 break;
2464 default:
2465 return False;
2468 } else {
2469 t0 = newTemp(Ity_I32);
2470 t1 = newTemp(Ity_I32);
2471 t2 = newTemp(Ity_I32);
2472 t3 = newTemp(Ity_I32);
2474 assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)),
2475 unop(Iop_F32toF64, getFReg(ft))));
2476 /* Map compare result from IR to MIPS
2477 FP cmp result | MIPS | IR
2478 --------------------------
2479 UN | 0x1 | 0x45
2480 EQ | 0x2 | 0x40
2481 GT | 0x4 | 0x00
2482 LT | 0x8 | 0x01
2485 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
2486 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
2487 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
2488 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))),
2489 mkU32(2)), binop(Iop_And32,
2490 binop(Iop_Xor32, mkexpr(ccIR),
2491 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
2492 mkU32(1))))));
2493 /* UN */
2494 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
2495 /* EQ */
2496 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
2497 mkU8(0x1)), mkU32(0x1)));
2498 /* NGT */
2499 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
2500 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
2501 /* LT */
2502 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
2503 mkU8(0x3)), mkU32(0x1)));
2505 switch (cond) {
2506 case 0x0:
2507 setFPUCondCode(mkU32(0), fpc_cc);
2508 break;
2509 case 0x1:
2510 setFPUCondCode(mkexpr(t0), fpc_cc);
2511 break;
2512 case 0x2:
2513 setFPUCondCode(mkexpr(t1), fpc_cc);
2514 break;
2515 case 0x3:
2516 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2517 fpc_cc);
2518 break;
2519 case 0x4:
2520 setFPUCondCode(mkexpr(t3), fpc_cc);
2521 break;
2522 case 0x5:
2523 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2524 fpc_cc);
2525 break;
2526 case 0x6:
2527 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2528 fpc_cc);
2529 break;
2530 case 0x7:
2531 setFPUCondCode(mkexpr(t2), fpc_cc);
2532 break;
2533 case 0x8:
2534 setFPUCondCode(mkU32(0), fpc_cc);
2535 break;
2536 case 0x9:
2537 setFPUCondCode(mkexpr(t0), fpc_cc);
2538 break;
2539 case 0xA:
2540 setFPUCondCode(mkexpr(t1), fpc_cc);
2541 break;
2542 case 0xB:
2543 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2544 fpc_cc);
2545 break;
2546 case 0xC:
2547 setFPUCondCode(mkexpr(t3), fpc_cc);
2548 break;
2549 case 0xD:
2550 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2551 fpc_cc);
2552 break;
2553 case 0xE:
2554 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2555 fpc_cc);
2556 break;
2557 case 0xF:
2558 setFPUCondCode(mkexpr(t2), fpc_cc);
2559 break;
2561 default:
2562 return False;
2566 break;
2568 case 0x11: { /* C.cond.D */
2569 DIP("c.%s.d %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft);
2570 t0 = newTemp(Ity_I32);
2571 t1 = newTemp(Ity_I32);
2572 t2 = newTemp(Ity_I32);
2573 t3 = newTemp(Ity_I32);
2574 assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
2575 /* Map compare result from IR to MIPS
2576 FP cmp result | MIPS | IR
2577 --------------------------
2578 UN | 0x1 | 0x45
2579 EQ | 0x2 | 0x40
2580 GT | 0x4 | 0x00
2581 LT | 0x8 | 0x01
2584 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
2585 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
2586 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
2587 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
2588 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
2589 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
2590 mkU32(1))))));
2592 /* UN */
2593 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
2594 /* EQ */
2595 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
2596 mkU8(0x1)), mkU32(0x1)));
2597 /* NGT */
2598 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
2599 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
2600 /* LT */
2601 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
2602 mkU8(0x3)), mkU32(0x1)));
2604 switch (cond) {
2605 case 0x0:
2606 setFPUCondCode(mkU32(0), fpc_cc);
2607 break;
2608 case 0x1:
2609 setFPUCondCode(mkexpr(t0), fpc_cc);
2610 break;
2611 case 0x2:
2612 setFPUCondCode(mkexpr(t1), fpc_cc);
2613 break;
2614 case 0x3:
2615 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2616 fpc_cc);
2617 break;
2618 case 0x4:
2619 setFPUCondCode(mkexpr(t3), fpc_cc);
2620 break;
2621 case 0x5:
2622 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2623 fpc_cc);
2624 break;
2625 case 0x6:
2626 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2627 fpc_cc);
2628 break;
2629 case 0x7:
2630 setFPUCondCode(mkexpr(t2), fpc_cc);
2631 break;
2632 case 0x8:
2633 setFPUCondCode(mkU32(0), fpc_cc);
2634 break;
2635 case 0x9:
2636 setFPUCondCode(mkexpr(t0), fpc_cc);
2637 break;
2638 case 0xA:
2639 setFPUCondCode(mkexpr(t1), fpc_cc);
2640 break;
2641 case 0xB:
2642 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2643 fpc_cc);
2644 break;
2645 case 0xC:
2646 setFPUCondCode(mkexpr(t3), fpc_cc);
2647 break;
2648 case 0xD:
2649 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2650 fpc_cc);
2651 break;
2652 case 0xE:
2653 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2654 fpc_cc);
2655 break;
2656 case 0xF:
2657 setFPUCondCode(mkexpr(t2), fpc_cc);
2658 break;
2659 default:
2660 return False;
2663 break;
2665 default:
2666 return False;
2668 } else {
2669 return False;
2672 return True;
2675 /*********************************************************/
2676 /*--- Branch Instructions for mips64 ---*/
2677 /*********************************************************/
2678 static Bool dis_instr_branch ( UInt theInstr, DisResult * dres,
2679 Bool(*resteerOkFn) (void *, Addr),
2680 void *callback_opaque, IRStmt ** set )
2682 UInt jmpKind = 0;
2683 UChar opc1 = get_opcode(theInstr);
2684 UChar regRs = get_rs(theInstr);
2685 UChar regRt = get_rt(theInstr);
2686 UInt offset = get_imm(theInstr);
2687 Long sOffset = extend_s_16to64(offset);
2688 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2689 IROp opSlt = mode64 ? Iop_CmpLT64S : Iop_CmpLT32S;
2691 IRTemp tmp = newTemp(ty);
2692 IRTemp tmpRs = newTemp(ty);
2693 IRTemp tmpRt = newTemp(ty);
2694 IRTemp tmpLt = newTemp(ty);
2695 IRTemp tmpReg0 = newTemp(ty);
2697 UChar regLnk = 31; /* reg 31 is link reg in MIPS */
2698 Addr64 addrTgt = 0;
2699 Addr64 cia = guest_PC_curr_instr;
2701 IRExpr *eConst0 = mkSzImm(ty, (UInt) 0);
2702 IRExpr *eNia = mkSzImm(ty, cia + 8);
2703 IRExpr *eCond = NULL;
2705 assign(tmpRs, getIReg(regRs));
2706 assign(tmpRt, getIReg(regRt));
2707 assign(tmpReg0, getIReg(0));
2709 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpReg0), mkexpr(tmpReg0));
2711 switch (opc1) {
2712 case 0x01:
2713 switch (regRt) {
2714 case 0x00: { /* BLTZ rs, offset */
2715 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
2716 IRTemp tmpLtRes = newTemp(Ity_I1);
2718 assign(tmp, eConst0);
2719 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
2720 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
2721 unop(Iop_1Uto32, mkexpr(tmpLtRes)));
2723 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpLt),
2724 mkexpr(tmpReg0));
2726 jmpKind = Ijk_Boring;
2727 break;
2730 case 0x01: { /* BGEZ rs, offset */
2731 IRTemp tmpLtRes = newTemp(Ity_I1);
2732 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
2734 assign(tmp, eConst0);
2735 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
2736 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
2737 unop(Iop_1Uto32, mkexpr(tmpLtRes)));
2738 eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
2739 mkexpr(tmpReg0));
2741 jmpKind = Ijk_Boring;
2742 break;
2745 case 0x11: { /* BGEZAL rs, offset */
2746 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
2747 putIReg(regLnk, eNia);
2748 IRTemp tmpLtRes = newTemp(Ity_I1);
2750 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), eConst0));
2751 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
2752 unop(Iop_1Uto32, mkexpr(tmpLtRes)));
2754 eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
2755 mkexpr(tmpReg0));
2757 jmpKind = Ijk_Call;
2758 break;
2761 case 0x10: { /* BLTZAL rs, offset */
2762 IRTemp tmpLtRes = newTemp(Ity_I1);
2763 IRTemp tmpRes = newTemp(ty);
2765 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
2766 putIReg(regLnk, eNia);
2768 assign(tmp, eConst0);
2769 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
2770 assign(tmpRes, mode64 ? unop(Iop_1Uto64,
2771 mkexpr(tmpLtRes)) : unop(Iop_1Uto32, mkexpr(tmpLtRes)));
2772 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpRes),
2773 mkexpr(tmpReg0));
2775 jmpKind = Ijk_Call;
2776 break;
2780 break;
2781 default:
2782 return False;
2784 *set = IRStmt_Exit(eCond, jmpKind, mkSzConst(ty, addrTgt), OFFB_PC);
2785 return True;
2788 /*********************************************************/
2789 /*--- Cavium Specific Instructions ---*/
2790 /*********************************************************/
2792 /* Convenience function to yield to thread scheduler */
2793 static void jump_back(IRExpr *condition)
2795 stmt( IRStmt_Exit(condition,
2796 Ijk_Yield,
2797 IRConst_U64( guest_PC_curr_instr ),
2798 OFFB_PC) );
2801 /* Based on s390_irgen_load_and_add32. */
2802 static void mips_load_store32(IRTemp op1addr, IRTemp new_val,
2803 IRTemp expd, UChar rd, Bool putIntoRd)
2805 IRCAS *cas;
2806 IRTemp old_mem = newTemp(Ity_I32);
2807 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2809 cas = mkIRCAS(IRTemp_INVALID, old_mem,
2810 #if defined (_MIPSEL)
2811 Iend_LE, mkexpr(op1addr),
2812 #else /* _MIPSEB */
2813 Iend_BE, mkexpr(op1addr),
2814 #endif
2815 NULL, mkexpr(expd), /* expected value */
2816 NULL, mkexpr(new_val) /* new value */);
2817 stmt(IRStmt_CAS(cas));
2819 /* If old_mem contains the expected value, then the CAS succeeded.
2820 Otherwise, it did not */
2821 jump_back(binop(Iop_CmpNE32, mkexpr(old_mem), mkexpr(expd)));
2822 if (putIntoRd)
2823 putIReg(rd, mkWidenFrom32(ty, mkexpr(old_mem), True));
2826 /* Based on s390_irgen_load_and_add64. */
2827 static void mips_load_store64(IRTemp op1addr, IRTemp new_val,
2828 IRTemp expd, UChar rd, Bool putIntoRd)
2830 IRCAS *cas;
2831 IRTemp old_mem = newTemp(Ity_I64);
2832 vassert(mode64);
2833 cas = mkIRCAS(IRTemp_INVALID, old_mem,
2834 #if defined (_MIPSEL)
2835 Iend_LE, mkexpr(op1addr),
2836 #else /* _MIPSEB */
2837 Iend_BE, mkexpr(op1addr),
2838 #endif
2839 NULL, mkexpr(expd), /* expected value */
2840 NULL, mkexpr(new_val) /* new value */);
2841 stmt(IRStmt_CAS(cas));
2843 /* If old_mem contains the expected value, then the CAS succeeded.
2844 Otherwise, it did not */
2845 jump_back(binop(Iop_CmpNE64, mkexpr(old_mem), mkexpr(expd)));
2846 if (putIntoRd)
2847 putIReg(rd, mkexpr(old_mem));
2850 static Bool dis_instr_CVM ( UInt theInstr )
2852 UChar opc2 = get_function(theInstr);
2853 UChar opc1 = get_opcode(theInstr);
2854 UChar regRs = get_rs(theInstr);
2855 UChar regRt = get_rt(theInstr);
2856 UChar regRd = get_rd(theInstr);
2857 /* MIPS trap instructions extract code from theInstr[15:6].
2858 Cavium OCTEON instructions SNEI, SEQI extract immediate operands
2859 from the same bit field [15:6]. */
2860 UInt imm = get_code(theInstr);
2861 UChar lenM1 = get_msb(theInstr);
2862 UChar p = get_lsb(theInstr);
2863 IRType ty = mode64? Ity_I64 : Ity_I32;
2864 IRTemp tmp = newTemp(ty);
2865 IRTemp tmpRs = newTemp(ty);
2866 IRTemp tmpRt = newTemp(ty);
2867 IRTemp t1 = newTemp(ty);
2868 UInt size;
2869 assign(tmpRs, getIReg(regRs));
2871 switch(opc1) {
2872 case 0x1C: {
2873 switch(opc2) {
2874 case 0x03: { /* DMUL rd, rs, rt */
2875 DIP("dmul r%u, r%u, r%u", regRd, regRs, regRt);
2876 IRTemp t0 = newTemp(Ity_I128);
2877 assign(t0, binop(Iop_MullU64, getIReg(regRs), getIReg(regRt)));
2878 putIReg(regRd, unop(Iop_128to64, mkexpr(t0)));
2879 break;
2882 case 0x18: { /* Store Atomic Add Word - SAA; Cavium OCTEON */
2883 DIP("saa r%u, (r%u)", regRt, regRs);
2884 IRTemp addr = newTemp(Ity_I64);
2885 IRTemp new_val = newTemp(Ity_I32);
2886 IRTemp old = newTemp(Ity_I32);
2887 assign(addr, getIReg(regRs));
2888 assign(old, load(Ity_I32, mkexpr(addr)));
2889 assign(new_val, binop(Iop_Add32,
2890 mkexpr(old),
2891 mkNarrowTo32(ty, getIReg(regRt))));
2892 mips_load_store32(addr, new_val, old, 0, False);
2893 break;
2896 /* Store Atomic Add Doubleword - SAAD; Cavium OCTEON */
2897 case 0x19: {
2898 DIP( "saad r%u, (r%u)", regRt, regRs);
2899 IRTemp addr = newTemp(Ity_I64);
2900 IRTemp new_val = newTemp(Ity_I64);
2901 IRTemp old = newTemp(Ity_I64);
2902 assign(addr, getIReg(regRs));
2903 assign(old, load(Ity_I64, mkexpr(addr)));
2904 assign(new_val, binop(Iop_Add64,
2905 mkexpr(old),
2906 getIReg(regRt)));
2907 mips_load_store64(addr, new_val, old, 0, False);
2908 break;
2911 /* LAI, LAID, LAD, LADD, LAS, LASD,
2912 LAC, LACD, LAA, LAAD, LAW, LAWD */
2913 case 0x1f: {
2914 UInt opc3 = get_sa(theInstr);
2915 IRTemp addr = newTemp(Ity_I64);
2916 switch (opc3) {
2917 /* Load Atomic Increment Word - LAI; Cavium OCTEON2 */
2918 case 0x02: {
2919 DIP("lai r%u,(r%u)\n", regRd, regRs);
2920 IRTemp new_val = newTemp(Ity_I32);
2921 IRTemp old = newTemp(Ity_I32);
2922 assign(addr, getIReg(regRs));
2923 assign(old, load(Ity_I32, mkexpr(addr)));
2924 assign(new_val, binop(Iop_Add32,
2925 mkexpr(old),
2926 mkU32(1)));
2927 mips_load_store32(addr, new_val, old, regRd, True);
2928 break;
2930 /* Load Atomic Increment Doubleword - LAID; Cavium OCTEON2 */
2931 case 0x03: {
2932 DIP("laid r%u,(r%u)\n", regRd, regRs);
2933 IRTemp new_val = newTemp(Ity_I64);
2934 IRTemp old = newTemp(Ity_I64);
2935 assign(addr, getIReg(regRs));
2936 assign(old, load(Ity_I64, mkexpr(addr)));
2937 assign(new_val, binop(Iop_Add64,
2938 mkexpr(old),
2939 mkU64(1)));
2940 mips_load_store64(addr, new_val, old, regRd, True);
2941 break;
2943 /* Load Atomic Decrement Word - LAD; Cavium OCTEON2 */
2944 case 0x06: {
2945 DIP("lad r%u,(r%u)\n", regRd, regRs);
2946 IRTemp new_val = newTemp(Ity_I32);
2947 IRTemp old = newTemp(Ity_I32);
2948 assign(addr, getIReg(regRs));
2949 assign(old, load(Ity_I32, mkexpr(addr)));
2950 assign(new_val, binop(Iop_Sub32,
2951 mkexpr(old),
2952 mkU32(1)));
2953 mips_load_store32(addr, new_val, old, regRd, True);
2954 break;
2956 /* Load Atomic Decrement Doubleword - LADD; Cavium OCTEON2 */
2957 case 0x07: {
2958 DIP("ladd r%u,(r%u)\n", regRd, regRs);
2959 IRTemp new_val = newTemp(Ity_I64);
2960 IRTemp old = newTemp(Ity_I64);
2961 assign(addr, getIReg(regRs));
2962 assign(old, load(Ity_I64, mkexpr(addr)));
2963 assign(new_val, binop(Iop_Sub64,
2964 mkexpr(old),
2965 mkU64(1)));
2966 mips_load_store64(addr, new_val, old, regRd, True);
2967 break;
2969 /* Load Atomic Set Word - LAS; Cavium OCTEON2 */
2970 case 0x0a: {
2971 DIP("las r%u,(r%u)\n", regRd, regRs);
2972 IRTemp new_val = newTemp(Ity_I32);
2973 IRTemp old = newTemp(Ity_I32);
2974 assign(addr, getIReg(regRs));
2975 assign(new_val, mkU32(0xffffffff));
2976 assign(old, load(Ity_I32, mkexpr(addr)));
2977 mips_load_store32(addr, new_val, old, regRd, True);
2978 break;
2980 /* Load Atomic Set Doubleword - LASD; Cavium OCTEON2 */
2981 case 0x0b: {
2982 DIP("lasd r%u,(r%u)\n", regRd, regRs);
2983 IRTemp new_val = newTemp(Ity_I64);
2984 IRTemp old = newTemp(Ity_I64);
2985 assign(addr, getIReg(regRs));
2986 assign(new_val, mkU64(0xffffffffffffffffULL));
2987 assign(old, load(Ity_I64, mkexpr(addr)));
2988 mips_load_store64(addr, new_val, old, regRd, True);
2989 break;
2991 /* Load Atomic Clear Word - LAC; Cavium OCTEON2 */
2992 case 0x0e: {
2993 DIP("lac r%u,(r%u)\n", regRd, regRs);
2994 IRTemp new_val = newTemp(Ity_I32);
2995 IRTemp old = newTemp(Ity_I32);
2996 assign(addr, getIReg(regRs));
2997 assign(new_val, mkU32(0));
2998 assign(old, load(Ity_I32, mkexpr(addr)));
2999 mips_load_store32(addr, new_val, old, regRd, True);
3000 break;
3002 /* Load Atomic Clear Doubleword - LACD; Cavium OCTEON2 */
3003 case 0x0f: {
3004 DIP("lacd r%u,(r%u)\n", regRd, regRs);
3005 IRTemp new_val = newTemp(Ity_I64);
3006 IRTemp old = newTemp(Ity_I64);
3007 assign(addr, getIReg(regRs));
3008 assign(new_val, mkU64(0));
3009 assign(old, load(Ity_I64, mkexpr(addr)));
3010 mips_load_store64(addr, new_val, old, regRd, True);
3011 break;
3013 /* Load Atomic Add Word - LAA; Cavium OCTEON2 */
3014 case 0x12: {
3015 DIP("laa r%u,(r%u),r%u\n", regRd, regRs, regRt);
3016 IRTemp new_val = newTemp(Ity_I32);
3017 IRTemp old = newTemp(Ity_I32);
3018 assign(addr, getIReg(regRs));
3019 assign(old, load(Ity_I32, mkexpr(addr)));
3020 assign(new_val, binop(Iop_Add32,
3021 mkexpr(old),
3022 mkNarrowTo32(ty, getIReg(regRt))));
3023 mips_load_store32(addr, new_val, old, regRd, True);
3024 break;
3026 /* Load Atomic Add Doubleword - LAAD; Cavium OCTEON2 */
3027 case 0x13: {
3028 DIP("laad r%u,(r%u),r%u\n", regRd, regRs, regRt);
3029 IRTemp new_val = newTemp(Ity_I64);
3030 IRTemp old = newTemp(Ity_I64);
3031 assign(addr, getIReg(regRs));
3032 assign(old, load(Ity_I64, mkexpr(addr)));
3033 assign(new_val, binop(Iop_Add64,
3034 load(Ity_I64, mkexpr(addr)),
3035 getIReg(regRt)));
3036 mips_load_store64(addr, new_val, old, regRd, True);
3037 break;
3039 /* Load Atomic Swap Word - LAW; Cavium OCTEON2 */
3040 case 0x16: {
3041 DIP("law r%u,(r%u)\n", regRd, regRs);
3042 IRTemp new_val = newTemp(Ity_I32);
3043 IRTemp old = newTemp(Ity_I32);
3044 assign(addr, getIReg(regRs));
3045 assign(new_val, mkNarrowTo32(ty, getIReg(regRt)));
3046 assign(old, load(Ity_I32, mkexpr(addr)));
3047 mips_load_store32(addr, new_val, old, regRd, True);
3048 break;
3050 /* Load Atomic Swap Doubleword - LAWD; Cavium OCTEON2 */
3051 case 0x17: {
3052 DIP("lawd r%u,(r%u)\n", regRd, regRs);
3053 IRTemp new_val = newTemp(Ity_I64);
3054 IRTemp old = newTemp(Ity_I64);
3055 assign(addr, getIReg(regRs));
3056 assign(new_val, getIReg(regRt));
3057 assign(old, load(Ity_I64, mkexpr(addr)));
3058 mips_load_store64(addr, new_val, old, regRd, True);
3059 break;
3061 default:
3062 vex_printf("Unknown laxx instruction, opc3=0x%x\n", opc3);
3063 vex_printf("Instruction=0x%08x\n", theInstr);
3064 return False;
3066 break;
3069 /* Unsigned Byte Add - BADDU rd, rs, rt; Cavium OCTEON */
3070 case 0x28: {
3071 DIP("BADDU r%u, r%u, r%u", regRs, regRt, regRd);
3072 IRTemp t0 = newTemp(Ity_I8);
3074 assign(t0, binop(Iop_Add8,
3075 mkNarrowTo8(ty, getIReg(regRs)),
3076 mkNarrowTo8(ty, getIReg(regRt))));
3078 if (mode64)
3079 putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
3080 unop(Iop_8Uto64, mkexpr(t0)),
3081 mkSzImm(ty, 0xFF)));
3082 else
3083 putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
3084 unop(Iop_8Uto32, mkexpr(t0)),
3085 mkSzImm(ty, 0xFF)));
3086 break;
3089 case 0x2c: { /* Count Ones in a Word - POP; Cavium OCTEON */
3090 int i, shift[5];
3091 IRTemp mask[5];
3092 IRTemp old = newTemp(ty);
3093 IRTemp nyu = IRTemp_INVALID;
3094 assign(old, getIReg(regRs));
3095 DIP("pop r%u, r%u", regRd, regRs);
3097 for (i = 0; i < 5; i++) {
3098 mask[i] = newTemp(ty);
3099 shift[i] = 1 << i;
3101 if(mode64) {
3102 assign(mask[0], mkU64(0x0000000055555555));
3103 assign(mask[1], mkU64(0x0000000033333333));
3104 assign(mask[2], mkU64(0x000000000F0F0F0F));
3105 assign(mask[3], mkU64(0x0000000000FF00FF));
3106 assign(mask[4], mkU64(0x000000000000FFFF));
3108 for (i = 0; i < 5; i++) {
3109 nyu = newTemp(ty);
3110 assign(nyu,
3111 binop(Iop_Add64,
3112 binop(Iop_And64,
3113 mkexpr(old), mkexpr(mask[i])),
3114 binop(Iop_And64,
3115 binop(Iop_Shr64,
3116 mkexpr(old), mkU8(shift[i])),
3117 mkexpr(mask[i]))));
3118 old = nyu;
3120 } else {
3121 assign(mask[0], mkU32(0x55555555));
3122 assign(mask[1], mkU32(0x33333333));
3123 assign(mask[2], mkU32(0x0F0F0F0F));
3124 assign(mask[3], mkU32(0x00FF00FF));
3125 assign(mask[4], mkU32(0x0000FFFF));
3126 assign(old, getIReg(regRs));
3128 for (i = 0; i < 5; i++) {
3129 nyu = newTemp(ty);
3130 assign(nyu,
3131 binop(Iop_Add32,
3132 binop(Iop_And32,
3133 mkexpr(old), mkexpr(mask[i])),
3134 binop(Iop_And32,
3135 binop(Iop_Shr32,
3136 mkexpr(old), mkU8(shift[i])),
3137 mkexpr(mask[i]))));
3138 old = nyu;
3141 putIReg(regRd, mkexpr(nyu));
3142 break;
3145 /* Count Ones in a Doubleword - DPOP; Cavium OCTEON */
3146 case 0x2d: {
3147 int i, shift[6];
3148 IRTemp mask[6];
3149 IRTemp old = newTemp(ty);
3150 IRTemp nyu = IRTemp_INVALID;
3151 DIP("dpop r%u, r%u", regRd, regRs);
3153 for (i = 0; i < 6; i++) {
3154 mask[i] = newTemp(ty);
3155 shift[i] = 1 << i;
3157 vassert(mode64); /*Caution! Only for Mode 64*/
3158 assign(mask[0], mkU64(0x5555555555555555ULL));
3159 assign(mask[1], mkU64(0x3333333333333333ULL));
3160 assign(mask[2], mkU64(0x0F0F0F0F0F0F0F0FULL));
3161 assign(mask[3], mkU64(0x00FF00FF00FF00FFULL));
3162 assign(mask[4], mkU64(0x0000FFFF0000FFFFULL));
3163 assign(mask[5], mkU64(0x00000000FFFFFFFFULL));
3164 assign(old, getIReg(regRs));
3165 for (i = 0; i < 6; i++) {
3166 nyu = newTemp(Ity_I64);
3167 assign(nyu,
3168 binop(Iop_Add64,
3169 binop(Iop_And64,
3170 mkexpr(old), mkexpr(mask[i])),
3171 binop(Iop_And64,
3172 binop(Iop_Shr64,
3173 mkexpr(old), mkU8(shift[i])),
3174 mkexpr(mask[i]))));
3175 old = nyu;
3177 putIReg(regRd, mkexpr(nyu));
3178 break;
3181 case 0x32: /* 5. CINS rd, rs, p, lenm1 */
3182 DIP("cins r%u, r%u, %u, %u\n", regRt, regRs, p, lenM1);
3183 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
3184 mkU8(64-( lenM1+1 ))));
3185 assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
3186 mkU8(64-(p+lenM1+1))));
3187 putIReg( regRt, mkexpr(tmpRt));
3188 break;
3190 case 0x33: /* 6. CINS32 rd, rs, p+32, lenm1 */
3191 DIP("cins32 r%u, r%u, %d, %d\n", regRt, regRs, p+32, lenM1);
3192 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
3193 mkU8(64-( lenM1+1 ))));
3194 assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
3195 mkU8(32-(p+lenM1+1))));
3196 putIReg( regRt, mkexpr(tmpRt));
3197 break;
3199 case 0x3A: /* 3. EXTS rt, rs, p len */
3200 DIP("exts r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
3201 size = lenM1 + 1; /* lenm1+1 */
3202 UChar lsAmt = 64 - (p + size); /* p+lenm1+1 */
3203 UChar rsAmt = 64 - size; /* lenm1+1 */
3204 tmp = newTemp(Ity_I64);
3205 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
3206 putIReg(regRt, binop(Iop_Sar64, mkexpr(tmp), mkU8(rsAmt)));
3207 break;
3209 case 0x3B: /* 4. EXTS32 rt, rs, p len */
3210 DIP("exts32 r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
3211 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
3212 mkU8(32-(p+lenM1+1))));
3213 assign ( tmpRt, binop(Iop_Sar64, mkexpr(tmp),
3214 mkU8(64-(lenM1+1))) );
3215 putIReg( regRt, mkexpr(tmpRt));
3216 break;
3218 case 0x2B: /* 20. SNE rd, rs, rt */
3219 DIP("sne r%u, r%u, r%u", regRd,regRs, regRt);
3220 if (mode64)
3221 putIReg(regRd, unop(Iop_1Uto64, binop(Iop_CmpNE64,
3222 getIReg(regRs),
3223 getIReg(regRt))));
3224 else
3225 putIReg(regRd,unop(Iop_1Uto32, binop(Iop_CmpNE32,
3226 getIReg(regRs),
3227 getIReg(regRt))));
3228 break;
3230 case 0x2A: /* Set Equals - SEQ; Cavium OCTEON */
3231 DIP("seq r%u, r%u, %d", regRd, regRs, regRt);
3232 if (mode64)
3233 putIReg(regRd, unop(Iop_1Uto64,
3234 binop(Iop_CmpEQ64, getIReg(regRs),
3235 getIReg(regRt))));
3236 else
3237 putIReg(regRd, unop(Iop_1Uto32,
3238 binop(Iop_CmpEQ32, getIReg(regRs),
3239 getIReg(regRt))));
3240 break;
3242 case 0x2E: /* Set Equals Immediate - SEQI; Cavium OCTEON */
3243 DIP("seqi r%u, r%u, %u", regRt, regRs, imm);
3244 if (mode64)
3245 putIReg(regRt, unop(Iop_1Uto64,
3246 binop(Iop_CmpEQ64, getIReg(regRs),
3247 mkU64(extend_s_10to64(imm)))));
3248 else
3249 putIReg(regRt, unop(Iop_1Uto32,
3250 binop(Iop_CmpEQ32, getIReg(regRs),
3251 mkU32(extend_s_10to32(imm)))));
3252 break;
3254 case 0x2F: /* Set Not Equals Immediate - SNEI; Cavium OCTEON */
3255 DIP("snei r%u, r%u, %u", regRt, regRs, imm);
3256 if (mode64)
3257 putIReg(regRt, unop(Iop_1Uto64,
3258 binop(Iop_CmpNE64,
3259 getIReg(regRs),
3260 mkU64(extend_s_10to64(imm)))));
3261 else
3262 putIReg(regRt, unop(Iop_1Uto32,
3263 binop(Iop_CmpNE32,
3264 getIReg(regRs),
3265 mkU32(extend_s_10to32(imm)))));
3266 break;
3268 default:
3269 return False;
3271 break;
3272 } /* opc1 0x1C ends here*/
3273 case 0x1F: {
3274 switch(opc2) {
3275 case 0x0A: { // lx - Load indexed instructions
3276 switch (get_sa(theInstr)) {
3277 case 0x00: { // LWX rd, index(base)
3278 DIP("lwx r%u, r%u(r%u)", regRd, regRt, regRs);
3279 LOADX_STORE_PATTERN;
3280 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
3281 True));
3282 break;
3284 case 0x04: // LHX rd, index(base)
3285 DIP("lhx r%u, r%u(r%u)", regRd, regRt, regRs);
3286 LOADX_STORE_PATTERN;
3287 if (mode64)
3288 putIReg(regRd, unop(Iop_16Sto64, load(Ity_I16,
3289 mkexpr(t1))));
3290 else
3291 putIReg(regRd, unop(Iop_16Sto32, load(Ity_I16,
3292 mkexpr(t1))));
3293 break;
3294 case 0x08: { // LDX rd, index(base)
3295 DIP("ldx r%u, r%u(r%u)", regRd, regRt, regRs);
3296 vassert(mode64); /* Currently Implemented only for n64 */
3297 LOADX_STORE_PATTERN;
3298 putIReg(regRd, load(Ity_I64, mkexpr(t1)));
3299 break;
3301 case 0x06: { // LBUX rd, index(base)
3302 DIP("lbux r%u, r%u(r%u)", regRd, regRt, regRs);
3303 LOADX_STORE_PATTERN;
3304 if (mode64)
3305 putIReg(regRd, unop(Iop_8Uto64, load(Ity_I8,
3306 mkexpr(t1))));
3307 else
3308 putIReg(regRd, unop(Iop_8Uto32, load(Ity_I8,
3309 mkexpr(t1))));
3310 break;
3312 case 0x10: { // LWUX rd, index(base) (Cavium OCTEON)
3313 DIP("lwux r%u, r%u(r%u)", regRd, regRt, regRs);
3314 LOADX_STORE_PATTERN; /* same for both 32 and 64 modes*/
3315 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
3316 False));
3317 break;
3319 case 0x14: { // LHUX rd, index(base) (Cavium OCTEON)
3320 DIP("lhux r%u, r%u(r%u)", regRd, regRt, regRs);
3321 LOADX_STORE_PATTERN;
3322 if (mode64)
3323 putIReg(regRd,
3324 unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
3325 else
3326 putIReg(regRd,
3327 unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
3328 break;
3330 case 0x16: { // LBX rd, index(base) (Cavium OCTEON)
3331 DIP("lbx r%u, r%u(r%u)", regRd, regRs, regRt);
3332 LOADX_STORE_PATTERN;
3333 if (mode64)
3334 putIReg(regRd,
3335 unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
3336 else
3337 putIReg(regRd,
3338 unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
3339 break;
3341 default:
3342 vex_printf("\nUnhandled LX instruction opc3 = %x\n",
3343 get_sa(theInstr));
3344 return False;
3346 break;
3348 } /* opc1 = 0x1F & opc2 = 0xA (LX) ends here*/
3349 break;
3350 } /* opc1 = 0x1F ends here*/
3351 default:
3352 return False;
3353 } /* main opc1 switch ends here */
3354 return True;
3357 /*------------------------------------------------------------*/
3358 /*--- Disassemble a single DSP ASE instruction ---*/
3359 /*------------------------------------------------------------*/
3361 static UInt disDSPInstr_MIPS_WRK ( UInt cins )
3363 IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14,
3364 t15, t16, t17;
3365 UInt opcode, rs, rt, rd, sa, function, ac, ac_mfhilo, rddsp_mask,
3366 wrdsp_mask, dsp_imm, shift;
3368 opcode = get_opcode(cins);
3369 rs = get_rs(cins);
3370 rt = get_rt(cins);
3371 rd = get_rd(cins);
3372 sa = get_sa(cins);
3373 function = get_function(cins);
3374 ac = get_acNo(cins);
3375 ac_mfhilo = get_acNo_mfhilo(cins);
3376 rddsp_mask = get_rddspMask(cins);
3377 wrdsp_mask = get_wrdspMask(cins);
3378 dsp_imm = get_dspImm(cins);
3379 shift = get_shift(cins);
3381 switch (opcode) {
3382 case 0x00: { /* Special */
3383 switch (function) {
3384 case 0x10: { /* MFHI */
3385 DIP("mfhi ac%u r%u", ac_mfhilo, rd);
3386 putIReg(rd, unop(Iop_64HIto32, getAcc(ac_mfhilo)));
3387 break;
3390 case 0x11: { /* MTHI */
3391 DIP("mthi ac%u r%u", ac, rs);
3392 t1 = newTemp(Ity_I32);
3393 assign(t1, unop(Iop_64to32, getAcc(ac)));
3394 putAcc(ac, binop(Iop_32HLto64, getIReg(rs), mkexpr(t1)));
3395 break;
3398 case 0x12: { /* MFLO */
3399 DIP("mflo ac%u r%u", ac_mfhilo, rd);
3400 putIReg(rd, unop(Iop_64to32, getAcc(ac_mfhilo)));
3401 break;
3404 case 0x13: { /* MTLO */
3405 DIP("mtlo ac%u r%u", ac, rs);
3406 t1 = newTemp(Ity_I32);
3407 assign(t1, unop(Iop_64HIto32, getAcc(ac)));
3408 putAcc(ac, binop(Iop_32HLto64, mkexpr(t1), getIReg(rs)));
3409 break;
3412 case 0x18: { /* MULT */
3413 DIP("mult ac%u r%u, r%u", ac, rs, rt);
3414 t1 = newTemp(Ity_I64);
3415 assign(t1, binop(Iop_MullS32, mkNarrowTo32(Ity_I32, getIReg(rs)),
3416 mkNarrowTo32(Ity_I32, getIReg(rt))));
3417 putAcc(ac, mkexpr(t1));
3418 break;
3421 case 0x19: { /* MULTU */
3422 DIP("multu ac%u r%u, r%u", ac, rs, rt);
3423 t1 = newTemp(Ity_I64);
3424 assign(t1, binop(Iop_MullU32, mkNarrowTo32(Ity_I32, getIReg(rs)),
3425 mkNarrowTo32(Ity_I32,
3426 getIReg(rt))));
3427 putAcc(ac, mkexpr(t1));
3428 break;
3431 break;
3433 case 0x1C: { /* Special2 */
3434 switch (function) {
3435 case 0x00: { /* MADD */
3436 DIP("madd ac%u, r%u, r%u", ac, rs, rt);
3437 t1 = newTemp(Ity_I64);
3438 t2 = newTemp(Ity_I64);
3439 t3 = newTemp(Ity_I64);
3441 assign(t1, getAcc(ac));
3442 assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
3443 assign(t3, binop(Iop_Add64, mkexpr(t1), mkexpr(t2)));
3445 putAcc(ac, mkexpr(t3));
3446 break;
3448 case 0x01: { /* MADDU */
3449 DIP("maddu ac%u r%u, r%u", ac, rs, rt);
3450 t1 = newTemp(Ity_I64);
3451 t2 = newTemp(Ity_I64);
3452 t3 = newTemp(Ity_I64);
3454 assign(t1, getAcc(ac));
3455 assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
3456 assign(t3, binop(Iop_Add64, mkexpr(t2), mkexpr(t1)));
3458 putAcc(ac, mkexpr(t3));
3459 break;
3461 case 0x04: { /* MSUB */
3462 DIP("msub ac%u r%u, r%u", ac, rs, rt);
3463 t1 = newTemp(Ity_I64);
3464 t2 = newTemp(Ity_I64);
3465 t3 = newTemp(Ity_I64);
3467 assign(t1, getAcc(ac));
3468 assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
3469 assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));
3471 putAcc(ac, mkexpr(t3));
3472 break;
3474 case 0x05: { /* MSUBU */
3475 DIP("msubu ac%u r%u, r%u", ac, rs, rt);
3476 t1 = newTemp(Ity_I64);
3477 t2 = newTemp(Ity_I64);
3478 t3 = newTemp(Ity_I64);
3480 assign(t1, getAcc(ac));
3481 assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
3482 assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));
3484 putAcc(ac, mkexpr(t3));
3485 break;
3488 break;
3490 case 0x1F: { /* Special3 */
3491 switch (function) {
3492 case 0x12: { /* ABSQ_S.PH */
3493 switch (sa) {
3494 case 0x1: { /* ABSQ_S.QB */
3495 DIP("absq_s.qb r%u, r%u", rd, rt);
3496 vassert(!mode64);
3497 t0 = newTemp(Ity_I8);
3498 t1 = newTemp(Ity_I1);
3499 t2 = newTemp(Ity_I1);
3500 t3 = newTemp(Ity_I8);
3501 t4 = newTemp(Ity_I8);
3502 t5 = newTemp(Ity_I1);
3503 t6 = newTemp(Ity_I1);
3504 t7 = newTemp(Ity_I8);
3505 t8 = newTemp(Ity_I8);
3506 t9 = newTemp(Ity_I1);
3507 t10 = newTemp(Ity_I1);
3508 t11 = newTemp(Ity_I8);
3509 t12 = newTemp(Ity_I8);
3510 t13 = newTemp(Ity_I1);
3511 t14 = newTemp(Ity_I1);
3512 t15 = newTemp(Ity_I8);
3513 t16 = newTemp(Ity_I32);
3514 t17 = newTemp(Ity_I32);
3516 /* Absolute value of the rightmost byte (bits 7-0). */
3517 /* t0 - rightmost byte. */
3518 assign(t0, unop(Iop_16to8, unop(Iop_32to16, getIReg(rt))));
3519 /* t1 holds 1 if t0 is equal to 0x80, or 0 otherwise. */
3520 assign(t1, binop(Iop_CmpEQ32,
3521 unop(Iop_8Uto32, mkexpr(t0)),
3522 mkU32(0x00000080)));
3523 /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
3524 assign(t2, unop(Iop_32to1,
3525 binop(Iop_Shr32,
3526 binop(Iop_And32,
3527 getIReg(rt),
3528 mkU32(0x00000080)),
3529 mkU8(0x7))));
3530 /* t3 holds abs(t0). */
3531 assign(t3, IRExpr_ITE(mkexpr(t1),
3532 mkU8(0x7F),
3533 IRExpr_ITE(mkexpr(t2),
3534 binop(Iop_Add8,
3535 unop(Iop_Not8,
3536 mkexpr(t0)),
3537 mkU8(0x1)),
3538 mkexpr(t0))));
3540 /* Absolute value of bits 15-8. */
3541 /* t4 - input byte. */
3542 assign(t4,
3543 unop(Iop_16HIto8, unop(Iop_32to16, getIReg(rt))));
3544 /* t5 holds 1 if t4 is equal to 0x80, or 0 otherwise. */
3545 assign(t5, binop(Iop_CmpEQ32,
3546 unop(Iop_8Uto32, mkexpr(t4)),
3547 mkU32(0x00000080)));
3548 /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
3549 assign(t6, unop(Iop_32to1,
3550 binop(Iop_Shr32,
3551 binop(Iop_And32,
3552 getIReg(rt),
3553 mkU32(0x00008000)),
3554 mkU8(15))));
3555 /* t3 holds abs(t4). */
3556 assign(t7, IRExpr_ITE(mkexpr(t5),
3557 mkU8(0x7F),
3558 IRExpr_ITE(mkexpr(t6),
3559 binop(Iop_Add8,
3560 unop(Iop_Not8,
3561 mkexpr(t4)),
3562 mkU8(0x1)),
3563 mkexpr(t4))));
3565 /* Absolute value of bits 23-15. */
3566 /* t8 - input byte. */
3567 assign(t8,
3568 unop(Iop_16to8, unop(Iop_32HIto16, getIReg(rt))));
3569 /* t9 holds 1 if t8 is equal to 0x80, or 0 otherwise. */
3570 assign(t9, binop(Iop_CmpEQ32,
3571 unop(Iop_8Uto32, mkexpr(t8)),
3572 mkU32(0x00000080)));
3573 /* t6 holds 1 if value in t8 is negative, 0 otherwise. */
3574 assign(t10, unop(Iop_32to1,
3575 binop(Iop_Shr32,
3576 binop(Iop_And32,
3577 getIReg(rt),
3578 mkU32(0x00800000)),
3579 mkU8(23))));
3580 /* t3 holds abs(t8). */
3581 assign(t11, IRExpr_ITE(mkexpr(t9),
3582 mkU8(0x7F),
3583 IRExpr_ITE(mkexpr(t10),
3584 binop(Iop_Add8,
3585 unop(Iop_Not8,
3586 mkexpr(t8)),
3587 mkU8(0x1)),
3588 mkexpr(t8))));
3590 /* Absolute value of bits 31-24. */
3591 /* t12 - input byte. */
3592 assign(t12,
3593 unop(Iop_16HIto8, unop(Iop_32HIto16, getIReg(rt))));
3594 /* t13 holds 1 if t12 is equal to 0x80, or 0 otherwise. */
3595 assign(t13, binop(Iop_CmpEQ32,
3596 unop(Iop_8Uto32, mkexpr(t12)),
3597 mkU32(0x00000080)));
3598 /* t14 holds 1 if value in t12 is negative, 0 otherwise. */
3599 assign(t14, unop(Iop_32to1,
3600 binop(Iop_Shr32,
3601 binop(Iop_And32,
3602 getIReg(rt),
3603 mkU32(0x80000000)),
3604 mkU8(31))));
3605 /* t15 holds abs(t12). */
3606 assign(t15, IRExpr_ITE(mkexpr(t13),
3607 mkU8(0x7F),
3608 IRExpr_ITE(mkexpr(t14),
3609 binop(Iop_Add8,
3610 unop(Iop_Not8,
3611 mkexpr(t12)),
3612 mkU8(0x1)),
3613 mkexpr(t12))));
3615 /* t16 holds !0 if any of input bytes is 0x80 or 0
3616 otherwise. */
3617 assign(t16,
3618 binop(Iop_Or32,
3619 binop(Iop_Or32,
3620 binop(Iop_Or32,
3621 unop(Iop_1Sto32, mkexpr(t13)),
3622 unop(Iop_1Sto32, mkexpr(t9))),
3623 unop(Iop_1Sto32, mkexpr(t5))),
3624 unop(Iop_1Sto32, mkexpr(t1))));
3626 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
3627 mkexpr(t16),
3628 mkU32(0x0)),
3629 getDSPControl(),
3630 binop(Iop_Or32,
3631 getDSPControl(),
3632 mkU32(0x00100000))));
3634 /* t17 = t15|t11|t7|t3 */
3635 assign(t17,
3636 binop(Iop_16HLto32,
3637 binop(Iop_8HLto16, mkexpr(t15), mkexpr(t11)),
3638 binop(Iop_8HLto16, mkexpr(t7), mkexpr(t3))));
3640 putIReg(rd, mkexpr(t17));
3641 break;
3643 case 0x2: { /* REPL.QB */
3644 DIP("repl.qb r%u, %u", rd, dsp_imm);
3645 vassert(!mode64);
3647 putIReg(rd, mkU32((dsp_imm << 24) | (dsp_imm << 16) |
3648 (dsp_imm << 8) | (dsp_imm)));
3649 break;
3651 case 0x3: { /* REPLV.QB */
3652 DIP("replv.qb r%u, r%u", rd, rt);
3653 vassert(!mode64);
3654 t0 = newTemp(Ity_I8);
3656 assign(t0, unop(Iop_32to8,
3657 binop(Iop_And32, getIReg(rt), mkU32(0xff))));
3658 putIReg(rd,
3659 binop(Iop_16HLto32,
3660 binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)),
3661 binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0))));
3662 break;
3664 case 0x4: { /* PRECEQU.PH.QBL */
3665 DIP("precequ.ph.qbl r%u, r%u", rd, rt);
3666 vassert(!mode64);
3668 putIReg(rd, binop(Iop_Or32,
3669 binop(Iop_Shr32,
3670 binop(Iop_And32,
3671 getIReg(rt),
3672 mkU32(0xff000000)),
3673 mkU8(1)),
3674 binop(Iop_Shr32,
3675 binop(Iop_And32,
3676 getIReg(rt),
3677 mkU32(0x00ff0000)),
3678 mkU8(9))));
3679 break;
3681 case 0x5: { /* PRECEQU.PH.QBR */
3682 DIP("precequ.ph.qbr r%u, r%u", rd, rt);
3683 vassert(!mode64);
3685 putIReg(rd, binop(Iop_Or32,
3686 binop(Iop_Shl32,
3687 binop(Iop_And32,
3688 getIReg(rt),
3689 mkU32(0x0000ff00)),
3690 mkU8(15)),
3691 binop(Iop_Shl32,
3692 binop(Iop_And32,
3693 getIReg(rt),
3694 mkU32(0x000000ff)),
3695 mkU8(7))));
3696 break;
3698 case 0x6: { /* PRECEQU.PH.QBLA */
3699 DIP("precequ.ph.qbla r%u, r%u", rd, rt);
3700 vassert(!mode64);
3702 putIReg(rd, binop(Iop_Or32,
3703 binop(Iop_Shr32,
3704 binop(Iop_And32,
3705 getIReg(rt),
3706 mkU32(0xff000000)),
3707 mkU8(1)),
3708 binop(Iop_Shr32,
3709 binop(Iop_And32,
3710 getIReg(rt),
3711 mkU32(0x0000ff00)),
3712 mkU8(1))));
3713 break;
3715 case 0x7: { /* PRECEQU.PH.QBRA */
3716 DIP("precequ.ph.qbra r%u, r%u", rd, rt);
3717 vassert(!mode64);
3719 putIReg(rd, binop(Iop_Or32,
3720 binop(Iop_Shl32,
3721 binop(Iop_And32,
3722 getIReg(rt),
3723 mkU32(0x00ff0000)),
3724 mkU8(7)),
3725 binop(Iop_Shl32,
3726 binop(Iop_And32,
3727 getIReg(rt),
3728 mkU32(0x000000ff)),
3729 mkU8(7))));
3730 break;
3732 case 0x9: { /* ABSQ_S.PH */
3733 DIP("absq_s.ph r%u, r%u", rd, rt);
3734 vassert(!mode64);
3735 t0 = newTemp(Ity_I16);
3736 t1 = newTemp(Ity_I1);
3737 t2 = newTemp(Ity_I1);
3738 t3 = newTemp(Ity_I16);
3739 t4 = newTemp(Ity_I16);
3740 t5 = newTemp(Ity_I1);
3741 t6 = newTemp(Ity_I1);
3742 t7 = newTemp(Ity_I16);
3743 t8 = newTemp(Ity_I32);
3744 t9 = newTemp(Ity_I32);
3746 /* t0 holds lower 16 bits of value in rt. */
3747 assign(t0, unop(Iop_32to16, getIReg(rt)));
3748 /* t1 holds 1 if t0 is equal to 0x8000. */
3749 assign(t1, binop(Iop_CmpEQ32,
3750 unop(Iop_16Uto32, mkexpr(t0)),
3751 mkU32(0x00008000)));
3752 /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
3753 assign(t2, unop(Iop_32to1,
3754 binop(Iop_Shr32,
3755 binop(Iop_And32,
3756 getIReg(rt),
3757 mkU32(0x00008000)),
3758 mkU8(15))));
3759 /* t3 holds abs(t0). */
3760 assign(t3, IRExpr_ITE(mkexpr(t1),
3761 mkU16(0x7FFF),
3762 IRExpr_ITE(mkexpr(t2),
3763 binop(Iop_Add16,
3764 unop(Iop_Not16,
3765 mkexpr(t0)),
3766 mkU16(0x1)),
3767 mkexpr(t0))));
3769 /* t4 holds lower 16 bits of value in rt. */
3770 assign(t4, unop(Iop_32HIto16, getIReg(rt)));
3771 /* t5 holds 1 if t4 is equal to 0x8000. */
3772 assign(t5, binop(Iop_CmpEQ32,
3773 unop(Iop_16Uto32, mkexpr(t4)),
3774 mkU32(0x00008000)));
3775 /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
3776 assign(t6, unop(Iop_32to1,
3777 binop(Iop_Shr32,
3778 binop(Iop_And32,
3779 getIReg(rt),
3780 mkU32(0x80000000)),
3781 mkU8(31))));
3782 /* t7 holds abs(t4). */
3783 assign(t7, IRExpr_ITE(mkexpr(t5),
3784 mkU16(0x7FFF),
3785 IRExpr_ITE(mkexpr(t6),
3786 binop(Iop_Add16,
3787 unop(Iop_Not16,
3788 mkexpr(t4)),
3789 mkU16(0x1)),
3790 mkexpr(t4))));
3791 /* If any of the two input halfwords is equal 0x8000,
3792 set bit 20 in DSPControl register. */
3793 assign(t8, binop(Iop_Or32,
3794 unop(Iop_1Sto32, mkexpr(t5)),
3795 unop(Iop_1Sto32, mkexpr(t1))));
3797 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
3798 mkexpr(t8),
3799 mkU32(0x0)),
3800 getDSPControl(),
3801 binop(Iop_Or32,
3802 getDSPControl(),
3803 mkU32(0x00100000))));
3805 /* t9 = t7|t3 */
3806 assign(t9, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3)));
3808 putIReg(rd, mkexpr(t9));
3809 break;
3811 case 0xA: { /* REPL.PH */
3812 DIP("repl.ph r%u, %u", rd, dsp_imm);
3813 vassert(!mode64);
3814 UShort immediate = extend_s_10to16(dsp_imm);
3816 putIReg(rd, mkU32(immediate << 16 | immediate));
3817 break;
3819 case 0xB: { /* REPLV.PH */
3820 DIP("replv.ph r%u, r%u", rd, rt);
3821 vassert(!mode64);
3823 putIReg(rd, binop(Iop_16HLto32,
3824 unop(Iop_32to16, getIReg(rt)),
3825 unop(Iop_32to16, getIReg(rt))));
3826 break;
3828 case 0xC: { /* PRECEQ.W.PHL */
3829 DIP("preceq.w.phl r%u, r%u", rd, rt);
3830 vassert(!mode64);
3831 putIReg(rd, binop(Iop_And32,
3832 getIReg(rt),
3833 mkU32(0xffff0000)));
3834 break;
3836 case 0xD: { /* PRECEQ.W.PHR */
3837 DIP("preceq.w.phr r%u, r%u", rd, rt);
3838 vassert(!mode64);
3839 putIReg(rd, binop(Iop_16HLto32,
3840 unop(Iop_32to16, getIReg(rt)),
3841 mkU16(0x0)));
3842 break;
3844 case 0x11: { /* ABSQ_S.W */
3845 DIP("absq_s.w r%u, r%u", rd, rt);
3846 vassert(!mode64);
3847 t0 = newTemp(Ity_I1);
3848 t1 = newTemp(Ity_I1);
3849 t2 = newTemp(Ity_I32);
3851 assign(t0,
3852 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000)));
3854 putDSPControl(IRExpr_ITE(mkexpr(t0),
3855 binop(Iop_Or32,
3856 getDSPControl(),
3857 mkU32(0x00100000)),
3858 getDSPControl()));
3860 assign(t1, binop(Iop_CmpLT32S, getIReg(rt), mkU32(0x0)));
3862 assign(t2, IRExpr_ITE(mkexpr(t0),
3863 mkU32(0x7FFFFFFF),
3864 IRExpr_ITE(mkexpr(t1),
3865 binop(Iop_Add32,
3866 unop(Iop_Not32,
3867 getIReg(rt)),
3868 mkU32(0x1)),
3869 getIReg(rt))));
3870 putIReg(rd, mkexpr(t2));
3871 break;
3873 case 0x1B: { /* BITREV */
3874 DIP("bitrev r%u, r%u", rd, rt);
3875 vassert(!mode64);
3876 /* 32bit reversal as seen on Bit Twiddling Hacks site
3877 http://graphics.stanford.edu/~seander/bithacks.html
3878 section ReverseParallel */
3879 t1 = newTemp(Ity_I32);
3880 t2 = newTemp(Ity_I32);
3881 t3 = newTemp(Ity_I32);
3882 t4 = newTemp(Ity_I32);
3883 t5 = newTemp(Ity_I32);
3885 assign(t1, binop(Iop_Or32,
3886 binop(Iop_Shr32,
3887 binop(Iop_And32,
3888 getIReg(rt),
3889 mkU32(0xaaaaaaaa)),
3890 mkU8(0x1)),
3891 binop(Iop_Shl32,
3892 binop(Iop_And32,
3893 getIReg(rt),
3894 mkU32(0x55555555)),
3895 mkU8(0x1))));
3896 assign(t2, binop(Iop_Or32,
3897 binop(Iop_Shr32,
3898 binop(Iop_And32,
3899 mkexpr(t1),
3900 mkU32(0xcccccccc)),
3901 mkU8(0x2)),
3902 binop(Iop_Shl32,
3903 binop(Iop_And32,
3904 mkexpr(t1),
3905 mkU32(0x33333333)),
3906 mkU8(0x2))));
3907 assign(t3, binop(Iop_Or32,
3908 binop(Iop_Shr32,
3909 binop(Iop_And32,
3910 mkexpr(t2),
3911 mkU32(0xf0f0f0f0)),
3912 mkU8(0x4)),
3913 binop(Iop_Shl32,
3914 binop(Iop_And32,
3915 mkexpr(t2),
3916 mkU32(0x0f0f0f0f)),
3917 mkU8(0x4))));
3918 assign(t4, binop(Iop_Or32,
3919 binop(Iop_Shr32,
3920 binop(Iop_And32,
3921 mkexpr(t3),
3922 mkU32(0xff00ff00)),
3923 mkU8(0x8)),
3924 binop(Iop_Shl32,
3925 binop(Iop_And32,
3926 mkexpr(t3),
3927 mkU32(0x00ff00ff)),
3928 mkU8(0x8))));
3929 assign(t5, binop(Iop_Or32,
3930 binop(Iop_Shr32,
3931 mkexpr(t4),
3932 mkU8(0x10)),
3933 binop(Iop_Shl32,
3934 mkexpr(t4),
3935 mkU8(0x10))));
3936 putIReg(rd, binop(Iop_Shr32,
3937 mkexpr(t5),
3938 mkU8(16)));
3939 break;
3941 case 0x1C: { /* PRECEU.PH.QBL */
3942 DIP("preceu.ph.qbl r%u, r%u", rd, rt);
3943 vassert(!mode64);
3945 putIReg(rd, binop(Iop_Or32,
3946 binop(Iop_Shr32,
3947 binop(Iop_And32,
3948 getIReg(rt),
3949 mkU32(0xff000000)),
3950 mkU8(8)),
3951 binop(Iop_Shr32,
3952 binop(Iop_And32,
3953 getIReg(rt),
3954 mkU32(0x00ff0000)),
3955 mkU8(16))));
3956 break;
3958 case 0x1E: { /* PRECEU.PH.QBLA */
3959 DIP("preceu.ph.qbla r%u, r%u", rd, rt);
3960 vassert(!mode64);
3962 putIReg(rd, binop(Iop_Or32,
3963 binop(Iop_Shr32,
3964 binop(Iop_And32,
3965 getIReg(rt),
3966 mkU32(0xff000000)),
3967 mkU8(8)),
3968 binop(Iop_Shr32,
3969 binop(Iop_And32,
3970 getIReg(rt),
3971 mkU32(0x0000ff00)),
3972 mkU8(8))));
3973 break;
3975 case 0x1D: { /* PRECEU.PH.QBR */
3976 DIP("preceu.ph.qbr r%u, r%u", rd, rt);
3977 vassert(!mode64);
3979 putIReg(rd, binop(Iop_Or32,
3980 binop(Iop_Shl32,
3981 binop(Iop_And32,
3982 getIReg(rt),
3983 mkU32(0x0000ff00)),
3984 mkU8(8)),
3985 binop(Iop_And32,
3986 getIReg(rt),
3987 mkU32(0x000000ff))));
3988 break;
3990 case 0x1F: { /* PRECEU.PH.QBRA */
3991 DIP("preceu.ph.qbra r%u, r%u", rd, rt);
3992 vassert(!mode64);
3994 putIReg(rd, binop(Iop_Or32,
3995 binop(Iop_And32,
3996 getIReg(rt),
3997 mkU32(0x00ff0000)),
3998 binop(Iop_And32,
3999 getIReg(rt),
4000 mkU32(0x000000ff))));
4001 break;
4003 default:
4004 return -1;
4006 break; /* end of ABSQ_S.PH */
4008 case 0x38: { /* EXTR.W */
4009 switch(sa) {
4010 case 0x0: { /* EXTR.W */
4011 DIP("extr.w r%u, ac%u, %u", rt, ac, rs);
4012 vassert(!mode64);
4013 t0 = newTemp(Ity_I64);
4014 t1 = newTemp(Ity_I64);
4015 t2 = newTemp(Ity_I32);
4016 t3 = newTemp(Ity_I1);
4017 t4 = newTemp(Ity_I1);
4018 t5 = newTemp(Ity_I1);
4019 t6 = newTemp(Ity_I1);
4020 t7 = newTemp(Ity_I32);
4021 t8 = newTemp(Ity_I64);
4022 t9 = newTemp(Ity_I64);
4023 t10 = newTemp(Ity_I1);
4024 t11 = newTemp(Ity_I1);
4025 t12 = newTemp(Ity_I1);
4026 t13 = newTemp(Ity_I1);
4027 t14 = newTemp(Ity_I32);
4029 assign(t0, getAcc(ac));
4030 if (0 == rs) {
4031 assign(t1, mkexpr(t0));
4032 } else {
4033 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
4035 /* Check if bits 63..31 of the result in t1 aren't 0. */
4036 assign(t3, binop(Iop_CmpNE32,
4037 unop(Iop_64HIto32,
4038 mkexpr(t1)),
4039 mkU32(0)));
4040 assign(t4, binop(Iop_CmpNE32,
4041 binop(Iop_And32,
4042 unop(Iop_64to32,
4043 mkexpr(t1)),
4044 mkU32(0x80000000)),
4045 mkU32(0)));
4046 /* Check if bits 63..31 of the result in t1 aren't
4047 0x1ffffffff. */
4048 assign(t5, binop(Iop_CmpNE32,
4049 unop(Iop_64HIto32,
4050 mkexpr(t1)),
4051 mkU32(0xffffffff)));
4052 assign(t6, binop(Iop_CmpNE32,
4053 binop(Iop_And32,
4054 unop(Iop_64to32,
4055 mkexpr(t1)),
4056 mkU32(0x80000000)),
4057 mkU32(0x80000000)));
4058 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
4059 control register. */
4060 assign(t7, binop(Iop_And32,
4061 binop(Iop_Or32,
4062 unop(Iop_1Sto32, mkexpr(t3)),
4063 unop(Iop_1Sto32, mkexpr(t4))),
4064 binop(Iop_Or32,
4065 unop(Iop_1Sto32, mkexpr(t5)),
4066 unop(Iop_1Sto32, mkexpr(t6)))));
4067 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4068 mkexpr(t7),
4069 mkU32(0)),
4070 binop(Iop_Or32,
4071 getDSPControl(),
4072 mkU32(0x00800000)),
4073 getDSPControl()));
4075 /* If the last discarded bit is 1, there would be carry
4076 when rounding, otherwise there wouldn't. We use that
4077 fact and just add the value of the last discarded bit
4078 to the least sifgnificant bit of the shifted value
4079 from acc. */
4080 if (0 == rs) {
4081 assign(t8, mkU64(0x0ULL));
4082 } else {
4083 assign(t8, binop(Iop_And64,
4084 binop(Iop_Shr64,
4085 mkexpr(t0),
4086 mkU8(rs-1)),
4087 mkU64(0x1ULL)));
4089 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
4091 /* Repeat previous steps for the rounded value. */
4092 assign(t10, binop(Iop_CmpNE32,
4093 unop(Iop_64HIto32,
4094 mkexpr(t9)),
4095 mkU32(0)));
4096 assign(t11, binop(Iop_CmpNE32,
4097 binop(Iop_And32,
4098 unop(Iop_64to32,
4099 mkexpr(t9)),
4100 mkU32(0x80000000)),
4101 mkU32(0)));
4103 assign(t12, binop(Iop_CmpNE32,
4104 unop(Iop_64HIto32,
4105 mkexpr(t9)),
4106 mkU32(0xffffffff)));
4107 assign(t13, binop(Iop_CmpNE32,
4108 binop(Iop_And32,
4109 unop(Iop_64to32,
4110 mkexpr(t9)),
4111 mkU32(0x80000000)),
4112 mkU32(0x80000000)));
4114 assign(t14, binop(Iop_And32,
4115 binop(Iop_Or32,
4116 unop(Iop_1Sto32, mkexpr(t10)),
4117 unop(Iop_1Sto32, mkexpr(t11))),
4118 binop(Iop_Or32,
4119 unop(Iop_1Sto32, mkexpr(t12)),
4120 unop(Iop_1Sto32, mkexpr(t13)))));
4121 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4122 mkexpr(t14),
4123 mkU32(0)),
4124 binop(Iop_Or32,
4125 getDSPControl(),
4126 mkU32(0x00800000)),
4127 getDSPControl()));
4128 if (0 == rs) {
4129 putIReg(rt, unop(Iop_64to32, mkexpr(t0)));
4130 } else {
4131 putIReg(rt, unop(Iop_64to32, mkexpr(t1)));
4133 break;
4135 case 0x1: { /* EXTRV.W */
4136 DIP("extrv.w r%u, ac%u, r%u", rt, ac, rs);
4137 vassert(!mode64);
4138 t0 = newTemp(Ity_I64);
4139 t1 = newTemp(Ity_I64);
4140 t2 = newTemp(Ity_I32);
4141 t3 = newTemp(Ity_I1);
4142 t4 = newTemp(Ity_I1);
4143 t5 = newTemp(Ity_I1);
4144 t6 = newTemp(Ity_I1);
4145 t7 = newTemp(Ity_I32);
4146 t8 = newTemp(Ity_I64);
4147 t9 = newTemp(Ity_I64);
4148 t10 = newTemp(Ity_I1);
4149 t11 = newTemp(Ity_I1);
4150 t12 = newTemp(Ity_I1);
4151 t13 = newTemp(Ity_I1);
4152 t14 = newTemp(Ity_I32);
4153 t15 = newTemp(Ity_I8);
4155 assign(t15, unop(Iop_32to8,
4156 binop(Iop_And32,
4157 getIReg(rs),
4158 mkU32(0x1f))));
4159 assign(t0, getAcc(ac));
4160 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));
4161 putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
4162 unop(Iop_8Uto32,
4163 mkexpr(t15)),
4164 mkU32(0)),
4165 unop(Iop_64to32, mkexpr(t0)),
4166 unop(Iop_64to32, mkexpr(t1))));
4168 /* Check if bits 63..31 of the result in t1 aren't 0. */
4169 assign(t3, binop(Iop_CmpNE32,
4170 unop(Iop_64HIto32,
4171 mkexpr(t1)),
4172 mkU32(0)));
4173 assign(t4, binop(Iop_CmpNE32,
4174 binop(Iop_And32,
4175 unop(Iop_64to32,
4176 mkexpr(t1)),
4177 mkU32(0x80000000)),
4178 mkU32(0)));
4179 /* Check if bits 63..31 of the result in t1 aren't
4180 0x1ffffffff. */
4181 assign(t5, binop(Iop_CmpNE32,
4182 unop(Iop_64HIto32,
4183 mkexpr(t1)),
4184 mkU32(0xffffffff)));
4185 assign(t6, binop(Iop_CmpNE32,
4186 binop(Iop_And32,
4187 unop(Iop_64to32,
4188 mkexpr(t1)),
4189 mkU32(0x80000000)),
4190 mkU32(0x80000000)));
4191 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
4192 control register. */
4193 assign(t7, binop(Iop_And32,
4194 binop(Iop_Or32,
4195 unop(Iop_1Sto32, mkexpr(t3)),
4196 unop(Iop_1Sto32, mkexpr(t4))),
4197 binop(Iop_Or32,
4198 unop(Iop_1Sto32, mkexpr(t5)),
4199 unop(Iop_1Sto32, mkexpr(t6)))));
4200 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4201 mkexpr(t7),
4202 mkU32(0)),
4203 binop(Iop_Or32,
4204 getDSPControl(),
4205 mkU32(0x00800000)),
4206 getDSPControl()));
4208 /* If the last discarded bit is 1, there would be carry
4209 when rounding, otherwise there wouldn't. We use that
4210 fact and just add the value of the last discarded bit
4211 to the least sifgnificant bit of the shifted value
4212 from acc. */
4213 assign(t8,
4214 IRExpr_ITE(binop(Iop_CmpEQ32,
4215 unop(Iop_8Uto32,
4216 mkexpr(t15)),
4217 mkU32(0)),
4218 mkU64(0x0ULL),
4219 binop(Iop_And64,
4220 binop(Iop_Shr64,
4221 mkexpr(t0),
4222 unop(Iop_32to8,
4223 binop(Iop_Sub32,
4224 unop(Iop_8Uto32,
4225 mkexpr(t15)),
4226 mkU32(1)))),
4227 mkU64(0x1ULL))));
4229 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
4231 /* Repeat previous steps for the rounded value. */
4232 assign(t10, binop(Iop_CmpNE32,
4233 unop(Iop_64HIto32,
4234 mkexpr(t9)),
4235 mkU32(0)));
4236 assign(t11, binop(Iop_CmpNE32,
4237 binop(Iop_And32,
4238 unop(Iop_64to32,
4239 mkexpr(t9)),
4240 mkU32(0x80000000)),
4241 mkU32(0)));
4243 assign(t12, binop(Iop_CmpNE32,
4244 unop(Iop_64HIto32,
4245 mkexpr(t9)),
4246 mkU32(0xffffffff)));
4247 assign(t13, binop(Iop_CmpNE32,
4248 binop(Iop_And32,
4249 unop(Iop_64to32,
4250 mkexpr(t9)),
4251 mkU32(0x80000000)),
4252 mkU32(0x80000000)));
4254 assign(t14, binop(Iop_And32,
4255 binop(Iop_Or32,
4256 unop(Iop_1Sto32, mkexpr(t10)),
4257 unop(Iop_1Sto32, mkexpr(t11))),
4258 binop(Iop_Or32,
4259 unop(Iop_1Sto32, mkexpr(t12)),
4260 unop(Iop_1Sto32, mkexpr(t13)))));
4261 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4262 mkexpr(t14),
4263 mkU32(0)),
4264 binop(Iop_Or32,
4265 getDSPControl(),
4266 mkU32(0x00800000)),
4267 getDSPControl()));
4268 break;
4270 case 0x2: { /* EXTP */
4271 DIP("extp r%u, ac%u, %u", rt, ac, rs);
4272 vassert(!mode64);
4273 t0 = newTemp(Ity_I64);
4274 t1 = newTemp(Ity_I32);
4275 t2 = newTemp(Ity_I1);
4276 t3 = newTemp(Ity_I1);
4277 t4 = newTemp(Ity_I8);
4278 t5 = newTemp(Ity_I64);
4279 t6 = newTemp(Ity_I64);
4280 t7 = newTemp(Ity_I32);
4282 assign(t0, getAcc(ac));
4283 /* Extract pos field of DSPControl register. */
4284 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
4286 /* Check if (pos - size) >= 0 [size <= pos]
4287 if (pos < size)
4288 put 1 to EFI field of DSPControl register
4289 else
4290 extract bits from acc and put 0 to EFI field of
4291 DSPCtrl */
4292 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));
4294 putDSPControl(IRExpr_ITE(mkexpr(t2),
4295 binop(Iop_Or32,
4296 binop(Iop_And32,
4297 getDSPControl(),
4298 mkU32(0xffffbfff)),
4299 mkU32(0x4000)),
4300 binop(Iop_And32,
4301 getDSPControl(),
4302 mkU32(0xffffbfff))));
4304 /* If pos <= 31, shift right the value from the acc
4305 (pos-size) times and take (size+1) bits from the least
4306 significant positions. Otherwise, shift left the value
4307 (63-pos) times, take (size+1) bits from the most
4308 significant positions and shift right (31-size) times.*/
4309 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
4311 assign(t4,
4312 IRExpr_ITE(mkexpr(t3),
4313 unop(Iop_32to8,
4314 binop(Iop_Sub32,
4315 mkexpr(t1), mkU32(rs))),
4316 unop(Iop_32to8,
4317 binop(Iop_Sub32,
4318 mkU32(63), mkexpr(t1)))));
4320 assign(t5, IRExpr_ITE(mkexpr(t3),
4321 binop(Iop_Shr64,
4322 mkexpr(t0), mkexpr(t4)),
4323 binop(Iop_Shl64,
4324 mkexpr(t0), mkexpr(t4))));
4326 /* t6 holds a mask for bit extraction */
4327 assign(t6,
4328 IRExpr_ITE(mkexpr(t3),
4329 unop(Iop_Not64,
4330 binop(Iop_Shl64,
4331 mkU64(0xffffffffffffffffULL),
4332 mkU8(rs+1))),
4333 unop(Iop_Not64,
4334 binop(Iop_Shr64,
4335 mkU64(0xffffffffffffffffULL),
4336 mkU8(rs+1)))));
4338 assign(t7, IRExpr_ITE(mkexpr(t3),
4339 unop(Iop_64to32,
4340 binop(Iop_And64,
4341 mkexpr(t5),
4342 mkexpr(t6))),
4343 binop(Iop_Shr32,
4344 unop(Iop_64HIto32,
4345 binop(Iop_And64,
4346 mkexpr(t5),
4347 mkexpr(t6))),
4348 mkU8(31-rs))));
4350 putIReg(rt, mkexpr(t7));
4351 break;
4353 case 0x3: { /* EXTPV */
4354 DIP("extpv r%u, ac%u, r%u", rt, ac, rs);
4355 vassert(!mode64);
4356 t0 = newTemp(Ity_I64);
4357 t1 = newTemp(Ity_I32);
4358 t2 = newTemp(Ity_I1);
4359 t3 = newTemp(Ity_I1);
4360 t4 = newTemp(Ity_I8);
4361 t5 = newTemp(Ity_I64);
4362 t6 = newTemp(Ity_I64);
4363 t7 = newTemp(Ity_I32);
4364 t8 = newTemp(Ity_I32);
4366 assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
4367 assign(t0, getAcc(ac));
4368 /* Extract pos field of DSPControl register. */
4369 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
4371 /* Check if (pos - size) >= 0 [size <= pos]
4372 if (pos < size)
4373 put 1 to EFI field of DSPControl register
4374 else
4375 extract bits from acc and put 0 to EFI field of
4376 DSPCtrl */
4377 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));
4379 putDSPControl(IRExpr_ITE(mkexpr(t2),
4380 binop(Iop_Or32,
4381 binop(Iop_And32,
4382 getDSPControl(),
4383 mkU32(0xffffbfff)),
4384 mkU32(0x4000)),
4385 binop(Iop_And32,
4386 getDSPControl(),
4387 mkU32(0xffffbfff))));
4389 /* If pos <= 31, shift right the value from the acc
4390 (pos-size) times and take (size+1) bits from the least
4391 significant positions. Otherwise, shift left the value
4392 (63-pos) times, take (size+1) bits from the most
4393 significant positions and shift right (31-size)
4394 times. */
4395 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
4397 assign(t4,
4398 IRExpr_ITE(mkexpr(t3),
4399 unop(Iop_32to8,
4400 binop(Iop_Sub32,
4401 mkexpr(t1), mkexpr(t8))),
4402 unop(Iop_32to8,
4403 binop(Iop_Sub32,
4404 mkU32(63), mkexpr(t1)))));
4406 assign(t5, IRExpr_ITE(mkexpr(t3),
4407 binop(Iop_Shr64,
4408 mkexpr(t0), mkexpr(t4)),
4409 binop(Iop_Shl64,
4410 mkexpr(t0), mkexpr(t4))));
4412 /* t6 holds a mask for bit extraction. */
4413 assign(t6,
4414 IRExpr_ITE(mkexpr(t3),
4415 unop(Iop_Not64,
4416 binop(Iop_Shl64,
4417 mkU64(0xffffffffffffffffULL),
4418 unop(Iop_32to8,
4419 binop(Iop_Add32,
4420 mkexpr(t8),
4421 mkU32(1))))),
4422 unop(Iop_Not64,
4423 binop(Iop_Shr64,
4424 mkU64(0xffffffffffffffffULL),
4425 unop(Iop_32to8,
4426 binop(Iop_Add32,
4427 mkexpr(t8),
4428 mkU32(1)))))));
4430 assign(t7, IRExpr_ITE(mkexpr(t3),
4431 unop(Iop_64to32,
4432 binop(Iop_And64,
4433 mkexpr(t5),
4434 mkexpr(t6))),
4435 binop(Iop_Shr32,
4436 unop(Iop_64HIto32,
4437 binop(Iop_And64,
4438 mkexpr(t5),
4439 mkexpr(t6))),
4440 unop(Iop_32to8,
4441 binop(Iop_Sub32,
4442 mkU32(31),
4443 mkexpr(t8))))));
4445 putIReg(rt, mkexpr(t7));
4446 break;
4448 case 0x4: { /* EXTR_R.W */
4449 DIP("extr_r.w r%u, ac%u, %u", rt, ac, rs);
4450 vassert(!mode64);
4451 t0 = newTemp(Ity_I64);
4452 t1 = newTemp(Ity_I64);
4453 t2 = newTemp(Ity_I32);
4454 t3 = newTemp(Ity_I1);
4455 t4 = newTemp(Ity_I1);
4456 t5 = newTemp(Ity_I1);
4457 t6 = newTemp(Ity_I1);
4458 t7 = newTemp(Ity_I32);
4459 t8 = newTemp(Ity_I64);
4460 t9 = newTemp(Ity_I64);
4461 t10 = newTemp(Ity_I1);
4462 t11 = newTemp(Ity_I1);
4463 t12 = newTemp(Ity_I1);
4464 t13 = newTemp(Ity_I1);
4465 t14 = newTemp(Ity_I32);
4466 t15 = newTemp(Ity_I64);
4467 t16 = newTemp(Ity_I1);
4469 assign(t0, getAcc(ac));
4470 assign(t16, binop(Iop_CmpEQ32,
4471 mkU32(rs),
4472 mkU32(0)));
4473 assign(t1, IRExpr_ITE(mkexpr(t16),
4474 mkexpr(t0),
4475 binop(Iop_Sar64,
4476 mkexpr(t0),
4477 mkU8(rs))));
4478 /* If the last discarded bit is 1, there would be carry
4479 when rounding, otherwise there wouldn't. We use that
4480 fact and just add the value of the last discarded bit
4481 to the least significant bit of the shifted value
4482 from acc. */
4483 assign(t15, binop(Iop_Shr64,
4484 mkexpr(t0),
4485 unop(Iop_32to8,
4486 binop(Iop_Sub32,
4487 binop(Iop_And32,
4488 mkU32(rs),
4489 mkU32(0x1f)),
4490 mkU32(1)))));
4492 assign(t8,
4493 IRExpr_ITE(mkexpr(t16),
4494 mkU64(0x0ULL),
4495 binop(Iop_And64,
4496 mkexpr(t15),
4497 mkU64(0x0000000000000001ULL))));
4498 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
4499 putIReg(rt, unop(Iop_64to32, mkexpr(t9)));
4501 /* Check if bits 63..31 of the result in t1 aren't 0. */
4502 assign(t3, binop(Iop_CmpNE32,
4503 unop(Iop_64HIto32,
4504 mkexpr(t1)),
4505 mkU32(0)));
4506 assign(t4, binop(Iop_CmpNE32,
4507 binop(Iop_And32,
4508 unop(Iop_64to32,
4509 mkexpr(t1)),
4510 mkU32(0x80000000)),
4511 mkU32(0)));
4513 /* Check if bits 63..31 of the result in t1 aren't
4514 0x1ffffffff. */
4515 assign(t5, binop(Iop_CmpNE32,
4516 unop(Iop_64HIto32,
4517 mkexpr(t1)),
4518 mkU32(0xffffffff)));
4519 assign(t6, binop(Iop_CmpNE32,
4520 binop(Iop_And32,
4521 unop(Iop_64to32,
4522 mkexpr(t1)),
4523 mkU32(0x80000000)),
4524 mkU32(0x80000000)));
4525 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
4526 control register. */
4527 assign(t7, binop(Iop_And32,
4528 binop(Iop_Or32,
4529 unop(Iop_1Sto32, mkexpr(t3)),
4530 unop(Iop_1Sto32, mkexpr(t4))),
4531 binop(Iop_Or32,
4532 unop(Iop_1Sto32, mkexpr(t5)),
4533 unop(Iop_1Sto32, mkexpr(t6)))));
4534 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4535 mkexpr(t7),
4536 mkU32(0)),
4537 binop(Iop_Or32,
4538 getDSPControl(),
4539 mkU32(0x00800000)),
4540 getDSPControl()));
4542 /* Repeat previous steps for the rounded value. */
4543 assign(t10, binop(Iop_CmpNE32,
4544 unop(Iop_64HIto32,
4545 mkexpr(t9)),
4546 mkU32(0)));
4547 assign(t11, binop(Iop_CmpNE32,
4548 binop(Iop_And32,
4549 unop(Iop_64to32,
4550 mkexpr(t9)),
4551 mkU32(0x80000000)),
4552 mkU32(0)));
4554 assign(t12, binop(Iop_CmpNE32,
4555 unop(Iop_64HIto32,
4556 mkexpr(t9)),
4557 mkU32(0xffffffff)));
4558 assign(t13, binop(Iop_CmpNE32,
4559 binop(Iop_And32,
4560 unop(Iop_64to32,
4561 mkexpr(t9)),
4562 mkU32(0x80000000)),
4563 mkU32(0x80000000)));
4565 assign(t14, binop(Iop_And32,
4566 binop(Iop_Or32,
4567 unop(Iop_1Sto32, mkexpr(t10)),
4568 unop(Iop_1Sto32, mkexpr(t11))),
4569 binop(Iop_Or32,
4570 unop(Iop_1Sto32, mkexpr(t12)),
4571 unop(Iop_1Sto32, mkexpr(t13)))));
4572 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4573 mkexpr(t14),
4574 mkU32(0)),
4575 binop(Iop_Or32,
4576 getDSPControl(),
4577 mkU32(0x00800000)),
4578 getDSPControl()));
4579 break;
4581 case 0x5: { /* EXTRV_R.W */
4582 DIP("extrv_r.w r%u, ac%u, r%u", rt, ac, rs);
4583 vassert(!mode64);
4584 t0 = newTemp(Ity_I64);
4585 t1 = newTemp(Ity_I64);
4586 t2 = newTemp(Ity_I32);
4587 t3 = newTemp(Ity_I1);
4588 t4 = newTemp(Ity_I1);
4589 t5 = newTemp(Ity_I1);
4590 t6 = newTemp(Ity_I1);
4591 t7 = newTemp(Ity_I32);
4592 t8 = newTemp(Ity_I64);
4593 t9 = newTemp(Ity_I64);
4594 t10 = newTemp(Ity_I1);
4595 t11 = newTemp(Ity_I1);
4596 t12 = newTemp(Ity_I1);
4597 t13 = newTemp(Ity_I1);
4598 t14 = newTemp(Ity_I32);
4599 t15 = newTemp(Ity_I8);
4601 assign(t15, unop(Iop_32to8,
4602 binop(Iop_And32,
4603 getIReg(rs),
4604 mkU32(0x1f))));
4605 assign(t0, getAcc(ac));
4606 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));
4608 /* Check if bits 63..31 of the result in t1 aren't 0. */
4609 assign(t3, binop(Iop_CmpNE32,
4610 unop(Iop_64HIto32,
4611 mkexpr(t1)),
4612 mkU32(0)));
4613 assign(t4, binop(Iop_CmpNE32,
4614 binop(Iop_And32,
4615 unop(Iop_64to32,
4616 mkexpr(t1)),
4617 mkU32(0x80000000)),
4618 mkU32(0)));
4619 /* Check if bits 63..31 of the result in t1 aren't
4620 0x1ffffffff. */
4621 assign(t5, binop(Iop_CmpNE32,
4622 unop(Iop_64HIto32,
4623 mkexpr(t1)),
4624 mkU32(0xffffffff)));
4625 assign(t6, binop(Iop_CmpNE32,
4626 binop(Iop_And32,
4627 unop(Iop_64to32,
4628 mkexpr(t1)),
4629 mkU32(0x80000000)),
4630 mkU32(0x80000000)));
4631 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
4632 control register. */
4633 assign(t7, binop(Iop_And32,
4634 binop(Iop_Or32,
4635 unop(Iop_1Sto32, mkexpr(t3)),
4636 unop(Iop_1Sto32, mkexpr(t4))),
4637 binop(Iop_Or32,
4638 unop(Iop_1Sto32, mkexpr(t5)),
4639 unop(Iop_1Sto32, mkexpr(t6)))));
4640 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4641 mkexpr(t7),
4642 mkU32(0)),
4643 binop(Iop_Or32,
4644 getDSPControl(),
4645 mkU32(0x00800000)),
4646 getDSPControl()));
4648 /* If the last discarded bit is 1, there would be carry
4649 when rounding, otherwise there wouldn't. We use that
4650 fact and just add the value of the last discarded bit
4651 to the least sifgnificant bit of the shifted value
4652 from acc. */
4653 assign(t8,
4654 IRExpr_ITE(binop(Iop_CmpEQ32,
4655 unop(Iop_8Uto32,
4656 mkexpr(t15)),
4657 mkU32(0)),
4658 mkU64(0x0ULL),
4659 binop(Iop_And64,
4660 binop(Iop_Shr64,
4661 mkexpr(t0),
4662 unop(Iop_32to8,
4663 binop(Iop_Sub32,
4664 unop(Iop_8Uto32,
4665 mkexpr(t15)),
4666 mkU32(1)))),
4667 mkU64(0x1ULL))));
4669 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
4670 /* Put rounded value in destination register. */
4671 putIReg(rt, unop(Iop_64to32, mkexpr(t9)));
4673 /* Repeat previous steps for the rounded value. */
4674 assign(t10, binop(Iop_CmpNE32,
4675 unop(Iop_64HIto32,
4676 mkexpr(t9)),
4677 mkU32(0)));
4678 assign(t11, binop(Iop_CmpNE32,
4679 binop(Iop_And32,
4680 unop(Iop_64to32,
4681 mkexpr(t9)),
4682 mkU32(0x80000000)),
4683 mkU32(0)));
4685 assign(t12, binop(Iop_CmpNE32,
4686 unop(Iop_64HIto32,
4687 mkexpr(t9)),
4688 mkU32(0xffffffff)));
4689 assign(t13, binop(Iop_CmpNE32,
4690 binop(Iop_And32,
4691 unop(Iop_64to32,
4692 mkexpr(t9)),
4693 mkU32(0x80000000)),
4694 mkU32(0x80000000)));
4696 assign(t14, binop(Iop_And32,
4697 binop(Iop_Or32,
4698 unop(Iop_1Sto32, mkexpr(t10)),
4699 unop(Iop_1Sto32, mkexpr(t11))),
4700 binop(Iop_Or32,
4701 unop(Iop_1Sto32, mkexpr(t12)),
4702 unop(Iop_1Sto32, mkexpr(t13)))));
4703 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4704 mkexpr(t14),
4705 mkU32(0)),
4706 binop(Iop_Or32,
4707 getDSPControl(),
4708 mkU32(0x00800000)),
4709 getDSPControl()));
4710 break;
4712 case 0x6: { /* EXTR_RS.W */
4713 DIP("extr_rs.w r%u, ac%u, %u", rt, ac, rs);
4714 vassert(!mode64);
4715 t0 = newTemp(Ity_I64);
4716 t1 = newTemp(Ity_I64);
4717 t2 = newTemp(Ity_I32);
4718 t3 = newTemp(Ity_I1);
4719 t4 = newTemp(Ity_I1);
4720 t5 = newTemp(Ity_I1);
4721 t6 = newTemp(Ity_I1);
4722 t7 = newTemp(Ity_I32);
4723 t8 = newTemp(Ity_I64);
4724 t9 = newTemp(Ity_I64);
4725 t10 = newTemp(Ity_I1);
4726 t11 = newTemp(Ity_I1);
4727 t12 = newTemp(Ity_I1);
4728 t13 = newTemp(Ity_I1);
4729 t14 = newTemp(Ity_I32);
4730 t16 = newTemp(Ity_I32);
4732 assign(t0, getAcc(ac));
4733 if (0 == rs) {
4734 assign(t1, mkexpr(t0));
4735 } else {
4736 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
4739 /* Check if bits 63..31 of the result in t1 aren't 0. */
4740 assign(t3, binop(Iop_CmpNE32,
4741 unop(Iop_64HIto32,
4742 mkexpr(t1)),
4743 mkU32(0)));
4744 assign(t4, binop(Iop_CmpNE32,
4745 binop(Iop_And32,
4746 unop(Iop_64to32,
4747 mkexpr(t1)),
4748 mkU32(0x80000000)),
4749 mkU32(0)));
4750 /* Check if bits 63..31 of the result in t1 aren't
4751 0x1ffffffff. */
4752 assign(t5, binop(Iop_CmpNE32,
4753 unop(Iop_64HIto32,
4754 mkexpr(t1)),
4755 mkU32(0xffffffff)));
4756 assign(t6, binop(Iop_CmpNE32,
4757 binop(Iop_And32,
4758 unop(Iop_64to32,
4759 mkexpr(t1)),
4760 mkU32(0x80000000)),
4761 mkU32(0x80000000)));
4762 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
4763 control register. */
4764 assign(t7, binop(Iop_And32,
4765 binop(Iop_Or32,
4766 unop(Iop_1Sto32, mkexpr(t3)),
4767 unop(Iop_1Sto32, mkexpr(t4))),
4768 binop(Iop_Or32,
4769 unop(Iop_1Sto32, mkexpr(t5)),
4770 unop(Iop_1Sto32, mkexpr(t6)))));
4771 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4772 mkexpr(t7),
4773 mkU32(0)),
4774 binop(Iop_Or32,
4775 getDSPControl(),
4776 mkU32(0x00800000)),
4777 getDSPControl()));
4779 /* If the last discarded bit is 1, there would be carry
4780 when rounding, otherwise there wouldn't. We use that
4781 fact and just add the value of the last discarded bit
4782 to the least sifgnificant bit of the shifted value
4783 from acc. */
4784 if (0 == rs) {
4785 assign(t8, mkU64(0x0ULL));
4786 } else {
4787 assign(t8, binop(Iop_And64,
4788 binop(Iop_Shr64,
4789 mkexpr(t0),
4790 mkU8(rs-1)),
4791 mkU64(0x1ULL)));
4794 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
4796 /* Repeat previous steps for the rounded value. */
4797 assign(t10, binop(Iop_CmpNE32,
4798 unop(Iop_64HIto32,
4799 mkexpr(t9)),
4800 mkU32(0)));
4801 assign(t11, binop(Iop_CmpNE32,
4802 binop(Iop_And32,
4803 unop(Iop_64to32,
4804 mkexpr(t9)),
4805 mkU32(0x80000000)),
4806 mkU32(0)));
4808 assign(t12, binop(Iop_CmpNE32,
4809 unop(Iop_64HIto32,
4810 mkexpr(t9)),
4811 mkU32(0xffffffff)));
4812 assign(t13, binop(Iop_CmpNE32,
4813 binop(Iop_And32,
4814 unop(Iop_64to32,
4815 mkexpr(t9)),
4816 mkU32(0x80000000)),
4817 mkU32(0x80000000)));
4819 assign(t14, binop(Iop_And32,
4820 binop(Iop_Or32,
4821 unop(Iop_1Sto32, mkexpr(t10)),
4822 unop(Iop_1Sto32, mkexpr(t11))),
4823 binop(Iop_Or32,
4824 unop(Iop_1Sto32, mkexpr(t12)),
4825 unop(Iop_1Sto32, mkexpr(t13)))));
4826 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4827 mkexpr(t14),
4828 mkU32(0)),
4829 binop(Iop_Or32,
4830 getDSPControl(),
4831 mkU32(0x00800000)),
4832 getDSPControl()));
4834 assign(t16, binop(Iop_And32,
4835 unop(Iop_64HIto32,
4836 mkexpr(t9)),
4837 mkU32(0x80000000)));
4838 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
4839 mkexpr(t14),
4840 mkU32(0)),
4841 IRExpr_ITE(binop(Iop_CmpEQ32,
4842 mkexpr(t16),
4843 mkU32(0)),
4844 mkU32(0x7fffffff),
4845 mkU32(0x80000000)),
4846 unop(Iop_64to32, mkexpr(t9))));
4847 break;
4849 case 0x7: { /* EXTRV_RS.W */
4850 DIP("extrv_rs.w r%u, ac%u, r%u", rt, ac, rs);
4851 vassert(!mode64);
4852 t0 = newTemp(Ity_I64);
4853 t1 = newTemp(Ity_I64);
4854 t2 = newTemp(Ity_I32);
4855 t3 = newTemp(Ity_I1);
4856 t4 = newTemp(Ity_I1);
4857 t5 = newTemp(Ity_I1);
4858 t6 = newTemp(Ity_I1);
4859 t7 = newTemp(Ity_I32);
4860 t8 = newTemp(Ity_I64);
4861 t9 = newTemp(Ity_I64);
4862 t10 = newTemp(Ity_I1);
4863 t11 = newTemp(Ity_I1);
4864 t12 = newTemp(Ity_I1);
4865 t13 = newTemp(Ity_I1);
4866 t14 = newTemp(Ity_I32);
4867 t15 = newTemp(Ity_I32);
4868 t16 = newTemp(Ity_I32);
4869 t17 = newTemp(Ity_I1);
4871 assign(t15, binop(Iop_And32,
4872 getIReg(rs),
4873 mkU32(0x1f)));
4874 assign(t17, binop(Iop_CmpEQ32,
4875 mkexpr(t15),
4876 mkU32(0)));
4877 assign(t0, getAcc(ac));
4878 assign(t1, IRExpr_ITE(mkexpr(t17),
4879 mkexpr(t0),
4880 binop(Iop_Sar64,
4881 mkexpr(t0),
4882 unop(Iop_32to8,
4883 mkexpr(t15)))));
4885 /* Check if bits 63..31 of the result in t1 aren't 0. */
4886 assign(t3, binop(Iop_CmpNE32,
4887 unop(Iop_64HIto32,
4888 mkexpr(t1)),
4889 mkU32(0)));
4890 assign(t4, binop(Iop_CmpNE32,
4891 binop(Iop_And32,
4892 unop(Iop_64to32,
4893 mkexpr(t1)),
4894 mkU32(0x80000000)),
4895 mkU32(0)));
4896 /* Check if bits 63..31 of the result in t1 aren't
4897 0x1ffffffff. */
4898 assign(t5, binop(Iop_CmpNE32,
4899 unop(Iop_64HIto32,
4900 mkexpr(t1)),
4901 mkU32(0xffffffff)));
4902 assign(t6, binop(Iop_CmpNE32,
4903 binop(Iop_And32,
4904 unop(Iop_64to32,
4905 mkexpr(t1)),
4906 mkU32(0x80000000)),
4907 mkU32(0x80000000)));
4908 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
4909 control register. */
4910 assign(t7, binop(Iop_And32,
4911 binop(Iop_Or32,
4912 unop(Iop_1Sto32, mkexpr(t3)),
4913 unop(Iop_1Sto32, mkexpr(t4))),
4914 binop(Iop_Or32,
4915 unop(Iop_1Sto32, mkexpr(t5)),
4916 unop(Iop_1Sto32, mkexpr(t6)))));
4917 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4918 mkexpr(t7),
4919 mkU32(0)),
4920 binop(Iop_Or32,
4921 getDSPControl(),
4922 mkU32(0x00800000)),
4923 getDSPControl()));
4925 /* If the last discarded bit is 1, there would be carry
4926 when rounding, otherwise there wouldn't. We use that
4927 fact and just add the value of the last discarded bit
4928 to the least sifgnificant bit of the shifted value
4929 from acc. */
4930 assign(t8,
4931 IRExpr_ITE(mkexpr(t17),
4932 mkU64(0x0ULL),
4933 binop(Iop_And64,
4934 binop(Iop_Shr64,
4935 mkexpr(t0),
4936 unop(Iop_32to8,
4937 binop(Iop_Sub32,
4938 mkexpr(t15),
4939 mkU32(1)))),
4940 mkU64(0x1ULL))));
4942 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
4944 /* Repeat previous steps for the rounded value. */
4945 assign(t10, binop(Iop_CmpNE32,
4946 unop(Iop_64HIto32,
4947 mkexpr(t9)),
4948 mkU32(0)));
4949 assign(t11, binop(Iop_CmpNE32,
4950 binop(Iop_And32,
4951 unop(Iop_64to32,
4952 mkexpr(t9)),
4953 mkU32(0x80000000)),
4954 mkU32(0)));
4956 assign(t12, binop(Iop_CmpNE32,
4957 unop(Iop_64HIto32,
4958 mkexpr(t9)),
4959 mkU32(0xffffffff)));
4960 assign(t13, binop(Iop_CmpNE32,
4961 binop(Iop_And32,
4962 unop(Iop_64to32,
4963 mkexpr(t9)),
4964 mkU32(0x80000000)),
4965 mkU32(0x80000000)));
4967 assign(t14, binop(Iop_And32,
4968 binop(Iop_Or32,
4969 unop(Iop_1Sto32, mkexpr(t10)),
4970 unop(Iop_1Sto32, mkexpr(t11))),
4971 binop(Iop_Or32,
4972 unop(Iop_1Sto32, mkexpr(t12)),
4973 unop(Iop_1Sto32, mkexpr(t13)))));
4974 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
4975 mkexpr(t14),
4976 mkU32(0)),
4977 binop(Iop_Or32,
4978 getDSPControl(),
4979 mkU32(0x00800000)),
4980 getDSPControl()));
4982 assign(t16, binop(Iop_And32,
4983 unop(Iop_64HIto32,
4984 mkexpr(t9)),
4985 mkU32(0x80000000)));
4986 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
4987 mkexpr(t14),
4988 mkU32(0)),
4989 IRExpr_ITE(binop(Iop_CmpEQ32,
4990 mkexpr(t16),
4991 mkU32(0)),
4992 mkU32(0x7fffffff),
4993 mkU32(0x80000000)),
4994 unop(Iop_64to32, mkexpr(t9))));
4995 break;
4997 case 0xA: { /* EXTPDP */
4998 DIP("extpdp r%u, ac%u, %u", rt, ac, rs);
4999 vassert(!mode64);
5000 t0 = newTemp(Ity_I64);
5001 t1 = newTemp(Ity_I32);
5002 t2 = newTemp(Ity_I1);
5003 t3 = newTemp(Ity_I1);
5004 t4 = newTemp(Ity_I8);
5005 t5 = newTemp(Ity_I64);
5006 t6 = newTemp(Ity_I64);
5007 t7 = newTemp(Ity_I32);
5008 t8 = newTemp(Ity_I32);
5010 assign(t0, getAcc(ac));
5011 /* Extract pos field of DSPControl register. */
5012 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
5014 /* Check if (pos - size) >= 0 [size <= pos]
5015 if (pos < size)
5016 put 1 to EFI field of DSPControl register
5017 else
5018 extract bits from acc and put 0 to EFI field of
5019 DSPCtrl */
5020 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));
5022 assign(t8, binop(Iop_Or32,
5023 binop(Iop_And32,
5024 getDSPControl(),
5025 mkU32(0xffffbfc0)),
5026 binop(Iop_And32,
5027 binop(Iop_Sub32,
5028 binop(Iop_And32,
5029 getDSPControl(),
5030 mkU32(0x3f)),
5031 mkU32(rs+1)),
5032 mkU32(0x3f))));
5033 putDSPControl(IRExpr_ITE(mkexpr(t2),
5034 binop(Iop_Or32,
5035 binop(Iop_And32,
5036 getDSPControl(),
5037 mkU32(0xffffbfff)),
5038 mkU32(0x4000)),
5039 mkexpr(t8)));
5041 /* If pos <= 31, shift right the value from the acc
5042 (pos-size) times and take (size+1) bits from the least
5043 significant positions. Otherwise, shift left the value
5044 (63-pos) times, take (size+1) bits from the most
5045 significant positions and shift right (31-size) times.
5047 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
5049 assign(t4,
5050 IRExpr_ITE(mkexpr(t3),
5051 unop(Iop_32to8,
5052 binop(Iop_Sub32,
5053 mkexpr(t1), mkU32(rs))),
5054 unop(Iop_32to8,
5055 binop(Iop_Sub32,
5056 mkU32(63), mkexpr(t1)))));
5058 assign(t5, IRExpr_ITE(mkexpr(t3),
5059 binop(Iop_Shr64,
5060 mkexpr(t0), mkexpr(t4)),
5061 binop(Iop_Shl64,
5062 mkexpr(t0), mkexpr(t4))));
5064 /* t6 holds a mask for bit extraction. */
5065 assign(t6,
5066 IRExpr_ITE(mkexpr(t3),
5067 unop(Iop_Not64,
5068 binop(Iop_Shl64,
5069 mkU64(0xffffffffffffffffULL),
5070 mkU8(rs+1))),
5071 unop(Iop_Not64,
5072 binop(Iop_Shr64,
5073 mkU64(0xffffffffffffffffULL),
5074 mkU8(rs+1)))));
5076 assign(t7, IRExpr_ITE(mkexpr(t3),
5077 unop(Iop_64to32,
5078 binop(Iop_And64,
5079 mkexpr(t5),
5080 mkexpr(t6))),
5081 binop(Iop_Shr32,
5082 unop(Iop_64HIto32,
5083 binop(Iop_And64,
5084 mkexpr(t5),
5085 mkexpr(t6))),
5086 mkU8(31-rs))));
5088 putIReg(rt, mkexpr(t7));
5089 break;
5091 case 0xB: { /* EXTPDPV */
5092 DIP("extpdpv r%u, ac%u, r%u", rt, ac, rs);
5093 vassert(!mode64);
5094 t0 = newTemp(Ity_I64);
5095 t1 = newTemp(Ity_I32);
5096 t2 = newTemp(Ity_I1);
5097 t3 = newTemp(Ity_I1);
5098 t4 = newTemp(Ity_I8);
5099 t5 = newTemp(Ity_I64);
5100 t6 = newTemp(Ity_I64);
5101 t7 = newTemp(Ity_I32);
5102 t8 = newTemp(Ity_I32);
5103 t9 = newTemp(Ity_I32);
5105 assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
5106 assign(t0, getAcc(ac));
5107 /* Extract pos field of DSPControl register. */
5108 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
5110 /* Check if (pos - size) >= 0 [size <= pos]
5111 if (pos < size)
5112 put 1 to EFI field of DSPControl register
5113 else
5114 extract bits from acc and put 0 to EFI field of
5115 DSPCtrl */
5116 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));
5118 assign(t9, binop(Iop_Or32,
5119 binop(Iop_And32,
5120 getDSPControl(),
5121 mkU32(0xffffbfc0)),
5122 binop(Iop_And32,
5123 binop(Iop_Sub32,
5124 binop(Iop_And32,
5125 getDSPControl(),
5126 mkU32(0x3f)),
5127 binop(Iop_Add32,
5128 mkexpr(t8),
5129 mkU32(0x1))),
5130 mkU32(0x3f))));
5131 putDSPControl(IRExpr_ITE(mkexpr(t2),
5132 binop(Iop_Or32,
5133 binop(Iop_And32,
5134 getDSPControl(),
5135 mkU32(0xffffbfff)),
5136 mkU32(0x4000)),
5137 mkexpr(t9)));
5139 /* If pos <= 31, shift right the value from the acc
5140 (pos-size) times and take (size+1) bits from the least
5141 significant positions. Otherwise, shift left the value
5142 (63-pos) times, take (size+1) bits from the most
5143 significant positions and shift right (31-size) times.
5145 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
5147 assign(t4,
5148 IRExpr_ITE(mkexpr(t3),
5149 unop(Iop_32to8,
5150 binop(Iop_Sub32,
5151 mkexpr(t1), mkexpr(t8))),
5152 unop(Iop_32to8,
5153 binop(Iop_Sub32,
5154 mkU32(63), mkexpr(t1)))));
5156 assign(t5, IRExpr_ITE(mkexpr(t3),
5157 binop(Iop_Shr64,
5158 mkexpr(t0), mkexpr(t4)),
5159 binop(Iop_Shl64,
5160 mkexpr(t0), mkexpr(t4))));
5162 /* t6 holds a mask for bit extraction. */
5163 assign(t6,
5164 IRExpr_ITE(mkexpr(t3),
5165 unop(Iop_Not64,
5166 binop(Iop_Shl64,
5167 mkU64(0xffffffffffffffffULL),
5168 unop(Iop_32to8,
5169 binop(Iop_Add32,
5170 mkexpr(t8),
5171 mkU32(1))))),
5172 unop(Iop_Not64,
5173 binop(Iop_Shr64,
5174 mkU64(0xffffffffffffffffULL),
5175 unop(Iop_32to8,
5176 binop(Iop_Add32,
5177 mkexpr(t8),
5178 mkU32(1)))))));
5180 assign(t7, IRExpr_ITE(mkexpr(t3),
5181 unop(Iop_64to32,
5182 binop(Iop_And64,
5183 mkexpr(t5),
5184 mkexpr(t6))),
5185 binop(Iop_Shr32,
5186 unop(Iop_64HIto32,
5187 binop(Iop_And64,
5188 mkexpr(t5),
5189 mkexpr(t6))),
5190 unop(Iop_32to8,
5191 binop(Iop_Sub32,
5192 mkU32(31),
5193 mkexpr(t8))))));
5195 putIReg(rt, mkexpr(t7));
5196 break;
5198 case 0xE: { /* EXTR_S.H */
5199 DIP("extr_s.h r%u, ac%u, %u", rt, ac, rs);
5200 vassert(!mode64);
5201 t0 = newTemp(Ity_I64);
5202 t1 = newTemp(Ity_I64);
5203 t2 = newTemp(Ity_I32);
5204 t3 = newTemp(Ity_I64);
5205 t4 = newTemp(Ity_I32);
5206 t5 = newTemp(Ity_I32);
5207 t6 = newTemp(Ity_I64);
5208 t7 = newTemp(Ity_I32);
5209 t9 = newTemp(Ity_I32);
5211 assign(t0, getAcc(ac));
5213 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
5215 assign(t2, binop(Iop_Or32,
5216 getDSPControl(), mkU32(0x00800000)));
5218 assign(t9, binop(Iop_And32,
5219 unop(Iop_64to32,
5220 mkexpr(t1)),
5221 mkU32(0x80000000)));
5222 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
5223 mkexpr(t9),
5224 binop(Iop_And32,
5225 unop(Iop_64HIto32,
5226 mkexpr(t0)),
5227 mkU32(0x80000000))),
5228 mkexpr(t2),
5229 getDSPControl()));
5231 /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
5232 1. subtract 0x7fff from t1
5233 2. if the resulting number is positive (sign bit = 0)
5234 and any of the other bits is 1, the value is > 0. */
5235 assign(t3, binop(Iop_Sub64,
5236 mkexpr(t1),
5237 mkU64(0x0000000000007fffULL)));
5238 assign(t4, binop(Iop_And32,
5239 binop(Iop_Or32,
5240 unop(Iop_1Sto32,
5241 binop(Iop_CmpNE32,
5242 mkU32(0),
5243 binop(Iop_And32,
5244 unop(Iop_64HIto32,
5245 mkexpr(t3)),
5246 mkU32(0x7fffffff)))),
5247 unop(Iop_1Sto32,
5248 binop(Iop_CmpNE32,
5249 mkU32(0),
5250 unop(Iop_64to32,
5251 mkexpr(t3))))),
5252 unop(Iop_1Sto32,
5253 binop(Iop_CmpEQ32,
5254 binop(Iop_And32,
5255 unop(Iop_64HIto32,
5256 mkexpr(t3)),
5257 mkU32(0x80000000)),
5258 mkU32(0)))));
5259 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
5260 mkU32(0),
5261 mkexpr(t4)),
5262 binop(Iop_Or32,
5263 getDSPControl(),
5264 mkU32(0x00800000)),
5265 getDSPControl()));
5266 /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
5267 1. subtract t1 from 0xffffffffffff8000
5268 2. if the resulting number is positive (sign bit = 0)
5269 and any of the other bits is 1, the value is > 0 */
5270 assign(t6, binop(Iop_Sub64,
5271 mkU64(0xffffffffffff8000ULL),
5272 mkexpr(t1)));
5273 assign(t7, binop(Iop_And32,
5274 binop(Iop_Or32,
5275 unop(Iop_1Sto32,
5276 binop(Iop_CmpNE32,
5277 mkU32(0),
5278 binop(Iop_And32,
5279 unop(Iop_64HIto32,
5280 mkexpr(t6)),
5281 mkU32(0x7fffffff)))),
5282 unop(Iop_1Sto32,
5283 binop(Iop_CmpNE32,
5284 mkU32(0),
5285 unop(Iop_64to32,
5286 mkexpr(t6))))),
5287 unop(Iop_1Sto32,
5288 binop(Iop_CmpEQ32,
5289 binop(Iop_And32,
5290 unop(Iop_64HIto32,
5291 mkexpr(t6)),
5292 mkU32(0x80000000)),
5293 mkU32(0)))));
5294 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
5295 mkU32(0),
5296 mkexpr(t7)),
5297 binop(Iop_Or32,
5298 getDSPControl(),
5299 mkU32(0x00800000)),
5300 getDSPControl()));
5301 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
5302 mkU32(0),
5303 mkexpr(t4)),
5304 mkU32(0x00007fff),
5305 IRExpr_ITE(binop(Iop_CmpNE32,
5306 mkU32(0),
5307 mkexpr(t7)),
5308 mkU32(0xffff8000),
5309 unop(Iop_64to32,
5310 mkexpr(t1)))));
5311 break;
5313 case 0xF: { /* EXTRV_S.H */
5314 DIP("extrv_s.h r%u, ac%u, %u", rt, ac, rs);
5315 vassert(!mode64);
5316 t0 = newTemp(Ity_I64);
5317 t1 = newTemp(Ity_I64);
5318 t2 = newTemp(Ity_I32);
5319 t3 = newTemp(Ity_I64);
5320 t4 = newTemp(Ity_I32);
5321 t5 = newTemp(Ity_I32);
5322 t6 = newTemp(Ity_I64);
5323 t7 = newTemp(Ity_I32);
5324 t9 = newTemp(Ity_I32);
5326 assign(t0, getAcc(ac));
5328 assign(t1, binop(Iop_Sar64,
5329 mkexpr(t0),
5330 unop(Iop_32to8,
5331 binop(Iop_And32,
5332 getIReg(rs),
5333 mkU32(0x1f)))));
5335 assign(t2, binop(Iop_Or32,
5336 getDSPControl(), mkU32(0x00800000)));
5338 assign(t9, binop(Iop_And32,
5339 unop(Iop_64to32,
5340 mkexpr(t1)),
5341 mkU32(0x80000000)));
5342 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
5343 mkexpr(t9),
5344 binop(Iop_And32,
5345 unop(Iop_64HIto32,
5346 mkexpr(t0)),
5347 mkU32(0x80000000))),
5348 mkexpr(t2),
5349 getDSPControl()));
5351 /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
5352 1. subtract 0x7fff from t1
5353 2. if the resulting number is positive (sign bit = 0)
5354 and any of the other bits is 1, the value is > 0. */
5355 assign(t3, binop(Iop_Sub64,
5356 mkexpr(t1),
5357 mkU64(0x0000000000007fffULL)));
5358 assign(t4, binop(Iop_And32,
5359 binop(Iop_Or32,
5360 unop(Iop_1Sto32,
5361 binop(Iop_CmpNE32,
5362 mkU32(0),
5363 binop(Iop_And32,
5364 unop(Iop_64HIto32,
5365 mkexpr(t3)),
5366 mkU32(0x7fffffff)))),
5367 unop(Iop_1Sto32,
5368 binop(Iop_CmpNE32,
5369 mkU32(0),
5370 unop(Iop_64to32,
5371 mkexpr(t3))))),
5372 unop(Iop_1Sto32,
5373 binop(Iop_CmpEQ32,
5374 binop(Iop_And32,
5375 unop(Iop_64HIto32,
5376 mkexpr(t3)),
5377 mkU32(0x80000000)),
5378 mkU32(0)))));
5379 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
5380 mkU32(0),
5381 mkexpr(t4)),
5382 binop(Iop_Or32,
5383 getDSPControl(),
5384 mkU32(0x00800000)),
5385 getDSPControl()));
5386 /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
5387 1. subtract t1 from 0xffffffffffff8000
5388 2. if the resulting number is positive (sign bit = 0)
5389 and any of the other bits is 1, the value is > 0 */
5390 assign(t6, binop(Iop_Sub64,
5391 mkU64(0xffffffffffff8000ULL),
5392 mkexpr(t1)));
5393 assign(t7, binop(Iop_And32,
5394 binop(Iop_Or32,
5395 unop(Iop_1Sto32,
5396 binop(Iop_CmpNE32,
5397 mkU32(0),
5398 binop(Iop_And32,
5399 unop(Iop_64HIto32,
5400 mkexpr(t6)),
5401 mkU32(0x7fffffff)))),
5402 unop(Iop_1Sto32,
5403 binop(Iop_CmpNE32,
5404 mkU32(0),
5405 unop(Iop_64to32,
5406 mkexpr(t6))))),
5407 unop(Iop_1Sto32,
5408 binop(Iop_CmpEQ32,
5409 binop(Iop_And32,
5410 unop(Iop_64HIto32,
5411 mkexpr(t6)),
5412 mkU32(0x80000000)),
5413 mkU32(0)))));
5414 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
5415 mkU32(0),
5416 mkexpr(t7)),
5417 binop(Iop_Or32,
5418 getDSPControl(),
5419 mkU32(0x00800000)),
5420 getDSPControl()));
5421 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
5422 mkU32(0),
5423 mkexpr(t4)),
5424 mkU32(0x00007fff),
5425 IRExpr_ITE(binop(Iop_CmpNE32,
5426 mkU32(0),
5427 mkexpr(t7)),
5428 mkU32(0xffff8000),
5429 unop(Iop_64to32,
5430 mkexpr(t1)))));
5431 break;
5433 case 0x12: { /* RDDSP*/
5434 DIP("rddsp r%u, mask 0x%x", rd, rddsp_mask);
5435 vassert(!mode64);
5437 putIReg(rd, mkU32(0x0));
5439 if ((rddsp_mask & 0x1) == 0x1) {
5440 /* Read pos field (bits 5-0) of DSPControl register. */
5441 putIReg(rd, binop(Iop_Or32,
5442 getIReg(rd),
5443 binop(Iop_And32,
5444 getDSPControl(),
5445 mkU32(0x0000003F))));
5448 if ((rddsp_mask & 0x2) == 0x2) {
5449 /* Read scount field (bits 12-7) of DSPControl
5450 register. */
5451 putIReg(rd, binop(Iop_Or32,
5452 getIReg(rd),
5453 binop(Iop_And32,
5454 getDSPControl(),
5455 mkU32(0x00001F80))));
5458 if ((rddsp_mask & 0x4) == 0x4) {
5459 /* Read C field (bit 13) of DSPControl register. */
5460 putIReg(rd, binop(Iop_Or32,
5461 getIReg(rd),
5462 binop(Iop_And32,
5463 getDSPControl(),
5464 mkU32(0x00002000))));
5467 if ((rddsp_mask & 0x8) == 0x8) {
5468 /* Read outflag field (bit s 23-16) of DSPControl
5469 register. */
5470 putIReg(rd, binop(Iop_Or32,
5471 getIReg(rd),
5472 binop(Iop_And32,
5473 getDSPControl(),
5474 mkU32(0x00FF0000))));
5477 if ((rddsp_mask & 0x10) == 0x10) {
5478 /* Read ccond field (bits 31-24) of DSPControl
5479 register. */
5480 putIReg(rd, binop(Iop_Or32,
5481 getIReg(rd),
5482 binop(Iop_And32,
5483 getDSPControl(),
5484 mkU32(0xFF000000))));
5487 if ((rddsp_mask & 0x20) == 0x20) {
5488 /* Read EFI field (bit 14) of DSPControl register. */
5489 putIReg(rd, binop(Iop_Or32,
5490 getIReg(rd),
5491 binop(Iop_And32,
5492 getDSPControl(),
5493 mkU32(0x00004000))));
5496 if ((rddsp_mask & 0x3f) == 0x3f) {
5497 /* Read all fields of DSPControl register. */
5498 putIReg(rd, getDSPControl());
5500 break;
5502 case 0x13: { /* WRDSP */
5503 DIP("wrdsp r%u, mask 0x%x", rs, wrdsp_mask);
5504 vassert(!mode64);
5506 if ((wrdsp_mask & 0x3f) == 0x3f) {
5507 /* If mips64 put all fields of rs, except bit 15 and bit
5508 6, to DSPControl register, otherwise put all except
5509 bits 15, 6 and bits 31..28. */
5510 putDSPControl(mode64 ?
5511 binop(Iop_And32,
5512 getIReg(rs),
5513 mkU32(0xffff7fbf)) :
5514 binop(Iop_And32,
5515 getIReg(rs),
5516 mkU32(0x0fff7fbf)));
5517 } else {
5518 if ((wrdsp_mask & 0x1) == 0x1) {
5519 /* Put bits 5-0 of rs to DSPControl register pos
5520 field. */
5521 putDSPControl(binop(Iop_Or32,
5522 binop(Iop_And32,
5523 getDSPControl(),
5524 mkU32(0xFFFF7F40)),
5525 binop(Iop_And32,
5526 getIReg(rs),
5527 mkU32(0x0000003F))));
5530 if ((wrdsp_mask & 0x2) == 0x2) {
5531 /* Put bits 12-7 of rs to DSPControl scount field. */
5532 putDSPControl(binop(Iop_Or32,
5533 binop(Iop_And32,
5534 getDSPControl(),
5535 mkU32(0xFFFFE03F)),
5536 binop(Iop_And32,
5537 getIReg(rs),
5538 mkU32(0x00001F80))));
5541 if ((wrdsp_mask & 0x4) == 0x4) {
5542 /* Put bit 13 of rs to DSPControl register C
5543 field. */
5544 putDSPControl(binop(Iop_Or32,
5545 binop(Iop_And32,
5546 getDSPControl(),
5547 mkU32(0xFFFF5FBF)),
5548 binop(Iop_And32,
5549 getIReg(rs),
5550 mkU32(0x00002000))));
5553 if ((wrdsp_mask & 0x8) == 0x8) {
5554 /* Put bits 23-16 of rs to DSPControl reg outflag
5555 field. */
5556 putDSPControl(binop(Iop_Or32,
5557 binop(Iop_And32,
5558 getDSPControl(),
5559 mkU32(0xFF007FBF)),
5560 binop(Iop_And32,
5561 getIReg(rs),
5562 mkU32(0x00FF0000))));
5565 if ((wrdsp_mask & 0x10) == 0x10) {
5566 /* Put bits 31-24 of rs to DSPControl reg ccond
5567 field. */
5568 putDSPControl(binop(Iop_Or32,
5569 binop(Iop_And32,
5570 getDSPControl(),
5571 mkU32(0x00FF7FBF)),
5572 binop(Iop_And32,
5573 getIReg(rs),
5574 mode64 ? mkU32(0xFF000000)
5575 : mkU32(0x0F000000))
5580 if ((wrdsp_mask & 0x20) == 0x20) {
5581 /* Put bit 14 of rs to DSPControl register EFI
5582 field. */
5583 putDSPControl(binop(Iop_Or32,
5584 binop(Iop_And32,
5585 getDSPControl(),
5586 mkU32(0xFFFF3FBF)),
5587 binop(Iop_And32,
5588 getIReg(rs),
5589 mkU32(0x00004000))));
5592 break;
5594 case 0x1A: { /* SHILO */
5595 DIP("shilo ac%u, %u", ac, shift);
5596 vassert(!mode64);
5597 t0 = newTemp(Ity_I64);
5598 t1 = newTemp(Ity_I64);
5600 assign(t0, getAcc(ac));
5602 putAcc(ac, mkexpr(t0));
5604 if (0x20 == (shift & 0x3f)) {
5605 putAcc(ac, binop(Iop_32HLto64,
5606 unop(Iop_64to32, mkexpr(t0)),
5607 mkU32(0x0)));
5608 } else if (0x20 == (shift & 0x20)) {
5609 assign(t1, binop(Iop_Shl64,
5610 mkexpr(t0),
5611 unop(Iop_32to8,
5612 binop(Iop_Add32,
5613 unop(Iop_Not32,
5614 mkU32(shift)),
5615 mkU32(0x1)))));
5617 putAcc(ac, mkexpr(t1));
5618 } else {
5619 assign(t1, binop(Iop_Shr64, mkexpr(t0), mkU8(shift)));
5621 putAcc(ac, mkexpr(t1));
5623 break;
5625 case 0x1B: { /* SHILOV */
5626 DIP("shilov ac%u, r%u", ac, rs);
5627 vassert(!mode64);
5628 t0 = newTemp(Ity_I64);
5629 t1 = newTemp(Ity_I32);
5630 t2 = newTemp(Ity_I1);
5631 t3 = newTemp(Ity_I64);
5632 t4 = newTemp(Ity_I64);
5634 assign(t0, getAcc(ac));
5635 assign(t1, binop(Iop_And32, getIReg(rs), mkU32(0x3f)));
5636 assign(t2, binop(Iop_CmpEQ32, mkexpr(t1), mkU32(0x20)));
5637 assign(t3, binop(Iop_Shl64,
5638 mkexpr(t0),
5639 unop(Iop_32to8,
5640 binop(Iop_Add32,
5641 unop(Iop_Not32,
5642 mkexpr(t1)),
5643 mkU32(0x1)))));
5644 assign(t4, binop(Iop_Shr64,
5645 mkexpr(t0),
5646 unop(Iop_32to8,
5647 mkexpr(t1))));
5649 putAcc(ac,
5650 IRExpr_ITE(mkexpr(t2),
5651 binop(Iop_32HLto64,
5652 unop(Iop_64to32, mkexpr(t0)),
5653 mkU32(0x0)),
5654 IRExpr_ITE(binop(Iop_CmpEQ32,
5655 binop(Iop_And32,
5656 mkexpr(t1),
5657 mkU32(0x20)),
5658 mkU32(0x20)),
5659 mkexpr(t3),
5660 mkexpr(t4))));
5661 break;
5663 case 0x1F: { /* MTHLIP */
5664 DIP("mthlip r%u, ac%u", rs, ac);
5665 vassert(!mode64);
5666 t0 = newTemp(Ity_I64);
5667 t1 = newTemp(Ity_I32);
5668 t2 = newTemp(Ity_I32);
5669 t3 = newTemp(Ity_I1);
5671 assign(t0, getAcc(ac));
5672 putAcc(ac, binop(Iop_32HLto64,
5673 unop(Iop_64to32, mkexpr(t0)),
5674 getIReg(rs)));
5675 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
5676 putDSPControl(IRExpr_ITE(binop(Iop_CmpLE32U,
5677 mkU32(32),
5678 mkexpr(t1)),
5679 binop(Iop_Or32,
5680 binop(Iop_Sub32,
5681 mkexpr(t1),
5682 mkU32(32)),
5683 binop(Iop_And32,
5684 getDSPControl(),
5685 mkU32(0xffffffc0))),
5686 binop(Iop_Or32,
5687 binop(Iop_Add32,
5688 mkexpr(t1),
5689 mkU32(32)),
5690 binop(Iop_And32,
5691 getDSPControl(),
5692 mkU32(0xffffffc0)))));
5693 break;
5695 default:
5696 return -1;
5698 break; /* end of EXTR.W */
5700 case 0xA: { /* LX */
5701 switch(sa) {
5702 case 0x0: { /* LWX */
5703 DIP("lwx r%u, r%u(r%u)", rd, rt, rs);
5704 vassert(!mode64);
5705 t0 = newTemp(Ity_I32);
5707 assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
5709 putIReg(rd, load(Ity_I32, mkexpr(t0)));
5710 break;
5712 case 0x4: { /* LHX */
5713 DIP("lhx r%u, r%u(r%u)", rd, rt, rs);
5714 vassert(!mode64);
5715 t0 = newTemp(Ity_I32);
5717 assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
5719 putIReg(rd, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t0))));
5720 break;
5722 case 0x6: { /* LBUX */
5723 DIP("lbux r%u, r%u(r%u)", rd, rt, rs);
5724 vassert(!mode64);
5725 t0 = newTemp(Ity_I32);
5727 assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
5729 putIReg(rd, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t0))));
5730 break;
5732 default:
5733 return -1;
5735 break; /* end of LX */
5737 case 0xC: { /* INSV */
5738 switch(sa) {
5739 case 0x0: { /* INSV */
5740 DIP("insv r%u, r%u", rt, rs);
5741 vassert(!mode64);
5743 t0 = newTemp(Ity_I32);
5744 t1 = newTemp(Ity_I32);
5745 t2 = newTemp(Ity_I8);
5746 t3 = newTemp(Ity_I8);
5747 t4 = newTemp(Ity_I32);
5748 t5 = newTemp(Ity_I1);
5749 t6 = newTemp(Ity_I32);
5750 t7 = newTemp(Ity_I32);
5751 t8 = newTemp(Ity_I32);
5752 t9 = newTemp(Ity_I32);
5754 /* t0 <- pos field of DSPControl register. */
5755 assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
5756 /* t1 <- scount field of DSPControl register. */
5757 assign(t1, binop(Iop_Shr32,
5758 binop(Iop_And32,
5759 getDSPControl(),
5760 mkU32(0x1f80)),
5761 mkU8(7)));
5763 assign(t2, unop(Iop_32to8,
5764 binop(Iop_Add32,
5765 mkexpr(t1),
5766 mkexpr(t0))));
5768 /* 32-(pos+size) most significant bits of rt. */
5769 assign(t6, binop(Iop_Shl32,
5770 binop(Iop_Shr32,
5771 getIReg(rt),
5772 mkexpr(t2)),
5773 mkexpr(t2)));
5775 assign(t3, unop(Iop_32to8,
5776 binop(Iop_Sub32,
5777 mkU32(32),
5778 mkexpr(t0))));
5779 /* Pos least significant bits of rt. */
5780 assign(t7, binop(Iop_Shr32,
5781 binop(Iop_Shl32,
5782 getIReg(rt),
5783 mkexpr(t3)),
5784 mkexpr(t3)));
5786 /* Size least significant bits of rs,
5787 shifted to appropriate position. */
5788 assign(t8, binop(Iop_Shl32,
5789 binop(Iop_And32,
5790 getIReg(rs),
5791 unop(Iop_Not32,
5792 binop(Iop_Shl32,
5793 mkU32(0xffffffff),
5794 unop(Iop_32to8,
5795 mkexpr(t1))))),
5796 unop(Iop_32to8,
5797 mkexpr(t0))));
5799 putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
5800 mkexpr(t0),
5801 mkU32(0)),
5802 IRExpr_ITE(binop(Iop_CmpEQ32,
5803 mkexpr(t1),
5804 mkU32(32)),
5805 getIReg(rs),
5806 binop(Iop_Or32,
5807 mkexpr(t6),
5808 mkexpr(t8))),
5809 IRExpr_ITE(binop(Iop_CmpEQ32,
5810 unop(Iop_8Uto32,
5811 mkexpr(t2)),
5812 mkU32(32)),
5813 binop(Iop_Or32,
5814 mkexpr(t7),
5815 mkexpr(t8)),
5816 binop(Iop_Or32,
5817 binop(Iop_Or32,
5818 mkexpr(t6),
5819 mkexpr(t7)),
5820 mkexpr(t8)))));
5821 break;
5823 default:
5824 return -1;
5826 break; /* enf of INSV */
5828 case 0x10: { /* ADDU.QB */
5829 switch(sa) {
5830 case 0x00: { /* ADDU.QB */
5831 DIP("addu.qb r%u, r%u, r%u", rd, rs, rt);
5832 vassert(!mode64);
5833 t0 = newTemp(Ity_I32);
5834 t1 = newTemp(Ity_I1);
5835 t2 = newTemp(Ity_I32);
5836 t3 = newTemp(Ity_I1);
5837 t4 = newTemp(Ity_I32);
5838 t5 = newTemp(Ity_I1);
5839 t6 = newTemp(Ity_I32);
5840 t7 = newTemp(Ity_I1);
5841 t8 = newTemp(Ity_I32);
5843 /* Add rightmost bytes of rs and rt. */
5844 assign(t0,
5845 binop(Iop_Add32,
5846 unop(Iop_8Uto32,
5847 unop(Iop_16to8,
5848 unop(Iop_32to16, getIReg(rs)))),
5849 unop(Iop_8Uto32,
5850 unop(Iop_16to8,
5851 unop(Iop_32to16, getIReg(rt))))));
5852 /* t1 will be 1 if there is overflow, 0 otherwise. */
5853 assign(t1, binop(Iop_CmpEQ32,
5854 binop(Iop_And32,
5855 mkexpr(t0),
5856 mkU32(0x00000100)),
5857 mkU32(0x00000100)));
5859 /* Add bits 15-8 of rs and rt. */
5860 assign(t2,
5861 binop(Iop_Add32,
5862 unop(Iop_8Uto32,
5863 unop(Iop_16HIto8,
5864 unop(Iop_32to16, getIReg(rs)))),
5865 unop(Iop_8Uto32,
5866 unop(Iop_16HIto8,
5867 unop(Iop_32to16, getIReg(rt))))));
5868 /* t3 will be 1 if there is overflow, 0 otherwise. */
5869 assign(t3, binop(Iop_CmpEQ32,
5870 binop(Iop_And32,
5871 mkexpr(t2),
5872 mkU32(0x00000100)),
5873 mkU32(0x00000100)));
5875 /* Add bits 15-8 of rs and rt. */
5876 assign(t4,
5877 binop(Iop_Add32,
5878 unop(Iop_8Uto32,
5879 unop(Iop_16to8,
5880 unop(Iop_32HIto16, getIReg(rs)))),
5881 unop(Iop_8Uto32,
5882 unop(Iop_16to8,
5883 unop(Iop_32HIto16, getIReg(rt))))));
5884 /* t5 will be 1 if there is overflow, 0 otherwise. */
5885 assign(t5, binop(Iop_CmpEQ32,
5886 binop(Iop_And32,
5887 mkexpr(t4),
5888 mkU32(0x00000100)),
5889 mkU32(0x00000100)));
5891 /* Add bits 15-8 of rs and rt. */
5892 assign(t6,
5893 binop(Iop_Add32,
5894 unop(Iop_8Uto32,
5895 unop(Iop_16HIto8,
5896 unop(Iop_32HIto16, getIReg(rs)))),
5897 unop(Iop_8Uto32,
5898 unop(Iop_16HIto8,
5899 unop(Iop_32HIto16, getIReg(rt))))));
5900 /* t7 will be 1 if there is overflow, 0 otherwise. */
5901 assign(t7, binop(Iop_CmpEQ32,
5902 binop(Iop_And32,
5903 mkexpr(t6),
5904 mkU32(0x00000100)),
5905 mkU32(0x00000100)));
5907 assign(t8,
5908 binop(Iop_Or32,
5909 binop(Iop_Or32,
5910 binop(Iop_Or32,
5911 unop(Iop_1Sto32, mkexpr(t7)),
5912 unop(Iop_1Sto32, mkexpr(t5))),
5913 unop(Iop_1Sto32, mkexpr(t3))),
5914 unop(Iop_1Sto32, mkexpr(t1))));
5916 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
5917 mkexpr(t8),
5918 mkU32(0x0)),
5919 getDSPControl(),
5920 binop(Iop_Or32,
5921 getDSPControl(),
5922 mkU32(0x00100000))));
5924 putIReg(rd, binop(Iop_16HLto32,
5925 binop(Iop_8HLto16,
5926 unop(Iop_32to8, mkexpr(t6)),
5927 unop(Iop_32to8, mkexpr(t4))),
5928 binop(Iop_8HLto16,
5929 unop(Iop_32to8, mkexpr(t2)),
5930 unop(Iop_32to8, mkexpr(t0)))));
5931 break;
5933 case 0x1: { /* SUBU.QB */
5934 DIP("subu.qb r%u, r%u, r%u", rd, rs, rt);
5935 vassert(!mode64);
5936 t0 = newTemp(Ity_I32);
5937 t1 = newTemp(Ity_I1);
5938 t2 = newTemp(Ity_I32);
5939 t3 = newTemp(Ity_I1);
5940 t4 = newTemp(Ity_I32);
5941 t5 = newTemp(Ity_I1);
5942 t6 = newTemp(Ity_I32);
5943 t7 = newTemp(Ity_I1);
5944 t8 = newTemp(Ity_I32);
5946 /* Subtract rightmost bytes of rs and rt. */
5947 assign(t0,
5948 binop(Iop_Sub32,
5949 unop(Iop_8Uto32,
5950 unop(Iop_16to8,
5951 unop(Iop_32to16, getIReg(rs)))),
5952 unop(Iop_8Uto32,
5953 unop(Iop_16to8,
5954 unop(Iop_32to16, getIReg(rt))))));
5955 /* t1 will be 1 if there is overflow, 0 otherwise. */
5956 assign(t1, binop(Iop_CmpEQ32,
5957 binop(Iop_And32,
5958 mkexpr(t0),
5959 mkU32(0x00000100)),
5960 mkU32(0x00000100)));
5962 /* Subtract bits 15-8 of rs and rt. */
5963 assign(t2,
5964 binop(Iop_Sub32,
5965 unop(Iop_8Uto32,
5966 unop(Iop_16HIto8,
5967 unop(Iop_32to16, getIReg(rs)))),
5968 unop(Iop_8Uto32,
5969 unop(Iop_16HIto8,
5970 unop(Iop_32to16, getIReg(rt))))));
5971 /* t3 will be 1 if there is overflow, 0 otherwise. */
5972 assign(t3, binop(Iop_CmpEQ32,
5973 binop(Iop_And32,
5974 mkexpr(t2),
5975 mkU32(0x00000100)),
5976 mkU32(0x00000100)));
5978 /* Subtract bits 15-8 of rs and rt. */
5979 assign(t4,
5980 binop(Iop_Sub32,
5981 unop(Iop_8Uto32,
5982 unop(Iop_16to8,
5983 unop(Iop_32HIto16, getIReg(rs)))),
5984 unop(Iop_8Uto32,
5985 unop(Iop_16to8,
5986 unop(Iop_32HIto16, getIReg(rt))))));
5987 /* t5 will be 1 if there is overflow, 0 otherwise. */
5988 assign(t5, binop(Iop_CmpEQ32,
5989 binop(Iop_And32,
5990 mkexpr(t4),
5991 mkU32(0x00000100)),
5992 mkU32(0x00000100)));
5994 /* Subtract bits 15-8 of rs and rt. */
5995 assign(t6,
5996 binop(Iop_Sub32,
5997 unop(Iop_8Uto32,
5998 unop(Iop_16HIto8,
5999 unop(Iop_32HIto16, getIReg(rs)))),
6000 unop(Iop_8Uto32,
6001 unop(Iop_16HIto8,
6002 unop(Iop_32HIto16, getIReg(rt))))));
6003 /* t7 will be 1 if there is overflow, 0 otherwise. */
6004 assign(t7, binop(Iop_CmpEQ32,
6005 binop(Iop_And32,
6006 mkexpr(t6),
6007 mkU32(0x00000100)),
6008 mkU32(0x00000100)));
6010 assign(t8, binop(Iop_Or32,
6011 binop(Iop_Or32,
6012 binop(Iop_Or32,
6013 unop(Iop_1Sto32, mkexpr(t7)),
6014 unop(Iop_1Sto32, mkexpr(t5))),
6015 unop(Iop_1Sto32, mkexpr(t3))),
6016 unop(Iop_1Sto32, mkexpr(t1))));
6018 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
6019 mkexpr(t8),
6020 mkU32(0x0)),
6021 getDSPControl(),
6022 binop(Iop_Or32,
6023 getDSPControl(),
6024 mkU32(0x00100000))));
6026 putIReg(rd, binop(Iop_16HLto32,
6027 binop(Iop_8HLto16,
6028 unop(Iop_32to8, mkexpr(t6)),
6029 unop(Iop_32to8, mkexpr(t4))),
6030 binop(Iop_8HLto16,
6031 unop(Iop_32to8, mkexpr(t2)),
6032 unop(Iop_32to8, mkexpr(t0)))));
6033 break;
6035 case 0x04: { /* ADDU_S.QB */
6036 DIP("addu_s.qb r%u, r%u, r%u", rd, rs, rt);
6037 vassert(!mode64);
6038 t0 = newTemp(Ity_I32);
6039 t1 = newTemp(Ity_I1);
6040 t2 = newTemp(Ity_I8);
6041 t3 = newTemp(Ity_I32);
6042 t4 = newTemp(Ity_I1);
6043 t5 = newTemp(Ity_I8);
6044 t6 = newTemp(Ity_I32);
6045 t7 = newTemp(Ity_I1);
6046 t8 = newTemp(Ity_I8);
6047 t9 = newTemp(Ity_I32);
6048 t10 = newTemp(Ity_I1);
6049 t11 = newTemp(Ity_I8);
6050 t12 = newTemp(Ity_I32);
6052 /* Add rightmost bytes of rs and rt. */
6053 assign(t0,
6054 binop(Iop_Add32,
6055 unop(Iop_8Uto32,
6056 unop(Iop_16to8,
6057 unop(Iop_32to16, getIReg(rs)))),
6058 unop(Iop_8Uto32,
6059 unop(Iop_16to8,
6060 unop(Iop_32to16, getIReg(rt))))));
6061 /* t1 will be 1 if there is overflow, 0 otherwise. */
6062 assign(t1, binop(Iop_CmpEQ32,
6063 binop(Iop_And32,
6064 mkexpr(t0),
6065 mkU32(0x00000100)),
6066 mkU32(0x00000100)));
6067 /* Saturate if necessary. */
6068 assign(t2, IRExpr_ITE(mkexpr(t1),
6069 mkU8(0xff),
6070 unop(Iop_32to8, mkexpr(t0))));
6072 /* Add bits 15-8 of rs and rt. */
6073 assign(t3,
6074 binop(Iop_Add32,
6075 unop(Iop_8Uto32,
6076 unop(Iop_16HIto8,
6077 unop(Iop_32to16, getIReg(rs)))),
6078 unop(Iop_8Uto32,
6079 unop(Iop_16HIto8,
6080 unop(Iop_32to16, getIReg(rt))))));
6081 /* t4 will be 1 if there is overflow, 0 otherwise. */
6082 assign(t4, binop(Iop_CmpEQ32,
6083 binop(Iop_And32,
6084 mkexpr(t3),
6085 mkU32(0x00000100)),
6086 mkU32(0x00000100)));
6087 /* Saturate if necessary. */
6088 assign(t5, IRExpr_ITE(mkexpr(t4),
6089 mkU8(0xff),
6090 unop(Iop_32to8, mkexpr(t3))));
6092 /* Add bits 15-8 of rs and rt. */
6093 assign(t6,
6094 binop(Iop_Add32,
6095 unop(Iop_8Uto32,
6096 unop(Iop_16to8,
6097 unop(Iop_32HIto16, getIReg(rs)))),
6098 unop(Iop_8Uto32,
6099 unop(Iop_16to8,
6100 unop(Iop_32HIto16, getIReg(rt))))));
6101 /* t7 will be 1 if there is overflow, 0 otherwise. */
6102 assign(t7, binop(Iop_CmpEQ32,
6103 binop(Iop_And32,
6104 mkexpr(t6),
6105 mkU32(0x00000100)),
6106 mkU32(0x00000100)));
6107 /* Saturate if necessary. */
6108 assign(t8, IRExpr_ITE(mkexpr(t7),
6109 mkU8(0xff),
6110 unop(Iop_32to8, mkexpr(t6))));
6112 /* Add bits 15-8 of rs and rt. */
6113 assign(t9,
6114 binop(Iop_Add32,
6115 unop(Iop_8Uto32,
6116 unop(Iop_16HIto8,
6117 unop(Iop_32HIto16, getIReg(rs)))),
6118 unop(Iop_8Uto32,
6119 unop(Iop_16HIto8,
6120 unop(Iop_32HIto16, getIReg(rt))))));
6121 /* t10 will be 1 if there is overflow, 0 otherwise. */
6122 assign(t10, binop(Iop_CmpEQ32,
6123 binop(Iop_And32,
6124 mkexpr(t9),
6125 mkU32(0x00000100)),
6126 mkU32(0x00000100)));
6127 /* Saturate if necessary. */
6128 assign(t11, IRExpr_ITE(mkexpr(t10),
6129 mkU8(0xff),
6130 unop(Iop_32to8, mkexpr(t9))));
6132 assign(t12,
6133 binop(Iop_Or32,
6134 binop(Iop_Or32,
6135 binop(Iop_Or32,
6136 unop(Iop_1Sto32, mkexpr(t10)),
6137 unop(Iop_1Sto32, mkexpr(t7))),
6138 unop(Iop_1Sto32, mkexpr(t4))),
6139 unop(Iop_1Sto32, mkexpr(t1))));
6141 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
6142 mkexpr(t12),
6143 mkU32(0x0)),
6144 getDSPControl(),
6145 binop(Iop_Or32,
6146 getDSPControl(),
6147 mkU32(0x00100000))));
6149 putIReg(rd,
6150 binop(Iop_16HLto32,
6151 binop(Iop_8HLto16, mkexpr(t11), mkexpr(t8)),
6152 binop(Iop_8HLto16, mkexpr(t5), mkexpr(t2))));
6153 break;
6155 case 0x05: { /* SUBU_S.QB */
6156 DIP("subu_s.qb r%u, r%u, r%u", rd, rs, rt);
6157 vassert(!mode64);
6158 t1 = newTemp(Ity_I32);
6159 t2 = newTemp(Ity_I1);
6160 t3 = newTemp(Ity_I1);
6161 t4 = newTemp(Ity_I1);
6162 t5 = newTemp(Ity_I1);
6163 t6 = newTemp(Ity_I32);
6164 t7 = newTemp(Ity_I32);
6165 t8 = newTemp(Ity_I32);
6166 t9 = newTemp(Ity_I32);
6168 /* Use C function to easily calculate the result
6169 and write it in the register more conveniently
6170 Underflow is checked using step by step subtraction. */
6171 assign(t1, binop(Iop_QSub8Ux4, getIReg(rs), getIReg(rt)));
6173 /* Subtract each byte of rs and rt. */
6174 assign(t6,
6175 binop(Iop_Sub32,
6176 unop(Iop_8Uto32,
6177 unop(Iop_16to8,
6178 unop(Iop_32to16, getIReg(rs)))),
6179 unop(Iop_8Uto32,
6180 unop(Iop_16to8,
6181 unop(Iop_32to16, getIReg(rt))))));
6182 assign(t7,
6183 binop(Iop_Sub32,
6184 unop(Iop_8Uto32,
6185 unop(Iop_16HIto8,
6186 unop(Iop_32to16, getIReg(rs)))),
6187 unop(Iop_8Uto32,
6188 unop(Iop_16HIto8,
6189 unop(Iop_32to16, getIReg(rt))))));
6190 assign(t8,
6191 binop(Iop_Sub32,
6192 unop(Iop_8Uto32,
6193 unop(Iop_16to8,
6194 unop(Iop_32HIto16, getIReg(rs)))),
6195 unop(Iop_8Uto32,
6196 unop(Iop_16to8,
6197 unop(Iop_32HIto16, getIReg(rt))))));
6198 assign(t9,
6199 binop(Iop_Sub32,
6200 unop(Iop_8Uto32,
6201 unop(Iop_16HIto8,
6202 unop(Iop_32HIto16, getIReg(rs)))),
6203 unop(Iop_8Uto32,
6204 unop(Iop_16HIto8,
6205 unop(Iop_32HIto16, getIReg(rt))))));
6207 /* Put 1 to bit 20 in DSPControl if there is underflow
6208 in either byte. */
6209 assign(t2, binop(Iop_CmpEQ32,
6210 binop(Iop_And32,
6211 mkexpr(t6),
6212 mkU32(0x00000100)),
6213 mkU32(0x00000100)));
6214 putDSPControl(IRExpr_ITE(mkexpr(t2),
6215 binop(Iop_Or32,
6216 getDSPControl(),
6217 mkU32(0x00100000)),
6218 getDSPControl()));
6219 assign(t3, binop(Iop_CmpEQ32,
6220 binop(Iop_And32,
6221 mkexpr(t7),
6222 mkU32(0x00000100)),
6223 mkU32(0x00000100)));
6224 putDSPControl(IRExpr_ITE(mkexpr(t3),
6225 binop(Iop_Or32,
6226 getDSPControl(),
6227 mkU32(0x00100000)),
6228 getDSPControl()));
6229 assign(t4, binop(Iop_CmpEQ32,
6230 binop(Iop_And32,
6231 mkexpr(t8),
6232 mkU32(0x00000100)),
6233 mkU32(0x00000100)));
6234 putDSPControl(IRExpr_ITE(mkexpr(t4),
6235 binop(Iop_Or32,
6236 getDSPControl(),
6237 mkU32(0x00100000)),
6238 getDSPControl()));
6239 assign(t5, binop(Iop_CmpEQ32,
6240 binop(Iop_And32,
6241 mkexpr(t9),
6242 mkU32(0x00000100)),
6243 mkU32(0x00000100)));
6244 putDSPControl(IRExpr_ITE(mkexpr(t5),
6245 binop(Iop_Or32,
6246 getDSPControl(),
6247 mkU32(0x00100000)),
6248 getDSPControl()));
6249 putIReg(rd, mkexpr(t1));
6250 break;
6252 case 0x6: { /* MULEU_S.PH.QBL */
6253 DIP("muleu_s.ph.qbl r%u, r%u, r%u", rd, rs, rt);
6254 vassert(!mode64);
6255 t0 = newTemp(Ity_I32);
6256 t1 = newTemp(Ity_I32);
6257 t2 = newTemp(Ity_I1);
6258 t3 = newTemp(Ity_I1);
6260 assign(t0,
6261 unop(Iop_64to32,
6262 binop(Iop_MullU32,
6263 unop(Iop_8Uto32,
6264 unop(Iop_16HIto8,
6265 unop(Iop_32HIto16,
6266 getIReg(rs)))),
6267 unop(Iop_16Uto32,
6268 unop(Iop_32HIto16, getIReg(rt))))));
6269 assign(t1,
6270 unop(Iop_64to32,
6271 binop(Iop_MullU32,
6272 unop(Iop_8Uto32,
6273 unop(Iop_16to8,
6274 unop(Iop_32HIto16,
6275 getIReg(rs)))),
6276 unop(Iop_16Uto32,
6277 unop(Iop_32to16, getIReg(rt))))));
6279 assign(t2, binop(Iop_CmpNE32,
6280 mkU32(0x0),
6281 binop(Iop_And32,
6282 mkexpr(t0),
6283 mkU32(0x03ff0000))));
6284 assign(t3, binop(Iop_CmpNE32,
6285 mkU32(0x0),
6286 binop(Iop_And32,
6287 mkexpr(t1),
6288 mkU32(0x03ff0000))));
6289 putDSPControl(IRExpr_ITE(mkexpr(t2),
6290 binop(Iop_Or32,
6291 getDSPControl(),
6292 mkU32(0x200000)),
6293 IRExpr_ITE(mkexpr(t3),
6294 binop(Iop_Or32,
6295 getDSPControl(),
6296 mkU32(0x200000)),
6297 getDSPControl())));
6298 putIReg(rd,
6299 binop(Iop_16HLto32,
6300 IRExpr_ITE(mkexpr(t2),
6301 mkU16(0xffff),
6302 unop(Iop_32to16, mkexpr(t0))),
6303 IRExpr_ITE(mkexpr(t3),
6304 mkU16(0xffff),
6305 unop(Iop_32to16, mkexpr(t1)))));
6306 break;
6308 case 0x7: { /* MULEU_S.PH.QBR */
6309 DIP("muleu_s.ph.qbr r%u, r%u, r%u", rd, rs, rt);
6310 vassert(!mode64);
6311 t0 = newTemp(Ity_I32);
6312 t1 = newTemp(Ity_I32);
6313 t2 = newTemp(Ity_I1);
6314 t3 = newTemp(Ity_I1);
6316 assign(t0, unop(Iop_64to32,
6317 binop(Iop_MullU32,
6318 unop(Iop_8Uto32,
6319 unop(Iop_16HIto8,
6320 unop(Iop_32to16,
6321 getIReg(rs)))),
6322 unop(Iop_16Uto32,
6323 unop(Iop_32HIto16,
6324 getIReg(rt))))));
6325 assign(t1, unop(Iop_64to32,
6326 binop(Iop_MullU32,
6327 unop(Iop_8Uto32,
6328 unop(Iop_16to8,
6329 unop(Iop_32to16,
6330 getIReg(rs)))),
6331 unop(Iop_16Uto32,
6332 unop(Iop_32to16,
6333 getIReg(rt))))));
6335 assign(t2, binop(Iop_CmpNE32,
6336 mkU32(0x0),
6337 binop(Iop_And32,
6338 mkexpr(t0),
6339 mkU32(0x03ff0000))));
6340 assign(t3, binop(Iop_CmpNE32,
6341 mkU32(0x0),
6342 binop(Iop_And32,
6343 mkexpr(t1),
6344 mkU32(0x03ff0000))));
6345 putDSPControl(IRExpr_ITE(mkexpr(t2),
6346 binop(Iop_Or32,
6347 getDSPControl(),
6348 mkU32(0x200000)),
6349 IRExpr_ITE(mkexpr(t3),
6350 binop(Iop_Or32,
6351 getDSPControl(),
6352 mkU32(0x200000)),
6353 getDSPControl())));
6354 putIReg(rd, binop(Iop_16HLto32,
6355 IRExpr_ITE(mkexpr(t2),
6356 mkU16(0xffff),
6357 unop(Iop_32to16,
6358 mkexpr(t0))),
6359 IRExpr_ITE(mkexpr(t3),
6360 mkU16(0xffff),
6361 unop(Iop_32to16,
6362 mkexpr(t1)))));
6363 break;
6365 case 0x08: { /* ADDU.PH */
6366 DIP("addu.ph r%u, r%u, r%u", rd, rs, rt);
6367 vassert(!mode64);
6368 t0 = newTemp(Ity_I32);
6369 t1 = newTemp(Ity_I1);
6370 t2 = newTemp(Ity_I32);
6371 t3 = newTemp(Ity_I1);
6373 /* Add lower halves. */
6374 assign(t0, binop(Iop_Add32,
6375 unop(Iop_16Uto32,
6376 unop(Iop_32to16, getIReg(rs))),
6377 unop(Iop_16Uto32,
6378 unop(Iop_32to16, getIReg(rt)))));
6380 /* Detect overflow. */
6381 assign(t1, binop(Iop_CmpLT32U,
6382 unop(Iop_16Uto32,
6383 unop(Iop_32to16, mkexpr(t0))),
6384 unop(Iop_16Uto32,
6385 unop(Iop_32to16, getIReg(rs)))));
6387 putDSPControl(IRExpr_ITE(mkexpr(t1),
6388 binop(Iop_Or32,
6389 getDSPControl(),
6390 mkU32(0x00100000)),
6391 getDSPControl()));
6393 /* Add higher halves. */
6394 assign(t2, binop(Iop_Add32,
6395 unop(Iop_16Uto32,
6396 unop(Iop_32HIto16, getIReg(rs))),
6397 unop(Iop_16Uto32,
6398 unop(Iop_32HIto16, getIReg(rt)))));
6400 /* Detect overflow. */
6401 assign(t3, binop(Iop_CmpLT32U,
6402 unop(Iop_16Uto32,
6403 unop(Iop_32to16, mkexpr(t2))),
6404 unop(Iop_16Uto32,
6405 unop(Iop_32HIto16,
6406 getIReg(rs)))));
6408 putDSPControl(IRExpr_ITE(mkexpr(t3),
6409 binop(Iop_Or32,
6410 getDSPControl(),
6411 mkU32(0x00100000)),
6412 getDSPControl()));
6414 putIReg(rd, binop(Iop_16HLto32,
6415 unop(Iop_32to16, mkexpr(t2)),
6416 unop(Iop_32to16, mkexpr(t0))));
6417 break;
6419 case 0x9: { /* SUBU.PH */
6420 DIP("subu.ph r%u, r%u, r%u", rd, rs, rt);
6421 vassert(!mode64);
6422 t0 = newTemp(Ity_I32);
6423 t1 = newTemp(Ity_I1);
6424 t2 = newTemp(Ity_I32);
6425 t3 = newTemp(Ity_I1);
6427 /* Substract lower halves. */
6428 assign(t0, binop(Iop_Sub32,
6429 unop(Iop_16Uto32,
6430 unop(Iop_32to16, getIReg(rs))),
6431 unop(Iop_16Uto32,
6432 unop(Iop_32to16, getIReg(rt)))));
6434 /* Detect underflow. */
6435 assign(t1, binop(Iop_CmpNE32,
6436 binop(Iop_And32,
6437 mkexpr(t0),
6438 mkU32(0x00010000)),
6439 mkU32(0x0)));
6441 putDSPControl(IRExpr_ITE(mkexpr(t1),
6442 binop(Iop_Or32,
6443 getDSPControl(),
6444 mkU32(0x00100000)),
6445 getDSPControl()));
6447 /* Subtract higher halves. */
6448 assign(t2, binop(Iop_Sub32,
6449 unop(Iop_16Uto32,
6450 unop(Iop_32HIto16, getIReg(rs))),
6451 unop(Iop_16Uto32,
6452 unop(Iop_32HIto16, getIReg(rt)))));
6454 /* Detect underflow. */
6455 assign(t3, binop(Iop_CmpNE32,
6456 binop(Iop_And32,
6457 mkexpr(t2),
6458 mkU32(0x00010000)),
6459 mkU32(0x0)));
6461 putDSPControl(IRExpr_ITE(mkexpr(t3),
6462 binop(Iop_Or32,
6463 getDSPControl(),
6464 mkU32(0x00100000)),
6465 getDSPControl()));
6467 putIReg(rd, binop(Iop_16HLto32,
6468 unop(Iop_32to16, mkexpr(t2)),
6469 unop(Iop_32to16, mkexpr(t0))));
6470 break;
6472 case 0xA: { /* ADDQ.PH */
6473 DIP("addq.ph r%u, r%u, r%u", rd, rs, rt);
6474 vassert(!mode64);
6475 t0 = newTemp(Ity_I32);
6476 t1 = newTemp(Ity_I1);
6477 t2 = newTemp(Ity_I32);
6478 t3 = newTemp(Ity_I1);
6479 t6 = newTemp(Ity_I32);
6480 t7 = newTemp(Ity_I32);
6482 /* Add lower halves. */
6483 assign(t0, binop(Iop_Add32,
6484 unop(Iop_16Sto32,
6485 unop(Iop_32to16, getIReg(rs))),
6486 unop(Iop_16Sto32,
6487 unop(Iop_32to16, getIReg(rt)))));
6489 /* Bit 16 of the result. */
6490 assign(t6, binop(Iop_And32,
6491 unop(Iop_16Uto32,
6492 unop(Iop_32HIto16, mkexpr(t0))),
6493 mkU32(0x1)));
6494 /* Detect overflow. */
6495 assign(t1, binop(Iop_CmpNE32,
6496 binop(Iop_Shr32,
6497 binop(Iop_And32,
6498 mkexpr(t0),
6499 mkU32(0x8000)),
6500 mkU8(15)),
6501 mkexpr(t6)));
6503 putDSPControl(IRExpr_ITE(mkexpr(t1),
6504 binop(Iop_Or32,
6505 getDSPControl(),
6506 mkU32(0x00100000)),
6507 getDSPControl()));
6509 /* Add higher halves. */
6510 assign(t2, binop(Iop_Add32,
6511 unop(Iop_16Sto32,
6512 unop(Iop_32HIto16, getIReg(rs))),
6513 unop(Iop_16Sto32,
6514 unop(Iop_32HIto16, getIReg(rt)))));
6516 /* Bit 16 of the result. */
6517 assign(t7, binop(Iop_And32,
6518 unop(Iop_16Uto32,
6519 unop(Iop_32HIto16, mkexpr(t2))),
6520 mkU32(0x1)));
6521 /* Detect overflow. */
6522 assign(t3, binop(Iop_CmpNE32,
6523 binop(Iop_Shr32,
6524 binop(Iop_And32,
6525 mkexpr(t2),
6526 mkU32(0x00008000)),
6527 mkU8(15)),
6528 mkexpr(t7)));
6530 putDSPControl(IRExpr_ITE(mkexpr(t3),
6531 binop(Iop_Or32,
6532 getDSPControl(),
6533 mkU32(0x00100000)),
6534 getDSPControl()));
6536 putIReg(rd, binop(Iop_16HLto32,
6537 unop(Iop_32to16, mkexpr(t2)),
6538 unop(Iop_32to16, mkexpr(t0))));
6539 break;
6541 case 0xB: { /* SUBQ.PH */
6542 DIP("subq.ph r%u, r%u, r%u", rd, rs, rt);
6543 vassert(!mode64);
6544 t0 = newTemp(Ity_I32);
6545 t1 = newTemp(Ity_I1);
6546 t2 = newTemp(Ity_I32);
6547 t3 = newTemp(Ity_I1);
6548 t6 = newTemp(Ity_I32);
6549 t7 = newTemp(Ity_I32);
6551 /* Subtract lower halves. */
6552 assign(t0, binop(Iop_Sub32,
6553 unop(Iop_16Sto32,
6554 unop(Iop_32to16, getIReg(rs))),
6555 unop(Iop_16Sto32,
6556 unop(Iop_32to16, getIReg(rt)))));
6558 /* Bit 16 of the result. */
6559 assign(t6, binop(Iop_And32,
6560 unop(Iop_16Uto32,
6561 unop(Iop_32HIto16, mkexpr(t0))),
6562 mkU32(0x1)));
6563 /* Compare the signs of input value and the result. */
6564 assign(t1, binop(Iop_CmpNE32,
6565 binop(Iop_Shr32,
6566 binop(Iop_And32,
6567 mkexpr(t0),
6568 mkU32(0x8000)),
6569 mkU8(15)),
6570 mkexpr(t6)));
6572 putDSPControl(IRExpr_ITE(mkexpr(t1),
6573 binop(Iop_Or32,
6574 getDSPControl(),
6575 mkU32(0x00100000)),
6576 getDSPControl()));
6578 /* Subtract higher halves. */
6579 assign(t2, binop(Iop_Sub32,
6580 unop(Iop_16Sto32,
6581 unop(Iop_32HIto16, getIReg(rs))),
6582 unop(Iop_16Sto32,
6583 unop(Iop_32HIto16, getIReg(rt)))));
6585 /* Bit 16 of the result. */
6586 assign(t7, binop(Iop_And32,
6587 unop(Iop_16Uto32,
6588 unop(Iop_32HIto16, mkexpr(t2))),
6589 mkU32(0x1)));
6590 /* Compare the signs of input value and the result. */
6591 assign(t3, binop(Iop_CmpNE32,
6592 binop(Iop_Shr32,
6593 binop(Iop_And32,
6594 mkexpr(t2),
6595 mkU32(0x00008000)),
6596 mkU8(15)),
6597 mkexpr(t7)));
6599 putDSPControl(IRExpr_ITE(mkexpr(t3),
6600 binop(Iop_Or32,
6601 getDSPControl(),
6602 mkU32(0x00100000)),
6603 getDSPControl()));
6605 putIReg(rd, binop(Iop_16HLto32,
6606 unop(Iop_32to16, mkexpr(t2)),
6607 unop(Iop_32to16, mkexpr(t0))));
6608 break;
6610 case 0xC: { /* ADDU_S.PH */
6611 DIP("addu_s.ph r%u, r%u, r%u", rd, rs, rt);
6612 vassert(!mode64);
6613 t0 = newTemp(Ity_I32);
6614 t1 = newTemp(Ity_I1);
6615 t2 = newTemp(Ity_I32);
6616 t3 = newTemp(Ity_I1);
6618 /* Add lower halves. */
6619 assign(t0, binop(Iop_Add32,
6620 unop(Iop_16Uto32,
6621 unop(Iop_32to16, getIReg(rs))),
6622 unop(Iop_16Uto32,
6623 unop(Iop_32to16, getIReg(rt)))));
6625 /* Detect overflow. */
6626 assign(t1, binop(Iop_CmpLT32U,
6627 unop(Iop_16Uto32,
6628 unop(Iop_32to16, mkexpr(t0))),
6629 unop(Iop_16Uto32,
6630 unop(Iop_32to16, getIReg(rs)))));
6632 putDSPControl(IRExpr_ITE(mkexpr(t1),
6633 binop(Iop_Or32,
6634 getDSPControl(),
6635 mkU32(0x00100000)),
6636 getDSPControl()));
6638 /* Add higher halves. */
6639 assign(t2, binop(Iop_Add32,
6640 unop(Iop_16Uto32,
6641 unop(Iop_32HIto16, getIReg(rs))),
6642 unop(Iop_16Uto32,
6643 unop(Iop_32HIto16, getIReg(rt)))));
6645 /* Detect overflow. */
6646 assign(t3, binop(Iop_CmpLT32U,
6647 unop(Iop_16Uto32,
6648 unop(Iop_32to16, mkexpr(t2))),
6649 unop(Iop_16Uto32,
6650 unop(Iop_32HIto16, getIReg(rs)))));
6652 putDSPControl(IRExpr_ITE(mkexpr(t3),
6653 binop(Iop_Or32,
6654 getDSPControl(),
6655 mkU32(0x00100000)),
6656 getDSPControl()));
6658 putIReg(rd, binop(Iop_16HLto32,
6659 IRExpr_ITE(mkexpr(t3),
6660 mkU16(0xffff),
6661 unop(Iop_32to16,
6662 mkexpr(t2))),
6663 IRExpr_ITE(mkexpr(t1),
6664 mkU16(0xffff),
6665 unop(Iop_32to16,
6666 mkexpr(t0)))));
6667 break;
6669 case 0xD: { /* SUBU_S.PH */
6670 DIP("subu_s.ph r%u, r%u, r%u", rd, rs, rt);
6671 vassert(!mode64);
6672 t0 = newTemp(Ity_I32);
6673 t1 = newTemp(Ity_I1);
6674 t2 = newTemp(Ity_I32);
6675 t3 = newTemp(Ity_I1);
6677 /* Subtract lower halves. */
6678 assign(t0, binop(Iop_Sub32,
6679 unop(Iop_16Uto32,
6680 unop(Iop_32to16, getIReg(rs))),
6681 unop(Iop_16Uto32,
6682 unop(Iop_32to16, getIReg(rt)))));
6684 /* Detect underflow. */
6685 assign(t1, binop(Iop_CmpNE32,
6686 binop(Iop_And32,
6687 mkexpr(t0), mkU32(0x00010000)),
6688 mkU32(0x0)));
6690 putDSPControl(IRExpr_ITE(mkexpr(t1),
6691 binop(Iop_Or32,
6692 getDSPControl(),
6693 mkU32(0x00100000)),
6694 getDSPControl()));
6696 /* Subtract higher halves. */
6697 assign(t2, binop(Iop_Sub32,
6698 unop(Iop_16Uto32,
6699 unop(Iop_32HIto16, getIReg(rs))),
6700 unop(Iop_16Uto32,
6701 unop(Iop_32HIto16, getIReg(rt)))));
6703 /* Detect underflow. */
6704 assign(t3, binop(Iop_CmpNE32,
6705 binop(Iop_And32,
6706 mkexpr(t2), mkU32(0x00010000)),
6707 mkU32(0x0)));
6709 putDSPControl(IRExpr_ITE(mkexpr(t3),
6710 binop(Iop_Or32,
6711 getDSPControl(),
6712 mkU32(0x00100000)),
6713 getDSPControl()));
6715 putIReg(rd,
6716 binop(Iop_16HLto32,
6717 IRExpr_ITE(mkexpr(t3),
6718 mkU16(0x0000),
6719 unop(Iop_32to16, mkexpr(t2))),
6720 IRExpr_ITE(mkexpr(t1),
6721 mkU16(0x0000),
6722 unop(Iop_32to16, mkexpr(t0)))));
6723 break;
6725 case 0xE: { /* ADDQ_S.PH */
6726 DIP("addq_s.ph r%u r%u, r%u", rd, rs, rt);
6727 vassert(!mode64);
6728 t0 = newTemp(Ity_I32);
6729 t1 = newTemp(Ity_I1);
6730 t2 = newTemp(Ity_I32);
6731 t3 = newTemp(Ity_I1);
6732 t4 = newTemp(Ity_I16);
6733 t5 = newTemp(Ity_I16);
6734 t6 = newTemp(Ity_I32);
6735 t7 = newTemp(Ity_I32);
6737 /* Add lower halves. */
6738 assign(t0, binop(Iop_Add32,
6739 unop(Iop_16Sto32,
6740 unop(Iop_32to16, getIReg(rs))),
6741 unop(Iop_16Sto32,
6742 unop(Iop_32to16, getIReg(rt)))));
6744 /* Bit 16 of the result. */
6745 assign(t6, binop(Iop_And32,
6746 unop(Iop_16Uto32,
6747 unop(Iop_32HIto16, mkexpr(t0))),
6748 mkU32(0x1)));
6749 /* Detect overflow. */
6750 assign(t1, binop(Iop_CmpNE32,
6751 binop(Iop_Shr32,
6752 binop(Iop_And32,
6753 mkexpr(t0),
6754 mkU32(0x8000)),
6755 mkU8(15)),
6756 mkexpr(t6)));
6758 putDSPControl(IRExpr_ITE(mkexpr(t1),
6759 binop(Iop_Or32,
6760 getDSPControl(),
6761 mkU32(0x00100000)),
6762 getDSPControl()));
6763 /* Saturate if needed. */
6764 assign(t4, IRExpr_ITE(mkexpr(t1),
6765 IRExpr_ITE(binop(Iop_CmpEQ32,
6766 mkexpr(t6),
6767 mkU32(0x0)),
6768 mkU16(0x7fff),
6769 mkU16(0x8000)),
6770 unop(Iop_32to16, mkexpr(t0))));
6772 /* Add higher halves. */
6773 assign(t2, binop(Iop_Add32,
6774 unop(Iop_16Sto32,
6775 unop(Iop_32HIto16, getIReg(rs))),
6776 unop(Iop_16Sto32,
6777 unop(Iop_32HIto16, getIReg(rt)))));
6779 /* Bit 16 of the result. */
6780 assign(t7, binop(Iop_And32,
6781 unop(Iop_16Uto32,
6782 unop(Iop_32HIto16, mkexpr(t2))),
6783 mkU32(0x1)));
6784 /* Detect overflow. */
6785 assign(t3, binop(Iop_CmpNE32,
6786 binop(Iop_Shr32,
6787 binop(Iop_And32,
6788 mkexpr(t2),
6789 mkU32(0x00008000)),
6790 mkU8(15)),
6791 mkexpr(t7)));
6793 putDSPControl(IRExpr_ITE(mkexpr(t3),
6794 binop(Iop_Or32,
6795 getDSPControl(),
6796 mkU32(0x00100000)),
6797 getDSPControl()));
6798 /* Saturate if needed. */
6799 assign(t5, IRExpr_ITE(mkexpr(t3),
6800 IRExpr_ITE(binop(Iop_CmpEQ32,
6801 mkexpr(t7),
6802 mkU32(0x0)),
6803 mkU16(0x7fff),
6804 mkU16(0x8000)),
6805 unop(Iop_32to16, mkexpr(t2))));
6807 putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
6808 break;
6810 case 0xF: { /* SUBQ_S.PH */
6811 DIP("subq_s.ph r%u r%u, r%u", rd, rs, rt);
6812 vassert(!mode64);
6813 t0 = newTemp(Ity_I32);
6814 t1 = newTemp(Ity_I1);
6815 t2 = newTemp(Ity_I32);
6816 t3 = newTemp(Ity_I1);
6817 t4 = newTemp(Ity_I16);
6818 t5 = newTemp(Ity_I16);
6819 t6 = newTemp(Ity_I32);
6820 t7 = newTemp(Ity_I32);
6822 /* Subtract lower halves. */
6823 assign(t0, binop(Iop_Sub32,
6824 unop(Iop_16Sto32,
6825 unop(Iop_32to16, getIReg(rs))),
6826 unop(Iop_16Sto32,
6827 unop(Iop_32to16, getIReg(rt)))));
6829 /* Bit 16 of the result. */
6830 assign(t6, binop(Iop_And32,
6831 unop(Iop_16Uto32,
6832 unop(Iop_32HIto16, mkexpr(t0))),
6833 mkU32(0x1)));
6834 /* Detect overflow or underflow. */
6835 assign(t1, binop(Iop_CmpNE32,
6836 binop(Iop_Shr32,
6837 binop(Iop_And32,
6838 mkexpr(t0),
6839 mkU32(0x8000)),
6840 mkU8(15)),
6841 mkexpr(t6)));
6843 putDSPControl(IRExpr_ITE(mkexpr(t1),
6844 binop(Iop_Or32,
6845 getDSPControl(),
6846 mkU32(0x00100000)),
6847 getDSPControl()));
6848 /* Saturate if needed. */
6849 assign(t4, IRExpr_ITE(mkexpr(t1),
6850 IRExpr_ITE(binop(Iop_CmpEQ32,
6851 mkexpr(t6),
6852 mkU32(0x0)),
6853 mkU16(0x7fff),
6854 mkU16(0x8000)),
6855 unop(Iop_32to16, mkexpr(t0))));
6857 /* Subtract higher halves. */
6858 assign(t2, binop(Iop_Sub32,
6859 unop(Iop_16Sto32,
6860 unop(Iop_32HIto16, getIReg(rs))),
6861 unop(Iop_16Sto32,
6862 unop(Iop_32HIto16, getIReg(rt)))));
6864 /* Bit 16 of the result. */
6865 assign(t7, binop(Iop_And32,
6866 unop(Iop_16Uto32,
6867 unop(Iop_32HIto16, mkexpr(t2))),
6868 mkU32(0x1)));
6869 /* Detect overflow or underflow. */
6870 assign(t3, binop(Iop_CmpNE32,
6871 binop(Iop_Shr32,
6872 binop(Iop_And32,
6873 mkexpr(t2),
6874 mkU32(0x00008000)),
6875 mkU8(15)),
6876 mkexpr(t7)));
6878 putDSPControl(IRExpr_ITE(mkexpr(t3),
6879 binop(Iop_Or32,
6880 getDSPControl(),
6881 mkU32(0x00100000)),
6882 getDSPControl()));
6883 /* Saturate if needed. */
6884 assign(t5, IRExpr_ITE(mkexpr(t3),
6885 IRExpr_ITE(binop(Iop_CmpEQ32,
6886 mkexpr(t7),
6887 mkU32(0x0)),
6888 mkU16(0x7fff),
6889 mkU16(0x8000)),
6890 unop(Iop_32to16, mkexpr(t2))));
6892 putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
6893 break;
6895 case 0x10: { /* ADDSC */
6896 DIP("addsc r%u, r%u, r%u", rd, rs, rt);
6897 vassert(!mode64);
6898 t0 = newTemp(Ity_I64);
6899 t1 = newTemp(Ity_I1);
6901 /* The carry bit result out of the addition operation is
6902 written to bit 13(the c field) of the DSPControl reg. */
6903 assign(t0, binop(Iop_Add64,
6904 unop(Iop_32Uto64, getIReg(rs)),
6905 unop(Iop_32Uto64, getIReg(rt))));
6907 assign(t1, binop(Iop_CmpEQ32,
6908 binop(Iop_And32,
6909 unop(Iop_64HIto32, mkexpr(t0)),
6910 mkU32(0x1)),
6911 mkU32(0x1)));
6912 putDSPControl(IRExpr_ITE(mkexpr(t1),
6913 binop(Iop_Or32,
6914 getDSPControl(),
6915 mkU32(0x2000)),
6916 binop(Iop_And32,
6917 getDSPControl(),
6918 mkU32(0xffffdfff))));
6920 putIReg(rd, unop(Iop_64to32, mkexpr(t0)));
6921 break;
6923 case 0x11: { /* ADDWC */
6924 DIP("addwc r%u, r%u, r%u", rd, rs, rt);
6925 vassert(!mode64);
6926 t0 = newTemp(Ity_I32);
6927 t1 = newTemp(Ity_I64);
6928 t2 = newTemp(Ity_I32);
6929 t3 = newTemp(Ity_I32);
6930 t4 = newTemp(Ity_I1);
6932 /* Get carry bit from DSPControl register. */
6933 assign(t0, binop(Iop_Shr32,
6934 binop(Iop_And32,
6935 getDSPControl(),
6936 mkU32(0x2000)),
6937 mkU8(0xd)));
6938 assign(t1, binop(Iop_Add64,
6939 unop(Iop_32Sto64, getIReg(rs)),
6940 unop(Iop_32Sto64,
6941 binop(Iop_Add32,
6942 getIReg(rt),
6943 mkexpr(t0)))));
6945 /* Extract bits 32 and 31. */
6946 assign(t2, binop(Iop_And32,
6947 unop(Iop_64HIto32, mkexpr(t1)),
6948 mkU32(0x1)));
6949 assign(t3, binop(Iop_Shr32,
6950 binop(Iop_And32,
6951 unop(Iop_64to32, mkexpr(t1)),
6952 mkU32(0x80000000)),
6953 mkU8(31)));
6954 assign(t4, binop(Iop_CmpNE32, mkexpr(t2), mkexpr(t3)));
6956 putDSPControl(IRExpr_ITE(mkexpr(t4),
6957 binop(Iop_Or32,
6958 getDSPControl(),
6959 mkU32(0x00100000)),
6960 getDSPControl()));
6961 putIReg(rd, unop(Iop_64to32, mkexpr(t1)));
6962 break;
6964 case 0x12: { /* MODSUB */
6965 DIP("modsub r%u, r%u, r%u", rd, rs, rt);
6966 vassert(!mode64);
6967 t0 = newTemp(Ity_I32);
6968 t1 = newTemp(Ity_I32);
6969 t2 = newTemp(Ity_I32);
6971 /* decr_7..0 */
6972 assign(t0,
6973 unop(Iop_8Uto32,
6974 unop(Iop_16to8,
6975 unop(Iop_32to16, getIReg(rt)))));
6977 /* lastindex_15..0 */
6978 assign(t1,
6979 unop(Iop_16Uto32,
6980 binop(Iop_8HLto16,
6981 unop(Iop_16to8,
6982 unop(Iop_32HIto16, getIReg(rt))),
6983 unop(Iop_16HIto8,
6984 unop(Iop_32to16, getIReg(rt))))));
6985 /* temp_15..0 */
6986 assign(t2,
6987 IRExpr_ITE(binop(Iop_CmpEQ32,
6988 getIReg(rs),
6989 mkU32(0x00000000)),
6990 mkexpr(t1),
6991 binop(Iop_Sub32,
6992 getIReg(rs), mkexpr(t0))));
6993 putIReg(rd, mkexpr(t2));
6994 break;
6996 case 0x14: { /* RADDU.W.QB */
6997 DIP("raddu.w.qb r%u, r%u", rd, rs);
6998 vassert(!mode64);
6999 putIReg(rd, binop(Iop_Add32,
7000 binop(Iop_Add32,
7001 unop(Iop_8Uto32,
7002 unop(Iop_16to8,
7003 unop(Iop_32to16,
7004 getIReg(rs)))),
7005 unop(Iop_8Uto32,
7006 unop(Iop_16HIto8,
7007 unop(Iop_32to16,
7008 getIReg(rs))))),
7009 binop(Iop_Add32,
7010 unop(Iop_8Uto32,
7011 unop(Iop_16to8,
7012 unop(Iop_32HIto16,
7013 getIReg(rs)))),
7014 unop(Iop_8Uto32,
7015 unop(Iop_16HIto8,
7016 unop(Iop_32HIto16,
7017 getIReg(rs)))))));
7018 break;
7020 case 0x16: { /* ADDQ_S.W */
7021 DIP("addq_s.w r%u, r%u, r%u", rd, rs, rt);
7022 vassert(!mode64);
7023 t0 = newTemp(Ity_I64);
7024 t1 = newTemp(Ity_I1);
7025 t2 = newTemp(Ity_I32);
7026 t3 = newTemp(Ity_I32);
7028 assign(t0, binop(Iop_Add64,
7029 unop(Iop_32Sto64, getIReg(rs)),
7030 unop(Iop_32Sto64, getIReg(rt))));
7032 assign(t3, binop(Iop_And32,
7033 unop(Iop_64HIto32, mkexpr(t0)),
7034 mkU32(0x1)));
7035 assign(t1, binop(Iop_CmpNE32,
7036 binop(Iop_Shr32,
7037 binop(Iop_And32,
7038 unop(Iop_64to32, mkexpr(t0)),
7039 mkU32(0x80000000)),
7040 mkU8(31)),
7041 mkexpr(t3)));
7043 putDSPControl(IRExpr_ITE(mkexpr(t1),
7044 binop(Iop_Or32,
7045 getDSPControl(),
7046 mkU32(0x00100000)),
7047 getDSPControl()));
7049 putIReg(rd, IRExpr_ITE(mkexpr(t1),
7050 IRExpr_ITE(binop(Iop_CmpEQ32,
7051 mkexpr(t3),
7052 mkU32(0x0)),
7053 mkU32(0x7fffffff),
7054 mkU32(0x80000000)),
7055 unop(Iop_64to32, mkexpr(t0))));
7056 break;
7058 case 0x17: { /* SUBQ_S.W */
7059 DIP("subq_s.w r%u, r%u, r%u", rd, rs, rt);
7060 vassert(!mode64);
7061 t0 = newTemp(Ity_I64);
7062 t1 = newTemp(Ity_I1);
7063 t2 = newTemp(Ity_I32);
7064 t3 = newTemp(Ity_I32);
7066 assign(t0, binop(Iop_Sub64,
7067 unop(Iop_32Sto64, getIReg(rs)),
7068 unop(Iop_32Sto64, getIReg(rt))));
7070 assign(t3, binop(Iop_And32,
7071 unop(Iop_64HIto32, mkexpr(t0)),
7072 mkU32(0x1)));
7073 assign(t1, binop(Iop_CmpNE32,
7074 binop(Iop_Shr32,
7075 binop(Iop_And32,
7076 unop(Iop_64to32, mkexpr(t0)),
7077 mkU32(0x80000000)),
7078 mkU8(31)),
7079 mkexpr(t3)));
7081 putDSPControl(IRExpr_ITE(mkexpr(t1),
7082 binop(Iop_Or32,
7083 getDSPControl(),
7084 mkU32(0x00100000)),
7085 getDSPControl()));
7087 putIReg(rd, IRExpr_ITE(mkexpr(t1),
7088 IRExpr_ITE(binop(Iop_CmpEQ32,
7089 mkexpr(t3),
7090 mkU32(0x0)),
7091 mkU32(0x7fffffff),
7092 mkU32(0x80000000)),
7093 unop(Iop_64to32, mkexpr(t0))));
7094 break;
7096 case 0x1C: { /* MULEQ_S.W.PHL */
7097 DIP("muleq_s.w.phl r%u, r%u, r%u", rd, rs, rt);
7098 vassert(!mode64);
7099 t0 = newTemp(Ity_I32);
7100 t1 = newTemp(Ity_I1);
7101 t2 = newTemp(Ity_I1);
7102 t3 = newTemp(Ity_I32);
7104 assign(t0,
7105 binop(Iop_Shl32,
7106 binop(Iop_Mul32,
7107 unop(Iop_16Sto32,
7108 unop(Iop_32HIto16, getIReg(rt))),
7109 unop(Iop_16Sto32,
7110 unop(Iop_32HIto16, getIReg(rs)))),
7111 mkU8(0x1)));
7112 assign(t1, binop(Iop_CmpEQ32,
7113 binop(Iop_And32,
7114 getIReg(rt),
7115 mkU32(0xffff0000)),
7116 mkU32(0x80000000)));
7117 assign(t2, binop(Iop_CmpEQ32,
7118 binop(Iop_And32,
7119 getIReg(rs),
7120 mkU32(0xffff0000)),
7121 mkU32(0x80000000)));
7122 assign(t3, IRExpr_ITE(mkexpr(t1),
7123 IRExpr_ITE(mkexpr(t2),
7124 binop(Iop_Or32,
7125 getDSPControl(),
7126 mkU32(0x00200000)),
7127 getDSPControl()),
7128 getDSPControl()));
7129 putDSPControl(mkexpr(t3));
7131 putIReg(rd, IRExpr_ITE(mkexpr(t1),
7132 IRExpr_ITE(mkexpr(t2),
7133 mkU32(0x7fffffff),
7134 mkexpr(t0)),
7135 mkexpr(t0)));
7136 break;
7138 case 0x1D: { /* MULEQ_S.W.PHR */
7139 DIP("muleq_s.w.phr r%u, r%u, r%u", rd, rs, rt);
7140 vassert(!mode64);
7141 t0 = newTemp(Ity_I32);
7142 t1 = newTemp(Ity_I1);
7143 t2 = newTemp(Ity_I1);
7145 assign(t0,
7146 binop(Iop_Shl32,
7147 binop(Iop_Mul32,
7148 unop(Iop_16Sto32,
7149 unop(Iop_32to16, getIReg(rt))),
7150 unop(Iop_16Sto32,
7151 unop(Iop_32to16, getIReg(rs)))),
7152 mkU8(0x1)));
7153 assign(t1, binop(Iop_CmpEQ32,
7154 binop(Iop_And32,
7155 getIReg(rt),
7156 mkU32(0xffff)),
7157 mkU32(0x8000)));
7158 assign(t2, binop(Iop_CmpEQ32,
7159 binop(Iop_And32,
7160 getIReg(rs),
7161 mkU32(0xffff)),
7162 mkU32(0x8000)));
7163 putDSPControl(IRExpr_ITE(mkexpr(t1),
7164 IRExpr_ITE(mkexpr(t2),
7165 binop(Iop_Or32,
7166 getDSPControl(),
7167 mkU32(0x00200000)
7169 getDSPControl()),
7170 getDSPControl()));
7171 putIReg(rd, IRExpr_ITE(mkexpr(t1),
7172 IRExpr_ITE(mkexpr(t2),
7173 mkU32(0x7fffffff),
7174 mkexpr(t0)),
7175 mkexpr(t0)));
7176 break;
7178 case 0x1E: { /* MULQ_S.PH */
7179 DIP("mulq_s.ph r%u, r%u, r%u", rd, rs, rt);
7180 vassert(!mode64);
7181 t0 = newTemp(Ity_I32);
7182 t1 = newTemp(Ity_I32);
7183 t2 = newTemp(Ity_I16);
7184 t3 = newTemp(Ity_I16);
7185 t5 = newTemp(Ity_I32);
7186 t6 = newTemp(Ity_I32);
7187 t7 = newTemp(Ity_I32);
7188 t8 = newTemp(Ity_I32);
7190 assign(t5,
7191 unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rs))));
7192 assign(t6,
7193 unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
7195 assign(t7,
7196 unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rs))));
7197 assign(t8,
7198 unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rt))));
7200 assign(t0, binop(Iop_And32,
7201 unop(Iop_1Sto32,
7202 binop(Iop_CmpEQ32,
7203 binop(Iop_And32,
7204 mkexpr(t5),
7205 mkU32(0xffff)),
7206 mkU32(0x8000))),
7207 unop(Iop_1Sto32,
7208 binop(Iop_CmpEQ32,
7209 binop(Iop_And32,
7210 mkexpr(t6),
7211 mkU32(0xffff)),
7212 mkU32(0x8000)))));
7213 assign(t1, binop(Iop_And32,
7214 unop(Iop_1Sto32,
7215 binop(Iop_CmpEQ32,
7216 binop(Iop_And32,
7217 mkexpr(t7),
7218 mkU32(0xffff)),
7219 mkU32(0x8000))),
7220 unop(Iop_1Sto32,
7221 binop(Iop_CmpEQ32,
7222 binop(Iop_And32,
7223 mkexpr(t8),
7224 mkU32(0xffff)),
7225 mkU32(0x8000)))));
7227 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
7228 binop(Iop_Or32,
7229 mkexpr(t0),
7230 mkexpr(t1)),
7231 mkU32(0x0)),
7232 getDSPControl(),
7233 binop(Iop_Or32,
7234 getDSPControl(),
7235 mkU32(0x200000))));
7237 assign(t2, unop(Iop_32HIto16,
7238 binop(Iop_Shl32,
7239 unop(Iop_64to32,
7240 binop(Iop_MullS32,
7241 mkexpr(t7),
7242 mkexpr(t8))),
7243 mkU8(0x1))));
7244 assign(t3, unop(Iop_32HIto16,
7245 binop(Iop_Shl32,
7246 unop(Iop_64to32,
7247 binop(Iop_MullS32,
7248 mkexpr(t5),
7249 mkexpr(t6))),
7250 mkU8(0x1))));
7251 putIReg(rd, binop(Iop_16HLto32,
7252 IRExpr_ITE(binop(Iop_CmpEQ32,
7253 mkexpr(t1),
7254 mkU32(0x0)),
7255 mkexpr(t2),
7256 mkU16(0x7fff)),
7257 IRExpr_ITE(binop(Iop_CmpEQ32,
7258 mkexpr(t0),
7259 mkU32(0x0)),
7260 mkexpr(t3),
7261 mkU16(0x7fff))));
7262 break;
7264 case 0x1F: { /* MULQ_RS.PH */
7265 DIP("mulq_rs.ph r%u, r%u, r%u", rd, rs, rt);
7266 vassert(!mode64);
7267 t0 = newTemp(Ity_I32);
7268 t1 = newTemp(Ity_I1);
7269 t2 = newTemp(Ity_I1);
7270 t3 = newTemp(Ity_I16);
7271 t4 = newTemp(Ity_I32);
7272 t5 = newTemp(Ity_I1);
7273 t6 = newTemp(Ity_I1);
7274 t7 = newTemp(Ity_I16);
7276 /* Multiply and round lower halfwords. */
7277 assign(t0, binop(Iop_Add32,
7278 binop(Iop_Shl32,
7279 binop(Iop_Mul32,
7280 unop(Iop_16Sto32,
7281 unop(Iop_32to16,
7282 getIReg(rt))),
7283 unop(Iop_16Sto32,
7284 unop(Iop_32to16,
7285 getIReg(rs)))),
7286 mkU8(0x1)),
7287 mkU32(0x00008000)));
7288 assign(t1, binop(Iop_CmpEQ32,
7289 binop(Iop_And32,
7290 getIReg(rt), mkU32(0xffff)),
7291 mkU32(0x8000)));
7292 assign(t2, binop(Iop_CmpEQ32,
7293 binop(Iop_And32,
7294 getIReg(rs), mkU32(0xffff)),
7295 mkU32(0x8000)));
7296 putDSPControl(IRExpr_ITE(mkexpr(t1),
7297 IRExpr_ITE(mkexpr(t2),
7298 binop(Iop_Or32,
7299 getDSPControl(),
7300 mkU32(0x00200000)
7302 getDSPControl()),
7303 getDSPControl()));
7304 assign(t3, IRExpr_ITE(mkexpr(t1),
7305 IRExpr_ITE(mkexpr(t2),
7306 mkU16(0x7fff),
7307 unop(Iop_32HIto16,
7308 mkexpr(t0))),
7309 unop(Iop_32HIto16, mkexpr(t0))));
7311 /* Multiply and round higher halfwords. */
7312 assign(t4, binop(Iop_Add32,
7313 binop(Iop_Shl32,
7314 binop(Iop_Mul32,
7315 unop(Iop_16Sto32,
7316 unop(Iop_32HIto16,
7317 getIReg(rt))),
7318 unop(Iop_16Sto32,
7319 unop(Iop_32HIto16,
7320 getIReg(rs)))),
7321 mkU8(0x1)),
7322 mkU32(0x00008000)));
7323 assign(t5, binop(Iop_CmpEQ32,
7324 binop(Iop_And32,
7325 getIReg(rt),
7326 mkU32(0xffff0000)),
7327 mkU32(0x80000000)));
7328 assign(t6, binop(Iop_CmpEQ32,
7329 binop(Iop_And32,
7330 getIReg(rs),
7331 mkU32(0xffff0000)),
7332 mkU32(0x80000000)));
7333 putDSPControl(IRExpr_ITE(mkexpr(t5),
7334 IRExpr_ITE(mkexpr(t6),
7335 binop(Iop_Or32,
7336 getDSPControl(),
7337 mkU32(0x00200000)),
7338 getDSPControl()),
7339 getDSPControl()));
7340 assign(t7, IRExpr_ITE(mkexpr(t5),
7341 IRExpr_ITE(mkexpr(t6),
7342 mkU16(0x7fff),
7343 unop(Iop_32HIto16,
7344 mkexpr(t4))),
7345 unop(Iop_32HIto16, mkexpr(t4))));
7347 putIReg(rd, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3)));
7348 break;
7350 default:
7351 return -1;
7353 break; /* end of ADDU.QB */
7355 case 0x11: { /* CMPU.EQ.QB */
7356 switch(sa) {
7357 case 0x0: { /* CMPU.EQ.QB */
7358 DIP("cmpu.eq.qb r%u, r%u", rs, rt);
7359 vassert(!mode64);
7360 t1 = newTemp(Ity_I1);
7361 t2 = newTemp(Ity_I1);
7362 t3 = newTemp(Ity_I1);
7363 t4 = newTemp(Ity_I1);
7365 assign(t1,
7366 binop(Iop_CmpEQ32,
7367 binop(Iop_And32, getIReg(rs), mkU32(0xff)),
7368 binop(Iop_And32, getIReg(rt), mkU32(0xff))));
7369 putDSPControl(IRExpr_ITE(mkexpr(t1),
7370 binop(Iop_Or32,
7371 getDSPControl(),
7372 mkU32(0x01000000)),
7373 binop(Iop_And32,
7374 getDSPControl(),
7375 mkU32(0xfeffffff))));
7377 assign(t2, binop(Iop_CmpEQ32,
7378 unop(Iop_8Uto32,
7379 unop(Iop_16HIto8,
7380 unop(Iop_32to16,
7381 getIReg(rs)))),
7382 unop(Iop_8Uto32,
7383 unop(Iop_16HIto8,
7384 unop(Iop_32to16,
7385 getIReg(rt))))));
7386 putDSPControl(IRExpr_ITE(mkexpr(t2),
7387 binop(Iop_Or32,
7388 getDSPControl(),
7389 mkU32(0x02000000)),
7390 binop(Iop_And32,
7391 getDSPControl(),
7392 mkU32(0xfdffffff))));
7394 assign(t3, binop(Iop_CmpEQ32,
7395 unop(Iop_8Uto32,
7396 unop(Iop_16to8,
7397 unop(Iop_32HIto16,
7398 getIReg(rs)))),
7399 unop(Iop_8Uto32,
7400 unop(Iop_16to8,
7401 unop(Iop_32HIto16,
7402 getIReg(rt))))));
7403 putDSPControl(IRExpr_ITE(mkexpr(t3),
7404 binop(Iop_Or32,
7405 getDSPControl(),
7406 mkU32(0x04000000)),
7407 binop(Iop_And32,
7408 getDSPControl(),
7409 mkU32(0xfbffffff))));
7411 assign(t4, binop(Iop_CmpEQ32,
7412 unop(Iop_8Uto32,
7413 unop(Iop_16HIto8,
7414 unop(Iop_32HIto16,
7415 getIReg(rs)))),
7416 unop(Iop_8Uto32,
7417 unop(Iop_16HIto8,
7418 unop(Iop_32HIto16,
7419 getIReg(rt))))));
7420 putDSPControl(IRExpr_ITE(mkexpr(t4),
7421 binop(Iop_Or32,
7422 getDSPControl(),
7423 mkU32(0x08000000)),
7424 binop(Iop_And32,
7425 getDSPControl(),
7426 mkU32(0xf7ffffff))));
7427 break;
7429 case 0x1: { /* CMPU.LT.QB */
7430 DIP("cmpu.lt.qb r%u, r%u", rs, rt);
7431 vassert(!mode64);
7432 t1 = newTemp(Ity_I1);
7433 t2 = newTemp(Ity_I1);
7434 t3 = newTemp(Ity_I1);
7435 t4 = newTemp(Ity_I1);
7437 assign(t1, binop(Iop_CmpLT32U,
7438 unop(Iop_8Uto32,
7439 unop(Iop_16to8,
7440 unop(Iop_32to16,
7441 getIReg(rs)))),
7442 unop(Iop_8Uto32,
7443 unop(Iop_16to8,
7444 unop(Iop_32to16,
7445 getIReg(rt))))));
7446 putDSPControl(IRExpr_ITE(mkexpr(t1),
7447 binop(Iop_Or32,
7448 getDSPControl(),
7449 mkU32(0x01000000)),
7450 binop(Iop_And32,
7451 getDSPControl(),
7452 mkU32(0xfeffffff))));
7454 assign(t2, binop(Iop_CmpLT32U,
7455 unop(Iop_8Uto32,
7456 unop(Iop_16HIto8,
7457 unop(Iop_32to16,
7458 getIReg(rs)))),
7459 unop(Iop_8Uto32,
7460 unop(Iop_16HIto8,
7461 unop(Iop_32to16,
7462 getIReg(rt))))));
7463 putDSPControl(IRExpr_ITE(mkexpr(t2),
7464 binop(Iop_Or32,
7465 getDSPControl(),
7466 mkU32(0x02000000)),
7467 binop(Iop_And32,
7468 getDSPControl(),
7469 mkU32(0xfdffffff))));
7471 assign(t3, binop(Iop_CmpLT32U,
7472 unop(Iop_8Uto32,
7473 unop(Iop_16to8,
7474 unop(Iop_32HIto16,
7475 getIReg(rs)))),
7476 unop(Iop_8Uto32,
7477 unop(Iop_16to8,
7478 unop(Iop_32HIto16,
7479 getIReg(rt))))));
7480 putDSPControl(IRExpr_ITE(mkexpr(t3),
7481 binop(Iop_Or32,
7482 getDSPControl(),
7483 mkU32(0x04000000)),
7484 binop(Iop_And32,
7485 getDSPControl(),
7486 mkU32(0xfbffffff))));
7488 assign(t4, binop(Iop_CmpLT32U,
7489 unop(Iop_8Uto32,
7490 unop(Iop_16HIto8,
7491 unop(Iop_32HIto16,
7492 getIReg(rs)))),
7493 unop(Iop_8Uto32,
7494 unop(Iop_16HIto8,
7495 unop(Iop_32HIto16,
7496 getIReg(rt))))));
7497 putDSPControl(IRExpr_ITE(mkexpr(t4),
7498 binop(Iop_Or32,
7499 getDSPControl(),
7500 mkU32(0x08000000)),
7501 binop(Iop_And32,
7502 getDSPControl(),
7503 mkU32(0xf7ffffff))));
7504 break;
7506 case 0x2: { /* CMPU.LE.QB */
7507 DIP("cmpu.le.qb r%u, r%u", rs, rt);
7508 vassert(!mode64);
7509 t1 = newTemp(Ity_I1);
7510 t2 = newTemp(Ity_I1);
7511 t3 = newTemp(Ity_I1);
7512 t4 = newTemp(Ity_I1);
7514 assign(t1, binop(Iop_CmpLE32U,
7515 unop(Iop_8Uto32,
7516 unop(Iop_16to8,
7517 unop(Iop_32to16,
7518 getIReg(rs)))),
7519 unop(Iop_8Uto32,
7520 unop(Iop_16to8,
7521 unop(Iop_32to16,
7522 getIReg(rt))))));
7523 putDSPControl(IRExpr_ITE(mkexpr(t1),
7524 binop(Iop_Or32,
7525 getDSPControl(),
7526 mkU32(0x01000000)),
7527 binop(Iop_And32,
7528 getDSPControl(),
7529 mkU32(0xfeffffff))));
7531 assign(t2, binop(Iop_CmpLE32U,
7532 unop(Iop_8Uto32,
7533 unop(Iop_16HIto8,
7534 unop(Iop_32to16,
7535 getIReg(rs)))),
7536 unop(Iop_8Uto32,
7537 unop(Iop_16HIto8,
7538 unop(Iop_32to16,
7539 getIReg(rt))))));
7540 putDSPControl(IRExpr_ITE(mkexpr(t2),
7541 binop(Iop_Or32,
7542 getDSPControl(),
7543 mkU32(0x02000000)),
7544 binop(Iop_And32,
7545 getDSPControl(),
7546 mkU32(0xfdffffff))));
7548 assign(t3, binop(Iop_CmpLE32U,
7549 unop(Iop_8Uto32,
7550 unop(Iop_16to8,
7551 unop(Iop_32HIto16,
7552 getIReg(rs)))),
7553 unop(Iop_8Uto32,
7554 unop(Iop_16to8,
7555 unop(Iop_32HIto16,
7556 getIReg(rt))))));
7557 putDSPControl(IRExpr_ITE(mkexpr(t3),
7558 binop(Iop_Or32,
7559 getDSPControl(),
7560 mkU32(0x04000000)),
7561 binop(Iop_And32,
7562 getDSPControl(),
7563 mkU32(0xfbffffff))));
7565 assign(t4, binop(Iop_CmpLE32U,
7566 unop(Iop_8Uto32,
7567 unop(Iop_16HIto8,
7568 unop(Iop_32HIto16,
7569 getIReg(rs)))),
7570 unop(Iop_8Uto32,
7571 unop(Iop_16HIto8,
7572 unop(Iop_32HIto16,
7573 getIReg(rt))))));
7574 putDSPControl(IRExpr_ITE(mkexpr(t4),
7575 binop(Iop_Or32,
7576 getDSPControl(),
7577 mkU32(0x08000000)),
7578 binop(Iop_And32,
7579 getDSPControl(),
7580 mkU32(0xf7ffffff))));
7581 break;
7583 case 0x3: { /* PICK.QB */
7584 DIP("pick.qb r%u, r%u, r%u", rd, rs, rt);
7585 vassert(!mode64);
7586 t0 = newTemp(Ity_I32);
7587 t1 = newTemp(Ity_I8);
7588 t2 = newTemp(Ity_I8);
7589 t3 = newTemp(Ity_I8);
7590 t4 = newTemp(Ity_I8);
7592 assign(t0, getDSPControl());
7593 assign(t1, IRExpr_ITE(binop(Iop_CmpNE32,
7594 binop(Iop_And32,
7595 mkexpr(t0),
7596 mkU32(0x01000000)),
7597 mkU32(0x0)),
7598 unop(Iop_16to8,
7599 unop(Iop_32to16,
7600 getIReg(rs))),
7601 unop(Iop_16to8,
7602 unop(Iop_32to16,
7603 getIReg(rt)))));
7604 assign(t2, IRExpr_ITE(binop(Iop_CmpNE32,
7605 binop(Iop_And32,
7606 mkexpr(t0),
7607 mkU32(0x02000000)),
7608 mkU32(0x0)),
7609 unop(Iop_16HIto8,
7610 unop(Iop_32to16, getIReg(rs))),
7611 unop(Iop_16HIto8,
7612 unop(Iop_32to16,
7613 getIReg(rt)))));
7614 assign(t3, IRExpr_ITE(binop(Iop_CmpNE32,
7615 binop(Iop_And32,
7616 mkexpr(t0),
7617 mkU32(0x04000000)),
7618 mkU32(0x0)),
7619 unop(Iop_16to8,
7620 unop(Iop_32HIto16,
7621 getIReg(rs))),
7622 unop(Iop_16to8,
7623 unop(Iop_32HIto16,
7624 getIReg(rt)))));
7625 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
7626 binop(Iop_And32,
7627 mkexpr(t0),
7628 mkU32(0x08000000)),
7629 mkU32(0x0)),
7630 unop(Iop_16HIto8,
7631 unop(Iop_32HIto16,
7632 getIReg(rs))),
7633 unop(Iop_16HIto8,
7634 unop(Iop_32HIto16,
7635 getIReg(rt)))));
7636 putIReg(rd,
7637 binop(Iop_16HLto32,
7638 binop(Iop_8HLto16, mkexpr(t4), mkexpr(t3)),
7639 binop(Iop_8HLto16, mkexpr(t2), mkexpr(t1))));
7640 break;
7642 case 0x4: { /* CMPGU.EQ.QB */
7643 DIP("cmpgu.eq.qb r%u, r%u, r%u", rd, rs, rt);
7644 vassert(!mode64);
7645 t1 = newTemp(Ity_I1);
7646 t2 = newTemp(Ity_I1);
7647 t3 = newTemp(Ity_I1);
7648 t4 = newTemp(Ity_I1);
7649 t5 = newTemp(Ity_I32);
7650 t6 = newTemp(Ity_I32);
7651 t7 = newTemp(Ity_I32);
7652 t8 = newTemp(Ity_I32);
7654 assign(t1, binop(Iop_CmpEQ32,
7655 unop(Iop_8Uto32,
7656 unop(Iop_16to8,
7657 unop(Iop_32to16, getIReg(rs)))),
7658 unop(Iop_8Uto32,
7659 unop(Iop_16to8,
7660 unop(Iop_32to16,
7661 getIReg(rt))))));
7662 assign(t5, IRExpr_ITE(mkexpr(t1),
7663 mkU32(0x00000001), mkU32(0)));
7665 assign(t2, binop(Iop_CmpEQ32,
7666 unop(Iop_8Uto32,
7667 unop(Iop_16HIto8,
7668 unop(Iop_32to16, getIReg(rs)))),
7669 unop(Iop_8Uto32,
7670 unop(Iop_16HIto8,
7671 unop(Iop_32to16,
7672 getIReg(rt))))));
7673 assign(t6, IRExpr_ITE(mkexpr(t2),
7674 mkU32(0x00000002), mkU32(0)));
7676 assign(t3, binop(Iop_CmpEQ32,
7677 unop(Iop_8Uto32,
7678 unop(Iop_16to8,
7679 unop(Iop_32HIto16,
7680 getIReg(rs)))),
7681 unop(Iop_8Uto32,
7682 unop(Iop_16to8,
7683 unop(Iop_32HIto16,
7684 getIReg(rt))))));
7685 assign(t7, IRExpr_ITE(mkexpr(t3),
7686 mkU32(0x00000004), mkU32(0)));
7688 assign(t4, binop(Iop_CmpEQ32,
7689 unop(Iop_8Uto32,
7690 unop(Iop_16HIto8,
7691 unop(Iop_32HIto16,
7692 getIReg(rs)))),
7693 unop(Iop_8Uto32,
7694 unop(Iop_16HIto8,
7695 unop(Iop_32HIto16,
7696 getIReg(rt))))));
7697 assign(t8, IRExpr_ITE(mkexpr(t4),
7698 mkU32(0x00000008), mkU32(0)));
7700 putIReg(rd, binop(Iop_Or32,
7701 binop(Iop_Or32,
7702 binop(Iop_Or32,
7703 mkexpr(t5), mkexpr(t6)),
7704 mkexpr(t7)),
7705 mkexpr(t8)));
7706 break;
7708 case 0x5: { /* CMPGU.LT.QB */
7709 DIP("cmpgu.lt.qb r%u, r%u, r%u", rd, rs, rt);
7710 vassert(!mode64);
7711 t1 = newTemp(Ity_I1);
7712 t2 = newTemp(Ity_I1);
7713 t3 = newTemp(Ity_I1);
7714 t4 = newTemp(Ity_I1);
7715 t5 = newTemp(Ity_I32);
7716 t6 = newTemp(Ity_I32);
7717 t7 = newTemp(Ity_I32);
7718 t8 = newTemp(Ity_I32);
7720 assign(t1, binop(Iop_CmpLT32U,
7721 unop(Iop_8Uto32,
7722 unop(Iop_16to8,
7723 unop(Iop_32to16, getIReg(rs)))),
7724 unop(Iop_8Uto32,
7725 unop(Iop_16to8,
7726 unop(Iop_32to16,
7727 getIReg(rt))))));
7728 assign(t5, IRExpr_ITE(mkexpr(t1),
7729 mkU32(0x00000001), mkU32(0)));
7731 assign(t2, binop(Iop_CmpLT32U,
7732 unop(Iop_8Uto32,
7733 unop(Iop_16HIto8,
7734 unop(Iop_32to16, getIReg(rs)))),
7735 unop(Iop_8Uto32,
7736 unop(Iop_16HIto8,
7737 unop(Iop_32to16,
7738 getIReg(rt))))));
7739 assign(t6, IRExpr_ITE(mkexpr(t2),
7740 mkU32(0x00000002), mkU32(0)));
7742 assign(t3, binop(Iop_CmpLT32U,
7743 unop(Iop_8Uto32,
7744 unop(Iop_16to8,
7745 unop(Iop_32HIto16,
7746 getIReg(rs)))),
7747 unop(Iop_8Uto32,
7748 unop(Iop_16to8,
7749 unop(Iop_32HIto16,
7750 getIReg(rt))))));
7751 assign(t7, IRExpr_ITE(mkexpr(t3),
7752 mkU32(0x00000004), mkU32(0)));
7754 assign(t4, binop(Iop_CmpLT32U,
7755 unop(Iop_8Uto32,
7756 unop(Iop_16HIto8,
7757 unop(Iop_32HIto16,
7758 getIReg(rs)))),
7759 unop(Iop_8Uto32,
7760 unop(Iop_16HIto8,
7761 unop(Iop_32HIto16,
7762 getIReg(rt))))));
7763 assign(t8, IRExpr_ITE(mkexpr(t4),
7764 mkU32(0x00000008), mkU32(0)));
7765 putIReg(rd, binop(Iop_Or32,
7766 binop(Iop_Or32,
7767 binop(Iop_Or32,
7768 mkexpr(t5), mkexpr(t6)),
7769 mkexpr(t7)),
7770 mkexpr(t8)));
7771 break;
7773 case 0x6: { /* CMPGU.LE.QB */
7774 DIP("cmpgu.le.qb r%u, r%u, r%u", rd, rs, rt);
7775 vassert(!mode64);
7776 t1 = newTemp(Ity_I1);
7777 t2 = newTemp(Ity_I1);
7778 t3 = newTemp(Ity_I1);
7779 t4 = newTemp(Ity_I1);
7780 t5 = newTemp(Ity_I32);
7781 t6 = newTemp(Ity_I32);
7782 t7 = newTemp(Ity_I32);
7783 t8 = newTemp(Ity_I32);
7785 assign(t1, binop(Iop_CmpLE32U,
7786 unop(Iop_8Uto32,
7787 unop(Iop_16to8,
7788 unop(Iop_32to16, getIReg(rs)))),
7789 unop(Iop_8Uto32,
7790 unop(Iop_16to8,
7791 unop(Iop_32to16,
7792 getIReg(rt))))));
7793 assign(t5, IRExpr_ITE(mkexpr(t1),
7794 mkU32(0x00000001), mkU32(0)));
7796 assign(t2, binop(Iop_CmpLE32U,
7797 unop(Iop_8Uto32,
7798 unop(Iop_16HIto8,
7799 unop(Iop_32to16, getIReg(rs)))),
7800 unop(Iop_8Uto32,
7801 unop(Iop_16HIto8,
7802 unop(Iop_32to16,
7803 getIReg(rt))))));
7804 assign(t6, IRExpr_ITE(mkexpr(t2),
7805 mkU32(0x00000002), mkU32(0)));
7807 assign(t3, binop(Iop_CmpLE32U,
7808 unop(Iop_8Uto32,
7809 unop(Iop_16to8,
7810 unop(Iop_32HIto16,
7811 getIReg(rs)))),
7812 unop(Iop_8Uto32,
7813 unop(Iop_16to8,
7814 unop(Iop_32HIto16,
7815 getIReg(rt))))));
7816 assign(t7, IRExpr_ITE(mkexpr(t3),
7817 mkU32(0x00000004), mkU32(0)));
7819 assign(t4, binop(Iop_CmpLE32U,
7820 unop(Iop_8Uto32,
7821 unop(Iop_16HIto8,
7822 unop(Iop_32HIto16,
7823 getIReg(rs)))),
7824 unop(Iop_8Uto32,
7825 unop(Iop_16HIto8,
7826 unop(Iop_32HIto16,
7827 getIReg(rt))))));
7828 assign(t8, IRExpr_ITE(mkexpr(t4),
7829 mkU32(0x00000008), mkU32(0)));
7830 putIReg(rd, binop(Iop_Or32,
7831 binop(Iop_Or32,
7832 binop(Iop_Or32,
7833 mkexpr(t5), mkexpr(t6)),
7834 mkexpr(t7)),
7835 mkexpr(t8)));
7836 break;
7838 case 0x8: { /* CMP.EQ.PH */
7839 DIP("cmp.eq.ph r%u, r%u", rs, rt);
7840 vassert(!mode64);
7841 t1 = newTemp(Ity_I1);
7842 t2 = newTemp(Ity_I1);
7844 assign(t1, binop(Iop_CmpEQ16,
7845 unop(Iop_32to16, getIReg(rs)),
7846 unop(Iop_32to16, getIReg(rt))));
7847 putDSPControl(IRExpr_ITE(mkexpr(t1),
7848 binop(Iop_Or32,
7849 getDSPControl(),
7850 mkU32(0x01000000)),
7851 binop(Iop_And32,
7852 getDSPControl(),
7853 mkU32(0xfeffffff))));
7854 assign(t2, binop(Iop_CmpEQ16,
7855 unop(Iop_32HIto16, getIReg(rs)),
7856 unop(Iop_32HIto16, getIReg(rt))));
7857 putDSPControl(IRExpr_ITE(mkexpr(t2),
7858 binop(Iop_Or32,
7859 getDSPControl(),
7860 mkU32(0x02000000)),
7861 binop(Iop_And32,
7862 getDSPControl(),
7863 mkU32(0xfdffffff))));
7864 break;
7866 case 0x9: { /* CMP.LT.PH */
7867 DIP("cmp.lt.ph r%u, r%u", rs, rt);
7868 vassert(!mode64);
7869 t1 = newTemp(Ity_I1);
7870 t2 = newTemp(Ity_I1);
7872 assign(t1, binop(Iop_CmpLT32S,
7873 unop(Iop_16Sto32,
7874 unop(Iop_32to16, getIReg(rs))),
7875 unop(Iop_16Sto32,
7876 unop(Iop_32to16, getIReg(rt)))));
7877 putDSPControl(IRExpr_ITE(mkexpr(t1),
7878 binop(Iop_Or32,
7879 getDSPControl(),
7880 mkU32(0x01000000)),
7881 binop(Iop_And32,
7882 getDSPControl(),
7883 mkU32(0xfeffffff))));
7885 assign(t2, binop(Iop_CmpLT32S,
7886 unop(Iop_16Sto32,
7887 unop(Iop_32HIto16, getIReg(rs))),
7888 unop(Iop_16Sto32,
7889 unop(Iop_32HIto16, getIReg(rt)))));
7890 putDSPControl(IRExpr_ITE(mkexpr(t2),
7891 binop(Iop_Or32,
7892 getDSPControl(),
7893 mkU32(0x02000000)),
7894 binop(Iop_And32,
7895 getDSPControl(),
7896 mkU32(0xfdffffff))));
7897 break;
7899 case 0xA: { /* CMP.LE.PH */
7900 DIP("cmp.le.ph r%u, r%u", rs, rt);
7901 vassert(!mode64);
7902 t1 = newTemp(Ity_I1);
7903 t2 = newTemp(Ity_I1);
7905 assign(t1, binop(Iop_CmpLE32S,
7906 unop(Iop_16Sto32,
7907 unop(Iop_32to16, getIReg(rs))),
7908 unop(Iop_16Sto32,
7909 unop(Iop_32to16, getIReg(rt)))));
7910 putDSPControl(IRExpr_ITE(mkexpr(t1),
7911 binop(Iop_Or32,
7912 getDSPControl(),
7913 mkU32(0x01000000)),
7914 binop(Iop_And32,
7915 getDSPControl(),
7916 mkU32(0xfeffffff))));
7918 assign(t2, binop(Iop_CmpLE32S,
7919 unop(Iop_16Sto32,
7920 unop(Iop_32HIto16, getIReg(rs))),
7921 unop(Iop_16Sto32,
7922 unop(Iop_32HIto16, getIReg(rt)))));
7923 putDSPControl(IRExpr_ITE(mkexpr(t2),
7924 binop(Iop_Or32,
7925 getDSPControl(),
7926 mkU32(0x02000000)),
7927 binop(Iop_And32,
7928 getDSPControl(),
7929 mkU32(0xfdffffff))));
7930 break;
7932 case 0xB: { /* PICK.PH */
7933 DIP("pick.qb r%u, r%u, r%u", rd, rs, rt);
7934 vassert(!mode64);
7935 t0 = newTemp(Ity_I32);
7936 t1 = newTemp(Ity_I16);
7937 t2 = newTemp(Ity_I16);
7939 assign(t0, getDSPControl());
7941 assign(t1, IRExpr_ITE(binop(Iop_CmpNE32,
7942 binop(Iop_And32,
7943 mkexpr(t0),
7944 mkU32(0x01000000)),
7945 mkU32(0x0)),
7946 unop(Iop_32to16, getIReg(rs)),
7947 unop(Iop_32to16, getIReg(rt))));
7949 assign(t2, IRExpr_ITE(binop(Iop_CmpNE32,
7950 binop(Iop_And32,
7951 mkexpr(t0),
7952 mkU32(0x02000000)),
7953 mkU32(0x0)),
7954 unop(Iop_32HIto16, getIReg(rs)),
7955 unop(Iop_32HIto16, getIReg(rt))));
7957 putIReg(rd, binop(Iop_16HLto32, mkexpr(t2), mkexpr(t1)));
7958 break;
7960 case 0xC: { /* PRECRQ.QB.PH */
7961 DIP("precrq.qb.ph r%u, r%u, %u", rd, rs, rt);
7962 vassert(!mode64);
7963 putIReg(rd,
7964 binop(Iop_16HLto32,
7965 binop(Iop_8HLto16,
7966 unop(Iop_16HIto8,
7967 unop(Iop_32HIto16, getIReg(rs))),
7968 unop(Iop_16HIto8,
7969 unop(Iop_32to16, getIReg(rs)))),
7970 binop(Iop_8HLto16,
7971 unop(Iop_16HIto8,
7972 unop(Iop_32HIto16, getIReg(rt))),
7973 unop(Iop_16HIto8,
7974 unop(Iop_32to16, getIReg(rt))))));
7975 break;
7977 case 0xD: { /* PRECR.QB.PH */
7978 DIP("precr.qb.ph r%u, r%u, r%u", rd, rs, rt);
7979 vassert(!mode64);
7981 putIReg(rd,
7982 binop(Iop_16HLto32,
7983 binop(Iop_8HLto16,
7984 unop(Iop_16to8,
7985 unop(Iop_32HIto16, getIReg(rs))),
7986 unop(Iop_16to8,
7987 unop(Iop_32to16, getIReg(rs)))),
7988 binop(Iop_8HLto16,
7989 unop(Iop_16to8,
7990 unop(Iop_32HIto16, getIReg(rt))),
7991 unop(Iop_16to8,
7992 unop(Iop_32to16, getIReg(rt))))));
7993 break;
7995 case 0xF: { /* PRECRQU_S.QB.PH */
7996 DIP("precrqu_s.qb.ph r%u, r%u, %u", rd, rs, rt);
7997 vassert(!mode64);
7998 t0 = newTemp(Ity_I8);
7999 t1 = newTemp(Ity_I8);
8000 t2 = newTemp(Ity_I8);
8001 t3 = newTemp(Ity_I8);
8002 t4 = newTemp(Ity_I8);
8003 t5 = newTemp(Ity_I32);
8004 t6 = newTemp(Ity_I1);
8005 t7 = newTemp(Ity_I8);
8006 t8 = newTemp(Ity_I1);
8007 t9 = newTemp(Ity_I32);
8008 t10 = newTemp(Ity_I8);
8009 t11 = newTemp(Ity_I1);
8010 t12 = newTemp(Ity_I32);
8011 t13 = newTemp(Ity_I8);
8012 t14 = newTemp(Ity_I1);
8013 t15 = newTemp(Ity_I32);
8015 assign(t4, IRExpr_ITE(binop(Iop_CmpLT32U,
8016 mkU32(0x7f80),
8017 binop(Iop_And32,
8018 unop(Iop_16Uto32,
8019 unop(Iop_32to16,
8020 getIReg(rs))),
8021 mkU32(0x7fff))),
8022 mkU8(0xff),
8023 unop(Iop_16HIto8,
8024 unop(Iop_32to16,
8025 binop(Iop_Shl32,
8026 getIReg(rs),
8027 mkU8(1))))));
8028 assign(t0, IRExpr_ITE(binop(Iop_CmpEQ32,
8029 binop(Iop_And32,
8030 unop(Iop_16Uto32,
8031 unop(Iop_32to16,
8032 getIReg(rs))),
8033 mkU32(0x00008000)),
8034 mkU32(0x0)),
8035 mkexpr(t4),
8036 mkU8(0x0)));
8037 assign(t5, binop(Iop_And32,
8038 unop(Iop_16Uto32,
8039 unop(Iop_32to16,
8040 getIReg(rs))),
8041 mkU32(0x00008000)));
8042 assign(t6, binop(Iop_CmpLT32U,
8043 mkU32(0x7f80),
8044 binop(Iop_And32,
8045 unop(Iop_16Uto32,
8046 unop(Iop_32to16,
8047 getIReg(rs))),
8048 mkU32(0x7fff))));
8049 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
8050 mkexpr(t5),
8051 mkU32(0x0)),
8052 IRExpr_ITE(mkexpr(t6),
8053 binop(Iop_Or32,
8054 getDSPControl(),
8055 mkU32(0x00400000)
8057 getDSPControl()),
8058 binop(Iop_Or32,
8059 getDSPControl(),
8060 mkU32(0x00400000))));
8062 assign(t7, IRExpr_ITE(binop(Iop_CmpLT32U,
8063 mkU32(0x7f80),
8064 binop(Iop_And32,
8065 unop(Iop_16Uto32,
8066 unop(Iop_32HIto16,
8067 getIReg(rs))),
8068 mkU32(0x7fff))),
8069 mkU8(0xff),
8070 unop(Iop_16HIto8,
8071 unop(Iop_32HIto16,
8072 binop(Iop_Shl32,
8073 getIReg(rs),
8074 mkU8(1))))));
8075 assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32,
8076 binop(Iop_And32,
8077 unop(Iop_16Uto32,
8078 unop(Iop_32HIto16,
8079 getIReg(rs))),
8080 mkU32(0x00008000)),
8081 mkU32(0x0)),
8082 mkexpr(t7),
8083 mkU8(0x0)));
8084 assign(t8, binop(Iop_CmpEQ32,
8085 binop(Iop_And32,
8086 unop(Iop_16Uto32,
8087 unop(Iop_32HIto16,
8088 getIReg(rs))),
8089 mkU32(0x00008000)),
8090 mkU32(0x0)));
8091 assign(t9, IRExpr_ITE(binop(Iop_CmpLT32U,
8092 mkU32(0x7f80),
8093 binop(Iop_And32,
8094 unop(Iop_16Uto32,
8095 unop(Iop_32HIto16,
8096 getIReg(rs))),
8097 mkU32(0x7fff))),
8098 binop(Iop_Or32,
8099 getDSPControl(),
8100 mkU32(0x00400000)),
8101 getDSPControl()));
8102 putDSPControl(IRExpr_ITE(mkexpr(t8),
8103 mkexpr(t9),
8104 binop(Iop_Or32,
8105 getDSPControl(),
8106 mkU32(0x00400000))));
8108 assign(t10, IRExpr_ITE(binop(Iop_CmpLT32U,
8109 mkU32(0x7f80),
8110 binop(Iop_And32,
8111 unop(Iop_16Uto32,
8112 unop(Iop_32to16,
8113 getIReg(rt))),
8114 mkU32(0x7fff))),
8115 mkU8(0xff),
8116 unop(Iop_16HIto8,
8117 unop(Iop_32to16,
8118 binop(Iop_Shl32,
8119 getIReg(rt),
8120 mkU8(1))))));
8121 assign(t2, IRExpr_ITE(binop(Iop_CmpEQ32,
8122 binop(Iop_And32,
8123 unop(Iop_16Uto32,
8124 unop(Iop_32to16,
8125 getIReg(rt))),
8126 mkU32(0x00008000)),
8127 mkU32(0x0)),
8128 mkexpr(t10),
8129 mkU8(0x0)));
8130 assign(t11, binop(Iop_CmpEQ32,
8131 binop(Iop_And32,
8132 unop(Iop_16Uto32,
8133 unop(Iop_32to16,
8134 getIReg(rt))),
8135 mkU32(0x00008000)),
8136 mkU32(0x0)));
8137 assign(t12, IRExpr_ITE(binop(Iop_CmpLT32U,
8138 mkU32(0x7f80),
8139 binop(Iop_And32,
8140 unop(Iop_16Uto32,
8141 unop(Iop_32to16,
8142 getIReg(rt))),
8143 mkU32(0x7fff))),
8144 binop(Iop_Or32,
8145 getDSPControl(),
8146 mkU32(0x00400000)),
8147 getDSPControl()));
8148 putDSPControl(IRExpr_ITE(mkexpr(t11),
8149 mkexpr(t12),
8150 binop(Iop_Or32,
8151 getDSPControl(),
8152 mkU32(0x00400000))));
8154 assign(t13, IRExpr_ITE(binop(Iop_CmpLT32U,
8155 mkU32(0x7f80),
8156 binop(Iop_And32,
8157 unop(Iop_16Uto32,
8158 unop(Iop_32HIto16,
8159 getIReg(rt))),
8160 mkU32(0x7fff))),
8161 mkU8(0xff),
8162 unop(Iop_16HIto8,
8163 unop(Iop_32HIto16,
8164 binop(Iop_Shl32,
8165 getIReg(rt),
8166 mkU8(1))))));
8167 assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
8168 binop(Iop_And32,
8169 unop(Iop_16Uto32,
8170 unop(Iop_32HIto16,
8171 getIReg(rt))),
8172 mkU32(0x00008000)),
8173 mkU32(0x0)),
8174 mkexpr(t13),
8175 mkU8(0x0)));
8176 assign(t14, binop(Iop_CmpEQ32,
8177 binop(Iop_And32,
8178 unop(Iop_16Uto32,
8179 unop(Iop_32HIto16,
8180 getIReg(rt))),
8181 mkU32(0x00008000)),
8182 mkU32(0x0)));
8183 assign(t15, IRExpr_ITE(binop(Iop_CmpLT32U,
8184 mkU32(0x7f80),
8185 binop(Iop_And32,
8186 unop(Iop_16Uto32,
8187 unop(Iop_32HIto16,
8188 getIReg(rt))),
8189 mkU32(0x7fff))),
8190 binop(Iop_Or32,
8191 getDSPControl(),
8192 mkU32(0x00400000)),
8193 getDSPControl()));
8194 putDSPControl(IRExpr_ITE(mkexpr(t14),
8195 mkexpr(t15),
8196 binop(Iop_Or32,
8197 getDSPControl(),
8198 mkU32(0x00400000))));
8200 putIReg(rd, binop(Iop_16HLto32,
8201 binop(Iop_8HLto16,
8202 mkexpr(t1), mkexpr(t0)),
8203 binop(Iop_8HLto16,
8204 mkexpr(t3), mkexpr(t2))));
8205 break;
8207 case 0x14: { /* PRECRQ.PH.W */
8208 DIP("precrq.ph.w r%u, r%u, %u", rd, rs, rt);
8209 vassert(!mode64);
8210 putIReg(rd, binop(Iop_16HLto32,
8211 unop(Iop_32HIto16, getIReg(rs)),
8212 unop(Iop_32HIto16, getIReg(rt))));
8213 break;
8215 case 0x15: { /* PRECRQ_RS.PH.W */
8216 DIP("precrq_rs.ph.w r%u, r%u, %u", rd, rs, rt);
8217 vassert(!mode64);
8218 t0 = newTemp(Ity_I64);
8219 t1 = newTemp(Ity_I1);
8220 t2 = newTemp(Ity_I32);
8221 t3 = newTemp(Ity_I64);
8222 t4 = newTemp(Ity_I1);
8223 t5 = newTemp(Ity_I32);
8225 assign(t0, binop(Iop_Add64,
8226 binop(Iop_32HLto64,
8227 binop(Iop_Shr32,
8228 binop(Iop_And32,
8229 getIReg(rs),
8230 mkU32(0x80000000)),
8231 mkU8(31)),
8232 getIReg(rs)),
8233 mkU64(0x0000000000008000ULL)));
8234 assign(t1, binop(Iop_CmpNE32,
8235 binop(Iop_And32,
8236 unop(Iop_64HIto32, mkexpr(t0)),
8237 mkU32(0x1)),
8238 binop(Iop_And32,
8239 binop(Iop_Shr32,
8240 unop(Iop_64to32, mkexpr(t0)),
8241 mkU8(31)),
8242 mkU32(0x1))));
8243 assign(t2, IRExpr_ITE(mkexpr(t1),
8244 mkU32(0x7fffffff),
8245 unop(Iop_64to32, mkexpr(t0))));
8246 putDSPControl(IRExpr_ITE(mkexpr(t1),
8247 binop(Iop_Or32,
8248 getDSPControl(),
8249 mkU32(0x400000)),
8250 getDSPControl()));
8251 assign(t3, binop(Iop_Add64,
8252 binop(Iop_32HLto64,
8253 binop(Iop_Shr32,
8254 binop(Iop_And32,
8255 getIReg(rt),
8256 mkU32(0x80000000)),
8257 mkU8(31)),
8258 getIReg(rt)),
8259 mkU64(0x0000000000008000ULL)));
8260 assign(t4, binop(Iop_CmpNE32,
8261 binop(Iop_And32,
8262 unop(Iop_64HIto32, mkexpr(t3)),
8263 mkU32(0x1)),
8264 binop(Iop_And32,
8265 binop(Iop_Shr32,
8266 unop(Iop_64to32, mkexpr(t3)),
8267 mkU8(31)),
8268 mkU32(0x1))));
8269 assign(t5, IRExpr_ITE(mkexpr(t4),
8270 mkU32(0x7fffffff),
8271 unop(Iop_64to32, mkexpr(t3))));
8272 putDSPControl(IRExpr_ITE(mkexpr(t4),
8273 binop(Iop_Or32,
8274 getDSPControl(),
8275 mkU32(0x400000)),
8276 getDSPControl()));
8277 putIReg(rd, binop(Iop_16HLto32,
8278 unop(Iop_32HIto16, mkexpr(t2)),
8279 unop(Iop_32HIto16, mkexpr(t5))));
8280 break;
8282 case 0x1E: { /* PRECR_SRA.PH.W */
8283 DIP("precr_sra.ph.w r%u, r%u, %u", rt, rs, rd);
8284 vassert(!mode64);
8286 if (0 == rd) {
8287 putIReg(rt, binop(Iop_16HLto32,
8288 unop(Iop_32to16, getIReg(rt)),
8289 unop(Iop_32to16, getIReg(rs))));
8290 } else {
8291 putIReg(rt, binop(Iop_16HLto32,
8292 unop(Iop_32to16, binop(Iop_Sar32,
8293 getIReg(rt),
8294 mkU8(rd))),
8295 unop(Iop_32to16, binop(Iop_Sar32,
8296 getIReg(rs),
8297 mkU8(rd)))));
8299 break;
8301 case 0x1F: { /* PRECR_SRA_R.PH.W */
8302 DIP("precr_sra_r.ph.w r%u, r%u, %u", rt, rs, rd);
8303 vassert(!mode64);
8305 t0 = newTemp(Ity_I32);
8306 t1 = newTemp(Ity_I32);
8308 if (0 == rd) {
8309 putIReg(rt, binop(Iop_16HLto32,
8310 unop(Iop_32to16, getIReg(rt)),
8311 unop(Iop_32to16, getIReg(rs))));
8312 } else {
8313 assign(t0, binop(Iop_Shr32,
8314 binop(Iop_Add32,
8315 binop(Iop_Sar32,
8316 getIReg(rt),
8317 mkU8(rd-1)),
8318 mkU32(0x1)),
8319 mkU8(0x1)));
8320 assign(t1, binop(Iop_Shr32,
8321 binop(Iop_Add32,
8322 binop(Iop_Sar32,
8323 getIReg(rs),
8324 mkU8(rd-1)),
8325 mkU32(0x1)),
8326 mkU8(0x1)));
8327 putIReg(rt, binop(Iop_16HLto32,
8328 unop(Iop_32to16, mkexpr(t0)),
8329 unop(Iop_32to16, mkexpr(t1))));
8331 break;
8333 case 0xE: { /* PACKRL.PH */
8334 DIP("packrl.ph r%u, r%u, r%u", rd, rs, rt);
8335 vassert(!mode64);
8337 putIReg(rd, binop(Iop_16HLto32,
8338 unop(Iop_32to16, getIReg(rs)),
8339 unop(Iop_32HIto16, getIReg(rt))));
8340 break;
8342 case 0x18: { /* CMPGDU.EQ.QB */
8343 DIP("cmpgdu.eq.qb r%u, r%u, r%u", rd, rs, rt);
8344 vassert(!mode64);
8345 t1 = newTemp(Ity_I1);
8346 t2 = newTemp(Ity_I1);
8347 t3 = newTemp(Ity_I1);
8348 t4 = newTemp(Ity_I1);
8349 t5 = newTemp(Ity_I32);
8350 t6 = newTemp(Ity_I32);
8351 t7 = newTemp(Ity_I32);
8352 t8 = newTemp(Ity_I32);
8354 assign(t1,
8355 binop(Iop_CmpEQ32,
8356 unop(Iop_8Uto32,
8357 unop(Iop_16to8,
8358 unop(Iop_32to16, getIReg(rs)))),
8359 unop(Iop_8Uto32,
8360 unop(Iop_16to8,
8361 unop(Iop_32to16, getIReg(rt))))));
8362 assign(t5, IRExpr_ITE(mkexpr(t1),
8363 mkU32(0x00000001), mkU32(0)));
8364 putDSPControl(IRExpr_ITE(mkexpr(t1),
8365 binop(Iop_Or32,
8366 getDSPControl(),
8367 mkU32(0x01000000)),
8368 binop(Iop_And32,
8369 getDSPControl(),
8370 mkU32(0xfeffffff))));
8372 assign(t2, binop(Iop_CmpEQ32,
8373 unop(Iop_8Uto32,
8374 unop(Iop_16HIto8,
8375 unop(Iop_32to16, getIReg(rs)))),
8376 unop(Iop_8Uto32,
8377 unop(Iop_16HIto8,
8378 unop(Iop_32to16,
8379 getIReg(rt))))));
8380 assign(t6, IRExpr_ITE(mkexpr(t2),
8381 mkU32(0x00000002), mkU32(0)));
8382 putDSPControl(IRExpr_ITE(mkexpr(t2),
8383 binop(Iop_Or32,
8384 getDSPControl(),
8385 mkU32(0x02000000)),
8386 binop(Iop_And32,
8387 getDSPControl(),
8388 mkU32(0xfdffffff))));
8390 assign(t3, binop(Iop_CmpEQ32,
8391 unop(Iop_8Uto32,
8392 unop(Iop_16to8,
8393 unop(Iop_32HIto16,
8394 getIReg(rs)))),
8395 unop(Iop_8Uto32,
8396 unop(Iop_16to8,
8397 unop(Iop_32HIto16,
8398 getIReg(rt))))));
8399 assign(t7, IRExpr_ITE(mkexpr(t3),
8400 mkU32(0x00000004), mkU32(0)));
8401 putDSPControl(IRExpr_ITE(mkexpr(t3),
8402 binop(Iop_Or32,
8403 getDSPControl(),
8404 mkU32(0x04000000)),
8405 binop(Iop_And32,
8406 getDSPControl(),
8407 mkU32(0xfbffffff))));
8409 assign(t4, binop(Iop_CmpEQ32,
8410 unop(Iop_8Uto32,
8411 unop(Iop_16HIto8,
8412 unop(Iop_32HIto16,
8413 getIReg(rs)))),
8414 unop(Iop_8Uto32,
8415 unop(Iop_16HIto8,
8416 unop(Iop_32HIto16,
8417 getIReg(rt))))));
8418 assign(t8, IRExpr_ITE(mkexpr(t4),
8419 mkU32(0x00000008), mkU32(0)));
8420 putDSPControl(IRExpr_ITE(mkexpr(t4),
8421 binop(Iop_Or32,
8422 getDSPControl(),
8423 mkU32(0x08000000)),
8424 binop(Iop_And32,
8425 getDSPControl(),
8426 mkU32(0xf7ffffff))));
8428 putIReg(rd, binop(Iop_Or32,
8429 binop(Iop_Or32,
8430 binop(Iop_Or32,
8431 mkexpr(t5), mkexpr(t6)),
8432 mkexpr(t7)),
8433 mkexpr(t8)));
8434 break;
8436 case 0x19: { /* CMPGDU.LT.QB */
8437 DIP("cmpgdu.lt.qb r%u, r%u, r%u", rd, rs, rt);
8438 vassert(!mode64);
8439 t1 = newTemp(Ity_I1);
8440 t2 = newTemp(Ity_I1);
8441 t3 = newTemp(Ity_I1);
8442 t4 = newTemp(Ity_I1);
8443 t5 = newTemp(Ity_I32);
8444 t6 = newTemp(Ity_I32);
8445 t7 = newTemp(Ity_I32);
8446 t8 = newTemp(Ity_I32);
8448 assign(t1, binop(Iop_CmpLT32U,
8449 unop(Iop_8Uto32,
8450 unop(Iop_16to8,
8451 unop(Iop_32to16, getIReg(rs)))),
8452 unop(Iop_8Uto32,
8453 unop(Iop_16to8,
8454 unop(Iop_32to16,
8455 getIReg(rt))))));
8456 assign(t5, IRExpr_ITE(mkexpr(t1),
8457 mkU32(0x00000001), mkU32(0)));
8458 putDSPControl(IRExpr_ITE(mkexpr(t1),
8459 binop(Iop_Or32,
8460 getDSPControl(),
8461 mkU32(0x01000000)),
8462 binop(Iop_And32,
8463 getDSPControl(),
8464 mkU32(0xfeffffff))));
8466 assign(t2, binop(Iop_CmpLT32U,
8467 unop(Iop_8Uto32,
8468 unop(Iop_16HIto8,
8469 unop(Iop_32to16, getIReg(rs)))),
8470 unop(Iop_8Uto32,
8471 unop(Iop_16HIto8,
8472 unop(Iop_32to16,
8473 getIReg(rt))))));
8474 assign(t6, IRExpr_ITE(mkexpr(t2),
8475 mkU32(0x00000002), mkU32(0)));
8476 putDSPControl(IRExpr_ITE(mkexpr(t2),
8477 binop(Iop_Or32,
8478 getDSPControl(),
8479 mkU32(0x02000000)),
8480 binop(Iop_And32,
8481 getDSPControl(),
8482 mkU32(0xfdffffff))));
8484 assign(t3, binop(Iop_CmpLT32U,
8485 unop(Iop_8Uto32,
8486 unop(Iop_16to8,
8487 unop(Iop_32HIto16,
8488 getIReg(rs)))),
8489 unop(Iop_8Uto32,
8490 unop(Iop_16to8,
8491 unop(Iop_32HIto16,
8492 getIReg(rt))))));
8493 assign(t7, IRExpr_ITE(mkexpr(t3),
8494 mkU32(0x00000004), mkU32(0)));
8495 putDSPControl(IRExpr_ITE(mkexpr(t3),
8496 binop(Iop_Or32,
8497 getDSPControl(),
8498 mkU32(0x04000000)),
8499 binop(Iop_And32,
8500 getDSPControl(),
8501 mkU32(0xfbffffff))));
8503 assign(t4, binop(Iop_CmpLT32U,
8504 unop(Iop_8Uto32,
8505 unop(Iop_16HIto8,
8506 unop(Iop_32HIto16,
8507 getIReg(rs)))),
8508 unop(Iop_8Uto32,
8509 unop(Iop_16HIto8,
8510 unop(Iop_32HIto16,
8511 getIReg(rt))))));
8512 assign(t8, IRExpr_ITE(mkexpr(t4),
8513 mkU32(0x00000008), mkU32(0)));
8514 putDSPControl(IRExpr_ITE(mkexpr(t4),
8515 binop(Iop_Or32,
8516 getDSPControl(),
8517 mkU32(0x08000000)),
8518 binop(Iop_And32,
8519 getDSPControl(),
8520 mkU32(0xf7ffffff))));
8522 putIReg(rd, binop(Iop_Or32,
8523 binop(Iop_Or32,
8524 binop(Iop_Or32,
8525 mkexpr(t5), mkexpr(t6)),
8526 mkexpr(t7)),
8527 mkexpr(t8)));
8528 break;
8530 case 0x1A: { /* CMPGDU.LE.QB */
8531 DIP("cmpgdu.le.qb r%u, r%u, r%u", rd, rs, rt);
8532 vassert(!mode64);
8533 t1 = newTemp(Ity_I1);
8534 t2 = newTemp(Ity_I1);
8535 t3 = newTemp(Ity_I1);
8536 t4 = newTemp(Ity_I1);
8537 t5 = newTemp(Ity_I32);
8538 t6 = newTemp(Ity_I32);
8539 t7 = newTemp(Ity_I32);
8540 t8 = newTemp(Ity_I32);
8542 assign(t1, binop(Iop_CmpLE32U,
8543 unop(Iop_8Uto32,
8544 unop(Iop_16to8,
8545 unop(Iop_32to16, getIReg(rs)))),
8546 unop(Iop_8Uto32,
8547 unop(Iop_16to8,
8548 unop(Iop_32to16,
8549 getIReg(rt))))));
8550 assign(t5, IRExpr_ITE(mkexpr(t1),
8551 mkU32(0x00000001),
8552 mkU32(0)));
8553 putDSPControl(IRExpr_ITE(mkexpr(t1),
8554 binop(Iop_Or32,
8555 getDSPControl(),
8556 mkU32(0x01000000)),
8557 binop(Iop_And32,
8558 getDSPControl(),
8559 mkU32(0xfeffffff))));
8561 assign(t2, binop(Iop_CmpLE32U,
8562 unop(Iop_8Uto32,
8563 unop(Iop_16HIto8,
8564 unop(Iop_32to16, getIReg(rs)))),
8565 unop(Iop_8Uto32,
8566 unop(Iop_16HIto8,
8567 unop(Iop_32to16,
8568 getIReg(rt))))));
8569 assign(t6, IRExpr_ITE(mkexpr(t2),
8570 mkU32(0x00000002), mkU32(0)));
8571 putDSPControl(IRExpr_ITE(mkexpr(t2),
8572 binop(Iop_Or32,
8573 getDSPControl(),
8574 mkU32(0x02000000)),
8575 binop(Iop_And32,
8576 getDSPControl(),
8577 mkU32(0xfdffffff))));
8579 assign(t3, binop(Iop_CmpLE32U,
8580 unop(Iop_8Uto32,
8581 unop(Iop_16to8,
8582 unop(Iop_32HIto16,
8583 getIReg(rs)))),
8584 unop(Iop_8Uto32,
8585 unop(Iop_16to8,
8586 unop(Iop_32HIto16,
8587 getIReg(rt))))));
8588 assign(t7, IRExpr_ITE(mkexpr(t3),
8589 mkU32(0x00000004), mkU32(0)));
8590 putDSPControl(IRExpr_ITE(mkexpr(t3),
8591 binop(Iop_Or32,
8592 getDSPControl(),
8593 mkU32(0x04000000)),
8594 binop(Iop_And32,
8595 getDSPControl(),
8596 mkU32(0xfbffffff))));
8598 assign(t4, binop(Iop_CmpLE32U,
8599 unop(Iop_8Uto32,
8600 unop(Iop_16HIto8,
8601 unop(Iop_32HIto16,
8602 getIReg(rs)))),
8603 unop(Iop_8Uto32,
8604 unop(Iop_16HIto8,
8605 unop(Iop_32HIto16,
8606 getIReg(rt))))));
8607 assign(t8, IRExpr_ITE(mkexpr(t4),
8608 mkU32(0x00000008), mkU32(0)));
8609 putDSPControl(IRExpr_ITE(mkexpr(t4),
8610 binop(Iop_Or32,
8611 getDSPControl(),
8612 mkU32(0x08000000)),
8613 binop(Iop_And32,
8614 getDSPControl(),
8615 mkU32(0xf7ffffff))));
8617 putIReg(rd, binop(Iop_Or32,
8618 binop(Iop_Or32,
8619 binop(Iop_Or32,
8620 mkexpr(t5), mkexpr(t6)),
8621 mkexpr(t7)),
8622 mkexpr(t8)));
8623 break;
8625 default:
8626 return -1;
8628 break; /* end of CMPU.EQ.QB */
8630 case 0x13: { /* SHLL.QB */
8631 switch(sa) {
8632 case 0x0: { /* SHLL.QB */
8633 DIP("shll.qb r%u, r%u, %u", rd, rt, rs);
8634 vassert(!mode64);
8635 t0 = newTemp(Ity_I32);
8636 t1 = newTemp(Ity_I1);
8637 t2 = newTemp(Ity_I1);
8638 t3 = newTemp(Ity_I32);
8639 t4 = newTemp(Ity_I1);
8640 t5 = newTemp(Ity_I1);
8641 t6 = newTemp(Ity_I32);
8642 t7 = newTemp(Ity_I1);
8643 t8 = newTemp(Ity_I1);
8644 t9 = newTemp(Ity_I1);
8645 t10 = newTemp(Ity_I1);
8647 if (0 == rs) {
8648 putIReg(rd, getIReg(rt));
8649 } else {
8650 /* Shift bits 7..0 and 23..16. */
8651 assign(t0, binop(Iop_Shl32,
8652 binop(Iop_And32,
8653 getIReg(rt),
8654 mkU32(0x00ff00ff)),
8655 mkU8(rs)));
8656 assign(t1, binop(Iop_CmpNE32,
8657 binop(Iop_And32,
8658 mkexpr(t0),
8659 mkU32(0xff000000)),
8660 mkU32(0x00000000)));
8661 assign(t2, binop(Iop_CmpNE32,
8662 binop(Iop_And32,
8663 mkexpr(t0),
8664 mkU32(0xff000000)),
8665 mkU32(0xff000000)));
8666 assign(t7, binop(Iop_CmpNE32,
8667 binop(Iop_And32,
8668 mkexpr(t0),
8669 mkU32(0x0000ff00)),
8670 mkU32(0x00000000)));
8671 assign(t8, binop(Iop_CmpNE32,
8672 binop(Iop_And32,
8673 mkexpr(t0),
8674 mkU32(0x0000ff00)),
8675 mkU32(0x000ff00)));
8676 /* Shift bits 15..8 and 31..24. */
8677 assign(t3, binop(Iop_Shl32,
8678 binop(Iop_Shr32,
8679 binop(Iop_And32,
8680 getIReg(rt),
8681 mkU32(0xff00ff00)),
8682 mkU8(8)),
8683 mkU8(rs)));
8684 assign(t4, binop(Iop_CmpNE32,
8685 binop(Iop_And32,
8686 mkexpr(t3),
8687 mkU32(0xff000000)),
8688 mkU32(0x00000000)));
8689 assign(t5, binop(Iop_CmpNE32,
8690 binop(Iop_And32,
8691 mkexpr(t3),
8692 mkU32(0xff000000)),
8693 mkU32(0xff000000)));
8694 assign(t9, binop(Iop_CmpNE32,
8695 binop(Iop_And32,
8696 mkexpr(t3),
8697 mkU32(0x0000ff00)),
8698 mkU32(0x00000000)));
8699 assign(t10, binop(Iop_CmpNE32,
8700 binop(Iop_And32,
8701 mkexpr(t3),
8702 mkU32(0x0000ff00)),
8703 mkU32(0x0000ff00)));
8705 assign(t6, binop(Iop_Or32,
8706 binop(Iop_Or32,
8707 binop(Iop_And32,
8708 unop(Iop_1Uto32,
8709 mkexpr(t1)),
8710 unop(Iop_1Uto32,
8711 mkexpr(t2))),
8712 binop(Iop_And32,
8713 unop(Iop_1Uto32,
8714 mkexpr(t7)),
8715 unop(Iop_1Uto32,
8716 mkexpr(t8)))),
8717 binop(Iop_Or32,
8718 binop(Iop_And32,
8719 unop(Iop_1Uto32,
8720 mkexpr(t4)),
8721 unop(Iop_1Uto32,
8722 mkexpr(t5))),
8723 binop(Iop_And32,
8724 unop(Iop_1Uto32,
8725 mkexpr(t9)),
8726 unop(Iop_1Uto32,
8727 mkexpr(t10))))));
8729 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
8730 mkexpr(t6),
8731 mkU32(0x0)),
8732 binop(Iop_Or32,
8733 getDSPControl(),
8734 mkU32(0x400000)),
8735 getDSPControl()));
8736 putIReg(rd, binop(Iop_Or32,
8737 binop(Iop_Shl32,
8738 binop(Iop_And32,
8739 mkexpr(t3),
8740 mkU32(0x00ff00ff)),
8741 mkU8(8)),
8742 binop(Iop_And32,
8743 mkexpr(t0),
8744 mkU32(0x00ff00ff))));
8746 break;
8748 case 0x3: { /* SHRL.QB */
8749 DIP("shrl.qb r%u, r%u, %u", rd, rt, rs);
8750 vassert(!mode64);
8751 t0 = newTemp(Ity_I32);
8752 t1 = newTemp(Ity_I8);
8753 t2 = newTemp(Ity_I32);
8754 t3 = newTemp(Ity_I8);
8755 t4 = newTemp(Ity_I32);
8756 t5 = newTemp(Ity_I8);
8757 t6 = newTemp(Ity_I32);
8758 t7 = newTemp(Ity_I8);
8759 t9 = newTemp(Ity_I32);
8761 assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7)));
8762 assign(t0, unop(Iop_8Uto32,
8763 unop(Iop_16to8,
8764 unop(Iop_32to16, getIReg(rt)))));
8765 assign(t1, unop(Iop_32to8,
8766 binop(Iop_Shr32,
8767 mkexpr(t0),
8768 unop(Iop_32to8, mkexpr(t9)))));
8770 assign(t2, unop(Iop_8Uto32,
8771 unop(Iop_16HIto8,
8772 unop(Iop_32to16, getIReg(rt)))));
8773 assign(t3, unop(Iop_32to8,
8774 binop(Iop_Shr32,
8775 mkexpr(t2),
8776 unop(Iop_32to8, mkexpr(t9)))));
8778 assign(t4, unop(Iop_8Uto32,
8779 unop(Iop_16to8,
8780 unop(Iop_32HIto16, getIReg(rt)))));
8781 assign(t5, unop(Iop_32to8,
8782 binop(Iop_Shr32,
8783 mkexpr(t4),
8784 unop(Iop_32to8, mkexpr(t9)))));
8786 assign(t6, unop(Iop_8Uto32,
8787 unop(Iop_16HIto8,
8788 unop(Iop_32HIto16, getIReg(rt)))));
8789 assign(t7, unop(Iop_32to8,
8790 binop(Iop_Shr32,
8791 mkexpr(t6),
8792 unop(Iop_32to8, mkexpr(t9)))));
8793 putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
8794 mkexpr(t9),
8795 mkU32(0x0)),
8796 getIReg(rt),
8797 binop(Iop_16HLto32,
8798 binop(Iop_8HLto16,
8799 mkexpr(t7),
8800 mkexpr(t5)),
8801 binop(Iop_8HLto16,
8802 mkexpr(t3),
8803 mkexpr(t1)))));
8804 break;
8806 case 0x2: { /* SHLLV.QB */
8807 DIP("shllv.qb r%u, r%u, r%u", rd, rt, rs);
8808 vassert(!mode64);
8809 t0 = newTemp(Ity_I32);
8810 t1 = newTemp(Ity_I1);
8811 t2 = newTemp(Ity_I1);
8812 t3 = newTemp(Ity_I32);
8813 t4 = newTemp(Ity_I1);
8814 t5 = newTemp(Ity_I1);
8815 t6 = newTemp(Ity_I32);
8816 t7 = newTemp(Ity_I1);
8817 t8 = newTemp(Ity_I1);
8818 t9 = newTemp(Ity_I1);
8819 t10 = newTemp(Ity_I1);
8820 t11 = newTemp(Ity_I8);
8822 assign(t11, unop(Iop_32to8,
8823 binop(Iop_And32,
8824 getIReg(rs),
8825 mkU32(0x7))));
8826 /* Shift bits 7..0 and 23..16. */
8827 assign(t0, binop(Iop_Shl32,
8828 binop(Iop_And32,
8829 getIReg(rt),
8830 mkU32(0x00ff00ff)),
8831 mkexpr(t11)));
8832 assign(t1, binop(Iop_CmpNE32,
8833 binop(Iop_And32,
8834 mkexpr(t0),
8835 mkU32(0xff000000)),
8836 mkU32(0x00000000)));
8837 assign(t2, binop(Iop_CmpNE32,
8838 binop(Iop_And32,
8839 mkexpr(t0),
8840 mkU32(0xff000000)),
8841 mkU32(0xff000000)));
8842 assign(t7, binop(Iop_CmpNE32,
8843 binop(Iop_And32,
8844 mkexpr(t0),
8845 mkU32(0x0000ff00)),
8846 mkU32(0x00000000)));
8847 assign(t8, binop(Iop_CmpNE32,
8848 binop(Iop_And32,
8849 mkexpr(t0),
8850 mkU32(0x0000ff00)),
8851 mkU32(0x000ff00)));
8852 /* Shift bits 15..8 and 31..24. */
8853 assign(t3, binop(Iop_Shl32,
8854 binop(Iop_Shr32,
8855 binop(Iop_And32,
8856 getIReg(rt),
8857 mkU32(0xff00ff00)),
8858 mkU8(8)),
8859 mkexpr(t11)));
8860 assign(t4, binop(Iop_CmpNE32,
8861 binop(Iop_And32,
8862 mkexpr(t3),
8863 mkU32(0xff000000)),
8864 mkU32(0x00000000)));
8865 assign(t5, binop(Iop_CmpNE32,
8866 binop(Iop_And32,
8867 mkexpr(t3),
8868 mkU32(0xff000000)),
8869 mkU32(0xff000000)));
8870 assign(t9, binop(Iop_CmpNE32,
8871 binop(Iop_And32,
8872 mkexpr(t3),
8873 mkU32(0x0000ff00)),
8874 mkU32(0x00000000)));
8875 assign(t10, binop(Iop_CmpNE32,
8876 binop(Iop_And32,
8877 mkexpr(t3),
8878 mkU32(0x0000ff00)),
8879 mkU32(0x0000ff00)));
8881 assign(t6, binop(Iop_Or32,
8882 binop(Iop_Or32,
8883 binop(Iop_And32,
8884 unop(Iop_1Uto32,
8885 mkexpr(t1)),
8886 unop(Iop_1Uto32,
8887 mkexpr(t2))),
8888 binop(Iop_And32,
8889 unop(Iop_1Uto32,
8890 mkexpr(t7)),
8891 unop(Iop_1Uto32,
8892 mkexpr(t8)))),
8893 binop(Iop_Or32,
8894 binop(Iop_And32,
8895 unop(Iop_1Uto32,
8896 mkexpr(t4)),
8897 unop(Iop_1Uto32,
8898 mkexpr(t5))),
8899 binop(Iop_And32,
8900 unop(Iop_1Uto32,
8901 mkexpr(t9)),
8902 unop(Iop_1Uto32,
8903 mkexpr(t10))))));
8905 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
8906 mkexpr(t6),
8907 mkU32(0x0)),
8908 binop(Iop_Or32,
8909 getDSPControl(),
8910 mkU32(0x400000)),
8911 getDSPControl()));
8912 putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
8913 unop(Iop_8Uto32, mkexpr(t11)),
8914 mkU32(0)),
8915 getIReg(rt),
8916 binop(Iop_Or32,
8917 binop(Iop_Shl32,
8918 binop(Iop_And32,
8919 mkexpr(t3),
8920 mkU32(0xff00ff)),
8921 mkU8(8)),
8922 binop(Iop_And32,
8923 mkexpr(t0),
8924 mkU32(0x00ff00ff)))));
8925 break;
8927 case 0x1: { /* SHRLV.QB */
8928 DIP("shrlv.qb r%u, r%u, r%u", rd, rt, rs);
8929 vassert(!mode64);
8930 t0 = newTemp(Ity_I8);
8931 t1 = newTemp(Ity_I8);
8932 t2 = newTemp(Ity_I8);
8933 t3 = newTemp(Ity_I8);
8935 assign(t0, unop(Iop_32to8,
8936 binop(Iop_Shr32,
8937 unop(Iop_8Uto32,
8938 unop(Iop_32to8, getIReg(rt))),
8939 mkU8(rs))));
8940 assign(t1, unop(Iop_32to8,
8941 binop(Iop_Shr32,
8942 unop(Iop_8Uto32,
8943 unop(Iop_16HIto8,
8944 unop(Iop_32to16,
8945 getIReg(rt)))),
8946 mkU8(rs))));
8947 assign(t2, unop(Iop_32to8,
8948 binop(Iop_Shr32,
8949 unop(Iop_8Uto32,
8950 unop(Iop_16to8,
8951 unop(Iop_32HIto16,
8952 getIReg(rt)))),
8953 mkU8(rs))));
8954 assign(t3, unop(Iop_32to8,
8955 binop(Iop_Shr32,
8956 unop(Iop_8Uto32,
8957 unop(Iop_16HIto8,
8958 unop(Iop_32HIto16,
8959 getIReg(rt)))),
8960 mkU8(rs))));
8961 putIReg(rd,
8962 binop(Iop_16HLto32,
8963 binop(Iop_8HLto16, mkexpr(t3), mkexpr(t2)),
8964 binop(Iop_8HLto16, mkexpr(t1), mkexpr(t0))));
8965 break;
8967 case 0x4: { /* SHRA.QB */
8968 DIP("shra.qb r%u, r%u, %u", rd, rt, rs);
8969 vassert(!mode64);
8970 t0 = newTemp(Ity_I32);
8971 t1 = newTemp(Ity_I32);
8972 t2 = newTemp(Ity_I32);
8973 t3 = newTemp(Ity_I32);
8974 t4 = newTemp(Ity_I32);
8975 t5 = newTemp(Ity_I32);
8976 t6 = newTemp(Ity_I32);
8977 t7 = newTemp(Ity_I32);
8978 t8 = newTemp(Ity_I32);
8979 t9 = newTemp(Ity_I32);
8980 t10 = newTemp(Ity_I32);
8981 t11 = newTemp(Ity_I32);
8983 /* ========== GPR[rt]_31..24 ========== */
8984 assign(t1,
8985 unop(Iop_8Uto32,
8986 unop(Iop_16HIto8,
8987 unop(Iop_32HIto16, getIReg(rt)))));
8988 assign(t2,
8989 binop(Iop_Shr32, mkexpr(t1), mkU8(rs)));
8990 /* tempD_7..0 */
8991 assign(t0,
8992 binop(Iop_Or32,
8993 mkexpr(t2),
8994 binop(Iop_Shl32,
8995 IRExpr_ITE(binop(Iop_CmpEQ32,
8996 binop(Iop_And32,
8997 mkexpr(t1),
8998 mkU32(0x00000080)
9000 mkU32(0x00000080)),
9001 mkU32(0xFFFFFFFF),
9002 mkU32(0x00000000)),
9003 binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
9005 /* ========== GPR[rt]_23..16 ========== */
9006 assign(t4,
9007 unop(Iop_8Uto32,
9008 unop(Iop_16to8,
9009 unop(Iop_32HIto16, getIReg(rt)))));
9010 assign(t5, binop(Iop_Shr32, mkexpr(t4), mkU8(rs)));
9011 /* tempC_7..0 */
9012 assign(t3,
9013 binop(Iop_Or32,
9014 mkexpr(t5),
9015 binop(Iop_Shl32,
9016 IRExpr_ITE(binop(Iop_CmpEQ32,
9017 binop(Iop_And32,
9018 mkexpr(t4),
9019 mkU32(0x00000080)
9021 mkU32(0x00000080)),
9022 mkU32(0xFFFFFFFF),
9023 mkU32(0x00000000)),
9024 binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
9026 /* ========== GPR[rt]_15..8 ========== */
9027 assign(t7,
9028 unop(Iop_8Uto32,
9029 unop(Iop_16HIto8,
9030 unop(Iop_32to16, getIReg(rt)))));
9031 assign(t8, binop(Iop_Shr32, mkexpr(t7), mkU8(rs)));
9032 /* tempB_7..0 */
9033 assign(t6,
9034 binop(Iop_Or32,
9035 mkexpr(t8),
9036 binop(Iop_Shl32,
9037 IRExpr_ITE(binop(Iop_CmpEQ32,
9038 binop(Iop_And32,
9039 mkexpr(t7),
9040 mkU32(0x00000080)
9042 mkU32(0x00000080)),
9043 mkU32(0xFFFFFFFF),
9044 mkU32(0x00000000)),
9045 binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
9047 /* ========== GPR[rt]_7..0 ========== */
9048 assign(t10,
9049 unop(Iop_8Uto32,
9050 unop(Iop_16to8,
9051 unop(Iop_32to16, getIReg(rt)))));
9052 assign(t11, binop(Iop_Shr32, mkexpr(t10), mkU8(rs)));
9053 /* tempB_7..0 */
9054 assign(t9,
9055 binop(Iop_Or32,
9056 mkexpr(t11),
9057 binop(Iop_Shl32,
9058 IRExpr_ITE(binop(Iop_CmpEQ32,
9059 binop(Iop_And32,
9060 mkexpr(t10),
9061 mkU32(0x00000080)
9063 mkU32(0x00000080)),
9064 mkU32(0xFFFFFFFF),
9065 mkU32(0x00000000)),
9066 binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
9068 putIReg(rd,
9069 binop(Iop_16HLto32,
9070 binop(Iop_8HLto16,
9071 unop(Iop_32to8, mkexpr(t0)),
9072 unop(Iop_32to8, mkexpr(t3))),
9073 binop(Iop_8HLto16,
9074 unop(Iop_32to8, mkexpr(t6)),
9075 unop(Iop_32to8, mkexpr(t9)))));
9076 break;
9078 case 0x5: { /* SHRA_R.QB */
9079 DIP("shra_r.qb r%u, r%u, %u", rd, rt, rs);
9080 vassert(!mode64);
9081 t0 = newTemp(Ity_I32);
9082 t1 = newTemp(Ity_I8);
9083 t2 = newTemp(Ity_I32);
9084 t3 = newTemp(Ity_I8);
9085 t4 = newTemp(Ity_I32);
9086 t5 = newTemp(Ity_I8);
9087 t6 = newTemp(Ity_I32);
9088 t7 = newTemp(Ity_I8);
9090 if (0 == rs) {
9091 putIReg(rd, getIReg(rt));
9092 } else {
9093 assign(t0, unop(Iop_8Sto32,
9094 unop(Iop_16to8,
9095 unop(Iop_32to16, getIReg(rt)))));
9096 assign(t1, unop(Iop_32to8,
9097 binop(Iop_Sar32,
9098 binop(Iop_Add32,
9099 mkexpr(t0),
9100 binop(Iop_Shl32,
9101 mkU32(0x1),
9102 mkU8(rs-1))),
9103 mkU8(rs))));
9105 assign(t2, unop(Iop_8Sto32,
9106 unop(Iop_16HIto8,
9107 unop(Iop_32to16, getIReg(rt)))));
9108 assign(t3, unop(Iop_32to8,
9109 binop(Iop_Sar32,
9110 binop(Iop_Add32,
9111 mkexpr(t2),
9112 binop(Iop_Shl32,
9113 mkU32(0x1),
9114 mkU8(rs-1))),
9115 mkU8(rs))));
9117 assign(t4, unop(Iop_8Sto32,
9118 unop(Iop_16to8,
9119 unop(Iop_32HIto16, getIReg(rt)))));
9120 assign(t5, unop(Iop_32to8,
9121 binop(Iop_Sar32,
9122 binop(Iop_Add32,
9123 mkexpr(t4),
9124 binop(Iop_Shl32,
9125 mkU32(0x1),
9126 mkU8(rs-1))),
9127 mkU8(rs))));
9129 assign(t6, unop(Iop_8Sto32,
9130 unop(Iop_16HIto8,
9131 unop(Iop_32HIto16, getIReg(rt)))));
9132 assign(t7, unop(Iop_32to8,
9133 binop(Iop_Sar32,
9134 binop(Iop_Add32,
9135 mkexpr(t6),
9136 binop(Iop_Shl32,
9137 mkU32(0x1),
9138 mkU8(rs-1))),
9139 mkU8(rs))));
9140 putIReg(rd, binop(Iop_16HLto32,
9141 binop(Iop_8HLto16,
9142 mkexpr(t7), mkexpr(t5)),
9143 binop(Iop_8HLto16,
9144 mkexpr(t3), mkexpr(t1))));
9146 break;
9148 case 0x6: { /* SHRAV.QB */
9149 DIP("shrav.qb r%u, r%u, %u", rd, rt, rs);
9150 vassert(!mode64);
9152 t0 = newTemp(Ity_I32);
9153 t1 = newTemp(Ity_I32);
9154 t2 = newTemp(Ity_I32);
9156 t3 = newTemp(Ity_I32);
9157 t4 = newTemp(Ity_I32);
9158 t5 = newTemp(Ity_I32);
9160 t6 = newTemp(Ity_I32);
9161 t7 = newTemp(Ity_I32);
9162 t8 = newTemp(Ity_I32);
9164 t9 = newTemp(Ity_I32);
9165 t10 = newTemp(Ity_I32);
9166 t11 = newTemp(Ity_I32);
9168 /* ========== GPR[rt]_31..24 ========== */
9169 assign(t1,
9170 unop(Iop_8Uto32,
9171 unop(Iop_16HIto8,
9172 unop(Iop_32HIto16, getIReg(rt)))));
9173 assign(t2,
9174 binop(Iop_Shr32,
9175 mkexpr(t1),
9176 unop(Iop_32to8, binop(Iop_And32,
9177 getIReg(rs),
9178 mkU32(0x7)))));
9179 /* tempD_7..0 */
9180 assign(t0,
9181 binop(Iop_Or32,
9182 mkexpr(t2),
9183 binop(Iop_Shl32,
9184 IRExpr_ITE(binop(Iop_CmpEQ32,
9185 binop(Iop_And32,
9186 mkexpr(t1),
9187 mkU32(0x00000080)
9189 mkU32(0x00000080)),
9190 mkU32(0xFFFFFFFF),
9191 mkU32(0x00000000)),
9192 binop(Iop_Sub8,
9193 mkU8(0x8),
9194 unop(Iop_32to8, binop(Iop_And32,
9195 getIReg(rs),
9196 mkU32(0x7)))
9197 ))));
9199 /* ========== GPR[rt]_23..16 ========== */
9200 assign(t4,
9201 unop(Iop_8Uto32,
9202 unop(Iop_16to8,
9203 unop(Iop_32HIto16, getIReg(rt)))));
9204 assign(t5,
9205 binop(Iop_Shr32,
9206 mkexpr(t4),
9207 unop(Iop_32to8, binop(Iop_And32,
9208 getIReg(rs),
9209 mkU32(0x7)))));
9210 /* tempC_7..0 */
9211 assign(t3,
9212 binop(Iop_Or32,
9213 mkexpr(t5),
9214 binop(Iop_Shl32,
9215 IRExpr_ITE(binop(Iop_CmpEQ32,
9216 binop(Iop_And32,
9217 mkexpr(t4),
9218 mkU32(0x00000080)
9220 mkU32(0x00000080)),
9221 mkU32(0xFFFFFFFF),
9222 mkU32(0x00000000)),
9223 binop(Iop_Sub8,
9224 mkU8(0x8),
9225 unop(Iop_32to8, binop(Iop_And32,
9226 getIReg(rs),
9227 mkU32(0x7)))
9228 ))));
9230 /* ========== GPR[rt]_15..8 ========== */
9231 assign(t7,
9232 unop(Iop_8Uto32,
9233 unop(Iop_16HIto8,
9234 unop(Iop_32to16, getIReg(rt)))));
9235 assign(t8,
9236 binop(Iop_Shr32,
9237 mkexpr(t7),
9238 unop(Iop_32to8, binop(Iop_And32,
9239 getIReg(rs),
9240 mkU32(0x7)))));
9241 /* tempB_7..0 */
9242 assign(t6,
9243 binop(Iop_Or32,
9244 mkexpr(t8),
9245 binop(Iop_Shl32,
9246 IRExpr_ITE(binop(Iop_CmpEQ32,
9247 binop(Iop_And32,
9248 mkexpr(t7),
9249 mkU32(0x00000080)
9251 mkU32(0x00000080)),
9252 mkU32(0xFFFFFFFF),
9253 mkU32(0x00000000)),
9254 binop(Iop_Sub8,
9255 mkU8(0x8),
9256 unop(Iop_32to8, binop(Iop_And32,
9257 getIReg(rs),
9258 mkU32(0x7)))
9259 ))));
9261 /* ========== GPR[rt]_7..0 ========== */
9262 assign(t10,
9263 unop(Iop_8Uto32,
9264 unop(Iop_16to8,
9265 unop(Iop_32to16, getIReg(rt)))));
9266 assign(t11,
9267 binop(Iop_Shr32,
9268 mkexpr(t10),
9269 unop(Iop_32to8, binop(Iop_And32,
9270 getIReg(rs),
9271 mkU32(0x7)))));
9272 /* tempB_7..0 */
9273 assign(t9,
9274 binop(Iop_Or32,
9275 mkexpr(t11),
9276 binop(Iop_Shl32,
9277 IRExpr_ITE(binop(Iop_CmpEQ32,
9278 binop(Iop_And32,
9279 mkexpr(t10),
9280 mkU32(0x00000080)
9282 mkU32(0x00000080)),
9283 mkU32(0xFFFFFFFF),
9284 mkU32(0x00000000)),
9285 binop(Iop_Sub8,
9286 mkU8(0x8),
9287 unop(Iop_32to8, binop(Iop_And32,
9288 getIReg(rs),
9289 mkU32(0x7)))
9290 ))));
9292 putIReg(rd,
9293 binop(Iop_16HLto32,
9294 binop(Iop_8HLto16,
9295 unop(Iop_32to8,
9296 IRExpr_ITE(binop(Iop_CmpEQ32,
9297 binop(Iop_And32,
9298 mkU32(rs),
9299 mkU32(0x7)
9301 mkU32(0x0)),
9302 mkexpr(t1),
9303 mkexpr(t0))),
9304 unop(Iop_32to8,
9305 IRExpr_ITE(binop(Iop_CmpEQ32,
9306 binop(Iop_And32,
9307 mkU32(rs),
9308 mkU32(0x7)
9310 mkU32(0x0)),
9311 mkexpr(t2),
9312 mkexpr(t3)))),
9313 binop(Iop_8HLto16,
9314 unop(Iop_32to8,
9315 IRExpr_ITE(binop(Iop_CmpEQ32,
9316 binop(Iop_And32,
9317 mkU32(rs),
9318 mkU32(0x7)
9320 mkU32(0x0)),
9321 mkexpr(t5),
9322 mkexpr(t6))),
9323 unop(Iop_32to8,
9324 IRExpr_ITE(binop(Iop_CmpEQ32,
9325 binop(Iop_And32,
9326 mkU32(rs),
9327 mkU32(0x7)
9329 mkU32(0x0)),
9330 mkexpr(t8),
9331 mkexpr(t9))))));
9332 break;
9334 case 0x7: { /* SHRAV_R.QB */
9335 DIP("shrav_r.qb r%u, r%u, r%u", rd, rt, rs);
9336 vassert(!mode64);
9337 t0 = newTemp(Ity_I32);
9338 t1 = newTemp(Ity_I8);
9339 t2 = newTemp(Ity_I32);
9340 t3 = newTemp(Ity_I8);
9341 t4 = newTemp(Ity_I32);
9342 t5 = newTemp(Ity_I8);
9343 t6 = newTemp(Ity_I32);
9344 t7 = newTemp(Ity_I8);
9345 t8 = newTemp(Ity_I8);
9346 t9 = newTemp(Ity_I32);
9348 assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7)));
9349 assign(t8, unop(Iop_32to8,
9350 binop(Iop_Sub32, mkexpr(t9), mkU32(0x1))));
9351 assign(t0, unop(Iop_8Sto32,
9352 unop(Iop_16to8,
9353 unop(Iop_32to16, getIReg(rt)))));
9354 assign(t1, unop(Iop_32to8,
9355 binop(Iop_Sar32,
9356 binop(Iop_Add32,
9357 mkexpr(t0),
9358 binop(Iop_Shl32,
9359 mkU32(0x1),
9360 mkexpr(t8))),
9361 unop(Iop_32to8,
9362 mkexpr(t9)))));
9364 assign(t2, unop(Iop_8Sto32,
9365 unop(Iop_16HIto8,
9366 unop(Iop_32to16, getIReg(rt)))));
9367 assign(t3, unop(Iop_32to8,
9368 binop(Iop_Sar32,
9369 binop(Iop_Add32,
9370 mkexpr(t2),
9371 binop(Iop_Shl32,
9372 mkU32(0x1),
9373 mkexpr(t8))),
9374 unop(Iop_32to8, mkexpr(t9)))));
9376 assign(t4, unop(Iop_8Sto32,
9377 unop(Iop_16to8,
9378 unop(Iop_32HIto16, getIReg(rt)))));
9379 assign(t5, unop(Iop_32to8,
9380 binop(Iop_Sar32,
9381 binop(Iop_Add32,
9382 mkexpr(t4),
9383 binop(Iop_Shl32,
9384 mkU32(0x1),
9385 mkexpr(t8))),
9386 unop(Iop_32to8, mkexpr(t9)))));
9388 assign(t6, unop(Iop_8Sto32,
9389 unop(Iop_16HIto8,
9390 unop(Iop_32HIto16, getIReg(rt)))));
9391 assign(t7, unop(Iop_32to8,
9392 binop(Iop_Sar32,
9393 binop(Iop_Add32,
9394 mkexpr(t6),
9395 binop(Iop_Shl32,
9396 mkU32(0x1),
9397 mkexpr(t8))),
9398 unop(Iop_32to8, mkexpr(t9)))));
9399 putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
9400 mkexpr(t9),
9401 mkU32(0x0)),
9402 getIReg(rt),
9403 binop(Iop_16HLto32,
9404 binop(Iop_8HLto16,
9405 mkexpr(t7),
9406 mkexpr(t5)),
9407 binop(Iop_8HLto16,
9408 mkexpr(t3),
9409 mkexpr(t1)))));
9410 break;
9412 case 0x8: { /* SHLL.PH */
9413 DIP("shll.ph r%u, r%u, %u", rd, rt, rs);
9414 vassert(!mode64);
9415 t0 = newTemp(Ity_I32);
9416 t1 = newTemp(Ity_I32);
9417 t2 = newTemp(Ity_I32);
9418 t3 = newTemp(Ity_I32);
9419 t4 = newTemp(Ity_I32);
9420 t5 = newTemp(Ity_I32);
9421 t6 = newTemp(Ity_I32);
9422 t7 = newTemp(Ity_I32);
9424 if (0 == rs) {
9425 putIReg(rd, getIReg(rt));
9426 } else {
9427 /* Shift lower 16 bits. */
9428 assign(t0, binop(Iop_Shl32,
9429 unop(Iop_16Sto32,
9430 unop(Iop_32to16, getIReg(rt))),
9431 mkU8(rs)));
9433 assign(t1, unop(Iop_1Uto32,
9434 binop(Iop_CmpNE32,
9435 binop(Iop_Sar32,
9436 mkexpr(t0),
9437 mkU8(16)),
9438 mkU32(0))));
9439 assign(t2, unop(Iop_1Uto32,
9440 binop(Iop_CmpNE32,
9441 binop(Iop_Sar32,
9442 mkexpr(t0),
9443 mkU8(16)),
9444 mkU32(0xffffffff))));
9445 assign(t3, binop(Iop_And32,
9446 mkexpr(t1),
9447 mkexpr(t2)));
9448 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9449 mkexpr(t3),
9450 mkU32(0x1)),
9451 binop(Iop_Or32,
9452 getDSPControl(),
9453 mkU32(0x400000)),
9454 getDSPControl()));
9455 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9456 binop(Iop_And32,
9457 getIReg(rt),
9458 mkU32(0x00008000)),
9459 binop(Iop_And32,
9460 mkexpr(t0),
9461 mkU32(0x00008000))
9463 getDSPControl(),
9464 binop(Iop_Or32,
9465 getDSPControl(),
9466 mkU32(0x400000))));
9467 /* Shift higher 16 bits. */
9468 assign(t4, binop(Iop_Shl32,
9469 unop(Iop_16Sto32,
9470 unop(Iop_32HIto16, getIReg(rt))),
9471 mkU8(rs)));
9473 assign(t5, unop(Iop_1Uto32,
9474 binop(Iop_CmpNE32,
9475 binop(Iop_Sar32,
9476 mkexpr(t4),
9477 mkU8(16)),
9478 mkU32(0))));
9479 assign(t6, unop(Iop_1Uto32,
9480 binop(Iop_CmpNE32,
9481 binop(Iop_Sar32,
9482 mkexpr(t4),
9483 mkU8(16)),
9484 mkU32(0xffffffff))));
9485 assign(t7, binop(Iop_And32,
9486 mkexpr(t5),
9487 mkexpr(t6)));
9488 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9489 mkexpr(t7),
9490 mkU32(0x1)),
9491 binop(Iop_Or32,
9492 getDSPControl(),
9493 mkU32(0x400000)),
9494 getDSPControl()));
9495 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9496 mkexpr(t7),
9497 mkU32(0x1)),
9498 binop(Iop_Or32,
9499 getDSPControl(),
9500 mkU32(0x400000)),
9501 getDSPControl()));
9502 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9503 binop(Iop_And32,
9504 getIReg(rt),
9505 mkU32(0x80000000)),
9506 binop(Iop_Shl32,
9507 binop(Iop_And32,
9508 mkexpr(t4),
9509 mkU32(0x00008000)),
9510 mkU8(16))
9512 getDSPControl(),
9513 binop(Iop_Or32,
9514 getDSPControl(),
9515 mkU32(0x400000))));
9516 putIReg(rd, binop(Iop_16HLto32,
9517 unop(Iop_32to16, mkexpr(t4)),
9518 unop(Iop_32to16, mkexpr(t0))));
9520 break;
9522 case 0x9: { /* SHRA.PH */
9523 DIP("shra.ph r%u, r%u, %u", rd, rt, rs);
9524 vassert(!mode64);
9525 t0 = newTemp(Ity_I32);
9526 t1 = newTemp(Ity_I32);
9527 if (0 == rs) {
9528 putIReg(rd, getIReg(rt));
9529 } else {
9530 assign(t0, binop(Iop_Sar32,
9531 unop(Iop_16Sto32,
9532 unop(Iop_32to16, getIReg(rt))),
9533 mkU8(rs)));
9534 assign(t1, binop(Iop_Sar32,
9535 unop(Iop_16Sto32,
9536 unop(Iop_32HIto16, getIReg(rt))),
9537 mkU8(rs)));
9538 putIReg(rd, binop(Iop_16HLto32,
9539 unop(Iop_32to16, mkexpr(t1)),
9540 unop(Iop_32to16, mkexpr(t0))));
9542 break;
9544 case 0xA: { /* SHLLV.PH */
9545 DIP("shllv.ph r%u, r%u, r%u", rd, rt, rs);
9546 vassert(!mode64);
9547 t0 = newTemp(Ity_I32);
9548 t2 = newTemp(Ity_I32);
9549 t3 = newTemp(Ity_I1);
9550 t4 = newTemp(Ity_I1);
9551 t5 = newTemp(Ity_I32);
9552 t6 = newTemp(Ity_I32);
9553 t7 = newTemp(Ity_I1);
9554 t8 = newTemp(Ity_I1);
9555 t9 = newTemp(Ity_I32);
9556 t10 = newTemp(Ity_I32);
9557 t11 = newTemp(Ity_I32);
9558 t12 = newTemp(Ity_I1);
9559 t13 = newTemp(Ity_I1);
9561 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
9563 /* Shift lower 16 bits. */
9564 assign(t2, binop(Iop_Shl32,
9565 unop(Iop_16Sto32,
9566 unop(Iop_32to16, getIReg(rt))),
9567 unop(Iop_32to8, mkexpr(t0))));
9569 assign(t3, binop(Iop_CmpNE32,
9570 unop(Iop_16Sto32,
9571 unop(Iop_32HIto16, mkexpr(t2))),
9572 mkU32(0x00000000)));
9573 assign(t4, binop(Iop_CmpNE32,
9574 unop(Iop_16Sto32,
9575 unop(Iop_32HIto16, mkexpr(t2))),
9576 mkU32(0xffffffff)));
9577 assign(t10, binop(Iop_And32,
9578 unop(Iop_1Sto32, mkexpr(t3)),
9579 unop(Iop_1Sto32, mkexpr(t4))));
9580 assign(t5, binop(Iop_Shr32,
9581 binop(Iop_And32,
9582 getIReg(rt),
9583 mkU32(0x00008000)),
9584 mkU8(15)));
9585 assign(t12, binop(Iop_CmpEQ32,
9586 mkexpr(t5),
9587 binop(Iop_Shr32,
9588 binop(Iop_And32,
9589 mkexpr(t2),
9590 mkU32(0x00008000)),
9591 mkU8(15))));
9593 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
9594 mkexpr(t10),
9595 mkU32(0x0)),
9596 binop(Iop_Or32,
9597 getDSPControl(),
9598 mkU32(0x400000)),
9599 IRExpr_ITE(mkexpr(t12),
9600 getDSPControl(),
9601 binop(Iop_Or32,
9602 getDSPControl(),
9603 mkU32(0x400000)))
9605 /* Shift higher 16 bits. */
9606 assign(t6, binop(Iop_Shl32,
9607 unop(Iop_16Sto32,
9608 unop(Iop_32HIto16, getIReg(rt))),
9609 unop(Iop_32to8, mkexpr(t0))));
9611 assign(t7, binop(Iop_CmpNE32,
9612 unop(Iop_16Sto32,
9613 unop(Iop_32HIto16, mkexpr(t6))),
9614 mkU32(0x00000000)));
9615 assign(t8, binop(Iop_CmpNE32,
9616 unop(Iop_16Sto32,
9617 unop(Iop_32HIto16, mkexpr(t6))),
9618 mkU32(0xffffffff)));
9619 assign(t11, binop(Iop_And32,
9620 unop(Iop_1Sto32, mkexpr(t7)),
9621 unop(Iop_1Sto32, mkexpr(t8))));
9623 assign(t9, binop(Iop_Shr32,
9624 binop(Iop_And32,
9625 getIReg(rt),
9626 mkU32(0x80000000)),
9627 mkU8(31)));
9628 assign(t13, binop(Iop_CmpEQ32,
9629 mkexpr(t9),
9630 binop(Iop_Shr32,
9631 binop(Iop_And32,
9632 mkexpr(t6),
9633 mkU32(0x00008000)),
9634 mkU8(15))));
9636 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
9637 mkexpr(t11),
9638 mkU32(0x0)),
9639 binop(Iop_Or32,
9640 getDSPControl(),
9641 mkU32(0x400000)),
9642 IRExpr_ITE(mkexpr(t13),
9643 getDSPControl(),
9644 binop(Iop_Or32,
9645 getDSPControl(),
9646 mkU32(0x400000)))
9649 putIReg(rd, binop(Iop_16HLto32,
9650 unop(Iop_32to16, mkexpr(t6)),
9651 unop(Iop_32to16, mkexpr(t2))));
9652 break;
9654 case 0xB: { /* SHRAV.PH */
9655 DIP("shrav.ph r%u, r%u, r%u", rd, rt, rs);
9656 vassert(!mode64);
9657 t0 = newTemp(Ity_I32);
9658 t1 = newTemp(Ity_I1);
9659 t2 = newTemp(Ity_I32);
9660 t3 = newTemp(Ity_I32);
9662 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
9663 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
9664 assign(t2, binop(Iop_Sar32,
9665 unop(Iop_16Sto32,
9666 unop(Iop_32to16, getIReg(rt))),
9667 unop(Iop_32to8, mkexpr(t0))));
9668 assign(t3, binop(Iop_Sar32,
9669 unop(Iop_16Sto32,
9670 unop(Iop_32HIto16, getIReg(rt))),
9671 unop(Iop_32to8, mkexpr(t0))));
9672 putIReg(rd,
9673 binop(Iop_16HLto32,
9674 IRExpr_ITE(mkexpr(t1),
9675 unop(Iop_32HIto16, getIReg(rt)),
9676 unop(Iop_32to16, mkexpr(t3))),
9677 IRExpr_ITE(mkexpr(t1),
9678 unop(Iop_32to16, getIReg(rt)),
9679 unop(Iop_32to16, mkexpr(t2)))));
9680 break;
9682 case 0xC: { /* SHLL_S.PH */
9683 DIP("shll_s.ph r%u, r%u, %u", rd, rt, rs);
9684 vassert(!mode64);
9685 t0 = newTemp(Ity_I32);
9686 t1 = newTemp(Ity_I32);
9687 t2 = newTemp(Ity_I32);
9688 t3 = newTemp(Ity_I32);
9689 t4 = newTemp(Ity_I32);
9690 t5 = newTemp(Ity_I32);
9691 t6 = newTemp(Ity_I32);
9692 t7 = newTemp(Ity_I32);
9693 t8 = newTemp(Ity_I32);
9694 t9 = newTemp(Ity_I32);
9695 t10 = newTemp(Ity_I32);
9696 t11 = newTemp(Ity_I32);
9697 t12 = newTemp(Ity_I32);
9698 t13 = newTemp(Ity_I32);
9699 t14 = newTemp(Ity_I32);
9701 if (0 == rs) {
9702 putIReg(rd, getIReg(rt));
9703 } else {
9704 /* Shift lower 16 bits. */
9705 assign(t0, binop(Iop_Shl32,
9706 unop(Iop_16Sto32,
9707 unop(Iop_32to16, getIReg(rt))),
9708 mkU8(rs)));
9710 assign(t1, unop(Iop_1Uto32,
9711 binop(Iop_CmpNE32,
9712 binop(Iop_Sar32,
9713 mkexpr(t0),
9714 mkU8(16)),
9715 mkU32(0))));
9716 assign(t2, unop(Iop_1Uto32,
9717 binop(Iop_CmpNE32,
9718 binop(Iop_Sar32,
9719 mkexpr(t0),
9720 mkU8(16)),
9721 mkU32(0xffffffff))));
9722 assign(t3, binop(Iop_And32,
9723 mkexpr(t1),
9724 mkexpr(t2)));
9725 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9726 mkexpr(t3),
9727 mkU32(0x1)),
9728 binop(Iop_Or32,
9729 getDSPControl(),
9730 mkU32(0x400000)),
9731 getDSPControl()));
9732 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9733 binop(Iop_And32,
9734 getIReg(rt),
9735 mkU32(0x00008000)),
9736 binop(Iop_And32,
9737 mkexpr(t0),
9738 mkU32(0x00008000))
9740 getDSPControl(),
9741 binop(Iop_Or32,
9742 getDSPControl(),
9743 mkU32(0x400000))));
9744 assign(t8,
9745 IRExpr_ITE(binop(Iop_CmpEQ32,
9746 mkexpr(t3),
9747 mkU32(0x1)),
9748 IRExpr_ITE(binop(Iop_CmpEQ32,
9749 binop(Iop_And32,
9750 getIReg(rt),
9751 mkU32(0x8000)),
9752 mkU32(0)),
9753 mkU32(0x00007fff),
9754 mkU32(0x00008000)),
9755 binop(Iop_And32,
9756 mkexpr(t0),
9757 mkU32(0x0000ffff))));
9758 assign(t10,
9759 IRExpr_ITE(binop(Iop_CmpEQ32,
9760 binop(Iop_And32,
9761 getIReg(rt),
9762 mkU32(0x00008000)),
9763 binop(Iop_And32,
9764 mkexpr(t0),
9765 mkU32(0x00008000))),
9766 mkexpr(t8),
9767 IRExpr_ITE(binop(Iop_CmpEQ32,
9768 binop(Iop_And32,
9769 getIReg(rt),
9770 mkU32(0x8000)),
9771 mkU32(0)),
9772 mkU32(0x00007fff),
9773 mkU32(0x00008000))));
9774 /* Shift higher 16 bits. */
9775 assign(t4, binop(Iop_Shl32,
9776 unop(Iop_16Sto32,
9777 unop(Iop_32HIto16, getIReg(rt))),
9778 mkU8(rs)));
9780 assign(t5, unop(Iop_1Uto32,
9781 binop(Iop_CmpNE32,
9782 binop(Iop_Sar32,
9783 mkexpr(t4),
9784 mkU8(16)),
9785 mkU32(0))));
9786 assign(t6, unop(Iop_1Uto32,
9787 binop(Iop_CmpNE32,
9788 binop(Iop_Sar32,
9789 mkexpr(t4),
9790 mkU8(16)),
9791 mkU32(0xffffffff))));
9792 assign(t7, binop(Iop_And32,
9793 mkexpr(t5),
9794 mkexpr(t6)));
9795 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9796 mkexpr(t7),
9797 mkU32(0x1)),
9798 binop(Iop_Or32,
9799 getDSPControl(),
9800 mkU32(0x400000)),
9801 getDSPControl()));
9802 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9803 mkexpr(t7),
9804 mkU32(0x1)),
9805 binop(Iop_Or32,
9806 getDSPControl(),
9807 mkU32(0x400000)),
9808 getDSPControl()));
9809 assign(t12, binop(Iop_Shl32,
9810 binop(Iop_And32,
9811 mkexpr(t4),
9812 mkU32(0x8000)),
9813 mkU8(16)));
9814 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
9815 binop(Iop_And32,
9816 getIReg(rt),
9817 mkU32(0x80000000)),
9818 mkexpr(t12)),
9819 getDSPControl(),
9820 binop(Iop_Or32,
9821 getDSPControl(),
9822 mkU32(0x400000))));
9823 assign(t13, IRExpr_ITE(binop(Iop_CmpEQ32,
9824 binop(Iop_And32,
9825 getIReg(rt),
9826 mkU32(0x80000000)),
9827 mkU32(0)),
9828 mkU32(0x7fff0000),
9829 mkU32(0x80000000)));
9830 assign(t9,
9831 IRExpr_ITE(binop(Iop_CmpEQ32,
9832 mkexpr(t7),
9833 mkU32(0x1)),
9834 mkexpr(t13),
9835 binop(Iop_Shl32,
9836 binop(Iop_And32,
9837 mkexpr(t4),
9838 mkU32(0x0000ffff)),
9839 mkU8(16))));
9840 assign(t14, IRExpr_ITE(binop(Iop_CmpEQ32,
9841 binop(Iop_And32,
9842 getIReg(rt),
9843 mkU32(0x80000000)),
9844 mkU32(0)),
9845 mkU32(0x7fff0000),
9846 mkU32(0x80000000)));
9847 assign(t11,
9848 IRExpr_ITE(binop(Iop_CmpEQ32,
9849 binop(Iop_And32,
9850 getIReg(rt),
9851 mkU32(0x80000000)),
9852 binop(Iop_Shl32,
9853 binop(Iop_And32,
9854 mkexpr(t4),
9855 mkU32(0x00008000)),
9856 mkU8(16))),
9857 mkexpr(t9),
9858 mkexpr(t14)));
9859 putIReg(rd, binop(Iop_Or32,
9860 mkexpr(t10),
9861 mkexpr(t11)));
9863 break;
9865 case 0xD: { /* SHRA_R.PH */
9866 DIP("shra.ph r%u, r%u, %u", rd, rt, rs);
9867 vassert(!mode64);
9868 t0 = newTemp(Ity_I32);
9869 t1 = newTemp(Ity_I32);
9870 if (0 == rs) {
9871 putIReg(rd, getIReg(rt));
9872 } else {
9873 assign(t0, binop(Iop_Sar32,
9874 binop(Iop_Add32,
9875 unop(Iop_16Sto32,
9876 unop(Iop_32to16,
9877 getIReg(rt))),
9878 binop(Iop_Shl32,
9879 mkU32(0x1),
9880 mkU8(rs-1))),
9881 mkU8(rs)));
9882 assign(t1, binop(Iop_Sar32,
9883 binop(Iop_Add32,
9884 unop(Iop_16Sto32,
9885 unop(Iop_32HIto16,
9886 getIReg(rt))),
9887 binop(Iop_Shl32,
9888 mkU32(0x1),
9889 mkU8(rs-1))),
9890 mkU8(rs)));
9891 putIReg(rd, binop(Iop_16HLto32,
9892 unop(Iop_32to16, mkexpr(t1)),
9893 unop(Iop_32to16, mkexpr(t0))));
9895 break;
9897 case 0xE: { /* SHLLV_S.PH */
9898 DIP("shllv_s.ph r%u, r%u, r%u", rd, rt, rs);
9899 vassert(!mode64);
9900 t0 = newTemp(Ity_I32);
9901 t2 = newTemp(Ity_I32);
9902 t3 = newTemp(Ity_I1);
9903 t4 = newTemp(Ity_I1);
9904 t5 = newTemp(Ity_I32);
9905 t6 = newTemp(Ity_I32);
9906 t7 = newTemp(Ity_I1);
9907 t8 = newTemp(Ity_I1);
9908 t9 = newTemp(Ity_I32);
9909 t10 = newTemp(Ity_I32);
9910 t11 = newTemp(Ity_I32);
9911 t12 = newTemp(Ity_I1);
9912 t13 = newTemp(Ity_I1);
9913 t14 = newTemp(Ity_I16);
9914 t15 = newTemp(Ity_I16);
9915 t16 = newTemp(Ity_I16);
9916 t17 = newTemp(Ity_I16);
9918 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
9920 /* Shift lower 16 bits. */
9921 assign(t2, binop(Iop_Shl32,
9922 unop(Iop_16Sto32,
9923 unop(Iop_32to16, getIReg(rt))),
9924 unop(Iop_32to8, mkexpr(t0))));
9926 assign(t3, binop(Iop_CmpNE32,
9927 unop(Iop_16Sto32,
9928 unop(Iop_32HIto16, mkexpr(t2))),
9929 mkU32(0x00000000)));
9930 assign(t4, binop(Iop_CmpNE32,
9931 unop(Iop_16Sto32,
9932 unop(Iop_32HIto16, mkexpr(t2))),
9933 mkU32(0xffffffff)));
9934 assign(t10, binop(Iop_And32,
9935 unop(Iop_1Sto32, mkexpr(t3)),
9936 unop(Iop_1Sto32, mkexpr(t4))));
9937 assign(t5, binop(Iop_Shr32,
9938 binop(Iop_And32,
9939 getIReg(rt),
9940 mkU32(0x00008000)),
9941 mkU8(15)));
9942 assign(t12, binop(Iop_CmpEQ32,
9943 mkexpr(t5),
9944 binop(Iop_Shr32,
9945 binop(Iop_And32,
9946 mkexpr(t2),
9947 mkU32(0x00008000)),
9948 mkU8(15))));
9950 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
9951 mkexpr(t10),
9952 mkU32(0x0)),
9953 binop(Iop_Or32,
9954 getDSPControl(),
9955 mkU32(0x400000)),
9956 IRExpr_ITE(mkexpr(t12),
9957 getDSPControl(),
9958 binop(Iop_Or32,
9959 getDSPControl(),
9960 mkU32(0x400000)))
9962 assign(t14, IRExpr_ITE(binop(Iop_CmpNE32,
9963 mkexpr(t5),
9964 mkU32(0x0)),
9965 mkU16(0x8000),
9966 mkU16(0x7fff)));
9967 assign(t15, IRExpr_ITE(binop(Iop_CmpNE32,
9968 mkexpr(t10),
9969 mkU32(0x0)),
9970 mkexpr(t14),
9971 IRExpr_ITE(mkexpr(t12),
9972 unop(Iop_32to16,
9973 mkexpr(t2)),
9974 mkexpr(t14))));
9975 /* Shift higher 16 bits. */
9976 assign(t6, binop(Iop_Shl32,
9977 unop(Iop_16Sto32,
9978 unop(Iop_32HIto16, getIReg(rt))),
9979 unop(Iop_32to8, mkexpr(t0))));
9981 assign(t7, binop(Iop_CmpNE32,
9982 unop(Iop_16Sto32,
9983 unop(Iop_32HIto16, mkexpr(t6))),
9984 mkU32(0x00000000)));
9985 assign(t8, binop(Iop_CmpNE32,
9986 unop(Iop_16Sto32,
9987 unop(Iop_32HIto16, mkexpr(t6))),
9988 mkU32(0xffffffff)));
9989 assign(t11, binop(Iop_And32,
9990 unop(Iop_1Sto32, mkexpr(t7)),
9991 unop(Iop_1Sto32, mkexpr(t8))));
9993 assign(t9, binop(Iop_Shr32,
9994 binop(Iop_And32,
9995 getIReg(rt),
9996 mkU32(0x80000000)),
9997 mkU8(31)));
9998 assign(t13, binop(Iop_CmpEQ32,
9999 mkexpr(t9),
10000 binop(Iop_Shr32,
10001 binop(Iop_And32,
10002 mkexpr(t6),
10003 mkU32(0x00008000)),
10004 mkU8(15))));
10006 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
10007 mkexpr(t11),
10008 mkU32(0x0)),
10009 binop(Iop_Or32,
10010 getDSPControl(),
10011 mkU32(0x400000)),
10012 IRExpr_ITE(mkexpr(t13),
10013 getDSPControl(),
10014 binop(Iop_Or32,
10015 getDSPControl(),
10016 mkU32(0x400000)))
10019 assign(t16, IRExpr_ITE(binop(Iop_CmpNE32,
10020 mkexpr(t9),
10021 mkU32(0x0)),
10022 mkU16(0x8000),
10023 mkU16(0x7fff)));
10024 assign(t17, IRExpr_ITE(binop(Iop_CmpNE32,
10025 mkexpr(t11),
10026 mkU32(0x0)),
10027 mkexpr(t16),
10028 IRExpr_ITE(mkexpr(t13),
10029 unop(Iop_32to16,
10030 mkexpr(t6)),
10031 mkexpr(t16))));
10033 putIReg(rd, binop(Iop_16HLto32, mkexpr(t17), mkexpr(t15)));
10034 break;
10036 case 0xF: { /* SHRAV_R.PH */
10037 DIP("shrav_r.ph r%u, r%u, r%u", rd, rt, rs);
10038 vassert(!mode64);
10039 t0 = newTemp(Ity_I32);
10040 t1 = newTemp(Ity_I1);
10041 t2 = newTemp(Ity_I8);
10042 t3 = newTemp(Ity_I32);
10043 t4 = newTemp(Ity_I32);
10045 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
10046 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
10047 assign(t2, unop(Iop_32to8,
10048 binop(Iop_Sub32, mkexpr(t0), mkU32(1))));
10050 assign(t3, binop(Iop_Sar32,
10051 binop(Iop_Add32,
10052 unop(Iop_16Sto32,
10053 unop(Iop_32to16, getIReg(rt))),
10054 binop(Iop_Shl32,
10055 mkU32(0x1),
10056 mkexpr(t2))),
10057 unop(Iop_32to8, mkexpr(t0))));
10058 assign(t4, binop(Iop_Sar32,
10059 binop(Iop_Add32,
10060 unop(Iop_16Sto32,
10061 unop(Iop_32HIto16,
10062 getIReg(rt))),
10063 binop(Iop_Shl32,
10064 mkU32(0x1),
10065 mkexpr(t2))),
10066 unop(Iop_32to8, mkexpr(t0))));
10068 putIReg(rd, binop(Iop_16HLto32,
10069 IRExpr_ITE(mkexpr(t1),
10070 unop(Iop_32HIto16,
10071 getIReg(rt)),
10072 unop(Iop_32to16,
10073 mkexpr(t4))),
10074 IRExpr_ITE(mkexpr(t1),
10075 unop(Iop_32to16, getIReg(rt)),
10076 unop(Iop_32to16,
10077 mkexpr(t3)))));
10078 break;
10080 case 0x14: { /* SHLL_S.W */
10081 DIP("shll_s.w r%u, r%u, %u", rd, rt, rs);
10082 vassert(!mode64);
10083 t0 = newTemp(Ity_I32);
10084 t1 = newTemp(Ity_I32);
10085 t2 = newTemp(Ity_I32);
10086 t3 = newTemp(Ity_I32);
10087 t4 = newTemp(Ity_I32);
10088 t5 = newTemp(Ity_I32);
10090 if (0 == rs) {
10091 putIReg(rd, getIReg(rt));
10092 } else {
10093 /* t0-bits that will be discarded, sign extended to
10094 32bits. */
10095 assign(t0, binop(Iop_Sar32,
10096 binop(Iop_And32,
10097 getIReg(rt),
10098 binop(Iop_Sar32,
10099 mkU32(0x80000000),
10100 mkU8(rs-1))),
10101 mkU8(32-rs)));
10103 assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32,
10104 binop(Iop_And32,
10105 getIReg(rt),
10106 mkU32(0x80000000)),
10107 mkU32(0x0)),
10108 mkU32(0x7fffffff),
10109 mkU32(0x80000000)));
10111 assign(t2, binop(Iop_Shl32, getIReg(rt), mkU8(rs)));
10112 assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
10113 binop(Iop_And32,
10114 getIReg(rt),
10115 mkU32(0x80000000)),
10116 binop(Iop_And32,
10117 mkexpr(t2),
10118 mkU32(0x80000000))),
10119 mkexpr(t2),
10120 mkexpr(t1)));
10122 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
10123 mkexpr(t0),
10124 mkU32(0x0)),
10125 IRExpr_ITE(binop(Iop_CmpNE32,
10126 mkexpr(t0),
10127 mkU32(0xffffffff)
10129 mkexpr(t1),
10130 mkexpr(t3)),
10131 mkexpr(t3)));
10132 assign(t5, IRExpr_ITE(binop(Iop_CmpNE32,
10133 mkexpr(t0),
10134 mkU32(0xffffffff)),
10135 binop(Iop_Or32,
10136 getDSPControl(),
10137 mkU32(0x400000)),
10138 getDSPControl()));
10139 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
10140 mkexpr(t0),
10141 mkU32(0x0)),
10142 mkexpr(t5),
10143 getDSPControl()));
10144 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
10145 binop(Iop_And32,
10146 getIReg(rt),
10147 mkU32(0x80000000)),
10148 binop(Iop_And32,
10149 mkexpr(t2),
10150 mkU32(0x80000000))
10152 getDSPControl(),
10153 binop(Iop_Or32,
10154 getDSPControl(),
10155 mkU32(0x400000))));
10156 putIReg(rd, mkexpr(t4));
10158 break;
10160 case 0x15: { /* SHRA_R.W */
10161 DIP("shra_r.w r%u, r%u, %u", rd, rt, rs);
10162 vassert(!mode64);
10163 if (0 == rs) {
10164 putIReg(rd, getIReg(rt));
10165 } else {
10166 putIReg(rd, binop(Iop_Add32,
10167 binop(Iop_Sar32,
10168 getIReg(rt), mkU8(rs)),
10169 binop(Iop_Shr32,
10170 binop(Iop_And32,
10171 getIReg(rt),
10172 binop(Iop_Shl32,
10173 mkU32(0x1),
10174 mkU8(rs-1))),
10175 mkU8(rs-1))));
10177 break;
10179 case 0x16: { /* SHLLV_S.W */
10180 DIP("shllv_s.w r%u, r%u, r%u", rd, rt, rs);
10181 vassert(!mode64);
10182 t0 = newTemp(Ity_I32);
10183 t1 = newTemp(Ity_I1);
10184 t2 = newTemp(Ity_I32);
10185 t3 = newTemp(Ity_I64);
10186 t4 = newTemp(Ity_I1);
10187 t5 = newTemp(Ity_I1);
10188 t6 = newTemp(Ity_I32);
10189 t7 = newTemp(Ity_I1);
10190 t8 = newTemp(Ity_I32);
10192 /* Check if shift amount is zero. */
10193 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
10194 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
10196 /* t2 = sign of the input value. */
10197 assign(t2, binop(Iop_Shr32,
10198 binop(Iop_And32,
10199 getIReg(rt),
10200 mkU32(0x80000000)),
10201 mkU8(31)));
10202 /* Shift left input value and check for overflow. */
10203 assign(t3, binop(Iop_Shl64,
10204 unop(Iop_32Sto64, getIReg(rt)),
10205 unop(Iop_32to8, mkexpr(t0))));
10206 assign(t4, binop(Iop_CmpNE32,
10207 unop(Iop_64HIto32, mkexpr(t3)),
10208 mkU32(0x00000000)));
10209 assign(t5, binop(Iop_CmpNE32,
10210 unop(Iop_64HIto32, mkexpr(t3)),
10211 mkU32(0xffffffff)));
10212 assign(t6, binop(Iop_And32,
10213 unop(Iop_1Uto32, mkexpr(t4)),
10214 unop(Iop_1Uto32, mkexpr(t5))));
10215 assign(t7, binop(Iop_CmpEQ32,
10216 binop(Iop_Shr32,
10217 binop(Iop_And32,
10218 getIReg(rt),
10219 mkU32(0x80000000)),
10220 mkU8(31)),
10221 binop(Iop_Shr32,
10222 binop(Iop_And32,
10223 unop(Iop_64to32, mkexpr(t3)),
10224 mkU32(0x80000000)),
10225 mkU8(31))));
10227 putDSPControl(IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)),
10228 binop(Iop_Or32,
10229 getDSPControl(),
10230 mkU32(0x400000)),
10231 IRExpr_ITE(mkexpr(t7),
10232 getDSPControl(),
10233 binop(Iop_Or32,
10234 getDSPControl(),
10235 mkU32(0x400000)))
10238 assign(t8, IRExpr_ITE(unop(Iop_32to1,
10239 mkexpr(t2)),
10240 mkU32(0x80000000),
10241 mkU32(0x7fffffff)));
10242 putIReg(rd, IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)),
10243 IRExpr_ITE(unop(Iop_32to1,
10244 mkexpr(t2)),
10245 mkU32(0x80000000),
10246 mkU32(0x7fffffff)),
10247 IRExpr_ITE(mkexpr(t7),
10248 unop(Iop_64to32,
10249 mkexpr(t3)),
10250 mkexpr(t8))));
10251 break;
10253 case 0x17: { /* SHRAV_R.W */
10254 DIP("shrav_r.w r%u, r%u, r%u", rd, rt, rs);
10255 vassert(!mode64);
10256 t0 = newTemp(Ity_I32);
10257 t1 = newTemp(Ity_I1);
10258 t2 = newTemp(Ity_I8);
10259 t3 = newTemp(Ity_I32);
10261 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
10262 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
10263 assign(t2, unop(Iop_32to8,
10264 binop(Iop_Sub32, mkexpr(t0), mkU32(1))));
10266 putIReg(rd, IRExpr_ITE(mkexpr(t1),
10267 getIReg(rt),
10268 binop(Iop_Sar32,
10269 binop(Iop_Add32,
10270 binop(Iop_Sar32,
10271 getIReg(rt),
10272 mkexpr(t2)),
10273 mkU32(0x1)),
10274 mkU8(1))));
10275 break;
10277 case 0x19: { /* SHRL.PH */
10278 DIP("shrl.ph r%u, r%u, %u", rd, rt, rs);
10279 vassert(!mode64);
10280 t0 = newTemp(Ity_I32);
10281 t1 = newTemp(Ity_I32);
10282 assign(t0, binop(Iop_Shr32,
10283 unop(Iop_16Uto32,
10284 unop(Iop_32to16, getIReg(rt))),
10285 mkU8(rs)));
10286 assign(t1, binop(Iop_Shr32,
10287 unop(Iop_16Uto32,
10288 unop(Iop_32HIto16, getIReg(rt))),
10289 mkU8(rs)));
10290 putIReg(rd, binop(Iop_16HLto32,
10291 unop(Iop_32to16, mkexpr(t1)),
10292 unop(Iop_32to16, mkexpr(t0))));
10293 break;
10295 case 0x1B: { /* SHRLV.PH */
10296 DIP("shrlv.ph r%u, r%u, r%u", rd, rt, rs);
10297 vassert(!mode64);
10298 t0 = newTemp(Ity_I32);
10299 t1 = newTemp(Ity_I1);
10300 t2 = newTemp(Ity_I32);
10301 t3 = newTemp(Ity_I32);
10302 t4 = newTemp(Ity_I16);
10303 t5 = newTemp(Ity_I16);
10305 /* Get shift amount from lower 5 bits of rs
10306 and check if it is zero. */
10307 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
10308 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
10310 assign(t2, binop(Iop_Shr32,
10311 unop(Iop_16Uto32,
10312 unop(Iop_32to16, getIReg(rt))),
10313 unop(Iop_32to8, mkexpr(t0))));
10314 assign(t3, binop(Iop_Shr32,
10315 unop(Iop_16Uto32,
10316 unop(Iop_32HIto16, getIReg(rt))),
10317 unop(Iop_32to8, mkexpr(t0))));
10319 assign(t4, IRExpr_ITE(mkexpr(t1),
10320 unop(Iop_32HIto16, getIReg(rt)),
10321 unop(Iop_32to16, mkexpr(t3))));
10322 assign(t5, IRExpr_ITE(mkexpr(t1),
10323 unop(Iop_32to16, getIReg(rt)),
10324 unop(Iop_32to16, mkexpr(t2))));
10325 putIReg(rd, binop(Iop_16HLto32, mkexpr(t4), mkexpr(t5)));
10326 break;
10328 default:
10329 return -1;
10331 break; /* end of SHLL.QB */
10333 case 0x18: { /* ADDUH.QB/MUL.PH */
10334 switch(sa) {
10335 case 0x00: { /* ADDUH.QB */
10336 DIP("adduh.qb r%u, r%u, r%u", rd, rs, rt);
10337 vassert(!mode64);
10338 t0 = newTemp(Ity_I32);
10340 assign(t0, binop(Iop_HAdd8Ux4, getIReg(rs), getIReg(rt)));
10342 putIReg(rd, mkexpr(t0));
10343 break;
10345 case 0x1: { /* SUBUH.QB */
10346 DIP("subuh.qb r%u, r%u, r%u", rd, rs, rt);
10347 vassert(!mode64);
10348 t0 = newTemp(Ity_I32);
10350 assign(t0, binop(Iop_HSub8Ux4, getIReg(rs), getIReg(rt)));
10352 putIReg(rd, mkexpr(t0));
10353 break;
10355 case 0x02: { /* ADDUH_R.QB */
10356 DIP("adduh_r.qb r%u, r%u, r%u", rd, rs, rt);
10357 vassert(!mode64);
10358 t0 = newTemp(Ity_I32);
10359 t1 = newTemp(Ity_I32);
10360 t2 = newTemp(Ity_I8);
10361 t3 = newTemp(Ity_I32);
10362 t4 = newTemp(Ity_I32);
10363 t5 = newTemp(Ity_I8);
10364 t6 = newTemp(Ity_I32);
10365 t7 = newTemp(Ity_I32);
10366 t8 = newTemp(Ity_I8);
10367 t9 = newTemp(Ity_I32);
10368 t10 = newTemp(Ity_I32);
10369 t11 = newTemp(Ity_I8);
10371 /* Extract input bytes, add values, add 1 and half the
10372 result. */
10373 assign(t0, unop(Iop_8Uto32,
10374 unop(Iop_16to8,
10375 unop(Iop_32to16, getIReg(rs)))));
10376 assign(t1, unop(Iop_8Uto32,
10377 unop(Iop_16to8,
10378 unop(Iop_32to16, getIReg(rt)))));
10379 assign(t2, unop(Iop_16to8,
10380 unop(Iop_32to16,
10381 binop(Iop_Shr32,
10382 binop(Iop_Add32,
10383 binop(Iop_Add32,
10384 mkexpr(t0),
10385 mkexpr(t1)),
10386 mkU32(0x00000001)),
10387 mkU8(0x01)))));
10389 assign(t3, unop(Iop_8Uto32,
10390 unop(Iop_16HIto8,
10391 unop(Iop_32to16, getIReg(rs)))));
10392 assign(t4, unop(Iop_8Uto32,
10393 unop(Iop_16HIto8,
10394 unop(Iop_32to16, getIReg(rt)))));
10395 assign(t5, unop(Iop_16to8,
10396 unop(Iop_32to16,
10397 binop(Iop_Shr32,
10398 binop(Iop_Add32,
10399 binop(Iop_Add32,
10400 mkexpr(t3),
10401 mkexpr(t4)),
10402 mkU32(0x00000001)),
10403 mkU8(0x01)))));
10405 assign(t6, unop(Iop_8Uto32,
10406 unop(Iop_16to8,
10407 unop(Iop_32HIto16, getIReg(rs)))));
10408 assign(t7, unop(Iop_8Uto32,
10409 unop(Iop_16to8,
10410 unop(Iop_32HIto16, getIReg(rt)))));
10411 assign(t8, unop(Iop_16to8,
10412 unop(Iop_32to16,
10413 binop(Iop_Shr32,
10414 binop(Iop_Add32,
10415 binop(Iop_Add32,
10416 mkexpr(t7),
10417 mkexpr(t6)),
10418 mkU32(0x00000001)),
10419 mkU8(0x01)))));
10421 assign(t9, unop(Iop_8Uto32,
10422 unop(Iop_16HIto8,
10423 unop(Iop_32HIto16, getIReg(rs)))));
10424 assign(t10, unop(Iop_8Uto32,
10425 unop(Iop_16HIto8,
10426 unop(Iop_32HIto16, getIReg(rt)))));
10427 assign(t11, unop(Iop_16to8,
10428 unop(Iop_32to16,
10429 binop(Iop_Shr32,
10430 binop(Iop_Add32,
10431 binop(Iop_Add32,
10432 mkexpr(t9),
10433 mkexpr(t10)),
10434 mkU32(0x00000001)),
10435 mkU8(0x01)))));
10437 putIReg(rd, binop(Iop_16HLto32,
10438 binop(Iop_8HLto16,
10439 mkexpr(t11), mkexpr(t8)),
10440 binop(Iop_8HLto16,
10441 mkexpr(t5), mkexpr(t2))));
10442 break;
10444 case 0x3: { /* SUBUH_R.QB */
10445 DIP("subuh_r.qb r%u, r%u, r%u", rd, rs, rt);
10446 vassert(!mode64);
10447 t1 = newTemp(Ity_I32);
10448 t2 = newTemp(Ity_I32);
10449 t3 = newTemp(Ity_I32);
10450 t4 = newTemp(Ity_I32);
10451 t5 = newTemp(Ity_I32);
10452 t6 = newTemp(Ity_I32);
10453 t7 = newTemp(Ity_I32);
10454 t8 = newTemp(Ity_I32);
10455 t9 = newTemp(Ity_I8);
10456 t10 = newTemp(Ity_I8);
10457 t11 = newTemp(Ity_I8);
10458 t12 = newTemp(Ity_I8);
10460 /* Extract each byte of rs and rt. */
10461 assign(t1, unop(Iop_8Uto32,
10462 unop(Iop_16to8,
10463 unop(Iop_32to16, getIReg(rs)))));
10464 assign(t2, unop(Iop_8Uto32,
10465 unop(Iop_16HIto8,
10466 unop(Iop_32to16, getIReg(rs)))));
10467 assign(t3, unop(Iop_8Uto32,
10468 unop(Iop_16to8,
10469 unop(Iop_32HIto16, getIReg(rs)))));
10470 assign(t4, unop(Iop_8Uto32,
10471 unop(Iop_16HIto8,
10472 unop(Iop_32HIto16, getIReg(rs)))));
10474 assign(t5, unop(Iop_8Uto32,
10475 unop(Iop_16to8,
10476 unop(Iop_32to16, getIReg(rt)))));
10477 assign(t6, unop(Iop_8Uto32,
10478 unop(Iop_16HIto8,
10479 unop(Iop_32to16, getIReg(rt)))));
10480 assign(t7, unop(Iop_8Uto32,
10481 unop(Iop_16to8,
10482 unop(Iop_32HIto16, getIReg(rt)))));
10483 assign(t8, unop(Iop_8Uto32,
10484 unop(Iop_16HIto8,
10485 unop(Iop_32HIto16, getIReg(rt)))));
10487 /* Add 1 to each resulting byte and half the results. */
10488 assign(t9, unop(Iop_16to8,
10489 unop(Iop_32to16,
10490 binop(Iop_Shr32,
10491 binop(Iop_Add32,
10492 binop(Iop_Sub32,
10493 mkexpr(t1),
10494 mkexpr(t5)),
10495 mkU32(0x00000001)),
10496 mkU8(0x01)))));
10497 assign(t10, unop(Iop_16to8,
10498 unop(Iop_32to16,
10499 binop(Iop_Shr32,
10500 binop(Iop_Add32,
10501 binop(Iop_Sub32,
10502 mkexpr(t2),
10503 mkexpr(t6)),
10504 mkU32(0x00000001)),
10505 mkU8(0x01)))));
10506 assign(t11, unop(Iop_16to8,
10507 unop(Iop_32to16,
10508 binop(Iop_Shr32,
10509 binop(Iop_Add32,
10510 binop(Iop_Sub32,
10511 mkexpr(t3),
10512 mkexpr(t7)),
10513 mkU32(0x00000001)),
10514 mkU8(0x01)))));
10515 assign(t12, unop(Iop_16to8,
10516 unop(Iop_32to16,
10517 binop(Iop_Shr32,
10518 binop(Iop_Add32,
10519 binop(Iop_Sub32,
10520 mkexpr(t4),
10521 mkexpr(t8)),
10522 mkU32(0x00000001)),
10523 mkU8(0x01)))));
10525 putIReg(rd, binop(Iop_16HLto32,
10526 binop(Iop_8HLto16,
10527 mkexpr(t12), mkexpr(t11)),
10528 binop(Iop_8HLto16,
10529 mkexpr(t10), mkexpr(t9))));
10530 break;
10532 case 0x8: { /* ADDQH.PH */
10533 DIP("addqh.ph r%u, r%u, r%u", rd, rs, rt);
10534 vassert(!mode64);
10535 t0 = newTemp(Ity_I32);
10536 t1 = newTemp(Ity_I16);
10537 t2 = newTemp(Ity_I32);
10538 t3 = newTemp(Ity_I16);
10540 /* Add lower halfs of rs and rt
10541 and right shift the result by 1. */
10542 assign(t0, binop(Iop_Add32,
10543 unop(Iop_16Sto32,
10544 unop(Iop_32to16, getIReg(rs))),
10545 unop(Iop_16Sto32,
10546 unop(Iop_32to16, getIReg(rt)))));
10547 assign(t1, unop(Iop_32to16,
10548 binop(Iop_Shr32,
10549 binop(Iop_And32,
10550 mkexpr(t0),
10551 mkU32(0x0001fffe)),
10552 mkU8(0x1))));
10553 /* Add higher halfs of rs and rt
10554 and right shift the result by 1. */
10555 assign(t2, binop(Iop_Add32,
10556 unop(Iop_16Sto32,
10557 unop(Iop_32HIto16, getIReg(rs))),
10558 unop(Iop_16Sto32,
10559 unop(Iop_32HIto16, getIReg(rt)))));
10560 assign(t3, unop(Iop_32to16,
10561 binop(Iop_Shr32,
10562 binop(Iop_And32,
10563 mkexpr(t2),
10564 mkU32(0x0001fffe)),
10565 mkU8(0x1))));
10566 putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
10567 break;
10569 case 0x9: { /* SUBQH.PH */
10570 DIP("subqh.ph r%u, r%u, r%u", rd, rs, rt);
10571 vassert(!mode64);
10573 putIReg(rd, binop(Iop_HSub16Sx2,
10574 getIReg(rs), getIReg(rt)));
10575 break;
10577 case 0xA: {/* ADDQH_R.PH */
10578 DIP("addqh_r.ph r%u, r%u, r%u", rd, rs, rt);
10579 vassert(!mode64);
10580 t0 = newTemp(Ity_I32);
10581 t1 = newTemp(Ity_I16);
10582 t2 = newTemp(Ity_I32);
10583 t3 = newTemp(Ity_I16);
10585 /* Add lower halfs of rs and rt, add 1
10586 and right shift the result by 1. */
10587 assign(t0, binop(Iop_Add32,
10588 unop(Iop_16Sto32,
10589 unop(Iop_32to16, getIReg(rs))),
10590 unop(Iop_16Sto32,
10591 unop(Iop_32to16, getIReg(rt)))));
10592 assign(t1, unop(Iop_32to16,
10593 binop(Iop_Shr32,
10594 binop(Iop_And32,
10595 binop(Iop_Add32,
10596 mkexpr(t0),
10597 mkU32(0x1)),
10598 mkU32(0x0001fffe)),
10599 mkU8(0x1))));
10600 /* Add higher halfs of rs and rt, add 1
10601 and right shift the result by 1. */
10602 assign(t2, binop(Iop_Add32,
10603 unop(Iop_16Sto32,
10604 unop(Iop_32HIto16, getIReg(rs))),
10605 unop(Iop_16Sto32,
10606 unop(Iop_32HIto16, getIReg(rt)))));
10607 assign(t3, unop(Iop_32to16,
10608 binop(Iop_Shr32,
10609 binop(Iop_And32,
10610 binop(Iop_Add32,
10611 mkexpr(t2),
10612 mkU32(0x1)),
10613 mkU32(0x0001fffe)),
10614 mkU8(0x1))));
10616 putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
10617 break;
10619 case 0xB: { /* SUBQH_R.PH */
10620 DIP("subqh_r.ph r%u, r%u, r%u", rd, rs, rt);
10621 vassert(!mode64);
10622 t0 = newTemp(Ity_I32);
10623 t1 = newTemp(Ity_I16);
10624 t2 = newTemp(Ity_I32);
10625 t3 = newTemp(Ity_I16);
10627 /* Sub lower halfs of rs and rt, add 1
10628 and right shift the result by 1. */
10629 assign(t0, binop(Iop_Sub32,
10630 unop(Iop_16Sto32,
10631 unop(Iop_32to16, getIReg(rs))),
10632 unop(Iop_16Sto32,
10633 unop(Iop_32to16, getIReg(rt)))));
10634 assign(t1, unop(Iop_32to16,
10635 binop(Iop_Shr32,
10636 binop(Iop_And32,
10637 binop(Iop_Add32,
10638 mkexpr(t0),
10639 mkU32(0x1)),
10640 mkU32(0x0001fffe)),
10641 mkU8(0x1))));
10642 /* Sub higher halfs of rs and rt, add 1
10643 and right shift the result by 1. */
10644 assign(t2, binop(Iop_Sub32,
10645 unop(Iop_16Sto32,
10646 unop(Iop_32HIto16, getIReg(rs))),
10647 unop(Iop_16Sto32,
10648 unop(Iop_32HIto16, getIReg(rt)))));
10649 assign(t3, unop(Iop_32to16,
10650 binop(Iop_Shr32,
10651 binop(Iop_And32,
10652 binop(Iop_Add32,
10653 mkexpr(t2),
10654 mkU32(0x1)),
10655 mkU32(0x0001fffe)),
10656 mkU8(0x1))));
10658 putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
10659 break;
10661 case 0xC: { /* MUL.PH */
10662 DIP("mul.ph r%u, r%u, r%u", rd, rs, rt);
10663 vassert(!mode64);
10664 t0 = newTemp(Ity_I32);
10665 t1 = newTemp(Ity_I32);
10666 t2 = newTemp(Ity_I32);
10668 assign(t0,
10669 binop(Iop_Mul32,
10670 unop(Iop_16Sto32,
10671 unop(Iop_32HIto16, getIReg(rs))),
10672 unop(Iop_16Sto32,
10673 unop(Iop_32HIto16, getIReg(rt)))));
10674 /* DSP Control flag. */
10675 putDSPControl(IRExpr_ITE(unop(Iop_Not1,
10676 binop(Iop_CmpLE32S,
10677 mkexpr(t0),
10678 mkU32(0x7FFF))),
10679 binop(Iop_Or32,
10680 getDSPControl(),
10681 mkU32(0x00200000)),
10682 IRExpr_ITE(binop(Iop_CmpLT32S,
10683 mkexpr(t0),
10684 mkU32(0xFFFF8000)
10686 binop(Iop_Or32,
10687 getDSPControl(),
10688 mkU32(0x00200000)
10690 getDSPControl())));
10692 assign(t1,
10693 binop(Iop_Mul32,
10694 unop(Iop_16Sto32,
10695 unop(Iop_32to16, getIReg(rs))),
10696 unop(Iop_16Sto32,
10697 unop(Iop_32to16, getIReg(rt)))));
10698 /* DSP Control flag. */
10699 putDSPControl(IRExpr_ITE(unop(Iop_Not1,
10700 binop(Iop_CmpLE32S,
10701 mkexpr(t1),
10702 mkU32(0x7FFF))),
10703 binop(Iop_Or32,
10704 getDSPControl(),
10705 mkU32(0x00200000)),
10706 IRExpr_ITE(binop(Iop_CmpLT32S,
10707 mkexpr(t1),
10708 mkU32(0xFFFF8000)
10710 binop(Iop_Or32,
10711 getDSPControl(),
10712 mkU32(0x00200000)
10714 getDSPControl())));
10716 assign(t2, binop(Iop_16HLto32,
10717 unop(Iop_32to16, mkexpr(t0)),
10718 unop(Iop_32to16, mkexpr(t1))));
10719 putIReg(rd, mkexpr(t2));
10720 break;
10722 case 0xE: { /* MUL_S.PH */
10723 DIP("mul_s.ph r%u r%u, r%u", rd, rs, rt);
10724 vassert(!mode64);
10726 t0 = newTemp(Ity_I32);
10727 t1 = newTemp(Ity_I32);
10728 t2 = newTemp(Ity_I32);
10729 t3 = newTemp(Ity_I32);
10730 t4 = newTemp(Ity_I32);
10732 /* t0 - signed intermediate result. */
10733 assign(t0,
10734 binop(Iop_Mul32,
10735 unop(Iop_16Sto32,
10736 unop(Iop_32HIto16, getIReg(rs))),
10737 unop(Iop_16Sto32,
10738 unop(Iop_32HIto16, getIReg(rt)))));
10740 assign(t1,
10741 IRExpr_ITE(unop(Iop_Not1,
10742 binop(Iop_CmpLE32S,
10743 mkexpr(t0),
10744 mkU32(0x7FFF))),
10745 mkU32(0x00007FFF),
10746 IRExpr_ITE(binop(Iop_CmpLT32S,
10747 mkexpr(t0),
10748 mkU32(0xFFFF8000)),
10749 mkU32(0xFFFF8000),
10750 mkexpr(t0))));
10752 /* DSP Control flag. */
10753 putDSPControl(IRExpr_ITE(unop(Iop_Not1,
10754 binop(Iop_CmpLE32S,
10755 mkexpr(t0),
10756 mkU32(0x7FFF))),
10757 binop(Iop_Or32,
10758 getDSPControl(),
10759 mkU32(0x00200000)),
10760 IRExpr_ITE(binop(Iop_CmpLT32S,
10761 mkexpr(t0),
10762 mkU32(0xFFFF8000)
10764 binop(Iop_Or32,
10765 getDSPControl(),
10766 mkU32(0x00200000)
10768 getDSPControl())));
10770 /* t2 - signed intermediate result. */
10771 assign(t2, binop(Iop_Mul32,
10772 unop(Iop_16Sto32,
10773 unop(Iop_32to16, getIReg(rs))),
10774 unop(Iop_16Sto32,
10775 unop(Iop_32to16, getIReg(rt)))));
10777 assign(t3, IRExpr_ITE(unop(Iop_Not1,
10778 binop(Iop_CmpLE32S,
10779 mkexpr(t2),
10780 mkU32(0x7FFF))),
10781 mkU32(0x00007FFF),
10782 IRExpr_ITE(binop(Iop_CmpLT32S,
10783 mkexpr(t2),
10784 mkU32(0xFFFF8000)),
10785 mkU32(0xFFFF8000),
10786 mkexpr(t2))));
10788 /* DSP Control flag. */
10789 putDSPControl(IRExpr_ITE(unop(Iop_Not1,
10790 binop(Iop_CmpLE32S,
10791 mkexpr(t2),
10792 mkU32(0x7FFF))),
10793 binop(Iop_Or32,
10794 getDSPControl(),
10795 mkU32(0x00200000)),
10796 IRExpr_ITE(binop(Iop_CmpLT32S,
10797 mkexpr(t2),
10798 mkU32(0xFFFF8000)
10800 binop(Iop_Or32,
10801 getDSPControl(),
10802 mkU32(0x00200000)
10804 getDSPControl())));
10806 assign(t4, binop(Iop_16HLto32,
10807 unop(Iop_32to16, mkexpr(t1)),
10808 unop(Iop_32to16, mkexpr(t3))));
10809 putIReg(rd, mkexpr(t4));
10810 break;
10812 case 0x10: { /* ADDQH.W */
10813 DIP("addqh.w r%u, r%u, r%u", rd, rs, rt);
10814 vassert(!mode64);
10815 t0 = newTemp(Ity_I64);
10816 t1 = newTemp(Ity_I64);
10818 assign(t0, binop(Iop_Add64,
10819 unop(Iop_32Sto64, getIReg(rs)),
10820 unop(Iop_32Sto64, getIReg(rt))));
10821 assign(t1, binop(Iop_And64,
10822 mkexpr(t0),
10823 mkU64(0x00000001fffffffeULL)));
10824 putIReg(rd, unop(Iop_64to32,
10825 binop(Iop_Shr64, mkexpr(t1), mkU8(0x1))));
10826 break;
10828 case 0x11: { /* SUBQH.W */
10829 DIP("subqh.w r%u, r%u, r%u", rd, rs, rt);
10830 vassert(!mode64);
10831 t0 = newTemp(Ity_I64);
10832 t1 = newTemp(Ity_I64);
10834 assign(t0, binop(Iop_Sub64,
10835 unop(Iop_32Sto64, getIReg(rs)),
10836 unop(Iop_32Sto64, getIReg(rt))));
10837 assign(t1, binop(Iop_And64,
10838 mkexpr(t0),
10839 mkU64(0x00000001fffffffeULL)));
10840 putIReg(rd, unop(Iop_64to32,
10841 binop(Iop_Shr64, mkexpr(t1), mkU8(0x1))));
10842 break;
10844 case 0x12: { /* ADDQH_R.W */
10845 DIP("addqh_r.w r%u, r%u, r%u", rd, rs, rt);
10846 vassert(!mode64);
10847 t0 = newTemp(Ity_I64);
10848 t1 = newTemp(Ity_I64);
10849 t2 = newTemp(Ity_I64);
10851 assign(t0, binop(Iop_Add64,
10852 unop(Iop_32Sto64, getIReg(rs)),
10853 unop(Iop_32Sto64, getIReg(rt))));
10854 assign(t1, binop(Iop_Add64,
10855 mkexpr(t0),
10856 mkU64(0x0000000000000001ULL)));
10857 assign(t2, binop(Iop_And64,
10858 mkexpr(t1),
10859 mkU64(0x00000001fffffffeULL)));
10860 putIReg(rd, unop(Iop_64to32,
10861 binop(Iop_Shr64, mkexpr(t2), mkU8(0x1))));
10862 break;
10864 case 0x13: { /* SUBQH_R.W */
10865 DIP("subqh_r.w r%u, r%u, r%u", rd, rs, rt);
10866 vassert(!mode64);
10867 t0 = newTemp(Ity_I64);
10868 t1 = newTemp(Ity_I64);
10869 t2 = newTemp(Ity_I64);
10871 assign(t0, binop(Iop_Sub64,
10872 unop(Iop_32Sto64, getIReg(rs)),
10873 unop(Iop_32Sto64, getIReg(rt))));
10874 assign(t1, binop(Iop_Add64,
10875 mkexpr(t0),
10876 mkU64(0x0000000000000001ULL)));
10877 assign(t2, binop(Iop_And64,
10878 mkexpr(t1),
10879 mkU64(0x00000001fffffffeULL)));
10880 putIReg(rd, unop(Iop_64to32,
10881 binop(Iop_Shr64, mkexpr(t2), mkU8(0x1))));
10882 break;
10884 case 0x16: { /* MULQ_S.W */
10885 DIP("mulq_s.w r%u, r%u, r%u", rd, rs, rt);
10886 vassert(!mode64);
10887 t0 = newTemp(Ity_I64);
10888 t1 = newTemp(Ity_I1);
10889 t2 = newTemp(Ity_I1);
10891 assign(t0, binop(Iop_Shl64,
10892 binop(Iop_MullS32,
10893 getIReg(rt), getIReg(rs)),
10894 mkU8(0x1)));
10895 assign(t1, binop(Iop_CmpEQ32,
10896 getIReg(rt), mkU32(0x80000000)));
10897 assign(t2, binop(Iop_CmpEQ32,
10898 getIReg(rs), mkU32(0x80000000)));
10900 putDSPControl(IRExpr_ITE(mkexpr(t1),
10901 IRExpr_ITE(mkexpr(t2),
10902 binop(Iop_Or32,
10903 getDSPControl(),
10904 mkU32(0x00200000)
10906 getDSPControl()),
10907 getDSPControl()));
10908 putIReg(rd, IRExpr_ITE(mkexpr(t1),
10909 IRExpr_ITE(mkexpr(t2),
10910 mkU32(0x7fffffff),
10911 unop(Iop_64HIto32,
10912 mkexpr(t0))),
10913 unop(Iop_64HIto32, mkexpr(t0))));
10914 break;
10916 case 0x17: { /* MULQ_RS.W */
10917 DIP("mulq_rs.w r%u, r%u, r%u", rd, rs, rt);
10918 vassert(!mode64);
10919 t0 = newTemp(Ity_I64);
10920 t1 = newTemp(Ity_I1);
10921 t2 = newTemp(Ity_I1);
10923 assign(t0, binop(Iop_Add64,
10924 binop(Iop_Shl64,
10925 binop(Iop_MullS32,
10926 getIReg(rt),
10927 getIReg(rs)),
10928 mkU8(0x1)),
10929 mkU64(0x0000000080000000ULL)));
10930 assign(t1,
10931 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000)));
10932 assign(t2,
10933 binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x80000000)));
10934 putDSPControl(IRExpr_ITE(mkexpr(t1),
10935 IRExpr_ITE(mkexpr(t2),
10936 binop(Iop_Or32,
10937 getDSPControl(),
10938 mkU32(0x00200000)
10940 getDSPControl()),
10941 getDSPControl()));
10942 putIReg(rd, IRExpr_ITE(mkexpr(t1),
10943 IRExpr_ITE(mkexpr(t2),
10944 mkU32(0x7fffffff),
10945 unop(Iop_64HIto32,
10946 mkexpr(t0))),
10947 unop(Iop_64HIto32, mkexpr(t0))));
10948 break;
10950 default:
10951 return -1;
10953 break; /* end of ADDUH.QB/MUL.PH */
10955 case 0x30: { /* DPAQ.W.PH */
10956 switch(sa) {
10957 case 0x0: { /* DPA.W.PH */
10958 DIP("dpa.w.ph ac%u, r%u, r%u", ac, rs, rt);
10959 vassert(!mode64);
10961 t0 = newTemp(Ity_I64);
10962 t1 = newTemp(Ity_I64);
10963 t2 = newTemp(Ity_I64);
10965 assign(t0,
10966 unop(Iop_32Sto64,
10967 binop(Iop_Mul32,
10968 unop(Iop_16Sto32,
10969 unop(Iop_32HIto16, getIReg(rs))),
10970 unop(Iop_16Sto32,
10971 unop(Iop_32HIto16, getIReg(rt))))));
10972 assign(t1,
10973 unop(Iop_32Sto64,
10974 binop(Iop_Mul32,
10975 unop(Iop_16Sto32,
10976 unop(Iop_32to16, getIReg(rs))),
10977 unop(Iop_16Sto32,
10978 unop(Iop_32to16, getIReg(rt))))));
10979 assign(t2,
10980 binop(Iop_Add64,
10981 getAcc(ac),
10982 binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
10983 putAcc(ac, mkexpr(t2));
10984 break;
10986 case 0x1: { /* DPS.W.PH */
10987 DIP("dps.w.ph ac%u, r%u, r%u", ac, rs, rt);
10988 vassert(!mode64);
10990 t0 = newTemp(Ity_I64);
10991 t1 = newTemp(Ity_I64);
10992 t2 = newTemp(Ity_I64);
10994 assign(t0,
10995 unop(Iop_32Sto64,
10996 binop(Iop_Mul32,
10997 unop(Iop_16Sto32,
10998 unop(Iop_32HIto16, getIReg(rs))),
10999 unop(Iop_16Sto32,
11000 unop(Iop_32HIto16, getIReg(rt))))));
11001 assign(t1,
11002 unop(Iop_32Sto64,
11003 binop(Iop_Mul32,
11004 unop(Iop_16Sto32,
11005 unop(Iop_32to16, getIReg(rs))),
11006 unop(Iop_16Sto32,
11007 unop(Iop_32to16, getIReg(rt))))));
11008 assign(t2,
11009 binop(Iop_Sub64,
11010 getAcc(ac),
11011 binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
11012 putAcc(ac, mkexpr(t2));
11013 break;
11015 case 0x2: { /* MULSA.W.PH */
11016 DIP("mulsa.w.ph ac%u, r%u, r%u", ac, rs, rt);
11017 vassert(!mode64);
11018 t0 = newTemp(Ity_I32);
11019 t1 = newTemp(Ity_I32);
11020 t2 = newTemp(Ity_I32);
11021 t3 = newTemp(Ity_I1);
11022 t4 = newTemp(Ity_I64);
11024 assign(t4, getAcc(ac));
11025 assign(t0, binop(Iop_Mul32,
11026 unop(Iop_16Sto32,
11027 unop(Iop_32to16, getIReg(rt))),
11028 unop(Iop_16Sto32,
11029 unop(Iop_32to16, getIReg(rs)))));
11030 assign(t1, binop(Iop_Mul32,
11031 unop(Iop_16Sto32,
11032 unop(Iop_32HIto16, getIReg(rt))),
11033 unop(Iop_16Sto32,
11034 unop(Iop_32HIto16, getIReg(rs)))));
11035 assign(t2, binop(Iop_Sub32, mkexpr(t1), mkexpr(t0)));
11036 putAcc(ac, binop(Iop_Add64,
11037 mkexpr(t4),
11038 unop(Iop_32Sto64, mkexpr(t2))));
11039 break;
11041 case 0x3: { /* DPAU.H.QBL */
11042 DIP("dpau.h.qbl ac%u, r%u, r%u", ac, rs, rt);
11043 vassert(!mode64);
11044 t0 = newTemp(Ity_I32);
11045 t1 = newTemp(Ity_I32);
11046 t2 = newTemp(Ity_I64);
11047 t3 = newTemp(Ity_I64);
11049 assign(t0,
11050 binop(Iop_Mul32,
11051 unop(Iop_8Uto32,
11052 unop(Iop_16HIto8,
11053 unop(Iop_32HIto16, getIReg(rs)))),
11054 unop(Iop_8Uto32,
11055 unop(Iop_16HIto8,
11056 unop(Iop_32HIto16, getIReg(rt))))));
11057 assign(t1,
11058 binop(Iop_Mul32,
11059 unop(Iop_8Uto32,
11060 unop(Iop_16to8,
11061 unop(Iop_32HIto16, getIReg(rs)))),
11062 unop(Iop_8Uto32,
11063 unop(Iop_16to8,
11064 unop(Iop_32HIto16, getIReg(rt))))));
11065 assign(t2,
11066 unop(Iop_32Uto64,
11067 binop(Iop_Add32,
11068 mkexpr(t0),
11069 mkexpr(t1))));
11070 assign(t3,
11071 binop(Iop_Add64, getAcc(ac), mkexpr(t2)));
11072 putAcc(ac, mkexpr(t3));
11073 break;
11075 case 0x4: { /* DPAQ_S.W.PH */
11076 DIP("dpaq_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
11077 vassert(!mode64);
11078 t0 = newTemp(Ity_I64);
11079 t1 = newTemp(Ity_I64);
11080 t2 = newTemp(Ity_I1);
11081 t3 = newTemp(Ity_I1);
11082 t4 = newTemp(Ity_I64);
11083 t5 = newTemp(Ity_I64);
11084 t6 = newTemp(Ity_I1);
11085 t7 = newTemp(Ity_I1);
11086 t8 = newTemp(Ity_I64);
11087 t9 = newTemp(Ity_I64);
11089 assign(t0, getAcc(ac));
11091 assign(t1, binop(Iop_Shl64,
11092 binop(Iop_MullS32,
11093 unop(Iop_16Sto32,
11094 unop(Iop_32HIto16,
11095 getIReg(rs))),
11096 unop(Iop_16Sto32,
11097 unop(Iop_32HIto16,
11098 getIReg(rt)))),
11099 mkU8(0x1)));
11100 assign(t2, binop(Iop_CmpEQ32,
11101 unop(Iop_16Uto32,
11102 unop(Iop_32HIto16, getIReg(rs))),
11103 mkU32(0x00008000)));
11104 assign(t3, binop(Iop_CmpEQ32,
11105 unop(Iop_16Uto32,
11106 unop(Iop_32HIto16, getIReg(rt))),
11107 mkU32(0x00008000)));
11108 assign(t4,
11109 IRExpr_ITE(mkexpr(t2),
11110 IRExpr_ITE(mkexpr(t3),
11111 mkU64(0x000000007fffffffULL),
11112 mkexpr(t1)),
11113 mkexpr(t1)));
11115 putDSPControl(IRExpr_ITE(mkexpr(t2),
11116 IRExpr_ITE(mkexpr(t3),
11117 binop(Iop_Or32,
11118 getDSPControl(),
11119 binop(Iop_Shl32,
11120 mkU32(0x1),
11121 mkU8(ac+16)
11124 getDSPControl()),
11125 getDSPControl()));
11127 assign(t5, binop(Iop_Shl64,
11128 binop(Iop_MullS32,
11129 unop(Iop_16Sto32,
11130 unop(Iop_32to16, getIReg(rs))),
11131 unop(Iop_16Sto32,
11132 unop(Iop_32to16, getIReg(rt)))
11134 mkU8(0x1)));
11135 assign(t6, binop(Iop_CmpEQ32,
11136 unop(Iop_16Uto32,
11137 unop(Iop_32to16, getIReg(rs))),
11138 mkU32(0x00008000)));
11139 assign(t7, binop(Iop_CmpEQ32,
11140 unop(Iop_16Uto32,
11141 unop(Iop_32to16, getIReg(rt))),
11142 mkU32(0x00008000)));
11143 assign(t8,
11144 IRExpr_ITE(mkexpr(t6),
11145 IRExpr_ITE(mkexpr(t7),
11146 mkU64(0x000000007fffffffULL),
11147 mkexpr(t5)),
11148 mkexpr(t5)));
11150 putDSPControl(IRExpr_ITE(mkexpr(t6),
11151 IRExpr_ITE(mkexpr(t7),
11152 binop(Iop_Or32,
11153 getDSPControl(),
11154 binop(Iop_Shl32,
11155 mkU32(0x1),
11156 mkU8(ac+16)
11159 getDSPControl()),
11160 getDSPControl()));
11162 assign(t9, binop(Iop_Add64,
11163 binop(Iop_Add64, mkexpr(t4), mkexpr(t8)),
11164 mkexpr(t0)));
11165 putAcc(ac, mkexpr(t9));
11166 break;
11168 case 0x5: { /* DPSQ_S.W.PH */
11169 DIP("dpsq_s.w.ph ac%u r%u, r%u", ac, rs, rt);
11170 vassert(!mode64);
11171 t0 = newTemp(Ity_I64);
11172 t1 = newTemp(Ity_I64);
11173 t2 = newTemp(Ity_I1);
11174 t3 = newTemp(Ity_I1);
11175 t4 = newTemp(Ity_I64);
11176 t5 = newTemp(Ity_I64);
11177 t6 = newTemp(Ity_I1);
11178 t7 = newTemp(Ity_I1);
11179 t8 = newTemp(Ity_I64);
11180 t9 = newTemp(Ity_I64);
11182 assign(t0, getAcc(ac));
11184 assign(t1, binop(Iop_Shl64,
11185 binop(Iop_MullS32,
11186 unop(Iop_16Sto32,
11187 unop(Iop_32HIto16,
11188 getIReg(rs))),
11189 unop(Iop_16Sto32,
11190 unop(Iop_32HIto16,
11191 getIReg(rt)))),
11192 mkU8(0x1)));
11193 assign(t2, binop(Iop_CmpEQ32,
11194 unop(Iop_16Uto32,
11195 unop(Iop_32HIto16, getIReg(rs))),
11196 mkU32(0x00008000)));
11197 assign(t3, binop(Iop_CmpEQ32,
11198 unop(Iop_16Uto32,
11199 unop(Iop_32HIto16, getIReg(rt))),
11200 mkU32(0x00008000)));
11201 assign(t4,
11202 IRExpr_ITE(mkexpr(t2),
11203 IRExpr_ITE(mkexpr(t3),
11204 mkU64(0x000000007fffffffULL),
11205 mkexpr(t1)),
11206 mkexpr(t1)));
11208 putDSPControl(IRExpr_ITE(mkexpr(t2),
11209 IRExpr_ITE(mkexpr(t3),
11210 binop(Iop_Or32,
11211 getDSPControl(),
11212 binop(Iop_Shl32,
11213 mkU32(0x1),
11214 mkU8(ac+16)
11217 getDSPControl()),
11218 getDSPControl()));
11220 assign(t5,
11221 binop(Iop_Shl64,
11222 binop(Iop_MullS32,
11223 unop(Iop_16Sto32,
11224 unop(Iop_32to16, getIReg(rs))),
11225 unop(Iop_16Sto32,
11226 unop(Iop_32to16, getIReg(rt)))),
11227 mkU8(0x1)));
11228 assign(t6, binop(Iop_CmpEQ32,
11229 unop(Iop_16Uto32,
11230 unop(Iop_32to16, getIReg(rs))),
11231 mkU32(0x00008000)));
11232 assign(t7, binop(Iop_CmpEQ32,
11233 unop(Iop_16Uto32,
11234 unop(Iop_32to16, getIReg(rt))),
11235 mkU32(0x00008000)));
11236 assign(t8,
11237 IRExpr_ITE(mkexpr(t6),
11238 IRExpr_ITE(mkexpr(t7),
11239 mkU64(0x000000007fffffffULL),
11240 mkexpr(t5)),
11241 mkexpr(t5)));
11243 putDSPControl(IRExpr_ITE(mkexpr(t6),
11244 IRExpr_ITE(mkexpr(t7),
11245 binop(Iop_Or32,
11246 getDSPControl(),
11247 binop(Iop_Shl32,
11248 mkU32(0x1),
11249 mkU8(ac+16)
11252 getDSPControl()),
11253 getDSPControl()));
11255 assign(t9,
11256 binop(Iop_Sub64,
11257 mkexpr(t0),
11258 binop(Iop_Add64, mkexpr(t4), mkexpr(t8))));
11259 putAcc(ac, mkexpr(t9));
11260 break;
11262 case 0x6: { /* MULSAQ_S.W.PH */
11263 DIP("mulsaq_s.w.ph ac%u r%u, r%u", ac, rs, rt);
11264 vassert(!mode64);
11266 t0 = newTemp(Ity_I32);
11267 t1 = newTemp(Ity_I32);
11268 t2 = newTemp(Ity_I32);
11269 t3 = newTemp(Ity_I32);
11270 t4 = newTemp(Ity_I32);
11271 t5 = newTemp(Ity_I32);
11272 t6 = newTemp(Ity_I64);
11273 t7 = newTemp(Ity_I64);
11274 t8 = newTemp(Ity_I32);
11275 t9 = newTemp(Ity_I32);
11277 assign(t0, unop(Iop_16Sto32,
11278 unop(Iop_32HIto16, getIReg(rs))));
11279 assign(t1, unop(Iop_16Sto32,
11280 unop(Iop_32HIto16, getIReg(rt))));
11282 assign(t8, binop(Iop_And32,
11283 unop(Iop_1Sto32,
11284 binop(Iop_CmpEQ32,
11285 unop(Iop_16Uto32,
11286 unop(Iop_32HIto16,
11287 getIReg(rs))),
11288 mkU32(0x8000))),
11289 unop(Iop_1Sto32,
11290 binop(Iop_CmpEQ32,
11291 unop(Iop_16Uto32,
11292 unop(Iop_32HIto16,
11293 getIReg(rt))),
11294 mkU32(0x8000)))));
11295 /* DSPControl_outflag:16+acc <- 1 */
11296 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
11297 mkexpr(t8),
11298 mkU32(0x0)),
11299 binop(Iop_Or32,
11300 getDSPControl(),
11301 binop(Iop_Shl32,
11302 mkU32(0x00010000),
11303 mkU8(ac))),
11304 getDSPControl()));
11306 /* tempB_31..0 */
11307 assign(t2,
11308 IRExpr_ITE(binop(Iop_CmpNE32,
11309 mkexpr(t8), mkU32(0x0)),
11310 mkU32(0x7FFFFFFF),
11311 binop(Iop_Shl32,
11312 binop(Iop_Mul32,
11313 mkexpr(t0), mkexpr(t1)),
11314 mkU8(1))));
11316 assign(t3, unop(Iop_16Sto32,
11317 unop(Iop_32to16, getIReg(rs))));
11318 assign(t4, unop(Iop_16Sto32,
11319 unop(Iop_32to16, getIReg(rt))));
11321 assign(t9, binop(Iop_And32,
11322 unop(Iop_1Sto32,
11323 binop(Iop_CmpEQ32,
11324 unop(Iop_16Uto32,
11325 unop(Iop_32to16,
11326 getIReg(rs))),
11327 mkU32(0x8000))),
11328 unop(Iop_1Sto32,
11329 binop(Iop_CmpEQ32,
11330 unop(Iop_16Uto32,
11331 unop(Iop_32to16,
11332 getIReg(rt))),
11333 mkU32(0x8000)))));
11334 /* DSPControl_outflag:16+acc <- 1 */
11335 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
11336 mkexpr(t9),
11337 mkU32(0x0)),
11338 binop(Iop_Or32,
11339 getDSPControl(),
11340 binop(Iop_Shl32,
11341 mkU32(0x00010000),
11342 mkU8(ac))),
11343 getDSPControl()));
11344 /* tempA_31..0 */
11345 assign(t5,
11346 IRExpr_ITE(binop(Iop_CmpNE32,
11347 mkexpr(t9),
11348 mkU32(0x0)),
11349 mkU32(0x7FFFFFFF),
11350 binop(Iop_Shl32,
11351 binop(Iop_Mul32,
11352 mkexpr(t3),
11353 mkexpr(t4)),
11354 mkU8(1))));
11355 /* dotp_63..0 */
11356 assign(t6,
11357 binop(Iop_Sub64,
11358 unop(Iop_32Sto64, mkexpr(t2)),
11359 unop(Iop_32Sto64, mkexpr(t5))));
11360 /* tempC_63..0 */
11361 assign(t7, binop(Iop_Add64, getAcc(ac), mkexpr(t6)));
11363 putAcc(ac, mkexpr(t7));
11364 break;
11366 case 0x7: { /* DPAU.H.QBR */
11367 DIP("dpau.h.qbr ac%u, r%u, r%u", ac, rs, rt);
11368 vassert(!mode64);
11369 t0 = newTemp(Ity_I32);
11370 t1 = newTemp(Ity_I32);
11371 t2 = newTemp(Ity_I64);
11372 t3 = newTemp(Ity_I64);
11374 assign(t0,
11375 binop(Iop_Mul32,
11376 unop(Iop_8Uto32,
11377 unop(Iop_16HIto8,
11378 unop(Iop_32to16, getIReg(rs)))),
11379 unop(Iop_8Uto32,
11380 unop(Iop_16HIto8,
11381 unop(Iop_32to16, getIReg(rt))))));
11382 assign(t1,
11383 binop(Iop_Mul32,
11384 unop(Iop_8Uto32,
11385 unop(Iop_16to8,
11386 unop(Iop_32to16, getIReg(rs)))),
11387 unop(Iop_8Uto32,
11388 unop(Iop_16to8,
11389 unop(Iop_32to16, getIReg(rt))))));
11390 assign(t2, unop(Iop_32Uto64,
11391 binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
11392 assign(t3, binop(Iop_Add64, getAcc(ac), mkexpr(t2)));
11393 putAcc(ac, mkexpr(t3));
11394 break;
11396 case 0x8: { /* DPAX.W.PH */
11397 DIP("dpax.w.ph ac%u, r%u, r%u", ac, rs, rt);
11398 vassert(!mode64);
11399 t0 = newTemp(Ity_I64);
11400 t1 = newTemp(Ity_I64);
11401 t2 = newTemp(Ity_I64);
11403 assign(t0,
11404 unop(Iop_32Sto64,
11405 binop(Iop_Mul32,
11406 unop(Iop_16Sto32,
11407 unop(Iop_32HIto16, getIReg(rs))),
11408 unop(Iop_16Sto32,
11409 unop(Iop_32to16, getIReg(rt))))));
11410 assign(t1,
11411 unop(Iop_32Sto64,
11412 binop(Iop_Mul32,
11413 unop(Iop_16Sto32,
11414 unop(Iop_32to16, getIReg(rs))),
11415 unop(Iop_16Sto32,
11416 unop(Iop_32HIto16, getIReg(rt))))));
11417 assign(t2,
11418 binop(Iop_Add64,
11419 getAcc(ac),
11420 binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
11421 putAcc(ac, mkexpr(t2));
11422 break;
11424 case 0x9: { /* DPSX.W.PH */
11425 DIP("dpsx.w.ph ac%u r%u, r%u", ac, rs, rt);
11426 vassert(!mode64);
11428 t0 = newTemp(Ity_I64);
11429 t1 = newTemp(Ity_I64);
11430 t2 = newTemp(Ity_I64);
11432 assign(t0,
11433 unop(Iop_32Sto64,
11434 binop(Iop_Mul32,
11435 unop(Iop_16Sto32,
11436 unop(Iop_32HIto16, getIReg(rs))),
11437 unop(Iop_16Sto32,
11438 unop(Iop_32to16, getIReg(rt))))));
11439 assign(t1,
11440 unop(Iop_32Sto64,
11441 binop(Iop_Mul32,
11442 unop(Iop_16Sto32,
11443 unop(Iop_32to16, getIReg(rs))),
11444 unop(Iop_16Sto32,
11445 unop(Iop_32HIto16, getIReg(rt))))));
11446 assign(t2,
11447 binop(Iop_Sub64,
11448 getAcc(ac),
11449 binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
11450 putAcc(ac, mkexpr(t2));
11451 break;
11453 case 0xB: { /* DPSU.H.QBL */
11454 DIP("dpsu.h.qbl ac%u, r%u, r%u", ac, rs, rt);
11455 vassert(!mode64);
11457 t0 = newTemp(Ity_I32);
11458 t1 = newTemp(Ity_I32);
11459 t2 = newTemp(Ity_I64);
11460 t3 = newTemp(Ity_I64);
11462 assign(t0,
11463 binop(Iop_Mul32,
11464 unop(Iop_8Uto32,
11465 unop(Iop_16HIto8,
11466 unop(Iop_32HIto16, getIReg(rs)))),
11467 unop(Iop_8Uto32,
11468 unop(Iop_16HIto8,
11469 unop(Iop_32HIto16, getIReg(rt))))));
11470 assign(t1,
11471 binop(Iop_Mul32,
11472 unop(Iop_8Uto32,
11473 unop(Iop_16to8,
11474 unop(Iop_32HIto16, getIReg(rs)))),
11475 unop(Iop_8Uto32,
11476 unop(Iop_16to8,
11477 unop(Iop_32HIto16, getIReg(rt))))));
11478 assign(t2,
11479 unop(Iop_32Uto64,
11480 binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
11481 assign(t3,
11482 binop(Iop_Sub64, getAcc(ac), mkexpr(t2)));
11483 putAcc(ac, mkexpr(t3));
11484 break;
11486 case 0xC: { /* DPAQ_SA.L.W */
11487 DIP("dpaq_sa.l.w ac%u, r%u, r%u", ac, rs, rt);
11488 vassert(!mode64);
11489 t0 = newTemp(Ity_I64);
11490 t1 = newTemp(Ity_I64);
11491 t2 = newTemp(Ity_I1);
11492 t3 = newTemp(Ity_I1);
11493 t4 = newTemp(Ity_I64);
11494 t5 = newTemp(Ity_I64);
11495 t6 = newTemp(Ity_I64);
11496 t7 = newTemp(Ity_I64);
11497 t8 = newTemp(Ity_I1);
11498 t9 = newTemp(Ity_I1);
11500 assign(t0, getAcc(ac));
11502 assign(t1, binop(Iop_Shl64,
11503 binop(Iop_MullS32,
11504 getIReg(rs), getIReg(rt)),
11505 mkU8(0x1)));
11507 assign(t2, binop(Iop_CmpEQ32,
11508 getIReg(rs),
11509 mkU32(0x80000000)));
11510 assign(t3, binop(Iop_CmpEQ32,
11511 getIReg(rt),
11512 mkU32(0x80000000)));
11514 assign(t4,
11515 IRExpr_ITE(mkexpr(t2),
11516 IRExpr_ITE(mkexpr(t3),
11517 mkU64(0x7fffffffffffffffULL),
11518 mkexpr(t1)),
11519 mkexpr(t1)));
11521 putDSPControl(IRExpr_ITE(mkexpr(t2),
11522 IRExpr_ITE(mkexpr(t3),
11523 binop(Iop_Or32,
11524 getDSPControl(),
11525 binop(Iop_Shl32,
11526 mkU32(0x1),
11527 mkU8(ac+16)
11530 getDSPControl()),
11531 getDSPControl()));
11533 assign(t5, binop(Iop_Add64,
11534 unop(Iop_32Uto64,
11535 unop(Iop_64to32, mkexpr(t0))),
11536 unop(Iop_32Uto64,
11537 unop(Iop_64to32, mkexpr(t4)))));
11538 assign(t6,
11539 binop(Iop_Add64,
11540 binop(Iop_Add64,
11541 unop(Iop_32Sto64,
11542 unop(Iop_64HIto32, mkexpr(t0))),
11543 unop(Iop_32Sto64,
11544 unop(Iop_64HIto32, mkexpr(t4)))),
11545 unop(Iop_32Uto64,
11546 binop(Iop_And32,
11547 unop(Iop_64HIto32, mkexpr(t5)),
11548 mkU32(0x1)))));
11549 assign(t7, binop(Iop_32HLto64,
11550 unop(Iop_64to32, mkexpr(t6)),
11551 unop(Iop_64to32, mkexpr(t5))));
11552 assign(t8, binop(Iop_CmpEQ32,
11553 binop(Iop_Shr32,
11554 binop(Iop_And32,
11555 unop(Iop_64to32, mkexpr(t6)),
11556 mkU32(0x80000000)),
11557 mkU8(31)),
11558 binop(Iop_And32,
11559 unop(Iop_64HIto32, mkexpr(t6)),
11560 mkU32(0x00000001))));
11561 assign(t9, binop(Iop_CmpEQ32,
11562 binop(Iop_And32,
11563 unop(Iop_64HIto32,
11564 mkexpr(t6)),
11565 mkU32(0x00000001)),
11566 mkU32(0x1)));
11567 putDSPControl(IRExpr_ITE(mkexpr(t8),
11568 getDSPControl(),
11569 binop(Iop_Or32,
11570 getDSPControl(),
11571 binop(Iop_Shl32,
11572 mkU32(0x1),
11573 mkU8(ac+16)))));
11574 putAcc(ac,
11575 IRExpr_ITE(mkexpr(t8),
11576 mkexpr(t7),
11577 IRExpr_ITE(mkexpr(t9),
11578 mkU64(0x8000000000000000ULL),
11579 mkU64(0x7fffffffffffffffULL)))
11581 break;
11583 case 0xD: { /* DPSQ_SA.L.W */
11584 DIP("dpsq_sa.l.w ac%u, r%u, r%u", ac, rs, rt);
11585 vassert(!mode64);
11586 t0 = newTemp(Ity_I64);
11587 t1 = newTemp(Ity_I64);
11588 t2 = newTemp(Ity_I1);
11589 t3 = newTemp(Ity_I1);
11590 t4 = newTemp(Ity_I64);
11591 t5 = newTemp(Ity_I64);
11592 t6 = newTemp(Ity_I64);
11593 t7 = newTemp(Ity_I64);
11594 t8 = newTemp(Ity_I1);
11595 t9 = newTemp(Ity_I1);
11597 assign(t0, getAcc(ac));
11599 assign(t1, binop(Iop_Shl64,
11600 binop(Iop_MullS32,
11601 getIReg(rs), getIReg(rt)),
11602 mkU8(0x1)));
11604 assign(t2, binop(Iop_CmpEQ32,
11605 getIReg(rs),
11606 mkU32(0x80000000)));
11607 assign(t3, binop(Iop_CmpEQ32,
11608 getIReg(rt),
11609 mkU32(0x80000000)));
11611 assign(t4,
11612 IRExpr_ITE(mkexpr(t2),
11613 IRExpr_ITE(mkexpr(t3),
11614 mkU64(0x7fffffffffffffffULL),
11615 mkexpr(t1)),
11616 mkexpr(t1)));
11618 putDSPControl(IRExpr_ITE(mkexpr(t2),
11619 IRExpr_ITE(mkexpr(t3),
11620 binop(Iop_Or32,
11621 getDSPControl(),
11622 binop(Iop_Shl32,
11623 mkU32(0x1),
11624 mkU8(ac+16)
11627 getDSPControl()),
11628 getDSPControl()));
11630 assign(t5, binop(Iop_Sub64,
11631 unop(Iop_32Uto64,
11632 unop(Iop_64to32, mkexpr(t0))),
11633 unop(Iop_32Uto64,
11634 unop(Iop_64to32, mkexpr(t4)))));
11635 assign(t6, binop(Iop_Sub64,
11636 binop(Iop_Add64,
11637 unop(Iop_32Sto64,
11638 unop(Iop_64HIto32, mkexpr(t0))
11640 unop(Iop_32Sto64,
11641 unop(Iop_1Sto32,
11642 binop(Iop_CmpLT32U,
11643 unop(Iop_64to32,
11644 mkexpr(t0)),
11645 unop(Iop_64to32,
11646 mkexpr(t4)))))),
11647 unop(Iop_32Sto64,
11648 unop(Iop_64HIto32, mkexpr(t4)))));
11649 assign(t7, binop(Iop_32HLto64,
11650 unop(Iop_64to32, mkexpr(t6)),
11651 unop(Iop_64to32, mkexpr(t5))));
11652 assign(t8, binop(Iop_CmpEQ32,
11653 binop(Iop_Shr32,
11654 binop(Iop_And32,
11655 unop(Iop_64to32, mkexpr(t6)),
11656 mkU32(0x80000000)),
11657 mkU8(31)),
11658 binop(Iop_And32,
11659 unop(Iop_64HIto32, mkexpr(t6)),
11660 mkU32(0x00000001))));
11661 assign(t9, binop(Iop_CmpEQ32,
11662 binop(Iop_And32,
11663 unop(Iop_64HIto32, mkexpr(t6)),
11664 mkU32(0x00000001)),
11665 mkU32(0x1)));
11666 putDSPControl(IRExpr_ITE(mkexpr(t8),
11667 getDSPControl(),
11668 binop(Iop_Or32,
11669 getDSPControl(),
11670 binop(Iop_Shl32,
11671 mkU32(0x1),
11672 mkU8(ac+16)))));
11673 putAcc(ac,
11674 IRExpr_ITE(mkexpr(t8),
11675 mkexpr(t7),
11676 IRExpr_ITE(mkexpr(t9),
11677 mkU64(0x8000000000000000ULL),
11678 mkU64(0x7fffffffffffffffULL)))
11680 break;
11682 case 0xF: { /* DPSU.H.QBR */
11683 DIP("dpsu.h.qbr ac%u r%u, r%u", ac, rs, rt);
11684 vassert(!mode64);
11686 t0 = newTemp(Ity_I32);
11687 t1 = newTemp(Ity_I32);
11688 t2 = newTemp(Ity_I64);
11689 t3 = newTemp(Ity_I64);
11691 assign(t0,
11692 binop(Iop_Mul32,
11693 unop(Iop_8Uto32,
11694 unop(Iop_16HIto8,
11695 unop(Iop_32to16, getIReg(rs)))),
11696 unop(Iop_8Uto32,
11697 unop(Iop_16HIto8,
11698 unop(Iop_32to16, getIReg(rt))))));
11699 assign(t1,
11700 binop(Iop_Mul32,
11701 unop(Iop_8Uto32,
11702 unop(Iop_16to8,
11703 unop(Iop_32to16, getIReg(rs)))),
11704 unop(Iop_8Uto32,
11705 unop(Iop_16to8,
11706 unop(Iop_32to16, getIReg(rt))))));
11707 assign(t2, unop(Iop_32Uto64,
11708 binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
11709 assign(t3, binop(Iop_Sub64, getAcc(ac), mkexpr(t2)));
11710 putAcc(ac, mkexpr(t3));
11712 break;
11714 case 0x10: { /* MAQ_SA.W.PHL */
11715 DIP("maq_sa.w.phl ac%u, r%u, r%u", ac, rs, rt);
11716 vassert(!mode64);
11717 t0 = newTemp(Ity_I64);
11718 t1 = newTemp(Ity_I64);
11719 t2 = newTemp(Ity_I1);
11720 t3 = newTemp(Ity_I1);
11721 t4 = newTemp(Ity_I64);
11722 t5 = newTemp(Ity_I64);
11723 t6 = newTemp(Ity_I1);
11724 t7 = newTemp(Ity_I64);
11726 assign(t0, getAcc(ac));
11727 assign(t1, unop(Iop_32Sto64,
11728 binop(Iop_Shl32,
11729 binop(Iop_Mul32,
11730 unop(Iop_16Sto32,
11731 unop(Iop_32HIto16,
11732 getIReg(rs))),
11733 unop(Iop_16Sto32,
11734 unop(Iop_32HIto16,
11735 getIReg(rt)))),
11736 mkU8(0x1))));
11738 /* If both input arguments are equal 0x8000, saturate
11739 intermediate product and write to DSPControl register.
11741 assign(t2, binop(Iop_CmpEQ32,
11742 unop(Iop_16Uto32,
11743 unop(Iop_32HIto16, getIReg(rs))),
11744 mkU32(0x00008000)));
11745 assign(t3, binop(Iop_CmpEQ32,
11746 unop(Iop_16Uto32,
11747 unop(Iop_32HIto16, getIReg(rt))),
11748 mkU32(0x00008000)));
11750 assign(t4,
11751 IRExpr_ITE(mkexpr(t2),
11752 IRExpr_ITE(mkexpr(t3),
11753 mkU64(0x000000007fffffffULL),
11754 mkexpr(t1)),
11755 mkexpr(t1)));
11757 putDSPControl(IRExpr_ITE(mkexpr(t2),
11758 IRExpr_ITE(mkexpr(t3),
11759 binop(Iop_Or32,
11760 getDSPControl(),
11761 binop(Iop_Shl32,
11762 mkU32(0x1),
11763 mkU8(ac+16)
11766 getDSPControl()),
11767 getDSPControl()));
11768 /* Add intermediate product and value in the
11769 accumulator. */
11770 assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4)));
11772 /* Compare bits 31 and 32 of the value in t5. */
11773 assign(t6, binop(Iop_CmpEQ32,
11774 binop(Iop_Shr32,
11775 binop(Iop_And32,
11776 unop(Iop_64to32, mkexpr(t5)),
11777 mkU32(0x80000000)),
11778 mkU8(31)),
11779 binop(Iop_And32,
11780 unop(Iop_64HIto32, mkexpr(t5)),
11781 mkU32(1))));
11782 putDSPControl(IRExpr_ITE(mkexpr(t6),
11783 getDSPControl(),
11784 binop(Iop_Or32,
11785 getDSPControl(),
11786 binop(Iop_Shl32,
11787 mkU32(0x1),
11788 mkU8(ac+16)))));
11789 assign(t7,
11790 IRExpr_ITE(mkexpr(t6),
11791 mkexpr(t5),
11792 IRExpr_ITE(binop(Iop_CmpEQ32,
11793 binop(Iop_And32,
11794 unop(Iop_64HIto32,
11795 mkexpr(t5)),
11796 mkU32(1)),
11797 mkU32(0x0)),
11798 mkU64(0x000000007fffffffULL),
11799 mkU64(0xffffffff80000000ULL)))
11801 putAcc(ac, mkexpr(t7));
11802 break;
11804 case 0x12: { /* MAQ_SA.W.PHR */
11805 DIP("maq_sa.w.phr ac%u, r%u, r%u", ac, rs, rt);
11806 vassert(!mode64);
11807 t0 = newTemp(Ity_I64);
11808 t1 = newTemp(Ity_I64);
11809 t2 = newTemp(Ity_I1);
11810 t3 = newTemp(Ity_I1);
11811 t4 = newTemp(Ity_I64);
11812 t5 = newTemp(Ity_I64);
11813 t6 = newTemp(Ity_I1);
11814 t7 = newTemp(Ity_I64);
11816 assign(t0, getAcc(ac));
11817 assign(t1, unop(Iop_32Sto64,
11818 binop(Iop_Shl32,
11819 binop(Iop_Mul32,
11820 unop(Iop_16Sto32,
11821 unop(Iop_32to16,
11822 getIReg(rs))),
11823 unop(Iop_16Sto32,
11824 unop(Iop_32to16,
11825 getIReg(rt)))),
11826 mkU8(0x1))));
11828 /* If both input arguments are equal 0x8000, saturate
11829 intermediate product and write to DSPControl
11830 register. */
11831 assign(t2, binop(Iop_CmpEQ32,
11832 unop(Iop_16Uto32,
11833 unop(Iop_32to16, getIReg(rs))),
11834 mkU32(0x00008000)));
11835 assign(t3, binop(Iop_CmpEQ32,
11836 unop(Iop_16Uto32,
11837 unop(Iop_32to16, getIReg(rt))),
11838 mkU32(0x00008000)));
11840 assign(t4,
11841 IRExpr_ITE(mkexpr(t2),
11842 IRExpr_ITE(mkexpr(t3),
11843 mkU64(0x000000007fffffffULL),
11844 mkexpr(t1)),
11845 mkexpr(t1)));
11847 putDSPControl(IRExpr_ITE(mkexpr(t2),
11848 IRExpr_ITE(mkexpr(t3),
11849 binop(Iop_Or32,
11850 getDSPControl(),
11851 binop(Iop_Shl32,
11852 mkU32(0x1),
11853 mkU8(ac+16)
11856 getDSPControl()),
11857 getDSPControl()));
11858 /* Add intermediate product and value in the
11859 accumulator. */
11860 assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4)));
11862 /* Compare bits 31 and 32 of the value in t5. */
11863 assign(t6, binop(Iop_CmpEQ32,
11864 binop(Iop_Shr32,
11865 binop(Iop_And32,
11866 unop(Iop_64to32, mkexpr(t5)),
11867 mkU32(0x80000000)),
11868 mkU8(31)),
11869 binop(Iop_And32,
11870 unop(Iop_64HIto32, mkexpr(t5)),
11871 mkU32(1))));
11872 putDSPControl(IRExpr_ITE(mkexpr(t6),
11873 getDSPControl(),
11874 binop(Iop_Or32,
11875 getDSPControl(),
11876 binop(Iop_Shl32,
11877 mkU32(0x1),
11878 mkU8(ac+16)))));
11879 assign(t7,
11880 IRExpr_ITE(mkexpr(t6),
11881 mkexpr(t5),
11882 IRExpr_ITE(binop(Iop_CmpEQ32,
11883 binop(Iop_And32,
11884 unop(Iop_64HIto32,
11885 mkexpr(t5)),
11886 mkU32(1)),
11887 mkU32(0x0)),
11888 mkU64(0x000000007fffffffULL),
11889 mkU64(0xffffffff80000000ULL)))
11891 putAcc(ac, mkexpr(t7));
11892 break;
11894 case 0x14: { /* MAQ_S.W.PHL */
11895 DIP("maq_s.w.phl ac%u, r%u, r%u", ac, rs, rt);
11896 vassert(!mode64);
11897 t0 = newTemp(Ity_I32);
11898 t1 = newTemp(Ity_I32);
11899 t2 = newTemp(Ity_I32);
11900 t3 = newTemp(Ity_I1);
11901 t4 = newTemp(Ity_I32);
11902 t5 = newTemp(Ity_I64);
11904 assign(t5, getAcc(ac));
11906 assign(t0, unop(Iop_16Sto32,
11907 unop(Iop_32HIto16, getIReg(rs))));
11908 assign(t1, unop(Iop_16Sto32,
11909 unop(Iop_32HIto16, getIReg(rt))));
11911 assign(t2, binop(Iop_And32,
11912 unop(Iop_1Sto32,
11913 binop(Iop_CmpEQ32,
11914 binop(Iop_And32,
11915 mkexpr(t0),
11916 mkU32(0xffff)),
11917 mkU32(0x8000))),
11918 unop(Iop_1Sto32,
11919 binop(Iop_CmpEQ32,
11920 binop(Iop_And32,
11921 mkexpr(t1),
11922 mkU32(0xffff)),
11923 mkU32(0x8000)))));
11925 assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0)));
11927 putDSPControl(IRExpr_ITE(mkexpr(t3),
11928 getDSPControl(),
11929 binop(Iop_Or32,
11930 getDSPControl(),
11931 binop(Iop_Shl32,
11932 mkU32(0x1),
11933 mkU8(ac+16)))));
11935 assign(t4, unop(Iop_64to32,
11936 binop(Iop_MullS32,
11937 mkexpr(t0), mkexpr(t1))));
11938 putAcc(ac, IRExpr_ITE(mkexpr(t3),
11939 binop(Iop_Add64,
11940 unop(Iop_32Sto64,
11941 binop(Iop_Shl32,
11942 mkexpr(t4),
11943 mkU8(0x1))),
11944 mkexpr(t5)),
11945 binop(Iop_Add64,
11946 mkexpr(t5),
11947 unop(Iop_32Sto64,
11948 mkU32(0x7fffffff)))));
11949 break;
11951 case 0x16: { /* MAQ_S.W.PHR */
11952 DIP("maq_s.w.phr ac%u, r%u, r%u", ac, rs, rt);
11953 vassert(!mode64);
11954 t0 = newTemp(Ity_I32);
11955 t1 = newTemp(Ity_I32);
11956 t2 = newTemp(Ity_I32);
11957 t3 = newTemp(Ity_I1);
11958 t4 = newTemp(Ity_I32);
11959 t5 = newTemp(Ity_I64);
11961 assign(t5, getAcc(ac));
11963 assign(t0, unop(Iop_16Sto32,
11964 unop(Iop_32to16, getIReg(rs))));
11965 assign(t1, unop(Iop_16Sto32,
11966 unop(Iop_32to16, getIReg(rt))));
11968 assign(t2, binop(Iop_And32,
11969 unop(Iop_1Sto32,
11970 binop(Iop_CmpEQ32,
11971 binop(Iop_And32,
11972 mkexpr(t0),
11973 mkU32(0xffff)),
11974 mkU32(0x8000))),
11975 unop(Iop_1Sto32,
11976 binop(Iop_CmpEQ32,
11977 binop(Iop_And32,
11978 mkexpr(t1),
11979 mkU32(0xffff)),
11980 mkU32(0x8000)))));
11982 assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0)));
11984 putDSPControl(IRExpr_ITE(mkexpr(t3),
11985 getDSPControl(),
11986 binop(Iop_Or32,
11987 getDSPControl(),
11988 binop(Iop_Shl32,
11989 mkU32(0x1),
11990 mkU8(ac+16)))));
11992 assign(t4, unop(Iop_64to32,
11993 binop(Iop_MullS32,
11994 mkexpr(t0), mkexpr(t1))));
11995 putAcc(ac, IRExpr_ITE(mkexpr(t3),
11996 binop(Iop_Add64,
11997 unop(Iop_32Sto64,
11998 binop(Iop_Shl32,
11999 mkexpr(t4),
12000 mkU8(0x1))),
12001 mkexpr(t5)),
12002 binop(Iop_Add64,
12003 mkexpr(t5),
12004 unop(Iop_32Sto64,
12005 mkU32(0x7fffffff)))));
12006 break;
12008 case 0x18: { /* DPAQX_S.W.PH */
12009 DIP("dpaqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
12010 vassert(!mode64);
12011 t0 = newTemp(Ity_I64);
12012 t1 = newTemp(Ity_I64);
12013 t2 = newTemp(Ity_I1);
12014 t3 = newTemp(Ity_I1);
12015 t4 = newTemp(Ity_I64);
12016 t5 = newTemp(Ity_I64);
12017 t6 = newTemp(Ity_I1);
12018 t7 = newTemp(Ity_I1);
12019 t8 = newTemp(Ity_I64);
12020 t9 = newTemp(Ity_I64);
12022 assign(t0, getAcc(ac));
12024 assign(t1, binop(Iop_Shl64,
12025 binop(Iop_MullS32,
12026 unop(Iop_16Sto32,
12027 unop(Iop_32HIto16,
12028 getIReg(rs))),
12029 unop(Iop_16Sto32,
12030 unop(Iop_32to16,
12031 getIReg(rt)))),
12032 mkU8(0x1)));
12033 assign(t2, binop(Iop_CmpEQ32,
12034 unop(Iop_16Uto32,
12035 unop(Iop_32HIto16, getIReg(rs))),
12036 mkU32(0x00008000)));
12037 assign(t3, binop(Iop_CmpEQ32,
12038 unop(Iop_16Uto32,
12039 unop(Iop_32to16, getIReg(rt))),
12040 mkU32(0x00008000)));
12041 assign(t4,
12042 IRExpr_ITE(mkexpr(t2),
12043 IRExpr_ITE(mkexpr(t3),
12044 mkU64(0x000000007fffffffULL),
12045 mkexpr(t1)),
12046 mkexpr(t1)));
12048 putDSPControl(IRExpr_ITE(mkexpr(t2),
12049 IRExpr_ITE(mkexpr(t3),
12050 binop(Iop_Or32,
12051 getDSPControl(),
12052 binop(Iop_Shl32,
12053 mkU32(0x1),
12054 mkU8(ac+16))),
12055 getDSPControl()),
12056 getDSPControl()));
12058 assign(t5, binop(Iop_Shl64,
12059 binop(Iop_MullS32,
12060 unop(Iop_16Sto32,
12061 unop(Iop_32to16,
12062 getIReg(rs))),
12063 unop(Iop_16Sto32,
12064 unop(Iop_32HIto16,
12065 getIReg(rt)))),
12066 mkU8(0x1)));
12067 assign(t6, binop(Iop_CmpEQ32,
12068 unop(Iop_16Uto32,
12069 unop(Iop_32to16, getIReg(rs))),
12070 mkU32(0x00008000)));
12071 assign(t7, binop(Iop_CmpEQ32,
12072 unop(Iop_16Uto32,
12073 unop(Iop_32HIto16, getIReg(rt))),
12074 mkU32(0x00008000)));
12075 assign(t8,
12076 IRExpr_ITE(mkexpr(t6),
12077 IRExpr_ITE(mkexpr(t7),
12078 mkU64(0x000000007fffffffULL),
12079 mkexpr(t5)),
12080 mkexpr(t5)));
12082 putDSPControl(IRExpr_ITE(mkexpr(t6),
12083 IRExpr_ITE(mkexpr(t7),
12084 binop(Iop_Or32,
12085 getDSPControl(),
12086 binop(Iop_Shl32,
12087 mkU32(0x1),
12088 mkU8(ac+16)
12091 getDSPControl()),
12092 getDSPControl()));
12094 assign(t9, binop(Iop_Add64,
12095 binop(Iop_Add64, mkexpr(t4), mkexpr(t8)),
12096 mkexpr(t0)));
12097 putAcc(ac, mkexpr(t9));
12098 break;
12100 case 0x19: { /* DPSQX_S.W.PH */
12101 DIP("dpsqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
12102 vassert(!mode64);
12103 t0 = newTemp(Ity_I64);
12104 t1 = newTemp(Ity_I64);
12105 t2 = newTemp(Ity_I1);
12106 t3 = newTemp(Ity_I1);
12107 t4 = newTemp(Ity_I64);
12108 t5 = newTemp(Ity_I64);
12109 t6 = newTemp(Ity_I1);
12110 t7 = newTemp(Ity_I1);
12111 t8 = newTemp(Ity_I64);
12112 t9 = newTemp(Ity_I64);
12114 assign(t0, getAcc(ac));
12116 assign(t1, binop(Iop_Shl64,
12117 binop(Iop_MullS32,
12118 unop(Iop_16Sto32,
12119 unop(Iop_32HIto16,
12120 getIReg(rs))),
12121 unop(Iop_16Sto32,
12122 unop(Iop_32to16,
12123 getIReg(rt)))),
12124 mkU8(0x1)));
12125 assign(t2, binop(Iop_CmpEQ32,
12126 unop(Iop_16Uto32,
12127 unop(Iop_32HIto16, getIReg(rs))),
12128 mkU32(0x00008000)));
12129 assign(t3, binop(Iop_CmpEQ32,
12130 unop(Iop_16Uto32,
12131 unop(Iop_32to16, getIReg(rt))),
12132 mkU32(0x00008000)));
12133 assign(t4,
12134 IRExpr_ITE(mkexpr(t2),
12135 IRExpr_ITE(mkexpr(t3),
12136 mkU64(0x000000007fffffffULL),
12137 mkexpr(t1)),
12138 mkexpr(t1)));
12140 putDSPControl(IRExpr_ITE(mkexpr(t2),
12141 IRExpr_ITE(mkexpr(t3),
12142 binop(Iop_Or32,
12143 getDSPControl(),
12144 binop(Iop_Shl32,
12145 mkU32(0x1),
12146 mkU8(ac+16)
12149 getDSPControl()),
12150 getDSPControl()));
12152 assign(t5, binop(Iop_Shl64,
12153 binop(Iop_MullS32,
12154 unop(Iop_16Sto32,
12155 unop(Iop_32to16,
12156 getIReg(rs))),
12157 unop(Iop_16Sto32,
12158 unop(Iop_32HIto16,
12159 getIReg(rt)))),
12160 mkU8(0x1)));
12161 assign(t6, binop(Iop_CmpEQ32,
12162 unop(Iop_16Uto32,
12163 unop(Iop_32to16, getIReg(rs))),
12164 mkU32(0x00008000)));
12165 assign(t7, binop(Iop_CmpEQ32,
12166 unop(Iop_16Uto32,
12167 unop(Iop_32HIto16, getIReg(rt))),
12168 mkU32(0x00008000)));
12169 assign(t8,
12170 IRExpr_ITE(mkexpr(t6),
12171 IRExpr_ITE(mkexpr(t7),
12172 mkU64(0x000000007fffffffULL),
12173 mkexpr(t5)),
12174 mkexpr(t5)));
12176 putDSPControl(IRExpr_ITE(mkexpr(t6),
12177 IRExpr_ITE(mkexpr(t7),
12178 binop(Iop_Or32,
12179 getDSPControl(),
12180 binop(Iop_Shl32,
12181 mkU32(0x1),
12182 mkU8(ac+16)
12185 getDSPControl()),
12186 getDSPControl()));
12188 assign(t9, binop(Iop_Sub64,
12189 mkexpr(t0),
12190 binop(Iop_Add64, mkexpr(t4), mkexpr(t8))));
12191 putAcc(ac, mkexpr(t9));
12192 break;
12194 case 0x1A: { /* DPAQX_SA.W.PH */
12195 DIP("dpaqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt);
12196 vassert(!mode64);
12197 t0 = newTemp(Ity_I64);
12198 t1 = newTemp(Ity_I64);
12199 t2 = newTemp(Ity_I1);
12200 t3 = newTemp(Ity_I1);
12201 t4 = newTemp(Ity_I64);
12202 t5 = newTemp(Ity_I64);
12203 t6 = newTemp(Ity_I1);
12204 t7 = newTemp(Ity_I1);
12205 t8 = newTemp(Ity_I64);
12206 t9 = newTemp(Ity_I64);
12207 t10 = newTemp(Ity_I32);
12209 assign(t0, getAcc(ac));
12210 /* Calculate the first cross dot product and saturate if
12211 needed. */
12212 assign(t1, unop(Iop_32Sto64,
12213 binop(Iop_Shl32,
12214 binop(Iop_Mul32,
12215 unop(Iop_16Sto32,
12216 unop(Iop_32HIto16,
12217 getIReg(rs))),
12218 unop(Iop_16Sto32,
12219 unop(Iop_32to16,
12220 getIReg(rt)))),
12221 mkU8(0x1))));
12223 /* If both input arguments are equal 0x8000, saturate
12224 intermediate product and write to DSPControl
12225 register. */
12226 assign(t2, binop(Iop_CmpEQ32,
12227 unop(Iop_16Uto32,
12228 unop(Iop_32HIto16, getIReg(rs))),
12229 mkU32(0x00008000)));
12230 assign(t3, binop(Iop_CmpEQ32,
12231 unop(Iop_16Uto32,
12232 unop(Iop_32to16, getIReg(rt))),
12233 mkU32(0x00008000)));
12235 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
12236 binop(Iop_And32,
12237 unop(Iop_1Sto32,
12238 mkexpr(t2)),
12239 unop(Iop_1Sto32,
12240 mkexpr(t3))),
12241 mkU32(0)),
12242 mkU64(0x000000007fffffffULL),
12243 mkexpr(t1)));
12245 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
12246 binop(Iop_And32,
12247 unop(Iop_1Sto32,
12248 mkexpr(t2)),
12249 unop(Iop_1Sto32,
12250 mkexpr(t3))),
12251 mkU32(0)),
12252 binop(Iop_Or32,
12253 getDSPControl(),
12254 binop(Iop_Shl32,
12255 mkU32(0x1),
12256 mkU8(ac+16))),
12257 getDSPControl()));
12258 /* Calculate second cross dot product and saturate if
12259 needed. */
12260 assign(t5, unop(Iop_32Sto64,
12261 binop(Iop_Shl32,
12262 binop(Iop_Mul32,
12263 unop(Iop_16Sto32,
12264 unop(Iop_32to16,
12265 getIReg(rs))),
12266 unop(Iop_16Sto32,
12267 unop(Iop_32HIto16,
12268 getIReg(rt)))),
12269 mkU8(0x1))));
12271 /* If both input arguments are equal 0x8000, saturate
12272 intermediate product and write to DSPControl
12273 register. */
12274 assign(t6, binop(Iop_CmpEQ32,
12275 unop(Iop_16Uto32,
12276 unop(Iop_32to16, getIReg(rs))),
12277 mkU32(0x00008000)));
12278 assign(t7, binop(Iop_CmpEQ32,
12279 unop(Iop_16Uto32,
12280 unop(Iop_32HIto16, getIReg(rt))),
12281 mkU32(0x00008000)));
12283 assign(t8, IRExpr_ITE(binop(Iop_CmpNE32,
12284 binop(Iop_And32,
12285 unop(Iop_1Sto32,
12286 mkexpr(t6)),
12287 unop(Iop_1Sto32,
12288 mkexpr(t7))),
12289 mkU32(0)),
12290 mkU64(0x000000007fffffffULL),
12291 mkexpr(t5)));
12293 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
12294 binop(Iop_And32,
12295 unop(Iop_1Sto32,
12296 mkexpr(t6)),
12297 unop(Iop_1Sto32,
12298 mkexpr(t7))),
12299 mkU32(0)),
12300 binop(Iop_Or32,
12301 getDSPControl(),
12302 binop(Iop_Shl32,
12303 mkU32(0x1),
12304 mkU8(ac+16))),
12305 getDSPControl()));
12306 /* Subtract intermediate products from value in the
12307 accumulator. */
12308 assign(t9,
12309 binop(Iop_Add64,
12310 mkexpr(t0),
12311 binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));
12313 putAcc(ac,
12314 IRExpr_ITE(binop(Iop_CmpEQ32,
12315 binop(Iop_And32,
12316 unop(Iop_64HIto32,
12317 mkexpr(t9)),
12318 mkU32(0x80000000)),
12319 mkU32(0x0)),
12320 IRExpr_ITE(binop(Iop_CmpNE32,
12321 unop(Iop_64HIto32,
12322 binop(Iop_Shl64,
12323 mkexpr(t9),
12324 mkU8(1))),
12325 mkU32(0x0)),
12326 mkU64(0x000000007fffffffULL),
12327 mkexpr(t9)),
12328 IRExpr_ITE(binop(Iop_CmpNE32,
12329 unop(Iop_64HIto32,
12330 binop(Iop_Shl64,
12331 mkexpr(t9),
12332 mkU8(1))),
12333 mkU32(0xffffffff)),
12334 mkU64(0xffffffff80000000ULL),
12335 mkexpr(t9))));
12336 assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32,
12337 unop(Iop_64to32,
12338 mkexpr(t9)),
12339 unop(Iop_64to32,
12340 getAcc(ac))),
12341 getDSPControl(),
12342 binop(Iop_Or32,
12343 getDSPControl(),
12344 binop(Iop_Shl32,
12345 mkU32(0x1),
12346 mkU8(ac+16)))));
12347 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
12348 unop(Iop_64HIto32,
12349 mkexpr(t9)),
12350 unop(Iop_64HIto32,
12351 getAcc(ac))),
12352 mkexpr(t10),
12353 binop(Iop_Or32,
12354 getDSPControl(),
12355 binop(Iop_Shl32,
12356 mkU32(0x1),
12357 mkU8(ac+16)))));
12358 break;
12360 case 0x1B: { /* DPSQX_SA.W.PH */
12361 DIP("dpsqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt);
12362 vassert(!mode64);
12363 t0 = newTemp(Ity_I64);
12364 t1 = newTemp(Ity_I64);
12365 t2 = newTemp(Ity_I1);
12366 t3 = newTemp(Ity_I1);
12367 t4 = newTemp(Ity_I64);
12368 t5 = newTemp(Ity_I64);
12369 t6 = newTemp(Ity_I1);
12370 t7 = newTemp(Ity_I1);
12371 t8 = newTemp(Ity_I64);
12372 t9 = newTemp(Ity_I64);
12373 t10 = newTemp(Ity_I32);
12375 assign(t0, getAcc(ac));
12376 /* Calculate the first cross dot product and saturate if
12377 needed. */
12378 assign(t1, unop(Iop_32Sto64,
12379 binop(Iop_Shl32,
12380 binop(Iop_Mul32,
12381 unop(Iop_16Sto32,
12382 unop(Iop_32HIto16,
12383 getIReg(rs))),
12384 unop(Iop_16Sto32,
12385 unop(Iop_32to16,
12386 getIReg(rt)))),
12387 mkU8(0x1))));
12389 /* If both input arguments are equal 0x8000, saturate
12390 intermediate product and write to DSPControl
12391 register. */
12392 assign(t2, binop(Iop_CmpEQ32,
12393 unop(Iop_16Uto32,
12394 unop(Iop_32HIto16, getIReg(rs))),
12395 mkU32(0x00008000)));
12396 assign(t3, binop(Iop_CmpEQ32,
12397 unop(Iop_16Uto32,
12398 unop(Iop_32to16, getIReg(rt))),
12399 mkU32(0x00008000)));
12401 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
12402 binop(Iop_And32,
12403 unop(Iop_1Sto32,
12404 mkexpr(t2)),
12405 unop(Iop_1Sto32,
12406 mkexpr(t3))),
12407 mkU32(0)),
12408 mkU64(0x000000007fffffffULL),
12409 mkexpr(t1)));
12411 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
12412 binop(Iop_And32,
12413 unop(Iop_1Sto32,
12414 mkexpr(t2)),
12415 unop(Iop_1Sto32,
12416 mkexpr(t3))),
12417 mkU32(0)),
12418 binop(Iop_Or32,
12419 getDSPControl(),
12420 binop(Iop_Shl32,
12421 mkU32(0x1),
12422 mkU8(ac+16))),
12423 getDSPControl()));
12424 /* Calculate second cross dot product and saturate if
12425 needed. */
12426 assign(t5, unop(Iop_32Sto64,
12427 binop(Iop_Shl32,
12428 binop(Iop_Mul32,
12429 unop(Iop_16Sto32,
12430 unop(Iop_32to16,
12431 getIReg(rs))),
12432 unop(Iop_16Sto32,
12433 unop(Iop_32HIto16,
12434 getIReg(rt)))),
12435 mkU8(0x1))));
12437 /* If both input arguments are equal 0x8000, saturate
12438 intermediate product and write to DSPControl
12439 register. */
12440 assign(t6, binop(Iop_CmpEQ32,
12441 unop(Iop_16Uto32,
12442 unop(Iop_32to16, getIReg(rs))),
12443 mkU32(0x00008000)));
12444 assign(t7, binop(Iop_CmpEQ32,
12445 unop(Iop_16Uto32,
12446 unop(Iop_32HIto16, getIReg(rt))),
12447 mkU32(0x00008000)));
12449 assign(t8, IRExpr_ITE(binop(Iop_CmpNE32,
12450 binop(Iop_And32,
12451 unop(Iop_1Sto32,
12452 mkexpr(t6)),
12453 unop(Iop_1Sto32,
12454 mkexpr(t7))),
12455 mkU32(0)),
12456 mkU64(0x000000007fffffffULL),
12457 mkexpr(t5)));
12459 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
12460 binop(Iop_And32,
12461 unop(Iop_1Sto32,
12462 mkexpr(t6)),
12463 unop(Iop_1Sto32,
12464 mkexpr(t7))),
12465 mkU32(0)),
12466 binop(Iop_Or32,
12467 getDSPControl(),
12468 binop(Iop_Shl32,
12469 mkU32(0x1),
12470 mkU8(ac+16))),
12471 getDSPControl()));
12472 /* Subtract intermediate products from value in the
12473 accumulator. */
12474 assign(t9,
12475 binop(Iop_Sub64,
12476 mkexpr(t0),
12477 binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));
12479 putAcc(ac,
12480 IRExpr_ITE(binop(Iop_CmpEQ32,
12481 binop(Iop_And32,
12482 unop(Iop_64HIto32,
12483 mkexpr(t9)),
12484 mkU32(0x80000000)),
12485 mkU32(0x0)),
12486 IRExpr_ITE(binop(Iop_CmpNE32,
12487 unop(Iop_64HIto32,
12488 binop(Iop_Shl64,
12489 mkexpr(t9),
12490 mkU8(1))),
12491 mkU32(0x0)),
12492 mkU64(0x000000007fffffffULL),
12493 mkexpr(t9)),
12494 IRExpr_ITE(binop(Iop_CmpNE32,
12495 unop(Iop_64HIto32,
12496 binop(Iop_Shl64,
12497 mkexpr(t9),
12498 mkU8(1))),
12499 mkU32(0xffffffff)),
12500 mkU64(0xffffffff80000000ULL),
12501 mkexpr(t9))));
12502 assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32,
12503 unop(Iop_64to32,
12504 mkexpr(t9)),
12505 unop(Iop_64to32,
12506 getAcc(ac))),
12507 getDSPControl(),
12508 binop(Iop_Or32,
12509 getDSPControl(),
12510 binop(Iop_Shl32,
12511 mkU32(0x1),
12512 mkU8(ac+16)))));
12513 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
12514 unop(Iop_64HIto32,
12515 mkexpr(t9)),
12516 unop(Iop_64HIto32,
12517 getAcc(ac))),
12518 mkexpr(t10),
12519 binop(Iop_Or32,
12520 getDSPControl(),
12521 binop(Iop_Shl32,
12522 mkU32(0x1),
12523 mkU8(ac+16)))));
12524 break;
12526 default:
12527 return -1;
12529 break; /* end of DPAQ.W.PH */
12531 case 0x31: { /* APPEND */
12532 switch(sa) {
12533 case 0x0: { /* APPEND */
12534 DIP("append r%u, r%u, %u", rt, rs, rd);
12535 vassert(!mode64);
12536 t1 = newTemp(Ity_I32);
12537 t2 = newTemp(Ity_I32);
12538 t3 = newTemp(Ity_I32);
12540 assign(t1, binop(Iop_Shl32, getIReg(rt), mkU8(rd)));
12542 if (31 == rd) {
12543 putIReg(rt, binop(Iop_Or32,
12544 mkexpr(t1),
12545 binop(Iop_And32,
12546 getIReg(rs),
12547 mkU32(0x7fffffff))));
12548 } else if (1 == rd) {
12549 putIReg(rt,
12550 binop(Iop_Or32,
12551 mkexpr(t1),
12552 binop(Iop_And32,
12553 getIReg(rs), mkU32(0x1))));
12554 } else {
12555 assign(t2,
12556 unop(Iop_Not32,
12557 binop(Iop_Shl32,
12558 mkU32(0xffffffff), mkU8(rd))));
12560 putIReg(rt, binop(Iop_Or32,
12561 mkexpr(t1),
12562 binop(Iop_And32,
12563 getIReg(rs), mkexpr(t2))));
12565 break;
12567 case 0x1: { /* PREPEND */
12568 DIP("prepend r%u, r%u, %u", rt, rs, rd);
12569 vassert(!mode64);
12570 t1 = newTemp(Ity_I32);
12571 t2 = newTemp(Ity_I32);
12572 t3 = newTemp(Ity_I32);
12574 if (0 != rd) {
12575 assign(t1, binop(Iop_Shr32, getIReg(rt), mkU8(rd)));
12577 if (31 == rd) {
12578 putIReg(rt, binop(Iop_Or32,
12579 mkexpr(t1),
12580 binop(Iop_Shl32,
12581 binop(Iop_And32,
12582 getIReg(rs),
12583 mkU32(0x7fffffff)),
12584 mkU8(1))));
12585 } else if (1 == rd) {
12586 putIReg(rt, binop(Iop_Or32,
12587 mkexpr(t1),
12588 binop(Iop_Shl32,
12589 binop(Iop_And32,
12590 getIReg(rs),
12591 mkU32(0x1)),
12592 mkU8(31))));
12593 } else {
12594 assign(t2, binop(Iop_Add32, mkU32(rd), mkU32(0x1)));
12596 assign(t3, unop(Iop_Not32,
12597 binop(Iop_Shl32,
12598 mkU32(0xffffffff),
12599 unop(Iop_32to8, mkexpr(t2)))));
12601 putIReg(rt, binop(Iop_Or32,
12602 mkexpr(t1),
12603 binop(Iop_Shl32,
12604 binop(Iop_And32,
12605 getIReg(rs),
12606 mkexpr(t3)),
12607 mkU8(32-rd))));
12610 break;
12612 case 0x10: { /* BALIGN */
12613 DIP("balign r%u, r%u, %u", rt, rs, rd);
12614 vassert(!mode64);
12615 t1 = newTemp(Ity_I32);
12616 t2 = newTemp(Ity_I32);
12617 t3 = newTemp(Ity_I32);
12619 if ((2 != rd) && (0 != rd)) {
12620 assign(t1, binop(Iop_Shl32,
12621 binop(Iop_And32,
12622 mkU32(rd), mkU32(0x3)),
12623 mkU8(0x3)));
12624 assign(t2, binop(Iop_Shl32,
12625 getIReg(rt),
12626 unop(Iop_32to8, mkexpr(t1))));
12627 assign(t3, binop(Iop_Shr32,
12628 getIReg(rs),
12629 unop(Iop_32to8,
12630 binop(Iop_Shl32,
12631 binop(Iop_Sub32,
12632 mkU32(0x4),
12633 binop(Iop_And32,
12634 mkU32(rd),
12635 mkU32(0x3))),
12636 mkU8(0x3)))));
12637 putIReg(rt, binop(Iop_Or32, mkexpr(t2), mkexpr(t3)));
12639 break;
12641 default:
12642 return -1;
12644 break; /* end of APPEND */
12646 default:
12647 return -1;
12649 break;
12651 default:
12652 return -1;
12654 return 0;
12657 static Int msa_I8_logical(UInt cins, UChar wd, UChar ws) {
12658 IRTemp t1, t2;
12659 UShort operation;
12660 UChar i8;
12662 operation = (cins >> 24) & 3;
12663 i8 = (cins & 0x00FF0000) >> 16;
12664 switch (operation) {
12665 case 0x00: { /* ANDI.B */
12666 DIP("ANDI.B w%d, w%d, %d", wd, ws, i8);
12667 t1 = newTemp(Ity_V128);
12668 t2 = newTemp(Ity_V128);
12669 ULong tmp = i8;
12670 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
12671 (tmp << 32) | (tmp << 24) | (tmp << 16) |
12672 (tmp << 8);
12673 assign(t1, getWReg(ws));
12674 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
12675 putWReg(wd, binop(Iop_AndV128, mkexpr(t1), mkexpr(t2)));
12676 break;
12679 case 0x01: { /* ORI.B */
12680 DIP("ORI.B w%d, w%d, %d", wd, ws, i8);
12681 t1 = newTemp(Ity_V128);
12682 t2 = newTemp(Ity_V128);
12683 ULong tmp = i8;
12684 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
12685 (tmp << 32) | (tmp << 24) | (tmp << 16) |
12686 (tmp << 8);
12687 assign(t1, getWReg(ws));
12688 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
12689 putWReg(wd, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
12690 break;
12693 case 0x02: { /* NORI.B */
12694 DIP("NORI.B w%d, w%d, %d", wd, ws, i8);
12695 t1 = newTemp(Ity_V128);
12696 t2 = newTemp(Ity_V128);
12697 ULong tmp = i8;
12698 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
12699 (tmp << 32) | (tmp << 24) | (tmp << 16) |
12700 (tmp << 8);
12701 assign(t1, getWReg(ws));
12702 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
12703 putWReg(wd, unop(Iop_NotV128, binop(Iop_OrV128,
12704 mkexpr(t1), mkexpr(t2))));
12705 break;
12708 case 0x03: { /* XORI.B */
12709 DIP("XORI.B w%d, w%d, %d", wd, ws, i8);
12710 t1 = newTemp(Ity_V128);
12711 t2 = newTemp(Ity_V128);
12712 ULong tmp = i8;
12713 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
12714 (tmp << 32) | (tmp << 24) | (tmp << 16) |
12715 (tmp << 8);
12716 assign(t1, getWReg(ws));
12717 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
12718 putWReg(wd, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
12719 break;
12722 default:
12723 return -1;
12726 return 0;
12729 static Int msa_I8_branch(UInt cins, UChar wd, UChar ws) {
12730 IRTemp t1, t2, t3, t4;
12731 UShort operation;
12732 UChar i8;
12734 operation = (cins >> 24) & 3;
12735 i8 = (cins & 0x00FF0000) >> 16;
12736 switch (operation) {
12737 case 0x00: { /* BMNZI.B */
12738 DIP("BMNZI.B w%d, w%d, %d", wd, ws, i8);
12739 t1 = newTemp(Ity_V128);
12740 t2 = newTemp(Ity_V128);
12741 t3 = newTemp(Ity_V128);
12742 t4 = newTemp(Ity_V128);
12743 ULong tmp = i8;
12744 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
12745 (tmp << 32) | (tmp << 24) | (tmp << 16) |
12746 (tmp << 8);
12747 assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
12748 assign(t1, binop(Iop_AndV128, getWReg(ws), mkexpr(t4)));
12749 assign(t2, binop(Iop_AndV128, getWReg(wd),
12750 unop(Iop_NotV128, mkexpr(t4))));
12751 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
12752 putWReg(wd, mkexpr(t3));
12753 break;
12756 case 0x01: { /* BMZI.B */
12757 DIP("BMZI.B w%d, w%d, %d", wd, ws, i8);
12758 t1 = newTemp(Ity_V128);
12759 t2 = newTemp(Ity_V128);
12760 t3 = newTemp(Ity_V128);
12761 t4 = newTemp(Ity_V128);
12762 ULong tmp = i8;
12763 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
12764 (tmp << 32) | (tmp << 24) | (tmp << 16) |
12765 (tmp << 8);
12766 assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
12767 assign(t1, binop(Iop_AndV128, getWReg(wd), mkexpr(t4)));
12768 assign(t2, binop(Iop_AndV128, getWReg(ws),
12769 unop(Iop_NotV128, mkexpr(t4))));
12770 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
12771 putWReg(wd, mkexpr(t3));
12772 break;
12775 case 0x02: { /* BSELI.B */
12776 DIP("BSELI.B w%d, w%d, %d", wd, ws, i8);
12777 t1 = newTemp(Ity_V128);
12778 t2 = newTemp(Ity_V128);
12779 t3 = newTemp(Ity_V128);
12780 t4 = newTemp(Ity_V128);
12781 ULong tmp = i8;
12782 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
12783 (tmp << 32) | (tmp << 24) | (tmp << 16) |
12784 (tmp << 8);
12785 assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
12786 assign(t1, binop(Iop_AndV128, getWReg(wd), mkexpr(t4)));
12787 assign(t2, binop(Iop_AndV128, getWReg(ws),
12788 unop(Iop_NotV128, getWReg(wd))));
12789 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
12790 putWReg(wd, mkexpr(t3));
12791 break;
12794 default:
12795 return -1;
12798 return 0;
12801 static Int msa_I8_shift(UInt cins, UChar wd, UChar ws) {
12802 IRTemp t1, t2;
12803 UShort operation;
12804 UChar i8;
12806 operation = (cins >> 24) & 3;
12807 i8 = (cins & 0x00FF0000) >> 16;
12808 switch (operation) {
12809 case 0x00: { /* SHF.B */
12810 DIP("SHF.B w%d, w%d, %d", wd, ws, i8);
12811 t1 = newTemp(Ity_V128);
12812 t2 = newTemp(Ity_V128);
12813 assign(t1, getWReg(wd));
12814 assign(t2, getWReg(ws));
12815 Int i;
12816 IRTemp tmp[16];
12818 for (i = 0; i < 16; i++) {
12819 tmp[i] = newTemp(Ity_I8);
12820 assign(tmp[i],
12821 binop(Iop_GetElem8x16, mkexpr(t2),
12822 mkU8(i - (i % 4) +
12823 ((i8 >> (i % 4) * 2) & 0x03))));
12826 putWReg(wd, binop(Iop_64HLtoV128,
12827 binop(Iop_32HLto64,
12828 binop(Iop_16HLto32,
12829 binop(Iop_8HLto16,
12830 mkexpr(tmp[15]),
12831 mkexpr(tmp[14])),
12832 binop(Iop_8HLto16,
12833 mkexpr(tmp[13]),
12834 mkexpr(tmp[12]))),
12835 binop(Iop_16HLto32,
12836 binop(Iop_8HLto16,
12837 mkexpr(tmp[11]),
12838 mkexpr(tmp[10])),
12839 binop(Iop_8HLto16,
12840 mkexpr(tmp[9]),
12841 mkexpr(tmp[8])))),
12842 binop(Iop_32HLto64,
12843 binop(Iop_16HLto32,
12844 binop(Iop_8HLto16,
12845 mkexpr(tmp[7]),
12846 mkexpr(tmp[6])),
12847 binop(Iop_8HLto16,
12848 mkexpr(tmp[5]),
12849 mkexpr(tmp[4]))),
12850 binop(Iop_16HLto32,
12851 binop(Iop_8HLto16,
12852 mkexpr(tmp[3]),
12853 mkexpr(tmp[2])),
12854 binop(Iop_8HLto16,
12855 mkexpr(tmp[1]),
12856 mkexpr(tmp[0]))))));
12857 break;
12860 case 0x01: { /* SHF.H */
12861 DIP("SHF.H w%d, w%d, %d", wd, ws, i8);
12862 t1 = newTemp(Ity_V128);
12863 t2 = newTemp(Ity_V128);
12864 assign(t1, getWReg(wd));
12865 assign(t2, getWReg(ws));
12866 Int i;
12867 IRTemp tmp[8];
12869 for (i = 0; i < 8; i++) {
12870 tmp[i] = newTemp(Ity_I16);
12871 assign(tmp[i],
12872 binop(Iop_GetElem16x8, mkexpr(t2),
12873 mkU8(i - (i % 4) +
12874 ((i8 >> (i % 4) * 2) & 0x03))));
12877 putWReg(wd, binop(Iop_64HLtoV128,
12878 binop(Iop_32HLto64,
12879 binop(Iop_16HLto32,
12880 mkexpr(tmp[7]), mkexpr(tmp[6])),
12881 binop(Iop_16HLto32,
12882 mkexpr(tmp[5]), mkexpr(tmp[4]))),
12883 binop(Iop_32HLto64,
12884 binop(Iop_16HLto32,
12885 mkexpr(tmp[3]), mkexpr(tmp[2])),
12886 binop(Iop_16HLto32,
12887 mkexpr(tmp[1]), mkexpr(tmp[0])))));
12888 break;
12891 case 0x02: { /* SHF.W */
12892 DIP("SHF.W w%d, w%d, %d", wd, ws, i8);
12893 t1 = newTemp(Ity_V128);
12894 t2 = newTemp(Ity_V128);
12895 assign(t1, getWReg(wd));
12896 assign(t2, getWReg(ws));
12897 Int i;
12898 IRTemp tmp[4];
12900 for (i = 0; i < 4; i++) {
12901 tmp[i] = newTemp(Ity_I32);
12902 assign(tmp[i],
12903 binop(Iop_GetElem32x4, mkexpr(t2),
12904 mkU8(i - (i % 4) +
12905 ((i8 >> (i % 4) * 2) & 0x03))));
12908 putWReg(wd, binop(Iop_64HLtoV128,
12909 binop(Iop_32HLto64,
12910 mkexpr(tmp[3]), mkexpr(tmp[2])),
12911 binop(Iop_32HLto64,
12912 mkexpr(tmp[1]), mkexpr(tmp[0]))));
12913 break;
12916 default:
12917 return -1;
12920 return 0;
12923 static Int msa_I5_06(UInt cins, UChar wd, UChar ws) { /* I5 (0x06) */
12924 IRTemp t1, t2, t3;
12925 UShort operation;
12926 UChar df, wt;
12928 operation = (cins & 0x03800000) >> 23;
12929 df = (cins & 0x00600000) >> 21;
12930 wt = (cins & 0x001F0000) >> 16;
12932 switch (operation) {
12933 case 0x00: { /* ADDVI */
12934 ULong tmp = wt;
12936 switch (df) {
12937 case 0x00: { /* ADDVI.B */
12938 DIP("ADDVI.B w%d, w%d, %d", wd, ws, wt);
12939 t1 = newTemp(Ity_V128);
12940 t2 = newTemp(Ity_V128);
12941 t3 = newTemp(Ity_V128);
12942 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
12943 (tmp << 32) | (tmp << 24) | (tmp << 16) |
12944 (tmp << 8);
12945 assign(t1, getWReg(ws));
12946 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
12947 assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
12948 putWReg(wd, mkexpr(t3));
12949 break;
12952 case 0x01: { /* ADDVI.H */
12953 DIP("ADDVI.H w%d, w%d, %d", wd, ws, wt);
12954 t1 = newTemp(Ity_V128);
12955 t2 = newTemp(Ity_V128);
12956 t3 = newTemp(Ity_V128);
12957 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
12958 assign(t1, getWReg(ws));
12959 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
12960 assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
12961 putWReg(wd, mkexpr(t3));
12962 break;
12965 case 0x02: { /* ADDVI.W */
12966 DIP("ADDVI.W w%d, w%d, %d", wd, ws, wt);
12967 t1 = newTemp(Ity_V128);
12968 t2 = newTemp(Ity_V128);
12969 t3 = newTemp(Ity_V128);
12970 tmp |= (tmp << 32);
12971 assign(t1, getWReg(ws));
12972 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
12973 assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
12974 putWReg(wd, mkexpr(t3));
12975 break;
12978 case 0x03: { /* ADDVI.D */
12979 DIP("ADDVI.D w%d, w%d, %d", wd, ws, wt);
12980 t1 = newTemp(Ity_V128);
12981 t2 = newTemp(Ity_V128);
12982 t3 = newTemp(Ity_V128);
12983 assign(t1, getWReg(ws));
12984 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
12985 assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
12986 putWReg(wd, mkexpr(t3));
12987 break;
12991 break;
12994 case 0x01: { /* SUBVI */
12995 ULong tmp = wt;
12997 switch (df) {
12998 case 0x00: { /* SUBVI.B */
12999 DIP("SUBVI.B w%d, w%d, %d", wd, ws, wt);
13000 t1 = newTemp(Ity_V128);
13001 t2 = newTemp(Ity_V128);
13002 t3 = newTemp(Ity_V128);
13003 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
13004 (tmp << 32) | (tmp << 24) | (tmp << 16) |
13005 (tmp << 8);
13006 assign(t1, getWReg(ws));
13007 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13008 assign(t3, binop(Iop_Sub8x16, mkexpr(t1), mkexpr(t2)));
13009 putWReg(wd, mkexpr(t3));
13010 break;
13013 case 0x01: { /* SUBVI.H */
13014 DIP("SUBVI.H w%d, w%d, %d", wd, ws, wt);
13015 t1 = newTemp(Ity_V128);
13016 t2 = newTemp(Ity_V128);
13017 t3 = newTemp(Ity_V128);
13018 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
13019 assign(t1, getWReg(ws));
13020 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13021 assign(t3, binop(Iop_Sub16x8, mkexpr(t1), mkexpr(t2)));
13022 putWReg(wd, mkexpr(t3));
13023 break;
13026 case 0x02: { /* SUBVI.W */
13027 DIP("SUBVI.W w%d, w%d, %d", wd, ws, wt);
13028 t1 = newTemp(Ity_V128);
13029 t2 = newTemp(Ity_V128);
13030 t3 = newTemp(Ity_V128);
13031 tmp |= (tmp << 32);
13032 assign(t1, getWReg(ws));
13033 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13034 assign(t3, binop(Iop_Sub32x4, mkexpr(t1), mkexpr(t2)));
13035 putWReg(wd, mkexpr(t3));
13036 break;
13039 case 0x03: { /* SUBVI.D */
13040 DIP("SUBVI.D w%d, w%d, %d", wd, ws, wt);
13041 t1 = newTemp(Ity_V128);
13042 t2 = newTemp(Ity_V128);
13043 t3 = newTemp(Ity_V128);
13044 assign(t1, getWReg(ws));
13045 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13046 assign(t3, binop(Iop_Sub64x2, mkexpr(t1), mkexpr(t2)));
13047 putWReg(wd, mkexpr(t3));
13048 break;
13052 break;
13055 case 0x02: { /* MAXI_S */
13056 ULong tmp = wt;
13058 switch (df) {
13059 case 0x00: { /* MAXI_S.B */
13060 DIP("MAXI_S.B w%d, w%d, %d", wd, ws, wt);
13061 t1 = newTemp(Ity_V128);
13062 t2 = newTemp(Ity_V128);
13063 t3 = newTemp(Ity_V128);
13064 char stemp = ((int)tmp << 27) >> 27;
13065 tmp = (UChar)stemp;
13066 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
13067 (tmp << 32) | (tmp << 24) | (tmp << 16) |
13068 (tmp << 8);
13069 assign(t1, getWReg(ws));
13070 assign(t2,binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13071 assign(t3, binop(Iop_Max8Sx16, mkexpr(t1), mkexpr(t2)));
13072 putWReg(wd, mkexpr(t3));
13073 break;
13076 case 0x01: { /* MAXI_S.H */
13077 DIP("MAXI_S.H w%d, w%d, %d", wd, ws, wt);
13078 t1 = newTemp(Ity_V128);
13079 t2 = newTemp(Ity_V128);
13080 t3 = newTemp(Ity_V128);
13081 short stemp = ((int)tmp << 27) >> 27;
13082 tmp = (UShort)stemp;
13083 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
13084 assign(t1, getWReg(ws));
13085 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13086 assign(t3, binop(Iop_Max16Sx8, mkexpr(t1), mkexpr(t2)));
13087 putWReg(wd, mkexpr(t3));
13088 break;
13091 case 0x02: { /* MAXI_S.W */
13092 DIP("MAXI_S.W w%d, w%d, %d", wd, ws, wt);
13093 t1 = newTemp(Ity_V128);
13094 t2 = newTemp(Ity_V128);
13095 t3 = newTemp(Ity_V128);
13096 int stemp = ((int)tmp << 27) >> 27;
13097 tmp = (UInt)stemp;
13098 tmp |= (tmp << 32);
13099 assign(t1, getWReg(ws));
13100 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13101 assign(t3, binop(Iop_Max32Sx4, mkexpr(t1), mkexpr(t2)));
13102 putWReg(wd, mkexpr(t3));
13103 break;
13106 case 0x03: { /* MAXI_S.D */
13107 DIP("MAXI_S.D w%d, w%d, %d", wd, ws, wt);
13108 t1 = newTemp(Ity_V128);
13109 t2 = newTemp(Ity_V128);
13110 t3 = newTemp(Ity_V128);
13111 Long stemp = ((Long)tmp << 59) >> 59;
13112 tmp = stemp;
13113 assign(t1, getWReg(ws));
13114 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13115 assign(t3, binop(Iop_Max64Sx2, mkexpr(t1), mkexpr(t2)));
13116 putWReg(wd, mkexpr(t3));
13117 break;
13121 break;
13124 case 0x03: { /* MAXI_U */
13125 ULong tmp = wt;
13127 switch (df) {
13128 case 0x00: { /* MAXI_U.B */
13129 DIP("MAXI_U.B w%d, w%d, %d", wd, ws, wt);
13130 t1 = newTemp(Ity_V128);
13131 t2 = newTemp(Ity_V128);
13132 t3 = newTemp(Ity_V128);
13133 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
13134 (tmp << 32) | (tmp << 24) | (tmp << 16) |
13135 (tmp << 8);
13136 assign(t1, getWReg(ws));
13137 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13138 assign(t3, binop(Iop_Max8Ux16, mkexpr(t1), mkexpr(t2)));
13139 putWReg(wd, mkexpr(t3));
13140 break;
13143 case 0x01: { /* MAXI_U.H */
13144 DIP("MAXI_U.H w%d, w%d, %d", wd, ws, wt);
13145 t1 = newTemp(Ity_V128);
13146 t2 = newTemp(Ity_V128);
13147 t3 = newTemp(Ity_V128);
13148 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
13149 assign(t1, getWReg(ws));
13150 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13151 assign(t3, binop(Iop_Max16Ux8, mkexpr(t1), mkexpr(t2)));
13152 putWReg(wd, mkexpr(t3));
13153 break;
13156 case 0x02: { /* MAXI_U.W */
13157 DIP("MAXI_U.W w%d, w%d, %d", wd, ws, wt);
13158 t1 = newTemp(Ity_V128);
13159 t2 = newTemp(Ity_V128);
13160 t3 = newTemp(Ity_V128);
13161 tmp |= (tmp << 32);
13162 assign(t1, getWReg(ws));
13163 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13164 assign(t3, binop(Iop_Max32Ux4, mkexpr(t1), mkexpr(t2)));
13165 putWReg(wd, mkexpr(t3));
13166 break;
13169 case 0x03: { /* MAXI_U.D */
13170 DIP("MAXI_U.D w%d, w%d, %d", wd, ws, wt);
13171 t1 = newTemp(Ity_V128);
13172 t2 = newTemp(Ity_V128);
13173 t3 = newTemp(Ity_V128);
13174 assign(t1, getWReg(ws));
13175 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13176 assign(t3, binop(Iop_Max64Ux2, mkexpr(t1), mkexpr(t2)));
13177 putWReg(wd, mkexpr(t3));
13178 break;
13182 break;
13185 case 0x04: { /* MINI_S */
13186 ULong tmp = wt;
13188 switch (df) {
13189 case 0x00: { /* MINI_S.B */
13190 DIP("MINI_S.B w%d, w%d, %d", wd, ws, wt);
13191 t1 = newTemp(Ity_V128);
13192 t2 = newTemp(Ity_V128);
13193 t3 = newTemp(Ity_V128);
13194 char stemp = ((int)tmp << 27) >> 27;
13195 tmp = (UChar)stemp;
13196 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
13197 (tmp << 32) | (tmp << 24) | (tmp << 16) |
13198 (tmp << 8);
13199 assign(t1, getWReg(ws));
13200 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13201 assign(t3, binop(Iop_Min8Sx16, mkexpr(t1), mkexpr(t2)));
13202 putWReg(wd, mkexpr(t3));
13203 break;
13206 case 0x01: { /* MINI_S.H */
13207 DIP("MINI_S.H w%d, w%d, %d", wd, ws, wt);
13208 t1 = newTemp(Ity_V128);
13209 t2 = newTemp(Ity_V128);
13210 t3 = newTemp(Ity_V128);
13211 short stemp = ((int)tmp << 27) >> 27;
13212 tmp = (UShort)stemp;
13213 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
13214 assign(t1, getWReg(ws));
13215 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13216 assign(t3, binop(Iop_Min16Sx8, mkexpr(t1), mkexpr(t2)));
13217 putWReg(wd, mkexpr(t3));
13218 break;
13221 case 0x02: { /* MINI_S.W */
13222 DIP("MINI_S.W w%d, w%d, %d", wd, ws, wt);
13223 t1 = newTemp(Ity_V128);
13224 t2 = newTemp(Ity_V128);
13225 t3 = newTemp(Ity_V128);
13226 int stemp = ((int)tmp << 27) >> 27;
13227 tmp = (UInt)stemp;
13228 tmp |= (tmp << 32);
13229 assign(t1, getWReg(ws));
13230 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13231 assign(t3, binop(Iop_Min32Sx4, mkexpr(t1), mkexpr(t2)));
13232 putWReg(wd, mkexpr(t3));
13233 break;
13236 case 0x03: { /* MINI_S.D */
13237 DIP("MINI_S.D w%d, w%d, %d", wd, ws, wt);
13238 t1 = newTemp(Ity_V128);
13239 t2 = newTemp(Ity_V128);
13240 t3 = newTemp(Ity_V128);
13241 Long stemp = ((Long)tmp << 59) >> 59;
13242 tmp = stemp;
13243 assign(t1, getWReg(ws));
13244 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13245 assign(t3, binop(Iop_Min64Sx2, mkexpr(t1), mkexpr(t2)));
13246 putWReg(wd, mkexpr(t3));
13247 break;
13251 break;
13254 case 0x05: { /* MINI_U */
13255 ULong tmp = wt;
13257 switch (df) {
13258 case 0x00: { /* MINI_U.B */
13259 DIP("MINI_U.B w%d, w%d, %d", wd, ws, wt);
13260 t1 = newTemp(Ity_V128);
13261 t2 = newTemp(Ity_V128);
13262 t3 = newTemp(Ity_V128);
13263 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
13264 (tmp << 32) | (tmp << 24) | (tmp << 16) |
13265 (tmp << 8);
13266 assign(t1, getWReg(ws));
13267 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13268 assign(t3, binop(Iop_Min8Ux16, mkexpr(t1), mkexpr(t2)));
13269 putWReg(wd, mkexpr(t3));
13270 break;
13273 case 0x01: { /* MINI_U.H */
13274 DIP("MINI_U.H w%d, w%d, %d", wd, ws, wt);
13275 t1 = newTemp(Ity_V128);
13276 t2 = newTemp(Ity_V128);
13277 t3 = newTemp(Ity_V128);
13278 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
13279 assign(t1, getWReg(ws));
13280 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13281 assign(t3, binop(Iop_Min16Ux8, mkexpr(t1), mkexpr(t2)));
13282 putWReg(wd, mkexpr(t3));
13283 break;
13286 case 0x02: { /* MINI_U.W */
13287 DIP("MINI_U.W w%d, w%d, %d", wd, ws, wt);
13288 t1 = newTemp(Ity_V128);
13289 t2 = newTemp(Ity_V128);
13290 t3 = newTemp(Ity_V128);
13291 tmp |= (tmp << 32);
13292 assign(t1, getWReg(ws));
13293 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13294 assign(t3, binop(Iop_Min32Ux4, mkexpr(t1), mkexpr(t2)));
13295 putWReg(wd, mkexpr(t3));
13296 break;
13299 case 0x03: { /* MINI_U.D */
13300 DIP("MINI_U.D w%d, w%d, %d", wd, ws, wt);
13301 t1 = newTemp(Ity_V128);
13302 t2 = newTemp(Ity_V128);
13303 t3 = newTemp(Ity_V128);
13304 assign(t1, getWReg(ws));
13305 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13306 assign(t3, binop(Iop_Min64Ux2, mkexpr(t1), mkexpr(t2)));
13307 putWReg(wd, mkexpr(t3));
13308 break;
13312 break;
13315 default: {
13316 return -1;
13320 return 0;
13323 static Int msa_I5_07(UInt cins, UChar wd, UChar ws) { /* I5 (0x07) / I10 */
13324 IRTemp t1, t2, t3;
13325 UShort operation;
13326 UChar df, i5;
13328 operation = (cins & 0x03800000) >> 23;
13329 df = (cins & 0x00600000) >> 21;
13330 i5 = (cins & 0x001F0000) >> 16;
13332 switch (operation) {
13333 case 0x00: {
13334 ULong tmp = i5;
13336 switch (df) {
13337 case 0x00: { /* CEQI.B */
13338 DIP("CEQI.B w%d, w%d, %d", wd, ws, i5);
13339 t1 = newTemp(Ity_V128);
13340 t2 = newTemp(Ity_V128);
13341 t3 = newTemp(Ity_V128);
13342 char stemp = ((int)tmp << 27) >> 27;
13343 tmp = (UChar)stemp;
13344 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
13345 (tmp << 32) | (tmp << 24) | (tmp << 16) |
13346 (tmp << 8);
13347 assign(t1, getWReg(ws));
13348 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13349 assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
13350 putWReg(wd, mkexpr(t3));
13351 break;
13354 case 0x01: { /* CEQI.H */
13355 DIP("CEQI.H w%d, w%d, %d", wd, ws, i5);
13356 t1 = newTemp(Ity_V128);
13357 t2 = newTemp(Ity_V128);
13358 t3 = newTemp(Ity_V128);
13359 short stemp = ((int)tmp << 27) >> 27;
13360 tmp = (UShort)stemp;
13361 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
13362 assign(t1, getWReg(ws));
13363 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13364 assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
13365 putWReg(wd, mkexpr(t3));
13366 break;
13369 case 0x02: { /* CEQI.W */
13370 DIP("CEQI.W w%d, w%d, %d", wd, ws, i5);
13371 t1 = newTemp(Ity_V128);
13372 t2 = newTemp(Ity_V128);
13373 t3 = newTemp(Ity_V128);
13374 int stemp = ((int)tmp << 27) >> 27;
13375 tmp = (UInt)stemp;
13376 tmp |= (tmp << 32);
13377 assign(t1, getWReg(ws));
13378 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13379 assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
13380 putWReg(wd, mkexpr(t3));
13381 break;
13384 case 0x03: { /* CEQI.D */
13385 DIP("CEQI.D w%d, w%d, %d", wd, ws, i5);
13386 t1 = newTemp(Ity_V128);
13387 t2 = newTemp(Ity_V128);
13388 t3 = newTemp(Ity_V128);
13389 Long stemp = ((Long)tmp << 59) >> 59;
13390 tmp = stemp;
13391 assign(t1, getWReg(ws));
13392 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13393 assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
13394 putWReg(wd, mkexpr(t3));
13395 break;
13399 break;
13402 case 0x02: { /* CLTI_S.df */
13403 ULong tmp = i5;
13405 switch (df) {
13406 case 0x00: { /* CLTI_S.B */
13407 DIP("CLTI_S.B w%d, w%d, %d", wd, ws, i5);
13408 t1 = newTemp(Ity_V128);
13409 t2 = newTemp(Ity_V128);
13410 t3 = newTemp(Ity_V128);
13411 char stemp = ((int)tmp << 27) >> 27;
13412 tmp = (UChar)stemp;
13413 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
13414 (tmp << 32) | (tmp << 24) | (tmp << 16) |
13415 (tmp << 8);
13416 assign(t1, getWReg(ws));
13417 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13418 assign(t3, binop(Iop_CmpGT8Sx16, mkexpr(t2), mkexpr(t1)));
13419 putWReg(wd, mkexpr(t3));
13420 break;
13423 case 0x01: { /* CLTI_S.H */
13424 DIP("CLTI_S.H w%d, w%d, %d", wd, ws, i5);
13425 t1 = newTemp(Ity_V128);
13426 t2 = newTemp(Ity_V128);
13427 t3 = newTemp(Ity_V128);
13428 short stemp = ((int)tmp << 27) >> 27;
13429 tmp = (UShort)stemp;
13430 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
13431 assign(t1, getWReg(ws));
13432 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13433 assign(t3, binop(Iop_CmpGT16Sx8, mkexpr(t2), mkexpr(t1)));
13434 putWReg(wd, mkexpr(t3));
13435 break;
13438 case 0x02: { /* CLTI_S.W */
13439 DIP("CLTI_S.W w%d, w%d, %d", wd, ws, i5);
13440 t1 = newTemp(Ity_V128);
13441 t2 = newTemp(Ity_V128);
13442 t3 = newTemp(Ity_V128);
13443 int stemp = ((int)tmp << 27) >> 27;
13444 tmp = (UInt)stemp;
13445 tmp |= (tmp << 32);
13446 assign(t1, getWReg(ws));
13447 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13448 assign(t3, binop(Iop_CmpGT32Sx4, mkexpr(t2), mkexpr(t1)));
13449 putWReg(wd, mkexpr(t3));
13450 break;
13453 case 0x03: { /* CLTI_S.D */
13454 DIP("CLTI_S.D w%d, w%d, %d", wd, ws, i5);
13455 t1 = newTemp(Ity_V128);
13456 t2 = newTemp(Ity_V128);
13457 t3 = newTemp(Ity_V128);
13458 Long stemp = ((Long)tmp << 59) >> 59;
13459 tmp = stemp;
13460 assign(t1, getWReg(ws));
13461 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13462 assign(t3, binop(Iop_CmpGT64Sx2, mkexpr(t2), mkexpr(t1)));
13463 putWReg(wd, mkexpr(t3));
13464 break;
13467 default:
13468 return -1;
13471 break;
13474 case 0x03: { /* CLTI_U.df */
13475 ULong tmp = i5;
13477 switch (df) {
13478 case 0x00: { /* CLTI_U.B */
13479 DIP("CLTI_U.B w%d, w%d, %d", wd, ws, i5);
13480 t1 = newTemp(Ity_V128);
13481 t2 = newTemp(Ity_V128);
13482 t3 = newTemp(Ity_V128);
13483 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
13484 (tmp << 32) | (tmp << 24) | (tmp << 16) |
13485 (tmp << 8);
13486 assign(t1, getWReg(ws));
13487 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13488 assign(t3, binop(Iop_CmpGT8Ux16, mkexpr(t2), mkexpr(t1)));
13489 putWReg(wd, mkexpr(t3));
13490 break;
13493 case 0x01: { /* CLTI_U.H */
13494 DIP("CLTI_U.H w%d, w%d, %d", wd, ws, i5);
13495 t1 = newTemp(Ity_V128);
13496 t2 = newTemp(Ity_V128);
13497 t3 = newTemp(Ity_V128);
13498 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
13499 assign(t1, getWReg(ws));
13500 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13501 assign(t3, binop(Iop_CmpGT16Ux8, mkexpr(t2), mkexpr(t1)));
13502 putWReg(wd, mkexpr(t3));
13503 break;
13506 case 0x02: { /* CLTI_U.W */
13507 DIP("CLTI_U.W w%d, w%d, %d", wd, ws, i5);
13508 t1 = newTemp(Ity_V128);
13509 t2 = newTemp(Ity_V128);
13510 t3 = newTemp(Ity_V128);
13511 tmp |= (tmp << 32);
13512 assign(t1, getWReg(ws));
13513 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13514 assign(t3, binop(Iop_CmpGT32Ux4, mkexpr(t2), mkexpr(t1)));
13515 putWReg(wd, mkexpr(t3));
13516 break;
13519 case 0x03: { /* CLTI_U.D */
13520 DIP("CLTI_U.D w%d, w%d, %d", wd, ws, i5);
13521 t1 = newTemp(Ity_V128);
13522 t2 = newTemp(Ity_V128);
13523 t3 = newTemp(Ity_V128);
13524 assign(t1, getWReg(ws));
13525 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13526 assign(t3, binop(Iop_CmpGT64Ux2, mkexpr(t2), mkexpr(t1)));
13527 putWReg(wd, mkexpr(t3));
13528 break;
13532 break;
13535 case 0x04: { /* CLEI_S.df */
13536 ULong tmp = i5;
13538 switch (df) {
13539 case 0x00: { /* CLEI_S.B */
13540 DIP("CLEI_S.B w%d, w%d, %d", wd, ws, i5);
13541 t1 = newTemp(Ity_V128);
13542 t2 = newTemp(Ity_V128);
13543 t3 = newTemp(Ity_V128);
13544 char stemp = ((int)tmp << 27) >> 27;
13545 tmp = (UChar)stemp;
13546 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
13547 (tmp << 32) | (tmp << 24) | (tmp << 16) |
13548 (tmp << 8);
13549 assign(t1, getWReg(ws));
13550 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13551 assign(t3, binop(Iop_OrV128, binop(Iop_CmpGT8Sx16,
13552 mkexpr(t2), mkexpr(t1)),
13553 binop(Iop_CmpEQ8x16,
13554 mkexpr(t1), mkexpr(t2))));
13555 putWReg(wd, mkexpr(t3));
13556 break;
13559 case 0x01: { /* CLEI_S.H */
13560 DIP("CLEI_S.H w%d, w%d, %d", wd, ws, i5);
13561 t1 = newTemp(Ity_V128);
13562 t2 = newTemp(Ity_V128);
13563 t3 = newTemp(Ity_V128);
13564 short stemp = ((int)tmp << 27) >> 27;
13565 tmp = (UShort)stemp;
13566 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
13567 assign(t1, getWReg(ws));
13568 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13569 assign(t3, binop(Iop_OrV128, binop(Iop_CmpGT16Sx8,
13570 mkexpr(t2), mkexpr(t1)),
13571 binop(Iop_CmpEQ16x8,
13572 mkexpr(t1), mkexpr(t2))));
13573 putWReg(wd, mkexpr(t3));
13574 break;
13577 case 0x02: { /* CLEI_S.W */
13578 DIP("CLEI_S.W w%d, w%d, %d", wd, ws, i5);
13579 t1 = newTemp(Ity_V128);
13580 t2 = newTemp(Ity_V128);
13581 t3 = newTemp(Ity_V128);
13582 int stemp = ((int)tmp << 27) >> 27;
13583 tmp = (UInt)stemp;
13584 tmp |= (tmp << 32);
13585 assign(t1, getWReg(ws));
13586 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13587 assign(t3, binop(Iop_OrV128,
13588 binop(Iop_CmpGT32Sx4,
13589 mkexpr(t2), mkexpr(t1)),
13590 binop(Iop_CmpEQ32x4,
13591 mkexpr(t1), mkexpr(t2))));
13592 putWReg(wd, mkexpr(t3));
13593 break;
13596 case 0x03: { /* CLEI_S.D */
13597 DIP("CLEI_S.D w%d, w%d, %d", wd, ws, i5);
13598 t1 = newTemp(Ity_V128);
13599 t2 = newTemp(Ity_V128);
13600 t3 = newTemp(Ity_V128);
13601 Long stemp = ((Long)tmp << 59) >> 59;
13602 tmp = stemp;
13603 assign(t1, getWReg(ws));
13604 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13605 assign(t3, binop(Iop_OrV128,
13606 binop(Iop_CmpGT64Sx2,
13607 mkexpr(t2), mkexpr(t1)),
13608 binop(Iop_CmpEQ64x2,
13609 mkexpr(t1), mkexpr(t2))));
13610 putWReg(wd, mkexpr(t3));
13611 break;
13614 default:
13615 return -1;
13618 break;
13621 case 0x05: { /* CLEI_U.df */
13622 ULong tmp = i5;
13624 switch (df) {
13625 case 0x00: { /* CLEI_U.B */
13626 DIP("CLEI_U.B w%d, w%d, %d", wd, ws, i5);
13627 t1 = newTemp(Ity_V128);
13628 t2 = newTemp(Ity_V128);
13629 t3 = newTemp(Ity_V128);
13630 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
13631 (tmp << 32) | (tmp << 24) | (tmp << 16) |
13632 (tmp << 8);
13633 assign(t1, getWReg(ws));
13634 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13635 assign(t3, binop(Iop_OrV128,
13636 binop(Iop_CmpGT8Ux16,
13637 mkexpr(t2), mkexpr(t1)),
13638 binop(Iop_CmpEQ8x16,
13639 mkexpr(t1), mkexpr(t2))));
13640 putWReg(wd, mkexpr(t3));
13641 break;
13644 case 0x01: { /* CLEI_U.H */
13645 DIP("CLEI_U.H w%d, w%d, %d", wd, ws, i5);
13646 t1 = newTemp(Ity_V128);
13647 t2 = newTemp(Ity_V128);
13648 t3 = newTemp(Ity_V128);
13649 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
13650 assign(t1, getWReg(ws));
13651 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13652 assign(t3, binop(Iop_OrV128,
13653 binop(Iop_CmpGT16Ux8,
13654 mkexpr(t2), mkexpr(t1)),
13655 binop(Iop_CmpEQ16x8,
13656 mkexpr(t1), mkexpr(t2))));
13657 putWReg(wd, mkexpr(t3));
13658 break;
13661 case 0x02: { /* CLEI_U.W */
13662 DIP("CLEI_U.W w%d, w%d, %d", wd, ws, i5);
13663 t1 = newTemp(Ity_V128);
13664 t2 = newTemp(Ity_V128);
13665 t3 = newTemp(Ity_V128);
13666 tmp |= (tmp << 32);
13667 assign(t1, getWReg(ws));
13668 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13669 assign(t3, binop(Iop_OrV128,
13670 binop(Iop_CmpGT32Ux4,
13671 mkexpr(t2), mkexpr(t1)),
13672 binop(Iop_CmpEQ32x4,
13673 mkexpr(t1), mkexpr(t2))));
13674 putWReg(wd, mkexpr(t3));
13675 break;
13678 case 0x03: { /* CLEI_U.D */
13679 DIP("CLEI_U.D w%d, w%d, %d", wd, ws, i5);
13680 t1 = newTemp(Ity_V128);
13681 t2 = newTemp(Ity_V128);
13682 t3 = newTemp(Ity_V128);
13683 assign(t1, getWReg(ws));
13684 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13685 assign(t3, binop(Iop_OrV128,
13686 binop(Iop_CmpGT64Ux2,
13687 mkexpr(t2), mkexpr(t1)),
13688 binop(Iop_CmpEQ64x2,
13689 mkexpr(t1), mkexpr(t2))));
13690 putWReg(wd, mkexpr(t3));
13691 break;
13695 break;
13698 case 0x06: { /* LDI.df */
13699 ULong tmp;
13700 UShort s10;
13701 s10 = (cins & 0x001FF800) >> 11;
13702 switch (df) {
13703 case 0x00: /* LDI.B */
13704 DIP("LDI.B w%d, %d", wd, s10);
13705 tmp = s10 & 0xFFl;
13706 tmp = tmp | (tmp << 8) | (tmp << 16) | (tmp << 24)
13707 | (tmp << 32) | (tmp << 40) | (tmp << 48) |
13708 (tmp << 56);
13709 break;
13711 case 0x01: /* LDI.H */
13712 DIP("LDI.H w%d, %d", wd, s10);
13713 tmp = extend_s_10to16(s10);
13714 tmp = tmp | (tmp << 16) | (tmp << 32) | (tmp << 48);
13715 break;
13717 case 0x02: /* LDI.W */
13718 DIP("LDI.W w%d, %d", wd, s10);
13719 tmp = extend_s_10to32(s10);
13720 tmp = tmp | (tmp << 32);
13721 break;
13723 case 0x03: /* LDI.D */
13724 DIP("LDI.D w%d, %d", wd, s10);
13725 tmp = extend_s_10to64(s10);
13726 break;
13728 default:
13729 return -1;
13732 putWReg(wd, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
13733 break;
13736 default:
13737 return -1;
13740 return 0;
13743 static Int msa_BIT_09(UInt cins, UChar wd, UChar ws) { /* BIT (0x09) */
13744 IRTemp t1, t2, t3;
13745 UShort operation;
13746 UChar df, m;
13748 operation = (cins & 0x03800000) >> 23;
13749 df = (cins & 0x007F0000) >> 16;
13751 if ((df & 0x70) == 0x70) { // 111mmmm; b
13752 m = df & 0x07;
13753 df = 0;
13754 } else if ((df & 0x60) == 0x60) { // 110mmmm; h
13755 m = df & 0x0F;
13756 df = 1;
13757 } else if ((df & 0x40) == 0x40) { // 10mmmmm; w
13758 m = df & 0x1F;
13759 df = 2;
13760 } else if ((df & 0x00) == 0x00) { // 0mmmmmm; d
13761 m = df & 0x3F;
13762 df = 3;
13765 switch (operation) {
13766 case 0x00: { /* SLLI.df */
13767 switch (df) {
13768 case 0x00: { /* SLLI.B */
13769 DIP("SLLI.B w%d, w%d, %d", wd, ws, m);
13770 putWReg(wd, binop(Iop_ShlN8x16, getWReg(ws), mkU8(m)));
13771 break;
13774 case 0x01: { /* SLLI.H */
13775 DIP("SLLI.H w%d, w%d, %d", wd, ws, m);
13776 putWReg(wd, binop(Iop_ShlN16x8, getWReg(ws), mkU8(m)));
13777 break;
13780 case 0x02: { /* SLLI.W */
13781 DIP("SLLI.W w%d, w%d, %d", wd, ws, m);
13782 putWReg(wd, binop(Iop_ShlN32x4, getWReg(ws), mkU8(m)));
13783 break;
13786 case 0x03: { /* SLLI.D */
13787 DIP("SLLI.D w%d, w%d, %d", wd, ws, m);
13788 putWReg(wd, binop(Iop_ShlN64x2, getWReg(ws), mkU8(m)));
13789 break;
13793 break;
13796 case 0x01: { /* SRAI.df */
13797 switch (df) {
13798 case 0x00: { /* SRAI.B */
13799 DIP("SRAI.B w%d, w%d, %d", wd, ws, m);
13800 putWReg(wd, binop(Iop_SarN8x16, getWReg(ws), mkU8(m)));
13801 break;
13804 case 0x01: { /* SRAI.H */
13805 DIP("SRAI.H w%d, w%d, %d", wd, ws, m);
13806 putWReg(wd, binop(Iop_SarN16x8, getWReg(ws), mkU8(m)));
13807 break;
13810 case 0x02: { /* SRAI.W */
13811 DIP("SRAI.W w%d, w%d, %d", wd, ws, m);
13812 putWReg(wd, binop(Iop_SarN32x4, getWReg(ws), mkU8(m)));
13813 break;
13816 case 0x03: { /* SRAI.D */
13817 DIP("SRAI.D w%d, w%d, %d", wd, ws, m);
13818 putWReg(wd, binop(Iop_SarN64x2, getWReg(ws), mkU8(m)));
13819 break;
13823 break;
13826 case 0x02: { /* SRLI.df */
13827 switch (df) {
13828 case 0x00: { /* SRLI.B */
13829 DIP("SRLI.B w%d, w%d, %d", wd, ws, m);
13830 putWReg(wd, binop(Iop_ShrN8x16, getWReg(ws), mkU8(m)));
13831 break;
13834 case 0x01: { /* SRLI.H */
13835 DIP("SRLI.H w%d, w%d, %d", wd, ws, m);
13836 putWReg(wd, binop(Iop_ShrN16x8, getWReg(ws), mkU8(m)));
13837 break;
13840 case 0x02: { /* SRLI.W */
13841 DIP("SRLI.W w%d, w%d, %d", wd, ws, m);
13842 putWReg(wd, binop(Iop_ShrN32x4, getWReg(ws), mkU8(m)));
13843 break;
13846 case 0x03: { /* SRLI.D */
13847 DIP("SRLI.D w%d, w%d, %d", wd, ws, m);
13848 putWReg(wd, binop(Iop_ShrN64x2, getWReg(ws), mkU8(m)));
13849 break;
13853 break;
13856 case 0x03: { /* BCLRI.df */
13857 t1 = newTemp(Ity_V128);
13858 t2 = newTemp(Ity_V128);
13859 t3 = newTemp(Ity_V128);
13860 ULong tmp = 1;
13861 assign(t1, getWReg(ws));
13863 switch (df) {
13864 case 0x00: { /* BCLRI.B */
13865 DIP("BCLRI.B w%d, w%d, %d", wd, ws, m);
13866 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
13867 (tmp << 32) | (tmp << 24) | (tmp << 16) |
13868 (tmp << 8);
13869 assign(t2, binop(Iop_ShlN8x16,
13870 binop(Iop_64HLtoV128,
13871 mkU64(tmp), mkU64(tmp)),mkU8(m)));
13872 break;
13875 case 0x01: { /* BCLRI.H */
13876 DIP("BCLRI.H w%d, w%d, %d", wd, ws, m);
13877 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
13878 assign(t2, binop(Iop_ShlN16x8,
13879 binop(Iop_64HLtoV128,
13880 mkU64(tmp), mkU64(tmp)), mkU8(m)));
13881 break;
13884 case 0x02: { /* BCLRI.W */
13885 DIP("BCLRI.W w%d, w%d, %d", wd, ws, m);
13886 tmp |= (tmp << 32);
13887 assign(t2, binop(Iop_ShlN32x4,
13888 binop(Iop_64HLtoV128,
13889 mkU64(tmp), mkU64(tmp)), mkU8(m)));
13890 break;
13893 case 0x03: { /* BCLRI.D */
13894 DIP("BCLRI.D w%d, w%d, %d", wd, ws, m);
13895 assign(t2, binop(Iop_ShlN64x2,
13896 binop(Iop_64HLtoV128,
13897 mkU64(tmp), mkU64(tmp)), mkU8(m)));
13898 break;
13902 assign(t3, binop(Iop_AndV128,
13903 mkexpr(t1), unop(Iop_NotV128, mkexpr(t2))));
13904 putWReg(wd, mkexpr(t3));
13905 break;
13908 case 0x04: { /* BSETI */
13909 t1 = newTemp(Ity_V128);
13910 t2 = newTemp(Ity_V128);
13911 t3 = newTemp(Ity_V128);
13912 ULong tmp = 1;
13913 assign(t1, getWReg(ws));
13915 switch (df) {
13916 case 0x00: { /* BSETI.B */
13917 DIP("BSETI.B w%d, w%d, %d", wd, ws, m);
13918 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
13919 (tmp << 32) | (tmp << 24) | (tmp << 16) |
13920 (tmp << 8);
13921 assign(t2, binop(Iop_ShlN8x16,
13922 binop(Iop_64HLtoV128,
13923 mkU64(tmp), mkU64(tmp)), mkU8(m)));
13924 break;
13927 case 0x01: { /* BSETI.H */
13928 DIP("BSETI.H w%d, w%d, %d", wd, ws, m);
13929 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
13930 assign(t2, binop(Iop_ShlN16x8,
13931 binop(Iop_64HLtoV128,
13932 mkU64(tmp), mkU64(tmp)), mkU8(m)));
13933 break;
13936 case 0x02: { /* BSETI.W */
13937 DIP("BSETI.W w%d, w%d, %d", wd, ws, m);
13938 tmp |= (tmp << 32);
13939 assign(t2, binop(Iop_ShlN32x4,
13940 binop(Iop_64HLtoV128,
13941 mkU64(tmp), mkU64(tmp)), mkU8(m)));
13942 break;
13945 case 0x03: { /* BSETI.D */
13946 DIP("BSETI.D w%d, w%d, %d", wd, ws, m);
13947 assign(t2, binop(Iop_ShlN64x2,
13948 binop(Iop_64HLtoV128,
13949 mkU64(tmp), mkU64(tmp)), mkU8(m)));
13950 break;
13954 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
13955 putWReg(wd, mkexpr(t3));
13956 break;
13959 case 0x05: { /* BNEGI.df */
13960 t1 = newTemp(Ity_V128);
13961 t2 = newTemp(Ity_V128);
13962 t3 = newTemp(Ity_V128);
13963 ULong tmp = 1;
13964 assign(t1, getWReg(ws));
13966 switch (df) {
13967 case 0x00: { /* BNEGI.B */
13968 DIP("BNEGI.B w%d, w%d, %d", wd, ws, m);
13969 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
13970 (tmp << 32) | (tmp << 24) | (tmp << 16) |
13971 (tmp << 8);
13972 assign(t2, binop(Iop_ShlN8x16,
13973 binop(Iop_64HLtoV128,
13974 mkU64(tmp), mkU64(tmp)), mkU8(m)));
13975 break;
13978 case 0x01: { /* BNEGI.H */
13979 DIP("BNEGI.H w%d, w%d, %d", wd, ws, m);
13980 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
13981 assign(t2, binop(Iop_ShlN16x8,
13982 binop(Iop_64HLtoV128,
13983 mkU64(tmp), mkU64(tmp)), mkU8(m)));
13984 break;
13987 case 0x02: { /* BNEGI.W */
13988 DIP("BNEGI.W w%d, w%d, %d", wd, ws, m);
13989 tmp |= (tmp << 32);
13990 assign(t2, binop(Iop_ShlN32x4,
13991 binop(Iop_64HLtoV128,
13992 mkU64(tmp), mkU64(tmp)), mkU8(m)));
13993 break;
13996 case 0x03: { /* BNEGI.D */
13997 DIP("BNEGI.D w%d, w%d, %d", wd, ws, m);
13998 assign(t2, binop(Iop_ShlN64x2,
13999 binop(Iop_64HLtoV128,
14000 mkU64(tmp), mkU64(tmp)), mkU8(m)));
14001 break;
14005 assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
14006 putWReg(wd, mkexpr(t3));
14007 break;
14010 case 0x06: { /* BINSLI.df */
14011 switch (df) {
14012 case 0x00: { /* BINSLI.B */
14013 DIP("BINSLI.B w%d, w%d, w%d", wd, ws, m);
14014 t1 = newTemp(Ity_V128);
14015 t2 = newTemp(Ity_V128);
14016 t3 = newTemp(Ity_V128);
14017 ULong tmp = 0x8080808080808080ULL;
14018 assign(t1, binop(Iop_SarN8x16,
14019 binop(Iop_64HLtoV128,
14020 mkU64(tmp), mkU64(tmp)), mkU8(m)));
14021 assign(t2,
14022 binop(Iop_AndV128,
14023 unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
14024 assign(t3,
14025 binop(Iop_AndV128,
14026 mkexpr(t1), getWReg(ws)));
14027 putWReg(wd,
14028 binop(Iop_OrV128,
14029 mkexpr(t2), mkexpr(t3)));
14030 break;
14033 case 0x01: { /* BINSLI.H */
14034 DIP("BINSLI.H w%d, w%d, w%d", wd, ws, m);
14035 t1 = newTemp(Ity_V128);
14036 t2 = newTemp(Ity_V128);
14037 t3 = newTemp(Ity_V128);
14038 ULong tmp = 0x8000800080008000ULL;
14039 assign(t1,
14040 binop(Iop_SarN16x8,
14041 binop(Iop_64HLtoV128,
14042 mkU64(tmp), mkU64(tmp)), mkU8(m)));
14043 assign(t2,
14044 binop(Iop_AndV128,
14045 unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
14046 assign(t3,
14047 binop(Iop_AndV128,
14048 mkexpr(t1), getWReg(ws)));
14049 putWReg(wd,
14050 binop(Iop_OrV128,
14051 mkexpr(t2), mkexpr(t3)));
14052 break;
14055 case 0x02: { /* BINSLI.W */
14056 DIP("BINSLI.W w%d, w%d, w%d", wd, ws, m);
14057 t1 = newTemp(Ity_V128);
14058 t2 = newTemp(Ity_V128);
14059 t3 = newTemp(Ity_V128);
14060 ULong tmp = 0x8000000080000000ULL;
14061 assign(t1,
14062 binop(Iop_SarN32x4,
14063 binop(Iop_64HLtoV128,
14064 mkU64(tmp), mkU64(tmp)), mkU8(m)));
14065 assign(t2,
14066 binop(Iop_AndV128,
14067 unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
14068 assign(t3,
14069 binop(Iop_AndV128,
14070 mkexpr(t1), getWReg(ws)));
14071 putWReg(wd,
14072 binop(Iop_OrV128,
14073 mkexpr(t2), mkexpr(t3)));
14074 break;
14077 case 0x03: { /* BINSLI.D */
14078 DIP("BINSLI.D w%d, w%d, w%d", wd, ws, m);
14079 t1 = newTemp(Ity_V128);
14080 t2 = newTemp(Ity_V128);
14081 t3 = newTemp(Ity_V128);
14082 ULong tmp = 0x8000000000000000ULL;
14083 assign(t1,
14084 binop(Iop_SarN64x2,
14085 binop(Iop_64HLtoV128,
14086 mkU64(tmp), mkU64(tmp)), mkU8(m)));
14087 assign(t2,
14088 binop(Iop_AndV128,
14089 unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
14090 assign(t3,
14091 binop(Iop_AndV128,
14092 mkexpr(t1), getWReg(ws)));
14093 putWReg(wd,
14094 binop(Iop_OrV128,
14095 mkexpr(t2), mkexpr(t3)));
14096 break;
14099 default:
14100 return -1;
14103 break;
14106 case 0x07: {
14107 switch (df) {
14108 case 0x00: { /* BINSRI.B */
14109 DIP("BINSRI.B w%d, w%d, w%d", wd, ws, m);
14110 t1 = newTemp(Ity_V128);
14111 t2 = newTemp(Ity_V128);
14112 t3 = newTemp(Ity_V128);
14113 ULong tmp = 0xFEFEFEFEFEFEFEFEULL;
14114 assign(t1,
14115 binop(Iop_ShlN8x16,
14116 binop(Iop_64HLtoV128,
14117 mkU64(tmp), mkU64(tmp)), mkU8(m)));
14118 assign(t2,
14119 binop(Iop_AndV128,
14120 unop(Iop_NotV128, mkexpr(t1)), getWReg(ws)));
14121 assign(t3,
14122 binop(Iop_AndV128,
14123 mkexpr(t1), getWReg(wd)));
14124 putWReg(wd,
14125 binop(Iop_OrV128,
14126 mkexpr(t2), mkexpr(t3)));
14127 break;
14130 case 0x01: { /* BINSRI.H */
14131 DIP("BINSRI.H w%d, w%d, w%d", wd, ws, m);
14132 t1 = newTemp(Ity_V128);
14133 t2 = newTemp(Ity_V128);
14134 t3 = newTemp(Ity_V128);
14135 ULong tmp = 0xFFFEFFFEFFFEFFFEULL;
14136 assign(t1,
14137 binop(Iop_ShlN16x8,
14138 binop(Iop_64HLtoV128,
14139 mkU64(tmp), mkU64(tmp)),
14140 mkU8(m)));
14141 assign(t2,
14142 binop(Iop_AndV128,
14143 unop(Iop_NotV128, mkexpr(t1)),
14144 getWReg(ws)));
14145 assign(t3,
14146 binop(Iop_AndV128,
14147 mkexpr(t1), getWReg(wd)));
14148 putWReg(wd,
14149 binop(Iop_OrV128,
14150 mkexpr(t2), mkexpr(t3)));
14151 break;
14154 case 0x02: { /* BINSRI.W */
14155 DIP("BINSRI.W w%d, w%d, w%d", wd, ws, m);
14156 t1 = newTemp(Ity_V128);
14157 t2 = newTemp(Ity_V128);
14158 t3 = newTemp(Ity_V128);
14159 ULong tmp = 0xFFFFFFFEFFFFFFFEULL;
14160 assign(t1,
14161 binop(Iop_ShlN32x4,
14162 binop(Iop_64HLtoV128,
14163 mkU64(tmp), mkU64(tmp)),
14164 mkU8(m)));
14165 assign(t2,
14166 binop(Iop_AndV128,
14167 unop(Iop_NotV128, mkexpr(t1)),
14168 getWReg(ws)));
14169 assign(t3,
14170 binop(Iop_AndV128,
14171 mkexpr(t1), getWReg(wd)));
14172 putWReg(wd,
14173 binop(Iop_OrV128,
14174 mkexpr(t2), mkexpr(t3)));
14175 break;
14178 case 0x03: { /* BINSRI.D */
14179 DIP("BINSRI.D w%d, w%d, w%d", wd, ws, m);
14180 t1 = newTemp(Ity_V128);
14181 t2 = newTemp(Ity_V128);
14182 t3 = newTemp(Ity_V128);
14183 ULong tmp = -2;
14184 assign(t1,
14185 binop(Iop_ShlN64x2,
14186 binop(Iop_64HLtoV128,
14187 mkU64(tmp), mkU64(tmp)),
14188 mkU8(m)));
14189 assign(t2,
14190 binop(Iop_AndV128,
14191 unop(Iop_NotV128, mkexpr(t1)),
14192 getWReg(ws)));
14193 assign(t3,
14194 binop(Iop_AndV128,
14195 mkexpr(t1), getWReg(wd)));
14196 putWReg(wd,
14197 binop(Iop_OrV128,
14198 mkexpr(t2), mkexpr(t3)));
14199 break;
14202 default:
14203 return -1;
14206 break;
14209 default:
14210 return -1;
14213 return 0;
14216 static Int msa_BIT_0A(UInt cins, UChar wd, UChar ws) { /* BIT (0x0A) */
14217 IRTemp t1, t2;
14218 UShort operation;
14219 UChar df, m;
14221 operation = (cins & 0x03800000) >> 23;
14222 df = (cins & 0x007F0000) >> 16;
14224 if ((df & 0x70) == 0x70) { // 111mmmm; b
14225 m = df & 0x07;
14226 df = 0;
14227 } else if ((df & 0x60) == 0x60) { // 110mmmm; h
14228 m = df & 0x0F;
14229 df = 1;
14230 } else if ((df & 0x40) == 0x40) { // 10mmmmm; w
14231 m = df & 0x1F;
14232 df = 2;
14233 } else if ((df & 0x00) == 0x00) { // 0mmmmmm; d
14234 m = df & 0x3F;
14235 df = 3;
14238 switch (operation) {
14239 case 0x00: { /* SAT_S.df */
14240 switch (df) {
14241 case 0x00: { /* SAT_S.B */
14242 DIP("SAT_S.B w%d, w%d, %d", wd, ws, m);
14243 t1 = newTemp(Ity_V128);
14244 assign(t1, binop(Iop_SarN8x16, getWReg(ws), mkU8(7)));
14246 if (m == 0) {
14247 putWReg(wd, mkexpr(t1));
14248 } else {
14249 t2 = newTemp(Ity_V128);
14250 assign(t2,
14251 binop(Iop_SarN8x16, getWReg(ws), mkU8(m)));
14252 putWReg(wd,
14253 binop(Iop_OrV128,
14254 binop(Iop_OrV128,
14255 binop(Iop_AndV128,
14256 binop(Iop_CmpEQ8x16,
14257 mkexpr(t1),
14258 mkexpr(t2)),
14259 getWReg(ws)),
14260 binop(Iop_ShlN8x16,
14261 binop(Iop_CmpGT8Sx16,
14262 mkexpr(t1),
14263 mkexpr(t2)),
14264 mkU8(m))),
14265 binop(Iop_ShrN8x16,
14266 binop(Iop_CmpGT8Sx16,
14267 mkexpr(t2),
14268 mkexpr(t1)),
14269 mkU8(8 - m))));
14272 break;
14275 case 0x01: { /* SAT_S.H */
14276 DIP("SAT_S.H w%d, w%d, %d", wd, ws, m);
14277 t1 = newTemp(Ity_V128);
14278 assign(t1, binop(Iop_SarN16x8, getWReg(ws), mkU8(15)));
14280 if (m == 0) {
14281 putWReg(wd, mkexpr(t1));
14282 } else {
14283 t2 = newTemp(Ity_V128);
14284 assign(t2,
14285 binop(Iop_SarN16x8,
14286 getWReg(ws),
14287 mkU8(m)));
14288 putWReg(wd,
14289 binop(Iop_OrV128,
14290 binop(Iop_OrV128,
14291 binop(Iop_AndV128,
14292 binop(Iop_CmpEQ16x8,
14293 mkexpr(t1),
14294 mkexpr(t2)),
14295 getWReg(ws)),
14296 binop(Iop_ShlN16x8,
14297 binop(Iop_CmpGT16Sx8,
14298 mkexpr(t1),
14299 mkexpr(t2)),
14300 mkU8(m))),
14301 binop(Iop_ShrN16x8,
14302 binop(Iop_CmpGT16Sx8,
14303 mkexpr(t2),
14304 mkexpr(t1)),
14305 mkU8(16 - m))));
14308 break;
14311 case 0x02: { /* SAT_S.W */
14312 DIP("SAT_S.W w%d, w%d, %d", wd, ws, m);
14313 t1 = newTemp(Ity_V128);
14314 assign(t1, binop(Iop_SarN32x4, getWReg(ws), mkU8(31)));
14316 if (m == 0) {
14317 putWReg(wd, mkexpr(t1));
14318 } else {
14319 t2 = newTemp(Ity_V128);
14320 assign(t2,
14321 binop(Iop_SarN32x4,
14322 getWReg(ws),
14323 mkU8(m)));
14324 putWReg(wd,
14325 binop(Iop_OrV128,
14326 binop(Iop_OrV128,
14327 binop(Iop_AndV128,
14328 binop(Iop_CmpEQ32x4,
14329 mkexpr(t1),
14330 mkexpr(t2)),
14331 getWReg(ws)),
14332 binop(Iop_ShlN32x4,
14333 binop(Iop_CmpGT32Sx4,
14334 mkexpr(t1),
14335 mkexpr(t2)),
14336 mkU8(m))),
14337 binop(Iop_ShrN32x4,
14338 binop(Iop_CmpGT32Sx4,
14339 mkexpr(t2),
14340 mkexpr(t1)),
14341 mkU8(32 - m))));
14344 break;
14347 case 0x03: { /* SAT_S.D */
14348 DIP("SAT_S.D w%d, w%d, %d", wd, ws, m);
14349 t1 = newTemp(Ity_V128);
14350 assign(t1, binop(Iop_SarN64x2, getWReg(ws), mkU8(63)));
14352 if (m == 0) {
14353 putWReg(wd, mkexpr(t1));
14354 } else {
14355 t2 = newTemp(Ity_V128);
14356 assign(t2,
14357 binop(Iop_SarN64x2,
14358 getWReg(ws),
14359 mkU8(m)));
14360 putWReg(wd,
14361 binop(Iop_OrV128,
14362 binop(Iop_OrV128,
14363 binop(Iop_AndV128,
14364 binop(Iop_CmpEQ64x2,
14365 mkexpr(t1),
14366 mkexpr(t2)),
14367 getWReg(ws)),
14368 binop(Iop_ShlN64x2,
14369 binop(Iop_CmpGT64Sx2,
14370 mkexpr(t1),
14371 mkexpr(t2)),
14372 mkU8(m))),
14373 binop(Iop_ShrN64x2,
14374 binop(Iop_CmpGT64Sx2,
14375 mkexpr(t2),
14376 mkexpr(t1)),
14377 mkU8(64 - m))));
14380 break;
14384 break;
14387 case 0x01: { /* SAT_U.df */
14388 switch (df) {
14389 case 0x00: { /* SAT_U.B */
14390 DIP("SAT_U.B w%d, w%d, %d", wd, ws, m);
14392 if (m == 7) {
14393 putWReg(wd, getWReg(ws));
14394 } else {
14395 t1 = newTemp(Ity_V128);
14396 assign(t1,
14397 binop(Iop_CmpEQ8x16,
14398 binop(Iop_ShrN8x16,
14399 getWReg(ws),
14400 mkU8(m + 1)),
14401 binop(Iop_64HLtoV128,
14402 mkU64(0), mkU64(0))));
14403 putWReg(wd,
14404 binop(Iop_OrV128,
14405 binop(Iop_AndV128,
14406 mkexpr(t1),
14407 getWReg(ws)),
14408 binop(Iop_ShrN8x16,
14409 unop(Iop_NotV128,
14410 mkexpr(t1)),
14411 mkU8(7 - m))));
14414 break;
14417 case 0x01: { /* SAT_U.H */
14418 DIP("SAT_U.H w%d, w%d, %d", wd, ws, m);
14420 if (m == 15) {
14421 putWReg(wd, getWReg(ws));
14422 } else {
14423 t1 = newTemp(Ity_V128);
14424 assign(t1,
14425 binop(Iop_CmpEQ16x8,
14426 binop(Iop_ShrN16x8,
14427 getWReg(ws),
14428 mkU8(m + 1)),
14429 binop(Iop_64HLtoV128,
14430 mkU64(0), mkU64(0))));
14431 putWReg(wd,
14432 binop(Iop_OrV128,
14433 binop(Iop_AndV128,
14434 mkexpr(t1),
14435 getWReg(ws)),
14436 binop(Iop_ShrN16x8,
14437 unop(Iop_NotV128,
14438 mkexpr(t1)),
14439 mkU8(15 - m))));
14442 break;
14445 case 0x02: { /* SAT_U.W */
14446 DIP("SAT_U.W w%d, w%d, %d", wd, ws, m);
14448 if (m == 31) {
14449 putWReg(wd, getWReg(ws));
14450 } else {
14451 t1 = newTemp(Ity_V128);
14452 assign(t1,
14453 binop(Iop_CmpEQ32x4,
14454 binop(Iop_ShrN32x4,
14455 getWReg(ws),
14456 mkU8(m + 1)),
14457 binop(Iop_64HLtoV128,
14458 mkU64(0), mkU64(0))));
14459 putWReg(wd,
14460 binop(Iop_OrV128,
14461 binop(Iop_AndV128,
14462 mkexpr(t1), \
14463 getWReg(ws)),
14464 binop(Iop_ShrN32x4,
14465 unop(Iop_NotV128,
14466 mkexpr(t1)),
14467 mkU8(31 - m))));
14470 break;
14473 case 0x03: { /* SAT_U.D */
14474 DIP("SAT_U.D w%d, w%d, %d", wd, ws, m);
14476 if (m == 63) {
14477 putWReg(wd, getWReg(ws));
14478 } else {
14479 t1 = newTemp(Ity_V128);
14480 assign(t1,
14481 binop(Iop_CmpEQ64x2,
14482 binop(Iop_ShrN64x2,
14483 getWReg(ws),
14484 mkU8(m + 1)),
14485 binop(Iop_64HLtoV128,
14486 mkU64(0), mkU64(0))));
14487 putWReg(wd,
14488 binop(Iop_OrV128,
14489 binop(Iop_AndV128,
14490 mkexpr(t1),
14491 getWReg(ws)),
14492 binop(Iop_ShrN64x2,
14493 unop(Iop_NotV128,
14494 mkexpr(t1)),
14495 mkU8(63 - m))));
14498 break;
14502 break;
14505 case 0x02: { /* SRARI.df */
14506 switch (df) {
14507 case 0x00: { /* SRARI.B */
14508 DIP("SRARI.B w%d, w%d, %d", wd, ws, m);
14509 t1 = newTemp(Ity_V128);
14510 t2 = newTemp(Ity_V128);
14511 assign(t1,
14512 binop(Iop_SarN8x16,
14513 getWReg(ws),
14514 mkU8(m)));
14515 assign(t2,
14516 binop(Iop_ShrN8x16,
14517 binop(Iop_ShlN8x16,
14518 getWReg(ws),
14519 mkU8(8 - m)),
14520 mkU8(7)));
14522 if (m) putWReg(wd, binop(Iop_Add8x16,
14523 mkexpr(t1),
14524 mkexpr(t2)));
14525 else putWReg(wd, mkexpr(t1));
14527 break;
14530 case 0x01: { /* SRARI.H */
14531 DIP("SRARI.H w%d, w%d, %d", wd, ws, m);
14532 t1 = newTemp(Ity_V128);
14533 t2 = newTemp(Ity_V128);
14534 assign(t1,
14535 binop(Iop_SarN16x8,
14536 getWReg(ws),
14537 mkU8(m)));
14538 assign(t2,
14539 binop(Iop_ShrN16x8,
14540 binop(Iop_ShlN16x8,
14541 getWReg(ws),
14542 mkU8(16 - m)),
14543 mkU8(15)));
14545 if (m)
14546 putWReg(wd,
14547 binop(Iop_Add16x8,
14548 mkexpr(t1), mkexpr(t2)));
14549 else putWReg(wd, mkexpr(t1));
14551 break;
14554 case 0x02: { /* SRARI.W */
14555 DIP("SRARI.W w%d, w%d, %d", wd, ws, m);
14556 t1 = newTemp(Ity_V128);
14557 t2 = newTemp(Ity_V128);
14558 assign(t1,
14559 binop(Iop_SarN32x4,
14560 getWReg(ws),
14561 mkU8(m)));
14562 assign(t2,
14563 binop(Iop_ShrN32x4,
14564 binop(Iop_ShlN32x4,
14565 getWReg(ws),
14566 mkU8(32 - m)),
14567 mkU8(31)));
14569 if (m)
14570 putWReg(wd,
14571 binop(Iop_Add32x4,
14572 mkexpr(t1), mkexpr(t2)));
14573 else putWReg(wd, mkexpr(t1));
14575 break;
14578 case 0x03: { /* SRARI.D */
14579 DIP("SRARI.D w%d, w%d, %d", wd, ws, m);
14580 t1 = newTemp(Ity_V128);
14581 t2 = newTemp(Ity_V128);
14582 assign(t1,
14583 binop(Iop_SarN64x2,
14584 getWReg(ws),
14585 mkU8(m)));
14586 assign(t2,
14587 binop(Iop_ShrN64x2,
14588 binop(Iop_ShlN64x2,
14589 getWReg(ws),
14590 mkU8(64 - m)),
14591 mkU8(63)));
14593 if (m)
14594 putWReg(wd,
14595 binop(Iop_Add64x2,
14596 mkexpr(t1), mkexpr(t2)));
14597 else putWReg(wd, mkexpr(t1));
14599 break;
14603 break;
14606 case 0x03: { /* SRLRI.df */
14607 switch (df) {
14608 case 0x00: { /* SRLRI.B */
14609 DIP("SRLRI.B w%d, w%d, %d", wd, ws, m);
14610 t1 = newTemp(Ity_V128);
14611 t2 = newTemp(Ity_V128);
14612 assign(t1,
14613 binop(Iop_ShrN8x16,
14614 getWReg(ws),
14615 mkU8(m)));
14616 assign(t2,
14617 binop(Iop_ShrN8x16,
14618 binop(Iop_ShlN8x16,
14619 getWReg(ws),
14620 mkU8(8 - m)),
14621 mkU8(7)));
14623 if (m)
14624 putWReg(wd,
14625 binop(Iop_Add8x16,
14626 mkexpr(t1), mkexpr(t2)));
14627 else putWReg(wd, mkexpr(t1));
14629 break;
14632 case 0x01: { /* SRLRI.H */
14633 DIP("SRLRI.H w%d, w%d, %d", wd, ws, m);
14634 t1 = newTemp(Ity_V128);
14635 t2 = newTemp(Ity_V128);
14636 assign(t1,
14637 binop(Iop_ShrN16x8,
14638 getWReg(ws),
14639 mkU8(m)));
14640 assign(t2,
14641 binop(Iop_ShrN16x8,
14642 binop(Iop_ShlN16x8,
14643 getWReg(ws),
14644 mkU8(16 - m)),
14645 mkU8(15)));
14647 if (m)
14648 putWReg(wd,
14649 binop(Iop_Add16x8,
14650 mkexpr(t1), mkexpr(t2)));
14651 else putWReg(wd, mkexpr(t1));
14653 break;
14656 case 0x02: { /* SRLRI.W */
14657 DIP("SRLRI.W w%d, w%d, %d", wd, ws, m);
14658 t1 = newTemp(Ity_V128);
14659 t2 = newTemp(Ity_V128);
14660 assign(t1,
14661 binop(Iop_ShrN32x4,
14662 getWReg(ws),
14663 mkU8(m)));
14664 assign(t2,
14665 binop(Iop_ShrN32x4,
14666 binop(Iop_ShlN32x4,
14667 getWReg(ws),
14668 mkU8(32 - m)),
14669 mkU8(31)));
14671 if (m)
14672 putWReg(wd,
14673 binop(Iop_Add32x4,
14674 mkexpr(t1), mkexpr(t2)));
14675 else putWReg(wd, mkexpr(t1));
14677 break;
14680 case 0x03: { /* SRLRI.D */
14681 DIP("SRLRI.D w%d, w%d, %d", wd, ws, m);
14682 t1 = newTemp(Ity_V128);
14683 t2 = newTemp(Ity_V128);
14684 assign(t1,
14685 binop(Iop_ShrN64x2,
14686 getWReg(ws),
14687 mkU8(m)));
14688 assign(t2,
14689 binop(Iop_ShrN64x2,
14690 binop(Iop_ShlN64x2,
14691 getWReg(ws),
14692 mkU8(64 - m)),
14693 mkU8(63)));
14695 if (m)
14696 putWReg(wd,
14697 binop(Iop_Add64x2,
14698 mkexpr(t1), mkexpr(t2)));
14699 else putWReg(wd, mkexpr(t1));
14701 break;
14705 break;
14708 default:
14709 return -1;
14712 return 0;
14715 static Int msa_3R_0D(UInt cins, UChar wd, UChar ws) { /* 3R (0x0D) */
14716 IRTemp t1, t2, t3;
14717 UShort operation;
14718 UChar df, wt;
14720 operation = (cins & 0x03800000) >> 23;
14721 df = (cins & 0x00600000) >> 21;
14722 wt = (cins & 0x001F0000) >> 16;
14724 switch (operation) {
14725 case 0x00: { /* SLL.df */
14726 switch (df) {
14727 case 0x00: { /* SLL.B */
14728 DIP("SLL.B w%d, w%d, w%d", wd, ws, wt);
14729 t1 = newTemp(Ity_V128);
14730 t2 = newTemp(Ity_V128);
14731 t3 = newTemp(Ity_V128);
14732 assign(t1, getWReg(ws));
14733 assign(t2, getWReg(wt));
14734 assign(t3, binop(Iop_Shl8x16, mkexpr(t1), mkexpr(t2)));
14735 putWReg(wd, mkexpr(t3));
14736 break;
14739 case 0x01: { /* SLL.H */
14740 DIP("SLL.H w%d, w%d, w%d", wd, ws, wt);
14741 t1 = newTemp(Ity_V128);
14742 t2 = newTemp(Ity_V128);
14743 t3 = newTemp(Ity_V128);
14744 assign(t1, getWReg(ws));
14745 assign(t2, getWReg(wt));
14746 assign(t3, binop(Iop_Shl16x8, mkexpr(t1), mkexpr(t2)));
14747 putWReg(wd, mkexpr(t3));
14748 break;
14751 case 0x02: { /* SLL.W */
14752 DIP("SLL.W w%d, w%d, w%d", wd, ws, wt);
14753 t1 = newTemp(Ity_V128);
14754 t2 = newTemp(Ity_V128);
14755 t3 = newTemp(Ity_V128);
14756 assign(t1, getWReg(ws));
14757 assign(t2, getWReg(wt));
14758 assign(t3, binop(Iop_Shl32x4, mkexpr(t1), mkexpr(t2)));
14759 putWReg(wd, mkexpr(t3));
14760 break;
14763 case 0x03: { /* SLL.D */
14764 DIP("SLL.D w%d, w%d, w%d", wd, ws, wt);
14765 t1 = newTemp(Ity_V128);
14766 t2 = newTemp(Ity_V128);
14767 t3 = newTemp(Ity_V128);
14768 assign(t1, getWReg(ws));
14769 assign(t2, getWReg(wt));
14770 assign(t3, binop(Iop_Shl64x2, mkexpr(t1), mkexpr(t2)));
14771 putWReg(wd, mkexpr(t3));
14772 break;
14775 default:
14776 return -1;
14779 break;
14782 case 0x01: { /* SRA.df */
14783 switch (df) {
14784 case 0x00: { /* SRA.B */
14785 DIP("SRA.B w%d, w%d, w%d", wd, ws, wt);
14786 t1 = newTemp(Ity_V128);
14787 t2 = newTemp(Ity_V128);
14788 t3 = newTemp(Ity_V128);
14789 assign(t1, getWReg(ws));
14790 assign(t2, getWReg(wt));
14791 assign(t3, binop(Iop_Sar8x16, mkexpr(t1), mkexpr(t2)));
14792 putWReg(wd, mkexpr(t3));
14793 break;
14796 case 0x01: { /* SRA.H */
14797 DIP("SRA.H w%d, w%d, w%d", wd, ws, wt);
14798 t1 = newTemp(Ity_V128);
14799 t2 = newTemp(Ity_V128);
14800 t3 = newTemp(Ity_V128);
14801 assign(t1, getWReg(ws));
14802 assign(t2, getWReg(wt));
14803 assign(t3, binop(Iop_Sar16x8, mkexpr(t1), mkexpr(t2)));
14804 putWReg(wd, mkexpr(t3));
14805 break;
14808 case 0x02: { /* SRA.W */
14809 DIP("SRA.W w%d, w%d, w%d", wd, ws, wt);
14810 t1 = newTemp(Ity_V128);
14811 t2 = newTemp(Ity_V128);
14812 t3 = newTemp(Ity_V128);
14813 assign(t1, getWReg(ws));
14814 assign(t2, getWReg(wt));
14815 assign(t3, binop(Iop_Sar32x4, mkexpr(t1), mkexpr(t2)));
14816 putWReg(wd, mkexpr(t3));
14817 break;
14820 case 0x03: { /* SRA.D */
14821 DIP("SRA.D w%d, w%d, w%d", wd, ws, wt);
14822 t1 = newTemp(Ity_V128);
14823 t2 = newTemp(Ity_V128);
14824 t3 = newTemp(Ity_V128);
14825 assign(t1, getWReg(ws));
14826 assign(t2, getWReg(wt));
14827 assign(t3, binop(Iop_Sar64x2, mkexpr(t1), mkexpr(t2)));
14828 putWReg(wd, mkexpr(t3));
14829 break;
14832 default:
14833 return -1;
14836 break;
14839 case 0x02: { /* SRL.df */
14840 switch (df) {
14841 case 0x00: { /* SRL.B */
14842 DIP("SRL.B w%d, w%d, w%d", wd, ws, wt);
14843 t1 = newTemp(Ity_V128);
14844 t2 = newTemp(Ity_V128);
14845 t3 = newTemp(Ity_V128);
14846 assign(t1, getWReg(ws));
14847 assign(t2, getWReg(wt));
14848 assign(t3, binop(Iop_Shr8x16, mkexpr(t1), mkexpr(t2)));
14849 putWReg(wd, mkexpr(t3));
14850 break;
14853 case 0x01: { /* SRL.H */
14854 DIP("SRL.H w%d, w%d, w%d", wd, ws, wt);
14855 t1 = newTemp(Ity_V128);
14856 t2 = newTemp(Ity_V128);
14857 t3 = newTemp(Ity_V128);
14858 assign(t1, getWReg(ws));
14859 assign(t2, getWReg(wt));
14860 assign(t3, binop(Iop_Shr16x8, mkexpr(t1), mkexpr(t2)));
14861 putWReg(wd, mkexpr(t3));
14862 break;
14865 case 0x02: { /* SRL.W */
14866 DIP("SRL.W w%d, w%d, w%d", wd, ws, wt);
14867 t1 = newTemp(Ity_V128);
14868 t2 = newTemp(Ity_V128);
14869 t3 = newTemp(Ity_V128);
14870 assign(t1, getWReg(ws));
14871 assign(t2, getWReg(wt));
14872 assign(t3, binop(Iop_Shr32x4, mkexpr(t1), mkexpr(t2)));
14873 putWReg(wd, mkexpr(t3));
14874 break;
14877 case 0x03: { /* SRL.D */
14878 DIP("SRL.D w%d, w%d, w%d", wd, ws, wt);
14879 t1 = newTemp(Ity_V128);
14880 t2 = newTemp(Ity_V128);
14881 t3 = newTemp(Ity_V128);
14882 assign(t1, getWReg(ws));
14883 assign(t2, getWReg(wt));
14884 assign(t3, binop(Iop_Shr64x2, mkexpr(t1), mkexpr(t2)));
14885 putWReg(wd, mkexpr(t3));
14886 break;
14889 default:
14890 return -1;
14893 break;
14896 case 0x03: { /* BCLR.df */
14897 t1 = newTemp(Ity_V128);
14898 t2 = newTemp(Ity_V128);
14899 t3 = newTemp(Ity_V128);
14900 ULong tmp = 1;
14901 assign(t1, getWReg(ws));
14903 switch (df) {
14904 case 0x00: { /* BCLR.B */
14905 DIP("BCLR.B w%d, w%d, w%d", wd, ws, wt);
14906 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
14907 (tmp << 32) | (tmp << 24) | (tmp << 16) |
14908 (tmp << 8);
14909 assign(t2, binop(Iop_Shl8x16,
14910 binop(Iop_64HLtoV128,
14911 mkU64(tmp), mkU64(tmp)),
14912 getWReg(wt)));
14913 break;
14916 case 0x01: { /* BCLR.H */
14917 DIP("BCLR.H w%d, w%d, w%d", wd, ws, wt);
14918 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
14919 assign(t2,
14920 binop(Iop_Shl16x8,
14921 binop(Iop_64HLtoV128,
14922 mkU64(tmp), mkU64(tmp)),
14923 getWReg(wt)));
14924 break;
14927 case 0x02: { /* BCLR.W */
14928 DIP("BCLR.W w%d, w%d, w%d", wd, ws, wt);
14929 tmp |= (tmp << 32);
14930 assign(t2,
14931 binop(Iop_Shl32x4,
14932 binop(Iop_64HLtoV128,
14933 mkU64(tmp), mkU64(tmp)),
14934 getWReg(wt)));
14935 break;
14938 case 0x03: { /* BCLR.D */
14939 DIP("BCLR.D w%d, w%d, w%d", wd, ws, wt);
14940 assign(t2,
14941 binop(Iop_Shl64x2,
14942 binop(Iop_64HLtoV128,
14943 mkU64(tmp), mkU64(tmp)),
14944 getWReg(wt)));
14945 break;
14949 assign(t3,
14950 binop(Iop_AndV128,
14951 mkexpr(t1), unop(Iop_NotV128, mkexpr(t2))));
14952 putWReg(wd, mkexpr(t3));
14953 break;
14956 case 0x04: { /* BSET.df */
14957 t1 = newTemp(Ity_V128);
14958 t2 = newTemp(Ity_V128);
14959 t3 = newTemp(Ity_V128);
14960 ULong tmp = 1;
14961 assign(t1, getWReg(ws));
14963 switch (df) {
14964 case 0x00: { /* BSET.B */
14965 DIP("BSET.B w%d, w%d, w%d", wd, ws, wt);
14966 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
14967 (tmp << 32) | (tmp << 24) | (tmp << 16) |
14968 (tmp << 8);
14969 assign(t2,
14970 binop(Iop_Shl8x16,
14971 binop(Iop_64HLtoV128,
14972 mkU64(tmp), mkU64(tmp)),
14973 getWReg(wt)));
14974 break;
14977 case 0x01: { /* BSET.H */
14978 DIP("BSET.H w%d, w%d, w%d", wd, ws, wt);
14979 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
14980 assign(t2,
14981 binop(Iop_Shl16x8,
14982 binop(Iop_64HLtoV128,
14983 mkU64(tmp), mkU64(tmp)),
14984 getWReg(wt)));
14985 break;
14988 case 0x02: { /* BSET.W */
14989 DIP("BSET.W w%d, w%d, w%d", wd, ws, wt);
14990 tmp |= (tmp << 32);
14991 assign(t2,
14992 binop(Iop_Shl32x4,
14993 binop(Iop_64HLtoV128,
14994 mkU64(tmp), mkU64(tmp)),
14995 getWReg(wt)));
14996 break;
14999 case 0x03: { /* BSET.D */
15000 DIP("BSET.D w%d, w%d, w%d", wd, ws, wt);
15001 assign(t2,
15002 binop(Iop_Shl64x2,
15003 binop(Iop_64HLtoV128,
15004 mkU64(tmp), mkU64(tmp)),
15005 getWReg(wt)));
15006 break;
15010 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
15011 putWReg(wd, mkexpr(t3));
15012 break;
15015 case 0x05: { /* BNEG.df */
15016 t1 = newTemp(Ity_V128);
15017 t2 = newTemp(Ity_V128);
15018 t3 = newTemp(Ity_V128);
15019 ULong tmp = 1;
15020 assign(t1, getWReg(ws));
15022 switch (df) {
15023 case 0x00: { /* BNEG.B */
15024 DIP("BNEG.B w%d, w%d, w%d", wd, ws, wt);
15025 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
15026 (tmp << 32) | (tmp << 24) | (tmp << 16) |
15027 (tmp << 8);
15028 assign(t2,
15029 binop(Iop_Shl8x16,
15030 binop(Iop_64HLtoV128,
15031 mkU64(tmp), mkU64(tmp)),
15032 getWReg(wt)));
15033 break;
15036 case 0x01: { /* BNEG.H */
15037 DIP("BNEG.H w%d, w%d, w%d", wd, ws, wt);
15038 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
15039 assign(t2,
15040 binop(Iop_Shl16x8,
15041 binop(Iop_64HLtoV128,
15042 mkU64(tmp), mkU64(tmp)),
15043 getWReg(wt)));
15044 break;
15047 case 0x02: { /* BNEG.W */
15048 DIP("BNEG.W w%d, w%d, w%d", wd, ws, wt);
15049 tmp |= (tmp << 32);
15050 assign(t2,
15051 binop(Iop_Shl32x4,
15052 binop(Iop_64HLtoV128,
15053 mkU64(tmp), mkU64(tmp)),
15054 getWReg(wt)));
15055 break;
15058 case 0x03: { /* BNEG.D */
15059 DIP("BNEG.D w%d, w%d, w%d", wd, ws, wt);
15060 assign(t2,
15061 binop(Iop_Shl64x2,
15062 binop(Iop_64HLtoV128,
15063 mkU64(tmp), mkU64(tmp)),
15064 getWReg(wt)));
15065 break;
15069 assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
15070 putWReg(wd, mkexpr(t3));
15071 break;
15074 case 0x06: { /* BINSL.df */
15075 switch (df) {
15076 case 0x00: { /* BINSL.B */
15077 DIP("BINSL.B w%d, w%d, w%d", wd, ws, wt);
15078 t1 = newTemp(Ity_V128);
15079 t2 = newTemp(Ity_V128);
15080 t3 = newTemp(Ity_V128);
15081 ULong tmp = 0x8080808080808080ULL;
15082 assign(t1,
15083 binop(Iop_Sar8x16,
15084 binop(Iop_64HLtoV128,
15085 mkU64(tmp), mkU64(tmp)),
15086 getWReg(wt)));
15087 assign(t2,
15088 binop(Iop_AndV128,
15089 unop(Iop_NotV128, mkexpr(t1)),
15090 getWReg(wd)));
15091 assign(t3,
15092 binop(Iop_AndV128,
15093 mkexpr(t1), getWReg(ws)));
15094 putWReg(wd,
15095 binop(Iop_OrV128,
15096 mkexpr(t2), mkexpr(t3)));
15097 break;
15100 case 0x01: { /* BINSL.H */
15101 DIP("BINSL.H w%d, w%d, w%d", wd, ws, wt);
15102 t1 = newTemp(Ity_V128);
15103 t2 = newTemp(Ity_V128);
15104 t3 = newTemp(Ity_V128);
15105 ULong tmp = 0x8000800080008000ULL;
15106 assign(t1,
15107 binop(Iop_Sar16x8,
15108 binop(Iop_64HLtoV128,
15109 mkU64(tmp), mkU64(tmp)),
15110 getWReg(wt)));
15111 assign(t2,
15112 binop(Iop_AndV128,
15113 unop(Iop_NotV128, mkexpr(t1)),
15114 getWReg(wd)));
15115 assign(t3,
15116 binop(Iop_AndV128,
15117 mkexpr(t1), getWReg(ws)));
15118 putWReg(wd,
15119 binop(Iop_OrV128,
15120 mkexpr(t2), mkexpr(t3)));
15121 break;
15124 case 0x02: { /* BINSL.W */
15125 DIP("BINSL.W w%d, w%d, w%d", wd, ws, wt);
15126 t1 = newTemp(Ity_V128);
15127 t2 = newTemp(Ity_V128);
15128 t3 = newTemp(Ity_V128);
15129 ULong tmp = 0x8000000080000000ULL;
15130 assign(t1,
15131 binop(Iop_Sar32x4,
15132 binop(Iop_64HLtoV128,
15133 mkU64(tmp), mkU64(tmp)),
15134 getWReg(wt)));
15135 assign(t2,
15136 binop(Iop_AndV128,
15137 unop(Iop_NotV128, mkexpr(t1)),
15138 getWReg(wd)));
15139 assign(t3,
15140 binop(Iop_AndV128,
15141 mkexpr(t1), getWReg(ws)));
15142 putWReg(wd,
15143 binop(Iop_OrV128,
15144 mkexpr(t2), mkexpr(t3)));
15145 break;
15148 case 0x03: { /* BINSL.D */
15149 DIP("BINSL.D w%d, w%d, w%d", wd, ws, wt);
15150 t1 = newTemp(Ity_V128);
15151 t2 = newTemp(Ity_V128);
15152 t3 = newTemp(Ity_V128);
15153 ULong tmp = 0x8000000000000000ULL;
15154 assign(t1,
15155 binop(Iop_Sar64x2,
15156 binop(Iop_64HLtoV128,
15157 mkU64(tmp), mkU64(tmp)),
15158 getWReg(wt)));
15159 assign(t2,
15160 binop(Iop_AndV128,
15161 unop(Iop_NotV128, mkexpr(t1)),
15162 getWReg(wd)));
15163 assign(t3,
15164 binop(Iop_AndV128,
15165 mkexpr(t1), getWReg(ws)));
15166 putWReg(wd,
15167 binop(Iop_OrV128,
15168 mkexpr(t2), mkexpr(t3)));
15169 break;
15172 default:
15173 return -1;
15176 break;
15179 case 0x07: { /* BINSR.df */
15180 switch (df) {
15181 case 0x00: { /* BINSR.B */
15182 DIP("BINSR.B w%d, w%d, w%d", wd, ws, wt);
15183 t1 = newTemp(Ity_V128);
15184 t2 = newTemp(Ity_V128);
15185 t3 = newTemp(Ity_V128);
15186 ULong tmp = 0xFEFEFEFEFEFEFEFEULL;
15187 assign(t1,
15188 binop(Iop_Shl8x16,
15189 binop(Iop_64HLtoV128,
15190 mkU64(tmp), mkU64(tmp)),
15191 getWReg(wt)));
15192 assign(t2,
15193 binop(Iop_AndV128,
15194 unop(Iop_NotV128, mkexpr(t1)),
15195 getWReg(ws)));
15196 assign(t3,
15197 binop(Iop_AndV128,
15198 mkexpr(t1), getWReg(wd)));
15199 putWReg(wd,
15200 binop(Iop_OrV128,
15201 mkexpr(t2), mkexpr(t3)));
15202 break;
15205 case 0x01: { /* BINSR.H */
15206 DIP("BINSR.H w%d, w%d, w%d", wd, ws, wt);
15207 t1 = newTemp(Ity_V128);
15208 t2 = newTemp(Ity_V128);
15209 t3 = newTemp(Ity_V128);
15210 ULong tmp = 0xFFFEFFFEFFFEFFFEULL;
15211 assign(t1,
15212 binop(Iop_Shl16x8,
15213 binop(Iop_64HLtoV128,
15214 mkU64(tmp), mkU64(tmp)),
15215 getWReg(wt)));
15216 assign(t2,
15217 binop(Iop_AndV128,
15218 unop(Iop_NotV128, mkexpr(t1)),
15219 getWReg(ws)));
15220 assign(t3,
15221 binop(Iop_AndV128,
15222 mkexpr(t1), getWReg(wd)));
15223 putWReg(wd,
15224 binop(Iop_OrV128,
15225 mkexpr(t2), mkexpr(t3)));
15226 break;
15229 case 0x02: { /* BINSR.W */
15230 DIP("BINSR.W w%d, w%d, w%d", wd, ws, wt);
15231 t1 = newTemp(Ity_V128);
15232 t2 = newTemp(Ity_V128);
15233 t3 = newTemp(Ity_V128);
15234 ULong tmp = 0xFFFFFFFEFFFFFFFEULL;
15235 assign(t1,
15236 binop(Iop_Shl32x4,
15237 binop(Iop_64HLtoV128,
15238 mkU64(tmp), mkU64(tmp)),
15239 getWReg(wt)));
15240 assign(t2,
15241 binop(Iop_AndV128,
15242 unop(Iop_NotV128, mkexpr(t1)),
15243 getWReg(ws)));
15244 assign(t3,
15245 binop(Iop_AndV128,
15246 mkexpr(t1), getWReg(wd)));
15247 putWReg(wd,
15248 binop(Iop_OrV128,
15249 mkexpr(t2), mkexpr(t3)));
15250 break;
15253 case 0x03: { /* BINSR.D */
15254 DIP("BINSR.D w%d, w%d, w%d", wd, ws, wt);
15255 t1 = newTemp(Ity_V128);
15256 t2 = newTemp(Ity_V128);
15257 t3 = newTemp(Ity_V128);
15258 ULong tmp = -2;
15259 assign(t1,
15260 binop(Iop_Shl64x2,
15261 binop(Iop_64HLtoV128,
15262 mkU64(tmp), mkU64(tmp)),
15263 getWReg(wt)));
15264 assign(t2,
15265 binop(Iop_AndV128,
15266 unop(Iop_NotV128, mkexpr(t1)),
15267 getWReg(ws)));
15268 assign(t3,
15269 binop(Iop_AndV128,
15270 mkexpr(t1), getWReg(wd)));
15271 putWReg(wd,
15272 binop(Iop_OrV128,
15273 mkexpr(t2), mkexpr(t3)));
15274 break;
15277 default:
15278 return -1;
15281 break;
15284 default:
15285 return -1;
15288 return 0;
15291 static Int msa_3R_0E(UInt cins, UChar wd, UChar ws) { /* 3R (0x0E) */
15292 IRTemp t1, t2, t3, t4;
15293 UShort operation;
15294 UChar df, wt;
15296 operation = (cins & 0x03800000) >> 23;
15297 df = (cins & 0x00600000) >> 21;
15298 wt = (cins & 0x001F0000) >> 16;
15300 switch (operation) {
15301 case 0x00: { /* ADDV.df */
15302 switch (df) {
15303 case 0x00: { /* ADDV.B */
15304 DIP("ADDV.B w%d, w%d, w%d", wd, ws, wt);
15305 t1 = newTemp(Ity_V128);
15306 t2 = newTemp(Ity_V128);
15307 t3 = newTemp(Ity_V128);
15308 assign(t1, getWReg(ws));
15309 assign(t2, getWReg(wt));
15310 assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
15311 putWReg(wd, mkexpr(t3));
15312 break;
15315 case 0x01: { /* ADDV.H */
15316 DIP("ADDV.H w%d, w%d, w%d", wd, ws, wt);
15317 t1 = newTemp(Ity_V128);
15318 t2 = newTemp(Ity_V128);
15319 t3 = newTemp(Ity_V128);
15320 assign(t1, getWReg(ws));
15321 assign(t2, getWReg(wt));
15322 assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
15323 putWReg(wd, mkexpr(t3));
15324 break;
15327 case 0x02: { /* ADDV.W */
15328 DIP("ADDV.W w%d, w%d, w%d", wd, ws, wt);
15329 t1 = newTemp(Ity_V128);
15330 t2 = newTemp(Ity_V128);
15331 t3 = newTemp(Ity_V128);
15332 assign(t1, getWReg(ws));
15333 assign(t2, getWReg(wt));
15334 assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
15335 putWReg(wd, mkexpr(t3));
15336 break;
15339 case 0x03: { /* ADDV.D */
15340 DIP("ADDV.D w%d, w%d, w%d", wd, ws, wt);
15341 t1 = newTemp(Ity_V128);
15342 t2 = newTemp(Ity_V128);
15343 t3 = newTemp(Ity_V128);
15344 assign(t1, getWReg(ws));
15345 assign(t2, getWReg(wt));
15346 assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
15347 putWReg(wd, mkexpr(t3));
15348 break;
15351 default:
15352 return -1;
15355 break;
15358 case 0x01: { /* SUBV.df */
15359 switch (df) {
15360 case 0x00: { /* SUBV.B */
15361 DIP("SUBV.B w%d, w%d, w%d", wd, ws, wt);
15362 t1 = newTemp(Ity_V128);
15363 t2 = newTemp(Ity_V128);
15364 t3 = newTemp(Ity_V128);
15365 assign(t1, getWReg(ws));
15366 assign(t2, getWReg(wt));
15367 assign(t3, binop(Iop_Sub8x16, mkexpr(t1), mkexpr(t2)));
15368 putWReg(wd, mkexpr(t3));
15369 break;
15372 case 0x01: { /* SUBV.H */
15373 DIP("SUBV.H w%d, w%d, w%d", wd, ws, wt);
15374 t1 = newTemp(Ity_V128);
15375 t2 = newTemp(Ity_V128);
15376 t3 = newTemp(Ity_V128);
15377 assign(t1, getWReg(ws));
15378 assign(t2, getWReg(wt));
15379 assign(t3, binop(Iop_Sub16x8, mkexpr(t1), mkexpr(t2)));
15380 putWReg(wd, mkexpr(t3));
15381 break;
15384 case 0x02: { /* SUBV.W */
15385 DIP("SUBV.W w%d, w%d, w%d", wd, ws, wt);
15386 t1 = newTemp(Ity_V128);
15387 t2 = newTemp(Ity_V128);
15388 t3 = newTemp(Ity_V128);
15389 assign(t1, getWReg(ws));
15390 assign(t2, getWReg(wt));
15391 assign(t3, binop(Iop_Sub32x4, mkexpr(t1), mkexpr(t2)));
15392 putWReg(wd, mkexpr(t3));
15393 break;
15396 case 0x03: { /* SUBV.D */
15397 DIP("SUBV.D w%d, w%d, w%d", wd, ws, wt);
15398 t1 = newTemp(Ity_V128);
15399 t2 = newTemp(Ity_V128);
15400 t3 = newTemp(Ity_V128);
15401 assign(t1, getWReg(ws));
15402 assign(t2, getWReg(wt));
15403 assign(t3, binop(Iop_Sub64x2, mkexpr(t1), mkexpr(t2)));
15404 putWReg(wd, mkexpr(t3));
15405 break;
15408 default:
15409 return -1;
15412 break;
15415 case 0x02: { /* MAX_S.df */
15416 switch (df) {
15417 case 0x00: { /* MAX_S.B */
15418 DIP("MAX_S.B w%d, w%d, w%d", wd, ws, wt);
15419 t1 = newTemp(Ity_V128);
15420 t2 = newTemp(Ity_V128);
15421 t3 = newTemp(Ity_V128);
15422 assign(t1, getWReg(ws));
15423 assign(t2, getWReg(wt));
15424 assign(t3, binop(Iop_Max8Sx16, mkexpr(t1), mkexpr(t2)));
15425 putWReg(wd, mkexpr(t3));
15426 break;
15429 case 0x01: { /* MAX_S.H */
15430 DIP("MAX_S.H w%d, w%d, w%d", wd, ws, wt);
15431 t1 = newTemp(Ity_V128);
15432 t2 = newTemp(Ity_V128);
15433 t3 = newTemp(Ity_V128);
15434 assign(t1, getWReg(ws));
15435 assign(t2, getWReg(wt));
15436 assign(t3, binop(Iop_Max16Sx8, mkexpr(t1), mkexpr(t2)));
15437 putWReg(wd, mkexpr(t3));
15438 break;
15441 case 0x02: { /* MAX_S.W */
15442 DIP("MAX_S.W w%d, w%d, w%d", wd, ws, wt);
15443 t1 = newTemp(Ity_V128);
15444 t2 = newTemp(Ity_V128);
15445 t3 = newTemp(Ity_V128);
15446 assign(t1, getWReg(ws));
15447 assign(t2, getWReg(wt));
15448 assign(t3, binop(Iop_Max32Sx4, mkexpr(t1), mkexpr(t2)));
15449 putWReg(wd, mkexpr(t3));
15450 break;
15453 case 0x03: { /* MAX_S.D */
15454 DIP("MAX_S.D w%d, w%d, w%d", wd, ws, wt);
15455 t1 = newTemp(Ity_V128);
15456 t2 = newTemp(Ity_V128);
15457 t3 = newTemp(Ity_V128);
15458 assign(t1, getWReg(ws));
15459 assign(t2, getWReg(wt));
15460 assign(t3, binop(Iop_Max64Sx2, mkexpr(t1), mkexpr(t2)));
15461 putWReg(wd, mkexpr(t3));
15462 break;
15465 default:
15466 return -1;
15469 break;
15472 case 0x03: { /* MAX_U.df */
15473 switch (df) {
15474 case 0x00: { /* MAX_U.B */
15475 DIP("MAX_U.B w%d, w%d, w%d", wd, ws, wt);
15476 t1 = newTemp(Ity_V128);
15477 t2 = newTemp(Ity_V128);
15478 t3 = newTemp(Ity_V128);
15479 assign(t1, getWReg(ws));
15480 assign(t2, getWReg(wt));
15481 assign(t3, binop(Iop_Max8Ux16, mkexpr(t1), mkexpr(t2)));
15482 putWReg(wd, mkexpr(t3));
15483 break;
15486 case 0x01: { /* MAX_U.H */
15487 DIP("MAX_U.H w%d, w%d, w%d", wd, ws, wt);
15488 t1 = newTemp(Ity_V128);
15489 t2 = newTemp(Ity_V128);
15490 t3 = newTemp(Ity_V128);
15491 assign(t1, getWReg(ws));
15492 assign(t2, getWReg(wt));
15493 assign(t3, binop(Iop_Max16Ux8, mkexpr(t1), mkexpr(t2)));
15494 putWReg(wd, mkexpr(t3));
15495 break;
15498 case 0x02: { /* MAX_U.W */
15499 DIP("MAX_U.W w%d, w%d, w%d", wd, ws, wt);
15500 t1 = newTemp(Ity_V128);
15501 t2 = newTemp(Ity_V128);
15502 t3 = newTemp(Ity_V128);
15503 assign(t1, getWReg(ws));
15504 assign(t2, getWReg(wt));
15505 assign(t3, binop(Iop_Max32Ux4, mkexpr(t1), mkexpr(t2)));
15506 putWReg(wd, mkexpr(t3));
15507 break;
15510 case 0x03: { /* MAX_U.D */
15511 DIP("MAX_U.D w%d, w%d, w%d", wd, ws, wt);
15512 t1 = newTemp(Ity_V128);
15513 t2 = newTemp(Ity_V128);
15514 t3 = newTemp(Ity_V128);
15515 assign(t1, getWReg(ws));
15516 assign(t2, getWReg(wt));
15517 assign(t3, binop(Iop_Max64Ux2, mkexpr(t1), mkexpr(t2)));
15518 putWReg(wd, mkexpr(t3));
15519 break;
15522 default:
15523 return -1;
15526 break;
15529 case 0x04: { /* MIN_S.df */
15530 switch (df) {
15531 case 0x00: { /* MIN_S.B */
15532 DIP("MIN_S.B w%d, w%d, w%d", wd, ws, wt);
15533 t1 = newTemp(Ity_V128);
15534 t2 = newTemp(Ity_V128);
15535 t3 = newTemp(Ity_V128);
15536 assign(t1, getWReg(ws));
15537 assign(t2, getWReg(wt));
15538 assign(t3, binop(Iop_Min8Sx16, mkexpr(t1), mkexpr(t2)));
15539 putWReg(wd, mkexpr(t3));
15540 break;
15543 case 0x01: { /* MIN_S.H */
15544 DIP("MIN_S.H w%d, w%d, w%d", wd, ws, wt);
15545 t1 = newTemp(Ity_V128);
15546 t2 = newTemp(Ity_V128);
15547 t3 = newTemp(Ity_V128);
15548 assign(t1, getWReg(ws));
15549 assign(t2, getWReg(wt));
15550 assign(t3, binop(Iop_Min16Sx8, mkexpr(t1), mkexpr(t2)));
15551 putWReg(wd, mkexpr(t3));
15552 break;
15555 case 0x02: { /* MIN_S.W */
15556 DIP("MIN_S.W w%d, w%d, w%d", wd, ws, wt);
15557 t1 = newTemp(Ity_V128);
15558 t2 = newTemp(Ity_V128);
15559 t3 = newTemp(Ity_V128);
15560 assign(t1, getWReg(ws));
15561 assign(t2, getWReg(wt));
15562 assign(t3, binop(Iop_Min32Sx4, mkexpr(t1), mkexpr(t2)));
15563 putWReg(wd, mkexpr(t3));
15564 break;
15567 case 0x03: { /* MIN_S.D */
15568 DIP("MIN_S.D w%d, w%d, w%d", wd, ws, wt);
15569 t1 = newTemp(Ity_V128);
15570 t2 = newTemp(Ity_V128);
15571 t3 = newTemp(Ity_V128);
15572 assign(t1, getWReg(ws));
15573 assign(t2, getWReg(wt));
15574 assign(t3, binop(Iop_Min64Sx2, mkexpr(t1), mkexpr(t2)));
15575 putWReg(wd, mkexpr(t3));
15576 break;
15579 default:
15580 return -1;
15583 break;
15586 case 0x05: { /* MIN_U.df */
15587 switch (df) {
15588 case 0x00: { /* MIN_U.B */
15589 DIP("MIN_U.B w%d, w%d, w%d", wd, ws, wt);
15590 t1 = newTemp(Ity_V128);
15591 t2 = newTemp(Ity_V128);
15592 t3 = newTemp(Ity_V128);
15593 assign(t1, getWReg(ws));
15594 assign(t2, getWReg(wt));
15595 assign(t3, binop(Iop_Min8Ux16, mkexpr(t1), mkexpr(t2)));
15596 putWReg(wd, mkexpr(t3));
15597 break;
15600 case 0x01: { /* MIN_U.H */
15601 DIP("MIN_U.H w%d, w%d, w%d", wd, ws, wt);
15602 t1 = newTemp(Ity_V128);
15603 t2 = newTemp(Ity_V128);
15604 t3 = newTemp(Ity_V128);
15605 assign(t1, getWReg(ws));
15606 assign(t2, getWReg(wt));
15607 assign(t3, binop(Iop_Min16Ux8, mkexpr(t1), mkexpr(t2)));
15608 putWReg(wd, mkexpr(t3));
15609 break;
15612 case 0x02: { /* MIN_U.W */
15613 DIP("MIN_U.W w%d, w%d, w%d", wd, ws, wt);
15614 t1 = newTemp(Ity_V128);
15615 t2 = newTemp(Ity_V128);
15616 t3 = newTemp(Ity_V128);
15617 assign(t1, getWReg(ws));
15618 assign(t2, getWReg(wt));
15619 assign(t3, binop(Iop_Min32Ux4, mkexpr(t1), mkexpr(t2)));
15620 putWReg(wd, mkexpr(t3));
15621 break;
15624 case 0x03: { /* MIN_U.D */
15625 DIP("MIN_U.D w%d, w%d, w%d", wd, ws, wt);
15626 t1 = newTemp(Ity_V128);
15627 t2 = newTemp(Ity_V128);
15628 t3 = newTemp(Ity_V128);
15629 assign(t1, getWReg(ws));
15630 assign(t2, getWReg(wt));
15631 assign(t3, binop(Iop_Min64Ux2, mkexpr(t1), mkexpr(t2)));
15632 putWReg(wd, mkexpr(t3));
15633 break;
15636 default:
15637 return -1;
15640 break;
15643 case 0x06: { /* MAX_A.df */
15644 switch (df) {
15645 case 0x00: { /* MAX_A.B */
15646 DIP("MAX_A.B w%d, w%d, w%d", wd, ws, wt);
15647 t1 = newTemp(Ity_V128);
15648 t2 = newTemp(Ity_V128);
15649 t3 = newTemp(Ity_V128);
15650 t4 = newTemp(Ity_V128);
15651 assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
15652 assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
15653 assign(t4, binop(Iop_CmpGT8Ux16, mkexpr(t1), mkexpr(t2)));
15654 assign(t3, binop(Iop_OrV128,
15655 binop(Iop_AndV128,
15656 mkexpr(t4),
15657 getWReg(ws)),
15658 binop(Iop_AndV128,
15659 unop(Iop_NotV128, mkexpr(t4)),
15660 getWReg(wt))));
15661 putWReg(wd, mkexpr(t3));
15662 break;
15665 case 0x01: { /* MAX_A.H */
15666 DIP("MAX_A.H w%d, w%d, w%d", wd, ws, wt);
15667 t1 = newTemp(Ity_V128);
15668 t2 = newTemp(Ity_V128);
15669 t3 = newTemp(Ity_V128);
15670 t4 = newTemp(Ity_V128);
15671 assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
15672 assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
15673 assign(t4, binop(Iop_CmpGT16Ux8, mkexpr(t1), mkexpr(t2)));
15674 assign(t3, binop(Iop_OrV128,
15675 binop(Iop_AndV128,
15676 mkexpr(t4),
15677 getWReg(ws)),
15678 binop(Iop_AndV128,
15679 unop(Iop_NotV128, mkexpr(t4)),
15680 getWReg(wt))));
15681 putWReg(wd, mkexpr(t3));
15682 break;
15685 case 0x02: { /* MAX_A.W */
15686 DIP("MAX_A.W w%d, w%d, w%d", wd, ws, wt);
15687 t1 = newTemp(Ity_V128);
15688 t2 = newTemp(Ity_V128);
15689 t3 = newTemp(Ity_V128);
15690 t4 = newTemp(Ity_V128);
15691 assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
15692 assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
15693 assign(t4, binop(Iop_CmpGT32Ux4, mkexpr(t1), mkexpr(t2)));
15694 assign(t3, binop(Iop_OrV128,
15695 binop(Iop_AndV128,
15696 mkexpr(t4),
15697 getWReg(ws)),
15698 binop(Iop_AndV128,
15699 unop(Iop_NotV128, mkexpr(t4)),
15700 getWReg(wt))));
15701 putWReg(wd, mkexpr(t3));
15702 break;
15705 case 0x03: { /* MAX_A.D */
15706 DIP("MAX_A.D w%d, w%d, w%d", wd, ws, wt);
15707 t1 = newTemp(Ity_V128);
15708 t2 = newTemp(Ity_V128);
15709 t3 = newTemp(Ity_V128);
15710 t4 = newTemp(Ity_V128);
15711 assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
15712 assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
15713 assign(t4, binop(Iop_CmpGT64Ux2, mkexpr(t1), mkexpr(t2)));
15714 assign(t3, binop(Iop_OrV128,
15715 binop(Iop_AndV128,
15716 mkexpr(t4),
15717 getWReg(ws)),
15718 binop(Iop_AndV128,
15719 unop(Iop_NotV128, mkexpr(t4)),
15720 getWReg(wt))));
15721 putWReg(wd, mkexpr(t3));
15722 break;
15725 default:
15726 return -1;
15729 break;
15732 case 0x07: { /* MIN_A.df */
15733 switch (df) {
15734 case 0x00: { /* MIN_A.B */
15735 DIP("MIN_A.B w%d, w%d, w%d", wd, ws, wt);
15736 t1 = newTemp(Ity_V128);
15737 t2 = newTemp(Ity_V128);
15738 t3 = newTemp(Ity_V128);
15739 t4 = newTemp(Ity_V128);
15740 assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
15741 assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
15742 assign(t4, binop(Iop_OrV128,
15743 binop(Iop_CmpGT8Ux16,
15744 mkexpr(t1), mkexpr(t2)),
15745 binop(Iop_CmpEQ8x16,
15746 mkexpr(t1), mkexpr(t2))));
15747 assign(t3, binop(Iop_OrV128,
15748 binop(Iop_AndV128,
15749 mkexpr(t4),
15750 getWReg(wt)),
15751 binop(Iop_AndV128,
15752 unop(Iop_NotV128, mkexpr(t4)),
15753 getWReg(ws))));
15754 putWReg(wd, mkexpr(t3));
15755 break;
15758 case 0x01: { /* MIN_A.H */
15759 DIP("MIN_A.H w%d, w%d, w%d", wd, ws, wt);
15760 t1 = newTemp(Ity_V128);
15761 t2 = newTemp(Ity_V128);
15762 t3 = newTemp(Ity_V128);
15763 t4 = newTemp(Ity_V128);
15764 assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
15765 assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
15766 assign(t4, binop(Iop_OrV128,
15767 binop(Iop_CmpGT16Ux8,
15768 mkexpr(t1), mkexpr(t2)),
15769 binop(Iop_CmpEQ16x8,
15770 mkexpr(t1), mkexpr(t2))));
15771 assign(t3, binop(Iop_OrV128,
15772 binop(Iop_AndV128,
15773 mkexpr(t4),
15774 getWReg(wt)),
15775 binop(Iop_AndV128,
15776 unop(Iop_NotV128, mkexpr(t4)),
15777 getWReg(ws))));
15778 putWReg(wd, mkexpr(t3));
15779 break;
15782 case 0x02: { /* MIN_A.W */
15783 DIP("MIN_A.W w%d, w%d, w%d", wd, ws, wt);
15784 t1 = newTemp(Ity_V128);
15785 t2 = newTemp(Ity_V128);
15786 t3 = newTemp(Ity_V128);
15787 t4 = newTemp(Ity_V128);
15788 assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
15789 assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
15790 assign(t4, binop(Iop_OrV128,
15791 binop(Iop_CmpGT32Ux4,
15792 mkexpr(t1), mkexpr(t2)),
15793 binop(Iop_CmpEQ32x4,
15794 mkexpr(t1), mkexpr(t2))));
15795 assign(t3, binop(Iop_OrV128,
15796 binop(Iop_AndV128,
15797 mkexpr(t4),
15798 getWReg(wt)),
15799 binop(Iop_AndV128,
15800 unop(Iop_NotV128, mkexpr(t4)),
15801 getWReg(ws))));
15802 putWReg(wd, mkexpr(t3));
15803 break;
15806 case 0x03: { /* MIN_A.D */
15807 DIP("MIN_A.D w%d, w%d, w%d", wd, ws, wt);
15808 t1 = newTemp(Ity_V128);
15809 t2 = newTemp(Ity_V128);
15810 t3 = newTemp(Ity_V128);
15811 t4 = newTemp(Ity_V128);
15812 assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
15813 assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
15814 assign(t4, binop(Iop_OrV128,
15815 binop(Iop_CmpGT64Ux2,
15816 mkexpr(t1), mkexpr(t2)),
15817 binop(Iop_CmpEQ64x2,
15818 mkexpr(t1), mkexpr(t2))));
15819 assign(t3, binop(Iop_OrV128,
15820 binop(Iop_AndV128,
15821 mkexpr(t4),
15822 getWReg(wt)),
15823 binop(Iop_AndV128,
15824 unop(Iop_NotV128, mkexpr(t4)),
15825 getWReg(ws))));
15826 putWReg(wd, mkexpr(t3));
15827 break;
15830 default:
15831 return -1;
15834 break;
15837 default:
15838 return -1;
15841 return 0;
15844 static Int msa_3R_0F(UInt cins, UChar wd, UChar ws) { /* 3R (0x0F) */
15845 IRTemp t1, t2, t3;
15846 UShort operation;
15847 UChar df, wt;
15849 operation = (cins & 0x03800000) >> 23;
15850 df = (cins & 0x00600000) >> 21;
15851 wt = (cins & 0x001F0000) >> 16;
15853 switch (operation) {
15854 case 0x00: { /* CEQ.df */
15855 switch (df) {
15856 case 0x00: { /* CEQ.B */
15857 DIP("CEQ.B w%d, w%d, w%d", wd, ws, wt);
15858 t1 = newTemp(Ity_V128);
15859 t2 = newTemp(Ity_V128);
15860 t3 = newTemp(Ity_V128);
15861 assign(t1, getWReg(ws));
15862 assign(t2, getWReg(wt));
15863 assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
15864 putWReg(wd, mkexpr(t3));
15865 break;
15868 case 0x01: { /* CEQ.H */
15869 DIP("CEQ.H w%d, w%d, w%d", wd, ws, wt);
15870 t1 = newTemp(Ity_V128);
15871 t2 = newTemp(Ity_V128);
15872 t3 = newTemp(Ity_V128);
15873 assign(t1, getWReg(ws));
15874 assign(t2, getWReg(wt));
15875 assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
15876 putWReg(wd, mkexpr(t3));
15877 break;
15880 case 0x02: { /* CEQ.W */
15881 DIP("CEQ.W w%d, w%d, w%d", wd, ws, wt);
15882 t1 = newTemp(Ity_V128);
15883 t2 = newTemp(Ity_V128);
15884 t3 = newTemp(Ity_V128);
15885 assign(t1, getWReg(ws));
15886 assign(t2, getWReg(wt));
15887 assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
15888 putWReg(wd, mkexpr(t3));
15889 break;
15892 case 0x03: { /* CEQ.D */
15893 DIP("CEQ.D w%d, w%d, w%d", wd, ws, wt);
15894 t1 = newTemp(Ity_V128);
15895 t2 = newTemp(Ity_V128);
15896 t3 = newTemp(Ity_V128);
15897 assign(t1, getWReg(ws));
15898 assign(t2, getWReg(wt));
15899 assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
15900 putWReg(wd, mkexpr(t3));
15901 break;
15904 default:
15905 return -1;
15908 break;
15911 case 0x02: { /* CLT_S.df */
15912 switch (df) {
15913 case 0x00: { /* CLT_S.B */
15914 DIP("CLT_S.B w%d, w%d, w%d", wd, ws, wt);
15915 t1 = newTemp(Ity_V128);
15916 t2 = newTemp(Ity_V128);
15917 t3 = newTemp(Ity_V128);
15918 assign(t1, getWReg(ws));
15919 assign(t2, getWReg(wt));
15920 assign(t3, binop(Iop_CmpGT8Sx16, mkexpr(t2), mkexpr(t1)));
15921 putWReg(wd, mkexpr(t3));
15922 break;
15925 case 0x01: { /* CLT_S.H */
15926 DIP("CLT_S.H w%d, w%d, w%d", wd, ws, wt);
15927 t1 = newTemp(Ity_V128);
15928 t2 = newTemp(Ity_V128);
15929 t3 = newTemp(Ity_V128);
15930 assign(t1, getWReg(ws));
15931 assign(t2, getWReg(wt));
15932 assign(t3, binop(Iop_CmpGT16Sx8, mkexpr(t2), mkexpr(t1)));
15933 putWReg(wd, mkexpr(t3));
15934 break;
15937 case 0x02: { /* CLT_S.W */
15938 DIP("CLT_S.W w%d, w%d, w%d", wd, ws, wt);
15939 t1 = newTemp(Ity_V128);
15940 t2 = newTemp(Ity_V128);
15941 t3 = newTemp(Ity_V128);
15942 assign(t1, getWReg(ws));
15943 assign(t2, getWReg(wt));
15944 assign(t3, binop(Iop_CmpGT32Sx4, mkexpr(t2), mkexpr(t1)));
15945 putWReg(wd, mkexpr(t3));
15946 break;
15949 case 0x03: { /* CLT_S.D */
15950 DIP("CLT_S.D w%d, w%d, w%d", wd, ws, wt);
15951 t1 = newTemp(Ity_V128);
15952 t2 = newTemp(Ity_V128);
15953 t3 = newTemp(Ity_V128);
15954 assign(t1, getWReg(ws));
15955 assign(t2, getWReg(wt));
15956 assign(t3, binop(Iop_CmpGT64Sx2, mkexpr(t2), mkexpr(t1)));
15957 putWReg(wd, mkexpr(t3));
15958 break;
15961 default:
15962 return -1;
15965 break;
15968 case 0x03: { /* CLT_U.df */
15969 switch (df) {
15970 case 0x00: { /* CLT_U.B */
15971 DIP("CLT_U.B w%d, w%d, w%d", wd, ws, wt);
15972 t1 = newTemp(Ity_V128);
15973 t2 = newTemp(Ity_V128);
15974 t3 = newTemp(Ity_V128);
15975 assign(t1, getWReg(ws));
15976 assign(t2, getWReg(wt));
15977 assign(t3, binop(Iop_CmpGT8Ux16, mkexpr(t2), mkexpr(t1)));
15978 putWReg(wd, mkexpr(t3));
15979 break;
15982 case 0x01: { /* CLT_U.H */
15983 DIP("CLT_U.H w%d, w%d, w%d", wd, ws, wt);
15984 t1 = newTemp(Ity_V128);
15985 t2 = newTemp(Ity_V128);
15986 t3 = newTemp(Ity_V128);
15987 assign(t1, getWReg(ws));
15988 assign(t2, getWReg(wt));
15989 assign(t3, binop(Iop_CmpGT16Ux8, mkexpr(t2), mkexpr(t1)));
15990 putWReg(wd, mkexpr(t3));
15991 break;
15994 case 0x02: { /* CLT_U.W */
15995 DIP("CLT_U.W w%d, w%d, w%d", wd, ws, wt);
15996 t1 = newTemp(Ity_V128);
15997 t2 = newTemp(Ity_V128);
15998 t3 = newTemp(Ity_V128);
15999 assign(t1, getWReg(ws));
16000 assign(t2, getWReg(wt));
16001 assign(t3, binop(Iop_CmpGT32Ux4, mkexpr(t2), mkexpr(t1)));
16002 putWReg(wd, mkexpr(t3));
16003 break;
16006 case 0x03: { /* CLT_U.D */
16007 DIP("CLT_U.D w%d, w%d, w%d", wd, ws, wt);
16008 t1 = newTemp(Ity_V128);
16009 t2 = newTemp(Ity_V128);
16010 t3 = newTemp(Ity_V128);
16011 assign(t1, getWReg(ws));
16012 assign(t2, getWReg(wt));
16013 assign(t3, binop(Iop_CmpGT64Ux2, mkexpr(t2), mkexpr(t1)));
16014 putWReg(wd, mkexpr(t3));
16015 break;
16018 default:
16019 return -1;
16022 break;
16025 case 0x04: { /* CLE_S.df */
16026 switch (df) {
16027 case 0x00: { /* CLE_S.B */
16028 DIP("CLE_S.B w%d, w%d, w%d", wd, ws, wt);
16029 t1 = newTemp(Ity_V128);
16030 t2 = newTemp(Ity_V128);
16031 t3 = newTemp(Ity_V128);
16032 assign(t1, getWReg(ws));
16033 assign(t2, getWReg(wt));
16034 assign(t3, binop(Iop_OrV128,
16035 binop(Iop_CmpGT8Sx16,
16036 mkexpr(t2), mkexpr(t1)),
16037 binop(Iop_CmpEQ8x16,
16038 mkexpr(t1), mkexpr(t2))));
16039 putWReg(wd, mkexpr(t3));
16040 break;
16043 case 0x01: { /* CLE_S.H */
16044 DIP("CLE_S.H w%d, w%d, w%d", wd, ws, wt);
16045 t1 = newTemp(Ity_V128);
16046 t2 = newTemp(Ity_V128);
16047 t3 = newTemp(Ity_V128);
16048 assign(t1, getWReg(ws));
16049 assign(t2, getWReg(wt));
16050 assign(t3, binop(Iop_OrV128,
16051 binop(Iop_CmpGT16Sx8,
16052 mkexpr(t2), mkexpr(t1)),
16053 binop(Iop_CmpEQ16x8,
16054 mkexpr(t1), mkexpr(t2))));
16055 putWReg(wd, mkexpr(t3));
16056 break;
16059 case 0x02: { /* CLE_S.W */
16060 DIP("CLE_S.W w%d, w%d, w%d", wd, ws, wt);
16061 t1 = newTemp(Ity_V128);
16062 t2 = newTemp(Ity_V128);
16063 t3 = newTemp(Ity_V128);
16064 assign(t1, getWReg(ws));
16065 assign(t2, getWReg(wt));
16066 assign(t3, binop(Iop_OrV128,
16067 binop(Iop_CmpGT32Sx4,
16068 mkexpr(t2), mkexpr(t1)),
16069 binop(Iop_CmpEQ32x4,
16070 mkexpr(t1), mkexpr(t2))));
16071 putWReg(wd, mkexpr(t3));
16072 break;
16075 case 0x03: { /* CLE_S.D */
16076 DIP("CLE_S.D w%d, w%d, w%d", wd, ws, wt);
16077 t1 = newTemp(Ity_V128);
16078 t2 = newTemp(Ity_V128);
16079 t3 = newTemp(Ity_V128);
16080 assign(t1, getWReg(ws));
16081 assign(t2, getWReg(wt));
16082 assign(t3, binop(Iop_OrV128,
16083 binop(Iop_CmpGT64Sx2,
16084 mkexpr(t2), mkexpr(t1)),
16085 binop(Iop_CmpEQ64x2,
16086 mkexpr(t1), mkexpr(t2))));
16087 putWReg(wd, mkexpr(t3));
16088 break;
16091 default:
16092 return -1;
16095 break;
16098 case 0x05: { /* CLE_U.df */
16099 switch (df) {
16100 case 0x00: { /* CLE_U.B */
16101 DIP("CLE_U.B w%d, w%d, w%d", wd, ws, wt);
16102 t1 = newTemp(Ity_V128);
16103 t2 = newTemp(Ity_V128);
16104 t3 = newTemp(Ity_V128);
16105 assign(t1, getWReg(ws));
16106 assign(t2, getWReg(wt));
16107 assign(t3, binop(Iop_OrV128,
16108 binop(Iop_CmpGT8Ux16,
16109 mkexpr(t2), mkexpr(t1)),
16110 binop(Iop_CmpEQ8x16,
16111 mkexpr(t1), mkexpr(t2))));
16112 putWReg(wd, mkexpr(t3));
16113 break;
16116 case 0x01: { /* CLE_U.H */
16117 DIP("CLE_U.H w%d, w%d, w%d", wd, ws, wt);
16118 t1 = newTemp(Ity_V128);
16119 t2 = newTemp(Ity_V128);
16120 t3 = newTemp(Ity_V128);
16121 assign(t1, getWReg(ws));
16122 assign(t2, getWReg(wt));
16123 assign(t3, binop(Iop_OrV128,
16124 binop(Iop_CmpGT16Ux8,
16125 mkexpr(t2), mkexpr(t1)),
16126 binop(Iop_CmpEQ16x8,
16127 mkexpr(t1), mkexpr(t2))));
16128 putWReg(wd, mkexpr(t3));
16129 break;
16132 case 0x02: { /* CLE_U.W */
16133 DIP("CLE_U.W w%d, w%d, w%d", wd, ws, wt);
16134 t1 = newTemp(Ity_V128);
16135 t2 = newTemp(Ity_V128);
16136 t3 = newTemp(Ity_V128);
16137 assign(t1, getWReg(ws));
16138 assign(t2, getWReg(wt));
16139 assign(t3, binop(Iop_OrV128,
16140 binop(Iop_CmpGT32Ux4,
16141 mkexpr(t2), mkexpr(t1)),
16142 binop(Iop_CmpEQ32x4,
16143 mkexpr(t1), mkexpr(t2))));
16144 putWReg(wd, mkexpr(t3));
16145 break;
16148 case 0x03: { /* CLE_U.D */
16149 DIP("CLE_U.D w%d, w%d, w%d", wd, ws, wt);
16150 t1 = newTemp(Ity_V128);
16151 t2 = newTemp(Ity_V128);
16152 t3 = newTemp(Ity_V128);
16153 assign(t1, getWReg(ws));
16154 assign(t2, getWReg(wt));
16155 assign(t3,
16156 binop(Iop_OrV128,
16157 binop(Iop_CmpGT64Ux2,
16158 mkexpr(t2), mkexpr(t1)),
16159 binop(Iop_CmpEQ64x2,
16160 mkexpr(t1), mkexpr(t2))));
16161 putWReg(wd, mkexpr(t3));
16162 break;
16165 default:
16166 return -1;
16169 break;
16172 default:
16173 return -1;
16176 return 0;
16179 static Int msa_3R_10(UInt cins, UChar wd, UChar ws) { /* 3R (0x10) */
16180 IRTemp t1, t2, t3, t4;
16181 UShort operation;
16182 UChar df, wt;
16184 operation = (cins & 0x03800000) >> 23;
16185 df = (cins & 0x00600000) >> 21;
16186 wt = (cins & 0x001F0000) >> 16;
16188 switch (operation) {
16189 case 0x00: { /* ADD_A.df */
16190 switch (df) {
16191 case 0x00: { /* ADD_A.B */
16192 DIP("ADD_A.B w%d, w%d, w%d", wd, ws, wt);
16193 t1 = newTemp(Ity_V128);
16194 t2 = newTemp(Ity_V128);
16195 t3 = newTemp(Ity_V128);
16196 assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
16197 assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
16198 assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
16199 putWReg(wd, mkexpr(t3));
16200 break;
16203 case 0x01: { /* ADD_A.H */
16204 DIP("ADD_A.H w%d, w%d, w%d", wd, ws, wt);
16205 t1 = newTemp(Ity_V128);
16206 t2 = newTemp(Ity_V128);
16207 t3 = newTemp(Ity_V128);
16208 assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
16209 assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
16210 assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
16211 putWReg(wd, mkexpr(t3));
16212 break;
16215 case 0x02: { /* ADD_A.W */
16216 DIP("ADD_A.W w%d, w%d, w%d", wd, ws, wt);
16217 t1 = newTemp(Ity_V128);
16218 t2 = newTemp(Ity_V128);
16219 t3 = newTemp(Ity_V128);
16220 assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
16221 assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
16222 assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
16223 putWReg(wd, mkexpr(t3));
16224 break;
16227 case 0x03: { /* ADD_A.D */
16228 DIP("ADD_A.D w%d, w%d, w%d", wd, ws, wt);
16229 t1 = newTemp(Ity_V128);
16230 t2 = newTemp(Ity_V128);
16231 t3 = newTemp(Ity_V128);
16232 assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
16233 assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
16234 assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
16235 putWReg(wd, mkexpr(t3));
16236 break;
16239 default:
16240 return -1;
16243 break;
16246 case 0x01: { /* ADDS_A.df */
16247 switch (df) {
16248 case 0x00: { /* ADDS_A.B */
16249 DIP("ADDS_A.B w%d, w%d, w%d", wd, ws, wt);
16250 t1 = newTemp(Ity_V128);
16251 t2 = newTemp(Ity_V128);
16252 t3 = newTemp(Ity_V128);
16253 t4 = newTemp(Ity_V128);
16254 assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
16255 assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
16256 assign(t3, binop(Iop_SarN8x16,
16257 binop(Iop_AndV128,
16258 mkexpr(t1),
16259 getWReg(ws)),
16260 mkU8(7)));
16261 assign(t4, binop(Iop_SarN8x16,
16262 binop(Iop_AndV128,
16263 mkexpr(t2),
16264 getWReg(wt)),
16265 mkU8(7)));
16266 putWReg(wd, binop(Iop_QAdd8Sx16,
16267 binop(Iop_OrV128,
16268 binop(Iop_AndV128,
16269 unop(Iop_NotV128,
16270 mkexpr(t3)),
16271 mkexpr(t1)),
16272 binop(Iop_AndV128,
16273 unop(Iop_NotV128,
16274 mkexpr(t1)),
16275 mkexpr(t3))),
16276 binop(Iop_OrV128,
16277 binop(Iop_AndV128,
16278 unop(Iop_NotV128,
16279 mkexpr(t4)),
16280 mkexpr(t2)),
16281 binop(Iop_AndV128,
16282 unop(Iop_NotV128,
16283 mkexpr(t2)),
16284 mkexpr(t4)))));
16285 break;
16288 case 0x01: { /* ADDS_A.H */
16289 DIP("ADDS_A.H w%d, w%d, w%d", wd, ws, wt);
16290 t1 = newTemp(Ity_V128);
16291 t2 = newTemp(Ity_V128);
16292 t3 = newTemp(Ity_V128);
16293 t4 = newTemp(Ity_V128);
16294 assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
16295 assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
16296 assign(t3, binop(Iop_SarN16x8,
16297 binop(Iop_AndV128,
16298 mkexpr(t1),
16299 getWReg(ws)),
16300 mkU8(15)));
16301 assign(t4, binop(Iop_SarN16x8,
16302 binop(Iop_AndV128,
16303 mkexpr(t2),
16304 getWReg(wt)),
16305 mkU8(15)));
16306 putWReg(wd, binop(Iop_QAdd16Sx8,
16307 binop(Iop_OrV128,
16308 binop(Iop_AndV128,
16309 unop(Iop_NotV128,
16310 mkexpr(t3)),
16311 mkexpr(t1)),
16312 binop(Iop_AndV128,
16313 unop(Iop_NotV128,
16314 mkexpr(t1)),
16315 mkexpr(t3))),
16316 binop(Iop_OrV128,
16317 binop(Iop_AndV128,
16318 unop(Iop_NotV128,
16319 mkexpr(t4)),
16320 mkexpr(t2)),
16321 binop(Iop_AndV128,
16322 unop(Iop_NotV128,
16323 mkexpr(t2)),
16324 mkexpr(t4)))));
16325 break;
16328 case 0x02: { /* ADDS_A.W */
16329 DIP("ADDS_A.W w%d, w%d, w%d", wd, ws, wt);
16330 t1 = newTemp(Ity_V128);
16331 t2 = newTemp(Ity_V128);
16332 t3 = newTemp(Ity_V128);
16333 t4 = newTemp(Ity_V128);
16334 assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
16335 assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
16336 assign(t3, binop(Iop_SarN32x4,
16337 binop(Iop_AndV128,
16338 mkexpr(t1),
16339 getWReg(ws)),
16340 mkU8(31)));
16341 assign(t4, binop(Iop_SarN32x4,
16342 binop(Iop_AndV128,
16343 mkexpr(t2),
16344 getWReg(wt)),
16345 mkU8(31)));
16346 putWReg(wd, binop(Iop_QAdd32Sx4,
16347 binop(Iop_OrV128,
16348 binop(Iop_AndV128,
16349 unop(Iop_NotV128,
16350 mkexpr(t3)),
16351 mkexpr(t1)),
16352 binop(Iop_AndV128,
16353 unop(Iop_NotV128,
16354 mkexpr(t1)),
16355 mkexpr(t3))),
16356 binop(Iop_OrV128,
16357 binop(Iop_AndV128,
16358 unop(Iop_NotV128,
16359 mkexpr(t4)),
16360 mkexpr(t2)),
16361 binop(Iop_AndV128,
16362 unop(Iop_NotV128,
16363 mkexpr(t2)),
16364 mkexpr(t4)))));
16365 break;
16368 case 0x03: { /* ADDS_A.D */
16369 DIP("ADDS_A.D w%d, w%d, w%d", wd, ws, wt);
16370 t1 = newTemp(Ity_V128);
16371 t2 = newTemp(Ity_V128);
16372 t3 = newTemp(Ity_V128);
16373 t4 = newTemp(Ity_V128);
16374 assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
16375 assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
16376 assign(t3, binop(Iop_SarN64x2,
16377 binop(Iop_AndV128,
16378 mkexpr(t1),
16379 getWReg(ws)),
16380 mkU8(63)));
16381 assign(t4, binop(Iop_SarN64x2,
16382 binop(Iop_AndV128,
16383 mkexpr(t2),
16384 getWReg(wt)),
16385 mkU8(63)));
16386 putWReg(wd,
16387 binop(Iop_QAdd64Sx2,
16388 binop(Iop_OrV128,
16389 binop(Iop_AndV128,
16390 unop(Iop_NotV128,
16391 mkexpr(t3)),
16392 mkexpr(t1)),
16393 binop(Iop_AndV128,
16394 unop(Iop_NotV128,
16395 mkexpr(t1)),
16396 mkexpr(t3))),
16397 binop(Iop_OrV128,
16398 binop(Iop_AndV128,
16399 unop(Iop_NotV128,
16400 mkexpr(t4)),
16401 mkexpr(t2)),
16402 binop(Iop_AndV128,
16403 unop(Iop_NotV128,
16404 mkexpr(t2)),
16405 mkexpr(t4)))));
16406 break;
16409 default:
16410 return -1;
16413 break;
16416 case 0x02: { /* ADDS_S.df */
16417 switch (df) {
16418 case 0x00: { /* ADDS_S.B */
16419 DIP("ADDS_S.B w%d, w%d, w%d", wd, ws, wt);
16420 t1 = newTemp(Ity_V128);
16421 t2 = newTemp(Ity_V128);
16422 t3 = newTemp(Ity_V128);
16423 assign(t1, getWReg(ws));
16424 assign(t2, getWReg(wt));
16425 assign(t3, binop(Iop_QAdd8Sx16, mkexpr(t1), mkexpr(t2)));
16426 putWReg(wd, mkexpr(t3));
16427 break;
16430 case 0x01: { /* ADDS_S.H */
16431 DIP("ADDS_S.H w%d, w%d, w%d", wd, ws, wt);
16432 t1 = newTemp(Ity_V128);
16433 t2 = newTemp(Ity_V128);
16434 t3 = newTemp(Ity_V128);
16435 assign(t1, getWReg(ws));
16436 assign(t2, getWReg(wt));
16437 assign(t3, binop(Iop_QAdd16Sx8, mkexpr(t1), mkexpr(t2)));
16438 putWReg(wd, mkexpr(t3));
16439 break;
16442 case 0x02: { /* ADDS_S.W */
16443 DIP("ADDS_S.W w%d, w%d, w%d", wd, ws, wt);
16444 t1 = newTemp(Ity_V128);
16445 t2 = newTemp(Ity_V128);
16446 t3 = newTemp(Ity_V128);
16447 assign(t1, getWReg(ws));
16448 assign(t2, getWReg(wt));
16449 assign(t3, binop(Iop_QAdd32Sx4, mkexpr(t1), mkexpr(t2)));
16450 putWReg(wd, mkexpr(t3));
16451 break;
16454 case 0x03: { /* ADDS_S.D */
16455 DIP("ADDS_S.D w%d, w%d, w%d", wd, ws, wt);
16456 t1 = newTemp(Ity_V128);
16457 t2 = newTemp(Ity_V128);
16458 t3 = newTemp(Ity_V128);
16459 assign(t1, getWReg(ws));
16460 assign(t2, getWReg(wt));
16461 assign(t3, binop(Iop_QAdd64Sx2, mkexpr(t1), mkexpr(t2)));
16462 putWReg(wd, mkexpr(t3));
16463 break;
16466 default:
16467 return -1;
16470 break;
16473 case 0x03: { /* ADDS_U.df */
16474 switch (df) {
16475 case 0x00: { /* ADDS_U.B */
16476 DIP("ADDS_U.B w%d, w%d, w%d", wd, ws, wt);
16477 t1 = newTemp(Ity_V128);
16478 t2 = newTemp(Ity_V128);
16479 t3 = newTemp(Ity_V128);
16480 assign(t1, getWReg(ws));
16481 assign(t2, getWReg(wt));
16482 assign(t3, binop(Iop_QAdd8Ux16, mkexpr(t1), mkexpr(t2)));
16483 putWReg(wd, mkexpr(t3));
16484 break;
16487 case 0x01: { /* ADDS_U.H */
16488 DIP("ADDS_U.H w%d, w%d, w%d", wd, ws, wt);
16489 t1 = newTemp(Ity_V128);
16490 t2 = newTemp(Ity_V128);
16491 t3 = newTemp(Ity_V128);
16492 assign(t1, getWReg(ws));
16493 assign(t2, getWReg(wt));
16494 assign(t3, binop(Iop_QAdd16Ux8, mkexpr(t1), mkexpr(t2)));
16495 putWReg(wd, mkexpr(t3));
16496 break;
16499 case 0x02: { /* ADDS_U.W */
16500 DIP("ADDS_U.W w%d, w%d, w%d", wd, ws, wt);
16501 t1 = newTemp(Ity_V128);
16502 t2 = newTemp(Ity_V128);
16503 t3 = newTemp(Ity_V128);
16504 assign(t1, getWReg(ws));
16505 assign(t2, getWReg(wt));
16506 assign(t3, binop(Iop_QAdd32Ux4, mkexpr(t1), mkexpr(t2)));
16507 putWReg(wd, mkexpr(t3));
16508 break;
16511 case 0x03: { /* ADDS_U.D */
16512 DIP("ADDS_U.D w%d, w%d, w%d", wd, ws, wt);
16513 t1 = newTemp(Ity_V128);
16514 t2 = newTemp(Ity_V128);
16515 t3 = newTemp(Ity_V128);
16516 assign(t1, getWReg(ws));
16517 assign(t2, getWReg(wt));
16518 assign(t3, binop(Iop_QAdd64Ux2, mkexpr(t1), mkexpr(t2)));
16519 putWReg(wd, mkexpr(t3));
16520 break;
16523 default:
16524 return -1;
16527 break;
16530 case 0x04: { /* AVE_S.df */
16531 switch (df) {
16532 case 0x00: { /* AVE_S.B */
16533 DIP("AVE_S.B w%d, w%d, w%d", wd, ws, wt);
16534 t1 = newTemp(Ity_V128);
16535 t2 = newTemp(Ity_V128);
16536 t3 = newTemp(Ity_V128);
16537 assign(t1, getWReg(ws));
16538 assign(t2, getWReg(wt));
16539 assign(t3, binop(Iop_Add8x16,
16540 binop(Iop_Add8x16,
16541 binop(Iop_SarN8x16,
16542 mkexpr(t1), mkU8(1)),
16543 binop(Iop_SarN8x16,
16544 mkexpr(t2), mkU8(1))),
16545 binop(Iop_ShrN8x16,
16546 binop(Iop_ShlN8x16,
16547 binop(Iop_AndV128,
16548 mkexpr(t1),
16549 mkexpr(t2)),
16550 mkU8(7)),
16551 mkU8(7))));
16552 putWReg(wd, mkexpr(t3));
16553 break;
16556 case 0x01: { /* AVE_S.H */
16557 DIP("AVE_S.H w%d, w%d, w%d", wd, ws, wt);
16558 t1 = newTemp(Ity_V128);
16559 t2 = newTemp(Ity_V128);
16560 t3 = newTemp(Ity_V128);
16561 assign(t1, getWReg(ws));
16562 assign(t2, getWReg(wt));
16563 assign(t3,
16564 binop(Iop_Add16x8,
16565 binop(Iop_Add16x8,
16566 binop(Iop_SarN16x8,
16567 mkexpr(t1), mkU8(1)),
16568 binop(Iop_SarN16x8,
16569 mkexpr(t2), mkU8(1))),
16570 binop(Iop_ShrN16x8,
16571 binop(Iop_ShlN16x8,
16572 binop(Iop_AndV128,
16573 mkexpr(t1),
16574 mkexpr(t2)),
16575 mkU8(15)),
16576 mkU8(15))));
16577 putWReg(wd, mkexpr(t3));
16578 break;
16581 case 0x02: { /* AVE_S.W */
16582 DIP("AVE_S.W w%d, w%d, w%d", wd, ws, wt);
16583 t1 = newTemp(Ity_V128);
16584 t2 = newTemp(Ity_V128);
16585 t3 = newTemp(Ity_V128);
16586 assign(t1, getWReg(ws));
16587 assign(t2, getWReg(wt));
16588 assign(t3, binop(Iop_Add32x4,
16589 binop(Iop_Add32x4,
16590 binop(Iop_SarN32x4,
16591 mkexpr(t1), mkU8(1)),
16592 binop(Iop_SarN32x4,
16593 mkexpr(t2), mkU8(1))),
16594 binop(Iop_ShrN32x4,
16595 binop(Iop_ShlN32x4,
16596 binop(Iop_AndV128,
16597 mkexpr(t1),
16598 mkexpr(t2)),
16599 mkU8(31)),
16600 mkU8(31))));
16601 putWReg(wd, mkexpr(t3));
16602 break;
16605 case 0x03: { /* AVE_S.D */
16606 DIP("AVE_S.D w%d, w%d, w%d", wd, ws, wt);
16607 t1 = newTemp(Ity_V128);
16608 t2 = newTemp(Ity_V128);
16609 t3 = newTemp(Ity_V128);
16610 assign(t1, getWReg(ws));
16611 assign(t2, getWReg(wt));
16612 assign(t3, binop(Iop_Add64x2,
16613 binop(Iop_Add64x2,
16614 binop(Iop_SarN64x2,
16615 mkexpr(t1), mkU8(1)),
16616 binop(Iop_SarN64x2,
16617 mkexpr(t2), mkU8(1))),
16618 binop(Iop_ShrN64x2,
16619 binop(Iop_ShlN64x2,
16620 binop(Iop_AndV128,
16621 mkexpr(t1),
16622 mkexpr(t2)),
16623 mkU8(63)),
16624 mkU8(63))));
16625 putWReg(wd, mkexpr(t3));
16626 break;
16629 default:
16630 return -1;
16633 break;
16636 case 0x05: { /* AVE_U.df */
16637 switch (df) {
16638 case 0x00: { /* AVE_U.B */
16639 DIP("AVE_U.B w%d, w%d, w%d", wd, ws, wt);
16640 t1 = newTemp(Ity_V128);
16641 t2 = newTemp(Ity_V128);
16642 t3 = newTemp(Ity_V128);
16643 assign(t1, getWReg(ws));
16644 assign(t2, getWReg(wt));
16645 assign(t3, binop(Iop_Add16x8,
16646 binop(Iop_Add8x16,
16647 binop(Iop_ShrN8x16,
16648 mkexpr(t1), mkU8(1)),
16649 binop(Iop_ShrN8x16,
16650 mkexpr(t2), mkU8(1))),
16651 binop(Iop_ShrN8x16,
16652 binop(Iop_ShlN8x16,
16653 binop(Iop_AndV128,
16654 mkexpr(t1),
16655 mkexpr(t2)),
16656 mkU8(7)),
16657 mkU8(7))));
16658 putWReg(wd, mkexpr(t3));
16659 break;
16662 case 0x01: { /* AVE_U.H */
16663 DIP("AVE_U.H w%d, w%d, w%d", wd, ws, wt);
16664 t1 = newTemp(Ity_V128);
16665 t2 = newTemp(Ity_V128);
16666 t3 = newTemp(Ity_V128);
16667 assign(t1, getWReg(ws));
16668 assign(t2, getWReg(wt));
16669 assign(t3, binop(Iop_Add16x8,
16670 binop(Iop_Add16x8,
16671 binop(Iop_ShrN16x8,
16672 mkexpr(t1), mkU8(1)),
16673 binop(Iop_ShrN16x8,
16674 mkexpr(t2), mkU8(1))),
16675 binop(Iop_ShrN16x8,
16676 binop(Iop_ShlN16x8,
16677 binop(Iop_AndV128,
16678 mkexpr(t1),
16679 mkexpr(t2)),
16680 mkU8(15)),
16681 mkU8(15))));
16682 putWReg(wd, mkexpr(t3));
16683 break;
16686 case 0x02: { /* AVE_U.W */
16687 DIP("AVE_U.W w%d, w%d, w%d", wd, ws, wt);
16688 t1 = newTemp(Ity_V128);
16689 t2 = newTemp(Ity_V128);
16690 t3 = newTemp(Ity_V128);
16691 assign(t1, getWReg(ws));
16692 assign(t2, getWReg(wt));
16693 assign(t3, binop(Iop_Add32x4,
16694 binop(Iop_Add32x4,
16695 binop(Iop_ShrN32x4,
16696 mkexpr(t1), mkU8(1)),
16697 binop(Iop_ShrN32x4,
16698 mkexpr(t2), mkU8(1))),
16699 binop(Iop_ShrN32x4,
16700 binop(Iop_ShlN32x4,
16701 binop(Iop_AndV128,
16702 mkexpr(t1),
16703 mkexpr(t2)),
16704 mkU8(31)),
16705 mkU8(31))));
16706 putWReg(wd, mkexpr(t3));
16707 break;
16710 case 0x03: { /* AVE_U.D */
16711 DIP("AVE_U.D w%d, w%d, w%d", wd, ws, wt);
16712 t1 = newTemp(Ity_V128);
16713 t2 = newTemp(Ity_V128);
16714 t3 = newTemp(Ity_V128);
16715 assign(t1, getWReg(ws));
16716 assign(t2, getWReg(wt));
16717 assign(t3, binop(Iop_Add64x2,
16718 binop(Iop_Add64x2,
16719 binop(Iop_ShrN64x2,
16720 mkexpr(t1), mkU8(1)),
16721 binop(Iop_ShrN64x2,
16722 mkexpr(t2), mkU8(1))),
16723 binop(Iop_ShrN64x2,
16724 binop(Iop_ShlN64x2,
16725 binop(Iop_AndV128,
16726 mkexpr(t1),
16727 mkexpr(t2)),
16728 mkU8(63)),
16729 mkU8(63))));
16730 putWReg(wd, mkexpr(t3));
16731 break;
16734 default:
16735 return -1;
16738 break;
16741 case 0x06: { /* AVER_S.df */
16742 switch (df) {
16743 case 0x00: { /* AVER_S.B */
16744 DIP("AVER_S.B w%d, w%d, w%d", wd, ws, wt);
16745 t1 = newTemp(Ity_V128);
16746 t2 = newTemp(Ity_V128);
16747 t3 = newTemp(Ity_V128);
16748 assign(t1, getWReg(ws));
16749 assign(t2, getWReg(wt));
16750 assign(t3, binop(Iop_Avg8Sx16, mkexpr(t1), mkexpr(t2)));
16751 putWReg(wd, mkexpr(t3));
16752 break;
16755 case 0x01: { /* AVER_S.H */
16756 DIP("AVER_S.H w%d, w%d, w%d", wd, ws, wt);
16757 t1 = newTemp(Ity_V128);
16758 t2 = newTemp(Ity_V128);
16759 t3 = newTemp(Ity_V128);
16760 assign(t1, getWReg(ws));
16761 assign(t2, getWReg(wt));
16762 assign(t3, binop(Iop_Avg16Sx8, mkexpr(t1), mkexpr(t2)));
16763 putWReg(wd, mkexpr(t3));
16764 break;
16767 case 0x02: { /* AVER_S.W */
16768 DIP("AVER_S.W w%d, w%d, w%d", wd, ws, wt);
16769 t1 = newTemp(Ity_V128);
16770 t2 = newTemp(Ity_V128);
16771 t3 = newTemp(Ity_V128);
16772 assign(t1, getWReg(ws));
16773 assign(t2, getWReg(wt));
16774 assign(t3, binop(Iop_Avg32Sx4, mkexpr(t1), mkexpr(t2)));
16775 putWReg(wd, mkexpr(t3));
16776 break;
16779 case 0x03: { /* AVER_S.D */
16780 DIP("AVER_S.D w%d, w%d, w%d", wd, ws, wt);
16781 t1 = newTemp(Ity_V128);
16782 t2 = newTemp(Ity_V128);
16783 t3 = newTemp(Ity_V128);
16784 assign(t1, getWReg(ws));
16785 assign(t2, getWReg(wt));
16786 assign(t3, binop(Iop_Add64x2,
16787 binop(Iop_Add64x2,
16788 binop(Iop_SarN64x2,
16789 mkexpr(t1), mkU8(1)),
16790 binop(Iop_SarN64x2,
16791 mkexpr(t2), mkU8(1))),
16792 binop(Iop_ShrN64x2,
16793 binop(Iop_ShlN64x2,
16794 binop(Iop_OrV128,
16795 mkexpr(t1),
16796 mkexpr(t2)),
16797 mkU8(63)),
16798 mkU8(63))));
16799 putWReg(wd, mkexpr(t3));
16800 break;
16803 default:
16804 return -1;
16807 break;
16810 case 0x07: { /* AVER_U.df */
16811 switch (df) {
16812 case 0x00: { /* AVER_U.B */
16813 DIP("AVER_U.B w%d, w%d, w%d", wd, ws, wt);
16814 t1 = newTemp(Ity_V128);
16815 t2 = newTemp(Ity_V128);
16816 t3 = newTemp(Ity_V128);
16817 assign(t1, getWReg(ws));
16818 assign(t2, getWReg(wt));
16819 assign(t3, binop(Iop_Avg8Ux16, mkexpr(t1), mkexpr(t2)));
16820 putWReg(wd, mkexpr(t3));
16821 break;
16824 case 0x01: { /* AVER_U.H */
16825 DIP("AVER_U.H w%d, w%d, w%d", wd, ws, wt);
16826 t1 = newTemp(Ity_V128);
16827 t2 = newTemp(Ity_V128);
16828 t3 = newTemp(Ity_V128);
16829 assign(t1, getWReg(ws));
16830 assign(t2, getWReg(wt));
16831 assign(t3, binop(Iop_Avg16Ux8, mkexpr(t1), mkexpr(t2)));
16832 putWReg(wd, mkexpr(t3));
16833 break;
16836 case 0x02: { /* AVER_U.W */
16837 DIP("AVER_U.W w%d, w%d, w%d", wd, ws, wt);
16838 t1 = newTemp(Ity_V128);
16839 t2 = newTemp(Ity_V128);
16840 t3 = newTemp(Ity_V128);
16841 assign(t1, getWReg(ws));
16842 assign(t2, getWReg(wt));
16843 assign(t3, binop(Iop_Avg32Ux4, mkexpr(t1), mkexpr(t2)));
16844 putWReg(wd, mkexpr(t3));
16845 break;
16848 case 0x03: { /* AVER_U.D */
16849 DIP("AVER_U.D w%d, w%d, w%d", wd, ws, wt);
16850 t1 = newTemp(Ity_V128);
16851 t2 = newTemp(Ity_V128);
16852 t3 = newTemp(Ity_V128);
16853 assign(t1, getWReg(ws));
16854 assign(t2, getWReg(wt));
16855 assign(t3, binop(Iop_Add64x2,
16856 binop(Iop_Add64x2,
16857 binop(Iop_ShrN64x2,
16858 mkexpr(t1), mkU8(1)),
16859 binop(Iop_ShrN64x2,
16860 mkexpr(t2), mkU8(1))),
16861 binop(Iop_ShrN64x2,
16862 binop(Iop_ShlN64x2,
16863 binop(Iop_OrV128,
16864 mkexpr(t1),
16865 mkexpr(t2)),
16866 mkU8(63)),
16867 mkU8(63))));
16868 putWReg(wd, mkexpr(t3));
16869 break;
16872 default:
16873 return -1;
16876 break;
16879 default:
16880 return -1;
16883 return 0;
16886 static Int msa_3R_11(UInt cins, UChar wd, UChar ws) { /* 3R (0x11) */
16887 IRTemp t1, t2, t3;
16888 UShort operation;
16889 UChar df, wt;
16891 operation = (cins & 0x03800000) >> 23;
16892 df = (cins & 0x00600000) >> 21;
16893 wt = (cins & 0x001F0000) >> 16;
16895 switch (operation) {
16896 case 0x00: { /* SUBS_S.df */
16897 switch (df) {
16898 case 0x00: { /* SUBS_S.B */
16899 DIP("SUBS_S.B w%d, w%d, w%d", wd, ws, wt);
16900 t1 = newTemp(Ity_V128);
16901 t2 = newTemp(Ity_V128);
16902 t3 = newTemp(Ity_V128);
16903 assign(t1, getWReg(ws));
16904 assign(t2, getWReg(wt));
16905 assign(t3, binop(Iop_QSub8Sx16, mkexpr(t1), mkexpr(t2)));
16906 putWReg(wd, mkexpr(t3));
16907 break;
16910 case 0x01: { /* SUBS_S.H */
16911 DIP("SUBS_S.H w%d, w%d, w%d", wd, ws, wt);
16912 t1 = newTemp(Ity_V128);
16913 t2 = newTemp(Ity_V128);
16914 t3 = newTemp(Ity_V128);
16915 assign(t1, getWReg(ws));
16916 assign(t2, getWReg(wt));
16917 assign(t3, binop(Iop_QSub16Sx8, mkexpr(t1), mkexpr(t2)));
16918 putWReg(wd, mkexpr(t3));
16919 break;
16922 case 0x02: { /* SUBS_S.W */
16923 DIP("SUBS_S.W w%d, w%d, w%d", wd, ws, wt);
16924 t1 = newTemp(Ity_V128);
16925 t2 = newTemp(Ity_V128);
16926 t3 = newTemp(Ity_V128);
16927 assign(t1, getWReg(ws));
16928 assign(t2, getWReg(wt));
16929 assign(t3, binop(Iop_QSub32Sx4, mkexpr(t1), mkexpr(t2)));
16930 putWReg(wd, mkexpr(t3));
16931 break;
16934 case 0x03: { /* SUBS_S.D */
16935 DIP("SUBS_S.D w%d, w%d, w%d", wd, ws, wt);
16936 t1 = newTemp(Ity_V128);
16937 t2 = newTemp(Ity_V128);
16938 t3 = newTemp(Ity_V128);
16939 assign(t1, getWReg(ws));
16940 assign(t2, getWReg(wt));
16941 assign(t3, binop(Iop_QSub64Sx2, mkexpr(t1), mkexpr(t2)));
16942 putWReg(wd, mkexpr(t3));
16943 break;
16946 default:
16947 return -1;
16950 break;
16953 case 0x01: { /* SUBS_U.df */
16954 switch (df) {
16955 case 0x00: { /* SUBS_U.B */
16956 DIP("SUBS_U.B w%d, w%d, w%d", wd, ws, wt);
16957 t1 = newTemp(Ity_V128);
16958 t2 = newTemp(Ity_V128);
16959 t3 = newTemp(Ity_V128);
16960 assign(t1, getWReg(ws));
16961 assign(t2, getWReg(wt));
16962 assign(t3, binop(Iop_QSub8Ux16, mkexpr(t1), mkexpr(t2)));
16963 putWReg(wd, mkexpr(t3));
16964 break;
16967 case 0x01: { /* SUBS_U.H */
16968 DIP("SUBS_U.H w%d, w%d, w%d", wd, ws, wt);
16969 t1 = newTemp(Ity_V128);
16970 t2 = newTemp(Ity_V128);
16971 t3 = newTemp(Ity_V128);
16972 assign(t1, getWReg(ws));
16973 assign(t2, getWReg(wt));
16974 assign(t3, binop(Iop_QSub16Ux8, mkexpr(t1), mkexpr(t2)));
16975 putWReg(wd, mkexpr(t3));
16976 break;
16979 case 0x02: { /* SUBS_U.W */
16980 DIP("SUBS_U.W w%d, w%d, w%d", wd, ws, wt);
16981 t1 = newTemp(Ity_V128);
16982 t2 = newTemp(Ity_V128);
16983 t3 = newTemp(Ity_V128);
16984 assign(t1, getWReg(ws));
16985 assign(t2, getWReg(wt));
16986 assign(t3, binop(Iop_QSub32Ux4, mkexpr(t1), mkexpr(t2)));
16987 putWReg(wd, mkexpr(t3));
16988 break;
16991 case 0x03: { /* SUBS_U.D */
16992 DIP("SUBS_U.D w%d, w%d, w%d", wd, ws, wt);
16993 t1 = newTemp(Ity_V128);
16994 t2 = newTemp(Ity_V128);
16995 t3 = newTemp(Ity_V128);
16996 assign(t1, getWReg(ws));
16997 assign(t2, getWReg(wt));
16998 assign(t3, binop(Iop_QSub64Ux2, mkexpr(t1), mkexpr(t2)));
16999 putWReg(wd, mkexpr(t3));
17000 break;
17003 default:
17004 return -1;
17007 break;
17010 case 0x02: { /* SUBSUS_U.df */
17011 switch (df) {
17012 case 0x00: { /* SUBSUS_U.B */
17013 DIP("SUBSUS_U.B w%d, w%d, w%d", wd, ws, wt);
17014 t1 = newTemp(Ity_V128);
17015 t2 = newTemp(Ity_V128);
17016 t3 = newTemp(Ity_V128);
17017 assign(t1, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
17018 assign(t2, binop(Iop_SarN8x16, getWReg(wt), mkU8(7)));
17019 assign(t3, binop(Iop_OrV128,
17020 binop(Iop_CmpGT8Ux16,
17021 getWReg(ws),
17022 getWReg(wt)),
17023 binop(Iop_CmpEQ8x16,
17024 getWReg(ws),
17025 getWReg(wt))));
17026 putWReg(wd,
17027 binop(Iop_OrV128,
17028 binop(Iop_AndV128,
17029 mkexpr(t3), mkexpr(t2)),
17030 binop(Iop_AndV128,
17031 mkexpr(t1),
17032 binop(Iop_XorV128,
17033 mkexpr(t3),
17034 mkexpr(t2)))));
17035 break;
17038 case 0x01: { /* SUBSUS_U.H */
17039 DIP("SUBSUS_U.H w%d, w%d, w%d", wd, ws, wt);
17040 t1 = newTemp(Ity_V128);
17041 t2 = newTemp(Ity_V128);
17042 t3 = newTemp(Ity_V128);
17043 assign(t1, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
17044 assign(t2, binop(Iop_SarN16x8, getWReg(wt), mkU8(15)));
17045 assign(t3,
17046 binop(Iop_OrV128,
17047 binop(Iop_CmpGT16Ux8,
17048 getWReg(ws),
17049 getWReg(wt)),
17050 binop(Iop_CmpEQ16x8,
17051 getWReg(ws),
17052 getWReg(wt))));
17053 putWReg(wd,
17054 binop(Iop_OrV128,
17055 binop(Iop_AndV128,
17056 mkexpr(t3), mkexpr(t2)),
17057 binop(Iop_AndV128,
17058 mkexpr(t1),
17059 binop(Iop_XorV128,
17060 mkexpr(t3),
17061 mkexpr(t2)))));
17062 break;
17065 case 0x02: { /* SUBSUS_U.W */
17066 DIP("SUBSUS_U.W w%d, w%d, w%d", wd, ws, wt);
17067 t1 = newTemp(Ity_V128);
17068 t2 = newTemp(Ity_V128);
17069 t3 = newTemp(Ity_V128);
17070 assign(t1, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
17071 assign(t2, binop(Iop_SarN32x4, getWReg(wt), mkU8(31)));
17072 assign(t3,
17073 binop(Iop_OrV128,
17074 binop(Iop_CmpGT32Ux4,
17075 getWReg(ws),
17076 getWReg(wt)),
17077 binop(Iop_CmpEQ32x4,
17078 getWReg(ws),
17079 getWReg(wt))));
17080 putWReg(wd,
17081 binop(Iop_OrV128,
17082 binop(Iop_AndV128,
17083 mkexpr(t3), mkexpr(t2)),
17084 binop(Iop_AndV128,
17085 mkexpr(t1),
17086 binop(Iop_XorV128,
17087 mkexpr(t3),
17088 mkexpr(t2)))));
17089 break;
17092 case 0x03: { /* SUBSUS_U.D */
17093 DIP("SUBSUS_U.D w%d, w%d, w%d", wd, ws, wt);
17094 t1 = newTemp(Ity_V128);
17095 t2 = newTemp(Ity_V128);
17096 t3 = newTemp(Ity_V128);
17097 assign(t1, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
17098 assign(t2, binop(Iop_SarN64x2, getWReg(wt), mkU8(63)));
17099 assign(t3,
17100 binop(Iop_OrV128,
17101 binop(Iop_CmpGT64Ux2,
17102 getWReg(ws),
17103 getWReg(wt)),
17104 binop(Iop_CmpEQ64x2,
17105 getWReg(ws),
17106 getWReg(wt))));
17107 putWReg(wd,
17108 binop(Iop_OrV128,
17109 binop(Iop_AndV128,
17110 mkexpr(t3), mkexpr(t2)),
17111 binop(Iop_AndV128,
17112 mkexpr(t1),
17113 binop(Iop_XorV128,
17114 mkexpr(t3),
17115 mkexpr(t2)))));
17116 break;
17119 default:
17120 return -1;
17123 break;
17126 case 0x03: { /* SUBSUU_S.df */
17127 switch (df) {
17128 case 0x00: { /* SUBSUU_S.B */
17129 DIP("SUBSUU_S.B w%d, w%d, w%d", wd, ws, wt);
17130 t1 = newTemp(Ity_V128);
17131 t2 = newTemp(Ity_V128);
17132 t3 = newTemp(Ity_V128);
17133 assign(t1, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
17134 assign(t2,
17135 binop(Iop_SarN8x16,
17136 binop (Iop_AndV128,
17137 binop(Iop_XorV128,
17138 getWReg(ws),
17139 getWReg(wt)),
17140 binop(Iop_XorV128,
17141 mkexpr(t1),
17142 getWReg(wt))),
17143 mkU8(7)));
17144 assign(t3,
17145 binop(Iop_AndV128,
17146 binop(Iop_SarN8x16,
17147 getWReg(ws), mkU8(7)),
17148 mkexpr(t2)));
17149 putWReg(wd,
17150 binop(Iop_OrV128,
17151 binop(Iop_AndV128,
17152 mkexpr(t1),
17153 unop(Iop_NotV128,
17154 mkexpr(t2))),
17155 binop(Iop_XorV128,
17156 binop(Iop_ShlN8x16,
17157 mkexpr(t2), mkU8(7)),
17158 mkexpr(t3))));
17159 break;
17162 case 0x01: { /* SUBSUU_S.H */
17163 DIP("SUBSUU_S.H w%d, w%d, w%d", wd, ws, wt);
17164 t1 = newTemp(Ity_V128);
17165 t2 = newTemp(Ity_V128);
17166 t3 = newTemp(Ity_V128);
17167 assign(t1, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
17168 assign(t2,
17169 binop(Iop_SarN16x8,
17170 binop (Iop_AndV128,
17171 binop(Iop_XorV128,
17172 getWReg(ws),
17173 getWReg(wt)),
17174 binop(Iop_XorV128,
17175 mkexpr(t1),
17176 getWReg(wt))),
17177 mkU8(15)));
17178 assign(t3,
17179 binop(Iop_AndV128,
17180 binop(Iop_SarN16x8,
17181 getWReg(ws),
17182 mkU8(15)),
17183 mkexpr(t2)));
17184 putWReg(wd,
17185 binop(Iop_OrV128,
17186 binop(Iop_AndV128,
17187 mkexpr(t1),
17188 unop(Iop_NotV128,
17189 mkexpr(t2))),
17190 binop(Iop_XorV128,
17191 binop(Iop_ShlN16x8,
17192 mkexpr(t2), mkU8(15)),
17193 mkexpr(t3))));
17194 break;
17197 case 0x02: { /* SUBSUU_S.W */
17198 DIP("SUBSUU_S.W w%d, w%d, w%d", wd, ws, wt);
17199 t1 = newTemp(Ity_V128);
17200 t2 = newTemp(Ity_V128);
17201 t3 = newTemp(Ity_V128);
17202 assign(t1, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
17203 assign(t2,
17204 binop(Iop_SarN32x4,
17205 binop (Iop_AndV128,
17206 binop(Iop_XorV128,
17207 getWReg(ws),
17208 getWReg(wt)),
17209 binop(Iop_XorV128,
17210 mkexpr(t1),
17211 getWReg(wt))),
17212 mkU8(31)));
17213 assign(t3,
17214 binop(Iop_AndV128,
17215 binop(Iop_SarN32x4,
17216 getWReg(ws),
17217 mkU8(31)),
17218 mkexpr(t2)));
17219 putWReg(wd,
17220 binop(Iop_OrV128,
17221 binop(Iop_AndV128,
17222 mkexpr(t1),
17223 unop(Iop_NotV128,
17224 mkexpr(t2))),
17225 binop(Iop_XorV128,
17226 binop(Iop_ShlN32x4,
17227 mkexpr(t2),
17228 mkU8(31)),
17229 mkexpr(t3))));
17230 break;
17233 case 0x03: { /* SUBSUU_S.D */
17234 DIP("SUBSUU_S.D w%d, w%d, w%d", wd, ws, wt);
17235 t1 = newTemp(Ity_V128);
17236 t2 = newTemp(Ity_V128);
17237 t3 = newTemp(Ity_V128);
17238 assign(t1, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
17239 assign(t2,
17240 binop(Iop_SarN64x2,
17241 binop (Iop_AndV128,
17242 binop(Iop_XorV128,
17243 getWReg(ws),
17244 getWReg(wt)),
17245 binop(Iop_XorV128,
17246 mkexpr(t1),
17247 getWReg(wt))),
17248 mkU8(63)));
17249 assign(t3,
17250 binop(Iop_AndV128,
17251 binop(Iop_SarN64x2,
17252 getWReg(ws),
17253 mkU8(63)),
17254 mkexpr(t2)));
17255 putWReg(wd,
17256 binop(Iop_OrV128,
17257 binop(Iop_AndV128,
17258 mkexpr(t1),
17259 unop(Iop_NotV128,
17260 mkexpr(t2))),
17261 binop(Iop_XorV128,
17262 binop(Iop_ShlN64x2,
17263 mkexpr(t2), mkU8(63)),
17264 mkexpr(t3))));
17265 break;
17268 default:
17269 return -1;
17272 break;
17275 case 0x04: { /* ASUB_S.df */
17276 switch (df) {
17277 case 0x00: { /* ASUB_S.B */
17278 DIP("ASUB_S.B w%d, w%d, w%d", wd, ws, wt);
17279 t1 = newTemp(Ity_V128);
17280 t2 = newTemp(Ity_V128);
17281 t3 = newTemp(Ity_V128);
17282 assign(t1, binop(Iop_SarN8x16, getWReg(ws), mkU8(7)));
17283 assign(t2, binop(Iop_SarN8x16, getWReg(wt), mkU8(7)));
17284 assign(t3, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
17285 putWReg(wd,
17286 binop(Iop_OrV128,
17287 binop(Iop_OrV128,
17288 binop(Iop_AndV128,
17289 binop(Iop_AndV128,
17290 unop(Iop_NotV128,
17291 mkexpr(t1)),
17292 mkexpr(t2)),
17293 mkexpr(t3)),
17294 binop(Iop_AndV128,
17295 unop(Iop_NotV128,
17296 binop(Iop_XorV128,
17297 mkexpr(t1),
17298 mkexpr(t2))),
17299 unop(Iop_Abs8x16,
17300 mkexpr(t3)))),
17301 binop(Iop_AndV128,
17302 binop(Iop_AndV128,
17303 mkexpr(t1),
17304 unop(Iop_NotV128,
17305 mkexpr(t2))),
17306 binop(Iop_Sub8x16,
17307 getWReg(wt),
17308 getWReg(ws)))));
17309 break;
17312 case 0x01: { /* ASUB_S.H */
17313 DIP("ASUB_S.H w%d, w%d, w%d", wd, ws, wt);
17314 t1 = newTemp(Ity_V128);
17315 t2 = newTemp(Ity_V128);
17316 t3 = newTemp(Ity_V128);
17317 assign(t1, binop(Iop_SarN16x8, getWReg(ws), mkU8(15)));
17318 assign(t2, binop(Iop_SarN16x8, getWReg(wt), mkU8(15)));
17319 assign(t3, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
17320 putWReg(wd,
17321 binop(Iop_OrV128,
17322 binop(Iop_OrV128,
17323 binop(Iop_AndV128,
17324 binop(Iop_AndV128,
17325 unop(Iop_NotV128,
17326 mkexpr(t1)),
17327 mkexpr(t2)),
17328 mkexpr(t3)),
17329 binop(Iop_AndV128,
17330 unop(Iop_NotV128,
17331 binop(Iop_XorV128,
17332 mkexpr(t1),
17333 mkexpr(t2))),
17334 unop(Iop_Abs16x8,
17335 mkexpr(t3)))),
17336 binop(Iop_AndV128,
17337 binop(Iop_AndV128,
17338 mkexpr(t1),
17339 unop(Iop_NotV128,
17340 mkexpr(t2))),
17341 binop(Iop_Sub16x8,
17342 getWReg(wt),
17343 getWReg(ws)))));
17344 break;
17347 case 0x02: { /* ASUB_S.W */
17348 DIP("ASUB_S.W w%d, w%d, w%d", wd, ws, wt);
17349 t1 = newTemp(Ity_V128);
17350 t2 = newTemp(Ity_V128);
17351 t3 = newTemp(Ity_V128);
17352 assign(t1, binop(Iop_SarN32x4, getWReg(ws), mkU8(31)));
17353 assign(t2, binop(Iop_SarN32x4, getWReg(wt), mkU8(31)));
17354 assign(t3, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
17355 putWReg(wd,
17356 binop(Iop_OrV128,
17357 binop(Iop_OrV128,
17358 binop(Iop_AndV128,
17359 binop(Iop_AndV128,
17360 unop(Iop_NotV128,
17361 mkexpr(t1)),
17362 mkexpr(t2)),
17363 mkexpr(t3)),
17364 binop(Iop_AndV128,
17365 unop(Iop_NotV128,
17366 binop(Iop_XorV128,
17367 mkexpr(t1),
17368 mkexpr(t2))),
17369 unop(Iop_Abs32x4,
17370 mkexpr(t3)))),
17371 binop(Iop_AndV128,
17372 binop(Iop_AndV128,
17373 mkexpr(t1),
17374 unop(Iop_NotV128,
17375 mkexpr(t2))),
17376 binop(Iop_Sub32x4,
17377 getWReg(wt),
17378 getWReg(ws)))));
17379 break;
17382 case 0x03: { /* ASUB_S.D */
17383 DIP("ASUB_S.D w%d, w%d, w%d", wd, ws, wt);
17384 t1 = newTemp(Ity_V128);
17385 t2 = newTemp(Ity_V128);
17386 t3 = newTemp(Ity_V128);
17387 assign(t1, binop(Iop_SarN64x2, getWReg(ws), mkU8(63)));
17388 assign(t2, binop(Iop_SarN64x2, getWReg(wt), mkU8(63)));
17389 assign(t3, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
17390 putWReg(wd,
17391 binop(Iop_OrV128,
17392 binop(Iop_OrV128,
17393 binop(Iop_AndV128,
17394 binop(Iop_AndV128,
17395 unop(Iop_NotV128,
17396 mkexpr(t1)),
17397 mkexpr(t2)),
17398 mkexpr(t3)),
17399 binop(Iop_AndV128,
17400 unop(Iop_NotV128,
17401 binop(Iop_XorV128,
17402 mkexpr(t1),
17403 mkexpr(t2))),
17404 unop(Iop_Abs64x2,
17405 mkexpr(t3)))),
17406 binop(Iop_AndV128,
17407 binop(Iop_AndV128,
17408 mkexpr(t1),
17409 unop(Iop_NotV128,
17410 mkexpr(t2))),
17411 binop(Iop_Sub64x2,
17412 getWReg(wt),
17413 getWReg(ws)))));
17414 break;
17417 default:
17418 return -1;
17421 break;
17424 case 0x05: { /* ASUB_U.df */
17425 switch (df) {
17426 case 0x00: { /* ASUB_U.B */
17427 DIP("ASUB_U.B w%d, w%d, w%d", wd, ws, wt);
17428 t1 = newTemp(Ity_V128);
17429 t2 = newTemp(Ity_V128);
17430 t3 = newTemp(Ity_V128);
17431 assign(t1, getWReg(ws));
17432 assign(t2, getWReg(wt));
17433 assign(t3,
17434 binop(Iop_SarN8x16,
17435 binop(Iop_XorV128,
17436 mkexpr(t1), mkexpr(t2)),
17437 mkU8(7)));
17438 putWReg(wd,
17439 binop(Iop_OrV128,
17440 binop(Iop_AndV128,
17441 unop(Iop_NotV128, mkexpr(t3)),
17442 unop(Iop_Abs8x16,
17443 binop(Iop_Sub8x16,
17444 mkexpr(t1),
17445 mkexpr(t2)))),
17446 binop(Iop_AndV128, mkexpr(t3),
17447 binop(Iop_Sub8x16,
17448 binop(Iop_Max8Ux16,
17449 mkexpr(t1),
17450 mkexpr(t2)),
17451 binop(Iop_Min8Ux16,
17452 mkexpr(t1),
17453 mkexpr(t2))))));
17454 break;
17457 case 0x01: { /* ASUB_U.H */
17458 DIP("ASUB_U.H w%d, w%d, w%d", wd, ws, wt);
17459 t1 = newTemp(Ity_V128);
17460 t2 = newTemp(Ity_V128);
17461 t3 = newTemp(Ity_V128);
17462 assign(t1, getWReg(ws));
17463 assign(t2, getWReg(wt));
17464 assign(t3,
17465 binop(Iop_SarN16x8,
17466 binop(Iop_XorV128,
17467 mkexpr(t1), mkexpr(t2)),
17468 mkU8(15)));
17469 putWReg(wd,
17470 binop(Iop_OrV128,
17471 binop(Iop_AndV128,
17472 unop(Iop_NotV128,
17473 mkexpr(t3)),
17474 unop(Iop_Abs16x8,
17475 binop(Iop_Sub16x8,
17476 mkexpr(t1),
17477 mkexpr(t2)))),
17478 binop(Iop_AndV128,
17479 mkexpr(t3),
17480 binop(Iop_Sub16x8,
17481 binop(Iop_Max16Ux8,
17482 mkexpr(t1),
17483 mkexpr(t2)),
17484 binop(Iop_Min16Ux8,
17485 mkexpr(t1),
17486 mkexpr(t2))))));
17487 break;
17490 case 0x02: { /* ASUB_U.W */
17491 DIP("ASUB_U.W w%d, w%d, w%d", wd, ws, wt);
17492 t1 = newTemp(Ity_V128);
17493 t2 = newTemp(Ity_V128);
17494 t3 = newTemp(Ity_V128);
17495 assign(t1, getWReg(ws));
17496 assign(t2, getWReg(wt));
17497 assign(t3,
17498 binop(Iop_SarN32x4,
17499 binop(Iop_XorV128,
17500 mkexpr(t1), mkexpr(t2)),
17501 mkU8(31)));
17502 putWReg(wd,
17503 binop(Iop_OrV128,
17504 binop(Iop_AndV128,
17505 unop(Iop_NotV128, mkexpr(t3)),
17506 unop(Iop_Abs32x4,
17507 binop(Iop_Sub32x4,
17508 mkexpr(t1),
17509 mkexpr(t2)))),
17510 binop(Iop_AndV128,
17511 mkexpr(t3),
17512 binop(Iop_Sub32x4,
17513 binop(Iop_Max32Ux4,
17514 mkexpr(t1),
17515 mkexpr(t2)),
17516 binop(Iop_Min32Ux4,
17517 mkexpr(t1),
17518 mkexpr(t2))))));
17519 break;
17522 case 0x03: { /* ASUB_U.D */
17523 DIP("ASUB_U.D w%d, w%d, w%d", wd, ws, wt);
17524 t1 = newTemp(Ity_V128);
17525 t2 = newTemp(Ity_V128);
17526 t3 = newTemp(Ity_V128);
17527 assign(t1, getWReg(ws));
17528 assign(t2, getWReg(wt));
17529 assign(t3,
17530 binop(Iop_SarN64x2,
17531 binop(Iop_XorV128,
17532 mkexpr(t1), mkexpr(t2)),
17533 mkU8(63)));
17534 putWReg(wd,
17535 binop(Iop_OrV128,
17536 binop(Iop_AndV128,
17537 unop(Iop_NotV128, mkexpr(t3)),
17538 unop(Iop_Abs64x2,
17539 binop(Iop_Sub64x2,
17540 mkexpr(t1),
17541 mkexpr(t2)))),
17542 binop(Iop_AndV128,
17543 mkexpr(t3),
17544 binop(Iop_Sub64x2,
17545 binop(Iop_Max64Ux2,
17546 mkexpr(t1),
17547 mkexpr(t2)),
17548 binop(Iop_Min64Ux2,
17549 mkexpr(t1),
17550 mkexpr(t2))))));
17551 break;
17554 default:
17555 return -1;
17558 break;
17561 default:
17562 return -1;
17565 return 0;
17568 static Int msa_3R_12(UInt cins, UChar wd, UChar ws) { /* 3R (0x12) */
17569 IRTemp t1, t2, t3, t4, t5, t6;
17570 UShort operation;
17571 UChar df, wt;
17573 operation = (cins & 0x03800000) >> 23;
17574 df = (cins & 0x00600000) >> 21;
17575 wt = (cins & 0x001F0000) >> 16;
17577 switch (operation) {
17578 case 0x00: { /* MULV.df */
17579 switch (df) {
17580 case 0x00: { /* MULV.B */
17581 DIP("MULV.B w%d, w%d, w%d", wd, ws, wt);
17582 putWReg(wd, binop(Iop_Mul8x16, getWReg(ws), getWReg(wt)));
17583 break;
17586 case 0x01: { /* MULV.H */
17587 DIP("MULV.H w%d, w%d, w%d", wd, ws, wt);
17588 putWReg(wd, binop(Iop_Mul16x8, getWReg(ws), getWReg(wt)));
17589 break;
17592 case 0x02: { /* MULV.W */
17593 DIP("MULV.W w%d, w%d, w%d", wd, ws, wt);
17594 putWReg(wd, binop(Iop_Mul32x4, getWReg(ws), getWReg(wt)));
17595 break;
17598 case 0x03: { /* MULV.D */
17599 DIP("MULV.D w%d, w%d, w%d", wd, ws, wt);
17600 t1 = newTemp(Ity_V128);
17601 t2 = newTemp(Ity_V128);
17602 assign(t1, getWReg(ws));
17603 assign(t2, getWReg(wt));
17604 putWReg(wd,
17605 binop(Iop_64HLtoV128,
17606 binop(Iop_Mul64,
17607 unop(Iop_V128HIto64,
17608 mkexpr(t1)),
17609 unop(Iop_V128HIto64,
17610 mkexpr(t2))),
17611 binop(Iop_Mul64,
17612 unop(Iop_V128to64,
17613 mkexpr(t1)),
17614 unop(Iop_V128to64,
17615 mkexpr(t2)))));
17616 break;
17619 default:
17620 return -1;
17623 break;
17626 case 0x01: { /* MADDV.df */
17627 switch (df) {
17628 case 0x00: { /* MADDV.B */
17629 DIP("MADDV.B w%d, w%d, w%d", wd, ws, wt);
17630 putWReg(wd,
17631 binop(Iop_Add8x16,
17632 getWReg(wd),
17633 binop(Iop_Mul8x16,
17634 getWReg(ws),
17635 getWReg(wt))));
17636 break;
17639 case 0x01: { /* MADDV.H */
17640 DIP("MADDV.H w%d, w%d, w%d", wd, ws, wt);
17641 putWReg(wd,
17642 binop(Iop_Add16x8,
17643 getWReg(wd),
17644 binop(Iop_Mul16x8,
17645 getWReg(ws),
17646 getWReg(wt))));
17647 break;
17650 case 0x02: { /* MADDV.W */
17651 DIP("MADDV.W w%d, w%d, w%d", wd, ws, wt);
17652 putWReg(wd,
17653 binop(Iop_Add32x4,
17654 getWReg(wd),
17655 binop(Iop_Mul32x4,
17656 getWReg(ws),
17657 getWReg(wt))));
17658 break;
17661 case 0x03: { /* MADDV.D */
17662 DIP("MADDV.D w%d, w%d, w%d", wd, ws, wt);
17663 t1 = newTemp(Ity_V128);
17664 t2 = newTemp(Ity_V128);
17665 assign(t1, getWReg(ws));
17666 assign(t2, getWReg(wt));
17667 putWReg(wd,
17668 binop(Iop_Add64x2,
17669 getWReg(wd),
17670 binop(Iop_64HLtoV128,
17671 binop(Iop_Mul64,
17672 unop(Iop_V128HIto64,
17673 mkexpr(t1)),
17674 unop(Iop_V128HIto64,
17675 mkexpr(t2))),
17676 binop(Iop_Mul64,
17677 unop(Iop_V128to64,
17678 mkexpr(t1)),
17679 unop(Iop_V128to64,
17680 mkexpr(t2))))));
17681 break;
17684 default:
17685 return -1;
17688 break;
17691 case 0x02: { /* MSUBV.df */
17692 switch (df) {
17693 case 0x00: { /* MSUBV.B */
17694 DIP("MSUBV.B w%d, w%d, w%d", wd, ws, wt);
17695 putWReg(wd,
17696 binop(Iop_Sub8x16,
17697 getWReg(wd),
17698 binop(Iop_Mul8x16,
17699 getWReg(ws),
17700 getWReg(wt))));
17701 break;
17704 case 0x01: { /* MSUBV.H */
17705 DIP("MSUBV.H w%d, w%d, w%d", wd, ws, wt);
17706 putWReg(wd,
17707 binop(Iop_Sub16x8,
17708 getWReg(wd),
17709 binop(Iop_Mul16x8,
17710 getWReg(ws),
17711 getWReg(wt))));
17712 break;
17715 case 0x02: { /* MSUBV.W */
17716 DIP("MSUBV.W w%d, w%d, w%d", wd, ws, wt);
17717 putWReg(wd,
17718 binop(Iop_Sub32x4,
17719 getWReg(wd),
17720 binop(Iop_Mul32x4,
17721 getWReg(ws),
17722 getWReg(wt))));
17723 break;
17726 case 0x03: { /* MSUBV.D */
17727 DIP("MSUBV.D w%d, w%d, w%d", wd, ws, wt);
17728 t1 = newTemp(Ity_V128);
17729 t2 = newTemp(Ity_V128);
17730 assign(t1, getWReg(ws));
17731 assign(t2, getWReg(wt));
17732 putWReg(wd,
17733 binop(Iop_Sub64x2,
17734 getWReg(wd),
17735 binop(Iop_64HLtoV128,
17736 binop(Iop_Mul64,
17737 unop(Iop_V128HIto64,
17738 mkexpr(t1)),
17739 unop(Iop_V128HIto64,
17740 mkexpr(t2))),
17741 binop(Iop_Mul64,
17742 unop(Iop_V128to64,
17743 mkexpr(t1)),
17744 unop(Iop_V128to64,
17745 mkexpr(t2))))));
17746 break;
17749 default:
17750 return -1;
17753 break;
17756 case 0x04: { /* DIV_S.df */
17757 t1 = newTemp(Ity_V128);
17758 t2 = newTemp(Ity_V128);
17759 assign(t1, getWReg(ws));
17760 assign(t2, getWReg(wt));
17762 switch (df) {
17763 case 0x00: { /* DIV_S.B */
17764 DIP("DIV_S.B w%d, w%d, w%d", wd, ws, wt);
17765 IRTemp tmp[16];
17766 Int i;
17768 for (i = 0; i < 16; i++) {
17769 tmp[i] = newTemp(Ity_I32);
17770 assign(tmp[i],
17771 binop(Iop_Shl32,
17772 binop(Iop_And32,
17773 mkU32(0xFF),
17774 binop(Iop_DivS32,
17775 unop(Iop_8Sto32,
17776 binop(Iop_GetElem8x16,
17777 mkexpr(t1),
17778 mkU8(i))),
17779 unop(Iop_8Sto32,
17780 binop(Iop_GetElem8x16,
17781 mkexpr(t2),
17782 mkU8(i))))),
17783 mkU8((i & 3) << 3)));
17786 putWReg(wd,
17787 binop(Iop_64HLtoV128,
17788 binop(Iop_32HLto64,
17789 binop(Iop_Or32,
17790 mkexpr(tmp[15]),
17791 binop(Iop_Or32,
17792 mkexpr(tmp[14]),
17793 binop(Iop_Or32,
17794 mkexpr(tmp[13]),
17795 mkexpr(tmp[12])))),
17796 binop(Iop_Or32,
17797 mkexpr(tmp[11]),
17798 binop(Iop_Or32,
17799 mkexpr(tmp[10]),
17800 binop(Iop_Or32,
17801 mkexpr(tmp[9]),
17802 mkexpr(tmp[8]))))),
17803 binop(Iop_32HLto64,
17804 binop(Iop_Or32,
17805 mkexpr(tmp[7]),
17806 binop(Iop_Or32,
17807 mkexpr(tmp[6]),
17808 binop(Iop_Or32,
17809 mkexpr(tmp[5]),
17810 mkexpr(tmp[4])))),
17811 binop(Iop_Or32,
17812 mkexpr(tmp[3]),
17813 binop(Iop_Or32,
17814 mkexpr(tmp[2]),
17815 binop(Iop_Or32,
17816 mkexpr(tmp[1]),
17817 mkexpr(tmp[0]))))))
17819 break;
17822 case 0x01: { /* DIV_S.H */
17823 DIP("DIV_S.H w%d, w%d, w%d", wd, ws, wt);
17824 IRTemp tmp[8];
17825 Int i;
17827 for (i = 0; i < 8; i++) {
17828 tmp[i] = newTemp(Ity_I32);
17829 assign(tmp[i],
17830 binop(Iop_Shl32,
17831 binop(Iop_And32,
17832 mkU32(0xFFFF),
17833 binop(Iop_DivS32,
17834 unop(Iop_16Sto32,
17835 binop(Iop_GetElem16x8,
17836 mkexpr(t1),
17837 mkU8(i))),
17838 unop(Iop_16Sto32,
17839 binop(Iop_GetElem16x8,
17840 mkexpr(t2),
17841 mkU8(i))))),
17842 mkU8((i & 1) << 4)));
17845 putWReg(wd,
17846 binop(Iop_64HLtoV128,
17847 binop(Iop_32HLto64,
17848 binop(Iop_Or32,
17849 mkexpr(tmp[7]),
17850 mkexpr(tmp[6])),
17851 binop(Iop_Or32,
17852 mkexpr(tmp[5]),
17853 mkexpr(tmp[4]))),
17854 binop(Iop_32HLto64,
17855 binop(Iop_Or32,
17856 mkexpr(tmp[3]),
17857 mkexpr(tmp[2])),
17858 binop(Iop_Or32,
17859 mkexpr(tmp[1]),
17860 mkexpr(tmp[0])))));
17861 break;
17864 case 0x02: { /* DIV_S.W */
17865 DIP("DIV_S.W w%d, w%d, w%d", wd, ws, wt);
17866 IRTemp tmp[4];
17867 Int i;
17869 for (i = 0; i < 4; i++) {
17870 tmp[i] = newTemp(Ity_I32);
17871 assign(tmp[i],
17872 binop(Iop_DivS32,
17873 binop(Iop_GetElem32x4,
17874 mkexpr(t1), mkU8(i)),
17875 binop(Iop_GetElem32x4,
17876 mkexpr(t2), mkU8(i))));
17879 putWReg(wd,
17880 binop(Iop_64HLtoV128, \
17881 binop(Iop_32HLto64,
17882 mkexpr(tmp[3]),
17883 mkexpr(tmp[2])),
17884 binop(Iop_32HLto64,
17885 mkexpr(tmp[1]),
17886 mkexpr(tmp[0]))));
17887 break;
17890 case 0x03: { /* DIV_S.D */
17891 DIP("DIV_S.D w%d, w%d, w%d", wd, ws, wt);
17892 putWReg(wd,
17893 binop(Iop_64HLtoV128,
17894 binop(Iop_DivS64,
17895 unop(Iop_V128HIto64,
17896 mkexpr(t1)),
17897 unop(Iop_V128HIto64,
17898 mkexpr(t2))),
17899 binop(Iop_DivS64,
17900 unop(Iop_V128to64,
17901 mkexpr(t1)),
17902 unop(Iop_V128to64,
17903 mkexpr(t2)))));
17904 break;
17907 default:
17908 return -1;
17911 break;
17914 case 0x05: { /* DIV_U.df */
17915 t1 = newTemp(Ity_V128);
17916 t2 = newTemp(Ity_V128);
17917 assign(t1, getWReg(ws));
17918 assign(t2, getWReg(wt));
17920 switch (df) {
17921 case 0x00: { /* DIV_U.B */
17922 DIP("DIV_U.B w%d, w%d, w%d", wd, ws, wt);
17923 IRTemp tmp[16];
17924 Int i;
17926 for (i = 0; i < 16; i++) {
17927 tmp[i] = newTemp(Ity_I32);
17928 assign(tmp[i],
17929 binop(Iop_Shl32,
17930 binop(Iop_And32,
17931 mkU32(0xFF),
17932 binop(Iop_DivU32,
17933 unop(Iop_8Uto32,
17934 binop(Iop_GetElem8x16,
17935 mkexpr(t1),
17936 mkU8(i))),
17937 unop(Iop_8Uto32,
17938 binop(Iop_GetElem8x16,
17939 mkexpr(t2),
17940 mkU8(i))))),
17941 mkU8((i & 3) << 3)));
17944 putWReg(wd,
17945 binop(Iop_64HLtoV128,
17946 binop(Iop_32HLto64,
17947 binop(Iop_Or32,
17948 mkexpr(tmp[15]),
17949 binop(Iop_Or32,
17950 mkexpr(tmp[14]),
17951 binop(Iop_Or32,
17952 mkexpr(tmp[13]),
17953 mkexpr(tmp[12])))),
17954 binop(Iop_Or32,
17955 mkexpr(tmp[11]),
17956 binop(Iop_Or32,
17957 mkexpr(tmp[10]),
17958 binop(Iop_Or32,
17959 mkexpr(tmp[9]),
17960 mkexpr(tmp[8]))))),
17961 binop(Iop_32HLto64,
17962 binop(Iop_Or32,
17963 mkexpr(tmp[7]),
17964 binop(Iop_Or32,
17965 mkexpr(tmp[6]),
17966 binop(Iop_Or32,
17967 mkexpr(tmp[5]),
17968 mkexpr(tmp[4])))),
17969 binop(Iop_Or32,
17970 mkexpr(tmp[3]),
17971 binop(Iop_Or32,
17972 mkexpr(tmp[2]),
17973 binop(Iop_Or32,
17974 mkexpr(tmp[1]),
17975 mkexpr(tmp[0]))))))
17977 break;
17980 case 0x01: { /* DIV_U.H */
17981 DIP("DIV_U.H w%d, w%d, w%d", wd, ws, wt);
17982 IRTemp tmp[8];
17983 Int i;
17985 for (i = 0; i < 8; i++) {
17986 tmp[i] = newTemp(Ity_I32);
17987 assign(tmp[i],
17988 binop(Iop_Shl32,
17989 binop(Iop_And32,
17990 mkU32(0xFFFF),
17991 binop(Iop_DivU32,
17992 unop(Iop_16Uto32,
17993 binop(Iop_GetElem16x8,
17994 mkexpr(t1),
17995 mkU8(i))),
17996 unop(Iop_16Uto32,
17997 binop(Iop_GetElem16x8,
17998 mkexpr(t2),
17999 mkU8(i))))),
18000 mkU8((i & 1) << 4)));
18003 putWReg(wd,
18004 binop(Iop_64HLtoV128,
18005 binop(Iop_32HLto64,
18006 binop(Iop_Or32,
18007 mkexpr(tmp[7]),
18008 mkexpr(tmp[6])),
18009 binop(Iop_Or32,
18010 mkexpr(tmp[5]),
18011 mkexpr(tmp[4]))),
18012 binop(Iop_32HLto64,
18013 binop(Iop_Or32,
18014 mkexpr(tmp[3]),
18015 mkexpr(tmp[2])),
18016 binop(Iop_Or32,
18017 mkexpr(tmp[1]),
18018 mkexpr(tmp[0])))));
18019 break;
18022 case 0x02: { /* DIV_U.W */
18023 DIP("DIV_U.W w%d, w%d, w%d", wd, ws, wt);
18024 IRTemp tmp[4];
18025 Int i;
18027 for (i = 0; i < 4; i++) {
18028 tmp[i] = newTemp(Ity_I32);
18029 assign(tmp[i],
18030 binop(Iop_DivU32,
18031 binop(Iop_GetElem32x4,
18032 mkexpr(t1), mkU8(i)),
18033 binop(Iop_GetElem32x4,
18034 mkexpr(t2), mkU8(i))));
18037 putWReg(wd,
18038 binop(Iop_64HLtoV128,
18039 binop(Iop_32HLto64,
18040 mkexpr(tmp[3]),
18041 mkexpr(tmp[2])),
18042 binop(Iop_32HLto64,
18043 mkexpr(tmp[1]),
18044 mkexpr(tmp[0]))));
18045 break;
18048 case 0x03: { /* DIV_U.D */
18049 DIP("DIV_U.D w%d, w%d, w%d", wd, ws, wt);
18050 putWReg(wd,
18051 binop(Iop_64HLtoV128,
18052 binop(Iop_DivU64,
18053 unop(Iop_V128HIto64,
18054 mkexpr(t1)),
18055 unop(Iop_V128HIto64,
18056 mkexpr(t2))),
18057 binop(Iop_DivU64,
18058 unop(Iop_V128to64,
18059 mkexpr(t1)),
18060 unop(Iop_V128to64,
18061 mkexpr(t2)))));
18062 break;
18065 default:
18066 return -1;
18069 break;
18072 case 0x06: { /* MOD_S.df */
18073 t1 = newTemp(Ity_V128);
18074 t2 = newTemp(Ity_V128);
18075 assign(t1, getWReg(ws));
18076 assign(t2, getWReg(wt));
18078 switch (df) {
18079 case 0x00: { /* MOD_S.B */
18080 DIP("MOD_S.B w%d, w%d, w%d", wd, ws, wt);
18081 IRTemp tmp[16];
18082 Int i;
18084 for (i = 0; i < 16; i++) {
18085 tmp[i] = newTemp(Ity_I32);
18086 assign(tmp[i],
18087 binop(Iop_Shl32,
18088 binop(Iop_And32,
18089 mkU32(0xFF),
18090 unop(Iop_64HIto32,
18091 binop(Iop_DivModS32to32,
18092 unop(Iop_8Sto32,
18093 binop(Iop_GetElem8x16,
18094 mkexpr(t1),
18095 mkU8(i))),
18096 unop(Iop_8Sto32,
18097 binop(Iop_GetElem8x16,
18098 mkexpr(t2),
18099 mkU8(i)))))),
18100 mkU8((i & 3) << 3)));
18103 putWReg(wd,
18104 binop(Iop_64HLtoV128,
18105 binop(Iop_32HLto64,
18106 binop(Iop_Or32,
18107 mkexpr(tmp[15]),
18108 binop(Iop_Or32,
18109 mkexpr(tmp[14]),
18110 binop(Iop_Or32,
18111 mkexpr(tmp[13]),
18112 mkexpr(tmp[12])))),
18113 binop(Iop_Or32,
18114 mkexpr(tmp[11]),
18115 binop(Iop_Or32,
18116 mkexpr(tmp[10]),
18117 binop(Iop_Or32,
18118 mkexpr(tmp[9]),
18119 mkexpr(tmp[8]))))),
18120 binop(Iop_32HLto64,
18121 binop(Iop_Or32,
18122 mkexpr(tmp[7]),
18123 binop(Iop_Or32,
18124 mkexpr(tmp[6]),
18125 binop(Iop_Or32,
18126 mkexpr(tmp[5]),
18127 mkexpr(tmp[4])))),
18128 binop(Iop_Or32,
18129 mkexpr(tmp[3]),
18130 binop(Iop_Or32,
18131 mkexpr(tmp[2]),
18132 binop(Iop_Or32,
18133 mkexpr(tmp[1]),
18134 mkexpr(tmp[0])))))));
18135 break;
18138 case 0x01: { /* MOD_S.H */
18139 DIP("MOD_S.H w%d, w%d, w%d", wd, ws, wt);
18140 IRTemp tmp[8];
18141 Int i;
18143 for (i = 0; i < 8; i++) {
18144 tmp[i] = newTemp(Ity_I32);
18145 assign(tmp[i],
18146 binop(Iop_Shl32,
18147 binop(Iop_And32,
18148 mkU32(0xFFFF),
18149 unop(Iop_64HIto32,
18150 binop(Iop_DivModS32to32,
18151 unop(Iop_16Sto32,
18152 binop(Iop_GetElem16x8,
18153 mkexpr(t1),
18154 mkU8(i))),
18155 unop(Iop_16Sto32,
18156 binop(Iop_GetElem16x8,
18157 mkexpr(t2),
18158 mkU8(i)))))),
18159 mkU8((i & 1) << 4)));
18162 putWReg(wd,
18163 binop(Iop_64HLtoV128,
18164 binop(Iop_32HLto64,
18165 binop(Iop_Or32,
18166 mkexpr(tmp[7]),
18167 mkexpr(tmp[6])),
18168 binop(Iop_Or32,
18169 mkexpr(tmp[5]),
18170 mkexpr(tmp[4]))),
18171 binop(Iop_32HLto64,
18172 binop(Iop_Or32,
18173 mkexpr(tmp[3]),
18174 mkexpr(tmp[2])),
18175 binop(Iop_Or32,
18176 mkexpr(tmp[1]),
18177 mkexpr(tmp[0])))));
18178 break;
18181 case 0x02: { /* MOD_S.W */
18182 DIP("MOD_S.W w%d, w%d, w%d", wd, ws, wt);
18183 IRTemp tmp[4];
18184 Int i;
18186 for (i = 0; i < 4; i++) {
18187 tmp[i] = newTemp(Ity_I32);
18188 assign(tmp[i],
18189 unop(Iop_64HIto32,
18190 binop(Iop_DivModS32to32,
18191 binop(Iop_GetElem32x4,
18192 mkexpr(t1),
18193 mkU8(i)),
18194 binop(Iop_GetElem32x4,
18195 mkexpr(t2),
18196 mkU8(i)))));
18199 putWReg(wd,
18200 binop(Iop_64HLtoV128,
18201 binop(Iop_32HLto64,
18202 mkexpr(tmp[3]),
18203 mkexpr(tmp[2])),
18204 binop(Iop_32HLto64,
18205 mkexpr(tmp[1]),
18206 mkexpr(tmp[0]))));
18207 break;
18210 case 0x03: { /* MOD_S.D */
18211 DIP("MOD_S.D w%d, w%d, w%d", wd, ws, wt);
18212 t3 = newTemp(Ity_I64);
18213 t4 = newTemp(Ity_I64);
18214 t5 = newTemp(Ity_I64);
18215 t6 = newTemp(Ity_I64);
18216 assign(t3, unop(Iop_V128HIto64, mkexpr(t1)));
18217 assign(t4, unop(Iop_V128HIto64, mkexpr(t2)));
18218 assign(t5, unop(Iop_V128to64, mkexpr(t1)));
18219 assign(t6, unop(Iop_V128to64, mkexpr(t2)));
18220 putWReg(wd,
18221 binop(Iop_64HLtoV128,
18222 binop(Iop_Sub64,
18223 mkexpr(t3),
18224 binop(Iop_Mul64,
18225 mkexpr(t4),
18226 binop(Iop_DivS64,
18227 mkexpr(t3),
18228 mkexpr(t4)))),
18229 binop(Iop_Sub64,
18230 mkexpr(t5),
18231 binop(Iop_Mul64,
18232 mkexpr(t6),
18233 binop(Iop_DivS64,
18234 mkexpr(t5),
18235 mkexpr(t6))))));
18236 break;
18239 default:
18240 return -1;
18243 break;
18246 case 0x07: { /* MOD_U.df */
18247 t1 = newTemp(Ity_V128);
18248 t2 = newTemp(Ity_V128);
18249 assign(t1, getWReg(ws));
18250 assign(t2, getWReg(wt));
18252 switch (df) {
18253 case 0x00: { /* MOD_U.B */
18254 DIP("MOD_U.B w%d, w%d, w%d", wd, ws, wt);
18255 IRTemp tmp[16];
18256 Int i;
18258 for (i = 0; i < 16; i++) {
18259 tmp[i] = newTemp(Ity_I32);
18260 assign(tmp[i],
18261 binop(Iop_Shl32,
18262 binop(Iop_And32,
18263 mkU32(0xFF),
18264 unop(Iop_64HIto32,
18265 binop(Iop_DivModU32to32,
18266 unop(Iop_8Uto32,
18267 binop(Iop_GetElem8x16,
18268 mkexpr(t1),
18269 mkU8(i))),
18270 unop(Iop_8Uto32,
18271 binop(Iop_GetElem8x16,
18272 mkexpr(t2),
18273 mkU8(i)))))),
18274 mkU8((i & 3) << 3)));
18277 putWReg(wd,
18278 binop(Iop_64HLtoV128,
18279 binop(Iop_32HLto64,
18280 binop(Iop_Or32,
18281 mkexpr(tmp[15]),
18282 binop(Iop_Or32,
18283 mkexpr(tmp[14]),
18284 binop(Iop_Or32,
18285 mkexpr(tmp[13]),
18286 mkexpr(tmp[12])))),
18287 binop(Iop_Or32,
18288 mkexpr(tmp[11]),
18289 binop(Iop_Or32,
18290 mkexpr(tmp[10]),
18291 binop(Iop_Or32,
18292 mkexpr(tmp[9]),
18293 mkexpr(tmp[8]))))),
18294 binop(Iop_32HLto64,
18295 binop(Iop_Or32,
18296 mkexpr(tmp[7]),
18297 binop(Iop_Or32,
18298 mkexpr(tmp[6]),
18299 binop(Iop_Or32,
18300 mkexpr(tmp[5]),
18301 mkexpr(tmp[4])))),
18302 binop(Iop_Or32,
18303 mkexpr(tmp[3]),
18304 binop(Iop_Or32,
18305 mkexpr(tmp[2]),
18306 binop(Iop_Or32,
18307 mkexpr(tmp[1]),
18308 mkexpr(tmp[0])))))));
18309 break;
18312 case 0x01: { /* MOD_U.H */
18313 DIP("MOD_U.H w%d, w%d, w%d", wd, ws, wt);
18314 IRTemp tmp[8];
18315 Int i;
18317 for (i = 0; i < 8; i++) {
18318 tmp[i] = newTemp(Ity_I32);
18319 assign(tmp[i],
18320 binop(Iop_Shl32,
18321 binop(Iop_And32,
18322 mkU32(0xFFFF),
18323 unop(Iop_64HIto32,
18324 binop(Iop_DivModU32to32,
18325 unop(Iop_16Uto32,
18326 binop(Iop_GetElem16x8,
18327 mkexpr(t1),
18328 mkU8(i))),
18329 unop(Iop_16Uto32,
18330 binop(Iop_GetElem16x8,
18331 mkexpr(t2),
18332 mkU8(i)))))),
18333 mkU8((i & 1) << 4)));
18336 putWReg(wd,
18337 binop(Iop_64HLtoV128,
18338 binop(Iop_32HLto64,
18339 binop(Iop_Or32,
18340 mkexpr(tmp[7]),
18341 mkexpr(tmp[6])),
18342 binop(Iop_Or32,
18343 mkexpr(tmp[5]),
18344 mkexpr(tmp[4]))),
18345 binop(Iop_32HLto64,
18346 binop(Iop_Or32,
18347 mkexpr(tmp[3]),
18348 mkexpr(tmp[2])),
18349 binop(Iop_Or32,
18350 mkexpr(tmp[1]),
18351 mkexpr(tmp[0])))));
18352 break;
18355 case 0x02: { /* MOD_U.W */
18356 DIP("MOD_U.W w%d, w%d, w%d", wd, ws, wt);
18357 IRTemp tmp[4];
18358 Int i;
18360 for (i = 0; i < 4; i++) {
18361 tmp[i] = newTemp(Ity_I32);
18362 assign(tmp[i],
18363 unop(Iop_64HIto32,
18364 binop(Iop_DivModU32to32,
18365 binop(Iop_GetElem32x4,
18366 mkexpr(t1),
18367 mkU8(i)),
18368 binop(Iop_GetElem32x4,
18369 mkexpr(t2),
18370 mkU8(i)))));
18373 putWReg(wd,
18374 binop(Iop_64HLtoV128,
18375 binop(Iop_32HLto64,
18376 mkexpr(tmp[3]),
18377 mkexpr(tmp[2])),
18378 binop(Iop_32HLto64,
18379 mkexpr(tmp[1]),
18380 mkexpr(tmp[0]))));
18381 break;
18384 case 0x03: { /* MOD_U.D */
18385 DIP("MOD_U.D w%d, w%d, w%d", wd, ws, wt);
18386 t3 = newTemp(Ity_I64);
18387 t4 = newTemp(Ity_I64);
18388 t5 = newTemp(Ity_I64);
18389 t6 = newTemp(Ity_I64);
18390 assign(t3, unop(Iop_V128HIto64, mkexpr(t1)));
18391 assign(t4, unop(Iop_V128HIto64, mkexpr(t2)));
18392 assign(t5, unop(Iop_V128to64, mkexpr(t1)));
18393 assign(t6, unop(Iop_V128to64, mkexpr(t2)));
18394 putWReg(wd,
18395 binop(Iop_64HLtoV128,
18396 binop(Iop_Sub64,
18397 mkexpr(t3),
18398 binop(Iop_Mul64,
18399 mkexpr(t4),
18400 binop(Iop_DivU64,
18401 mkexpr(t3),
18402 mkexpr(t4)))),
18403 binop(Iop_Sub64,
18404 mkexpr(t5),
18405 binop(Iop_Mul64,
18406 mkexpr(t6),
18407 binop(Iop_DivU64,
18408 mkexpr(t5),
18409 mkexpr(t6))))));
18410 break;
18413 default:
18414 return -1;
18417 break;
18420 default:
18421 return -1;
18424 return 0;
18427 static Int msa_3R_13(UInt cins, UChar wd, UChar ws) { /* 3R (0x13) */
18428 IRTemp t1, t2;
18429 UShort operation;
18430 UChar df, wt;
18432 operation = (cins & 0x03800000) >> 23;
18433 df = (cins & 0x00600000) >> 21;
18434 wt = (cins & 0x001F0000) >> 16;
18436 switch (operation) {
18437 case 0x00: { /* DOTP_S.df */
18438 t1 = newTemp(Ity_V128);
18439 t2 = newTemp(Ity_V128);
18440 assign(t1, getWReg(ws));
18441 assign(t2, getWReg(wt));
18443 switch (df) {
18444 case 0x01: { /* DOTP_S.H */
18445 DIP("DOTP_S.H w%d, w%d, w%d", wd, ws, wt);
18446 IRTemp tmp[8];
18447 Int i;
18449 for (i = 0; i < 8; i++) {
18450 tmp[i] = newTemp(Ity_I16);
18451 assign(tmp[i],
18452 binop(Iop_Add16,
18453 binop(Iop_MullS8,
18454 binop(Iop_GetElem8x16,
18455 mkexpr(t1),
18456 mkU8(2 * i)),
18457 binop(Iop_GetElem8x16,
18458 mkexpr(t2),
18459 mkU8(2 * i))),
18460 binop(Iop_MullS8,
18461 binop(Iop_GetElem8x16,
18462 mkexpr(t1),
18463 mkU8(2 * i + 1)),
18464 binop(Iop_GetElem8x16,
18465 mkexpr(t2),
18466 mkU8(2 * i + 1)))));
18469 putWReg(wd,
18470 binop(Iop_64HLtoV128,
18471 binop(Iop_32HLto64,
18472 binop(Iop_16HLto32,
18473 mkexpr(tmp[7]),
18474 mkexpr(tmp[6])),
18475 binop(Iop_16HLto32,
18476 mkexpr(tmp[5]),
18477 mkexpr(tmp[4]))),
18478 binop(Iop_32HLto64,
18479 binop(Iop_16HLto32,
18480 mkexpr(tmp[3]),
18481 mkexpr(tmp[2])),
18482 binop(Iop_16HLto32,
18483 mkexpr(tmp[1]),
18484 mkexpr(tmp[0])))));
18485 break;
18488 case 0x02: { /* DOTP_S.W */
18489 DIP("DOTP_S.W w%d, w%d, w%d", wd, ws, wt);
18490 IRTemp tmp[4];
18491 Int i;
18493 for (i = 0; i < 4; i++) {
18494 tmp[i] = newTemp(Ity_I32);
18495 assign(tmp[i],
18496 binop(Iop_Add32,
18497 binop(Iop_MullS16,
18498 binop(Iop_GetElem16x8,
18499 mkexpr(t1),
18500 mkU8(2 * i)),
18501 binop(Iop_GetElem16x8,
18502 mkexpr(t2),
18503 mkU8(2 * i))),
18504 binop(Iop_MullS16,
18505 binop(Iop_GetElem16x8,
18506 mkexpr(t1),
18507 mkU8(2 * i + 1)),
18508 binop(Iop_GetElem16x8,
18509 mkexpr(t2),
18510 mkU8(2 * i + 1)))));
18513 putWReg(wd,
18514 binop(Iop_64HLtoV128,
18515 binop(Iop_32HLto64,
18516 mkexpr(tmp[3]),
18517 mkexpr(tmp[2])),
18518 binop(Iop_32HLto64,
18519 mkexpr(tmp[1]),
18520 mkexpr(tmp[0]))));
18521 break;
18524 case 0x03: { /* DOTP_S.D */
18525 DIP("DOTP_S.D w%d, w%d, w%d", wd, ws, wt);
18526 IRTemp tmp[2];
18527 Int i;
18529 for (i = 0; i < 2; i++) {
18530 tmp[i] = newTemp(Ity_I64);
18531 assign(tmp[i],
18532 binop(Iop_Add64,
18533 binop(Iop_MullS32,
18534 binop(Iop_GetElem32x4,
18535 mkexpr(t1),
18536 mkU8(2 * i)),
18537 binop(Iop_GetElem32x4,
18538 mkexpr(t2),
18539 mkU8(2 * i))),
18540 binop(Iop_MullS32,
18541 binop(Iop_GetElem32x4,
18542 mkexpr(t1),
18543 mkU8(2 * i + 1)),
18544 binop(Iop_GetElem32x4,
18545 mkexpr(t2),
18546 mkU8(2 * i + 1)))));
18549 putWReg(wd,
18550 binop(Iop_64HLtoV128,
18551 mkexpr(tmp[1]), mkexpr(tmp[0])));
18552 break;
18555 default:
18556 return -1;
18559 break;
18562 case 0x01: { /* DOTP_U.df */
18563 t1 = newTemp(Ity_V128);
18564 t2 = newTemp(Ity_V128);
18565 assign(t1, getWReg(ws));
18566 assign(t2, getWReg(wt));
18568 switch (df) {
18569 case 0x01: { /* DOTP_U.H */
18570 DIP("DOTP_U.H w%d, w%d, w%d", wd, ws, wt);
18571 IRTemp tmp[8];
18572 Int i;
18574 for (i = 0; i < 8; i++) {
18575 tmp[i] = newTemp(Ity_I16);
18576 assign(tmp[i],
18577 binop(Iop_Add16,
18578 binop(Iop_MullU8,
18579 binop(Iop_GetElem8x16,
18580 mkexpr(t1),
18581 mkU8(2 * i)),
18582 binop(Iop_GetElem8x16,
18583 mkexpr(t2),
18584 mkU8(2 * i))),
18585 binop(Iop_MullU8,
18586 binop(Iop_GetElem8x16,
18587 mkexpr(t1),
18588 mkU8(2 * i + 1)),
18589 binop(Iop_GetElem8x16,
18590 mkexpr(t2),
18591 mkU8(2 * i + 1)))));
18594 putWReg(wd,
18595 binop(Iop_64HLtoV128,
18596 binop(Iop_32HLto64,
18597 binop(Iop_16HLto32,
18598 mkexpr(tmp[7]),
18599 mkexpr(tmp[6])),
18600 binop(Iop_16HLto32,
18601 mkexpr(tmp[5]),
18602 mkexpr(tmp[4]))),
18603 binop(Iop_32HLto64,
18604 binop(Iop_16HLto32,
18605 mkexpr(tmp[3]),
18606 mkexpr(tmp[2])),
18607 binop(Iop_16HLto32,
18608 mkexpr(tmp[1]),
18609 mkexpr(tmp[0])))));
18610 break;
18613 case 0x02: { /* DOTP_U.W */
18614 DIP("DOTP_U.W w%d, w%d, w%d", wd, ws, wt);
18615 IRTemp tmp[4];
18616 Int i;
18618 for (i = 0; i < 4; i++) {
18619 tmp[i] = newTemp(Ity_I32);
18620 assign(tmp[i],
18621 binop(Iop_Add32,
18622 binop(Iop_MullU16,
18623 binop(Iop_GetElem16x8,
18624 mkexpr(t1),
18625 mkU8(2 * i)),
18626 binop(Iop_GetElem16x8,
18627 mkexpr(t2),
18628 mkU8(2 * i))),
18629 binop(Iop_MullU16,
18630 binop(Iop_GetElem16x8,
18631 mkexpr(t1),
18632 mkU8(2 * i + 1)),
18633 binop(Iop_GetElem16x8,
18634 mkexpr(t2),
18635 mkU8(2 * i + 1)))));
18638 putWReg(wd,
18639 binop(Iop_64HLtoV128,
18640 binop(Iop_32HLto64,
18641 mkexpr(tmp[3]),
18642 mkexpr(tmp[2])),
18643 binop(Iop_32HLto64,
18644 mkexpr(tmp[1]),
18645 mkexpr(tmp[0]))));
18646 break;
18649 case 0x03: { /* DOTP_U.D */
18650 DIP("DOTP_U.D w%d, w%d, w%d", wd, ws, wt);
18651 IRTemp tmp[2];
18652 Int i;
18654 for (i = 0; i < 2; i++) {
18655 tmp[i] = newTemp(Ity_I64);
18656 assign(tmp[i],
18657 binop(Iop_Add64,
18658 binop(Iop_MullU32,
18659 binop(Iop_GetElem32x4,
18660 mkexpr(t1),
18661 mkU8(2 * i)),
18662 binop(Iop_GetElem32x4,
18663 mkexpr(t2),
18664 mkU8(2 * i))),
18665 binop(Iop_MullU32,
18666 binop(Iop_GetElem32x4,
18667 mkexpr(t1),
18668 mkU8(2 * i + 1)),
18669 binop(Iop_GetElem32x4,
18670 mkexpr(t2),
18671 mkU8(2 * i + 1)))));
18674 putWReg(wd,
18675 binop(Iop_64HLtoV128,
18676 mkexpr(tmp[1]), mkexpr(tmp[0])));
18677 break;
18680 default:
18681 return -1;
18684 break;
18687 case 0x02: { /* DPADD_S.df */
18688 t1 = newTemp(Ity_V128);
18689 t2 = newTemp(Ity_V128);
18690 assign(t1, getWReg(ws));
18691 assign(t2, getWReg(wt));
18693 switch (df) {
18694 case 0x01: { /* DPADD_S.H */
18695 DIP("DPADD_S.H w%d, w%d, w%d", wd, ws, wt);
18696 IRTemp tmp[8];
18697 Int i;
18699 for (i = 0; i < 8; i++) {
18700 tmp[i] = newTemp(Ity_I16);
18701 assign(tmp[i],
18702 binop(Iop_Add16,
18703 binop(Iop_MullS8,
18704 binop(Iop_GetElem8x16,
18705 mkexpr(t1),
18706 mkU8(2 * i)),
18707 binop(Iop_GetElem8x16,
18708 mkexpr(t2),
18709 mkU8(2 * i))),
18710 binop(Iop_MullS8,
18711 binop(Iop_GetElem8x16,
18712 mkexpr(t1),
18713 mkU8(2 * i + 1)),
18714 binop(Iop_GetElem8x16,
18715 mkexpr(t2),
18716 mkU8(2 * i + 1)))));
18719 putWReg(wd,
18720 binop(Iop_Add16x8,
18721 getWReg(wd),
18722 binop(Iop_64HLtoV128,
18723 binop(Iop_32HLto64,
18724 binop(Iop_16HLto32,
18725 mkexpr(tmp[7]),
18726 mkexpr(tmp[6])),
18727 binop(Iop_16HLto32,
18728 mkexpr(tmp[5]),
18729 mkexpr(tmp[4]))),
18730 binop(Iop_32HLto64,
18731 binop(Iop_16HLto32,
18732 mkexpr(tmp[3]),
18733 mkexpr(tmp[2])),
18734 binop(Iop_16HLto32,
18735 mkexpr(tmp[1]),
18736 mkexpr(tmp[0]))))));
18737 break;
18740 case 0x02: { /* DPADD_S.W */
18741 DIP("DPADD_S.W w%d, w%d, w%d", wd, ws, wt);
18742 IRTemp tmp[4];
18743 Int i;
18745 for (i = 0; i < 4; i++) {
18746 tmp[i] = newTemp(Ity_I32);
18747 assign(tmp[i],
18748 binop(Iop_Add32,
18749 binop(Iop_MullS16,
18750 binop(Iop_GetElem16x8,
18751 mkexpr(t1),
18752 mkU8(2 * i)),
18753 binop(Iop_GetElem16x8,
18754 mkexpr(t2),
18755 mkU8(2 * i))),
18756 binop(Iop_MullS16,
18757 binop(Iop_GetElem16x8,
18758 mkexpr(t1),
18759 mkU8(2 * i + 1)),
18760 binop(Iop_GetElem16x8,
18761 mkexpr(t2),
18762 mkU8(2 * i + 1)))));
18765 putWReg(wd,
18766 binop(Iop_Add32x4,
18767 getWReg(wd),
18768 binop(Iop_64HLtoV128,
18769 binop(Iop_32HLto64,
18770 mkexpr(tmp[3]),
18771 mkexpr(tmp[2])),
18772 binop(Iop_32HLto64,
18773 mkexpr(tmp[1]),
18774 mkexpr(tmp[0])))));
18775 break;
18778 case 0x03: { /* DPADD_S.D */
18779 DIP("DPADD_S.D w%d, w%d, w%d", wd, ws, wt);
18780 IRTemp tmp[2];
18781 Int i;
18783 for (i = 0; i < 2; i++) {
18784 tmp[i] = newTemp(Ity_I64);
18785 assign(tmp[i],
18786 binop(Iop_Add64,
18787 binop(Iop_MullS32,
18788 binop(Iop_GetElem32x4,
18789 mkexpr(t1),
18790 mkU8(2 * i)),
18791 binop(Iop_GetElem32x4,
18792 mkexpr(t2),
18793 mkU8(2 * i))),
18794 binop(Iop_MullS32,
18795 binop(Iop_GetElem32x4,
18796 mkexpr(t1),
18797 mkU8(2 * i + 1)),
18798 binop(Iop_GetElem32x4,
18799 mkexpr(t2),
18800 mkU8(2 * i + 1)))));
18803 putWReg(wd,
18804 binop(Iop_Add64x2,
18805 getWReg(wd),
18806 binop(Iop_64HLtoV128,
18807 mkexpr(tmp[1]),
18808 mkexpr(tmp[0]))));
18809 break;
18812 default:
18813 return -1;
18816 break;
18819 case 0x03: { /* DPADD_U.df */
18820 t1 = newTemp(Ity_V128);
18821 t2 = newTemp(Ity_V128);
18822 assign(t1, getWReg(ws));
18823 assign(t2, getWReg(wt));
18825 switch (df) {
18826 case 0x01: { /* DPADD_U.H */
18827 DIP("DPADD_U.H w%d, w%d, w%d", wd, ws, wt);
18828 IRTemp tmp[8];
18829 Int i;
18831 for (i = 0; i < 8; i++) {
18832 tmp[i] = newTemp(Ity_I16);
18833 assign(tmp[i],
18834 binop(Iop_Add16,
18835 binop(Iop_MullU8,
18836 binop(Iop_GetElem8x16,
18837 mkexpr(t1),
18838 mkU8(2 * i)),
18839 binop(Iop_GetElem8x16,
18840 mkexpr(t2),
18841 mkU8(2 * i))),
18842 binop(Iop_MullU8,
18843 binop(Iop_GetElem8x16,
18844 mkexpr(t1),
18845 mkU8(2 * i + 1)),
18846 binop(Iop_GetElem8x16,
18847 mkexpr(t2),
18848 mkU8(2 * i + 1)))));
18851 putWReg(wd,
18852 binop(Iop_Add16x8,
18853 getWReg(wd),
18854 binop(Iop_64HLtoV128,
18855 binop(Iop_32HLto64,
18856 binop(Iop_16HLto32,
18857 mkexpr(tmp[7]),
18858 mkexpr(tmp[6])),
18859 binop(Iop_16HLto32,
18860 mkexpr(tmp[5]),
18861 mkexpr(tmp[4]))),
18862 binop(Iop_32HLto64,
18863 binop(Iop_16HLto32,
18864 mkexpr(tmp[3]),
18865 mkexpr(tmp[2])),
18866 binop(Iop_16HLto32,
18867 mkexpr(tmp[1]),
18868 mkexpr(tmp[0]))))));
18869 break;
18872 case 0x02: { /* DPADD_U.W */
18873 DIP("DPADD_U.W w%d, w%d, w%d", wd, ws, wt);
18874 IRTemp tmp[4];
18875 Int i;
18877 for (i = 0; i < 4; i++) {
18878 tmp[i] = newTemp(Ity_I32);
18879 assign(tmp[i],
18880 binop(Iop_Add32,
18881 binop(Iop_MullU16,
18882 binop(Iop_GetElem16x8,
18883 mkexpr(t1),
18884 mkU8(2 * i)),
18885 binop(Iop_GetElem16x8,
18886 mkexpr(t2),
18887 mkU8(2 * i))),
18888 binop(Iop_MullU16,
18889 binop(Iop_GetElem16x8,
18890 mkexpr(t1),
18891 mkU8(2 * i + 1)),
18892 binop(Iop_GetElem16x8,
18893 mkexpr(t2),
18894 mkU8(2 * i + 1)))));
18897 putWReg(wd,
18898 binop(Iop_Add32x4,
18899 getWReg(wd),
18900 binop(Iop_64HLtoV128,
18901 binop(Iop_32HLto64,
18902 mkexpr(tmp[3]),
18903 mkexpr(tmp[2])),
18904 binop(Iop_32HLto64,
18905 mkexpr(tmp[1]),
18906 mkexpr(tmp[0])))));
18907 break;
18910 case 0x03: { /* DPADD_U.D */
18911 DIP("DPADD_U.D w%d, w%d, w%d", wd, ws, wt);
18912 IRTemp tmp[2];
18913 Int i;
18915 for (i = 0; i < 2; i++) {
18916 tmp[i] = newTemp(Ity_I64);
18917 assign(tmp[i],
18918 binop(Iop_Add64,
18919 binop(Iop_MullU32,
18920 binop(Iop_GetElem32x4,
18921 mkexpr(t1),
18922 mkU8(2 * i)),
18923 binop(Iop_GetElem32x4,
18924 mkexpr(t2),
18925 mkU8(2 * i))),
18926 binop(Iop_MullU32,
18927 binop(Iop_GetElem32x4,
18928 mkexpr(t1),
18929 mkU8(2 * i + 1)),
18930 binop(Iop_GetElem32x4,
18931 mkexpr(t2),
18932 mkU8(2 * i + 1)))));
18935 putWReg(wd,
18936 binop(Iop_Add64x2,
18937 getWReg(wd),
18938 binop(Iop_64HLtoV128,
18939 mkexpr(tmp[1]),
18940 mkexpr(tmp[0]))));
18941 break;
18944 default:
18945 return -1;
18948 break;
18951 case 0x04: { /* DPSUB_S.df */
18952 t1 = newTemp(Ity_V128);
18953 t2 = newTemp(Ity_V128);
18954 assign(t1, getWReg(ws));
18955 assign(t2, getWReg(wt));
18957 switch (df) {
18958 case 0x01: { /* DPSUB_S.H */
18959 DIP("DPSUB_S.H w%d, w%d, w%d", wd, ws, wt);
18960 IRTemp tmp[8];
18961 Int i;
18963 for (i = 0; i < 8; i++) {
18964 tmp[i] = newTemp(Ity_I16);
18965 assign(tmp[i],
18966 binop(Iop_Add16,
18967 binop(Iop_MullS8,
18968 binop(Iop_GetElem8x16,
18969 mkexpr(t1),
18970 mkU8(2 * i)),
18971 binop(Iop_GetElem8x16,
18972 mkexpr(t2),
18973 mkU8(2 * i))),
18974 binop(Iop_MullS8,
18975 binop(Iop_GetElem8x16,
18976 mkexpr(t1),
18977 mkU8(2 * i + 1)),
18978 binop(Iop_GetElem8x16,
18979 mkexpr(t2),
18980 mkU8(2 * i + 1)))));
18983 putWReg(wd,
18984 binop(Iop_Sub16x8,
18985 getWReg(wd),
18986 binop(Iop_64HLtoV128,
18987 binop(Iop_32HLto64,
18988 binop(Iop_16HLto32,
18989 mkexpr(tmp[7]),
18990 mkexpr(tmp[6])),
18991 binop(Iop_16HLto32,
18992 mkexpr(tmp[5]),
18993 mkexpr(tmp[4]))),
18994 binop(Iop_32HLto64,
18995 binop(Iop_16HLto32,
18996 mkexpr(tmp[3]),
18997 mkexpr(tmp[2])),
18998 binop(Iop_16HLto32,
18999 mkexpr(tmp[1]),
19000 mkexpr(tmp[0]))))));
19001 break;
19004 case 0x02: { /* DPSUB_S.W */
19005 DIP("DPSUB_S.W w%d, w%d, w%d", wd, ws, wt);
19006 IRTemp tmp[4];
19007 Int i;
19009 for (i = 0; i < 4; i++) {
19010 tmp[i] = newTemp(Ity_I32);
19011 assign(tmp[i],
19012 binop(Iop_Add32,
19013 binop(Iop_MullS16,
19014 binop(Iop_GetElem16x8,
19015 mkexpr(t1),
19016 mkU8(2 * i)),
19017 binop(Iop_GetElem16x8,
19018 mkexpr(t2),
19019 mkU8(2 * i))),
19020 binop(Iop_MullS16,
19021 binop(Iop_GetElem16x8,
19022 mkexpr(t1),
19023 mkU8(2 * i + 1)),
19024 binop(Iop_GetElem16x8,
19025 mkexpr(t2),
19026 mkU8(2 * i + 1)))));
19029 putWReg(wd,
19030 binop(Iop_Sub32x4,
19031 getWReg(wd),
19032 binop(Iop_64HLtoV128,
19033 binop(Iop_32HLto64,
19034 mkexpr(tmp[3]),
19035 mkexpr(tmp[2])),
19036 binop(Iop_32HLto64,
19037 mkexpr(tmp[1]),
19038 mkexpr(tmp[0])))));
19039 break;
19042 case 0x03: { /* DPSUB_S.D */
19043 DIP("DPSUB_S.D w%d, w%d, w%d", wd, ws, wt);
19044 IRTemp tmp[2];
19045 Int i;
19047 for (i = 0; i < 2; i++) {
19048 tmp[i] = newTemp(Ity_I64);
19049 assign(tmp[i],
19050 binop(Iop_Add64,
19051 binop(Iop_MullS32,
19052 binop(Iop_GetElem32x4,
19053 mkexpr(t1),
19054 mkU8(2 * i)),
19055 binop(Iop_GetElem32x4,
19056 mkexpr(t2),
19057 mkU8(2 * i))),
19058 binop(Iop_MullS32,
19059 binop(Iop_GetElem32x4,
19060 mkexpr(t1),
19061 mkU8(2 * i + 1)),
19062 binop(Iop_GetElem32x4,
19063 mkexpr(t2),
19064 mkU8(2 * i + 1)))));
19067 putWReg(wd,
19068 binop(Iop_Sub64x2,
19069 getWReg(wd),
19070 binop(Iop_64HLtoV128,
19071 mkexpr(tmp[1]),
19072 mkexpr(tmp[0]))));
19073 break;
19076 default:
19077 return -1;
19080 break;
19083 case 0x05: { /* DPSUB_U.df */
19084 t1 = newTemp(Ity_V128);
19085 t2 = newTemp(Ity_V128);
19086 assign(t1, getWReg(ws));
19087 assign(t2, getWReg(wt));
19089 switch (df) {
19090 case 0x01: { /* DPSUB_U.H */
19091 DIP("DPSUB_U.H w%d, w%d, w%d", wd, ws, wt);
19092 IRTemp tmp[8];
19093 Int i;
19095 for (i = 0; i < 8; i++) {
19096 tmp[i] = newTemp(Ity_I16);
19097 assign(tmp[i],
19098 binop(Iop_Add16,
19099 binop(Iop_MullU8,
19100 binop(Iop_GetElem8x16,
19101 mkexpr(t1),
19102 mkU8(2 * i)),
19103 binop(Iop_GetElem8x16,
19104 mkexpr(t2),
19105 mkU8(2 * i))),
19106 binop(Iop_MullU8,
19107 binop(Iop_GetElem8x16,
19108 mkexpr(t1),
19109 mkU8(2 * i + 1)),
19110 binop(Iop_GetElem8x16,
19111 mkexpr(t2),
19112 mkU8(2 * i + 1)))));
19115 putWReg(wd,
19116 binop(Iop_Sub16x8,
19117 getWReg(wd),
19118 binop(Iop_64HLtoV128,
19119 binop(Iop_32HLto64,
19120 binop(Iop_16HLto32,
19121 mkexpr(tmp[7]),
19122 mkexpr(tmp[6])),
19123 binop(Iop_16HLto32,
19124 mkexpr(tmp[5]),
19125 mkexpr(tmp[4]))),
19126 binop(Iop_32HLto64,
19127 binop(Iop_16HLto32,
19128 mkexpr(tmp[3]),
19129 mkexpr(tmp[2])),
19130 binop(Iop_16HLto32,
19131 mkexpr(tmp[1]),
19132 mkexpr(tmp[0]))))));
19133 break;
19136 case 0x02: { /* DPSUB_U.W */
19137 DIP("DPSUB_U.W w%d, w%d, w%d", wd, ws, wt);
19138 IRTemp tmp[4];
19139 Int i;
19141 for (i = 0; i < 4; i++) {
19142 tmp[i] = newTemp(Ity_I32);
19143 assign(tmp[i],
19144 binop(Iop_Add32,
19145 binop(Iop_MullU16,
19146 binop(Iop_GetElem16x8,
19147 mkexpr(t1),
19148 mkU8(2 * i)),
19149 binop(Iop_GetElem16x8,
19150 mkexpr(t2),
19151 mkU8(2 * i))),
19152 binop(Iop_MullU16,
19153 binop(Iop_GetElem16x8,
19154 mkexpr(t1),
19155 mkU8(2 * i + 1)),
19156 binop(Iop_GetElem16x8,
19157 mkexpr(t2),
19158 mkU8(2 * i + 1)))));
19161 putWReg(wd,
19162 binop(Iop_Sub32x4,
19163 getWReg(wd),
19164 binop(Iop_64HLtoV128,
19165 binop(Iop_32HLto64,
19166 mkexpr(tmp[3]),
19167 mkexpr(tmp[2])),
19168 binop(Iop_32HLto64,
19169 mkexpr(tmp[1]),
19170 mkexpr(tmp[0])))));
19171 break;
19174 case 0x03: { /* DPSUB_U.D */
19175 DIP("DPSUB_U.D w%d, w%d, w%d", wd, ws, wt);
19176 IRTemp tmp[2];
19177 Int i;
19179 for (i = 0; i < 2; i++) {
19180 tmp[i] = newTemp(Ity_I64);
19181 assign(tmp[i],
19182 binop(Iop_Add64,
19183 binop(Iop_MullU32,
19184 binop(Iop_GetElem32x4,
19185 mkexpr(t1),
19186 mkU8(2 * i)),
19187 binop(Iop_GetElem32x4,
19188 mkexpr(t2),
19189 mkU8(2 * i))),
19190 binop(Iop_MullU32,
19191 binop(Iop_GetElem32x4,
19192 mkexpr(t1),
19193 mkU8(2 * i + 1)),
19194 binop(Iop_GetElem32x4,
19195 mkexpr(t2),
19196 mkU8(2 * i + 1)))));
19199 putWReg(wd,
19200 binop(Iop_Sub64x2,
19201 getWReg(wd),
19202 binop(Iop_64HLtoV128,
19203 mkexpr(tmp[1]),
19204 mkexpr(tmp[0]))));
19205 break;
19208 default:
19209 return -1;
19212 break;
19215 default:
19216 return -1;
19219 return 0;
19222 static Int msa_3R_14(UInt cins, UChar wd, UChar ws) { /* 3R (0x14) */
19223 IRTemp t1, t2, t3, t4;
19224 IRType ty;
19225 UShort operation;
19226 UChar df, wt;
19228 operation = (cins & 0x03800000) >> 23;
19229 df = (cins & 0x00600000) >> 21;
19230 wt = (cins & 0x001F0000) >> 16;
19231 ty = mode64 ? Ity_I64 : Ity_I32;
19233 switch (operation) {
19234 case 0x00: { /* SLD.df */
19235 switch (df) {
19236 case 0x00: {
19237 DIP("SLD.B w%d, w%d[%d]", wd, ws, wt);
19238 t1 = newTemp(Ity_I32);
19239 t2 = newTemp(Ity_V128);
19240 t3 = newTemp(Ity_V128);
19241 assign(t1,
19242 binop(Iop_Shl32,
19243 binop(Iop_And32,
19244 mkNarrowTo32(ty,
19245 getIReg(wt)),
19246 mkU32(15)),
19247 mkU8(3)));
19248 assign(t2,
19249 binop(Iop_ShrV128,
19250 getWReg(ws),
19251 unop(Iop_32to8, mkexpr(t1))));
19252 assign(t3,
19253 binop(Iop_ShlV128,
19254 getWReg(wd),
19255 unop(Iop_32to8,
19256 binop(Iop_Sub32,
19257 mkU32(128),
19258 mkexpr(t1)))));
19259 putWReg(wd,
19260 binop(Iop_OrV128,
19261 mkexpr(t2), mkexpr(t3)));
19262 break;
19265 case 0x01: {/* SLD.H */
19266 DIP("SLD.H w%d, w%d[%d]", wd, ws, wt);
19267 t1 = newTemp(Ity_I32);
19268 t2 = newTemp(Ity_I64);
19269 t3 = newTemp(Ity_V128);
19270 t4 = newTemp(Ity_V128);
19271 assign(t1,
19272 binop(Iop_Shl32,
19273 binop(Iop_And32,
19274 mkNarrowTo32(ty,
19275 getIReg(wt)),
19276 mkU32(7)),
19277 mkU8(3)));
19278 assign(t2,
19279 binop(Iop_32HLto64, mkU32(0), mkexpr(t1)));
19280 assign(t3,
19281 binop(Iop_Shr64x2,
19282 getWReg(ws),
19283 binop(Iop_64HLtoV128,
19284 mkexpr(t2), mkexpr(t2))));
19285 assign(t4,
19286 binop(Iop_Shl64x2,
19287 getWReg(wd),
19288 binop(Iop_Sub64x2,
19289 binop(Iop_64HLtoV128,
19290 mkU64(0x40ul),
19291 mkU64(0x40ul)),
19292 binop(Iop_64HLtoV128,
19293 mkexpr(t2),
19294 mkexpr(t2)))));
19295 putWReg(wd,
19296 binop(Iop_OrV128,
19297 mkexpr(t3),
19298 IRExpr_ITE(
19299 binop(Iop_CmpNE32,
19300 mkexpr(t1), mkU32(0)),
19301 mkexpr(t4),
19302 binop(Iop_64HLtoV128,
19303 mkU64(0), mkU64(0)))));
19304 break;
19307 case 0x02: {/* SLD.W */
19308 DIP("SLD.W w%d, w%d[%d]", wd, ws, wt);
19309 t1 = newTemp(Ity_I32);
19310 t2 = newTemp(Ity_I64);
19311 t3 = newTemp(Ity_V128);
19312 t4 = newTemp(Ity_V128);
19313 assign(t1,
19314 binop(Iop_Shl32,
19315 binop(Iop_And32,
19316 mkNarrowTo32(ty,
19317 getIReg(wt)),
19318 mkU32(3)),
19319 mkU8(3)));
19320 assign(t2,
19321 binop(Iop_32HLto64,
19322 mkexpr(t1), mkexpr(t1)));
19323 assign(t3,
19324 binop(Iop_Shr32x4,
19325 getWReg(ws),
19326 binop(Iop_64HLtoV128,
19327 mkexpr(t2), mkexpr(t2))));
19328 assign(t4,
19329 binop(Iop_Shl32x4,
19330 getWReg(wd),
19331 binop(Iop_Sub32x4,
19332 binop(Iop_64HLtoV128,
19333 mkU64(0x2000000020ul),
19334 mkU64(0x2000000020ul)),
19335 binop(Iop_64HLtoV128,
19336 mkexpr(t2),
19337 mkexpr(t2)))));
19338 putWReg(wd,
19339 binop(Iop_OrV128,
19340 mkexpr(t3),
19341 IRExpr_ITE(
19342 binop(Iop_CmpNE32,
19343 mkexpr(t1), mkU32(0)),
19344 mkexpr(t4),
19345 binop(Iop_64HLtoV128,
19346 mkU64(0), mkU64(0)))));
19347 break;
19350 case 0x03: { /* SLD.D */
19351 DIP("SLD.D w%d, w%d[%d]", wd, ws, wt);
19352 t1 = newTemp(Ity_I32);
19353 t2 = newTemp(Ity_I64);
19354 t3 = newTemp(Ity_V128);
19355 t4 = newTemp(Ity_V128);
19356 assign(t1,
19357 binop(Iop_Shl32,
19358 binop(Iop_And32,
19359 mkNarrowTo32(ty,
19360 getIReg(wt)),
19361 mkU32(1)),
19362 mkU8(3)));
19363 assign(t2,
19364 binop(Iop_32HLto64,
19365 binop(Iop_Or32,
19366 mkexpr(t1),
19367 binop(Iop_Shl32,
19368 mkexpr(t1), mkU8(16))),
19369 binop(Iop_Or32,
19370 mkexpr(t1),
19371 binop(Iop_Shl32,
19372 mkexpr(t1), mkU8(16)))));
19373 assign(t3,
19374 binop(Iop_Shr16x8,
19375 getWReg(ws),
19376 binop(Iop_64HLtoV128,
19377 mkexpr(t2), mkexpr(t2))));
19378 assign(t4,
19379 binop(Iop_Shl16x8,
19380 getWReg(wd),
19381 binop(Iop_Sub16x8,
19382 binop(Iop_64HLtoV128,
19383 mkU64(0x10001000100010ul),
19384 mkU64(0x10001000100010ul)),
19385 binop(Iop_64HLtoV128,
19386 mkexpr(t2),
19387 mkexpr(t2)))));
19388 putWReg(wd,
19389 binop(Iop_OrV128,
19390 mkexpr(t3),
19391 IRExpr_ITE(
19392 binop(Iop_CmpNE32,
19393 mkexpr(t1), mkU32(0)),
19394 mkexpr(t4),
19395 binop(Iop_64HLtoV128,
19396 mkU64(0), mkU64(0)))));
19397 break;
19401 break;
19404 case 0x01: { /* SPLAT.df */
19405 switch (df) {
19406 Int i;
19408 case 0x00: { /* SPLAT.B */
19409 DIP("SPLAT.B w%d, w%d, w%d", wd, ws, wt);
19410 t1 = newTemp(Ity_V128);
19411 t2 = newTemp(Ity_I32);
19412 assign(t1, getWReg(ws));
19413 assign(t2,
19414 mkNarrowTo32(ty, getIReg(wt)));
19415 IRTemp tmp[16];
19417 for (i = 0; i < 16; i++) {
19418 tmp[i] = newTemp(Ity_I8);
19419 assign(tmp[i],
19420 binop(Iop_GetElem8x16,
19421 mkexpr(t1),
19422 unop(Iop_32to8, mkexpr(t2))));
19425 putWReg(wd,
19426 binop(Iop_64HLtoV128,
19427 binop(Iop_32HLto64,
19428 binop(Iop_16HLto32,
19429 binop(Iop_8HLto16,
19430 mkexpr(tmp[15]),
19431 mkexpr(tmp[14])),
19432 binop(Iop_8HLto16,
19433 mkexpr(tmp[13]),
19434 mkexpr(tmp[12]))),
19435 binop(Iop_16HLto32,
19436 binop(Iop_8HLto16,
19437 mkexpr(tmp[11]),
19438 mkexpr(tmp[10])),
19439 binop(Iop_8HLto16,
19440 mkexpr(tmp[9]),
19441 mkexpr(tmp[8])))),
19442 binop(Iop_32HLto64,
19443 binop(Iop_16HLto32,
19444 binop(Iop_8HLto16,
19445 mkexpr(tmp[7]),
19446 mkexpr(tmp[6])),
19447 binop(Iop_8HLto16,
19448 mkexpr(tmp[5]),
19449 mkexpr(tmp[4]))),
19450 binop(Iop_16HLto32,
19451 binop(Iop_8HLto16,
19452 mkexpr(tmp[3]),
19453 mkexpr(tmp[2])),
19454 binop(Iop_8HLto16,
19455 mkexpr(tmp[1]),
19456 mkexpr(tmp[0]))))));
19457 break;
19460 case 0x01: { /* SPLAT.H */
19461 DIP("SPLAT.H w%d, w%d, w%d", wd, ws, wt);
19462 t1 = newTemp(Ity_V128);
19463 t2 = newTemp(Ity_I32);
19464 assign(t1, getWReg(ws));
19465 assign(t2,
19466 mkNarrowTo32(ty, getIReg(wt)));
19467 IRTemp tmp[8];
19469 for (i = 0; i < 8; i++) {
19470 tmp[i] = newTemp(Ity_I16);
19471 assign(tmp[i],
19472 binop(Iop_GetElem16x8,
19473 mkexpr(t1),
19474 unop(Iop_32to8, mkexpr(t2))));
19477 putWReg(wd,
19478 binop(Iop_64HLtoV128,
19479 binop(Iop_32HLto64,
19480 binop(Iop_16HLto32,
19481 mkexpr(tmp[7]),
19482 mkexpr(tmp[6])),
19483 binop(Iop_16HLto32,
19484 mkexpr(tmp[5]),
19485 mkexpr(tmp[4]))),
19486 binop(Iop_32HLto64,
19487 binop(Iop_16HLto32,
19488 mkexpr(tmp[3]),
19489 mkexpr(tmp[2])),
19490 binop(Iop_16HLto32,
19491 mkexpr(tmp[1]),
19492 mkexpr(tmp[0])))));
19493 break;
19496 case 0x02: { /* SPLAT.W */
19497 DIP("SPLAT.W w%d, w%d, w%d", wd, ws, wt);
19498 t1 = newTemp(Ity_V128);
19499 t2 = newTemp(Ity_I32);
19500 assign(t1, getWReg(ws));
19501 assign(t2,
19502 mkNarrowTo32(ty, getIReg(wt)));
19503 IRTemp tmp[4];
19505 for (i = 0; i < 4; i++) {
19506 tmp[i] = newTemp(Ity_I32);
19507 assign(tmp[i],
19508 binop(Iop_GetElem32x4,
19509 mkexpr(t1),
19510 unop(Iop_32to8, mkexpr(t2))));
19513 putWReg(wd,
19514 binop(Iop_64HLtoV128,
19515 binop(Iop_32HLto64,
19516 mkexpr(tmp[3]),
19517 mkexpr(tmp[2])),
19518 binop(Iop_32HLto64,
19519 mkexpr(tmp[1]),
19520 mkexpr(tmp[0]))));
19521 break;
19524 case 0x03: { /* SPLAT.D */
19525 DIP("SPLAT.D w%d, w%d, w%d", wd, ws, wt);
19526 t1 = newTemp(Ity_V128);
19527 t2 = newTemp(Ity_I32);
19528 assign(t1, getWReg(ws));
19529 assign(t2,
19530 mkNarrowTo32(ty, getIReg(wt)));
19531 IRTemp tmp[2];
19533 for (i = 0; i < 2; i++) {
19534 tmp[i] = newTemp(Ity_I64);
19535 assign(tmp[i],
19536 binop(Iop_GetElem64x2,
19537 mkexpr(t1),
19538 unop(Iop_32to8, mkexpr(t2))));
19541 putWReg(wd,
19542 binop(Iop_64HLtoV128,
19543 mkexpr(tmp[1]), mkexpr(tmp[0])));
19544 break;
19548 break;
19551 case 0x02: { /* PCKEV.df */
19552 switch (df) {
19553 case 0x00: { /* PCKEV.B */
19554 DIP("PCKEV.B w%d, w%d, w%d", wd, ws, wt);
19555 t1 = newTemp(Ity_V128);
19556 t2 = newTemp(Ity_V128);
19557 t3 = newTemp(Ity_V128);
19558 assign(t1, getWReg(ws));
19559 assign(t2, getWReg(wt));
19560 assign(t3,
19561 binop(Iop_PackEvenLanes8x16,
19562 mkexpr(t1), mkexpr(t2)));
19563 putWReg(wd, mkexpr(t3));
19564 break;
19567 case 0x01: { /* PCKEV.H */
19568 DIP("PCKEV.H w%d, w%d, w%d", wd, ws, wt);
19569 t1 = newTemp(Ity_V128);
19570 t2 = newTemp(Ity_V128);
19571 t3 = newTemp(Ity_V128);
19572 assign(t1, getWReg(ws));
19573 assign(t2, getWReg(wt));
19574 assign(t3,
19575 binop(Iop_PackEvenLanes16x8,
19576 mkexpr(t1), mkexpr(t2)));
19577 putWReg(wd, mkexpr(t3));
19578 break;
19581 case 0x02: { /* PCKEV.W */
19582 DIP("PCKEV.W w%d, w%d, w%d", wd, ws, wt);
19583 t1 = newTemp(Ity_V128);
19584 t2 = newTemp(Ity_V128);
19585 t3 = newTemp(Ity_V128);
19586 assign(t1, getWReg(ws));
19587 assign(t2, getWReg(wt));
19588 assign(t3,
19589 binop(Iop_PackEvenLanes32x4,
19590 mkexpr(t1), mkexpr(t2)));
19591 putWReg(wd, mkexpr(t3));
19592 break;
19595 case 0x03: { /* PCKEV.D */
19596 DIP("PCKEV.D w%d, w%d, w%d", wd, ws, wt);
19597 t1 = newTemp(Ity_V128);
19598 t2 = newTemp(Ity_V128);
19599 t3 = newTemp(Ity_V128);
19600 assign(t1, getWReg(ws));
19601 assign(t2, getWReg(wt));
19602 assign(t3,
19603 binop(Iop_InterleaveLO64x2,
19604 mkexpr(t1), mkexpr(t2)));
19605 putWReg(wd, mkexpr(t3));
19606 break;
19609 default:
19610 return -1;
19613 break;
19616 case 0x03: { /* PCKOD.df */
19617 switch (df) {
19618 case 0x00: { /* PCKOD.B */
19619 DIP("PCKOD.B w%d, w%d, w%d", wd, ws, wt);
19620 t1 = newTemp(Ity_V128);
19621 t2 = newTemp(Ity_V128);
19622 t3 = newTemp(Ity_V128);
19623 assign(t1, getWReg(ws));
19624 assign(t2, getWReg(wt));
19625 assign(t3,
19626 binop(Iop_PackOddLanes8x16,
19627 mkexpr(t1), mkexpr(t2)));
19628 putWReg(wd, mkexpr(t3));
19629 break;
19632 case 0x01: { /* PCKOD.H */
19633 DIP("PCKOD.H w%d, w%d, w%d", wd, ws, wt);
19634 t1 = newTemp(Ity_V128);
19635 t2 = newTemp(Ity_V128);
19636 t3 = newTemp(Ity_V128);
19637 assign(t1, getWReg(ws));
19638 assign(t2, getWReg(wt));
19639 assign(t3,
19640 binop(Iop_PackOddLanes16x8,
19641 mkexpr(t1), mkexpr(t2)));
19642 putWReg(wd, mkexpr(t3));
19643 break;
19646 case 0x02: { /* PCKOD.W */
19647 DIP("PCKOD.W w%d, w%d, w%d", wd, ws, wt);
19648 t1 = newTemp(Ity_V128);
19649 t2 = newTemp(Ity_V128);
19650 t3 = newTemp(Ity_V128);
19651 assign(t1, getWReg(ws));
19652 assign(t2, getWReg(wt));
19653 assign(t3,
19654 binop(Iop_PackOddLanes32x4,
19655 mkexpr(t1), mkexpr(t2)));
19656 putWReg(wd, mkexpr(t3));
19657 break;
19660 case 0x03: { /* PCKOD.D */
19661 DIP("PCKOD.D w%d, w%d, w%d", wd, ws, wt);
19662 t1 = newTemp(Ity_V128);
19663 t2 = newTemp(Ity_V128);
19664 t3 = newTemp(Ity_V128);
19665 assign(t1, getWReg(ws));
19666 assign(t2, getWReg(wt));
19667 assign(t3,
19668 binop(Iop_InterleaveHI64x2,
19669 mkexpr(t1), mkexpr(t2)));
19670 putWReg(wd, mkexpr(t3));
19671 break;
19674 default:
19675 return -1;
19678 break;
19681 case 0x04: { /* ILVL.df */
19682 switch (df) {
19683 case 0x00: { /* ILVL.B */
19684 DIP("ILVL.B w%d, w%d, w%d", wd, ws, wt);
19685 t1 = newTemp(Ity_V128);
19686 t2 = newTemp(Ity_V128);
19687 t3 = newTemp(Ity_V128);
19688 assign(t1, getWReg(ws));
19689 assign(t2, getWReg(wt));
19690 assign(t3,
19691 binop(Iop_InterleaveHI8x16,
19692 mkexpr(t1), mkexpr(t2)));
19693 putWReg(wd, mkexpr(t3));
19694 break;
19697 case 0x01: { /* ILVL.H */
19698 DIP("ILVL.H w%d, w%d, w%d", wd, ws, wt);
19699 t1 = newTemp(Ity_V128);
19700 t2 = newTemp(Ity_V128);
19701 t3 = newTemp(Ity_V128);
19702 assign(t1, getWReg(ws));
19703 assign(t2, getWReg(wt));
19704 assign(t3,
19705 binop(Iop_InterleaveHI16x8,
19706 mkexpr(t1), mkexpr(t2)));
19707 putWReg(wd, mkexpr(t3));
19708 break;
19711 case 0x02: { /* ILVL.W */
19712 DIP("ILVL.W w%d, w%d, w%d", wd, ws, wt);
19713 t1 = newTemp(Ity_V128);
19714 t2 = newTemp(Ity_V128);
19715 t3 = newTemp(Ity_V128);
19716 assign(t1, getWReg(ws));
19717 assign(t2, getWReg(wt));
19718 assign(t3,
19719 binop(Iop_InterleaveHI32x4,
19720 mkexpr(t1), mkexpr(t2)));
19721 putWReg(wd, mkexpr(t3));
19722 break;
19725 case 0x03: { /* ILVL.D */
19726 DIP("ILVL.D w%d, w%d, w%d", wd, ws, wt);
19727 t1 = newTemp(Ity_V128);
19728 t2 = newTemp(Ity_V128);
19729 t3 = newTemp(Ity_V128);
19730 assign(t1, getWReg(ws));
19731 assign(t2, getWReg(wt));
19732 assign(t3,
19733 binop(Iop_InterleaveHI64x2,
19734 mkexpr(t1), mkexpr(t2)));
19735 putWReg(wd, mkexpr(t3));
19736 break;
19739 default:
19740 return -1;
19743 break;
19746 case 0x05: { /* ILVR.df */
19747 switch (df) {
19748 case 0x00: { /* ILVL.B */
19749 DIP("ILVL.B w%d, w%d, w%d", wd, ws, wt);
19750 t1 = newTemp(Ity_V128);
19751 t2 = newTemp(Ity_V128);
19752 t3 = newTemp(Ity_V128);
19753 assign(t1, getWReg(ws));
19754 assign(t2, getWReg(wt));
19755 assign(t3,
19756 binop(Iop_InterleaveLO8x16,
19757 mkexpr(t1), mkexpr(t2)));
19758 putWReg(wd, mkexpr(t3));
19759 break;
19762 case 0x01: { /* ILVL.H */
19763 DIP("ILVL.H w%d, w%d, w%d", wd, ws, wt);
19764 t1 = newTemp(Ity_V128);
19765 t2 = newTemp(Ity_V128);
19766 t3 = newTemp(Ity_V128);
19767 assign(t1, getWReg(ws));
19768 assign(t2, getWReg(wt));
19769 assign(t3,
19770 binop(Iop_InterleaveLO16x8,
19771 mkexpr(t1), mkexpr(t2)));
19772 putWReg(wd, mkexpr(t3));
19773 break;
19776 case 0x02: { /* ILVL.W */
19777 DIP("ILVL.W w%d, w%d, w%d", wd, ws, wt);
19778 t1 = newTemp(Ity_V128);
19779 t2 = newTemp(Ity_V128);
19780 t3 = newTemp(Ity_V128);
19781 assign(t1, getWReg(ws));
19782 assign(t2, getWReg(wt));
19783 assign(t3,
19784 binop(Iop_InterleaveLO32x4,
19785 mkexpr(t1), mkexpr(t2)));
19786 putWReg(wd, mkexpr(t3));
19787 break;
19790 case 0x03: { /* ILVL.D */
19791 DIP("ILVL.D w%d, w%d, w%d", wd, ws, wt);
19792 t1 = newTemp(Ity_V128);
19793 t2 = newTemp(Ity_V128);
19794 t3 = newTemp(Ity_V128);
19795 assign(t1, getWReg(ws));
19796 assign(t2, getWReg(wt));
19797 assign(t3,
19798 binop(Iop_InterleaveLO64x2,
19799 mkexpr(t1), mkexpr(t2)));
19800 putWReg(wd, mkexpr(t3));
19801 break;
19805 break;
19808 case 0x06: { /* ILVEV.df */
19809 switch (df) {
19810 case 0x00: { /* ILVEV.B */
19811 DIP("ILVEV.B w%d, w%d, w%d", wd, ws, wt);
19812 t1 = newTemp(Ity_V128);
19813 t2 = newTemp(Ity_V128);
19814 t3 = newTemp(Ity_V128);
19815 assign(t1, getWReg(ws));
19816 assign(t2, getWReg(wt));
19817 assign(t3,
19818 binop(Iop_InterleaveEvenLanes8x16,
19819 mkexpr(t1), mkexpr(t2)));
19820 putWReg(wd, mkexpr(t3));
19821 break;
19824 case 0x01: { /* ILVEV.H */
19825 DIP("ILVEV.H w%d, w%d, w%d", wd, ws, wt);
19826 t1 = newTemp(Ity_V128);
19827 t2 = newTemp(Ity_V128);
19828 t3 = newTemp(Ity_V128);
19829 assign(t1, getWReg(ws));
19830 assign(t2, getWReg(wt));
19831 assign(t3,
19832 binop(Iop_InterleaveEvenLanes16x8,
19833 mkexpr(t1), mkexpr(t2)));
19834 putWReg(wd, mkexpr(t3));
19835 break;
19838 case 0x02: { /* ILVEV.W */
19839 DIP("ILVEV.W w%d, w%d, w%d", wd, ws, wt);
19840 t1 = newTemp(Ity_V128);
19841 t2 = newTemp(Ity_V128);
19842 t3 = newTemp(Ity_V128);
19843 assign(t1, getWReg(ws));
19844 assign(t2, getWReg(wt));
19845 assign(t3,
19846 binop(Iop_InterleaveEvenLanes32x4,
19847 mkexpr(t1), mkexpr(t2)));
19848 putWReg(wd, mkexpr(t3));
19849 break;
19852 case 0x03: { /* ILVEV.D */
19853 DIP("ILVEV.D w%d, w%d, w%d", wd, ws, wt);
19854 t1 = newTemp(Ity_V128);
19855 t2 = newTemp(Ity_V128);
19856 t3 = newTemp(Ity_V128);
19857 assign(t1, getWReg(ws));
19858 assign(t2, getWReg(wt));
19859 assign(t3,
19860 binop(Iop_InterleaveLO64x2,
19861 mkexpr(t1), mkexpr(t2)));
19862 putWReg(wd, mkexpr(t3));
19863 break;
19866 default:
19867 return -1;
19870 break;
19873 case 0x07: { /* ILVOD.df */
19874 switch (df) {
19875 case 0x00: { /* ILVOD.B */
19876 DIP("ILVOD.B w%d, w%d, w%d", wd, ws, wt);
19877 t1 = newTemp(Ity_V128);
19878 t2 = newTemp(Ity_V128);
19879 t3 = newTemp(Ity_V128);
19880 assign(t1, getWReg(ws));
19881 assign(t2, getWReg(wt));
19882 assign(t3,
19883 binop(Iop_InterleaveOddLanes8x16,
19884 mkexpr(t1), mkexpr(t2)));
19885 putWReg(wd, mkexpr(t3));
19886 break;
19889 case 0x01: { /* ILVOD.H */
19890 DIP("ILVOD.H w%d, w%d, w%d", wd, ws, wt);
19891 t1 = newTemp(Ity_V128);
19892 t2 = newTemp(Ity_V128);
19893 t3 = newTemp(Ity_V128);
19894 assign(t1, getWReg(ws));
19895 assign(t2, getWReg(wt));
19896 assign(t3,
19897 binop(Iop_InterleaveOddLanes16x8,
19898 mkexpr(t1), mkexpr(t2)));
19899 putWReg(wd, mkexpr(t3));
19900 break;
19903 case 0x02: { /* ILVOD.W */
19904 DIP("ILVOD.W w%d, w%d, w%d", wd, ws, wt);
19905 t1 = newTemp(Ity_V128);
19906 t2 = newTemp(Ity_V128);
19907 t3 = newTemp(Ity_V128);
19908 assign(t1, getWReg(ws));
19909 assign(t2, getWReg(wt));
19910 assign(t3,
19911 binop(Iop_InterleaveOddLanes32x4,
19912 mkexpr(t1), mkexpr(t2)));
19913 putWReg(wd, mkexpr(t3));
19914 break;
19917 case 0x03: { /* ILVOD.D */
19918 DIP("ILVOD.D w%d, w%d, w%d", wd, ws, wt);
19919 t1 = newTemp(Ity_V128);
19920 t2 = newTemp(Ity_V128);
19921 t3 = newTemp(Ity_V128);
19922 assign(t1, getWReg(ws));
19923 assign(t2, getWReg(wt));
19924 assign(t3,
19925 binop(Iop_InterleaveHI64x2,
19926 mkexpr(t1), mkexpr(t2)));
19927 putWReg(wd, mkexpr(t3));
19928 break;
19931 default:
19932 return -1;
19935 break;
19938 default:
19939 return -1;
19942 return 0;
19945 static Int msa_3R_15(UInt cins, UChar wd, UChar ws) { /* 3R (0x15) */
19946 IRTemp t1, t2, t3, t4;
19947 UShort operation;
19948 UChar df, wt;
19950 operation = (cins & 0x03800000) >> 23;
19951 df = (cins & 0x00600000) >> 21;
19952 wt = (cins & 0x001F0000) >> 16;
19954 switch (operation) {
19955 case 0x00: { /* VSHF.df */
19956 t1 = newTemp(Ity_V128);
19957 t2 = newTemp(Ity_V128);
19958 t3 = newTemp(Ity_V128);
19959 assign(t1, getWReg(wd));
19960 assign(t2, getWReg(ws));
19961 assign(t3, getWReg(wt));
19963 switch (df) {
19964 case 0x00: { /* VSHF.B */
19965 DIP("VSHF.B w%d, w%d, w%d", wd, ws, wt);
19966 IRTemp tmp[16];
19967 Int i;
19969 for (i = 0; i < 16; i++) {
19970 tmp[i] = newTemp(Ity_I8);
19971 assign(tmp[i],
19972 IRExpr_ITE(
19973 binop(Iop_CmpEQ8,
19974 binop(Iop_And8,
19975 binop(Iop_GetElem8x16,
19976 mkexpr(t1),
19977 mkU8(i)),
19978 mkU8(0xC0)),
19979 mkU8(0x0)),
19980 IRExpr_ITE(
19981 binop(Iop_CmpEQ8,
19982 binop(Iop_And8,
19983 binop(Iop_GetElem8x16,
19984 mkexpr(t1),
19985 mkU8(i)),
19986 mkU8(0x10)),
19987 mkU8(0x0)),
19988 binop(Iop_GetElem8x16,
19989 mkexpr(t3),
19990 binop(Iop_GetElem8x16,
19991 mkexpr(t1),
19992 mkU8(i))),
19993 binop(Iop_GetElem8x16,
19994 mkexpr(t2),
19995 binop(Iop_GetElem8x16,
19996 mkexpr(t1),
19997 mkU8(i)))),
19998 mkU8(0x0)));
20001 putWReg(wd,
20002 binop(Iop_64HLtoV128,
20003 binop(Iop_32HLto64,
20004 binop(Iop_16HLto32,
20005 binop(Iop_8HLto16,
20006 mkexpr(tmp[15]),
20007 mkexpr(tmp[14])),
20008 binop(Iop_8HLto16,
20009 mkexpr(tmp[13]),
20010 mkexpr(tmp[12]))),
20011 binop(Iop_16HLto32,
20012 binop(Iop_8HLto16,
20013 mkexpr(tmp[11]),
20014 mkexpr(tmp[10])),
20015 binop(Iop_8HLto16,
20016 mkexpr(tmp[9]),
20017 mkexpr(tmp[8])))),
20018 binop(Iop_32HLto64,
20019 binop(Iop_16HLto32,
20020 binop(Iop_8HLto16,
20021 mkexpr(tmp[7]),
20022 mkexpr(tmp[6])),
20023 binop(Iop_8HLto16,
20024 mkexpr(tmp[5]),
20025 mkexpr(tmp[4]))),
20026 binop(Iop_16HLto32,
20027 binop(Iop_8HLto16,
20028 mkexpr(tmp[3]),
20029 mkexpr(tmp[2])),
20030 binop(Iop_8HLto16,
20031 mkexpr(tmp[1]),
20032 mkexpr(tmp[0]))))));
20033 break;
20036 case 0x01: { /* VSHF.H */
20037 DIP("VSHF.H w%d, w%d, w%d", wd, ws, wt);
20038 IRTemp tmp[8];
20039 Int i;
20041 for (i = 0; i < 8; i++) {
20042 tmp[i] = newTemp(Ity_I16);
20043 assign(tmp[i],
20044 IRExpr_ITE(
20045 binop(Iop_CmpEQ16,
20046 binop(Iop_And16,
20047 binop(Iop_GetElem16x8,
20048 mkexpr(t1),
20049 mkU8(i)),
20050 mkU16(0xC0)),
20051 mkU16(0x0)),
20052 IRExpr_ITE(
20053 binop(Iop_CmpEQ16,
20054 binop(Iop_And16,
20055 binop(Iop_GetElem16x8,
20056 mkexpr(t1),
20057 mkU8(i)),
20058 mkU16(0x08)),
20059 mkU16(0x0)),
20060 binop(Iop_GetElem16x8,
20061 mkexpr(t3),
20062 unop(Iop_16to8,
20063 binop(Iop_GetElem16x8,
20064 mkexpr(t1),
20065 mkU8(i)))),
20066 binop(Iop_GetElem16x8,
20067 mkexpr(t2),
20068 unop(Iop_16to8,
20069 binop(Iop_GetElem16x8,
20070 mkexpr(t1),
20071 mkU8(i))))),
20072 mkU16(0x0)));
20075 putWReg(wd,
20076 binop(Iop_64HLtoV128,
20077 binop(Iop_32HLto64,
20078 binop(Iop_16HLto32,
20079 mkexpr(tmp[7]),
20080 mkexpr(tmp[6])),
20081 binop(Iop_16HLto32,
20082 mkexpr(tmp[5]),
20083 mkexpr(tmp[4]))),
20084 binop(Iop_32HLto64,
20085 binop(Iop_16HLto32,
20086 mkexpr(tmp[3]),
20087 mkexpr(tmp[2])),
20088 binop(Iop_16HLto32,
20089 mkexpr(tmp[1]),
20090 mkexpr(tmp[0])))));
20091 break;
20094 case 0x02: { /* VSHF.W */
20095 DIP("VSHF.W w%d, w%d, w%d", wd, ws, wt);
20096 IRTemp tmp[4];
20097 Int i;
20099 for (i = 0; i < 4; i++) {
20100 tmp[i] = newTemp(Ity_I32);
20101 assign(tmp[i],
20102 IRExpr_ITE(
20103 binop(Iop_CmpEQ32,
20104 binop(Iop_And32,
20105 binop(Iop_GetElem32x4,
20106 mkexpr(t1),
20107 mkU8(i)),
20108 mkU32(0xC0)),
20109 mkU32(0x0)),
20110 IRExpr_ITE(
20111 binop(Iop_CmpEQ32,
20112 binop(Iop_And32,
20113 binop(Iop_GetElem32x4,
20114 mkexpr(t1),
20115 mkU8(i)),
20116 mkU32(0x04)),
20117 mkU32(0x0)),
20118 binop(Iop_GetElem32x4,
20119 mkexpr(t3),
20120 unop(Iop_32to8,
20121 binop(Iop_GetElem32x4,
20122 mkexpr(t1),
20123 mkU8(i)))),
20124 binop(Iop_GetElem32x4,
20125 mkexpr(t2),
20126 unop(Iop_32to8,
20127 binop(Iop_GetElem32x4,
20128 mkexpr(t1),
20129 mkU8(i))))),
20130 mkU32(0x0)));
20133 putWReg(wd,
20134 binop(Iop_64HLtoV128,
20135 binop(Iop_32HLto64,
20136 mkexpr(tmp[3]),
20137 mkexpr(tmp[2])),
20138 binop(Iop_32HLto64,
20139 mkexpr(tmp[1]),
20140 mkexpr(tmp[0]))));
20141 break;
20144 case 0x03: { /* VSHF.D */
20145 DIP("VSHF.D w%d, w%d, w%d", wd, ws, wt);
20146 IRTemp tmp[2];
20147 Int i;
20149 for (i = 0; i < 2; i++) {
20150 tmp[i] = newTemp(Ity_I64);
20151 assign(tmp[i],
20152 IRExpr_ITE(
20153 binop(Iop_CmpEQ64,
20154 binop(Iop_And64,
20155 binop(Iop_GetElem64x2,
20156 mkexpr(t1),
20157 mkU8(i)),
20158 mkU64(0xC0)),
20159 mkU64(0x0)),
20160 IRExpr_ITE(
20161 binop(Iop_CmpEQ64,
20162 binop(Iop_And64,
20163 binop(Iop_GetElem64x2,
20164 mkexpr(t1),
20165 mkU8(i)),
20166 mkU64(0x02)),
20167 mkU64(0x0)),
20168 binop(Iop_GetElem64x2,
20169 mkexpr(t3),
20170 unop(Iop_64to8,
20171 binop(Iop_GetElem64x2,
20172 mkexpr(t1),
20173 mkU8(i)))),
20174 binop(Iop_GetElem64x2,
20175 mkexpr(t2),
20176 unop(Iop_64to8,
20177 binop(Iop_GetElem64x2,
20178 mkexpr(t1),
20179 mkU8(i))))),
20180 mkU64(0x0)));
20183 putWReg(wd,
20184 binop(Iop_64HLtoV128,
20185 mkexpr(tmp[1]), mkexpr(tmp[0])));
20186 break;
20189 default:
20190 return -1;
20193 break;
20196 case 0x01: { /* SRAR.df */
20197 switch (df) {
20198 case 0x00: { /* SRAR.B */
20199 DIP("SRAR.B w%d, w%d, w%d", wd, ws, wt);
20200 t1 = newTemp(Ity_V128);
20201 t2 = newTemp(Ity_V128);
20202 t3 = newTemp(Ity_V128);
20203 t4 = newTemp(Ity_V128);
20204 assign(t1,
20205 binop(Iop_Sar8x16,
20206 getWReg(ws),
20207 getWReg(wt)));
20208 assign(t2,
20209 binop(Iop_Sub8x16,
20210 binop(Iop_64HLtoV128,
20211 mkU64(0x808080808080808ull),
20212 mkU64(0x808080808080808ull)),
20213 getWReg(wt)));
20214 assign(t4,
20215 unop(Iop_NotV128,
20216 binop(Iop_CmpEQ8x16,
20217 binop(Iop_ShlN8x16,
20218 getWReg(wt),
20219 mkU8(5)),
20220 binop(Iop_64HLtoV128,
20221 mkU64(0), mkU64(0)))));
20222 assign(t3,
20223 binop(Iop_ShrN8x16,
20224 binop(Iop_AndV128,
20225 binop(Iop_Shl8x16,
20226 getWReg(ws),
20227 mkexpr(t2)),
20228 mkexpr(t4)),
20229 mkU8(7)));
20230 putWReg(wd,
20231 binop(Iop_Add8x16,
20232 mkexpr(t1), mkexpr(t3)));
20233 break;
20236 case 0x01: { /* SRAR.H */
20237 DIP("SRAR.H w%d, w%d, w%d", wd, ws, wt);
20238 t1 = newTemp(Ity_V128);
20239 t2 = newTemp(Ity_V128);
20240 t3 = newTemp(Ity_V128);
20241 t4 = newTemp(Ity_V128);
20242 assign(t1,
20243 binop(Iop_Sar16x8,
20244 getWReg(ws),
20245 getWReg(wt)));
20246 assign(t2,
20247 binop(Iop_Sub16x8,
20248 binop(Iop_64HLtoV128,
20249 mkU64(0x10001000100010ul),
20250 mkU64(0x10001000100010ul)),
20251 getWReg(wt)));
20252 assign(t4,
20253 unop(Iop_NotV128,
20254 binop(Iop_CmpEQ16x8,
20255 binop(Iop_ShlN16x8,
20256 getWReg(wt),
20257 mkU8(12)),
20258 binop(Iop_64HLtoV128,
20259 mkU64(0), mkU64(0)))));
20260 assign(t3,
20261 binop(Iop_ShrN16x8,
20262 binop(Iop_AndV128,
20263 binop(Iop_Shl16x8,
20264 getWReg(ws),
20265 mkexpr(t2)),
20266 mkexpr(t4)),
20267 mkU8(15)));
20268 putWReg(wd,
20269 binop(Iop_Add16x8,
20270 mkexpr(t1), mkexpr(t3)));
20271 break;
20274 case 0x02: { /* SRAR.W */
20275 DIP("SRAR.W w%d, w%d, w%d", wd, ws, wt);
20276 t1 = newTemp(Ity_V128); // shifted
20277 t2 = newTemp(Ity_V128); // 32 - wt
20278 t3 = newTemp(Ity_V128); // rv
20279 t4 = newTemp(Ity_V128); // wt % 32 == 0
20280 assign(t1,
20281 binop(Iop_Sar32x4,
20282 getWReg(ws),
20283 getWReg(wt)));
20284 assign(t2,
20285 binop(Iop_Sub32x4,
20286 binop(Iop_64HLtoV128,
20287 mkU64(0x2000000020ul),
20288 mkU64(0x2000000020ul)),
20289 getWReg(wt)));
20290 assign(t4,
20291 unop(Iop_NotV128,
20292 binop(Iop_CmpEQ32x4,
20293 binop(Iop_ShlN32x4,
20294 getWReg(wt),
20295 mkU8(27)),
20296 binop(Iop_64HLtoV128,
20297 mkU64(0), mkU64(0)))));
20298 assign(t3,
20299 binop(Iop_ShrN32x4,
20300 binop(Iop_AndV128,
20301 binop(Iop_Shl32x4,
20302 getWReg(ws),
20303 mkexpr(t2)),
20304 mkexpr(t4)),
20305 mkU8(31)));
20306 putWReg(wd,
20307 binop(Iop_Add32x4,
20308 mkexpr(t1), mkexpr(t3)));
20309 break;
20312 case 0x03: { /* SRAR.D */
20313 DIP("SRAR.D w%d, w%d, w%d", wd, ws, wt);
20314 t1 = newTemp(Ity_V128);
20315 t2 = newTemp(Ity_V128);
20316 t3 = newTemp(Ity_V128);
20317 t4 = newTemp(Ity_V128);
20318 assign(t1,
20319 binop(Iop_Sar64x2,
20320 getWReg(ws),
20321 getWReg(wt)));
20322 assign(t2,
20323 binop(Iop_Sub64x2,
20324 binop(Iop_64HLtoV128,
20325 mkU64(64ul), mkU64(64ul)),
20326 getWReg(wt)));
20327 assign(t4,
20328 unop(Iop_NotV128,
20329 binop(Iop_CmpEQ64x2,
20330 binop(Iop_ShlN64x2,
20331 getWReg(wt),
20332 mkU8(58)),
20333 binop(Iop_64HLtoV128,
20334 mkU64(0), mkU64(0)))));
20335 assign(t3,
20336 binop(Iop_ShrN64x2,
20337 binop(Iop_AndV128,
20338 binop(Iop_Shl64x2,
20339 getWReg(ws),
20340 mkexpr(t2)),
20341 mkexpr(t4)),
20342 mkU8(63)));
20343 putWReg(wd,
20344 binop(Iop_Add64x2,
20345 mkexpr(t1), mkexpr(t3)));
20346 break;
20349 default:
20350 return -1;
20353 break;
20356 case 0x02: { /* SRLR.df */
20357 switch (df) {
20358 case 0x00: { /* SRLR.B */
20359 DIP("SRLR.B w%d, w%d, w%d", wd, ws, wt);
20360 t1 = newTemp(Ity_V128);
20361 t2 = newTemp(Ity_V128);
20362 t3 = newTemp(Ity_V128);
20363 t4 = newTemp(Ity_V128);
20364 assign(t1,
20365 binop(Iop_Shr8x16,
20366 getWReg(ws),
20367 getWReg(wt)));
20368 assign(t2,
20369 binop(Iop_Sub8x16,
20370 binop(Iop_64HLtoV128,
20371 mkU64(0x808080808080808ull),
20372 mkU64(0x808080808080808ull)),
20373 getWReg(wt)));
20374 assign(t4,
20375 unop(Iop_NotV128,
20376 binop(Iop_CmpEQ8x16,
20377 binop(Iop_ShlN8x16,
20378 getWReg(wt),
20379 mkU8(5)),
20380 binop(Iop_64HLtoV128,
20381 mkU64(0), mkU64(0)))));
20382 assign(t3,
20383 binop(Iop_ShrN8x16,
20384 binop(Iop_AndV128,
20385 binop(Iop_Shl8x16,
20386 getWReg(ws),
20387 mkexpr(t2)),
20388 mkexpr(t4)),
20389 mkU8(7)));
20390 putWReg(wd,
20391 binop(Iop_Add8x16,
20392 mkexpr(t1), mkexpr(t3)));
20393 break;
20396 case 0x01: { /* SRLR.H */
20397 DIP("SRLR.H w%d, w%d, w%d", wd, ws, wt);
20398 t1 = newTemp(Ity_V128);
20399 t2 = newTemp(Ity_V128);
20400 t3 = newTemp(Ity_V128);
20401 t4 = newTemp(Ity_V128);
20402 assign(t1,
20403 binop(Iop_Shr16x8,
20404 getWReg(ws),
20405 getWReg(wt)));
20406 assign(t2,
20407 binop(Iop_Sub16x8,
20408 binop(Iop_64HLtoV128,
20409 mkU64(0x10001000100010ul),
20410 mkU64(0x10001000100010ul)),
20411 getWReg(wt)));
20412 assign(t4,
20413 unop(Iop_NotV128,
20414 binop(Iop_CmpEQ16x8,
20415 binop(Iop_ShlN16x8,
20416 getWReg(wt),
20417 mkU8(12)),
20418 binop(Iop_64HLtoV128,
20419 mkU64(0), mkU64(0)))));
20420 assign(t3,
20421 binop(Iop_ShrN16x8,
20422 binop(Iop_AndV128,
20423 binop(Iop_Shl16x8,
20424 getWReg(ws),
20425 mkexpr(t2)),
20426 mkexpr(t4)),
20427 mkU8(15)));
20428 putWReg(wd,
20429 binop(Iop_Add16x8,
20430 mkexpr(t1), mkexpr(t3)));
20431 break;
20434 case 0x02: { /* SRLR.W */
20435 DIP("SRLR.W w%d, w%d, w%d", wd, ws, wt);
20436 t1 = newTemp(Ity_V128);
20437 t2 = newTemp(Ity_V128);
20438 t3 = newTemp(Ity_V128);
20439 t4 = newTemp(Ity_V128);
20440 assign(t1,
20441 binop(Iop_Shr32x4,
20442 getWReg(ws),
20443 getWReg(wt)));
20444 assign(t2,
20445 binop(Iop_Sub32x4,
20446 binop(Iop_64HLtoV128,
20447 mkU64(0x2000000020ul),
20448 mkU64(0x2000000020ul)),
20449 getWReg(wt)));
20450 assign(t4,
20451 unop(Iop_NotV128,
20452 binop(Iop_CmpEQ32x4,
20453 binop(Iop_ShlN32x4,
20454 getWReg(wt),
20455 mkU8(27)),
20456 binop(Iop_64HLtoV128,
20457 mkU64(0), mkU64(0)))));
20458 assign(t3,
20459 binop(Iop_ShrN32x4,
20460 binop(Iop_AndV128,
20461 binop(Iop_Shl32x4,
20462 getWReg(ws),
20463 mkexpr(t2)),
20464 mkexpr(t4)),
20465 mkU8(31)));
20466 putWReg(wd,
20467 binop(Iop_Add32x4,
20468 mkexpr(t1), mkexpr(t3)));
20469 break;
20472 case 0x03: { /* SRLR.D */
20473 DIP("SRLR.D w%d, w%d, w%d", wd, ws, wt);
20474 t1 = newTemp(Ity_V128);
20475 t2 = newTemp(Ity_V128);
20476 t3 = newTemp(Ity_V128);
20477 t4 = newTemp(Ity_V128);
20478 assign(t1,
20479 binop(Iop_Shr64x2,
20480 getWReg(ws),
20481 getWReg(wt)));
20482 assign(t2,
20483 binop(Iop_Sub64x2,
20484 binop(Iop_64HLtoV128,
20485 mkU64(64ul), mkU64(64ul)),
20486 getWReg(wt)));
20487 assign(t4,
20488 unop(Iop_NotV128,
20489 binop(Iop_CmpEQ64x2,
20490 binop(Iop_ShlN64x2,
20491 getWReg(wt),
20492 mkU8(58)),
20493 binop(Iop_64HLtoV128,
20494 mkU64(0), mkU64(0)))));
20495 assign(t3,
20496 binop(Iop_ShrN64x2,
20497 binop(Iop_AndV128,
20498 binop(Iop_Shl64x2,
20499 getWReg(ws),
20500 mkexpr(t2)),
20501 mkexpr(t4)),
20502 mkU8(63)));
20503 putWReg(wd,
20504 binop(Iop_Add64x2,
20505 mkexpr(t1), mkexpr(t3)));
20506 break;
20509 default:
20510 return -1;
20513 break;
20516 case 0x04: { /* HADD_S.df */
20517 switch (df) {
20518 case 0x01: { /* HADD_S.H */
20519 DIP("HADD_S.H w%d, w%d, w%d", wd, ws, wt);
20520 t1 = newTemp(Ity_V128);
20521 t2 = newTemp(Ity_V128);
20522 t3 = newTemp(Ity_V128);
20523 assign(t1, getWReg(ws));
20524 assign(t2, getWReg(wt));
20525 assign(t3,
20526 binop(Iop_Add16x8,
20527 binop(Iop_SarN16x8,
20528 mkexpr(t1), mkU8(8)),
20529 binop(Iop_SarN16x8,
20530 binop(Iop_ShlN16x8,
20531 mkexpr(t2), mkU8(8)),
20532 mkU8(8))));
20533 putWReg(wd, mkexpr(t3));
20534 break;
20537 case 0x02: { /* HADD_S.W */
20538 DIP("HADD_S.W w%d, w%d, w%d", wd, ws, wt);
20539 t1 = newTemp(Ity_V128);
20540 t2 = newTemp(Ity_V128);
20541 t3 = newTemp(Ity_V128);
20542 assign(t1, getWReg(ws));
20543 assign(t2, getWReg(wt));
20544 assign(t3,
20545 binop(Iop_Add32x4,
20546 binop(Iop_SarN32x4,
20547 mkexpr(t1), mkU8(16)),
20548 binop(Iop_SarN32x4,
20549 binop(Iop_ShlN32x4,
20550 mkexpr(t2), mkU8(16)),
20551 mkU8(16))));
20552 putWReg(wd, mkexpr(t3));
20553 break;
20556 case 0x03: { /* HADD_S.D */
20557 DIP("HADD_S.D w%d, w%d, w%d", wd, ws, wt);
20558 t1 = newTemp(Ity_V128);
20559 t2 = newTemp(Ity_V128);
20560 t3 = newTemp(Ity_V128);
20561 assign(t1, getWReg(ws));
20562 assign(t2, getWReg(wt));
20563 assign(t3,
20564 binop(Iop_Add64x2,
20565 binop(Iop_SarN64x2,
20566 mkexpr(t1), mkU8(32)),
20567 binop(Iop_SarN64x2,
20568 binop(Iop_ShlN64x2,
20569 mkexpr(t2), mkU8(32)),
20570 mkU8(32))));
20571 putWReg(wd, mkexpr(t3));
20572 break;
20575 default:
20576 return -1;
20579 break;
20582 case 0x05: { /* HADD_U.df */
20583 switch (df) {
20584 case 0x01: { /* HADD_U.H */
20585 DIP("HADD_U.H w%d, w%d, w%d", wd, ws, wt);
20586 t1 = newTemp(Ity_V128);
20587 t2 = newTemp(Ity_V128);
20588 t3 = newTemp(Ity_V128);
20589 assign(t1, getWReg(ws));
20590 assign(t2, getWReg(wt));
20591 assign(t3,
20592 binop(Iop_Add16x8,
20593 binop(Iop_ShrN16x8,
20594 mkexpr(t1), mkU8(8)),
20595 binop(Iop_ShrN16x8,
20596 binop(Iop_ShlN16x8,
20597 mkexpr(t2), mkU8(8)),
20598 mkU8(8))));
20599 putWReg(wd, mkexpr(t3));
20600 break;
20603 case 0x02: { /* HADD_U.W */
20604 DIP("HADD_U.W w%d, w%d, w%d", wd, ws, wt);
20605 t1 = newTemp(Ity_V128);
20606 t2 = newTemp(Ity_V128);
20607 t3 = newTemp(Ity_V128);
20608 assign(t1, getWReg(ws));
20609 assign(t2, getWReg(wt));
20610 assign(t3,
20611 binop(Iop_Add32x4,
20612 binop(Iop_ShrN32x4,
20613 mkexpr(t1), mkU8(16)),
20614 binop(Iop_ShrN32x4,
20615 binop(Iop_ShlN32x4,
20616 mkexpr(t2), mkU8(16)),
20617 mkU8(16))));
20618 putWReg(wd, mkexpr(t3));
20619 break;
20622 case 0x03: { /* HADD_U.D */
20623 DIP("HADD_U.D w%d, w%d, w%d", wd, ws, wt);
20624 t1 = newTemp(Ity_V128);
20625 t2 = newTemp(Ity_V128);
20626 t3 = newTemp(Ity_V128);
20627 assign(t1, getWReg(ws));
20628 assign(t2, getWReg(wt));
20629 assign(t3,
20630 binop(Iop_Add64x2,
20631 binop(Iop_ShrN64x2,
20632 mkexpr(t1), mkU8(32)),
20633 binop(Iop_ShrN64x2,
20634 binop(Iop_ShlN64x2,
20635 mkexpr(t2), mkU8(32)),
20636 mkU8(32))));
20637 putWReg(wd, mkexpr(t3));
20638 break;
20641 default:
20642 return -1;
20645 break;
20648 case 0x06: { /* HSUB_S.df */
20649 switch (df) {
20650 case 0x01: { /* HSUB_S.H */
20651 DIP("HSUB_S.H w%d, w%d, w%d", wd, ws, wt);
20652 t1 = newTemp(Ity_V128);
20653 t2 = newTemp(Ity_V128);
20654 t3 = newTemp(Ity_V128);
20655 assign(t1, getWReg(ws));
20656 assign(t2, getWReg(wt));
20657 assign(t3,
20658 binop(Iop_Sub16x8,
20659 binop(Iop_SarN16x8,
20660 mkexpr(t1), mkU8(8)),
20661 binop(Iop_SarN16x8,
20662 binop(Iop_ShlN16x8,
20663 mkexpr(t2), mkU8(8)),
20664 mkU8(8))));
20665 putWReg(wd, mkexpr(t3));
20666 break;
20669 case 0x02: { /* HSUB_S.W */
20670 DIP("HSUB_S.W w%d, w%d, w%d", wd, ws, wt);
20671 t1 = newTemp(Ity_V128);
20672 t2 = newTemp(Ity_V128);
20673 t3 = newTemp(Ity_V128);
20674 assign(t1, getWReg(ws));
20675 assign(t2, getWReg(wt));
20676 assign(t3,
20677 binop(Iop_Sub32x4,
20678 binop(Iop_SarN32x4,
20679 mkexpr(t1), mkU8(16)),
20680 binop(Iop_SarN32x4,
20681 binop(Iop_ShlN32x4,
20682 mkexpr(t2), mkU8(16)),
20683 mkU8(16))));
20684 putWReg(wd, mkexpr(t3));
20685 break;
20688 case 0x03: { /* HSUB_S.D */
20689 DIP("HSUB_S.D w%d, w%d, w%d", wd, ws, wt);
20690 t1 = newTemp(Ity_V128);
20691 t2 = newTemp(Ity_V128);
20692 t3 = newTemp(Ity_V128);
20693 assign(t1, getWReg(ws));
20694 assign(t2, getWReg(wt));
20695 assign(t3,
20696 binop(Iop_Sub64x2,
20697 binop(Iop_SarN64x2,
20698 mkexpr(t1), mkU8(32)),
20699 binop(Iop_SarN64x2,
20700 binop(Iop_ShlN64x2,
20701 mkexpr(t2), mkU8(32)),
20702 mkU8(32))));
20703 putWReg(wd, mkexpr(t3));
20704 break;
20707 default:
20708 return -1;
20711 break;
20714 case 0x07: { /* HSUB_U.df */
20715 switch (df) {
20716 case 0x01: { /* HSUB_U.H */
20717 DIP("HSUB_U.H w%d, w%d, w%d", wd, ws, wt);
20718 t1 = newTemp(Ity_V128);
20719 t2 = newTemp(Ity_V128);
20720 t3 = newTemp(Ity_V128);
20721 assign(t1, getWReg(ws));
20722 assign(t2, getWReg(wt));
20723 assign(t3,
20724 binop(Iop_Sub16x8,
20725 binop(Iop_ShrN16x8,
20726 mkexpr(t1), mkU8(8)),
20727 binop(Iop_ShrN16x8,
20728 binop(Iop_ShlN16x8,
20729 mkexpr(t2), mkU8(8)),
20730 mkU8(8))));
20731 putWReg(wd, mkexpr(t3));
20732 break;
20735 case 0x02: { /* HSUB_U.W */
20736 DIP("HSUB_U.W w%d, w%d, w%d", wd, ws, wt);
20737 t1 = newTemp(Ity_V128);
20738 t2 = newTemp(Ity_V128);
20739 t3 = newTemp(Ity_V128);
20740 assign(t1, getWReg(ws));
20741 assign(t2, getWReg(wt));
20742 assign(t3,
20743 binop(Iop_Sub32x4,
20744 binop(Iop_ShrN32x4,
20745 mkexpr(t1), mkU8(16)),
20746 binop(Iop_ShrN32x4,
20747 binop(Iop_ShlN32x4,
20748 mkexpr(t2), mkU8(16)),
20749 mkU8(16))));
20750 putWReg(wd, mkexpr(t3));
20751 break;
20754 case 0x03: { /* HSUB_U.D */
20755 DIP("HSUB_U.D w%d, w%d, w%d", wd, ws, wt);
20756 t1 = newTemp(Ity_V128);
20757 t2 = newTemp(Ity_V128);
20758 t3 = newTemp(Ity_V128);
20759 assign(t1, getWReg(ws));
20760 assign(t2, getWReg(wt));
20761 assign(t3,
20762 binop(Iop_Sub64x2,
20763 binop(Iop_ShrN64x2,
20764 mkexpr(t1), mkU8(32)),
20765 binop(Iop_ShrN64x2,
20766 binop(Iop_ShlN64x2,
20767 mkexpr(t2), mkU8(32)),
20768 mkU8(32))));
20769 putWReg(wd, mkexpr(t3));
20770 break;
20773 default:
20774 return -1;
20777 break;
20780 default:
20781 return -1;
20784 return 0;
20787 static Int msa_3R_1A(UInt cins, UChar wd, UChar ws) { /* 3R (0x1A) */
20788 UShort operation;
20789 UChar df, wt;
20791 operation = (cins & 0x03C00000) >> 22;
20792 df = (cins & 0x00200000) >> 21;
20793 wt = (cins & 0x001F0000) >> 16;
20795 switch (operation) {
20796 case 0x00: { /* FCAF.df */
20797 switch (df) {
20798 case 0x00: { /* FCAF.W */
20799 DIP("FCAF.W w%d, w%d, w%d", wd, ws, wt);
20800 calculateMSACSR(ws, wt, FCAFW, 2);
20801 putWReg(wd, binop(Iop_64HLtoV128, mkU64(0ul), mkU64(0ul)));
20802 break;
20805 case 0x01: { /* FCAF.D */
20806 DIP("FCAF.D w%d, w%d, w%d", wd, ws, wt);
20807 calculateMSACSR(ws, wt, FCAFD, 2);
20808 putWReg(wd, binop(Iop_64HLtoV128, mkU64(0ul), mkU64(0ul)));
20809 break;
20812 default:
20813 return -1;
20816 break;
20819 case 0x01: { /* FCUN.df */
20820 switch (df) {
20821 case 0x00: { /* FCUN.W */
20822 DIP("FCUN.W w%d, w%d, w%d", wd, ws, wt);
20823 calculateMSACSR(ws, wt, FCUNW, 2);
20824 putWReg(wd, binop(Iop_CmpUN32Fx4,
20825 getWReg(ws),
20826 getWReg(wt)));
20827 break;
20830 case 0x01: { /* FCUN.D */
20831 DIP("FCUN.D w%d, w%d, w%d", wd, ws, wt);
20832 calculateMSACSR(ws, wt, FCUND, 2);
20833 putWReg(wd, binop(Iop_CmpUN64Fx2,
20834 getWReg(ws),
20835 getWReg(wt)));
20836 break;
20839 default:
20840 return -1;
20843 break;
20846 case 0x02: { /* FCEQ.df */
20847 switch (df) {
20848 case 0x00: { /* FCEQ.W */
20849 DIP("FCEQ.W w%d, w%d, w%d", wd, ws, wt);
20850 calculateMSACSR(ws, wt, FCEQW, 2);
20851 putWReg(wd, binop(Iop_CmpEQ32Fx4,
20852 getWReg(ws),
20853 getWReg(wt)));
20854 break;
20857 case 0x01: { /* FCEQ.D */
20858 DIP("FCEQ.D w%d, w%d, w%d", wd, ws, wt);
20859 calculateMSACSR(ws, wt, FCEQD, 2);
20860 putWReg(wd, binop(Iop_CmpEQ64Fx2,
20861 getWReg(ws),
20862 getWReg(wt)));
20863 break;
20866 default:
20867 return -1;
20870 break;
20873 case 0x03: { /* FCUEQ.df */
20874 switch (df) {
20875 case 0x00: { /* FCUEQ.W */
20876 DIP("FCUEQ.W w%d, w%d, w%d", wd, ws, wt);
20877 calculateMSACSR(ws, wt, FCUEQW, 2);
20878 putWReg(wd,
20879 binop(Iop_OrV128,
20880 binop(Iop_CmpEQ32Fx4,
20881 getWReg(ws),
20882 getWReg(wt)),
20883 binop(Iop_CmpUN32Fx4,
20884 getWReg(ws),
20885 getWReg(wt))));
20886 break;
20889 case 0x01: { /* FCUEQ.D */
20890 DIP("FCUEQ.D w%d, w%d, w%d", wd, ws, wt);
20891 calculateMSACSR(ws, wt, FCUEQD, 2);
20892 putWReg(wd,
20893 binop(Iop_OrV128,
20894 binop(Iop_CmpEQ64Fx2,
20895 getWReg(ws),
20896 getWReg(wt)),
20897 binop(Iop_CmpUN64Fx2,
20898 getWReg(ws),
20899 getWReg(wt))));
20900 break;
20903 default:
20904 return -1;
20907 break;
20910 case 0x04: { /* FCLT.df */
20911 switch (df) {
20912 case 0x00: { /* FCLT.W */
20913 DIP("FCLT.W w%d, w%d, w%d", wd, ws, wt);
20914 calculateMSACSR(ws, wt, FCLTW, 2);
20915 putWReg(wd,
20916 binop(Iop_CmpLT32Fx4,
20917 getWReg(ws),
20918 getWReg(wt)));
20919 break;
20922 case 0x01: { /* FCLT.D */
20923 DIP("FCLT.D w%d, w%d, w%d", wd, ws, wt);
20924 calculateMSACSR(ws, wt, FCLTD, 2);
20925 putWReg(wd,
20926 binop(Iop_CmpLT64Fx2,
20927 getWReg(ws),
20928 getWReg(wt)));
20929 break;
20932 default:
20933 return -1;
20936 break;
20939 case 0x05: { /* FCULT.df */
20940 switch (df) {
20941 case 0x00: { /* FCULT.W */
20942 DIP("FCULT.W w%d, w%d, w%d", wd, ws, wt);
20943 calculateMSACSR(ws, wt, FCULTW, 2);
20944 putWReg(wd,
20945 binop(Iop_OrV128,
20946 binop(Iop_CmpLT32Fx4,
20947 getWReg(ws),
20948 getWReg(wt)),
20949 binop(Iop_CmpUN32Fx4,
20950 getWReg(ws),
20951 getWReg(wt))));
20952 break;
20955 case 0x01: { /* FCULT.D */
20956 DIP("FCULT.D w%d, w%d, w%d", wd, ws, wt);
20957 calculateMSACSR(ws, wt, FCULTD, 2);
20958 putWReg(wd,
20959 binop(Iop_OrV128,
20960 binop(Iop_CmpLT64Fx2,
20961 getWReg(ws),
20962 getWReg(wt)),
20963 binop(Iop_CmpUN64Fx2,
20964 getWReg(ws),
20965 getWReg(wt))));
20966 break;
20969 default:
20970 return -1;
20973 break;
20976 case 0x06: { /* FCLE.df */
20977 switch (df) {
20978 case 0x00: { /* FCLE.W */
20979 DIP("FCLE.W w%d, w%d, w%d", wd, ws, wt);
20980 calculateMSACSR(ws, wt, FCLEW, 2);
20981 putWReg(wd,
20982 binop(Iop_CmpLE32Fx4,
20983 getWReg(ws),
20984 getWReg(wt)));
20985 break;
20988 case 0x01: { /* FCLE.D */
20989 DIP("FCLE.D w%d, w%d, w%d", wd, ws, wt);
20990 calculateMSACSR(ws, wt, FCLED, 2);
20991 putWReg(wd,
20992 binop(Iop_CmpLE64Fx2,
20993 getWReg(ws),
20994 getWReg(wt)));
20995 break;
20998 default:
20999 return -1;
21002 break;
21005 case 0x07: { /* FCULE.df */
21006 switch (df) {
21007 case 0x00: { /* FCULE.W */
21008 DIP("FCULE.W w%d, w%d, w%d", wd, ws, wt);
21009 calculateMSACSR(ws, wt, FCULEW, 2);
21010 putWReg(wd,
21011 binop(Iop_OrV128,
21012 binop(Iop_CmpLE32Fx4,
21013 getWReg(ws),
21014 getWReg(wt)),
21015 binop(Iop_CmpUN32Fx4,
21016 getWReg(ws),
21017 getWReg(wt))));
21018 break;
21021 case 0x01: { /* FCULE.D */
21022 DIP("FCULE.D w%d, w%d, w%d", wd, ws, wt);
21023 calculateMSACSR(ws, wt, FCULED, 2);
21024 putWReg(wd,
21025 binop(Iop_OrV128,
21026 binop(Iop_CmpLE64Fx2,
21027 getWReg(ws),
21028 getWReg(wt)),
21029 binop(Iop_CmpUN64Fx2,
21030 getWReg(ws),
21031 getWReg(wt))));
21032 break;
21035 default:
21036 return -1;
21039 break;
21042 case 0x08: { /* FSAF.df */
21043 switch (df) {
21044 case 0x00: { /* FSAF.W */
21045 DIP("FSAF.W w%d, w%d, w%d", wd, ws, wt);
21046 calculateMSACSR(ws, wt, FSAFW, 2);
21047 putWReg(wd,
21048 binop(Iop_64HLtoV128,
21049 mkU64(0ul), mkU64(0ul)));
21050 break;
21053 case 0x01: { /* FSAF.D */
21054 DIP("FSAF.D w%d, w%d, w%d", wd, ws, wt);
21055 calculateMSACSR(ws, wt, FSAFD, 2);
21056 putWReg(wd,
21057 binop(Iop_64HLtoV128,
21058 mkU64(0ul), mkU64(0ul)));
21059 break;
21062 default:
21063 return -1;
21066 break;
21069 case 0x09: { /* FSUN.df */
21070 switch (df) {
21071 case 0x00: { /* FSUN.W */
21072 DIP("FSUN.W w%d, w%d, w%d", wd, ws, wt);
21073 calculateMSACSR(ws, wt, FSUNW, 2);
21074 putWReg(wd,
21075 binop(Iop_CmpUN32Fx4,
21076 getWReg(ws),
21077 getWReg(wt)));
21078 break;
21081 case 0x01: { /* FSUN.D */
21082 DIP("FSUN.D w%d, w%d, w%d", wd, ws, wt);
21083 calculateMSACSR(ws, wt, FSUND, 2);
21084 putWReg(wd,
21085 binop(Iop_CmpUN64Fx2,
21086 getWReg(ws),
21087 getWReg(wt)));
21088 break;
21091 default:
21092 return -1;
21095 break;
21098 case 0x0A: { /* FSEQ.df */
21099 switch (df) {
21100 case 0x00: { /* FSEQ.W */
21101 DIP("FSEQ.W w%d, w%d, w%d", wd, ws, wt);
21102 calculateMSACSR(ws, wt, FSEQW, 2);
21103 putWReg(wd,
21104 binop(Iop_CmpEQ32Fx4,
21105 getWReg(ws),
21106 getWReg(wt)));
21107 break;
21110 case 0x01: { /* FSEQ.D */
21111 DIP("FSEQ.D w%d, w%d, w%d", wd, ws, wt);
21112 calculateMSACSR(ws, wt, FSEQD, 2);
21113 putWReg(wd,
21114 binop(Iop_CmpEQ64Fx2,
21115 getWReg(ws),
21116 getWReg(wt)));
21117 break;
21120 default:
21121 return -1;
21124 break;
21127 case 0x0B: { /* FSUEQ.df */
21128 switch (df) {
21129 case 0x00: { /* FSUEQ.W */
21130 DIP("FSUEQ.W w%d, w%d, w%d", wd, ws, wt);
21131 calculateMSACSR(ws, wt, FSUEQW, 2);
21132 putWReg(wd,
21133 binop(Iop_OrV128,
21134 binop(Iop_CmpEQ32Fx4,
21135 getWReg(ws),
21136 getWReg(wt)),
21137 binop(Iop_CmpUN32Fx4,
21138 getWReg(ws),
21139 getWReg(wt))));
21140 break;
21143 case 0x01: { /* FSUEQ.D */
21144 DIP("FSUEQ.D w%d, w%d, w%d", wd, ws, wt);
21145 calculateMSACSR(ws, wt, FSUEQD, 2);
21146 putWReg(wd,
21147 binop(Iop_OrV128,
21148 binop(Iop_CmpEQ64Fx2,
21149 getWReg(ws),
21150 getWReg(wt)),
21151 binop(Iop_CmpUN64Fx2,
21152 getWReg(ws),
21153 getWReg(wt))));
21154 break;
21157 default:
21158 return -1;
21161 break;
21164 case 0x0C: { /* FSLT.df */
21165 switch (df) {
21166 case 0x00: { /* FSLT.W */
21167 DIP("FSLT.W w%d, w%d, w%d", wd, ws, wt);
21168 calculateMSACSR(ws, wt, FSLTW, 2);
21169 putWReg(wd,
21170 binop(Iop_CmpLT32Fx4,
21171 getWReg(ws),
21172 getWReg(wt)));
21173 break;
21176 case 0x01: { /* FSLT.D */
21177 DIP("FSLT.D w%d, w%d, w%d", wd, ws, wt);
21178 calculateMSACSR(ws, wt, FSLTD, 2);
21179 putWReg(wd,
21180 binop(Iop_CmpLT64Fx2,
21181 getWReg(ws),
21182 getWReg(wt)));
21183 break;
21186 default:
21187 return -1;
21190 break;
21193 case 0x0D: { /* FSULT.df */
21194 switch (df) {
21195 case 0x00: { /* FSULT.W */
21196 DIP("FSULT.W w%d, w%d, w%d", wd, ws, wt);
21197 calculateMSACSR(ws, wt, FSULTW, 2);
21198 putWReg(wd,
21199 binop(Iop_OrV128,
21200 binop(Iop_CmpLT32Fx4,
21201 getWReg(ws),
21202 getWReg(wt)),
21203 binop(Iop_CmpUN32Fx4,
21204 getWReg(ws),
21205 getWReg(wt))));
21206 break;
21209 case 0x01: { /* FSULT.D */
21210 DIP("FSULT.D w%d, w%d, w%d", wd, ws, wt);
21211 calculateMSACSR(ws, wt, FSULTD, 2);
21212 putWReg(wd,
21213 binop(Iop_OrV128,
21214 binop(Iop_CmpLT64Fx2,
21215 getWReg(ws),
21216 getWReg(wt)),
21217 binop(Iop_CmpUN64Fx2,
21218 getWReg(ws),
21219 getWReg(wt))));
21220 break;
21223 default:
21224 return -1;
21227 break;
21230 case 0x0E: { /* FSLE.df */
21231 switch (df) {
21232 case 0x00: { /* FSLE.W */
21233 DIP("FSLE.W w%d, w%d, w%d", wd, ws, wt);
21234 calculateMSACSR(ws, wt, FSLEW, 2);
21235 putWReg(wd,
21236 binop(Iop_CmpLE32Fx4,
21237 getWReg(ws),
21238 getWReg(wt)));
21239 break;
21242 case 0x01: { /* FSLE.D */
21243 DIP("FSLE.D w%d, w%d, w%d", wd, ws, wt);
21244 calculateMSACSR(ws, wt, FSLED, 2);
21245 putWReg(wd,
21246 binop(Iop_CmpLE64Fx2,
21247 getWReg(ws),
21248 getWReg(wt)));
21249 break;
21252 default:
21253 return -1;
21256 break;
21259 case 0x0F: { /* FSULE.df */
21260 switch (df) {
21261 case 0x00: { /* FSULE.W */
21262 DIP("FSULE.W w%d, w%d, w%d", wd, ws, wt);
21263 calculateMSACSR(ws, wt, FSULEW, 2);
21264 putWReg(wd,
21265 binop(Iop_OrV128,
21266 binop(Iop_CmpLE32Fx4,
21267 getWReg(ws),
21268 getWReg(wt)),
21269 binop(Iop_CmpUN32Fx4,
21270 getWReg(ws),
21271 getWReg(wt))));
21272 break;
21275 case 0x01: { /* FSULE.D */
21276 DIP("FSULE.D w%d, w%d, w%d", wd, ws, wt);
21277 calculateMSACSR(ws, wt, FSULED, 2);
21278 putWReg(wd,
21279 binop(Iop_OrV128,
21280 binop(Iop_CmpLE64Fx2,
21281 getWReg(ws),
21282 getWReg(wt)),
21283 binop(Iop_CmpUN64Fx2,
21284 getWReg(ws),
21285 getWReg(wt))));
21286 break;
21289 default:
21290 return -1;
21293 break;
21296 default:
21297 return -1;
21300 return 0;
21303 static Int msa_3R_1B(UInt cins, UChar wd, UChar ws) { /* 3R (0x1B) */
21304 IRTemp t1, t2, t3, t4;
21305 UShort operation;
21306 UChar df, wt;
21308 operation = (cins & 0x03C00000) >> 22;
21309 df = (cins & 0x00200000) >> 21;
21310 wt = (cins & 0x001F0000) >> 16;
21312 switch (operation) {
21313 case 0x00: { /* FADD.df */
21314 switch (df) {
21315 case 0x00: { /* FADD.W */
21316 DIP("FADD.W w%d, w%d, w%d", wd, ws, wt);
21317 calculateMSACSR(ws, wt, FADDW, 2);
21318 IRExpr *rm = get_IR_roundingmode_MSA();
21319 putWReg(wd,
21320 triop(Iop_Add32Fx4, rm,
21321 getWReg(ws),
21322 getWReg(wt)));
21323 break;
21326 case 0x01: { /* FADD.D */
21327 DIP("FADD.D w%d, w%d, w%d", wd, ws, wt);
21328 calculateMSACSR(ws, wt, FADDD, 2);
21329 IRExpr *rm = get_IR_roundingmode_MSA();
21330 putWReg(wd,
21331 triop(Iop_Add64Fx2, rm,
21332 getWReg(ws),
21333 getWReg(wt)));
21334 break;
21337 default:
21338 return -1;
21341 break;
21344 case 0x01: { /* FSUB.df */
21345 switch (df) {
21346 case 0x00: { /* FSUB.W */
21347 DIP("FSUB.W w%d, w%d, w%d", wd, ws, wt);
21348 calculateMSACSR(ws, wt, FSUBW, 2);
21349 IRExpr *rm = get_IR_roundingmode_MSA();
21350 putWReg(wd,
21351 triop(Iop_Sub32Fx4, rm,
21352 getWReg(ws),
21353 getWReg(wt)));
21354 break;
21357 case 0x01: { /* FSUB.D */
21358 DIP("FSUB.D w%d, w%d, w%d", wd, ws, wt);
21359 calculateMSACSR(ws, wt, FSUBD, 2);
21360 IRExpr *rm = get_IR_roundingmode_MSA();
21361 putWReg(wd,
21362 triop(Iop_Sub64Fx2, rm,
21363 getWReg(ws),
21364 getWReg(wt)));
21365 break;
21368 default:
21369 return -1;
21372 break;
21375 case 0x02: { /* FMUL.df */
21376 switch (df) {
21377 case 0x00: { /* FMUL.W */
21378 DIP("FMUL.W w%d, w%d, w%d", wd, ws, wt);
21379 calculateMSACSR(ws, wt, FMULW, 2);
21380 IRExpr *rm = get_IR_roundingmode_MSA();
21381 putWReg(wd,
21382 triop(Iop_Mul32Fx4, rm,
21383 getWReg(ws),
21384 getWReg(wt)));
21385 break;
21388 case 0x01: { /* FMUL.D */
21389 DIP("FMUL.D w%d, w%d, w%d", wd, ws, wt);
21390 calculateMSACSR(ws, wt, FMULW, 2);
21391 IRExpr *rm = get_IR_roundingmode_MSA();
21392 putWReg(wd,
21393 triop(Iop_Mul64Fx2, rm,
21394 getWReg(ws),
21395 getWReg(wt)));
21396 break;
21399 default:
21400 return -1;
21403 break;
21406 case 0x03: { /* FDIV.df */
21407 switch (df) {
21408 case 0x00: { /* FDIV.W */
21409 DIP("FDIV.W w%d, w%d, w%d", wd, ws, wt);
21410 calculateMSACSR(ws, wt, FDIVW, 2);
21411 IRExpr *rm = get_IR_roundingmode_MSA();
21412 putWReg(wd,
21413 triop(Iop_Div32Fx4, rm,
21414 getWReg(ws),
21415 getWReg(wt)));
21416 break;
21419 case 0x01: { /* FDIV.D */
21420 DIP("FDIV.D w%d, w%d, w%d", wd, ws, wt);
21421 calculateMSACSR(ws, wt, FDIVD, 2);
21422 IRExpr *rm = get_IR_roundingmode_MSA();
21423 putWReg(wd,
21424 triop(Iop_Div64Fx2, rm,
21425 getWReg(ws),
21426 getWReg(wt)));
21427 break;
21430 default:
21431 return -1;
21434 break;
21437 case 0x04: { /* FMADD.df */
21438 switch (df) {
21439 case 0x00: { /* FMADD.W */
21440 DIP("FMADD.W w%d, w%d, w%d", wd, ws, wt);
21441 calculateMSACSR(ws, wt, FMADDW, 2);
21442 IRExpr *rm = get_IR_roundingmode_MSA();
21443 IRTemp tmp[4];
21444 Int i;
21446 for (i = 0; i < 4; i++) {
21447 tmp[i] = newTemp(Ity_F32);
21448 assign(tmp[i],
21449 qop(Iop_MAddF32, rm,
21450 unop(Iop_ReinterpI32asF32,
21451 binop(Iop_GetElem32x4,
21452 getWReg(ws),
21453 mkU8(i))),
21454 unop(Iop_ReinterpI32asF32,
21455 binop(Iop_GetElem32x4,
21456 getWReg(wt),
21457 mkU8(i))),
21458 unop(Iop_ReinterpI32asF32,
21459 binop(Iop_GetElem32x4,
21460 getWReg(wd),
21461 mkU8(i)))));
21464 putWReg(wd,
21465 binop(Iop_64HLtoV128,
21466 binop(Iop_32HLto64,
21467 unop(Iop_ReinterpF32asI32,
21468 mkexpr(tmp[3])),
21469 unop(Iop_ReinterpF32asI32,
21470 mkexpr(tmp[2]))),
21471 binop(Iop_32HLto64,
21472 unop(Iop_ReinterpF32asI32,
21473 mkexpr(tmp[1])),
21474 unop(Iop_ReinterpF32asI32,
21475 mkexpr(tmp[0])))));
21476 break;
21479 case 0x01: { /* FMADD.D */
21480 DIP("FMADD.D w%d, w%d, w%d", wd, ws, wt);
21481 calculateMSACSR(ws, wt, FMADDW, 2);
21482 IRExpr *rm = get_IR_roundingmode_MSA();
21483 IRTemp tmp[2];
21484 Int i;
21486 for (i = 0; i < 2; i++) {
21487 tmp[i] = newTemp(Ity_F64);
21488 assign(tmp[i],
21489 qop(Iop_MAddF64, rm,
21490 unop(Iop_ReinterpI64asF64,
21491 binop(Iop_GetElem64x2,
21492 getWReg(ws),
21493 mkU8(i))),
21494 unop(Iop_ReinterpI64asF64,
21495 binop(Iop_GetElem64x2,
21496 getWReg(wt),
21497 mkU8(i))),
21498 unop(Iop_ReinterpI64asF64,
21499 binop(Iop_GetElem64x2,
21500 getWReg(wd),
21501 mkU8(i)))));
21504 putWReg(wd,
21505 binop(Iop_64HLtoV128,
21506 unop(Iop_ReinterpF64asI64,
21507 mkexpr(tmp[1])),
21508 unop(Iop_ReinterpF64asI64,
21509 mkexpr(tmp[0]))));
21510 break;
21513 default:
21514 return -1;
21517 break;
21520 case 0x05: { /* FMSUB.df */
21521 switch (df) {
21522 case 0x00: { /* FMSUB.W */
21523 DIP("FMSUB.W w%d, w%d, w%d", wd, ws, wt);
21524 calculateMSACSR(ws, wt, FMADDW, 2);
21525 IRExpr *rm = get_IR_roundingmode_MSA();
21526 IRTemp tmp[4];
21527 Int i;
21529 for (i = 0; i < 4; i++) {
21530 tmp[i] = newTemp(Ity_F32);
21531 assign(tmp[i],
21532 qop(Iop_MSubF32, rm,
21533 unop(Iop_ReinterpI32asF32,
21534 binop(Iop_GetElem32x4,
21535 getWReg(ws),
21536 mkU8(i))),
21537 unop(Iop_ReinterpI32asF32,
21538 binop(Iop_GetElem32x4,
21539 getWReg(wt),
21540 mkU8(i))),
21541 unop(Iop_ReinterpI32asF32,
21542 binop(Iop_GetElem32x4,
21543 getWReg(wd),
21544 mkU8(i)))));
21547 putWReg(wd,
21548 binop(Iop_64HLtoV128,
21549 binop(Iop_32HLto64,
21550 unop(Iop_ReinterpF32asI32,
21551 mkexpr(tmp[3])),
21552 unop(Iop_ReinterpF32asI32,
21553 mkexpr(tmp[2]))),
21554 binop(Iop_32HLto64,
21555 unop(Iop_ReinterpF32asI32,
21556 mkexpr(tmp[1])),
21557 unop(Iop_ReinterpF32asI32,
21558 mkexpr(tmp[0])))));
21559 break;
21562 case 0x01: { /* FMSUB.D */
21563 DIP("FMSUB.D w%d, w%d, w%d", wd, ws, wt);
21564 calculateMSACSR(ws, wt, FMADDD, 2);
21565 IRExpr *rm = get_IR_roundingmode_MSA();
21566 IRTemp tmp[2];
21567 Int i;
21569 for (i = 0; i < 2; i++) {
21570 tmp[i] = newTemp(Ity_F64);
21571 assign(tmp[i],
21572 qop(Iop_MSubF64, rm,
21573 unop(Iop_ReinterpI64asF64,
21574 binop(Iop_GetElem64x2,
21575 getWReg(ws),
21576 mkU8(i))),
21577 unop(Iop_ReinterpI64asF64,
21578 binop(Iop_GetElem64x2,
21579 getWReg(wt),
21580 mkU8(i))),
21581 unop(Iop_ReinterpI64asF64,
21582 binop(Iop_GetElem64x2,
21583 getWReg(wd),
21584 mkU8(i)))));
21587 putWReg(wd,
21588 binop(Iop_64HLtoV128,
21589 unop(Iop_ReinterpF64asI64,
21590 mkexpr(tmp[1])),
21591 unop(Iop_ReinterpF64asI64,
21592 mkexpr(tmp[0]))));
21593 break;
21596 default:
21597 return -1;
21600 break;
21603 case 0x07: { /* FEXP2.df */
21604 switch (df) {
21605 case 0x00: { /* FEXP2.W */
21606 DIP("FEXP2.W w%d, w%d, w%d", wd, ws, wt);
21607 calculateMSACSR(ws, wt, FEXP2W, 2);
21608 IRExpr *rm = get_IR_roundingmode_MSA();
21609 putWReg(wd,
21610 triop(Iop_Scale2_32Fx4, rm,
21611 getWReg(ws),
21612 getWReg(wt)));
21613 break;
21616 case 0x01: { /* FEXP2.D */
21617 DIP("FEXP2.D w%d, w%d, w%d", wd, ws, wt);
21618 calculateMSACSR(ws, wt, FEXP2D, 2);
21619 IRExpr *rm = get_IR_roundingmode_MSA();
21620 putWReg(wd,
21621 triop(Iop_Scale2_64Fx2, rm,
21622 getWReg(ws),
21623 getWReg(wt)));
21624 break;
21627 default:
21628 return -1;
21631 break;
21634 case 0x08: { /* FEXDO.df */
21635 switch (df) {
21636 case 0x00: { /* FEXDO.H */
21637 DIP("FEXDO.H w%d, w%d, w%d", wd, ws, wt);
21638 calculateMSACSR(ws, wt, FEXDOH, 2);
21639 t1 = newTemp(Ity_I64);
21640 t2 = newTemp(Ity_I64);
21641 assign(t1,
21642 unop(Iop_F32toF16x4_DEP,
21643 getWReg(ws)));
21644 assign(t2,
21645 unop(Iop_F32toF16x4_DEP,
21646 getWReg(wt)));
21647 putWReg(wd,
21648 binop(Iop_64HLtoV128,
21649 mkexpr(t1), mkexpr(t2)));
21650 break;
21653 case 0x01: { /* FEXDO.W */
21654 DIP("FEXDO.W w%d, w%d, w%d", wd, ws, wt);
21655 calculateMSACSR(ws, wt, FEXDOW, 2);
21656 t1 = newTemp(Ity_I32);
21657 t2 = newTemp(Ity_I32);
21658 t3 = newTemp(Ity_I32);
21659 t4 = newTemp(Ity_I32);
21660 IRExpr *rm = get_IR_roundingmode_MSA();
21661 assign(t1,
21662 unop(Iop_ReinterpF32asI32,
21663 binop(Iop_F64toF32, rm,
21664 unop(Iop_ReinterpI64asF64,
21665 unop(Iop_V128to64,
21666 getWReg(ws))))));
21667 assign(t2,
21668 unop(Iop_ReinterpF32asI32,
21669 binop(Iop_F64toF32, rm,
21670 unop(Iop_ReinterpI64asF64,
21671 unop(Iop_V128HIto64,
21672 getWReg(ws))))));
21673 assign(t3,
21674 unop(Iop_ReinterpF32asI32,
21675 binop(Iop_F64toF32, rm,
21676 unop(Iop_ReinterpI64asF64,
21677 unop(Iop_V128to64,
21678 getWReg(wt))))));
21679 assign(t4,
21680 unop(Iop_ReinterpF32asI32,
21681 binop(Iop_F64toF32, rm,
21682 unop(Iop_ReinterpI64asF64,
21683 unop(Iop_V128HIto64,
21684 getWReg(wt))))));
21685 putWReg(wd,
21686 binop(Iop_64HLtoV128,
21687 binop(Iop_32HLto64,
21688 mkexpr(t2), mkexpr(t1)),
21689 binop(Iop_32HLto64,
21690 mkexpr(t4), mkexpr(t3))));
21691 break;
21694 default:
21695 return -1;
21698 break;
21701 case 0x0A: { /* FTQ.df */
21702 switch (df) {
21703 case 0x00: { /* FTQ.H */
21704 DIP("FTQ.H w%d, w%d, w%d", wd, ws, wt);
21705 calculateMSACSR(ws, wt, FTQH, 2);
21706 IRExpr *rm = get_IR_roundingmode_MSA();
21707 putWReg(wd,
21708 triop(Iop_F32x4_2toQ16x8, rm,
21709 getWReg(ws),
21710 getWReg(wt)));
21711 break;
21714 case 0x01: { /* FTQ.W */
21715 DIP("FTQ.W w%d, w%d, w%d", wd, ws, wt);
21716 calculateMSACSR(ws, wt, FTQW, 2);
21717 IRExpr *rm = get_IR_roundingmode_MSA();
21718 putWReg(wd,
21719 triop(Iop_F64x2_2toQ32x4, rm,
21720 getWReg(ws),
21721 getWReg(wt)));
21722 break;
21725 default:
21726 return -1;
21729 break;
21732 case 0x0C: { /* FMIN.df */
21733 switch (df) {
21734 case 0x00: { /* FMIN.W */
21735 DIP("FMIN.W w%d, w%d, w%d", wd, ws, wt);
21736 calculateMSACSR(ws, wt, FMINW, 2);
21737 putWReg(wd,
21738 binop(Iop_Min32Fx4,
21739 getWReg(ws),
21740 getWReg(wt)));
21741 break;
21744 case 0x01: { /* FMIN.D */
21745 DIP("FMIN.D w%d, w%d, w%d", wd, ws, wt);
21746 calculateMSACSR(ws, wt, FMINW, 2);
21747 putWReg(wd,
21748 binop(Iop_Min64Fx2,
21749 getWReg(ws),
21750 getWReg(wt)));
21751 break;
21754 default:
21755 return -1;
21758 break;
21761 case 0x0D: { /* FMIN_A.df */
21762 switch (df) {
21763 case 0x00: { /* FMIN_A.W */
21764 DIP("FMIN_A.W w%d, w%d, w%d", wd, ws, wt);
21765 calculateMSACSR(ws, wt, FMINAW, 2);
21766 t1 = newTemp(Ity_V128);
21767 t2 = newTemp(Ity_V128);
21768 t3 = newTemp(Ity_V128);
21769 t4 = newTemp(Ity_V128);
21770 assign(t1,
21771 binop(Iop_AndV128,
21772 getWReg(ws),
21773 binop(Iop_64HLtoV128,
21774 mkU64(0x7FFFFFFF7FFFFFFF),
21775 mkU64(0x7FFFFFFF7FFFFFFF))));
21776 assign(t2,
21777 binop(Iop_AndV128,
21778 getWReg(wt),
21779 binop(Iop_64HLtoV128,
21780 mkU64(0x7FFFFFFF7FFFFFFF),
21781 mkU64(0x7FFFFFFF7FFFFFFF))));
21782 assign(t3,
21783 binop(Iop_Min32Fx4,
21784 mkexpr(t2), mkexpr(t1)));
21785 assign(t4,
21786 binop(Iop_AndV128,
21787 binop(Iop_AndV128,
21788 unop(Iop_NotV128,
21789 binop(Iop_CmpUN32Fx4,
21790 mkexpr(t3),
21791 mkexpr(t3))),
21792 binop(Iop_OrV128,
21793 binop(Iop_AndV128,
21794 binop(Iop_CmpEQ32Fx4,
21795 mkexpr(t1),
21796 mkexpr(t2)),
21797 binop(Iop_OrV128,
21798 getWReg(ws),
21799 getWReg(wt))),
21800 binop(Iop_OrV128,
21801 binop(Iop_AndV128,
21802 binop(Iop_OrV128,
21803 binop(Iop_CmpUN32Fx4,
21804 mkexpr(t1),
21805 mkexpr(t1)),
21806 binop(Iop_CmpLT32Fx4,
21807 mkexpr(t3),
21808 mkexpr(t1))),
21809 getWReg(wt)),
21810 binop(Iop_AndV128,
21811 binop(Iop_OrV128,
21812 binop(Iop_CmpUN32Fx4,
21813 mkexpr(t2),
21814 mkexpr(t2)),
21815 binop(Iop_CmpLT32Fx4,
21816 mkexpr(t3),
21817 mkexpr(t2))),
21818 getWReg(ws))))),
21819 binop(Iop_64HLtoV128,
21820 mkU64(0x8000000080000000),
21821 mkU64(0x8000000080000000))));
21822 putWReg(wd,
21823 binop(Iop_OrV128,
21824 mkexpr(t3), mkexpr(t4)));
21825 break;
21828 case 0x01: { /* FMIN_A.D */
21829 DIP("FMIN_A.D w%d, w%d, w%d", wd, ws, wt);
21830 calculateMSACSR(ws, wt, FMINAD, 2);
21831 t1 = newTemp(Ity_V128);
21832 t2 = newTemp(Ity_V128);
21833 t3 = newTemp(Ity_V128);
21834 t4 = newTemp(Ity_V128);
21835 assign(t1,
21836 binop(Iop_AndV128,
21837 getWReg(ws),
21838 binop(Iop_64HLtoV128,
21839 mkU64(0x7FFFFFFFFFFFFFFF),
21840 mkU64(0x7FFFFFFFFFFFFFFF))));
21841 assign(t2,
21842 binop(Iop_AndV128,
21843 getWReg(wt),
21844 binop(Iop_64HLtoV128,
21845 mkU64(0x7FFFFFFFFFFFFFFF),
21846 mkU64(0x7FFFFFFFFFFFFFFF))));
21847 assign(t3,
21848 binop(Iop_Min64Fx2,
21849 mkexpr(t2), mkexpr(t1)));
21850 assign(t4,
21851 binop(Iop_AndV128,
21852 binop(Iop_AndV128,
21853 unop(Iop_NotV128,
21854 binop(Iop_CmpUN64Fx2,
21855 mkexpr(t3),
21856 mkexpr(t3))),
21857 binop(Iop_OrV128,
21858 binop(Iop_AndV128,
21859 binop(Iop_CmpEQ64Fx2,
21860 mkexpr(t1),
21861 mkexpr(t2)),
21862 binop(Iop_OrV128,
21863 getWReg(ws),
21864 getWReg(wt))),
21865 binop(Iop_OrV128,
21866 binop(Iop_AndV128,
21867 binop(Iop_OrV128,
21868 binop(Iop_CmpUN64Fx2,
21869 mkexpr(t1),
21870 mkexpr(t1)),
21871 binop(Iop_CmpLT64Fx2,
21872 mkexpr(t3),
21873 mkexpr(t1))),
21874 getWReg(wt)),
21875 binop(Iop_AndV128,
21876 binop(Iop_OrV128,
21877 binop(Iop_CmpUN64Fx2,
21878 mkexpr(t2),
21879 mkexpr(t2)),
21880 binop(Iop_CmpLT64Fx2,
21881 mkexpr(t3),
21882 mkexpr(t2))),
21883 getWReg(ws))))),
21884 binop(Iop_64HLtoV128,
21885 mkU64(0x8000000000000000),
21886 mkU64(0x8000000000000000))));
21887 putWReg(wd,
21888 binop(Iop_OrV128,
21889 mkexpr(t3), mkexpr(t4)));
21890 break;
21893 default:
21894 return -1;
21897 break;
21900 case 0x0E: { /* FMAX.df */
21901 switch (df) {
21902 case 0x00: { /* FMAX.W */
21903 DIP("FMAX.W w%d, w%d, w%d", wd, ws, wt);
21904 calculateMSACSR(ws, wt, FMAXW, 2);
21905 putWReg(wd,
21906 binop(Iop_Max32Fx4,
21907 getWReg(ws),
21908 getWReg(wt)));
21909 break;
21912 case 0x01: { /* FMAX.D */
21913 DIP("FMAX.D w%d, w%d, w%d", wd, ws, wt);
21914 calculateMSACSR(ws, wt, FMAXW, 2);
21915 putWReg(wd,
21916 binop(Iop_Max64Fx2,
21917 getWReg(ws),
21918 getWReg(wt)));
21919 break;
21922 default:
21923 return -1;
21926 break;
21929 case 0x0F: { /* FMAX_A.df */
21930 switch (df) {
21931 case 0x00: { /* FMAX_A.W */
21932 DIP("FMAX_A.W w%d, w%d, w%d", wd, ws, wt);
21933 calculateMSACSR(ws, wt, FMAXAW, 2);
21934 t1 = newTemp(Ity_V128);
21935 t2 = newTemp(Ity_V128);
21936 t3 = newTemp(Ity_V128);
21937 t4 = newTemp(Ity_V128);
21938 assign(t1,
21939 binop(Iop_AndV128,
21940 getWReg(ws),
21941 binop(Iop_64HLtoV128,
21942 mkU64(0x7FFFFFFF7FFFFFFF),
21943 mkU64(0x7FFFFFFF7FFFFFFF))));
21944 assign(t2,
21945 binop(Iop_AndV128,
21946 getWReg(wt),
21947 binop(Iop_64HLtoV128,
21948 mkU64(0x7FFFFFFF7FFFFFFF),
21949 mkU64(0x7FFFFFFF7FFFFFFF))));
21950 assign(t3,
21951 binop(Iop_Max32Fx4,
21952 mkexpr(t2), mkexpr(t1)));
21953 assign(t4,
21954 binop(Iop_AndV128,
21955 binop(Iop_AndV128,
21956 unop(Iop_NotV128,
21957 binop(Iop_CmpUN32Fx4,
21958 mkexpr(t3),
21959 mkexpr(t3))),
21960 binop(Iop_OrV128,
21961 binop(Iop_AndV128,
21962 binop(Iop_CmpEQ32Fx4,
21963 mkexpr(t1),
21964 mkexpr(t2)),
21965 binop(Iop_AndV128,
21966 getWReg(ws),
21967 getWReg(wt))),
21968 binop(Iop_OrV128,
21969 binop(Iop_AndV128,
21970 binop(Iop_OrV128,
21971 binop(Iop_CmpUN32Fx4,
21972 mkexpr(t1),
21973 mkexpr(t1)),
21974 binop(Iop_CmpLT32Fx4,
21975 mkexpr(t1),
21976 mkexpr(t3))),
21977 getWReg(wt)),
21978 binop(Iop_AndV128,
21979 binop(Iop_OrV128,
21980 binop(Iop_CmpUN32Fx4,
21981 mkexpr(t2),
21982 mkexpr(t2)),
21983 binop(Iop_CmpLT32Fx4,
21984 mkexpr(t2),
21985 mkexpr(t3))),
21986 getWReg(ws))))),
21987 binop(Iop_64HLtoV128,
21988 mkU64(0x8000000080000000),
21989 mkU64(0x8000000080000000))));
21990 putWReg(wd,
21991 binop(Iop_OrV128,
21992 mkexpr(t3), mkexpr(t4)));
21993 break;
21996 case 0x01: { /* FMAX_A.D */
21997 DIP("FMAX_A.D w%d, w%d, w%d", wd, ws, wt);
21998 calculateMSACSR(ws, wt, FMAXAD, 2);
21999 t1 = newTemp(Ity_V128);
22000 t2 = newTemp(Ity_V128);
22001 t3 = newTemp(Ity_V128);
22002 t4 = newTemp(Ity_V128);
22003 assign(t1,
22004 binop(Iop_AndV128,
22005 getWReg(ws),
22006 binop(Iop_64HLtoV128,
22007 mkU64(0x7FFFFFFFFFFFFFFF),
22008 mkU64(0x7FFFFFFFFFFFFFFF))));
22009 assign(t2,
22010 binop(Iop_AndV128,
22011 getWReg(wt),
22012 binop(Iop_64HLtoV128,
22013 mkU64(0x7FFFFFFFFFFFFFFF),
22014 mkU64(0x7FFFFFFFFFFFFFFF))));
22015 assign(t3,
22016 binop(Iop_Max64Fx2,
22017 mkexpr(t2), mkexpr(t1)));
22018 assign(t4,
22019 binop(Iop_AndV128,
22020 binop(Iop_AndV128,
22021 unop(Iop_NotV128,
22022 binop(Iop_CmpUN64Fx2,
22023 mkexpr(t3),
22024 mkexpr(t3))),
22025 binop(Iop_OrV128,
22026 binop(Iop_AndV128,
22027 binop(Iop_CmpEQ64Fx2,
22028 mkexpr(t1),
22029 mkexpr(t2)),
22030 binop(Iop_AndV128,
22031 getWReg(ws),
22032 getWReg(wt))),
22033 binop(Iop_OrV128,
22034 binop(Iop_AndV128,
22035 binop(Iop_OrV128,
22036 binop(Iop_CmpUN64Fx2,
22037 mkexpr(t1),
22038 mkexpr(t1)),
22039 binop(Iop_CmpLT64Fx2,
22040 mkexpr(t1),
22041 mkexpr(t3))),
22042 getWReg(wt)),
22043 binop(Iop_AndV128,
22044 binop(Iop_OrV128,
22045 binop(Iop_CmpUN64Fx2,
22046 mkexpr(t2),
22047 mkexpr(t2)),
22048 binop(Iop_CmpLT64Fx2,
22049 mkexpr(t2),
22050 mkexpr(t3))),
22051 getWReg(ws))))),
22052 binop(Iop_64HLtoV128,
22053 mkU64(0x8000000000000000),
22054 mkU64(0x8000000000000000))));
22055 putWReg(wd,
22056 binop(Iop_OrV128,
22057 mkexpr(t3), mkexpr(t4)));
22058 break;
22061 default:
22062 return -1;
22065 break;
22068 default:
22069 return -1;
22072 return 0;
22075 static Int msa_3R_1C(UInt cins, UChar wd, UChar ws) { /* 3R (0x1C) */
22076 IRTemp t1, t2, t3, t4, t5, t6;
22077 UShort operation;
22078 UChar df, wt;
22080 operation = (cins & 0x03C00000) >> 22;
22081 df = (cins & 0x00200000) >> 21;
22082 wt = (cins & 0x001F0000) >> 16;
22084 switch (operation) {
22085 case 0x01: { /* FCOR.df */
22086 switch (df) {
22087 case 0x00: { /* FCOR.W */
22088 DIP("FCOR.W w%d, w%d, w%d", wd, ws, wt);
22089 calculateMSACSR(ws, wt, FCORW, 2);
22090 putWReg(wd,
22091 unop(Iop_NotV128,
22092 binop(Iop_CmpUN32Fx4,
22093 getWReg(ws),
22094 getWReg(wt))));
22095 break;
22098 case 0x01: { /* FCOR.D */
22099 DIP("FCOR.D w%d, w%d, w%d", wd, ws, wt);
22100 calculateMSACSR(ws, wt, FCORD, 2);
22101 putWReg(wd,
22102 unop(Iop_NotV128,
22103 binop(Iop_CmpUN64Fx2,
22104 getWReg(ws),
22105 getWReg(wt))));
22106 break;
22109 default:
22110 return -1;
22113 break;
22116 case 0x02: { /* FCUNE.df */
22117 switch (df) {
22118 case 0x00: { /* FCUNE.W */
22119 DIP("FCUNE.W w%d, w%d, w%d", wd, ws, wt);
22120 calculateMSACSR(ws, wt, FCUNEW, 2);
22121 putWReg(wd,
22122 unop(Iop_NotV128,
22123 binop(Iop_CmpEQ32Fx4,
22124 getWReg(ws),
22125 getWReg(wt))));
22126 break;
22129 case 0x01: { /* FCUNE.D */
22130 DIP("FCUNE.D w%d, w%d, w%d", wd, ws, wt);
22131 calculateMSACSR(ws, wt, FCUNED, 2);
22132 putWReg(wd,
22133 unop(Iop_NotV128,
22134 binop(Iop_CmpEQ64Fx2,
22135 getWReg(ws),
22136 getWReg(wt))));
22137 break;
22140 default:
22141 return -1;
22144 break;
22147 case 0x03: { /* FCNE.df */
22148 switch (df) {
22149 case 0x00: { /* FCNE.W */
22150 DIP("FCNE.W w%d, w%d, w%d", wd, ws, wt);
22151 calculateMSACSR(ws, wt, FCNEW, 2);
22152 putWReg(wd,
22153 binop(Iop_XorV128,
22154 unop(Iop_NotV128,
22155 binop(Iop_CmpEQ32Fx4,
22156 getWReg(ws),
22157 getWReg(wt))),
22158 binop(Iop_CmpUN32Fx4,
22159 getWReg(ws),
22160 getWReg(wt))));
22161 break;
22164 case 0x01: { /* FCNE.D */
22165 DIP("FCNE.D w%d, w%d, w%d", wd, ws, wt);
22166 calculateMSACSR(ws, wt, FCNED, 2);
22167 putWReg(wd,
22168 binop(Iop_XorV128,
22169 unop(Iop_NotV128,
22170 binop(Iop_CmpEQ64Fx2,
22171 getWReg(ws),
22172 getWReg(wt))),
22173 binop(Iop_CmpUN64Fx2,
22174 getWReg(ws),
22175 getWReg(wt))));
22176 break;
22179 default:
22180 return -1;
22183 break;
22186 case 0x04: { /* MUL_Q.df */
22187 switch (df) {
22188 case 0x00: { /* MUL_Q.H */
22189 DIP("MUL_Q.H w%d, w%d, w%d", wd, ws, wt);
22190 t1 = newTemp(Ity_V128);
22191 t2 = newTemp(Ity_V128);
22192 t3 = newTemp(Ity_V128);
22193 assign(t1, getWReg(ws));
22194 assign(t2, getWReg(wt));
22195 assign(t3,
22196 binop(Iop_QDMulHi16Sx8,
22197 mkexpr(t1), mkexpr(t2)));
22198 putWReg(wd, mkexpr(t3));
22199 break;
22202 case 0x01: { /* MUL_Q.W */
22203 DIP("MUL_Q.W w%d, w%d, w%d", wd, ws, wt);
22204 t1 = newTemp(Ity_V128);
22205 t2 = newTemp(Ity_V128);
22206 t3 = newTemp(Ity_V128);
22207 assign(t1, getWReg(ws));
22208 assign(t2, getWReg(wt));
22209 assign(t3,
22210 binop(Iop_QDMulHi32Sx4,
22211 mkexpr(t1), mkexpr(t2)));
22212 putWReg(wd, mkexpr(t3));
22213 break;
22216 default:
22217 return -1;
22220 break;
22223 case 0x05: { /* MADD_Q.df */
22224 switch (df) {
22225 case 0x00: { /* MADD_Q.W */
22226 DIP("MADD_Q.W w%d, w%d, w%d", wd, ws, wt);
22227 t1 = newTemp(Ity_V128);
22228 t2 = newTemp(Ity_V128);
22229 t3 = newTemp(Ity_V128);
22230 t4 = newTemp(Ity_V128);
22231 t5 = newTemp(Ity_V128);
22232 t6 = newTemp(Ity_V128);
22233 assign(t1, // even
22234 binop(Iop_SarN32x4,
22235 binop(Iop_InterleaveEvenLanes16x8,
22236 getWReg(ws),
22237 getWReg(ws)),
22238 mkU8(16)));
22239 assign(t2, // odd
22240 binop(Iop_SarN32x4,
22241 getWReg(ws), mkU8(16)));
22242 assign(t3, // even
22243 binop(Iop_SarN32x4,
22244 binop(Iop_InterleaveEvenLanes16x8,
22245 getWReg(wt),
22246 getWReg(wt)),
22247 mkU8(16)));
22248 assign(t4, // odd
22249 binop(Iop_SarN32x4,
22250 getWReg(wt), mkU8(16)));
22251 assign(t5,
22252 binop(Iop_Add32x4,
22253 binop(Iop_ShlN32x4,
22254 binop(Iop_SarN32x4,
22255 binop(Iop_InterleaveEvenLanes16x8,
22256 getWReg(wd),
22257 getWReg(wd)),
22258 mkU8(16)),
22259 mkU8(15)),
22260 binop(Iop_Mul32x4,
22261 mkexpr(t1), mkexpr(t3))));
22262 assign(t6,
22263 binop(Iop_Add32x4,
22264 binop(Iop_ShlN32x4,
22265 binop(Iop_SarN32x4,
22266 getWReg(wd),
22267 mkU8(16)),
22268 mkU8(15)),
22269 binop(Iop_Mul32x4,
22270 mkexpr(t2), mkexpr(t4))));
22271 putWReg(wd,
22272 binop(Iop_InterleaveEvenLanes16x8,
22273 binop(Iop_QandQSarNnarrow32Sto16Sx4,
22274 mkexpr(t6), mkU8(15)),
22275 binop(Iop_QandQSarNnarrow32Sto16Sx4,
22276 mkexpr(t5), mkU8(15))));
22277 break;
22280 case 0x01: { /* MADD_Q.W */
22281 DIP("MADD_Q.W w%d, w%d, w%d", wd, ws, wt);
22282 t1 = newTemp(Ity_V128);
22283 t2 = newTemp(Ity_V128);
22284 t3 = newTemp(Ity_V128);
22285 t4 = newTemp(Ity_V128);
22286 t5 = newTemp(Ity_V128);
22287 t6 = newTemp(Ity_V128);
22288 assign(t1, // even
22289 binop(Iop_SarN64x2,
22290 binop(Iop_InterleaveEvenLanes32x4,
22291 getWReg(ws),
22292 getWReg(ws)),
22293 mkU8(32)));
22294 assign(t2, // odd
22295 binop(Iop_SarN64x2,
22296 getWReg(ws), mkU8(32)));
22297 assign(t3, // even
22298 binop(Iop_SarN64x2,
22299 binop(Iop_InterleaveEvenLanes32x4,
22300 getWReg(wt),
22301 getWReg(wt)),
22302 mkU8(32)));
22303 assign(t4, // odd
22304 binop(Iop_SarN64x2,
22305 getWReg(wt), mkU8(32)));
22306 assign(t5,
22307 binop(Iop_Add64x2,
22308 binop(Iop_ShlN64x2,
22309 binop(Iop_SarN64x2,
22310 binop(Iop_InterleaveEvenLanes32x4,
22311 getWReg(wd),
22312 getWReg(wd)),
22313 mkU8(32)),
22314 mkU8(31)),
22315 binop(Iop_64HLtoV128,
22316 binop(Iop_Mul64,
22317 unop(Iop_V128HIto64,
22318 mkexpr(t1)),
22319 unop(Iop_V128HIto64,
22320 mkexpr(t3))),
22321 binop(Iop_Mul64,
22322 unop(Iop_V128to64,
22323 mkexpr(t1)),
22324 unop(Iop_V128to64,
22325 mkexpr(t3))))));
22326 assign(t6,
22327 binop(Iop_Add64x2,
22328 binop(Iop_ShlN64x2,
22329 binop(Iop_SarN64x2,
22330 getWReg(wd),
22331 mkU8(32)),
22332 mkU8(31)),
22333 binop(Iop_64HLtoV128,
22334 binop(Iop_Mul64,
22335 unop(Iop_V128HIto64,
22336 mkexpr(t2)),
22337 unop(Iop_V128HIto64,
22338 mkexpr(t4))),
22339 binop(Iop_Mul64,
22340 unop(Iop_V128to64,
22341 mkexpr(t2)),
22342 unop(Iop_V128to64,
22343 mkexpr(t4))))));
22344 putWReg(wd,
22345 binop(Iop_InterleaveEvenLanes32x4,
22346 binop(Iop_QandQSarNnarrow64Sto32Sx2,
22347 mkexpr(t6), mkU8(31)),
22348 binop(Iop_QandQSarNnarrow64Sto32Sx2,
22349 mkexpr(t5), mkU8(31))));
22350 break;
22353 default:
22354 return -1;
22357 break;
22360 case 0x06: { /* MSUB_Q.df */
22361 switch (df) {
22362 case 0x00: { /* MSUB_Q.H */
22363 DIP("MSUB_Q.H w%d, w%d, w%d", wd, ws, wt);
22364 t1 = newTemp(Ity_V128);
22365 t2 = newTemp(Ity_V128);
22366 t3 = newTemp(Ity_V128);
22367 t4 = newTemp(Ity_V128);
22368 t5 = newTemp(Ity_V128);
22369 t6 = newTemp(Ity_V128);
22370 assign(t1, // even
22371 binop(Iop_SarN32x4,
22372 binop(Iop_InterleaveEvenLanes16x8,
22373 getWReg(ws),
22374 getWReg(ws)),
22375 mkU8(16)));
22376 assign(t2, // odd
22377 binop(Iop_SarN32x4,
22378 getWReg(ws), mkU8(16)));
22379 assign(t3, // even
22380 binop(Iop_SarN32x4,
22381 binop(Iop_InterleaveEvenLanes16x8,
22382 getWReg(wt),
22383 getWReg(wt)),
22384 mkU8(16)));
22385 assign(t4, // odd
22386 binop(Iop_SarN32x4,
22387 getWReg(wt), mkU8(16)));
22388 assign(t5,
22389 binop(Iop_Sub32x4,
22390 binop(Iop_ShlN32x4,
22391 binop(Iop_SarN32x4,
22392 binop(Iop_InterleaveEvenLanes16x8,
22393 getWReg(wd),
22394 getWReg(wd)),
22395 mkU8(16)),
22396 mkU8(15)),
22397 binop(Iop_Mul32x4,
22398 mkexpr(t1), mkexpr(t3))));
22399 assign(t6,
22400 binop(Iop_Sub32x4,
22401 binop(Iop_ShlN32x4,
22402 binop(Iop_SarN32x4,
22403 getWReg(wd),
22404 mkU8(16)),
22405 mkU8(15)),
22406 binop(Iop_Mul32x4,
22407 mkexpr(t2), mkexpr(t4))));
22408 putWReg(wd,
22409 binop(Iop_InterleaveEvenLanes16x8,
22410 binop(Iop_QandQSarNnarrow32Sto16Sx4,
22411 mkexpr(t6), mkU8(15)),
22412 binop(Iop_QandQSarNnarrow32Sto16Sx4,
22413 mkexpr(t5), mkU8(15))));
22414 break;
22417 case 0x01: { /* MSUB_Q.W */
22418 DIP("MSUB_Q.W w%d, w%d, w%d", wd, ws, wt);
22419 t1 = newTemp(Ity_V128);
22420 t2 = newTemp(Ity_V128);
22421 t3 = newTemp(Ity_V128);
22422 t4 = newTemp(Ity_V128);
22423 t5 = newTemp(Ity_V128);
22424 t6 = newTemp(Ity_V128);
22425 assign(t1, // even
22426 binop(Iop_SarN64x2,
22427 binop(Iop_InterleaveEvenLanes32x4,
22428 getWReg(ws),
22429 getWReg(ws)),
22430 mkU8(32)));
22431 assign(t2, // odd
22432 binop(Iop_SarN64x2,
22433 getWReg(ws), mkU8(32)));
22434 assign(t3, // even
22435 binop(Iop_SarN64x2,
22436 binop(Iop_InterleaveEvenLanes32x4,
22437 getWReg(wt),
22438 getWReg(wt)),
22439 mkU8(32)));
22440 assign(t4, // odd
22441 binop(Iop_SarN64x2,
22442 getWReg(wt), mkU8(32)));
22443 assign(t5,
22444 binop(Iop_Sub64x2,
22445 binop(Iop_ShlN64x2,
22446 binop(Iop_SarN64x2,
22447 binop(Iop_InterleaveEvenLanes32x4,
22448 getWReg(wd),
22449 getWReg(wd)),
22450 mkU8(32)),
22451 mkU8(31)),
22452 binop(Iop_64HLtoV128,
22453 binop(Iop_Mul64,
22454 unop(Iop_V128HIto64,
22455 mkexpr(t1)),
22456 unop(Iop_V128HIto64,
22457 mkexpr(t3))),
22458 binop(Iop_Mul64,
22459 unop(Iop_V128to64,
22460 mkexpr(t1)),
22461 unop(Iop_V128to64,
22462 mkexpr(t3))))));
22463 assign(t6,
22464 binop(Iop_Sub64x2,
22465 binop(Iop_ShlN64x2,
22466 binop(Iop_SarN64x2,
22467 getWReg(wd),
22468 mkU8(32)),
22469 mkU8(31)),
22470 binop(Iop_64HLtoV128,
22471 binop(Iop_Mul64,
22472 unop(Iop_V128HIto64,
22473 mkexpr(t2)),
22474 unop(Iop_V128HIto64,
22475 mkexpr(t4))),
22476 binop(Iop_Mul64,
22477 unop(Iop_V128to64,
22478 mkexpr(t2)),
22479 unop(Iop_V128to64,
22480 mkexpr(t4))))));
22481 putWReg(wd,
22482 binop(Iop_InterleaveEvenLanes32x4,
22483 binop(Iop_QandQSarNnarrow64Sto32Sx2,
22484 mkexpr(t6), mkU8(31)),
22485 binop(Iop_QandQSarNnarrow64Sto32Sx2,
22486 mkexpr(t5), mkU8(31))));
22487 break;
22490 default:
22491 return -1;
22494 break;
22497 case 0x09: { /* FSOR.df */
22498 switch (df) {
22499 case 0x00: { /* FSOR.W */
22500 DIP("FSOR.W w%d, w%d, w%d", wd, ws, wt);
22501 calculateMSACSR(ws, wt, FSORW, 2);
22502 putWReg(wd,
22503 unop(Iop_NotV128,
22504 binop(Iop_CmpUN32Fx4,
22505 getWReg(ws),
22506 getWReg(wt))));
22507 break;
22510 case 0x01: { /* FSOR.D */
22511 DIP("FSOR.D w%d, w%d, w%d", wd, ws, wt);
22512 calculateMSACSR(ws, wt, FSORD, 2);
22513 putWReg(wd,
22514 unop(Iop_NotV128,
22515 binop(Iop_CmpUN64Fx2,
22516 getWReg(ws),
22517 getWReg(wt))));
22518 break;
22521 default:
22522 return -1;
22525 break;
22528 case 0x0A: { /* FSUNE.df */
22529 switch (df) {
22530 case 0x00: { /* FSUNE.W */
22531 DIP("FSUNE.W w%d, w%d, w%d", wd, ws, wt);
22532 calculateMSACSR(ws, wt, FSUNEW, 2);
22533 putWReg(wd,
22534 unop(Iop_NotV128,
22535 binop(Iop_CmpEQ32Fx4,
22536 getWReg(ws),
22537 getWReg(wt))));
22538 break;
22541 case 0x01: { /* FSUNE.D */
22542 DIP("FSUNE.D w%d, w%d, w%d", wd, ws, wt);
22543 calculateMSACSR(ws, wt, FSUNED, 2);
22544 putWReg(wd,
22545 unop(Iop_NotV128,
22546 binop(Iop_CmpEQ64Fx2,
22547 getWReg(ws),
22548 getWReg(wt))));
22549 break;
22552 default:
22553 return -1;
22556 break;
22559 case 0x0B: { /* FSNE.df */
22560 switch (df) {
22561 case 0x00: { /* FSNE.W */
22562 DIP("FSNE.W w%d, w%d, w%d", wd, ws, wt);
22563 calculateMSACSR(ws, wt, FSNEW, 2);
22564 putWReg(wd,
22565 binop(Iop_XorV128,
22566 unop(Iop_NotV128,
22567 binop(Iop_CmpEQ32Fx4,
22568 getWReg(ws),
22569 getWReg(wt))),
22570 binop(Iop_CmpUN32Fx4,
22571 getWReg(ws),
22572 getWReg(wt))));
22573 break;
22576 case 0x01: { /* FSNE.D */
22577 DIP("FSNE.D w%d, w%d, w%d", wd, ws, wt);
22578 calculateMSACSR(ws, wt, FSNED, 2);
22579 putWReg(wd,
22580 binop(Iop_XorV128,
22581 unop(Iop_NotV128,
22582 binop(Iop_CmpEQ64Fx2,
22583 getWReg(ws),
22584 getWReg(wt))),
22585 binop(Iop_CmpUN64Fx2,
22586 getWReg(ws),
22587 getWReg(wt))));
22588 break;
22591 default:
22592 return -1;
22595 break;
22598 case 0x0C: { /* MULR_Q.df */
22599 switch (df) {
22600 case 0x00: { /* MULR_Q.H */
22601 DIP("MULR_Q.H w%d, w%d, w%d", wd, ws, wt);
22602 t1 = newTemp(Ity_V128);
22603 t2 = newTemp(Ity_V128);
22604 t3 = newTemp(Ity_V128);
22605 assign(t1, getWReg(ws));
22606 assign(t2, getWReg(wt));
22607 assign(t3, binop(Iop_QRDMulHi16Sx8,
22608 mkexpr(t1), mkexpr(t2)));
22609 putWReg(wd, mkexpr(t3));
22610 break;
22613 case 0x01: { /* MULR_Q.W */
22614 DIP("MULR_Q.W w%d, w%d, w%d", wd, ws, wt);
22615 t1 = newTemp(Ity_V128);
22616 t2 = newTemp(Ity_V128);
22617 t3 = newTemp(Ity_V128);
22618 assign(t1, getWReg(ws));
22619 assign(t2, getWReg(wt));
22620 assign(t3, binop(Iop_QRDMulHi32Sx4,
22621 mkexpr(t1), mkexpr(t2)));
22622 putWReg(wd, mkexpr(t3));
22623 break;
22626 default:
22627 return -1;
22630 break;
22633 case 0x0D: { /* MADDR_Q.df */
22634 switch (df) {
22635 case 0x00: { /* MADDR_Q.W */
22636 DIP("MADDR_Q.W w%d, w%d, w%d", wd, ws, wt);
22637 t1 = newTemp(Ity_V128);
22638 t2 = newTemp(Ity_V128);
22639 t3 = newTemp(Ity_V128);
22640 t4 = newTemp(Ity_V128);
22641 t5 = newTemp(Ity_V128);
22642 t6 = newTemp(Ity_V128);
22643 assign(t1, // even
22644 binop(Iop_SarN32x4,
22645 binop(Iop_InterleaveEvenLanes16x8,
22646 getWReg(ws),
22647 getWReg(ws)),
22648 mkU8(16)));
22649 assign(t2, // odd
22650 binop(Iop_SarN32x4,
22651 getWReg(ws), mkU8(16)));
22652 assign(t3, // even
22653 binop(Iop_SarN32x4,
22654 binop(Iop_InterleaveEvenLanes16x8,
22655 getWReg(wt),
22656 getWReg(wt)),
22657 mkU8(16)));
22658 assign(t4, // odd
22659 binop(Iop_SarN32x4,
22660 getWReg(wt), mkU8(16)));
22661 assign(t5,
22662 binop(Iop_Add32x4,
22663 binop(Iop_ShlN32x4,
22664 binop(Iop_SarN32x4,
22665 binop(Iop_InterleaveEvenLanes16x8,
22666 getWReg(wd),
22667 getWReg(wd)),
22668 mkU8(16)),
22669 mkU8(15)),
22670 binop(Iop_Mul32x4,
22671 mkexpr(t1), mkexpr(t3))));
22672 assign(t6,
22673 binop(Iop_Add32x4,
22674 binop(Iop_ShlN32x4,
22675 binop(Iop_SarN32x4,
22676 getWReg(wd),
22677 mkU8(16)),
22678 mkU8(15)),
22679 binop(Iop_Mul32x4,
22680 mkexpr(t2), mkexpr(t4))));
22681 putWReg(wd,
22682 binop(Iop_InterleaveEvenLanes16x8,
22683 binop(Iop_QandQRSarNnarrow32Sto16Sx4,
22684 mkexpr(t6), mkU8(15)),
22685 binop(Iop_QandQRSarNnarrow32Sto16Sx4,
22686 mkexpr(t5), mkU8(15))));
22687 break;
22690 case 0x01: { /* MADDR_Q.D */
22691 DIP("MADDR_Q.D w%d, w%d, w%d", wd, ws, wt);
22692 t1 = newTemp(Ity_V128);
22693 t2 = newTemp(Ity_V128);
22694 t3 = newTemp(Ity_V128);
22695 t4 = newTemp(Ity_V128);
22696 t5 = newTemp(Ity_V128);
22697 t6 = newTemp(Ity_V128);
22698 assign(t1, // even
22699 binop(Iop_SarN64x2,
22700 binop(Iop_InterleaveEvenLanes32x4,
22701 getWReg(ws),
22702 getWReg(ws)),
22703 mkU8(32)));
22704 assign(t2, // odd
22705 binop(Iop_SarN64x2,
22706 getWReg(ws), mkU8(32)));
22707 assign(t3, // even
22708 binop(Iop_SarN64x2,
22709 binop(Iop_InterleaveEvenLanes32x4,
22710 getWReg(wt),
22711 getWReg(wt)),
22712 mkU8(32)));
22713 assign(t4, // odd
22714 binop(Iop_SarN64x2,
22715 getWReg(wt), mkU8(32)));
22716 assign(t5,
22717 binop(Iop_Add64x2,
22718 binop(Iop_ShlN64x2,
22719 binop(Iop_SarN64x2,
22720 binop(Iop_InterleaveEvenLanes32x4,
22721 getWReg(wd),
22722 getWReg(wd)),
22723 mkU8(32)),
22724 mkU8(31)),
22725 binop(Iop_64HLtoV128,
22726 binop(Iop_Mul64,
22727 unop(Iop_V128HIto64,
22728 mkexpr(t1)),
22729 unop(Iop_V128HIto64,
22730 mkexpr(t3))),
22731 binop(Iop_Mul64,
22732 unop(Iop_V128to64,
22733 mkexpr(t1)),
22734 unop(Iop_V128to64,
22735 mkexpr(t3))))));
22736 assign(t6,
22737 binop(Iop_Add64x2,
22738 binop(Iop_ShlN64x2,
22739 binop(Iop_SarN64x2,
22740 getWReg(wd),
22741 mkU8(32)),
22742 mkU8(31)),
22743 binop(Iop_64HLtoV128,
22744 binop(Iop_Mul64,
22745 unop(Iop_V128HIto64,
22746 mkexpr(t2)),
22747 unop(Iop_V128HIto64,
22748 mkexpr(t4))),
22749 binop(Iop_Mul64,
22750 unop(Iop_V128to64,
22751 mkexpr(t2)),
22752 unop(Iop_V128to64,
22753 mkexpr(t4))))));
22754 putWReg(wd,
22755 binop(Iop_InterleaveEvenLanes32x4,
22756 binop(Iop_QandQRSarNnarrow64Sto32Sx2,
22757 mkexpr(t6), mkU8(31)),
22758 binop(Iop_QandQRSarNnarrow64Sto32Sx2,
22759 mkexpr(t5), mkU8(31))));
22760 break;
22763 default:
22764 return -1;
22767 break;
22770 case 0x0E: { /* MSUBR_Q.df */
22771 switch (df) {
22772 case 0x00: { /* MSUBR_Q.W */
22773 DIP("MSUBR_Q.W w%d, w%d, w%d", wd, ws, wt);
22774 t1 = newTemp(Ity_V128);
22775 t2 = newTemp(Ity_V128);
22776 t3 = newTemp(Ity_V128);
22777 t4 = newTemp(Ity_V128);
22778 t5 = newTemp(Ity_V128);
22779 t6 = newTemp(Ity_V128);
22780 assign(t1, // even
22781 binop(Iop_SarN32x4,
22782 binop(Iop_InterleaveEvenLanes16x8,
22783 getWReg(ws),
22784 getWReg(ws)),
22785 mkU8(16)));
22786 assign(t2, // odd
22787 binop(Iop_SarN32x4,
22788 getWReg(ws), mkU8(16)));
22789 assign(t3, // even
22790 binop(Iop_SarN32x4,
22791 binop(Iop_InterleaveEvenLanes16x8,
22792 getWReg(wt),
22793 getWReg(wt)),
22794 mkU8(16)));
22795 assign(t4, // odd
22796 binop(Iop_SarN32x4,
22797 getWReg(wt), mkU8(16)));
22798 assign(t5,
22799 binop(Iop_Sub32x4,
22800 binop(Iop_ShlN32x4,
22801 binop(Iop_SarN32x4,
22802 binop(Iop_InterleaveEvenLanes16x8,
22803 getWReg(wd),
22804 getWReg(wd)),
22805 mkU8(16)),
22806 mkU8(15)),
22807 binop(Iop_Mul32x4,
22808 mkexpr(t1), mkexpr(t3))));
22809 assign(t6,
22810 binop(Iop_Sub32x4,
22811 binop(Iop_ShlN32x4,
22812 binop(Iop_SarN32x4,
22813 getWReg(wd),
22814 mkU8(16)),
22815 mkU8(15)),
22816 binop(Iop_Mul32x4,
22817 mkexpr(t2), mkexpr(t4))));
22818 putWReg(wd,
22819 binop(Iop_InterleaveEvenLanes16x8,
22820 binop(Iop_QandQRSarNnarrow32Sto16Sx4,
22821 mkexpr(t6), mkU8(15)),
22822 binop(Iop_QandQRSarNnarrow32Sto16Sx4,
22823 mkexpr(t5), mkU8(15))));
22824 break;
22827 case 0x01: { /* MSUBR_Q.D */
22828 DIP("MSUBR_Q.D w%d, w%d, w%d", wd, ws, wt);
22829 t1 = newTemp(Ity_V128);
22830 t2 = newTemp(Ity_V128);
22831 t3 = newTemp(Ity_V128);
22832 t4 = newTemp(Ity_V128);
22833 t5 = newTemp(Ity_V128);
22834 t6 = newTemp(Ity_V128);
22835 assign(t1, // even
22836 binop(Iop_SarN64x2,
22837 binop(Iop_InterleaveEvenLanes32x4,
22838 getWReg(ws),
22839 getWReg(ws)),
22840 mkU8(32)));
22841 assign(t2, // odd
22842 binop(Iop_SarN64x2,
22843 getWReg(ws), mkU8(32)));
22844 assign(t3, // even
22845 binop(Iop_SarN64x2,
22846 binop(Iop_InterleaveEvenLanes32x4,
22847 getWReg(wt),
22848 getWReg(wt)),
22849 mkU8(32)));
22850 assign(t4, // odd
22851 binop(Iop_SarN64x2,
22852 getWReg(wt), mkU8(32)));
22853 assign(t5,
22854 binop(Iop_Sub64x2,
22855 binop(Iop_ShlN64x2,
22856 binop(Iop_SarN64x2,
22857 binop(Iop_InterleaveEvenLanes32x4,
22858 getWReg(wd),
22859 getWReg(wd)),
22860 mkU8(32)),
22861 mkU8(31)),
22862 binop(Iop_64HLtoV128,
22863 binop(Iop_Mul64,
22864 unop(Iop_V128HIto64,
22865 mkexpr(t1)),
22866 unop(Iop_V128HIto64,
22867 mkexpr(t3))),
22868 binop(Iop_Mul64,
22869 unop(Iop_V128to64,
22870 mkexpr(t1)),
22871 unop(Iop_V128to64,
22872 mkexpr(t3))))));
22873 assign(t6,
22874 binop(Iop_Sub64x2,
22875 binop(Iop_ShlN64x2,
22876 binop(Iop_SarN64x2,
22877 getWReg(wd),
22878 mkU8(32)),
22879 mkU8(31)),
22880 binop(Iop_64HLtoV128,
22881 binop(Iop_Mul64,
22882 unop(Iop_V128HIto64,
22883 mkexpr(t2)),
22884 unop(Iop_V128HIto64,
22885 mkexpr(t4))),
22886 binop(Iop_Mul64,
22887 unop(Iop_V128to64,
22888 mkexpr(t2)),
22889 unop(Iop_V128to64,
22890 mkexpr(t4))))));
22891 putWReg(wd,
22892 binop(Iop_InterleaveEvenLanes32x4,
22893 binop(Iop_QandQRSarNnarrow64Sto32Sx2,
22894 mkexpr(t6), mkU8(31)),
22895 binop(Iop_QandQRSarNnarrow64Sto32Sx2,
22896 mkexpr(t5), mkU8(31))));
22897 break;
22900 default:
22901 return -1;
22904 break;
22907 default:
22908 return -1;
22911 return 0;
22914 static Int msa_ELM(UInt cins, UChar wd, UChar ws) { /* ELM (0x19) */
22915 IRTemp t1, t2, t3, t4, t5;
22916 IRType ty;
22917 UShort operation;
22918 UChar df, n;
22920 operation = (cins & 0x03C00000) >> 22;
22921 ty = mode64 ? Ity_I64 : Ity_I32;
22923 switch ((cins & 0x03FF0000) >> 16) {
22924 case 0x07E: /* CFCMSA */
22925 DIP("CFCMSA r%d, c%d", wd, ws);
22927 switch (ws) {
22928 case 0: { /* MSAIR */
22929 IRDirty *d;
22930 t1 = newTemp(Ity_I32);
22931 /* IRExpr_BBPTR() =>
22932 Need to pass pointer to
22933 guest state to helper. */
22934 d = unsafeIRDirty_1_N(t1, 0,
22935 "mips_dirtyhelper_get_MSAIR",
22936 &mips_dirtyhelper_get_MSAIR,
22937 mkIRExprVec_0());
22938 /* d->nFxState = 0; */
22939 stmt(IRStmt_Dirty(d));
22940 putIReg(wd,
22941 mkWidenFrom32(ty, mkexpr(t1), True));
22942 break;
22945 case 1: /* MSACSR */
22946 putIReg(wd,
22947 mkWidenFrom32(ty, getMSACSR(), True));
22948 break;
22950 default:
22951 putIReg(wd,
22952 mkWidenFrom32(ty, mkU32(0), False));
22953 break;
22956 break;
22958 case 0x03E: /* CTCMSA */
22959 DIP("CTCMSA r%d, c%d", ws, wd);
22961 if (wd == 1) { /* MSACSR */
22962 putMSACSR(
22963 binop(Iop_And32, mkNarrowTo32(ty, getIReg(ws)),
22964 mkU32(0x1FFFFFF)));
22967 break;
22969 case 0x0BE: /* MOVE.V */
22970 DIP("MOVE.V w%d, w%d", ws, wd);
22971 putWReg(wd, getWReg(ws));
22972 break;
22974 default:
22975 df = (cins & 0x003F0000) >> 16;
22976 if ((df & 0x38) == 0x38) { // 11100n; dw
22977 n = df & 0x01;
22978 df = 0x38;
22979 } else if ((df & 0x30) == 0x30) { // 1100nn; w
22980 n = df & 0x03;
22981 df = 0x30;
22982 } else if ((df & 0x20) == 0x20) { // 100nnn; hw
22983 n = df & 0x07;
22984 df = 0x20;
22985 } else if ((df & 0x00) == 0x00) { // 00nnnn; b
22986 n = df & 0x0F;
22987 df = 0x00;
22990 switch (operation) {
22991 case 0x00: /* SLDI.df */
22992 switch (df) {
22993 case 0x00: /* SLDI.B */
22994 DIP("SLDI.B w%d, w%d[%d]", wd, ws, n);
22995 t1 = newTemp(Ity_V128);
22996 t2 = newTemp(Ity_V128);
22997 assign(t1,
22998 binop(Iop_ShrV128,
22999 getWReg(ws),
23000 mkU8(n << 3)));
23001 assign(t2,
23002 binop(Iop_ShlV128,
23003 getWReg(wd),
23004 mkU8(n ?
23005 (16 - n) << 3 : 0)));
23006 putWReg(wd,
23007 binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
23008 break;
23010 case 0x20: /* SLDI.H */
23011 DIP("SLDI.H w%d, w%d[%d]", wd, ws, n);
23013 if (n == 0) {
23014 putWReg(wd, getWReg(ws));
23015 } else {
23016 t1 = newTemp(Ity_V128);
23017 t2 = newTemp(Ity_V128);
23018 assign(t1,
23019 binop(Iop_ShrN64x2,
23020 getWReg(ws),
23021 mkU8(n << 3)));
23022 assign(t2,
23023 binop(Iop_ShlN64x2,
23024 getWReg(wd),
23025 mkU8((8 - n) << 3)));
23026 putWReg(wd,
23027 binop(Iop_OrV128,
23028 mkexpr(t1),
23029 mkexpr(t2)));
23032 break;
23034 case 0x30: /* SLDI.W */
23035 DIP("SLDI.W w%d, w%d[%d]", wd, ws, n);
23037 if (n == 0) {
23038 putWReg(wd, getWReg(ws));
23039 } else {
23040 t1 = newTemp(Ity_V128);
23041 t2 = newTemp(Ity_V128);
23042 assign(t1,
23043 binop(Iop_ShrN32x4,
23044 getWReg(ws),
23045 mkU8(n << 3)));
23046 assign(t2,
23047 binop(Iop_ShlN32x4,
23048 getWReg(wd),
23049 mkU8((4 - n) << 3)));
23050 putWReg(wd,
23051 binop(Iop_OrV128,
23052 mkexpr(t1),
23053 mkexpr(t2)));
23056 break;
23058 case 0x38: /* SLDI.D */
23059 DIP("SLDI.D w%d, w%d[%d]", wd, ws, n);
23061 if (n == 0) {
23062 putWReg(wd, getWReg(ws));
23063 } else {
23064 t1 = newTemp(Ity_V128);
23065 t2 = newTemp(Ity_V128);
23066 assign(t1,
23067 binop(Iop_ShrN16x8,
23068 getWReg(ws),
23069 mkU8(n << 3)));
23070 assign(t2,
23071 binop(Iop_ShlN16x8,
23072 getWReg(wd),
23073 mkU8((2 - n) << 3)));
23074 putWReg(wd,
23075 binop(Iop_OrV128,
23076 mkexpr(t1),
23077 mkexpr(t2)));
23080 break;
23082 default:
23083 return -1;
23086 break;
23088 case 0x01: /* SPLATI.df */
23089 switch (df) {
23090 case 0x00: { /* SPLATI.B */
23091 DIP("SPLATI.B w%d, w%d[%d]", wd, ws, n);
23092 t1 = newTemp(Ity_V128);
23093 t2 = newTemp(Ity_V128);
23094 t3 = newTemp(Ity_V128);
23095 t4 = newTemp(Ity_V128);
23097 if (n & 1)
23098 assign(t1,
23099 binop(Iop_InterleaveOddLanes8x16,
23100 getWReg(ws),
23101 getWReg(ws)));
23102 else
23103 assign(t1,
23104 binop(Iop_InterleaveEvenLanes8x16,
23105 getWReg(ws),
23106 getWReg(ws)));
23108 n /= 2;
23110 if (n & 1)
23111 assign(t2,
23112 binop(Iop_InterleaveOddLanes16x8,
23113 mkexpr(t1), mkexpr(t1)));
23114 else
23115 assign(t2,
23116 binop(Iop_InterleaveEvenLanes16x8,
23117 mkexpr(t1), mkexpr(t1)));
23119 n /= 2;
23121 if (n & 1)
23122 assign(t3,
23123 binop(Iop_InterleaveOddLanes32x4,
23124 mkexpr(t2), mkexpr(t2)));
23125 else
23126 assign(t3,
23127 binop(Iop_InterleaveEvenLanes32x4,
23128 mkexpr(t2), mkexpr(t2)));
23130 n /= 2;
23132 if (n & 1)
23133 assign(t4,
23134 binop(Iop_InterleaveHI64x2,
23135 mkexpr(t3), mkexpr(t3)));
23136 else
23137 assign(t4,
23138 binop(Iop_InterleaveLO64x2,
23139 mkexpr(t3), mkexpr(t3)));
23141 putWReg(wd, mkexpr(t4));
23142 break;
23145 case 0x20: { /* SPLATI.H */
23146 DIP("SPLATI.H w%d, w%d[%d]", wd, ws, n);
23147 t1 = newTemp(Ity_V128);
23148 t2 = newTemp(Ity_V128);
23149 t3 = newTemp(Ity_V128);
23151 if (n & 1)
23152 assign(t1,
23153 binop(Iop_InterleaveOddLanes16x8,
23154 getWReg(ws),
23155 getWReg(ws)));
23156 else
23157 assign(t1,
23158 binop(Iop_InterleaveEvenLanes16x8,
23159 getWReg(ws),
23160 getWReg(ws)));
23162 n /= 2;
23164 if (n & 1)
23165 assign(t2,
23166 binop(Iop_InterleaveOddLanes32x4,
23167 mkexpr(t1), mkexpr(t1)));
23168 else
23169 assign(t2,
23170 binop(Iop_InterleaveEvenLanes32x4,
23171 mkexpr(t1), mkexpr(t1)));
23173 n /= 2;
23175 if (n & 1)
23176 assign(t3,
23177 binop(Iop_InterleaveHI64x2,
23178 mkexpr(t2), mkexpr(t2)));
23179 else
23180 assign(t3,
23181 binop(Iop_InterleaveLO64x2,
23182 mkexpr(t2), mkexpr(t2)));
23184 putWReg(wd, mkexpr(t3));
23185 break;
23188 case 0x30: { /* SPLATI.W */
23189 DIP("SPLATI.W w%d, w%d[%d]", wd, ws, n);
23190 t1 = newTemp(Ity_V128);
23191 t2 = newTemp(Ity_V128);
23192 t3 = newTemp(Ity_V128);
23193 assign(t1, getWReg(ws));
23195 if (n & 1)
23196 assign(t2,
23197 binop(Iop_InterleaveOddLanes32x4,
23198 mkexpr(t1), mkexpr(t1)));
23199 else
23200 assign(t2,
23201 binop(Iop_InterleaveEvenLanes32x4,
23202 mkexpr(t1), mkexpr(t1)));
23204 n /= 2;
23206 if (n & 1)
23207 assign(t3,
23208 binop(Iop_InterleaveHI64x2,
23209 mkexpr(t2), mkexpr(t2)));
23210 else
23211 assign(t3,
23212 binop(Iop_InterleaveLO64x2,
23213 mkexpr(t2), mkexpr(t2)));
23215 putWReg(wd, mkexpr(t3));
23216 break;
23219 case 0x38: /* SPLATI.D */
23220 DIP("SPLATI.D w%d, w%d[%d]", wd, ws, n);
23221 t1 = newTemp(Ity_V128);
23222 t3 = newTemp(Ity_V128);
23223 assign(t1, getWReg(ws));
23225 if (n)
23226 assign(t3,
23227 binop(Iop_InterleaveHI64x2,
23228 mkexpr(t1), mkexpr(t1)));
23229 else
23230 assign(t3,
23231 binop(Iop_InterleaveLO64x2,
23232 mkexpr(t1), mkexpr(t1)));
23234 putWReg(wd, mkexpr(t3));
23235 break;
23237 default:
23238 return -1;
23241 break;
23243 case 0x02: /* COPY_S.df */
23244 switch (df) {
23245 case 0x00: /* COPY_S.B */
23246 DIP("COPY_S.B r%d, w%d[%d]", wd, ws, n);
23247 t1 = newTemp(Ity_I8);
23249 switch (n) {
23250 case 0:
23251 assign(t1,
23252 unop(Iop_32to8,
23253 unop(Iop_V128to32,
23254 getWReg(ws))));
23255 break;
23257 case 1:
23258 assign(t1,
23259 unop(Iop_16HIto8,
23260 unop(Iop_32to16,
23261 unop(Iop_V128to32,
23262 getWReg(ws)))));
23263 break;
23265 case 2:
23266 assign(t1,
23267 unop(Iop_16to8,
23268 unop(Iop_32HIto16,
23269 unop(Iop_64to32,
23270 unop(Iop_V128to64,
23271 getWReg(ws))))));
23272 break;
23274 case 3:
23275 assign(t1,
23276 unop(Iop_16HIto8,
23277 unop(Iop_32HIto16,
23278 unop(Iop_64to32,
23279 unop(Iop_V128to64,
23280 getWReg(ws))))));
23281 break;
23283 case 4:
23284 assign(t1,
23285 unop(Iop_16to8,
23286 unop(Iop_32to16,
23287 unop(Iop_64HIto32,
23288 unop(Iop_V128to64,
23289 getWReg(ws))))));
23290 break;
23292 case 5:
23293 assign(t1,
23294 unop(Iop_16HIto8,
23295 unop(Iop_32to16,
23296 unop(Iop_64HIto32,
23297 unop(Iop_V128to64,
23298 getWReg(ws))))));
23299 break;
23301 case 6:
23302 assign(t1,
23303 unop(Iop_16to8,
23304 unop(Iop_32HIto16,
23305 unop(Iop_64HIto32,
23306 unop(Iop_V128to64,
23307 getWReg(ws))))));
23308 break;
23310 case 7:
23311 assign(t1,
23312 unop(Iop_16HIto8,
23313 unop(Iop_32HIto16,
23314 unop(Iop_64HIto32,
23315 unop(Iop_V128to64,
23316 getWReg(ws))))));
23317 break;
23319 case 8:
23320 assign(t1,
23321 unop(Iop_16to8,
23322 unop(Iop_32to16,
23323 unop(Iop_64to32,
23324 unop(Iop_V128HIto64,
23325 getWReg(ws))))));
23326 break;
23328 case 9:
23329 assign(t1,
23330 unop(Iop_16HIto8,
23331 unop(Iop_32to16,
23332 unop(Iop_64to32,
23333 unop(Iop_V128HIto64,
23334 getWReg(ws))))));
23335 break;
23337 case 10:
23338 assign(t1,
23339 unop(Iop_16to8,
23340 unop(Iop_32HIto16,
23341 unop(Iop_64to32,
23342 unop(Iop_V128HIto64,
23343 getWReg(ws))))));
23344 break;
23346 case 11:
23347 assign(t1,
23348 unop(Iop_16HIto8,
23349 unop(Iop_32HIto16,
23350 unop(Iop_64to32,
23351 unop(Iop_V128HIto64,
23352 getWReg(ws))))));
23353 break;
23355 case 12:
23356 assign(t1,
23357 unop(Iop_16to8,
23358 unop(Iop_32to16,
23359 unop(Iop_64HIto32,
23360 unop(Iop_V128HIto64,
23361 getWReg(ws))))));
23362 break;
23364 case 13:
23365 assign(t1,
23366 unop(Iop_16HIto8,
23367 unop(Iop_32to16,
23368 unop(Iop_64HIto32,
23369 unop(Iop_V128HIto64,
23370 getWReg(ws))))));
23371 break;
23373 case 14:
23374 assign(t1,
23375 unop(Iop_16to8,
23376 unop(Iop_32HIto16,
23377 unop(Iop_64HIto32,
23378 unop(Iop_V128HIto64,
23379 getWReg(ws))))));
23380 break;
23382 case 15:
23383 assign(t1,
23384 unop(Iop_16HIto8,
23385 unop(Iop_32HIto16,
23386 unop(Iop_64HIto32,
23387 unop(Iop_V128HIto64,
23388 getWReg(ws))))));
23389 break;
23392 putIReg(wd,
23393 unop(mode64 ? Iop_8Sto64 : Iop_8Sto32,
23394 mkexpr(t1)));
23395 break;
23397 case 0x20: /* COPY_S.H */
23398 DIP("COPY_S.H r%d, w%d[%d]", wd, ws, n);
23399 t1 = newTemp(Ity_I16);
23401 switch (n) {
23402 case 0:
23403 assign(t1,
23404 unop(Iop_32to16,
23405 unop(Iop_64to32,
23406 unop(Iop_V128to64,
23407 getWReg(ws)))));
23408 break;
23410 case 1:
23411 assign(t1,
23412 unop(Iop_32HIto16,
23413 unop(Iop_64to32,
23414 unop(Iop_V128to64,
23415 getWReg(ws)))));
23416 break;
23418 case 2:
23419 assign(t1,
23420 unop(Iop_32to16,
23421 unop(Iop_64HIto32,
23422 unop(Iop_V128to64,
23423 getWReg(ws)))));
23424 break;
23426 case 3:
23427 assign(t1,
23428 unop(Iop_32HIto16,
23429 unop(Iop_64HIto32,
23430 unop(Iop_V128to64,
23431 getWReg(ws)))));
23432 break;
23434 case 4:
23435 assign(t1,
23436 unop(Iop_32to16,
23437 unop(Iop_64to32,
23438 unop(Iop_V128HIto64,
23439 getWReg(ws)))));
23440 break;
23442 case 5:
23443 assign(t1,
23444 unop(Iop_32HIto16,
23445 unop(Iop_64to32,
23446 unop(Iop_V128HIto64,
23447 getWReg(ws)))));
23448 break;
23450 case 6:
23451 assign(t1,
23452 unop(Iop_32to16,
23453 unop(Iop_64HIto32,
23454 unop(Iop_V128HIto64,
23455 getWReg(ws)))));
23456 break;
23458 case 7:
23459 assign(t1,
23460 unop(Iop_32HIto16,
23461 unop(Iop_64HIto32,
23462 unop(Iop_V128HIto64,
23463 getWReg(ws)))));
23464 break;
23467 putIReg(wd,
23468 unop(mode64 ? Iop_16Sto64 : Iop_16Sto32,
23469 mkexpr(t1)));
23470 break;
23472 case 0x30: /* COPY_S.W */
23473 DIP("COPY_S.W r%d, w%d[%d]", wd, ws, n);
23475 switch (n) {
23476 case 0:
23477 putIReg(wd,
23478 mkWidenFrom32(ty,
23479 unop(Iop_V128to32,
23480 getWReg(ws)),
23481 True));
23482 break;
23484 case 1:
23485 t2 = newTemp(Ity_I64);
23486 assign(t2,
23487 unop(Iop_V128to64, getWReg(ws)));
23488 putIReg(wd,
23489 mkWidenFrom32(ty,
23490 unop(Iop_64HIto32,
23491 mkexpr(t2)),
23492 True));
23493 break;
23495 case 2:
23496 t2 = newTemp(Ity_I64);
23497 assign(t2,
23498 unop(Iop_V128HIto64,
23499 getWReg(ws)));
23500 putIReg(wd,
23501 mkWidenFrom32(ty,
23502 unop(Iop_64to32,
23503 mkexpr(t2)),
23504 True));
23505 break;
23507 case 3:
23508 t2 = newTemp(Ity_I64);
23509 assign(t2,
23510 unop(Iop_V128HIto64,
23511 getWReg(ws)));
23512 putIReg(wd,
23513 mkWidenFrom32(ty,
23514 unop(Iop_64HIto32,
23515 mkexpr(t2)),
23516 True));
23517 break;
23519 default:
23520 break;
23523 break;
23525 case 0x38: /* COPY_S.D */
23526 if (mode64) {
23527 DIP("COPY_S.D r%d, w%d[%d]", wd, ws, n);
23529 switch (n) {
23530 case 0:
23531 putIReg(wd,
23532 unop(Iop_V128to64,
23533 getWReg(ws)));
23534 break;
23536 case 1:
23537 putIReg(wd,
23538 unop(Iop_V128HIto64,
23539 getWReg(ws)));
23540 break;
23542 } else {
23543 return -2;
23546 break;
23548 default:
23549 return -1;
23552 break;
23554 case 0x03: { /* COPY_U.df */
23555 switch (df) {
23556 case 0x00: /* COPY_U.B */
23557 DIP("COPY_U.B r%d, w%d[%d]", wd, ws, n);
23558 t1 = newTemp(Ity_I8);
23560 switch (n) {
23561 case 0:
23562 assign(t1,
23563 unop(Iop_16to8,
23564 unop(Iop_32to16,
23565 unop(Iop_64to32,
23566 unop(Iop_V128to64,
23567 getWReg(ws))))));
23568 break;
23570 case 1:
23571 assign(t1,
23572 unop(Iop_16HIto8,
23573 unop(Iop_32to16,
23574 unop(Iop_64to32,
23575 unop(Iop_V128to64,
23576 getWReg(ws))))));
23577 break;
23579 case 2:
23580 assign(t1,
23581 unop(Iop_16to8,
23582 unop(Iop_32HIto16,
23583 unop(Iop_64to32,
23584 unop(Iop_V128to64,
23585 getWReg(ws))))));
23586 break;
23588 case 3:
23589 assign(t1,
23590 unop(Iop_16HIto8,
23591 unop(Iop_32HIto16,
23592 unop(Iop_64to32,
23593 unop(Iop_V128to64,
23594 getWReg(ws))))));
23595 break;
23597 case 4:
23598 assign(t1,
23599 unop(Iop_16to8,
23600 unop(Iop_32to16,
23601 unop(Iop_64HIto32,
23602 unop(Iop_V128to64,
23603 getWReg(ws))))));
23604 break;
23606 case 5:
23607 assign(t1,
23608 unop(Iop_16HIto8,
23609 unop(Iop_32to16,
23610 unop(Iop_64HIto32,
23611 unop(Iop_V128to64,
23612 getWReg(ws))))));
23613 break;
23615 case 6:
23616 assign(t1,
23617 unop(Iop_16to8,
23618 unop(Iop_32HIto16,
23619 unop(Iop_64HIto32,
23620 unop(Iop_V128to64,
23621 getWReg(ws))))));
23622 break;
23624 case 7:
23625 assign(t1,
23626 unop(Iop_16HIto8,
23627 unop(Iop_32HIto16,
23628 unop(Iop_64HIto32,
23629 unop(Iop_V128to64,
23630 getWReg(ws))))));
23631 break;
23633 case 8:
23634 assign(t1,
23635 unop(Iop_16to8,
23636 unop(Iop_32to16,
23637 unop(Iop_64to32,
23638 unop(Iop_V128HIto64,
23639 getWReg(ws))))));
23640 break;
23642 case 9:
23643 assign(t1,
23644 unop(Iop_16HIto8,
23645 unop(Iop_32to16,
23646 unop(Iop_64to32,
23647 unop(Iop_V128HIto64,
23648 getWReg(ws))))));
23649 break;
23651 case 10:
23652 assign(t1,
23653 unop(Iop_16to8,
23654 unop(Iop_32HIto16,
23655 unop(Iop_64to32,
23656 unop(Iop_V128HIto64,
23657 getWReg(ws))))));
23658 break;
23660 case 11:
23661 assign(t1,
23662 unop(Iop_16HIto8,
23663 unop(Iop_32HIto16,
23664 unop(Iop_64to32,
23665 unop(Iop_V128HIto64,
23666 getWReg(ws))))));
23667 break;
23669 case 12:
23670 assign(t1,
23671 unop(Iop_16to8,
23672 unop(Iop_32to16,
23673 unop(Iop_64HIto32,
23674 unop(Iop_V128HIto64,
23675 getWReg(ws))))));
23676 break;
23678 case 13:
23679 assign(t1,
23680 unop(Iop_16HIto8,
23681 unop(Iop_32to16,
23682 unop(Iop_64HIto32,
23683 unop(Iop_V128HIto64,
23684 getWReg(ws))))));
23685 break;
23687 case 14:
23688 assign(t1,
23689 unop(Iop_16to8,
23690 unop(Iop_32HIto16,
23691 unop(Iop_64HIto32,
23692 unop(Iop_V128HIto64,
23693 getWReg(ws))))));
23694 break;
23696 case 15:
23697 assign(t1,
23698 unop(Iop_16HIto8,
23699 unop(Iop_32HIto16,
23700 unop(Iop_64HIto32,
23701 unop(Iop_V128HIto64,
23702 getWReg(ws))))));
23703 break;
23706 putIReg(wd,
23707 unop(mode64 ? Iop_8Uto64 : Iop_8Uto32,
23708 mkexpr(t1)));
23709 break;
23711 case 0x20: /* COPY_U.H */
23712 DIP("COPY_U.H r%d, w%d[%d]", wd, ws, n);
23713 t1 = newTemp(Ity_I16);
23715 switch (n) {
23716 case 0:
23717 assign(t1,
23718 unop(Iop_32to16,
23719 unop(Iop_64to32,
23720 unop(Iop_V128to64,
23721 getWReg(ws)))));
23722 break;
23724 case 1:
23725 assign(t1,
23726 unop(Iop_32HIto16,
23727 unop(Iop_64to32,
23728 unop(Iop_V128to64,
23729 getWReg(ws)))));
23730 break;
23732 case 2:
23733 assign(t1,
23734 unop(Iop_32to16,
23735 unop(Iop_64HIto32,
23736 unop(Iop_V128to64,
23737 getWReg(ws)))));
23738 break;
23740 case 3:
23741 assign(t1,
23742 unop(Iop_32HIto16,
23743 unop(Iop_64HIto32,
23744 unop(Iop_V128to64,
23745 getWReg(ws)))));
23746 break;
23748 case 4:
23749 assign(t1,
23750 unop(Iop_32to16,
23751 unop(Iop_64to32,
23752 unop(Iop_V128HIto64,
23753 getWReg(ws)))));
23754 break;
23756 case 5:
23757 assign(t1,
23758 unop(Iop_32HIto16,
23759 unop(Iop_64to32,
23760 unop(Iop_V128HIto64,
23761 getWReg(ws)))));
23762 break;
23764 case 6:
23765 assign(t1,
23766 unop(Iop_32to16,
23767 unop(Iop_64HIto32,
23768 unop(Iop_V128HIto64,
23769 getWReg(ws)))));
23770 break;
23772 case 7:
23773 assign(t1,
23774 unop(Iop_32HIto16,
23775 unop(Iop_64HIto32,
23776 unop(Iop_V128HIto64,
23777 getWReg(ws)))));
23778 break;
23781 putIReg(wd,
23782 unop(mode64 ? Iop_16Uto64 : Iop_16Uto32,
23783 mkexpr(t1)));
23784 break;
23786 case 0x30: /* COPY_U.W */
23787 DIP("COPY_U.W r%d, w%d[%d]", wd, ws, n);
23789 switch (n) {
23790 case 0:
23791 putIReg(wd,
23792 mkWidenFrom32(ty,
23793 unop(Iop_V128to32,
23794 getWReg(ws)),
23795 False));
23796 break;
23798 case 1:
23799 t2 = newTemp(Ity_I64);
23800 assign(t2,
23801 unop(Iop_V128to64,
23802 getWReg(ws)));
23803 putIReg(wd,
23804 mkWidenFrom32(ty,
23805 unop(Iop_64HIto32,
23806 mkexpr(t2)),
23807 False));
23808 break;
23810 case 2:
23811 t2 = newTemp(Ity_I64);
23812 assign(t2,
23813 unop(Iop_V128HIto64,
23814 getWReg(ws)));
23815 putIReg(wd,
23816 mkWidenFrom32(ty,
23817 unop(Iop_64to32,
23818 mkexpr(t2)),
23819 False));
23820 break;
23822 case 3:
23823 t2 = newTemp(Ity_I64);
23824 assign(t2,
23825 unop(Iop_V128HIto64,
23826 getWReg(ws)));
23827 putIReg(wd,
23828 mkWidenFrom32(ty,
23829 unop(Iop_64HIto32,
23830 mkexpr(t2)),
23831 False));
23832 break;
23834 default:
23835 break;
23838 break;
23840 default:
23841 return -1;
23844 break;
23847 case 0x04: { /* INSERT.df */
23848 t5 = newTemp(Ity_I64);
23849 UInt hi = 1;
23850 ULong mask;
23851 IRTemp *src, *dst;
23852 assign(t5, mode64 ? getIReg(ws) :
23853 unop(Iop_32Uto64, getIReg(ws)));
23855 if (df == 0x38) { /* INSERT.D */
23856 if (mode64) {
23857 DIP("INSERT.D w%d[%d], r%d", wd, n, ws);
23859 if (n == 0) {
23860 putWReg(wd,
23861 binop(Iop_64HLtoV128,
23862 unop(Iop_V128HIto64,
23863 getWReg(wd)),
23864 mkexpr(t5)));
23865 } else {
23866 putWReg(wd,
23867 binop(Iop_64HLtoV128,
23868 mkexpr(t5),
23869 unop(Iop_V128to64,
23870 getWReg(wd))));
23873 break;
23874 } else {
23875 return -2;
23877 } else {
23878 t1 = newTemp(Ity_I64);
23879 t2 = newTemp(Ity_I64);
23880 assign(t1, unop(Iop_V128to64, getWReg(wd)));
23881 assign(t2, unop(Iop_V128HIto64, getWReg(wd)));
23884 switch (df) {
23885 case 0x00: /* INSERT.B */
23886 DIP("INSERT.B w%d[%d], r%d", wd, n, ws);
23888 if (n >= 8) {
23889 n -= 8;
23890 } else {
23891 hi = 0;
23894 n <<= 3;
23895 mask = 0xFFull;
23896 break;
23898 case 0x20: /* INSERT.H */
23899 DIP("INSERT.H w%d[%d], r%d", wd, n, ws);
23901 if (n >= 4) {
23902 n -= 4;
23903 } else {
23904 hi = 0;
23907 n <<= 4;
23908 mask = 0xFFFFull;
23909 break;
23911 case 0x30: /* INSERT.W */
23912 DIP("INSERT.W w%d[%d], r%d", wd, n, ws);
23914 if (n >= 2) {
23915 n -= 2;
23916 } else {
23917 hi = 0;
23920 n <<= 5;
23921 mask = 0xFFFFFFFFull;
23922 break;
23924 default:
23925 return -1;
23928 if (hi) {
23929 t4 = newTemp(Ity_I64);
23930 src = &t2;
23931 dst = &t4;
23932 t3 = t1;
23933 } else {
23934 t3 = newTemp(Ity_I64);
23935 src = &t1;
23936 dst = &t3;
23937 t4 = t2;
23940 mask <<= n;
23941 assign(*dst,
23942 binop(Iop_Or64,
23943 binop(Iop_And64, mkexpr(*src), mkU64(~mask)),
23944 binop(Iop_And64,
23945 binop(Iop_Shl64, mkexpr(t5), mkU8(n)),
23946 mkU64(mask))));
23947 putWReg(wd,
23948 binop(Iop_64HLtoV128, mkexpr(t4), mkexpr(t3)));
23949 break;
23952 case 0x05: { /* INSVE.df */
23953 switch (df) {
23954 case 0x00: { /* INSVE.B */
23955 DIP("INSVE.B w%d[%d], w%d[0]", wd, n, ws);
23956 t1 = newTemp(Ity_V128);
23957 t2 = newTemp(Ity_V128);
23958 assign(t1, getWReg(wd));
23959 assign(t2, getWReg(ws));
23960 Int i;
23961 IRTemp tmp[16];
23963 for (i = 0; i < 16; i++) {
23964 tmp[i] = newTemp(Ity_I8);
23966 if (n == i)
23967 assign(tmp[i],
23968 binop(Iop_GetElem8x16,
23969 mkexpr(t2), mkU8(0x0)));
23970 else
23971 assign(tmp[i],
23972 binop(Iop_GetElem8x16,
23973 mkexpr(t1), mkU8(i)));
23976 putWReg(wd,
23977 binop(Iop_64HLtoV128,
23978 binop(Iop_32HLto64,
23979 binop(Iop_16HLto32,
23980 binop(Iop_8HLto16,
23981 mkexpr(tmp[15]),
23982 mkexpr(tmp[14])),
23983 binop(Iop_8HLto16,
23984 mkexpr(tmp[13]),
23985 mkexpr(tmp[12]))),
23986 binop(Iop_16HLto32,
23987 binop(Iop_8HLto16,
23988 mkexpr(tmp[11]),
23989 mkexpr(tmp[10])),
23990 binop(Iop_8HLto16,
23991 mkexpr(tmp[9]),
23992 mkexpr(tmp[8])))),
23993 binop(Iop_32HLto64,
23994 binop(Iop_16HLto32,
23995 binop(Iop_8HLto16,
23996 mkexpr(tmp[7]),
23997 mkexpr(tmp[6])),
23998 binop(Iop_8HLto16,
23999 mkexpr(tmp[5]),
24000 mkexpr(tmp[4]))),
24001 binop(Iop_16HLto32,
24002 binop(Iop_8HLto16,
24003 mkexpr(tmp[3]),
24004 mkexpr(tmp[2])),
24005 binop(Iop_8HLto16,
24006 mkexpr(tmp[1]),
24007 mkexpr(tmp[0]))))));
24008 break;
24011 case 0x20: { /* INSVE.H */
24012 DIP("INSVE.H w%d[%d], r%d[0]", wd, n, ws);
24013 t1 = newTemp(Ity_V128);
24014 t2 = newTemp(Ity_V128);
24015 assign(t1, getWReg(wd));
24016 assign(t2, getWReg(ws));
24017 Int i;
24018 IRTemp tmp[8];
24020 for (i = 0; i < 8; i++) {
24021 tmp[i] = newTemp(Ity_I16);
24023 if (n == i)
24024 assign(tmp[i],
24025 binop(Iop_GetElem16x8,
24026 mkexpr(t2), mkU8(0x0)));
24027 else
24028 assign(tmp[i],
24029 binop(Iop_GetElem16x8,
24030 mkexpr(t1), mkU8(i)));
24033 putWReg(wd,
24034 binop(Iop_64HLtoV128,
24035 binop(Iop_32HLto64,
24036 binop(Iop_16HLto32,
24037 mkexpr(tmp[7]),
24038 mkexpr(tmp[6])),
24039 binop(Iop_16HLto32,
24040 mkexpr(tmp[5]),
24041 mkexpr(tmp[4]))),
24042 binop(Iop_32HLto64,
24043 binop(Iop_16HLto32,
24044 mkexpr(tmp[3]),
24045 mkexpr(tmp[2])),
24046 binop(Iop_16HLto32,
24047 mkexpr(tmp[1]),
24048 mkexpr(tmp[0])))));
24049 break;
24052 case 0x30: { /* INSVE.W */
24053 DIP("INSVE.W w%d[%d], r%d[0]", wd, n, ws);
24054 t1 = newTemp(Ity_V128);
24055 t2 = newTemp(Ity_V128);
24056 assign(t1, getWReg(wd));
24057 assign(t2, getWReg(ws));
24058 Int i;
24059 IRTemp tmp[4];
24061 for (i = 0; i < 4; i++) {
24062 tmp[i] = newTemp(Ity_I32);
24064 if (n == i)
24065 assign(tmp[i],
24066 binop(Iop_GetElem32x4,
24067 mkexpr(t2), mkU8(0x0)));
24068 else
24069 assign(tmp[i],
24070 binop(Iop_GetElem32x4,
24071 mkexpr(t1), mkU8(i)));
24074 putWReg(wd,
24075 binop(Iop_64HLtoV128,
24076 binop(Iop_32HLto64,
24077 mkexpr(tmp[3]),
24078 mkexpr(tmp[2])),
24079 binop(Iop_32HLto64,
24080 mkexpr(tmp[1]),
24081 mkexpr(tmp[0]))));
24082 break;
24085 case 0x38: { /* INSVE.D */
24086 DIP("INSVE.D w%d[%d], r%d[0]", wd, n, ws);
24087 t1 = newTemp(Ity_V128);
24088 t2 = newTemp(Ity_V128);
24089 assign(t1, getWReg(wd));
24090 assign(t2, getWReg(ws));
24091 Int i;
24092 IRTemp tmp[2];
24094 for (i = 0; i < 2; i++) {
24095 tmp[i] = newTemp(Ity_I64);
24097 if (n == i)
24098 assign(tmp[i],
24099 binop(Iop_GetElem64x2,
24100 mkexpr(t2), mkU8(0x0)));
24101 else
24102 assign(tmp[i],
24103 binop(Iop_GetElem64x2,
24104 mkexpr(t1), mkU8(i)));
24107 putWReg(wd,
24108 binop(Iop_64HLtoV128,
24109 mkexpr(tmp[1]), mkexpr(tmp[0])));
24110 break;
24114 break;
24117 default:
24118 return -1;
24121 return 0;
24124 static Int msa_VEC(UInt cins, UChar wd, UChar ws) { /* VEC */
24125 IRTemp t1, t2, t3;
24126 UShort operation;
24127 UChar wt;
24129 vassert((cins & 0x03000000) == 0);
24131 operation = (cins & 0x03E00000) >> 21;
24132 wt = (cins & 0x001F0000) >> 16;
24134 switch (operation) {
24135 case 0x00: { /* AND.V */
24136 DIP("AND.V w%d, w%d, w%d", wd, ws, wt);
24137 t1 = newTemp(Ity_V128);
24138 t2 = newTemp(Ity_V128);
24139 t3 = newTemp(Ity_V128);
24140 assign(t1, getWReg(ws));
24141 assign(t2, getWReg(wt));
24142 assign(t3, binop(Iop_AndV128, mkexpr(t1), mkexpr(t2)));
24143 putWReg(wd, mkexpr(t3));
24144 break;
24147 case 0x01: { /* OR.V */
24148 DIP("OR.V w%d, w%d, w%d", wd, ws, wt);
24149 t1 = newTemp(Ity_V128);
24150 t2 = newTemp(Ity_V128);
24151 t3 = newTemp(Ity_V128);
24152 assign(t1, getWReg(ws));
24153 assign(t2, getWReg(wt));
24154 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
24155 putWReg(wd, mkexpr(t3));
24156 break;
24159 case 0x02: { /* NOR.V */
24160 DIP("NOR.V w%d, w%d, w%d", wd, ws, wt);
24161 t1 = newTemp(Ity_V128);
24162 t2 = newTemp(Ity_V128);
24163 t3 = newTemp(Ity_V128);
24164 assign(t1, getWReg(ws));
24165 assign(t2, getWReg(wt));
24166 assign(t3,
24167 unop(Iop_NotV128,
24168 binop(Iop_OrV128, mkexpr(t1), mkexpr(t2))));
24169 putWReg(wd, mkexpr(t3));
24170 break;
24173 case 0x03: { /* XOR.V */
24174 DIP("XOR.V w%d, w%d, w%d", wd, ws, wt);
24175 t1 = newTemp(Ity_V128);
24176 t2 = newTemp(Ity_V128);
24177 t3 = newTemp(Ity_V128);
24178 assign(t1, getWReg(ws));
24179 assign(t2, getWReg(wt));
24180 assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
24181 putWReg(wd, mkexpr(t3));
24182 break;
24185 case 0x04: { /* BMNZ (ws AND wt) OR (wd AND NOT wt) */
24186 DIP("BMNZ.V w%d, w%d, w%d", wd, ws, wt);
24187 t1 = newTemp(Ity_V128);
24188 t2 = newTemp(Ity_V128);
24189 t3 = newTemp(Ity_V128);
24190 assign(t1,
24191 binop(Iop_AndV128,
24192 getWReg(ws), getWReg(wt)));
24193 assign(t2,
24194 binop(Iop_AndV128,
24195 getWReg(wd),
24196 unop(Iop_NotV128, getWReg(wt))));
24197 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
24198 putWReg(wd, mkexpr(t3));
24199 break;
24202 case 0x05: { /* BMZ.V (ws AND NOT wt) OR (wd AND wt) */
24203 DIP("BMZ.V w%d, w%d, w%d", wd, ws, wt);
24204 t1 = newTemp(Ity_V128);
24205 t2 = newTemp(Ity_V128);
24206 t3 = newTemp(Ity_V128);
24207 assign(t1,
24208 binop(Iop_AndV128,
24209 getWReg(wd), getWReg(wt)));
24210 assign(t2,
24211 binop(Iop_AndV128,
24212 getWReg(ws),
24213 unop(Iop_NotV128, getWReg(wt))));
24214 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
24215 putWReg(wd, mkexpr(t3));
24216 break;
24219 case 0x06: { /* BSEL (ws AND NOT wd) OR (wt AND wd) */
24220 DIP("BSEL.V w%d, w%d, w%d", wd, ws, wt);
24221 t1 = newTemp(Ity_V128);
24222 t2 = newTemp(Ity_V128);
24223 t3 = newTemp(Ity_V128);
24224 assign(t1,
24225 binop(Iop_AndV128,
24226 getWReg(wd), getWReg(wt)));
24227 assign(t2,
24228 binop(Iop_AndV128,
24229 getWReg(ws),
24230 unop(Iop_NotV128, getWReg(wd))));
24231 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
24232 putWReg(wd, mkexpr(t3));
24233 break;
24236 default:
24237 return -1;
24240 return 0;
24243 static Int msa_2R(UInt cins, UChar wd, UChar ws) { /* 2R */
24244 IRTemp t1, t2, t3, t4;
24245 IRType ty;
24246 UShort operation;
24247 UChar df;
24249 vassert((cins & 0x00200000) == 0);
24251 operation = (cins & 0x03FC0000) >> 18;
24252 df = (cins & 0x00030000) >> 16;
24253 ty = mode64 ? Ity_I64 : Ity_I32;
24255 switch (operation) {
24256 case 0xC0: { /* FILL.df */
24257 t1 = newTemp(Ity_I64);
24259 switch (df) {
24260 case 0x00: /* FILL.B */
24261 DIP("FILL.B w%d, r%d", wd, ws);
24262 t2 = newTemp(Ity_I32);
24263 t3 = newTemp(Ity_I16);
24264 t4 = newTemp(Ity_I8);
24265 assign(t4, mkNarrowTo8(ty, getIReg(ws)));
24266 assign(t3,
24267 binop(Iop_8HLto16, mkexpr(t4), mkexpr(t4)));
24268 assign(t2,
24269 binop(Iop_16HLto32, mkexpr(t3), mkexpr(t3)));
24270 assign(t1,
24271 binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
24272 break;
24274 case 0x01: /* FILL.H */
24275 DIP("FILL.H w%d, r%d", wd, ws);
24276 t2 = newTemp(Ity_I32);
24277 t3 = newTemp(Ity_I16);
24278 assign(t3, mkNarrowTo16(ty, getIReg(ws)));
24279 assign(t2,
24280 binop(Iop_16HLto32, mkexpr(t3), mkexpr(t3)));
24281 assign(t1,
24282 binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
24283 break;
24285 case 0x02: /* FILL.W */
24286 DIP("FILL.W w%d, r%d", wd, ws);
24287 t2 = newTemp(Ity_I32);
24288 assign(t2, mkNarrowTo32(ty, getIReg(ws)));
24289 assign(t1,
24290 binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
24291 break;
24293 case 0x03: /* FILL.D */
24294 if (mode64) {
24295 DIP("FILL.W w%d, r%d", wd, ws);
24296 t2 = newTemp(Ity_I32);
24297 assign(t1, getIReg(ws));
24298 } else {
24299 return -2;
24302 break;
24304 default:
24305 return -1;
24308 putWReg(wd,
24309 binop(Iop_64HLtoV128, mkexpr(t1), mkexpr(t1)));
24310 break;
24313 case 0xC1: { /* PCNT.df */
24314 switch (df) {
24315 case 0x00: /* PCNT.B */
24316 DIP("PCNT.B w%d, r%d", wd, ws);
24317 putWReg(wd,
24318 unop(Iop_Cnt8x16, getWReg(ws)));
24319 break;
24321 case 0x01: /* PCNT.H */
24322 DIP("PCNT.H w%d, r%d", wd, ws);
24323 t1 = newTemp(Ity_V128);
24324 t2 = newTemp(Ity_V128);
24325 assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
24326 assign(t2,
24327 binop(Iop_Add16x8,
24328 binop(Iop_AndV128,
24329 mkexpr(t1),
24330 binop(Iop_64HLtoV128,
24331 mkU64(0x00FF00FF00FF00FFULL),
24332 mkU64(0x00FF00FF00FF00FFULL))),
24333 binop(Iop_AndV128,
24334 binop(Iop_ShrN16x8,
24335 mkexpr(t1), mkU8(8)),
24336 binop(Iop_64HLtoV128,
24337 mkU64(0x00FF00FF00FF00FFULL),
24338 mkU64(0x00FF00FF00FF00FFULL)))));
24339 putWReg(wd, mkexpr(t2));
24340 break;
24342 case 0x02: /* PCNT.W */
24343 DIP("PCNT.W w%d, r%d", wd, ws);
24344 t1 = newTemp(Ity_V128);
24345 t2 = newTemp(Ity_V128);
24346 t3 = newTemp(Ity_V128);
24347 assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
24348 assign(t2,
24349 binop(Iop_Add32x4,
24350 binop(Iop_AndV128,
24351 mkexpr(t1),
24352 binop(Iop_64HLtoV128,
24353 mkU64(0x00FF00FF00FF00FFULL),
24354 mkU64(0x00FF00FF00FF00FFULL))),
24355 binop(Iop_AndV128,
24356 binop(Iop_ShrN32x4,
24357 mkexpr(t1), mkU8(8)),
24358 binop(Iop_64HLtoV128,
24359 mkU64(0x00FF00FF00FF00FFULL),
24360 mkU64(0x00FF00FF00FF00FFULL)))));
24361 assign(t3,
24362 binop(Iop_Add32x4,
24363 binop(Iop_AndV128,
24364 mkexpr(t2),
24365 binop(Iop_64HLtoV128,
24366 mkU64(0x0000FFFF0000FFFFULL),
24367 mkU64(0x0000FFFF0000FFFFULL))),
24368 binop(Iop_AndV128,
24369 binop(Iop_ShrN32x4,
24370 mkexpr(t2), mkU8(16)),
24371 binop(Iop_64HLtoV128,
24372 mkU64(0x0000FFFF0000FFFFULL),
24373 mkU64(0x0000FFFF0000FFFFULL)))));
24374 putWReg(wd, mkexpr(t3));
24375 break;
24377 case 0x03: /* PCNT.D */
24378 DIP("PCNT.D w%d, r%d", wd, ws);
24379 t1 = newTemp(Ity_V128);
24380 t2 = newTemp(Ity_V128);
24381 t3 = newTemp(Ity_V128);
24382 t4 = newTemp(Ity_V128);;
24383 assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
24384 assign(t2,
24385 binop(Iop_Add64x2,
24386 binop(Iop_AndV128,
24387 mkexpr(t1),
24388 binop(Iop_64HLtoV128,
24389 mkU64(0x00FF00FF00FF00FFULL),
24390 mkU64(0x00FF00FF00FF00FFULL))),
24391 binop(Iop_AndV128,
24392 binop(Iop_ShrN64x2,
24393 mkexpr(t1), mkU8(8)),
24394 binop(Iop_64HLtoV128,
24395 mkU64(0x00FF00FF00FF00FFULL),
24396 mkU64(0x00FF00FF00FF00FFULL)))));
24397 assign(t3,
24398 binop(Iop_Add64x2,
24399 binop(Iop_AndV128,
24400 mkexpr(t2),
24401 binop(Iop_64HLtoV128,
24402 mkU64(0x0000FFFF0000FFFFULL),
24403 mkU64(0x0000FFFF0000FFFFULL))),
24404 binop(Iop_AndV128,
24405 binop(Iop_ShrN64x2,
24406 mkexpr(t2), mkU8(16)),
24407 binop(Iop_64HLtoV128,
24408 mkU64(0x0000FFFF0000FFFFULL),
24409 mkU64(0x0000FFFF0000FFFFULL)))));
24410 assign(t4,
24411 binop(Iop_Add64x2,
24412 binop(Iop_AndV128,
24413 mkexpr(t3),
24414 binop(Iop_64HLtoV128,
24415 mkU64(0x00000000FFFFFFFFULL),
24416 mkU64(0x00000000FFFFFFFFULL))),
24417 binop(Iop_AndV128,
24418 binop(Iop_ShrN64x2,
24419 mkexpr(t3), mkU8(32)),
24420 binop(Iop_64HLtoV128,
24421 mkU64(0x00000000FFFFFFFFULL),
24422 mkU64(0x00000000FFFFFFFFULL)))));
24423 putWReg(wd, mkexpr(t4));
24424 break;
24426 default:
24427 return -1;
24430 break;
24433 case 0xC2: { /* NLOC.df */
24434 switch (df) {
24435 case 0x00: /* NLOC.B */
24436 DIP("NLOC.B w%d, w%d", wd, ws);
24437 putWReg(wd,
24438 unop(Iop_Cls8x16, getWReg(ws)));
24439 break;
24441 case 0x01: /* NLOC.H */
24442 DIP("NLOC.H w%d, w%d", wd, ws);
24443 putWReg(wd,
24444 unop(Iop_Cls16x8, getWReg(ws)));
24445 break;
24447 case 0x02: /* NLOC.W */
24448 DIP("NLOC.W w%d, w%d", wd, ws);
24449 putWReg(wd,
24450 unop(Iop_Cls32x4, getWReg(ws)));
24451 break;
24453 case 0x03: /* NLOC.D */
24454 DIP("NLOC.D w%d, w%d", wd, ws);
24455 t1 = newTemp(Ity_V128);
24456 assign(t1, unop(Iop_NotV128, getWReg(ws)));
24457 putWReg(wd, unop(Iop_Clz64x2, mkexpr(t1)));
24458 break;
24460 default:
24461 return -1;
24464 break;
24467 case 0xC3: { /* NLZC.df */
24468 switch (df) {
24469 case 0x00: /* NLZC.B */
24470 DIP("NLZC.W w%d, w%d", wd, ws);
24471 putWReg(wd,
24472 unop(Iop_Clz8x16, getWReg(ws)));
24473 break;
24475 case 0x01: /* NLZC.H */
24476 DIP("NLZC.H w%d, w%d", wd, ws);
24477 putWReg(wd,
24478 unop(Iop_Clz16x8, getWReg(ws)));
24479 break;
24481 case 0x02: /* NLZC.W */
24482 DIP("NLZC.W w%d, w%d", wd, ws);
24483 putWReg(wd,
24484 unop(Iop_Clz32x4, getWReg(ws)));
24485 break;
24487 case 0x03: {/* NLZC.D */
24488 putWReg(wd,
24489 unop(Iop_Clz64x2, getWReg(ws)));
24490 break;
24493 default:
24494 return -1;
24497 break;
24500 default:
24501 return -1;
24504 return 0;
24507 static Int msa_2RF(UInt cins, UChar wd, UChar ws) { /* 2RF */
24508 IRTemp t1, t2, t3, t4, t5;
24509 UShort operation;
24510 UChar df, wt;
24512 operation = (cins & 0x03FE0000) >> 17;
24513 df = (cins & 0x00010000) >> 16;
24514 wt = (cins & 0x001F0000) >> 16;
24516 switch (operation) {
24518 case 0x190: { /* FCLASS.df */
24519 IRTemp t0 = newTemp(Ity_V128);
24520 t1 = newTemp(Ity_V128);
24521 t2 = newTemp(Ity_V128);
24522 t3 = newTemp(Ity_V128);
24523 t4 = newTemp(Ity_V128);
24524 t5 = newTemp(Ity_V128);
24526 switch (df) {
24527 case 0x00: { /* FCLASS.W */
24528 DIP("FCLASS.W w%d, w%d", wd, ws);
24529 assign(t0,
24530 binop(Iop_CmpEQ32x4,
24531 binop(Iop_AndV128,
24532 getWReg(ws),
24533 binop(Iop_64HLtoV128,
24534 mkU64(0x7F8000007F800000ull),
24535 mkU64(0x7F8000007F800000ull))),
24536 binop(Iop_64HLtoV128,
24537 mkU64(0ull), mkU64(0ull))));
24538 assign(t1,
24539 binop(Iop_CmpEQ32x4,
24540 binop(Iop_AndV128,
24541 getWReg(ws),
24542 binop(Iop_64HLtoV128,
24543 mkU64(0x7F8000007F800000ull),
24544 mkU64(0x7F8000007F800000ull))),
24545 binop(Iop_64HLtoV128,
24546 mkU64(0x7F8000007F800000ull),
24547 mkU64(0x7F8000007F800000ull))));
24548 assign(t2,
24549 binop(Iop_SarN32x4,
24550 getWReg(ws), mkU8(31)));
24551 assign(t3,
24552 binop(Iop_CmpEQ32x4,
24553 binop(Iop_AndV128,
24554 getWReg(ws),
24555 binop(Iop_64HLtoV128,
24556 mkU64(0x0040000000400000ull),
24557 mkU64(0x0040000000400000ull))),
24558 binop(Iop_64HLtoV128,
24559 mkU64(0x0040000000400000ull),
24560 mkU64(0x0040000000400000ull))));
24561 assign(t4,
24562 binop(Iop_CmpEQ32x4,
24563 binop(Iop_AndV128,
24564 getWReg(ws),
24565 binop(Iop_64HLtoV128,
24566 mkU64(0x007FFFFF007FFFFFULL),
24567 mkU64(0x007FFFFF007FFFFFULL))),
24568 binop(Iop_64HLtoV128,
24569 mkU64(0ull), mkU64(0ull))));
24570 assign(t5,
24571 binop(Iop_Shl32x4,
24572 binop(Iop_OrV128,
24573 binop(Iop_AndV128,
24574 mkexpr(t1),
24575 binop(Iop_AndV128,
24576 mkexpr(t4),
24577 binop(Iop_64HLtoV128,
24578 mkU64(0x100000001ull),
24579 mkU64(0x100000001ull)))),
24580 binop(Iop_OrV128,
24581 binop(Iop_AndV128,
24582 mkexpr(t0),
24583 binop(Iop_OrV128,
24584 binop(Iop_AndV128,
24585 mkexpr(t4),
24586 binop(Iop_64HLtoV128,
24587 mkU64(0x800000008ull),
24588 mkU64(0x800000008ull))),
24589 binop(Iop_AndV128,
24590 unop(Iop_NotV128,
24591 mkexpr(t4)),
24592 binop(Iop_64HLtoV128,
24593 mkU64(0x400000004ull),
24594 mkU64(0x400000004ull))))),
24595 binop(Iop_AndV128,
24596 unop(Iop_NotV128,
24597 mkexpr(t1)),
24598 binop(Iop_AndV128,
24599 unop(Iop_NotV128,
24600 mkexpr(t0)),
24601 binop(Iop_64HLtoV128,
24602 mkU64(0x200000002ull),
24603 mkU64(0x200000002ull)))))),
24604 binop(Iop_OrV128,
24605 binop(Iop_AndV128,
24606 mkexpr(t2),
24607 binop(Iop_64HLtoV128,
24608 mkU64(0x200000002ull),
24609 mkU64(0x200000002ull))),
24610 binop(Iop_AndV128,
24611 unop(Iop_NotV128,
24612 mkexpr(t2)),
24613 binop(Iop_64HLtoV128,
24614 mkU64(0x600000006ull),
24615 mkU64(0x600000006ull))))));
24616 putWReg(wd,
24617 binop(Iop_OrV128,
24618 mkexpr(t5),
24619 binop(Iop_AndV128,
24620 binop(Iop_CmpEQ32x4,
24621 mkexpr(t5),
24622 binop(Iop_64HLtoV128,
24623 mkU64(0ull),
24624 mkU64(0ull))),
24625 binop(Iop_OrV128,
24626 binop(Iop_AndV128,
24627 mkexpr(t3),
24628 binop(Iop_64HLtoV128,
24629 mkU64(0x100000001ull),
24630 mkU64(0x100000001ull))),
24631 binop(Iop_AndV128,
24632 unop(Iop_NotV128, mkexpr(t3)),
24633 binop(Iop_64HLtoV128,
24634 mkU64(0x200000002ull),
24635 mkU64(0x200000002ull)))))));
24636 break;
24639 case 0x01: { /* FCLASS.D */
24640 DIP("FCLASS.D w%d, w%d", wd, ws);
24641 assign(t0,
24642 binop(Iop_CmpEQ64x2,
24643 binop(Iop_AndV128,
24644 getWReg(ws),
24645 binop(Iop_64HLtoV128,
24646 mkU64(0x7FF0000000000000ull),
24647 mkU64(0x7FF0000000000000ull))),
24648 binop(Iop_64HLtoV128,
24649 mkU64(0ull), mkU64(0ull))));
24650 assign(t1,
24651 binop(Iop_CmpEQ64x2,
24652 binop(Iop_AndV128,
24653 getWReg(ws),
24654 binop(Iop_64HLtoV128,
24655 mkU64(0x7FF0000000000000ull),
24656 mkU64(0x7FF0000000000000ull))),
24657 binop(Iop_64HLtoV128,
24658 mkU64(0x7FF0000000000000ull),
24659 mkU64(0x7FF0000000000000ull))));
24660 assign(t2,
24661 binop(Iop_SarN64x2,
24662 getWReg(ws), mkU8(63)));
24663 assign(t3,
24664 binop(Iop_CmpEQ64x2,
24665 binop(Iop_AndV128,
24666 getWReg(ws),
24667 binop(Iop_64HLtoV128,
24668 mkU64(0x0008000000000000ull),
24669 mkU64(0x0008000000000000ull))),
24670 binop(Iop_64HLtoV128,
24671 mkU64(0x0008000000000000ull),
24672 mkU64(0x0008000000000000ull))));
24673 assign(t4,
24674 binop(Iop_CmpEQ64x2,
24675 binop(Iop_AndV128,
24676 getWReg(ws),
24677 binop(Iop_64HLtoV128,
24678 mkU64(0x000FFFFFFFFFFFFFULL),
24679 mkU64(0x000FFFFFFFFFFFFFULL))),
24680 binop(Iop_64HLtoV128,
24681 mkU64(0ull), mkU64(0ull))));
24682 assign(t5,
24683 binop(Iop_Shl64x2,
24684 binop(Iop_OrV128,
24685 binop(Iop_AndV128,
24686 mkexpr(t1),
24687 binop(Iop_AndV128,
24688 mkexpr(t4),
24689 binop(Iop_64HLtoV128,
24690 mkU64(1ull),
24691 mkU64(1ull)))),
24692 binop(Iop_OrV128,
24693 binop(Iop_AndV128,
24694 mkexpr(t0),
24695 binop(Iop_OrV128,
24696 binop(Iop_AndV128,
24697 mkexpr(t4),
24698 binop(Iop_64HLtoV128,
24699 mkU64(8ull),
24700 mkU64(8ull))),
24701 binop(Iop_AndV128,
24702 unop(Iop_NotV128,
24703 mkexpr(t4)),
24704 binop(Iop_64HLtoV128,
24705 mkU64(4ull),
24706 mkU64(4ull))))),
24707 binop(Iop_AndV128,
24708 unop(Iop_NotV128,
24709 mkexpr(t1)),
24710 binop(Iop_AndV128,
24711 unop(Iop_NotV128,
24712 mkexpr(t0)),
24713 binop(Iop_64HLtoV128,
24714 mkU64(2ull),
24715 mkU64(2ull)))))),
24716 binop(Iop_OrV128,
24717 binop(Iop_AndV128,
24718 mkexpr(t2),
24719 binop(Iop_64HLtoV128,
24720 mkU64(2ull),
24721 mkU64(2ull))),
24722 binop(Iop_AndV128,
24723 unop(Iop_NotV128,
24724 mkexpr(t2)),
24725 binop(Iop_64HLtoV128,
24726 mkU64(6ull),
24727 mkU64(6ull))))));
24728 putWReg(wd,
24729 binop(Iop_OrV128,
24730 mkexpr(t5),
24731 binop(Iop_AndV128,
24732 binop(Iop_CmpEQ64x2,
24733 mkexpr(t5),
24734 binop(Iop_64HLtoV128,
24735 mkU64(0ull),
24736 mkU64(0ull))),
24737 binop(Iop_OrV128,
24738 binop(Iop_AndV128,
24739 mkexpr(t3),
24740 binop(Iop_64HLtoV128,
24741 mkU64(1ull),
24742 mkU64(1ull))),
24743 binop(Iop_AndV128,
24744 unop(Iop_NotV128,
24745 mkexpr(t3)),
24746 binop(Iop_64HLtoV128,
24747 mkU64(2ull),
24748 mkU64(2ull)))))));
24749 break;
24752 default:
24753 return -1;
24756 break;
24759 case 0x191: { /* FTRUNC_S.df */
24760 switch (df) {
24761 case 0x00: { /* FTRUNC_S.W */
24762 DIP("FTRUNC_S.W w%d, w%d", wd, ws);
24763 calculateMSACSR(ws, wd, FTRUNCSW, 1);
24764 putWReg(wd, unop(Iop_F32toI32Sx4_RZ, getWReg(ws)));
24765 break;
24768 case 0x01: { /* FTRUNC_S.D */
24769 DIP("FTRUNC_S.D w%d, w%d", wd, ws);
24770 calculateMSACSR(ws, wd, FTRUNCSD, 1);
24771 t1 = newTemp(Ity_I64);
24772 t2 = newTemp(Ity_I64);
24773 t3 = newTemp(Ity_V128);
24774 assign(t3,
24775 binop(Iop_AndV128,
24776 unop(Iop_NotV128,
24777 binop(Iop_CmpUN64Fx2,
24778 getWReg(ws),
24779 getWReg(ws))),
24780 binop(Iop_Max64Fx2,
24781 getWReg(ws),
24782 binop(Iop_64HLtoV128,
24783 mkU64(0xC3E0000000000000),
24784 mkU64(0xC3E0000000000000)))));
24785 assign(t1,
24786 binop(Iop_F64toI64S, mkU32(0x3),
24787 unop(Iop_ReinterpI64asF64,
24788 unop(Iop_V128to64, mkexpr(t3)))));
24789 assign(t2,
24790 binop(Iop_F64toI64S, mkU32(0x3),
24791 unop(Iop_ReinterpI64asF64,
24792 unop(Iop_V128HIto64, mkexpr(t3)))));
24793 putWReg(wd,
24794 binop(Iop_64HLtoV128,
24795 mkexpr(t2), mkexpr(t1)));
24796 break;
24799 default:
24800 return -1;
24803 break;
24806 case 0x192: { /* FTRUNC_U.df */
24807 switch (df) {
24808 case 0x00: { /* FTRUNC_U.W */
24809 DIP("FTRUNC_U.W w%d, w%d", wd, ws);
24810 calculateMSACSR(ws, wd, FTRUNCUW, 1);
24811 putWReg(wd, unop(Iop_F32toI32Ux4_RZ, getWReg(ws)));
24812 break;
24815 case 0x01: { /* FTRUNC_U.D */
24816 DIP("FTRUNC_U.D w%d, w%d", wd, ws);
24817 calculateMSACSR(ws, wd, FTRUNCUD, 1);
24818 t1 = newTemp(Ity_I64);
24819 t2 = newTemp(Ity_I64);
24820 assign(t1,
24821 binop(Iop_F64toI64U,
24822 mkU32(0x3),
24823 unop(Iop_ReinterpI64asF64,
24824 unop(Iop_V128to64,
24825 getWReg(ws)))));
24826 assign(t2,
24827 binop(Iop_F64toI64U,
24828 mkU32(0x3),
24829 unop(Iop_ReinterpI64asF64,
24830 unop(Iop_V128HIto64,
24831 getWReg(ws)))));
24832 putWReg(wd,
24833 binop(Iop_64HLtoV128,
24834 mkexpr(t2), mkexpr(t1)));
24835 break;
24838 default:
24839 return -1;
24842 break;
24845 case 0x193: { /* FSQRT.df */
24846 switch (df) {
24847 case 0x00: { /* FSQRT.W */
24848 DIP("FSQRT.W w%d, w%d", wd, ws);
24849 IRExpr *rm = get_IR_roundingmode_MSA();
24850 calculateMSACSR(ws, wd, FSQRTW, 1);
24851 putWReg(wd, binop(Iop_Sqrt32Fx4, rm, getWReg(ws)));
24852 break;
24855 case 0x01: { /* FSQRT.D */
24856 DIP("FSQRT.D w%d, w%d", wd, ws);
24857 IRExpr *rm = get_IR_roundingmode_MSA();
24858 calculateMSACSR(ws, wd, FSQRTD, 1);
24859 putWReg(wd, binop(Iop_Sqrt64Fx2, rm, getWReg(ws)));
24860 break;
24863 default:
24864 return -1;
24867 break;
24870 case 0x194: { /* FRSQRT.df */
24871 switch (df) {
24872 case 0x00: { /* FRSQRT.W */
24873 DIP("FRSQRT.W w%d, w%d", wd, ws);
24874 calculateMSACSR(ws, wd, FRSQRTW, 1);
24875 putWReg(wd, unop(Iop_RSqrtEst32Fx4, getWReg(ws)));
24876 break;
24879 case 0x01: { /* FRSQRT.D */
24880 DIP("FRSQRT.D w%d, w%d", wd, ws);
24881 calculateMSACSR(ws, wd, FRSQRTD, 1);
24882 putWReg(wd, unop(Iop_RSqrtEst64Fx2, getWReg(ws)));
24883 break;
24886 default:
24887 return -1;
24890 break;
24893 case 0x195: { /* FRCP.df */
24894 switch (df) { /* FRCP.W */
24895 case 0x00: {
24896 DIP("FRCP.W w%d, w%d", wd, ws);
24897 calculateMSACSR(ws, wd, FRCPW, 1);
24898 putWReg(wd, unop(Iop_RecipEst32Fx4, getWReg(ws)));
24899 break;
24902 case 0x01: { /* FRCP.D */
24903 DIP("FRCP.D w%d, w%d", wd, ws);
24904 calculateMSACSR(ws, wd, FRCPD, 1);
24905 putWReg(wd, unop(Iop_RecipEst64Fx2, getWReg(ws)));
24906 break;
24909 default:
24910 return -1;
24913 break;
24916 case 0x196: { /* FRINT.df */
24917 t1 = newTemp(Ity_V128);
24918 t2 = newTemp(Ity_V128);
24919 t3 = newTemp(Ity_V128);
24920 t4 = newTemp(Ity_V128);
24921 IRExpr *rm = get_IR_roundingmode_MSA();
24922 assign(t1, getWReg(ws));
24924 switch (df) {
24925 case 0x00: { /* FRINT.W */
24926 DIP("FRINT.W w%d, w%d", wd, ws);
24927 calculateMSACSR(ws, wt, FRINTW, 1);
24928 assign(t2,
24929 binop(Iop_OrV128,
24930 binop(Iop_CmpLT32Fx4,
24931 mkexpr(t1),
24932 binop(Iop_64HLtoV128,
24933 mkU64(0xCF000000CF000000ull),
24934 mkU64(0xCF000000CF000000ull))),
24935 binop(Iop_CmpLT32Fx4,
24936 binop(Iop_64HLtoV128,
24937 mkU64(0x4F0000004F000000ull),
24938 mkU64(0x4F0000004F000000ull)),
24939 mkexpr(t1))));
24940 assign(t3,
24941 binop(Iop_CmpEQ32x4,
24942 binop(Iop_AndV128,
24943 mkexpr(t1),
24944 binop(Iop_64HLtoV128,
24945 mkU64(0x0040000000400000ull),
24946 mkU64(0x0040000000400000ull))),
24947 binop(Iop_64HLtoV128,
24948 mkU64(0x0040000000400000ull),
24949 mkU64(0x0040000000400000ull))));
24950 assign(t4,
24951 binop(Iop_CmpUN32Fx4,
24952 mkexpr(t1), mkexpr(t1)));
24953 IRTemp tmp[4];
24954 Int i;
24956 for (i = 0; i < 4; i++) {
24957 tmp[i] = newTemp(Ity_I32);
24958 assign(tmp[i],
24959 unop(Iop_ReinterpF32asI32,
24960 binop(Iop_RoundF32toInt, rm,
24961 unop(Iop_ReinterpI32asF32,
24962 binop(Iop_GetElem32x4,
24963 mkexpr(t1), mkU8(i))))));
24966 putWReg(wd,
24967 binop(Iop_OrV128,
24968 binop(Iop_OrV128,
24969 binop(Iop_AndV128,
24970 binop(Iop_OrV128,
24971 mkexpr(t2),
24972 binop(Iop_AndV128,
24973 mkexpr(t4),
24974 unop(Iop_NotV128,
24975 mkexpr(t3)))),
24976 mkexpr(t1)),
24977 binop(Iop_AndV128,
24978 binop(Iop_AndV128,
24979 mkexpr(t4),
24980 mkexpr(t3)),
24981 binop(Iop_64HLtoV128,
24982 mkU64(0x7FBFFFFF7FBFFFFF),
24983 mkU64(0x7FBFFFFF7FBFFFFF)))),
24984 binop(Iop_AndV128,
24985 unop(Iop_NotV128,
24986 binop(Iop_OrV128,
24987 mkexpr(t2),
24988 mkexpr(t4))),
24989 binop(Iop_OrV128,
24990 binop(Iop_64HLtoV128,
24991 binop(Iop_32HLto64,
24992 mkexpr(tmp[3]),
24993 mkexpr(tmp[2])),
24994 binop(Iop_32HLto64,
24995 mkexpr(tmp[1]),
24996 mkexpr(tmp[0]))),
24997 binop(Iop_AndV128,
24998 mkexpr(t1),
24999 binop(Iop_64HLtoV128,
25000 mkU64(0x8000000080000000ull),
25001 mkU64(0x8000000080000000ull)))
25002 ))));
25003 break;
25006 case 0x01: { /* FRINT.D */
25007 DIP("FRINT.D w%d, w%d", wd, ws);
25008 calculateMSACSR(ws, wt, FRINTD, 1);
25009 assign(t2,
25010 binop(Iop_OrV128,
25011 binop(Iop_CmpLT64Fx2,
25012 mkexpr(t1),
25013 binop(Iop_64HLtoV128,
25014 mkU64(0xC3E0000000000000ull),
25015 mkU64(0xC3E0000000000000ull))),
25016 binop(Iop_CmpLT64Fx2,
25017 binop(Iop_64HLtoV128,
25018 mkU64(0x43E0000000000000ull),
25019 mkU64(0x43E0000000000000ull)),
25020 mkexpr(t1))));
25021 assign(t3,
25022 binop(Iop_CmpEQ64x2,
25023 binop(Iop_AndV128,
25024 getWReg(ws),
25025 binop(Iop_64HLtoV128,
25026 mkU64(0x0008000000000000ull),
25027 mkU64(0x0008000000000000ull))),
25028 binop(Iop_64HLtoV128,
25029 mkU64(0x0008000000000000ull),
25030 mkU64(0x0008000000000000ull))));
25031 assign(t4,
25032 binop(Iop_CmpUN64Fx2,
25033 mkexpr(t1), mkexpr(t1)));
25034 IRTemp tmp[2];
25035 Int i;
25037 for (i = 0; i < 2; i++) {
25038 tmp[i] = newTemp(Ity_I64);
25039 assign(tmp[i],
25040 unop(Iop_ReinterpF64asI64,
25041 binop(Iop_RoundF64toInt, rm,
25042 unop(Iop_ReinterpI64asF64,
25043 binop(Iop_GetElem64x2,
25044 mkexpr(t1), mkU8(i))))));
25047 putWReg(wd,
25048 binop(Iop_OrV128,
25049 binop(Iop_OrV128,
25050 binop(Iop_AndV128,
25051 binop(Iop_OrV128,
25052 mkexpr(t2),
25053 binop(Iop_AndV128,
25054 mkexpr(t4),
25055 unop(Iop_NotV128,
25056 mkexpr(t3)))),
25057 mkexpr(t1)),
25058 binop(Iop_AndV128,
25059 binop(Iop_AndV128,
25060 mkexpr(t4),
25061 mkexpr(t3)),
25062 binop(Iop_64HLtoV128,
25063 mkU64(0x7FF7FFFFFFFFFFFF),
25064 mkU64(0x7FF7FFFFFFFFFFFF)))),
25065 binop(Iop_AndV128,
25066 unop(Iop_NotV128,
25067 binop(Iop_OrV128,
25068 mkexpr(t2),
25069 mkexpr(t4))),
25070 binop(Iop_OrV128,
25071 binop(Iop_64HLtoV128,
25072 mkexpr(tmp[1]),
25073 mkexpr(tmp[0])),
25074 binop(Iop_AndV128,
25075 mkexpr(t1),
25076 binop(Iop_64HLtoV128,
25077 mkU64(0x8000000000000000ull),
25078 mkU64(0x8000000000000000ull))
25079 )))));
25080 break;
25083 default:
25084 return -1;
25087 break;
25090 case 0x197: { /* FLOG2.df */
25092 switch (df) {
25093 case 0x00: { /* FLOG2.W */
25094 DIP("FLOG2.W w%d, w%d", wd, ws);
25095 calculateMSACSR(ws, wt, FLOG2W, 1);
25096 putWReg(wd, unop(Iop_Log2_32Fx4, getWReg(ws)));
25097 break;
25100 case 0x01: { /* FLOG2.D */
25101 DIP("FLOG2.D w%d, w%d", wd, ws);
25102 calculateMSACSR(ws, wt, FLOG2D, 1);
25103 putWReg(wd, unop(Iop_Log2_64Fx2, getWReg(ws)));
25104 break;
25107 default:
25108 return -1;
25111 break;
25114 case 0x198: { /* FEXUPL.df */
25115 switch (df) {
25116 case 0x00: { /* FEXUPL.W */
25117 DIP("FEXUPL.W w%d, w%d", wd, ws);
25118 calculateMSACSR(ws, wt, FEXUPLW, 1);
25119 putWReg(wd,
25120 unop(Iop_F16toF32x4,
25121 unop(Iop_V128HIto64,
25122 getWReg(ws))));
25123 break;
25126 case 0x01: { /* FEXUPL.D */
25127 DIP("FEXUPL.D w%d, w%d", wd, ws);
25128 calculateMSACSR(ws, wt, FEXUPLD, 1);
25129 t1 = newTemp(Ity_I64);
25130 t2 = newTemp(Ity_I64);
25131 assign(t1,
25132 unop(Iop_ReinterpF64asI64,
25133 unop(Iop_F32toF64,
25134 unop(Iop_ReinterpI32asF32,
25135 unop(Iop_64to32,
25136 unop(Iop_V128HIto64,
25137 getWReg(ws)))))));
25138 assign(t2,
25139 unop(Iop_ReinterpF64asI64,
25140 unop(Iop_F32toF64,
25141 unop(Iop_ReinterpI32asF32,
25142 unop(Iop_64HIto32,
25143 unop(Iop_V128HIto64,
25144 getWReg(ws)))))));
25145 putWReg(wd,
25146 binop(Iop_64HLtoV128,
25147 mkexpr(t2), mkexpr(t1)));
25148 break;
25151 default:
25152 return -1;
25155 break;
25158 case 0x199: { /* FEXUPR.df */
25159 switch (df) {
25160 case 0x00: { /* FEXUPR.W */
25161 DIP("FEXUPR.W w%d, w%d", wd, ws);
25162 calculateMSACSR(ws, wt, FEXUPRW, 1);
25163 putWReg(wd,
25164 unop(Iop_F16toF32x4,
25165 unop(Iop_V128to64,
25166 getWReg(ws))));
25167 break;
25170 case 0x01: { /* FEXUPR.D */
25171 DIP("FEXUPR.D w%d, w%d", wd, ws);
25172 calculateMSACSR(ws, wt, FEXUPRD, 1);
25173 t1 = newTemp(Ity_I64);
25174 t2 = newTemp(Ity_I64);
25175 assign(t1,
25176 unop(Iop_ReinterpF64asI64,
25177 unop(Iop_F32toF64,
25178 unop(Iop_ReinterpI32asF32,
25179 unop(Iop_64to32,
25180 unop(Iop_V128to64,
25181 getWReg(ws)))))));
25182 assign(t2,
25183 unop(Iop_ReinterpF64asI64,
25184 unop(Iop_F32toF64,
25185 unop(Iop_ReinterpI32asF32,
25186 unop(Iop_64HIto32,
25187 unop(Iop_V128to64,
25188 getWReg(ws)))))));
25189 putWReg(wd,
25190 binop(Iop_64HLtoV128,
25191 mkexpr(t2), mkexpr(t1)));
25192 break;
25195 default:
25196 return -1;
25199 break;
25202 case 0x19A: { /* FFQL.df */
25203 switch (df) {
25204 case 0x00: { /* FFQL.W */
25205 DIP("FFQL.W w%d, w%d", wd, ws);
25206 calculateMSACSR(ws, wt, FFQLW, 1);
25207 t1 = newTemp(Ity_V128);
25208 t2 = newTemp(Ity_I64);
25209 t3 = newTemp(Ity_I64);
25210 IRExpr *rm = get_IR_roundingmode_MSA();
25211 assign(t1,
25212 binop(Iop_SarN32x4,
25213 binop(Iop_InterleaveHI16x8,
25214 getWReg(ws),
25215 getWReg(ws)),
25216 mkU8(16)));
25217 assign(t2,
25218 binop(Iop_32HLto64,
25219 unop(Iop_ReinterpF32asI32,
25220 binop(Iop_I32StoF32, rm,
25221 binop(Iop_GetElem32x4,
25222 mkexpr(t1),
25223 mkU8(1)))),
25224 unop(Iop_ReinterpF32asI32,
25225 binop(Iop_I32StoF32, rm,
25226 binop(Iop_GetElem32x4,
25227 mkexpr(t1),
25228 mkU8(0))))));
25229 assign(t3,
25230 binop(Iop_32HLto64,
25231 unop(Iop_ReinterpF32asI32,
25232 binop(Iop_I32StoF32, rm,
25233 binop(Iop_GetElem32x4,
25234 mkexpr(t1),
25235 mkU8(3)))),
25236 unop(Iop_ReinterpF32asI32,
25237 binop(Iop_I32StoF32, rm,
25238 binop(Iop_GetElem32x4,
25239 mkexpr(t1),
25240 mkU8(2))))));
25241 putWReg(wd,
25242 triop(Iop_Div32Fx4, rm,
25243 binop(Iop_64HLtoV128,
25244 mkexpr(t3), mkexpr(t2)),
25245 binop(Iop_64HLtoV128,
25246 mkU64(0x4700000047000000),
25247 mkU64(0x4700000047000000))));
25248 break;
25251 case 0x01: { /* FFQL.D */
25252 DIP("FFQL.D w%d, w%d", wd, ws);
25253 calculateMSACSR(ws, wt, FFQLD, 1);
25254 t1 = newTemp(Ity_V128);
25255 t2 = newTemp(Ity_I64);
25256 t3 = newTemp(Ity_I64);
25257 IRExpr *rm = get_IR_roundingmode_MSA();
25258 assign(t1,
25259 binop(Iop_SarN64x2,
25260 binop(Iop_InterleaveHI32x4,
25261 getWReg(ws),
25262 getWReg(ws)),
25263 mkU8(32)));
25264 assign(t2,
25265 unop(Iop_ReinterpF64asI64,
25266 binop(Iop_I64StoF64, rm,
25267 unop(Iop_V128to64,
25268 mkexpr(t1)))));
25269 assign(t3,
25270 unop(Iop_ReinterpF64asI64,
25271 binop(Iop_I64StoF64, rm,
25272 unop(Iop_V128HIto64,
25273 mkexpr(t1)))));
25274 putWReg(wd,
25275 triop(Iop_Div64Fx2, rm,
25276 binop(Iop_64HLtoV128,
25277 mkexpr(t3), mkexpr(t2)),
25278 binop(Iop_64HLtoV128,
25279 mkU64(0x41E0000000000000),
25280 mkU64(0x41E0000000000000))));
25281 break;
25284 default:
25285 return -1;
25288 break;
25291 case 0x19B: { /* FFQR.df */
25292 switch (df) {
25293 case 0x00: { /* FFQR.W */
25294 DIP("FFQR.W w%d, w%d", wd, ws);
25295 calculateMSACSR(ws, wt, FFQRW, 1);
25296 t1 = newTemp(Ity_V128);
25297 t2 = newTemp(Ity_I64);
25298 t3 = newTemp(Ity_I64);
25299 IRExpr *rm = get_IR_roundingmode_MSA();
25300 assign(t1,
25301 binop(Iop_SarN32x4,
25302 binop(Iop_InterleaveLO16x8,
25303 getWReg(ws),
25304 getWReg(ws)),
25305 mkU8(16)));
25306 assign(t2,
25307 binop(Iop_32HLto64,
25308 unop(Iop_ReinterpF32asI32,
25309 binop(Iop_I32StoF32, rm,
25310 binop(Iop_GetElem32x4,
25311 mkexpr(t1),
25312 mkU8(1)))),
25313 unop(Iop_ReinterpF32asI32,
25314 binop(Iop_I32StoF32, rm,
25315 binop(Iop_GetElem32x4,
25316 mkexpr(t1),
25317 mkU8(0))))));
25318 assign(t3,
25319 binop(Iop_32HLto64,
25320 unop(Iop_ReinterpF32asI32,
25321 binop(Iop_I32StoF32, rm,
25322 binop(Iop_GetElem32x4,
25323 mkexpr(t1),
25324 mkU8(3)))),
25325 unop(Iop_ReinterpF32asI32,
25326 binop(Iop_I32StoF32, rm,
25327 binop(Iop_GetElem32x4,
25328 mkexpr(t1),
25329 mkU8(2))))));
25330 putWReg(wd,
25331 triop(Iop_Div32Fx4, rm,
25332 binop(Iop_64HLtoV128,
25333 mkexpr(t3), mkexpr(t2)),
25334 binop(Iop_64HLtoV128,
25335 mkU64(0x4700000047000000),
25336 mkU64(0x4700000047000000))));
25337 break;
25340 case 0x01: { /* FFQR.D */
25341 DIP("FFQR.D w%d, w%d", wd, ws);
25342 calculateMSACSR(ws, wt, FFQRD, 1);
25343 t1 = newTemp(Ity_V128);
25344 t2 = newTemp(Ity_I64);
25345 t3 = newTemp(Ity_I64);
25346 IRExpr *rm = get_IR_roundingmode_MSA();
25347 assign(t1,
25348 binop(Iop_SarN64x2,
25349 binop(Iop_InterleaveLO32x4,
25350 getWReg(ws),
25351 getWReg(ws)),
25352 mkU8(32)));
25353 assign(t2,
25354 unop(Iop_ReinterpF64asI64,
25355 binop(Iop_I64StoF64, rm,
25356 unop(Iop_V128to64,
25357 mkexpr(t1)))));
25358 assign(t3,
25359 unop(Iop_ReinterpF64asI64,
25360 binop(Iop_I64StoF64, rm,
25361 unop(Iop_V128HIto64,
25362 mkexpr(t1)))));
25363 putWReg(wd,
25364 triop(Iop_Div64Fx2, rm,
25365 binop(Iop_64HLtoV128,
25366 mkexpr(t3), mkexpr(t2)),
25367 binop(Iop_64HLtoV128,
25368 mkU64(0x41E0000000000000),
25369 mkU64(0x41E0000000000000))));
25370 break;
25373 default:
25374 return -1;
25377 break;
25380 case 0x19C: { /* FTINT_S.df */
25381 switch (df) { /* FTINT_S.W */
25382 case 0x00: {
25383 DIP("FTINT_S.W w%d, w%d", wd, ws);
25384 calculateMSACSR(ws, wd, FTINT_SW, 1);
25385 t1 = newTemp(Ity_I64);
25386 t2 = newTemp(Ity_I64);
25387 t3 = newTemp(Ity_V128);
25388 t4 = newTemp(Ity_I32);
25389 assign(t3,
25390 binop(Iop_AndV128,
25391 unop(Iop_NotV128,
25392 binop(Iop_CmpUN32Fx4,
25393 getWReg(ws),
25394 getWReg(ws))),
25395 binop(Iop_Max32Fx4,
25396 getWReg(ws),
25397 binop(Iop_64HLtoV128,
25398 mkU64(0xCF000000CF000000),
25399 mkU64(0xCF000000CF000000)))));
25400 IRExpr *rm = get_IR_roundingmode_MSA();
25401 assign(t1,
25402 binop(Iop_32HLto64,
25403 binop(Iop_F32toI32S, rm,
25404 unop(Iop_ReinterpI32asF32,
25405 binop(Iop_GetElem32x4,
25406 mkexpr(t3), mkU8(1)))),
25407 binop(Iop_F32toI32S, rm,
25408 unop(Iop_ReinterpI32asF32,
25409 binop(Iop_GetElem32x4,
25410 mkexpr(t3), mkU8(0))))));
25411 assign(t2,
25412 binop(Iop_32HLto64,
25413 binop(Iop_F32toI32S, rm,
25414 unop(Iop_ReinterpI32asF32,
25415 binop(Iop_GetElem32x4,
25416 mkexpr(t3), mkU8(3)))),
25417 binop(Iop_F32toI32S, rm,
25418 unop(Iop_ReinterpI32asF32,
25419 binop(Iop_GetElem32x4,
25420 mkexpr(t3), mkU8(2))))));
25421 putWReg(wd,
25422 binop(Iop_64HLtoV128,
25423 mkexpr(t2), mkexpr(t1)));
25424 break;
25427 case 0x01: { /* FTINT_S.D */
25428 DIP("FTINT_S.D w%d, w%d", wd, ws);
25429 calculateMSACSR(ws, wd, FTINT_SD, 1);
25430 t1 = newTemp(Ity_I64);
25431 t2 = newTemp(Ity_I64);
25432 t3 = newTemp(Ity_V128);
25433 assign(t3,
25434 binop(Iop_AndV128,
25435 unop(Iop_NotV128,
25436 binop(Iop_CmpUN64Fx2,
25437 getWReg(ws),
25438 getWReg(ws))),
25439 binop(Iop_Max64Fx2,
25440 getWReg(ws),
25441 binop(Iop_64HLtoV128,
25442 mkU64(0xC3E0000000000000),
25443 mkU64(0xC3E0000000000000)))));
25444 IRExpr *rm = get_IR_roundingmode_MSA();
25445 assign(t1,
25446 binop(Iop_F64toI64S, rm,
25447 unop(Iop_ReinterpI64asF64,
25448 unop(Iop_V128to64, mkexpr(t3)))));
25449 assign(t2,
25450 binop(Iop_F64toI64S, rm,
25451 unop(Iop_ReinterpI64asF64,
25452 unop(Iop_V128HIto64, mkexpr(t3)))));
25453 putWReg(wd,
25454 binop(Iop_64HLtoV128,
25455 mkexpr(t2), mkexpr(t1)));
25456 break;
25459 default:
25460 return -1;
25463 break;
25466 case 0x19D: {/* FTINT_U.df */
25467 switch (df) { /* FTINT_U.W */
25468 case 0x00: {
25469 DIP("FTINT_U.W w%d, w%d", wd, ws);
25470 calculateMSACSR(ws, wd, FTINT_UW, 1);
25471 t1 = newTemp(Ity_I64);
25472 t2 = newTemp(Ity_I64);
25473 t3 = newTemp(Ity_V128);
25474 t4 = newTemp(Ity_V128);
25475 IRExpr *rm = get_IR_roundingmode_MSA();
25476 assign(t1,
25477 binop(Iop_32HLto64,
25478 binop(Iop_F32toI32U, rm,
25479 unop(Iop_ReinterpI32asF32,
25480 binop(Iop_GetElem32x4,
25481 getWReg(ws), mkU8(1)))),
25482 binop(Iop_F32toI32U, rm,
25483 unop(Iop_ReinterpI32asF32,
25484 binop(Iop_GetElem32x4,
25485 getWReg(ws), mkU8(0))))));
25486 assign(t2,
25487 binop(Iop_32HLto64,
25488 binop(Iop_F32toI32U, rm,
25489 unop(Iop_ReinterpI32asF32,
25490 binop(Iop_GetElem32x4,
25491 getWReg(ws), mkU8(3)))),
25492 binop(Iop_F32toI32U, rm,
25493 unop(Iop_ReinterpI32asF32,
25494 binop(Iop_GetElem32x4,
25495 getWReg(ws), mkU8(2))))));
25496 assign(t3,
25497 unop(Iop_NotV128,
25498 binop(Iop_SarN32x4,
25499 getWReg(ws),
25500 mkU8(31))));
25501 assign(t4,
25502 binop(Iop_CmpLT32Fx4,
25503 getWReg(ws),
25504 binop(Iop_64HLtoV128,
25505 mkU64(0x4EFFFFFF4EFFFFFF),
25506 mkU64(0x4EFFFFFF4EFFFFFF))));
25507 putWReg(wd,
25508 binop(Iop_OrV128,
25509 binop(Iop_AndV128,
25510 mkexpr(t4),
25511 binop(Iop_AndV128,
25512 binop(Iop_64HLtoV128,
25513 mkexpr(t2),
25514 mkexpr(t1)),
25515 mkexpr(t3))),
25516 binop(Iop_AndV128,
25517 unop(Iop_NotV128, mkexpr(t4)),
25518 unop(Iop_F32toI32Ux4_RZ,
25519 getWReg(ws)))));
25520 break;
25523 case 0x01: { /* FTINT_U.D */
25524 DIP("FTINT_U.D w%d, w%d", wd, ws);
25525 calculateMSACSR(ws, wd, FTINT_UD, 1);
25526 t1 = newTemp(Ity_I64);
25527 t2 = newTemp(Ity_I64);
25528 IRExpr *rm = get_IR_roundingmode_MSA();
25529 assign(t1,
25530 binop(Iop_F64toI64U, rm,
25531 unop(Iop_ReinterpI64asF64,
25532 unop(Iop_V128to64,
25533 getWReg(ws)))));
25534 assign(t2,
25535 binop(Iop_F64toI64U, rm,
25536 unop(Iop_ReinterpI64asF64,
25537 unop(Iop_V128HIto64,
25538 getWReg(ws)))));
25539 putWReg(wd,
25540 binop(Iop_64HLtoV128,
25541 mkexpr(t2), mkexpr(t1)));
25542 break;
25545 default:
25546 return -1;
25549 break;
25552 case 0x19E: { /* FFINT_S.df */
25553 t1 = newTemp(Ity_V128);
25554 assign(t1, getWReg(ws));
25555 IRExpr *rm = get_IR_roundingmode_MSA();
25557 switch (df) {
25558 case 0x00: { /* FFINT_S.W */
25559 DIP("FFINT_S.W w%d, w%d", wd, ws);
25560 calculateMSACSR(ws, wt, FFINTSW, 1);
25561 IRTemp tmp[4];
25562 Int i;
25564 for (i = 0; i < 4; i++) {
25565 tmp[i] = newTemp(Ity_F32);
25566 assign(tmp[i],
25567 binop(Iop_I32StoF32, rm,
25568 binop(Iop_GetElem32x4,
25569 mkexpr(t1), mkU8(i))));
25572 putWReg(wd,
25573 binop(Iop_64HLtoV128,
25574 binop(Iop_32HLto64,
25575 unop(Iop_ReinterpF32asI32,
25576 mkexpr(tmp[3])),
25577 unop(Iop_ReinterpF32asI32,
25578 mkexpr(tmp[2]))),
25579 binop(Iop_32HLto64,
25580 unop(Iop_ReinterpF32asI32,
25581 mkexpr(tmp[1])),
25582 unop(Iop_ReinterpF32asI32,
25583 mkexpr(tmp[0])))));
25584 break;
25587 case 0x01: { /* FFINT_S.D */
25588 DIP("FFINT_S.D w%d, w%d", wd, ws);
25589 calculateMSACSR(ws, wt, FFINTSD, 1);
25590 IRTemp tmp[2];
25591 Int i;
25593 for (i = 0; i < 2; i++) {
25594 tmp[i] = newTemp(Ity_F64);
25595 assign(tmp[i],
25596 binop(Iop_I64StoF64, rm,
25597 binop(Iop_GetElem64x2,
25598 mkexpr(t1), mkU8(i))));
25601 putWReg(wd,
25602 binop(Iop_64HLtoV128,
25603 unop(Iop_ReinterpF64asI64,
25604 mkexpr(tmp[1])),
25605 unop(Iop_ReinterpF64asI64,
25606 mkexpr(tmp[0]))));
25607 break;
25610 default:
25611 return -1;
25614 break;
25617 case 0x19F: { /* FFINT_U.df */
25618 IRExpr *rm = get_IR_roundingmode_MSA();
25620 switch (df) {
25621 case 0x00: { /* FFINT_U.W */
25622 DIP("FFINT_U.W w%d, w%d", wd, ws);
25623 calculateMSACSR(ws, wt, FFINT_UW, 1);
25624 putWReg(wd, unop(Iop_I32UtoF32x4_DEP, getWReg(ws)));
25625 break;
25628 case 0x01: { /* FFINT_U.D */
25629 DIP("FFINT_U.D w%d, w%d",
25630 wd, ws);
25631 calculateMSACSR(ws, wt,
25632 FFINT_UD, 1);
25633 t1 = newTemp(Ity_I64);
25634 t2 = newTemp(Ity_I64);
25635 assign(t1,
25636 unop(Iop_ReinterpF64asI64,
25637 binop(Iop_I64UtoF64, rm,
25638 unop(Iop_V128to64,
25639 getWReg(ws)))));
25640 assign(t2,
25641 unop(Iop_ReinterpF64asI64,
25642 binop(Iop_I64UtoF64, rm,
25643 unop(Iop_V128HIto64,
25644 getWReg(ws)))));
25645 putWReg(wd,
25646 binop(Iop_64HLtoV128,
25647 mkexpr(t2), mkexpr(t1)));
25648 break;
25651 default:
25652 return -1;
25655 break;
25658 default:
25659 return -1;
25662 return 0;
25665 static Int msa_MI10_load(UInt cins, UChar wd, UChar ws) { /* MI10 (0x20) */
25666 IRTemp t1;
25667 UShort i10;
25668 UChar df;
25670 i10 = (cins & 0x03FF0000) >> 16;
25671 df = cins & 0x00000003;
25673 switch (df) {
25674 case 0x00: { /* LD.B */
25675 DIP("LD.B w%d, %d(r%d)", wd, ws, i10);
25676 LOAD_STORE_PATTERN_MSA(i10);
25677 putWReg(wd, load(Ity_V128, mkexpr(t1)));
25678 break;
25681 case 0x01: { /* LD.H */
25682 DIP("LD.H w%d, %d(r%d)", wd, ws, i10);
25683 LOAD_STORE_PATTERN_MSA(i10 << 1);
25684 #if defined (_MIPSEL)
25685 putWReg(wd, load(Ity_V128, mkexpr(t1)));
25686 #elif defined (_MIPSEB)
25687 putWReg(wd,
25688 unop(Iop_Reverse8sIn16_x8,
25689 load(Ity_V128, mkexpr(t1))));
25690 #endif
25691 break;
25694 case 0x02: { /* LD.W */
25695 DIP("LD.W w%d, %d(r%d)", wd, ws, i10);
25696 LOAD_STORE_PATTERN_MSA(i10 << 2);
25697 #if defined (_MIPSEL)
25698 putWReg(wd, load(Ity_V128, mkexpr(t1)));
25699 #elif defined (_MIPSEB)
25700 putWReg(wd,
25701 unop(Iop_Reverse8sIn32_x4,
25702 load(Ity_V128, mkexpr(t1))));
25703 #endif
25704 break;
25707 case 0x03: { /* LD.D */
25708 DIP("LD.D w%d, %d(r%d)", wd, ws, i10);
25709 LOAD_STORE_PATTERN_MSA(i10 << 3);
25710 #if defined (_MIPSEL)
25711 putWReg(wd, load(Ity_V128, mkexpr(t1)));
25712 #elif defined (_MIPSEB)
25713 putWReg(wd,
25714 unop(Iop_Reverse8sIn64_x2,
25715 load(Ity_V128, mkexpr(t1))));
25716 #endif
25717 break;
25720 default:
25721 return -1;
25724 return 0;
25727 static Int msa_MI10_store(UInt cins, UChar wd, UChar ws) { /* MI10 (0x24) */
25728 IRTemp t1;
25729 UShort i10;
25730 UChar df;
25732 df = cins & 0x00000003;
25733 i10 = (cins & 0x03FF0000) >> 16;
25735 switch (df) {
25736 case 0x00: { /* ST.B */
25737 DIP("ST.B w%d, %d(r%d)", wd, ws, i10);
25738 LOAD_STORE_PATTERN_MSA(i10);
25739 store(mkexpr(t1), getWReg(wd));
25740 break;
25743 case 0x01: { /* ST.H */
25744 DIP("ST.H w%d, %d(r%d)", wd, ws, i10);
25745 LOAD_STORE_PATTERN_MSA(i10 << 1);
25746 #if defined (_MIPSEL)
25747 store(mkexpr(t1), getWReg(wd));
25748 #elif defined (_MIPSEB)
25749 store(mkexpr(t1),
25750 unop(Iop_Reverse8sIn16_x8, getWReg(wd)));
25751 #endif
25752 break;
25755 case 0x02: { /* ST.W */
25756 DIP("ST.W w%d, %d(r%d)", wd, ws, i10);
25757 LOAD_STORE_PATTERN_MSA(i10 << 2);
25758 #if defined (_MIPSEL)
25759 store(mkexpr(t1), getWReg(wd));
25760 #elif defined (_MIPSEB)
25761 store(mkexpr(t1),
25762 unop(Iop_Reverse8sIn32_x4, getWReg(wd)));
25763 #endif
25764 break;
25767 case 0x03: { /* ST.D */
25768 DIP("ST.D w%d, %d(r%d)", wd, ws, i10);
25769 LOAD_STORE_PATTERN_MSA(i10 << 3);
25770 #if defined (_MIPSEL)
25771 store(mkexpr(t1), getWReg(wd));
25772 #elif defined (_MIPSEB)
25773 store(mkexpr(t1),
25774 unop(Iop_Reverse8sIn64_x2, getWReg(wd)));
25775 #endif
25776 break;
25779 default:
25780 return -1;
25783 return 0;
25786 /*------------------------------------------------------------*/
25787 /*--- Disassemble a single MIPS MSA (SIMD) instruction ---*/
25788 /*--- Return values: ---*/
25789 /*--- 0: Success ---*/
25790 /*--- -1: Decode failure (unknown instruction) ---*/
25791 /*--- -2: Illegal instruction ---*/
25792 /*------------------------------------------------------------*/
25793 static Int disMSAInstr_MIPS_WRK ( UInt cins ) {
25794 UChar minor_opcode, wd, ws;
25796 vassert(has_msa);
25797 vassert((cins & 0xFC000000) == 0x78000000);
25799 minor_opcode = (cins & 0x20) > 0 ? (cins & 0x3C) : (cins & 0x3F);
25800 wd = (cins & 0x000007C0) >> 6;
25801 ws = (cins & 0x0000F800) >> 11;
25803 switch (minor_opcode) {
25804 case 0x0:
25805 return msa_I8_logical(cins, wd, ws);
25807 case 0x01:
25808 return msa_I8_branch(cins, wd, ws);
25810 case 0x02:
25811 return msa_I8_shift(cins, wd, ws);
25813 case 0x06:
25814 return msa_I5_06(cins, wd, ws);
25816 case 0x07:
25817 return msa_I5_07(cins, wd, ws);
25819 case 0x09:
25820 return msa_BIT_09(cins, wd, ws);
25822 case 0x0A:
25823 return msa_BIT_0A(cins, wd, ws);
25825 case 0x0D:
25826 return msa_3R_0D(cins, wd, ws);
25828 case 0x0E:
25829 return msa_3R_0E(cins, wd, ws);
25831 case 0x0F:
25832 return msa_3R_0F(cins, wd, ws);
25834 case 0x10:
25835 return msa_3R_10(cins, wd, ws);
25837 case 0x11:
25838 return msa_3R_11(cins, wd, ws);
25840 case 0x12:
25841 return msa_3R_12(cins, wd, ws);
25843 case 0x13:
25844 return msa_3R_13(cins, wd, ws);
25846 case 0x14:
25847 return msa_3R_14(cins, wd, ws);
25849 case 0x15:
25850 return msa_3R_15(cins, wd, ws);
25852 case 0x19:
25853 return msa_ELM(cins, wd, ws);
25855 case 0x1A:
25856 return msa_3R_1A(cins, wd, ws);
25858 case 0x1B:
25859 return msa_3R_1B(cins, wd, ws);
25861 case 0x1C:
25862 return msa_3R_1C(cins, wd, ws);
25864 case 0x1E:
25865 if ((cins & 0x03000000) == 0)
25866 return msa_VEC(cins, wd, ws);
25867 else if ((cins & 0x00200000) == 0)
25868 return msa_2R(cins, wd, ws);
25869 else
25870 return msa_2RF(cins, wd, ws);
25872 case 0x20:
25873 return msa_MI10_load(cins, wd, ws);
25875 case 0x24:
25876 return msa_MI10_store(cins, wd, ws);
25879 return -1;
25882 /*------------------------------------------------------------*/
25883 /*--- Disassemble a single instruction ---*/
25884 /*------------------------------------------------------------*/
25886 /* Disassemble a single instruction into IR. The instruction is
25887 located in host memory at guest_instr, and has guest IP of
25888 guest_PC_curr_instr, which will have been set before the call
25889 here. */
25891 static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
25892 Addr),
25893 Bool resteerCisOk,
25894 void* callback_opaque,
25895 Long delta64,
25896 const VexArchInfo* archinfo,
25897 const VexAbiInfo* abiinfo,
25898 Bool sigill_diag )
25900 IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7;
25902 UInt opcode, cins, rs, rt, rd, sa, ft, fs, fd, fmt, tf, nd, function,
25903 trap_code, imm, instr_index, p, msb, lsb, size, rot, sel;
25904 /* Additional variables for instruction fields in DSP ASE insructions */
25905 UInt ac;
25907 DisResult dres;
25909 static IRExpr *lastn = NULL; /* last jump addr */
25910 static IRStmt *bstmt = NULL; /* branch (Exit) stmt */
25912 /* The running delta */
25913 Int delta = (Int) delta64;
25915 /* Holds eip at the start of the insn, so that we can print
25916 consistent error messages for unimplemented insns. */
25917 Int delta_start = delta;
25919 /* Are we in a delay slot ? */
25920 Bool delay_slot_branch, likely_delay_slot, delay_slot_jump;
25922 /* Set result defaults. */
25923 dres.whatNext = Dis_Continue;
25924 dres.len = 0;
25925 dres.continueAt = 0;
25926 dres.jk_StopHere = Ijk_INVALID;
25927 dres.hint = Dis_HintNone;
25929 delay_slot_branch = likely_delay_slot = delay_slot_jump = False;
25931 const UChar *code = guest_code + delta;
25932 cins = getUInt(code);
25933 DIP("\t0x%llx:\t0x%08x\t", (Addr64)guest_PC_curr_instr, cins);
25935 if (delta != 0) {
25936 if (branch_or_jump(guest_code + delta - 4)) {
25937 if (lastn == NULL && bstmt == NULL) {
25938 vassert(0);
25939 } else {
25940 dres.whatNext = Dis_StopHere;
25941 if (lastn != NULL) {
25942 delay_slot_jump = True;
25943 } else if (bstmt != NULL) {
25944 delay_slot_branch = True;
25949 if (branch_or_link_likely(guest_code + delta - 4)) {
25950 likely_delay_slot = True;
25954 /* Spot "Special" instructions (see comment at top of file). */
25956 /* Spot the 16-byte preamble:
25957 ****mips32****
25958 "srl $0, $0, 13
25959 "srl $0, $0, 29
25960 "srl $0, $0, 3
25961 "srl $0, $0, 19
25963 ****mips64****
25964 dsll $0, $0, 3
25965 dsll $0, $0, 13
25966 dsll $0, $0, 29
25967 dsll $0, $0, 19 */
25969 UInt word1 = mode64 ? 0xF8 : 0x342;
25970 UInt word2 = mode64 ? 0x378 : 0x742;
25971 UInt word3 = mode64 ? 0x778 : 0xC2;
25972 UInt word4 = mode64 ? 0x4F8 : 0x4C2;
25973 if (getUInt(code + 0) == word1 && getUInt(code + 4) == word2 &&
25974 getUInt(code + 8) == word3 && getUInt(code + 12) == word4) {
25975 /* Got a "Special" instruction preamble. Which one is it? */
25976 if (getUInt(code + 16) == 0x01ad6825 /* or $13, $13, $13 */ ) {
25977 /* $11 = client_request ( $12 ) */
25978 DIP("$11 = client_request ( $12 )");
25979 if (mode64)
25980 putPC(mkU64(guest_PC_curr_instr + 20));
25981 else
25982 putPC(mkU32(guest_PC_curr_instr + 20));
25983 dres.jk_StopHere = Ijk_ClientReq;
25984 dres.whatNext = Dis_StopHere;
25986 goto decode_success;
25987 } else if (getUInt(code + 16) == 0x01ce7025 /* or $14, $14, $14 */ ) {
25988 /* $11 = guest_NRADDR */
25989 DIP("$11 = guest_NRADDR");
25990 dres.len = 20;
25991 delta += 20;
25992 if (mode64)
25993 putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS64State,
25994 guest_NRADDR), Ity_I64));
25995 else
25996 putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State,
25997 guest_NRADDR), Ity_I32));
25998 goto decode_success;
25999 } else if (getUInt(code + 16) == 0x01ef7825 /* or $15, $15, $15 */ ) {
26000 /* branch-and-link-to-noredir $25 */
26001 DIP("branch-and-link-to-noredir $25");
26002 if (mode64)
26003 putIReg(31, mkU64(guest_PC_curr_instr + 20));
26004 else
26005 putIReg(31, mkU32(guest_PC_curr_instr + 20));
26006 putPC(getIReg(25));
26007 dres.jk_StopHere = Ijk_NoRedir;
26008 dres.whatNext = Dis_StopHere;
26009 goto decode_success;
26010 } else if (getUInt(code + 16) == 0x016b5825 /* or $11,$11,$11 */ ) {
26011 /* IR injection */
26012 DIP("IR injection");
26013 #if defined (_MIPSEL)
26014 vex_inject_ir(irsb, Iend_LE);
26015 #elif defined (_MIPSEB)
26016 vex_inject_ir(irsb, Iend_BE);
26017 #endif
26018 if (mode64) {
26019 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMSTART),
26020 mkU64(guest_PC_curr_instr)));
26021 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMLEN),
26022 mkU64(20)));
26024 putPC(mkU64(guest_PC_curr_instr + 20));
26025 } else {
26026 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMSTART),
26027 mkU32(guest_PC_curr_instr)));
26028 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMLEN),
26029 mkU32(20)));
26031 putPC(mkU32(guest_PC_curr_instr + 20));
26033 dres.whatNext = Dis_StopHere;
26034 dres.jk_StopHere = Ijk_InvalICache;
26035 dres.len = 20;
26036 delta += 20;
26037 goto decode_success;
26040 /* We don't know what it is. Set opc1/opc2 so decode_failure
26041 can print the insn following the Special-insn preamble. */
26042 delta += 16;
26043 goto decode_failure;
26044 /*NOTREACHED*/}
26047 opcode = get_opcode(cins);
26048 imm = get_imm(cins);
26049 rs = get_rs(cins);
26050 rt = get_rt(cins);
26051 rd = get_rd(cins);
26052 sa = get_sa(cins);
26053 fs = get_fs(cins);
26054 fd = get_fd(cins);
26055 ft = get_ft(cins);
26056 tf = get_tf(cins);
26057 nd = get_nd(cins);
26058 sel = get_sel(cins);
26059 fmt = get_fmt(cins);
26060 instr_index = get_instr_index(cins);
26061 trap_code = get_code(cins);
26062 function = get_function(cins);
26063 IRType ty = mode64 ? Ity_I64 : Ity_I32;
26064 IRType tyF = fp_mode64 ? Ity_F64 : Ity_F32;
26066 ac = get_acNo(cins);
26068 switch (opcode) {
26070 case 0x03: /* JAL */
26071 DIP("jal 0x%x", instr_index);
26072 if (mode64) {
26073 putIReg(31, mkU64(guest_PC_curr_instr + 8));
26074 t0 = newTemp(ty);
26075 assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
26076 (instr_index << 2)));
26077 } else {
26078 putIReg(31, mkU32(guest_PC_curr_instr + 8));
26079 t0 = newTemp(ty);
26080 assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
26081 (instr_index << 2)));
26083 lastn = mkexpr(t0);
26084 break;
26085 case 0x02: /* J */
26086 DIP("j 0x%x", instr_index);
26087 t0 = newTemp(ty);
26088 if (mode64)
26089 assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
26090 (instr_index << 2)));
26091 else
26092 assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
26093 (instr_index << 2)));
26094 lastn = mkexpr(t0);
26095 break;
26097 case 0x11: { /* COP1 */
26098 if (fmt == 0x3 && fd == 0 && function == 0) { /* MFHC1 */
26099 DIP("mfhc1 r%u, f%u", rt, fs);
26100 if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
26101 VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
26102 if (fp_mode64) {
26103 t0 = newTemp(Ity_I64);
26104 t1 = newTemp(Ity_I32);
26105 assign(t0, unop(Iop_ReinterpF64asI64, getDReg(fs)));
26106 assign(t1, unop(Iop_64HIto32, mkexpr(t0)));
26107 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
26108 } else {
26109 putIReg(rt, mkWidenFrom32(ty, unop(Iop_ReinterpF32asI32,
26110 getFReg(fs | 1)), True));
26112 } else {
26113 ILLEGAL_INSTRUCTON;
26115 break;
26116 } else if (fmt == 0x7 && fd == 0 && function == 0) { /* MTHC1 */
26117 DIP("mthc1 r%u, f%u", rt, fs);
26118 if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
26119 VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
26120 if (fp_mode64) {
26121 t0 = newTemp(Ity_I64);
26122 assign(t0, binop(Iop_32HLto64, mkNarrowTo32(ty, getIReg(rt)),
26123 unop(Iop_ReinterpF32asI32,
26124 getLoFromF64(Ity_F64, getDReg(fs)))));
26125 putDReg(fs, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
26126 } else {
26127 putFReg(fs | 1, unop(Iop_ReinterpI32asF32,
26128 mkNarrowTo32(ty, getIReg(rt))));
26130 } else {
26131 ILLEGAL_INSTRUCTON;
26133 break;
26134 } else if (fmt == 0x8) { /* BC */
26135 /* FcConditionalCode(bc1_cc) */
26136 UInt bc1_cc = get_bc1_cc(cins);
26137 t1 = newTemp(Ity_I1);
26138 t2 = newTemp(Ity_I32);
26139 t3 = newTemp(Ity_I1);
26141 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(bc1_cc)));
26142 assign(t2, IRExpr_ITE(mkexpr(t1),
26143 binop(Iop_And32,
26144 binop(Iop_Shr32, getFCSR(), mkU8(23)),
26145 mkU32(0x1)),
26146 binop(Iop_And32,
26147 binop(Iop_Shr32, getFCSR(),
26148 mkU8(24 + bc1_cc)),
26149 mkU32(0x1))));
26151 if (tf == 1 && nd == 0) {
26152 /* branch on true */
26153 DIP("bc1t %u, %u", bc1_cc, imm);
26154 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
26155 dis_branch(False, mkexpr(t3), imm, &bstmt);
26156 break;
26157 } else if (tf == 0 && nd == 0) {
26158 /* branch on false */
26159 DIP("bc1f %u, %u", bc1_cc, imm);
26160 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
26161 dis_branch(False, mkexpr(t3), imm, &bstmt);
26162 break;
26163 } else if (nd == 1 && tf == 0) {
26164 DIP("bc1fl %u, %u", bc1_cc, imm);
26165 lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2),
26166 mkU32(0x0)), imm);
26167 break;
26168 } else if (nd == 1 && tf == 1) {
26169 DIP("bc1tl %u, %u", bc1_cc, imm);
26170 lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2),
26171 mkU32(0x0)), imm);
26172 break;
26173 } else
26174 goto decode_failure;
26175 } else if (fmt >= 0x1c && has_msa) { /* BNZ.df */
26176 Int df = fmt & 3;
26177 t0 = newTemp(Ity_I32);
26178 t1 = newTemp(Ity_V128);
26179 t2 = newTemp(Ity_V128);
26180 t3 = newTemp(Ity_V128);
26181 assign(t1, getWReg(ft));
26182 assign(t2, binop(Iop_64HLtoV128, mkU64(0), mkU64(0)));
26184 switch (df) {
26185 case 0x00: { /* BNZ.B */
26186 DIP("BNZ.B w%d, %d", ft, imm);
26187 assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
26188 break;
26191 case 0x01: { /* BNZ.H */
26192 DIP("BNZ.H w%d, %d", ft, imm);
26193 assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
26194 break;
26197 case 0x02: { /* BNZ.W */
26198 DIP("BNZ.W w%d, %d", ft, imm);
26199 assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
26200 break;
26203 case 0x03: { /* BNZ.D */
26204 DIP("BNZ.D w%d, %d", ft, imm);
26205 assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
26206 break;
26210 assign(t0,
26211 binop(Iop_Or32,
26212 binop(Iop_Or32,
26213 unop(Iop_V128to32, mkexpr(t3)),
26214 unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t3)))),
26215 binop(Iop_Or32,
26216 unop(Iop_64to32,
26217 unop(Iop_V128HIto64, mkexpr(t3))),
26218 unop(Iop_64HIto32,
26219 unop(Iop_V128HIto64, mkexpr(t3))))));
26220 dis_branch(False,
26221 binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0)), imm, &bstmt);
26222 } else if (fmt == 0x0F && has_msa) { /* BNZ.V */
26223 t0 = newTemp(Ity_I32);
26224 t1 = newTemp(Ity_V128);
26225 assign(t1, getWReg(ft));
26226 assign(t0,
26227 binop(Iop_Or32,
26228 binop(Iop_Or32,
26229 unop(Iop_V128to32, mkexpr(t1)),
26230 unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t1)))),
26231 binop(Iop_Or32,
26232 unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t1))),
26233 unop(Iop_64HIto32,
26234 unop(Iop_V128HIto64, mkexpr(t1))))));
26235 dis_branch(False,
26236 binop(Iop_CmpNE32, mkexpr(t0), mkU32(0)), imm, &bstmt);
26237 } else if (fmt >= 0x18 && has_msa) { /* BZ.df */
26238 Int df = fmt & 3;
26239 t0 = newTemp(Ity_I32);
26240 t1 = newTemp(Ity_V128);
26241 t2 = newTemp(Ity_V128);
26242 t3 = newTemp(Ity_V128);
26243 assign(t1, getWReg(ft));
26244 assign(t2, binop(Iop_64HLtoV128, mkU64(0), mkU64(0)));
26246 switch (df) {
26247 case 0x00: { /* BZ.B */
26248 DIP("BZ.B w%d, %d", ft, imm);
26249 assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
26250 break;
26253 case 0x01: { /* BZ.H */
26254 DIP("BZ.H w%d, %d", ft, imm);
26255 assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
26256 break;
26259 case 0x02: { /* BZ.W */
26260 DIP("BZ.W w%d, %d", ft, imm);
26261 assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
26262 break;
26265 case 0x03: { /* BZ.D */
26266 DIP("BZ.D w%d, %d", ft, imm);
26267 assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
26268 break;
26272 assign(t0,
26273 binop(Iop_Or32,
26274 binop(Iop_Or32,
26275 unop(Iop_V128to32, mkexpr(t3)),
26276 unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t3)))),
26277 binop(Iop_Or32,
26278 unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t3))),
26279 unop(Iop_64HIto32,
26280 unop(Iop_V128HIto64, mkexpr(t3))))));
26281 dis_branch(False,
26282 binop(Iop_CmpNE32, mkexpr(t0), mkU32(0)), imm, &bstmt);
26283 } else if (fmt == 0x0B && has_msa) { /* BZ.V */
26284 t0 = newTemp(Ity_I32);
26285 t1 = newTemp(Ity_V128);
26286 assign(t1, getWReg(ft));
26287 assign(t0,
26288 binop(Iop_Or32,
26289 binop(Iop_Or32,
26290 unop(Iop_V128to32, mkexpr(t1)),
26291 unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t1)))),
26292 binop(Iop_Or32,
26293 unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t1))),
26294 unop(Iop_64HIto32,
26295 unop(Iop_V128HIto64, mkexpr(t1))))));
26296 dis_branch(False,
26297 binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0)), imm, &bstmt);
26298 } else if (fmt == 0x09) { /* BC1EQZ */
26299 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
26300 DIP("bc1eqz f%u, %u", ft, imm);
26301 t1 = newTemp(Ity_I1);
26302 if (mode64) {
26303 assign(t1, binop(Iop_CmpEQ64,
26304 binop(Iop_And64,
26305 unop(Iop_ReinterpF64asI64, getDReg(ft)),
26306 mkU64(1)),
26307 mkU64(0)));
26308 } else {
26309 assign(t1, binop(Iop_CmpEQ32,
26310 binop(Iop_And32,
26311 unop(Iop_64to32,
26312 unop(Iop_ReinterpF64asI64, getDReg(ft))),
26313 mkU32(1)),
26314 mkU32(0)));
26316 dis_branch(False, mkexpr(t1), imm, &bstmt);
26317 } else {
26318 ILLEGAL_INSTRUCTON;
26320 } else if (fmt == 0x0D) { /* BC1NEZ */
26321 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
26322 DIP("bc1nez f%u, %u", ft, imm);
26323 t1 = newTemp(Ity_I1);
26324 if (mode64) {
26325 assign(t1, binop(Iop_CmpNE64,
26326 binop(Iop_And64,
26327 unop(Iop_ReinterpF64asI64, getDReg(ft)),
26328 mkU64(1)),
26329 mkU64(0)));
26330 } else {
26331 assign(t1, binop(Iop_CmpNE32,
26332 binop(Iop_And32,
26333 unop(Iop_64to32,
26334 unop(Iop_ReinterpF64asI64, getDReg(ft))),
26335 mkU32(1)),
26336 mkU32(0)));
26338 dis_branch(False, mkexpr(t1), imm, &bstmt);
26339 } else {
26340 ILLEGAL_INSTRUCTON;
26342 } else {
26343 if (fmt == 0x15) { /* CMP.cond.d */
26344 Bool comparison = True;
26345 UInt signaling = CMPAFD;
26346 DIP("cmp.cond.d f%u, f%u, f%u, cond %u", fd, fs, ft, function);
26347 t0 = newTemp(Ity_I32);
26348 /* Conditions starting with S should signal exception on QNaN inputs. */
26349 switch (function) {
26350 case 8: /* SAF */
26351 signaling = CMPSAFD;
26352 case 0: /* AF */
26353 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
26354 calculateFCSR(fs, ft, signaling, False, 2);
26355 putDReg(fd,
26356 binop(Iop_I64StoF64,
26357 get_IR_roundingmode(), mkU64(0)));
26358 break;
26359 case 9: /* SUN */
26360 signaling = CMPSAFD;
26361 case 1: /* UN */
26362 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
26363 calculateFCSR(fs, ft, signaling, False, 2);
26364 putDReg(fd,
26365 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
26366 unop(Iop_ReinterpI64asF64,
26367 mkU64(0xFFFFFFFFFFFFFFFFULL)),
26368 binop(Iop_I64StoF64,
26369 get_IR_roundingmode(), mkU64(0))));
26370 break;
26371 case 0x19: /* SOR */
26372 signaling = CMPSAFD;
26373 case 0x11: /* OR */
26374 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
26375 calculateFCSR(fs, ft, signaling, False, 2);
26376 putDReg(fd,
26377 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
26378 binop(Iop_I64StoF64,
26379 get_IR_roundingmode(), mkU64(0)),
26380 unop(Iop_ReinterpI64asF64,
26381 mkU64(0xFFFFFFFFFFFFFFFFULL))));
26382 break;
26383 case 0xa: /* SEQ */
26384 signaling = CMPSAFD;
26385 case 2: /* EQ */
26386 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
26387 calculateFCSR(fs, ft, signaling, False, 2);
26388 putDReg(fd,
26389 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
26390 unop(Iop_ReinterpI64asF64,
26391 mkU64(0xFFFFFFFFFFFFFFFFULL)),
26392 binop(Iop_I64StoF64,
26393 get_IR_roundingmode(), mkU64(0))));
26394 break;
26395 case 0x1A: /* SNEQ */
26396 signaling = CMPSAFD;
26397 case 0x12: /* NEQ */
26398 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
26399 calculateFCSR(fs, ft, signaling, False, 2);
26400 putDReg(fd,
26401 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
26402 binop(Iop_I64StoF64,
26403 get_IR_roundingmode(), mkU64(0)),
26404 unop(Iop_ReinterpI64asF64,
26405 mkU64(0xFFFFFFFFFFFFFFFFULL))));
26406 break;
26407 case 0xB: /* SUEQ */
26408 signaling = CMPSAFD;
26409 case 0x3: /* UEQ */
26410 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
26411 calculateFCSR(fs, ft, signaling, False, 2);
26412 putDReg(fd,
26413 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
26414 unop(Iop_ReinterpI64asF64,
26415 mkU64(0xFFFFFFFFFFFFFFFFULL)),
26416 IRExpr_ITE(binop(Iop_CmpEQ32,
26417 mkexpr(t0), mkU32(0x45)),
26418 unop(Iop_ReinterpI64asF64,
26419 mkU64(0xFFFFFFFFFFFFFFFFULL)),
26420 binop(Iop_I64StoF64,
26421 get_IR_roundingmode(),
26422 mkU64(0)))));
26423 break;
26424 case 0x1B: /* SNEQ */
26425 signaling = CMPSAFD;
26426 case 0x13: /* NEQ */
26427 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
26428 calculateFCSR(fs, ft, signaling, False, 2);
26429 putDReg(fd,
26430 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)),
26431 unop(Iop_ReinterpI64asF64,
26432 mkU64(0xFFFFFFFFFFFFFFFFULL)),
26433 IRExpr_ITE(binop(Iop_CmpEQ32,
26434 mkexpr(t0),mkU32(0x00)),
26435 unop(Iop_ReinterpI64asF64,
26436 mkU64(0xFFFFFFFFFFFFFFFFULL)),
26437 binop(Iop_I64StoF64,
26438 get_IR_roundingmode(),
26439 mkU64(0)))));
26440 break;
26441 case 0xC: /* SLT */
26442 signaling = CMPSAFD;
26443 case 0x4: /* LT */
26444 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
26445 calculateFCSR(fs, ft, signaling, False, 2);
26446 putDReg(fd,
26447 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
26448 unop(Iop_ReinterpI64asF64,
26449 mkU64(0xFFFFFFFFFFFFFFFFULL)),
26450 binop(Iop_I64StoF64,
26451 get_IR_roundingmode(), mkU64(0))));
26452 break;
26453 case 0xD: /* SULT */
26454 signaling = CMPSAFD;
26455 case 0x5: /* ULT */
26456 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
26457 calculateFCSR(fs, ft, signaling, False, 2);
26458 putDReg(fd,
26459 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
26460 unop(Iop_ReinterpI64asF64,
26461 mkU64(0xFFFFFFFFFFFFFFFFULL)),
26462 IRExpr_ITE(binop(Iop_CmpEQ32,
26463 mkexpr(t0), mkU32(0x45)),
26464 unop(Iop_ReinterpI64asF64,
26465 mkU64(0xFFFFFFFFFFFFFFFFULL)),
26466 binop(Iop_I64StoF64,
26467 get_IR_roundingmode(),
26468 mkU64(0)))));
26469 break;
26470 case 0xE: /* SLE */
26471 signaling = CMPSAFD;
26472 case 0x6: /* LE */
26473 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
26474 calculateFCSR(fs, ft, signaling, False, 2);
26475 putDReg(fd,
26476 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)),
26477 unop(Iop_ReinterpI64asF64,
26478 mkU64(0xFFFFFFFFFFFFFFFFULL)),
26479 IRExpr_ITE(binop(Iop_CmpEQ32,
26480 mkexpr(t0),mkU32(0x40)),
26481 unop(Iop_ReinterpI64asF64,
26482 mkU64(0xFFFFFFFFFFFFFFFFULL)),
26483 binop(Iop_I64StoF64,
26484 get_IR_roundingmode(),
26485 mkU64(0)))));
26486 break;
26487 case 0xF: /* SULE */
26488 signaling = CMPSAFD;
26489 case 0x7: /* ULE */
26490 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
26491 calculateFCSR(fs, ft, signaling, False, 2);
26492 putDReg(fd,
26493 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)),
26494 binop(Iop_I64StoF64,
26495 get_IR_roundingmode(), mkU64(0)),
26496 unop(Iop_ReinterpI64asF64,
26497 mkU64(0xFFFFFFFFFFFFFFFFULL))));
26498 break;
26499 default:
26500 comparison = False;
26502 if (comparison) {
26503 if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
26504 ILLEGAL_INSTRUCTON;
26506 break;
26509 } else if (fmt == 0x14) {
26510 Bool comparison = True;
26511 UInt signaling = CMPAFS;
26512 DIP("cmp.cond.s f%u, f%u, f%u, cond %u", fd, fs, ft, function);
26513 t0 = newTemp(Ity_I32);
26514 /* Conditions starting with S should signal exception on QNaN inputs. */
26515 switch (function) {
26516 case 8: /* SAF */
26517 signaling = CMPSAFS;
26518 case 0: /* AF */
26519 assign(t0, binop(Iop_CmpF32,
26520 getLoFromF64(Ity_F64, getFReg(fs)),
26521 getLoFromF64(Ity_F64, getFReg(ft))));
26522 calculateFCSR(fs, ft, signaling, True, 2);
26523 putFReg(fd,
26524 mkWidenFromF32(tyF,
26525 binop(Iop_I32StoF32,
26526 get_IR_roundingmode(), mkU32(0))));
26527 break;
26528 case 9: /* SUN */
26529 signaling = CMPSAFS;
26530 case 1: /* UN */
26531 assign(t0, binop(Iop_CmpF32,
26532 getLoFromF64(Ity_F64, getFReg(fs)),
26533 getLoFromF64(Ity_F64, getFReg(ft))));
26534 calculateFCSR(fs, ft, signaling, True, 2);
26535 putFReg(fd,
26536 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
26537 mkWidenFromF32(tyF,
26538 unop(Iop_ReinterpI32asF32,
26539 mkU32(0xFFFFFFFFU))),
26540 mkWidenFromF32(tyF,
26541 binop(Iop_I32StoF32,
26542 get_IR_roundingmode(),
26543 mkU32(0)))));
26544 break;
26545 case 0x19: /* SOR */
26546 signaling = CMPSAFS;
26547 case 0x11: /* OR */
26548 assign(t0, binop(Iop_CmpF32,
26549 getLoFromF64(Ity_F64, getFReg(fs)),
26550 getLoFromF64(Ity_F64, getFReg(ft))));
26551 calculateFCSR(fs, ft, signaling, True, 2);
26552 putFReg(fd,
26553 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
26554 mkWidenFromF32(tyF,
26555 binop(Iop_I32StoF32,
26556 get_IR_roundingmode(),
26557 mkU32(0))),
26558 mkWidenFromF32(tyF,
26559 unop(Iop_ReinterpI32asF32,
26560 mkU32(0xFFFFFFFFU)))));
26561 break;
26562 case 0xa: /* SEQ */
26563 signaling = CMPSAFS;
26564 case 2: /* EQ */
26565 assign(t0, binop(Iop_CmpF32,
26566 getLoFromF64(Ity_F64, getFReg(fs)),
26567 getLoFromF64(Ity_F64, getFReg(ft))));
26568 calculateFCSR(fs, ft, signaling, True, 2);
26569 putFReg(fd,
26570 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
26571 mkWidenFromF32(tyF,
26572 unop(Iop_ReinterpI32asF32,
26573 mkU32(0xFFFFFFFFU))),
26574 mkWidenFromF32(tyF,
26575 binop(Iop_I32StoF32,
26576 get_IR_roundingmode(),
26577 mkU32(0)))));
26578 break;
26579 case 0x1A: /* SNEQ */
26580 signaling = CMPSAFS;
26581 case 0x12: /* NEQ */
26582 assign(t0, binop(Iop_CmpF32,
26583 getLoFromF64(Ity_F64, getFReg(fs)),
26584 getLoFromF64(Ity_F64, getFReg(ft))));
26585 calculateFCSR(fs, ft, signaling, True, 2);
26586 putFReg(fd,
26587 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
26588 mkWidenFromF32(tyF,
26589 binop(Iop_I32StoF32,
26590 get_IR_roundingmode(),
26591 mkU32(0))),
26592 mkWidenFromF32(tyF,
26593 unop(Iop_ReinterpI32asF32,
26594 mkU32(0xFFFFFFFFU)))));
26595 break;
26596 case 0xB: /* SUEQ */
26597 signaling = CMPSAFS;
26598 case 0x3: /* UEQ */
26599 assign(t0, binop(Iop_CmpF32,
26600 getLoFromF64(Ity_F64, getFReg(fs)),
26601 getLoFromF64(Ity_F64, getFReg(ft))));
26602 calculateFCSR(fs, ft, signaling, True, 2);
26603 putFReg(fd,
26604 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
26605 mkWidenFromF32(tyF,
26606 unop(Iop_ReinterpI32asF32,
26607 mkU32(0xFFFFFFFFU))),
26608 IRExpr_ITE(binop(Iop_CmpEQ32,
26609 mkexpr(t0), mkU32(0x45)),
26610 mkWidenFromF32(tyF,
26611 unop(Iop_ReinterpI32asF32,
26612 mkU32(0xFFFFFFFFU))),
26613 mkWidenFromF32(tyF,
26614 binop(Iop_I32StoF32,
26615 get_IR_roundingmode(),
26616 mkU32(0))))));
26617 break;
26618 case 0x1B: /* SNEQ */
26619 signaling = CMPSAFS;
26620 case 0x13: /* NEQ */
26621 assign(t0, binop(Iop_CmpF32,
26622 getLoFromF64(Ity_F64, getFReg(fs)),
26623 getLoFromF64(Ity_F64, getFReg(ft))));
26624 calculateFCSR(fs, ft, signaling, True, 2);
26625 putFReg(fd,
26626 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)),
26627 mkWidenFromF32(tyF,
26628 unop(Iop_ReinterpI32asF32,
26629 mkU32(0xFFFFFFFFU))),
26630 IRExpr_ITE(binop(Iop_CmpEQ32,
26631 mkexpr(t0),mkU32(0x00)),
26632 mkWidenFromF32(tyF,
26633 unop(Iop_ReinterpI32asF32,
26634 mkU32(0xFFFFFFFFU))),
26635 mkWidenFromF32(tyF,
26636 binop(Iop_I32StoF32,
26637 get_IR_roundingmode(),
26638 mkU32(0))))));
26639 break;
26640 case 0xC: /* SLT */
26641 signaling = CMPSAFS;
26642 case 0x4: /* LT */
26643 assign(t0, binop(Iop_CmpF32,
26644 getLoFromF64(Ity_F64, getFReg(fs)),
26645 getLoFromF64(Ity_F64, getFReg(ft))));
26646 calculateFCSR(fs, ft, signaling, True, 2);
26647 putFReg(fd,
26648 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
26649 mkWidenFromF32(tyF,
26650 unop(Iop_ReinterpI32asF32,
26651 mkU32(0xFFFFFFFFU))),
26652 mkWidenFromF32(tyF,
26653 binop(Iop_I32StoF32,
26654 get_IR_roundingmode(),
26655 mkU32(0)))));
26656 break;
26657 case 0xD: /* SULT */
26658 signaling = CMPSAFS;
26659 case 0x5: /* ULT */
26660 assign(t0, binop(Iop_CmpF32,
26661 getLoFromF64(Ity_F64, getFReg(fs)),
26662 getLoFromF64(Ity_F64, getFReg(ft))));
26663 calculateFCSR(fs, ft, signaling, True, 2);
26664 putFReg(fd,
26665 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
26666 mkWidenFromF32(tyF,
26667 unop(Iop_ReinterpI32asF32,
26668 mkU32(0xFFFFFFFFU))),
26669 IRExpr_ITE(binop(Iop_CmpEQ32,
26670 mkexpr(t0), mkU32(0x45)),
26671 mkWidenFromF32(tyF,
26672 unop(Iop_ReinterpI32asF32,
26673 mkU32(0xFFFFFFFFU))),
26674 mkWidenFromF32(tyF,
26675 binop(Iop_I32StoF32,
26676 get_IR_roundingmode(),
26677 mkU32(0))))));
26678 break;
26679 case 0xE: /* SLE */
26680 signaling = CMPSAFS;
26681 case 0x6: /* LE */
26682 assign(t0, binop(Iop_CmpF32,
26683 getLoFromF64(Ity_F64, getFReg(fs)),
26684 getLoFromF64(Ity_F64, getFReg(ft))));
26685 calculateFCSR(fs, ft, signaling, True, 2);
26686 putFReg(fd,
26687 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)),
26688 mkWidenFromF32(tyF,
26689 unop(Iop_ReinterpI32asF32,
26690 mkU32(0xFFFFFFFFU))),
26691 IRExpr_ITE(binop(Iop_CmpEQ32,
26692 mkexpr(t0),mkU32(0x40)),
26693 mkWidenFromF32(tyF,
26694 unop(Iop_ReinterpI32asF32,
26695 mkU32(0xFFFFFFFFU))),
26696 mkWidenFromF32(tyF,
26697 binop(Iop_I32StoF32,
26698 get_IR_roundingmode(),
26699 mkU32(0))))));
26700 break;
26701 case 0xF: /* SULE */
26702 signaling = CMPSAFS;
26703 case 0x7: /* ULE */
26704 assign(t0, binop(Iop_CmpF32,
26705 getLoFromF64(Ity_F64, getFReg(fs)),
26706 getLoFromF64(Ity_F64, getFReg(ft))));
26707 calculateFCSR(fs, ft, signaling, True, 2);
26708 putFReg(fd,
26709 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)),
26710 mkWidenFromF32(tyF,
26711 binop(Iop_I32StoF32,
26712 get_IR_roundingmode(),
26713 mkU32(0))),
26714 mkWidenFromF32(tyF,
26715 unop(Iop_ReinterpI32asF32,
26716 mkU32(0xFFFFFFFFU)))));
26717 break;
26718 default:
26719 comparison = False;
26721 if (comparison) {
26722 if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
26723 ILLEGAL_INSTRUCTON;
26725 break;
26729 switch (function) {
26730 case 0x4: { /* SQRT.fmt */
26731 switch (fmt) {
26732 case 0x10: { /* S */
26733 IRExpr *rm = get_IR_roundingmode();
26734 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_SqrtF32, rm,
26735 getLoFromF64(tyF, getFReg(fs)))));
26736 break;
26738 case 0x11: { /* D */
26739 IRExpr *rm = get_IR_roundingmode();
26740 putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs)));
26741 break;
26743 default:
26744 goto decode_failure;
26747 break;
26748 case 0x5: /* abs.fmt */
26749 switch (fmt) {
26750 case 0x10: /* S */
26751 DIP("abs.s f%u, f%u", fd, fs);
26752 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32,
26753 getLoFromF64(tyF, getFReg(fs)))));
26754 break;
26755 case 0x11: /* D */
26756 DIP("abs.d f%u, f%u", fd, fs);
26757 putDReg(fd, unop(Iop_AbsF64, getDReg(fs)));
26758 break;
26759 default:
26760 goto decode_failure;
26762 break; /* case 0x5 */
26764 case 0x02: /* MUL.fmt */
26765 switch (fmt) {
26766 case 0x11: { /* D */
26767 DIP("mul.d f%u, f%u, f%u", fd, fs, ft);
26768 IRExpr *rm = get_IR_roundingmode();
26769 putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs),
26770 getDReg(ft)));
26771 break;
26773 case 0x10: { /* S */
26774 DIP("mul.s f%u, f%u, f%u", fd, fs, ft);
26775 IRExpr *rm = get_IR_roundingmode();
26776 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm,
26777 getLoFromF64(tyF, getFReg(fs)),
26778 getLoFromF64(tyF, getFReg(ft)))));
26779 break;
26781 default:
26782 goto decode_failure;
26784 break; /* MUL.fmt */
26786 case 0x03: /* DIV.fmt */
26787 switch (fmt) {
26788 case 0x11: { /* D */
26789 DIP("div.d f%u, f%u, f%u", fd, fs, ft);
26790 IRExpr *rm = get_IR_roundingmode();
26791 putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs),
26792 getDReg(ft)));
26793 break;
26795 case 0x10: { /* S */
26796 DIP("div.s f%u, f%u, f%u", fd, fs, ft);
26797 calculateFCSR(fs, ft, DIVS, False, 2);
26798 IRExpr *rm = get_IR_roundingmode();
26799 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
26800 getLoFromF64(tyF, getFReg(fs)),
26801 getLoFromF64(tyF, getFReg(ft)))));
26802 break;
26804 default:
26805 goto decode_failure;
26807 break; /* DIV.fmt */
26809 case 0x01: /* SUB.fmt */
26810 switch (fmt) {
26811 case 0x11: { /* D */
26812 DIP("sub.d f%u, f%u, f%u", fd, fs, ft);
26813 calculateFCSR(fs, ft, SUBD, False, 2);
26814 IRExpr *rm = get_IR_roundingmode();
26815 putDReg(fd, triop(Iop_SubF64, rm, getDReg(fs),
26816 getDReg(ft)));
26817 break;
26819 case 0x10: { /* S */
26820 DIP("sub.s f%u, f%u, f%u", fd, fs, ft);
26821 calculateFCSR(fs, ft, SUBS, True, 2);
26822 IRExpr *rm = get_IR_roundingmode();
26823 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm,
26824 getLoFromF64(tyF, getFReg(fs)),
26825 getLoFromF64(tyF, getFReg(ft)))));
26826 break;
26828 default:
26829 goto decode_failure;
26831 break; /* SUB.fmt */
26833 case 0x06: /* MOV.fmt */
26834 switch (fmt) {
26835 case 0x11: /* D */
26836 DIP("mov.d f%u, f%u", fd, fs);
26837 if (fp_mode64) {
26838 putDReg(fd, getDReg(fs));
26839 } else {
26840 putFReg(fd, getFReg(fs));
26841 putFReg(fd + 1, getFReg(fs + 1));
26843 break;
26844 case 0x10: /* S */
26845 DIP("mov.s f%u, f%u", fd, fs);
26846 putFReg(fd, getFReg(fs));
26847 break;
26848 default:
26849 goto decode_failure;
26851 break; /* MOV.fmt */
26853 case 0x7: /* neg.fmt */
26854 switch (fmt) {
26855 case 0x10: /* S */
26856 DIP("neg.s f%u, f%u", fd, fs);
26857 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32,
26858 getLoFromF64(tyF, getFReg(fs)))));
26859 break;
26860 case 0x11: /* D */
26861 DIP("neg.d f%u, f%u", fd, fs);
26862 putDReg(fd, unop(Iop_NegF64, getDReg(fs)));
26863 break;
26864 default:
26865 goto decode_failure;
26867 break; /* case 0x7 */
26869 case 0x08: /* ROUND.L.fmt */
26870 switch (fmt) {
26871 case 0x10: /* S */
26872 DIP("round.l.s f%u, f%u", fd, fs);
26873 if (fp_mode64) {
26874 calculateFCSR(fs, 0, ROUNDLS, True, 1);
26875 t0 = newTemp(Ity_I64);
26877 assign(t0, binop(Iop_F32toI64S, mkU32(0x0),
26878 getLoFromF64(Ity_F64, getFReg(fs))));
26880 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
26881 } else {
26882 ILLEGAL_INSTRUCTON;
26884 break;
26885 case 0x11: /* D */
26886 DIP("round.l.d f%u, f%u", fd, fs);
26887 if (fp_mode64) {
26888 calculateFCSR(fs, 0, ROUNDLD, False, 1);
26889 putDReg(fd, unop(Iop_ReinterpI64asF64,
26890 binop(Iop_F64toI64S,
26891 mkU32(0x0),
26892 getDReg(fs))));
26893 } else {
26894 ILLEGAL_INSTRUCTON;
26896 break;
26897 default:
26898 goto decode_failure;
26901 break; /* ROUND.L.fmt */
26903 case 0x09: /* TRUNC.L.fmt */
26904 switch (fmt) {
26905 case 0x10: /* S */
26906 DIP("trunc.l.s f%u, f%u", fd, fs);
26907 if (fp_mode64) {
26908 calculateFCSR(fs, 0, TRUNCLS, True, 1);
26909 t0 = newTemp(Ity_I64);
26910 assign(t0, binop(Iop_F32toI64S, mkU32(0x3),
26911 getLoFromF64(Ity_F64, getFReg(fs))));
26913 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
26914 } else {
26915 ILLEGAL_INSTRUCTON;
26917 break;
26918 case 0x11: /* D */
26919 DIP("trunc.l.d f%u, f%u", fd, fs);
26920 if (fp_mode64) {
26921 calculateFCSR(fs, 0, TRUNCLD, False, 1);
26922 putDReg(fd, unop(Iop_ReinterpI64asF64,
26923 binop(Iop_F64toI64S,
26924 mkU32(0x3),
26925 getDReg(fs))));
26926 } else {
26927 ILLEGAL_INSTRUCTON;
26929 break;
26930 default:
26931 goto decode_failure;
26933 break; /* TRUNC.L.fmt */
26935 case 0x15: /* RECIP.fmt */
26936 switch (fmt) {
26937 case 0x10: { /* S */
26938 DIP("recip.s f%u, f%u", fd, fs);
26939 IRExpr *rm = get_IR_roundingmode();
26940 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32,
26941 rm, unop(Iop_ReinterpI32asF32,
26942 mkU32(ONE_SINGLE)), getLoFromF64(tyF,
26943 getFReg(fs)))));
26944 break;
26946 case 0x11: { /* D */
26947 DIP("recip.d f%u, f%u", fd, fs);
26948 IRExpr *rm = get_IR_roundingmode();
26949 /* putDReg(fd, 1.0/getDreg(fs)); */
26950 putDReg(fd, triop(Iop_DivF64, rm,
26951 unop(Iop_ReinterpI64asF64,
26952 mkU64(ONE_DOUBLE)), getDReg(fs)));
26953 break;
26955 default:
26956 goto decode_failure;
26959 break; /* case 0x15 */
26961 case 0x13: /* MOVN.fmt */
26962 switch (fmt) {
26963 case 0x10: /* S */
26964 DIP("movn.s f%u, f%u, r%u", fd, fs, rt);
26965 t1 = newTemp(Ity_I1);
26967 if (mode64)
26968 assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
26969 else
26970 assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
26972 putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
26973 break;
26974 case 0x11: /* D */
26975 DIP("movn.d f%u, f%u, r%u", fd, fs, rt);
26976 t1 = newTemp(Ity_I1);
26978 if (mode64)
26979 assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
26980 else
26981 assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
26983 putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
26984 break;
26985 default:
26986 goto decode_failure;
26988 break; /* MOVN.fmt */
26990 case 0x12: /* MOVZ.fmt */
26991 switch (fmt) {
26992 case 0x10: /* S */
26993 DIP("movz.s f%u, f%u, r%u", fd, fs, rt);
26994 t1 = newTemp(Ity_I1);
26996 if (mode64)
26997 assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
26998 else
26999 assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
27001 putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
27002 break;
27003 case 0x11: /* D */
27004 DIP("movz.d f%u, f%u, r%u", fd, fs, rt);
27005 t1 = newTemp(Ity_I1);
27007 if (mode64)
27008 assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
27009 else
27010 assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
27012 putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
27013 break;
27014 default:
27015 goto decode_failure;
27017 break; /* MOVZ.fmt */
27019 case 0x11: /* MOVT.fmt */
27020 if (tf == 1) {
27021 UInt mov_cc = get_mov_cc(cins);
27022 switch (fmt) { /* MOVCF = 010001 */
27023 case 0x11: /* D */
27024 DIP("movt.d f%u, f%u, %u", fd, fs, mov_cc);
27025 t1 = newTemp(Ity_I1);
27026 t2 = newTemp(Ity_I32);
27027 t3 = newTemp(Ity_I1);
27028 t4 = newTemp(Ity_F64);
27030 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
27031 assign(t2, IRExpr_ITE(mkexpr(t1),
27032 binop(Iop_And32,
27033 binop(Iop_Shr32, getFCSR(),
27034 mkU8(23)),
27035 mkU32(0x1)),
27036 binop(Iop_And32,
27037 binop(Iop_Shr32, getFCSR(),
27038 mkU8(24 + mov_cc)),
27039 mkU32(0x1))
27042 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
27043 assign(t4, IRExpr_ITE(mkexpr(t3),
27044 getDReg(fs), getDReg(fd)));
27045 putDReg(fd, mkexpr(t4));
27046 break;
27047 case 0x10: /* S */
27048 DIP("movt.s f%u, f%u, %u", fd, fs, mov_cc);
27049 t1 = newTemp(Ity_I1);
27050 t2 = newTemp(Ity_I32);
27051 t3 = newTemp(Ity_I1);
27052 t4 = newTemp(Ity_F64);
27053 t5 = newTemp(Ity_F64);
27054 t6 = newTemp(Ity_F64);
27055 t7 = newTemp(Ity_I64);
27057 if (fp_mode64) {
27058 assign(t5, getFReg(fs));
27059 assign(t6, getFReg(fd));
27060 } else {
27061 assign(t5, unop(Iop_F32toF64, getFReg(fs)));
27062 assign(t6, unop(Iop_F32toF64, getFReg(fd)));
27065 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
27066 assign(t2, IRExpr_ITE(mkexpr(t1),
27067 binop(Iop_And32,
27068 binop(Iop_Shr32, getFCSR(),
27069 mkU8(23)),
27070 mkU32(0x1)),
27071 binop(Iop_And32,
27072 binop(Iop_Shr32, getFCSR(),
27073 mkU8(24 + mov_cc)),
27074 mkU32(0x1))
27077 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
27078 assign(t4, IRExpr_ITE(mkexpr(t3),
27079 mkexpr(t5), mkexpr(t6)));
27081 if (fp_mode64) {
27082 IRTemp f = newTemp(Ity_F64);
27083 IRTemp fd_hi = newTemp(Ity_I32);
27084 assign(f, getFReg(fd));
27085 assign(fd_hi, unop(Iop_64HIto32,
27086 unop(Iop_ReinterpF64asI64, mkexpr(f))));
27087 assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
27088 unop(Iop_ReinterpF64asI64, mkexpr(t4))),
27089 True));
27091 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
27092 } else
27093 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
27094 mkexpr(t4)));
27095 break;
27096 default:
27097 goto decode_failure;
27099 } else if (tf == 0) /* movf.fmt */
27101 UInt mov_cc = get_mov_cc(cins);
27102 switch (fmt) /* MOVCF = 010001 */
27104 case 0x11: /* D */
27105 DIP("movf.d f%u, f%u, %u", fd, fs, mov_cc);
27106 t1 = newTemp(Ity_I1);
27107 t2 = newTemp(Ity_I32);
27108 t3 = newTemp(Ity_I1);
27109 t4 = newTemp(Ity_F64);
27111 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
27112 assign(t2, IRExpr_ITE(mkexpr(t1),
27113 binop(Iop_And32,
27114 binop(Iop_Shr32, getFCSR(),
27115 mkU8(23)),
27116 mkU32(0x1)),
27117 binop(Iop_And32,
27118 binop(Iop_Shr32, getFCSR(),
27119 mkU8(24 + mov_cc)),
27120 mkU32(0x1))
27123 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
27124 assign(t4, IRExpr_ITE(mkexpr(t3),
27125 getDReg(fs), getDReg(fd)));
27126 putDReg(fd, mkexpr(t4));
27127 break;
27128 case 0x10: /* S */
27129 DIP("movf.s f%u, f%u, %u", fd, fs, mov_cc);
27130 t1 = newTemp(Ity_I1);
27131 t2 = newTemp(Ity_I32);
27132 t3 = newTemp(Ity_I1);
27133 t4 = newTemp(Ity_F64);
27134 t5 = newTemp(Ity_F64);
27135 t6 = newTemp(Ity_F64);
27137 if (fp_mode64) {
27138 assign(t5, getFReg(fs));
27139 assign(t6, getFReg(fd));
27140 } else {
27141 assign(t5, unop(Iop_F32toF64, getFReg(fs)));
27142 assign(t6, unop(Iop_F32toF64, getFReg(fd)));
27145 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
27146 assign(t2, IRExpr_ITE(mkexpr(t1),
27147 binop(Iop_And32,
27148 binop(Iop_Shr32, getFCSR(),
27149 mkU8(23)),
27150 mkU32(0x1)),
27151 binop(Iop_And32,
27152 binop(Iop_Shr32, getFCSR(),
27153 mkU8(24 + mov_cc)),
27154 mkU32(0x1))
27157 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
27158 assign(t4, IRExpr_ITE(mkexpr(t3),
27159 mkexpr(t5), mkexpr(t6)));
27161 if (fp_mode64) {
27162 IRTemp f = newTemp(Ity_F64);
27163 IRTemp fd_hi = newTemp(Ity_I32);
27164 t7 = newTemp(Ity_I64);
27165 assign(f, getFReg(fd));
27166 assign(fd_hi, unop(Iop_64HIto32,
27167 unop(Iop_ReinterpF64asI64, mkexpr(f))));
27168 assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
27169 unop(Iop_ReinterpF64asI64, mkexpr(t4))),
27170 True));
27172 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
27173 } else
27174 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
27175 mkexpr(t4)));
27176 break;
27177 default:
27178 goto decode_failure;
27182 break; /* MOVT.fmt */
27184 case 0x0: /* add.fmt */
27185 switch (fmt) {
27186 case 0x10: { /* S */
27187 DIP("add.s f%u, f%u, f%u", fd, fs, ft);
27188 calculateFCSR(fs, ft, ADDS, True, 2);
27189 IRExpr *rm = get_IR_roundingmode();
27190 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm,
27191 getLoFromF64(tyF, getFReg(fs)),
27192 getLoFromF64(tyF, getFReg(ft)))));
27193 break;
27195 case 0x11: { /* D */
27196 DIP("add.d f%u, f%u, f%u", fd, fs, ft);
27197 calculateFCSR(fs, ft, ADDD, False, 2);
27198 IRExpr *rm = get_IR_roundingmode();
27199 putDReg(fd, triop(Iop_AddF64, rm, getDReg(fs), getDReg(ft)));
27200 break;
27203 case 0x4: /* MTC1 (Move Word to Floating Point) */
27204 DIP("mtc1 r%u, f%u", rt, fs);
27205 if (fp_mode64) {
27206 t0 = newTemp(Ity_I32);
27207 t1 = newTemp(Ity_F32);
27208 assign(t0, mkNarrowTo32(ty, getIReg(rt)));
27209 assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
27211 putFReg(fs, mkWidenFromF32(tyF, mkexpr(t1)));
27212 } else
27213 putFReg(fs, unop(Iop_ReinterpI32asF32,
27214 mkNarrowTo32(ty, getIReg(rt))));
27215 break;
27217 case 0x5: /* Doubleword Move to Floating Point DMTC1; MIPS64 */
27218 DIP("dmtc1 r%u, f%u", rt, fs);
27219 vassert(mode64);
27220 putDReg(fs, unop(Iop_ReinterpI64asF64, getIReg(rt)));
27221 break;
27223 case 0x0: /* MFC1 */
27224 DIP("mfc1 r%u, f%u", rt, fs);
27225 if (fp_mode64) {
27226 t0 = newTemp(Ity_I64);
27227 t1 = newTemp(Ity_I32);
27228 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
27229 assign(t1, unop(Iop_64to32, mkexpr(t0)));
27230 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
27231 } else
27232 putIReg(rt, mkWidenFrom32(ty,
27233 unop(Iop_ReinterpF32asI32, getFReg(fs)),
27234 True));
27235 break;
27237 case 0x1: /* Doubleword Move from Floating Point DMFC1;
27238 MIPS64 */
27239 DIP("dmfc1 r%u, f%u", rt, fs);
27240 putIReg(rt, unop(Iop_ReinterpF64asI64, getDReg(fs)));
27241 break;
27243 case 0x6: /* CTC1 */
27244 DIP("ctc1 r%u, f%u", rt, fs);
27245 t0 = newTemp(Ity_I32);
27246 t1 = newTemp(Ity_I32);
27247 t2 = newTemp(Ity_I32);
27248 t3 = newTemp(Ity_I32);
27249 t4 = newTemp(Ity_I32);
27250 t5 = newTemp(Ity_I32);
27251 t6 = newTemp(Ity_I32);
27252 assign(t0, mkNarrowTo32(ty, getIReg(rt)));
27253 if (fs == 25) { /* FCCR */
27254 assign(t1, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
27255 mkU32(0x000000FE)), mkU8(24)));
27256 assign(t2, binop(Iop_And32, mkexpr(t0),
27257 mkU32(0x01000000)));
27258 assign(t3, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
27259 mkU32(0x00000001)), mkU8(23)));
27260 assign(t4, binop(Iop_And32, mkexpr(t0),
27261 mkU32(0x007FFFFF)));
27262 putFCSR(binop(Iop_Or32, binop(Iop_Or32, mkexpr(t1),
27263 mkexpr(t2)), binop(Iop_Or32, mkexpr(t3),
27264 mkexpr(t4))));
27265 } else if (fs == 26) { /* FEXR */
27266 assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFFFC0000)));
27267 assign(t2, binop(Iop_And32, mkexpr(t0),
27268 mkU32(0x0003F000)));
27269 assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00000F80)));
27270 assign(t4, binop(Iop_And32, mkexpr(t0),
27271 mkU32(0x0000007C)));
27272 assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x00000003)));
27273 putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
27274 mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
27275 mkexpr(t3), mkexpr(t4))), mkexpr(t5)));
27276 } else if (fs == 28) {
27277 assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFE000000)));
27278 assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
27279 mkU32(0x00000002)), mkU8(22)));
27280 assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00FFF000)));
27281 assign(t4, binop(Iop_And32, mkexpr(t0),
27282 mkU32(0x00000F80)));
27283 assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x0000007C)));
27284 assign(t6, binop(Iop_And32, mkexpr(t0),
27285 mkU32(0x00000003)));
27286 putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
27287 mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
27288 mkexpr(t3), mkexpr(t4))), binop(Iop_Or32,
27289 mkexpr(t5), mkexpr(t6))));
27290 } else if (fs == 31) {
27291 putFCSR(mkexpr(t0));
27293 break;
27294 case 0x2: /* CFC1 */
27295 DIP("cfc1 r%u, f%u", rt, fs);
27296 t0 = newTemp(Ity_I32);
27297 t1 = newTemp(Ity_I32);
27298 t2 = newTemp(Ity_I32);
27299 t3 = newTemp(Ity_I32);
27300 t4 = newTemp(Ity_I32);
27301 t5 = newTemp(Ity_I32);
27302 t6 = newTemp(Ity_I32);
27303 assign(t0, getFCSR());
27304 if (fs == 0) {
27305 putIReg(rt, mkWidenFrom32(ty,
27306 IRExpr_Get(offsetof(VexGuestMIPS32State,
27307 guest_FIR),
27308 Ity_I32),
27309 False));
27310 } else if (fs == 25) {
27311 assign(t1, mkU32(0x000000FF));
27312 assign(t2, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
27313 mkU32(0xFE000000)), mkU8(25)));
27314 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
27315 mkU32(0x00800000)), mkU8(23)));
27316 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
27317 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
27318 mkexpr(t3)), False));
27319 } else if (fs == 26) {
27320 assign(t1, mkU32(0xFFFFF07C));
27321 assign(t2, binop(Iop_And32, mkexpr(t0),
27322 mkU32(0x0003F000)));
27323 assign(t3, binop(Iop_And32, mkexpr(t0),
27324 mkU32(0x0000007C)));
27325 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
27326 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
27327 mkexpr(t3)), False));
27328 } else if (fs == 28) {
27329 assign(t1, mkU32(0x00000F87));
27330 assign(t2, binop(Iop_And32, mkexpr(t0),
27331 mkU32(0x00000F83)));
27332 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
27333 mkU32(0x01000000)), mkU8(22)));
27334 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
27335 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
27336 mkexpr(t3)), False));
27337 } else if (fs == 31) {
27338 putIReg(rt, mkWidenFrom32(ty, getFCSR(), False));
27340 break;
27341 default:
27342 goto decode_failure;
27344 break;
27346 case 0x21: /* CVT.D */
27347 switch (fmt) {
27348 case 0x10: /* S */
27349 DIP("cvt.d.s f%u, f%u", fd, fs);
27350 calculateFCSR(fs, 0, CVTDS, True, 1);
27351 if (fp_mode64) {
27352 t0 = newTemp(Ity_I64);
27353 t1 = newTemp(Ity_I32);
27354 t3 = newTemp(Ity_F32);
27355 t4 = newTemp(Ity_F32);
27356 /* get lo half of FPR */
27357 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
27359 assign(t1, unop(Iop_64to32, mkexpr(t0)));
27361 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1)));
27363 putFReg(fd, unop(Iop_F32toF64, mkexpr(t3)));
27364 } else
27365 putDReg(fd, unop(Iop_F32toF64, getFReg(fs)));
27366 break;
27368 case 0x14:
27369 DIP("cvt.d.w %u, %u", fd, fs);
27370 calculateFCSR(fs, 0, CVTDW, True, 1);
27371 if (fp_mode64) {
27372 t0 = newTemp(Ity_I64);
27373 t1 = newTemp(Ity_I32);
27374 t3 = newTemp(Ity_F32);
27375 t4 = newTemp(Ity_F32);
27376 /* get lo half of FPR */
27377 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
27379 assign(t1, unop(Iop_64to32, mkexpr(t0)));
27380 putDReg(fd,unop(Iop_I32StoF64, mkexpr(t1)));
27381 break;
27382 } else {
27383 t0 = newTemp(Ity_I32);
27384 assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
27385 putDReg(fd, unop(Iop_I32StoF64, mkexpr(t0)));
27386 break;
27389 case 0x15: { /* L */
27390 if (fp_mode64) {
27391 DIP("cvt.d.l %u, %u", fd, fs);
27392 calculateFCSR(fs, 0, CVTDL, False, 1);
27393 t0 = newTemp(Ity_I64);
27394 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
27396 putFReg(fd, binop(Iop_I64StoF64,
27397 get_IR_roundingmode(), mkexpr(t0)));
27398 break;
27399 } else
27400 goto decode_failure;
27402 default:
27403 goto decode_failure;
27405 break; /* CVT.D */
27407 case 0x20: /* cvt.s */
27408 switch (fmt) {
27409 case 0x14: /* W */
27410 DIP("cvt.s.w %u, %u", fd, fs);
27411 calculateFCSR(fs, 0, CVTSW, True, 1);
27412 if (fp_mode64) {
27413 t0 = newTemp(Ity_I64);
27414 t1 = newTemp(Ity_I32);
27415 t3 = newTemp(Ity_F32);
27416 t4 = newTemp(Ity_F32);
27417 /* get lo half of FPR */
27418 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
27420 assign(t1, unop(Iop_64to32, mkexpr(t0)));
27421 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I32StoF32,
27422 get_IR_roundingmode(), mkexpr(t1))));
27423 } else {
27424 t0 = newTemp(Ity_I32);
27425 assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
27426 putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(),
27427 mkexpr(t0)));
27429 break;
27431 case 0x11: /* D */
27432 DIP("cvt.s.d %u, %u", fd, fs);
27433 calculateFCSR(fs, 0, CVTSD, False, 1);
27434 t0 = newTemp(Ity_F32);
27435 assign(t0, binop(Iop_F64toF32, get_IR_roundingmode(),
27436 getDReg(fs)));
27437 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t0)));
27438 break;
27440 case 0x15: /* L */
27441 DIP("cvt.s.l %u, %u", fd, fs);
27442 if (fp_mode64) {
27443 calculateFCSR(fs, 0, CVTSL, False, 1);
27444 t0 = newTemp(Ity_I64);
27445 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
27447 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I64StoF32,
27448 get_IR_roundingmode(), mkexpr(t0))));
27449 } else {
27450 ILLEGAL_INSTRUCTON;
27452 break;
27454 default:
27455 goto decode_failure;
27457 break; /* cvt.s */
27459 case 0x24: /* cvt.w */
27460 switch (fmt) {
27461 case 0x10: /* S */
27462 DIP("cvt.w.s %u, %u", fd, fs);
27463 calculateFCSR(fs, 0, CVTWS, True, 1);
27464 putFReg(fd,
27465 mkWidenFromF32(tyF,
27466 unop(Iop_ReinterpI32asF32,
27467 binop(Iop_F32toI32S,
27468 get_IR_roundingmode(),
27469 getLoFromF64(tyF,
27470 getFReg(fs))))));
27471 break;
27473 case 0x11:
27474 DIP("cvt.w.d %u, %u", fd, fs);
27475 calculateFCSR(fs, 0, CVTWD, False, 1);
27476 t0 = newTemp(Ity_I32);
27477 t1 = newTemp(Ity_F32);
27478 assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(),
27479 getDReg(fs)));
27480 assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
27481 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
27482 break;
27484 default:
27485 goto decode_failure;
27488 break;
27490 case 0x25: /* cvt.l */
27491 switch (fmt) {
27492 case 0x10: /* S */
27493 DIP("cvt.l.s %u, %u", fd, fs);
27494 if (fp_mode64) {
27495 calculateFCSR(fs, 0, CVTLS, True, 1);
27496 t0 = newTemp(Ity_I64);
27498 assign(t0, binop(Iop_F32toI64S, get_IR_roundingmode(),
27499 getLoFromF64(tyF, getFReg(fs))));
27501 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
27502 } else {
27503 ILLEGAL_INSTRUCTON;
27505 break;
27507 case 0x11: { /* D */
27508 DIP("cvt.l.d %u, %u", fd, fs);
27509 if (fp_mode64) {
27510 calculateFCSR(fs, 0, CVTLD, False, 1);
27511 putDReg(fd, unop(Iop_ReinterpI64asF64,
27512 binop(Iop_F64toI64S,
27513 get_IR_roundingmode(),
27514 getDReg(fs))));
27515 } else {
27516 ILLEGAL_INSTRUCTON;
27518 break;
27521 default:
27522 goto decode_failure;
27524 break;
27526 case 0x0B: /* FLOOR.L.fmt */
27527 switch (fmt) {
27528 case 0x10: /* S */
27529 DIP("floor.l.s %u, %u", fd, fs);
27530 if (fp_mode64) {
27531 calculateFCSR(fs, 0, FLOORLS, True, 1);
27532 t0 = newTemp(Ity_I64);
27534 assign(t0, binop(Iop_F32toI64S, mkU32(0x1),
27535 getLoFromF64(tyF, getFReg(fs))));
27537 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
27538 } else {
27539 ILLEGAL_INSTRUCTON;
27541 break;
27543 case 0x11: /* D */
27544 DIP("floor.l.d %u, %u", fd, fs);
27545 if (fp_mode64) {
27546 calculateFCSR(fs, 0, FLOORLD, False, 1);
27547 putDReg(fd, unop(Iop_ReinterpI64asF64,
27548 binop(Iop_F64toI64S,
27549 mkU32(0x01),
27550 getDReg(fs))));
27551 } else {
27552 ILLEGAL_INSTRUCTON;
27554 break;
27555 default:
27556 goto decode_failure;
27558 break;
27560 case 0x0C: /* ROUND.W.fmt */
27561 switch (fmt) {
27562 case 0x10: /* S */
27563 DIP("round.w.s f%u, f%u", fd, fs);
27564 calculateFCSR(fs, 0, ROUNDWS, True, 1);
27565 putFReg(fd,
27566 mkWidenFromF32(tyF,
27567 unop(Iop_ReinterpI32asF32,
27568 binop(Iop_F32toI32S,
27569 mkU32(0x0),
27570 getLoFromF64(tyF,
27571 getFReg(fs))))));
27572 break;
27574 case 0x11: /* D */
27575 DIP("round.w.d f%u, f%u", fd, fs);
27576 calculateFCSR(fs, 0, ROUNDWD, False, 1);
27577 if (fp_mode64) {
27578 t0 = newTemp(Ity_I32);
27579 assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
27580 getDReg(fs)));
27581 putFReg(fd, mkWidenFromF32(tyF,
27582 unop(Iop_ReinterpI32asF32, mkexpr(t0))));
27583 } else {
27584 t0 = newTemp(Ity_I32);
27586 assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
27587 getDReg(fs)));
27589 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
27591 break;
27592 default:
27593 goto decode_failure;
27596 break; /* ROUND.W.fmt */
27598 case 0x0F: /* FLOOR.W.fmt */
27599 switch (fmt) {
27600 case 0x10: /* S */
27601 DIP("floor.w.s f%u, f%u", fd, fs);
27602 calculateFCSR(fs, 0, FLOORWS, True, 1);
27603 putFReg(fd,
27604 mkWidenFromF32(tyF,
27605 unop(Iop_ReinterpI32asF32,
27606 binop(Iop_F32toI32S,
27607 mkU32(0x1),
27608 getLoFromF64(tyF,
27609 getFReg(fs))))));
27610 break;
27612 case 0x11: /* D */
27613 DIP("floor.w.d f%u, f%u", fd, fs);
27614 calculateFCSR(fs, 0, FLOORWD, False, 1);
27615 if (fp_mode64) {
27616 t0 = newTemp(Ity_I32);
27617 assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
27618 getDReg(fs)));
27619 putFReg(fd, mkWidenFromF32(tyF,
27620 unop(Iop_ReinterpI32asF32, mkexpr(t0))));
27621 break;
27622 } else {
27623 t0 = newTemp(Ity_I32);
27625 assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
27626 getDReg(fs)));
27628 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
27629 break;
27631 default:
27632 goto decode_failure;
27635 break; /* FLOOR.W.fmt */
27637 case 0x0D: /* TRUNC.W */
27638 switch (fmt) {
27639 case 0x10: /* S */
27640 DIP("trunc.w.s %u, %u", fd, fs);
27641 calculateFCSR(fs, 0, TRUNCWS, True, 1);
27642 putFReg(fd,
27643 mkWidenFromF32(tyF,
27644 unop(Iop_ReinterpI32asF32,
27645 binop(Iop_F32toI32S,
27646 mkU32(0x3),
27647 getLoFromF64(tyF,
27648 getFReg(fs))))));
27649 break;
27650 case 0x11: /* D */
27651 DIP("trunc.w.d %u, %u", fd, fs);
27652 calculateFCSR(fs, 0, TRUNCWD, False, 1);
27653 if (fp_mode64) {
27654 t0 = newTemp(Ity_I32);
27656 assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
27657 getFReg(fs)));
27659 putFReg(fd, mkWidenFromF32(tyF,
27660 unop(Iop_ReinterpI32asF32, mkexpr(t0))));
27661 } else {
27662 t0 = newTemp(Ity_I32);
27664 assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
27665 getDReg(fs)));
27667 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
27669 break;
27670 default:
27671 goto decode_failure;
27674 break;
27676 case 0x0E: /* CEIL.W.fmt */
27677 switch (fmt) {
27678 case 0x10: /* S */
27679 DIP("ceil.w.s %u, %u", fd, fs);
27680 calculateFCSR(fs, 0, CEILWS, True, 1);
27681 putFReg(fd,
27682 mkWidenFromF32(tyF,
27683 unop(Iop_ReinterpI32asF32,
27684 binop(Iop_F32toI32S,
27685 mkU32(0x2),
27686 getLoFromF64(tyF,
27687 getFReg(fs))))));
27688 break;
27690 case 0x11: /* D */
27691 DIP("ceil.w.d %u, %u", fd, fs);
27692 calculateFCSR(fs, 0, CEILWD, False, 1);
27693 if (!fp_mode64) {
27694 t0 = newTemp(Ity_I32);
27695 assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
27696 getDReg(fs)));
27697 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
27698 } else {
27699 t0 = newTemp(Ity_I32);
27700 assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
27701 getDReg(fs)));
27702 putFReg(fd, mkWidenFromF32(tyF,
27703 unop(Iop_ReinterpI32asF32, mkexpr(t0))));
27705 break;
27707 default:
27708 goto decode_failure;
27711 break;
27713 case 0x0A: /* CEIL.L.fmt */
27714 switch (fmt) {
27715 case 0x10: /* S */
27716 DIP("ceil.l.s %u, %u", fd, fs);
27717 if (fp_mode64) {
27718 calculateFCSR(fs, 0, CEILLS, True, 1);
27719 t0 = newTemp(Ity_I64);
27721 assign(t0, binop(Iop_F32toI64S, mkU32(0x2),
27722 getLoFromF64(tyF, getFReg(fs))));
27724 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
27725 } else {
27726 ILLEGAL_INSTRUCTON;
27728 break;
27730 case 0x11: /* D */
27731 DIP("ceil.l.d %u, %u", fd, fs);
27732 if (fp_mode64) {
27733 calculateFCSR(fs, 0, CEILLD, False, 1);
27734 putDReg(fd, unop(Iop_ReinterpI64asF64,
27735 binop(Iop_F64toI64S,
27736 mkU32(0x2),
27737 getDReg(fs))));
27738 } else {
27739 ILLEGAL_INSTRUCTON;
27741 break;
27743 default:
27744 goto decode_failure;
27747 break;
27749 case 0x16: /* RSQRT.fmt */
27750 switch (fmt) {
27751 case 0x10: { /* S */
27752 DIP("rsqrt.s %u, %u", fd, fs);
27753 IRExpr *rm = get_IR_roundingmode();
27754 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
27755 unop(Iop_ReinterpI32asF32, mkU32(ONE_SINGLE)),
27756 binop(Iop_SqrtF32, rm, getLoFromF64(tyF,
27757 getFReg(fs))))));
27758 break;
27760 case 0x11: { /* D */
27761 DIP("rsqrt.d %u, %u", fd, fs);
27762 IRExpr *rm = get_IR_roundingmode();
27763 putDReg(fd, triop(Iop_DivF64, rm,
27764 unop(Iop_ReinterpI64asF64,
27765 mkU64(ONE_DOUBLE)),
27766 binop(Iop_SqrtF64, rm, getDReg(fs))));
27767 break;
27769 default:
27770 goto decode_failure;
27773 break;
27775 case 0x18: /* MADDF.fmt */
27776 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
27777 switch (fmt) {
27778 case 0x11: { /* D */
27779 DIP("maddf.d f%u, f%u, f%u", fd, fs, ft);
27780 IRExpr *rm = get_IR_roundingmode();
27781 putDReg(fd, qop(Iop_MAddF64, rm, getDReg(fs), getDReg(ft),
27782 getDReg(fd)));
27783 break;
27786 case 0x10: { /* S */
27787 DIP("maddf.s f%u, f%u, f%u", fd, fs, ft);
27788 IRExpr *rm = get_IR_roundingmode();
27789 t1 = newTemp(Ity_F32);
27790 assign(t1, qop(Iop_MAddF32, rm,
27791 getLoFromF64(tyF, getFReg(fs)),
27792 getLoFromF64(tyF, getFReg(ft)),
27793 getLoFromF64(tyF, getFReg(fd))));
27794 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
27795 break;
27798 default:
27799 goto decode_failure;
27801 } else {
27802 ILLEGAL_INSTRUCTON;
27805 break;
27807 case 0x19: /* MSUBF.fmt */
27808 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
27809 switch (fmt) {
27810 case 0x11: { /* D */
27811 DIP("msubf.d f%u, f%u, f%u", fd, fs, ft);
27812 IRExpr *rm = get_IR_roundingmode();
27813 putDReg(fd, qop(Iop_MSubF64, rm, getDReg(fs),
27814 getDReg(ft), getDReg(fd)));
27815 break;
27818 case 0x10: { /* S */
27819 DIP("msubf.s f%u, f%u, f%u", fd, fs, ft);
27820 IRExpr *rm = get_IR_roundingmode();
27821 t1 = newTemp(Ity_F32);
27822 assign(t1, qop(Iop_MSubF32, rm,
27823 getLoFromF64(tyF, getFReg(fs)),
27824 getLoFromF64(tyF, getFReg(ft)),
27825 getLoFromF64(tyF, getFReg(fd))));
27826 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
27827 break;
27830 default:
27831 goto decode_failure;
27833 } else {
27834 ILLEGAL_INSTRUCTON;
27837 break;
27839 case 0x1E: /* MAX.fmt */
27840 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
27841 switch (fmt) {
27842 case 0x11: { /* D */
27843 DIP("max.d f%u, f%u, f%u", fd, fs, ft);
27844 calculateFCSR(fs, ft, MAXD, False, 2);
27845 putDReg(fd, binop(Iop_MaxNumF64, getDReg(fs), getDReg(ft)));
27846 break;
27849 case 0x10: { /* S */
27850 DIP("max.s f%u, f%u, f%u", fd, fs, ft);
27851 calculateFCSR(fs, ft, MAXS, True, 2);
27852 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_MaxNumF32,
27853 getLoFromF64(Ity_F64,
27854 getFReg(fs)),
27855 getLoFromF64(Ity_F64,
27856 getFReg(ft)))));
27857 break;
27860 default:
27861 goto decode_failure;
27863 } else {
27864 ILLEGAL_INSTRUCTON;
27867 break;
27869 case 0x1C: /* MIN.fmt */
27870 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
27871 switch (fmt) {
27872 case 0x11: { /* D */
27873 DIP("min.d f%u, f%u, f%u", fd, fs, ft);
27874 calculateFCSR(fs, ft, MIND, False, 2);
27875 putDReg(fd, binop(Iop_MinNumF64, getDReg(fs), getDReg(ft)));
27876 break;
27879 case 0x10: { /* S */
27880 DIP("min.s f%u, f%u, f%u", fd, fs, ft);
27881 calculateFCSR(fs, ft, MINS, True, 2);
27882 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_MinNumF32,
27883 getLoFromF64(Ity_F64,
27884 getFReg(fs)),
27885 getLoFromF64(Ity_F64,
27886 getFReg(ft)))));
27887 break;
27889 default:
27890 goto decode_failure;
27892 } else {
27893 ILLEGAL_INSTRUCTON;
27896 break;
27898 case 0x1F: /* MAXA.fmt */
27899 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
27900 switch (fmt) {
27901 case 0x11: { /* D */
27902 DIP("maxa.d f%u, f%u, f%u", fd, fs, ft);
27903 calculateFCSR(fs, ft, MAXAD, False, 2);
27904 t1 = newTemp(Ity_F64);
27905 t2 = newTemp(Ity_F64);
27906 t3 = newTemp(Ity_F64);
27907 t4 = newTemp(Ity_I1);
27908 assign(t1, unop(Iop_AbsF64, getFReg(fs)));
27909 assign(t2, unop(Iop_AbsF64, getFReg(ft)));
27910 assign(t3, binop(Iop_MaxNumF64, mkexpr(t1), mkexpr(t2)));
27911 assign(t4, binop(Iop_CmpEQ32,
27912 binop(Iop_CmpF64, mkexpr(t3), mkexpr(t1)),
27913 mkU32(0x40)));
27914 putFReg(fd, IRExpr_ITE(mkexpr(t4),
27915 getFReg(fs), getFReg(ft)));
27916 break;
27919 case 0x10: { /* S */
27920 DIP("maxa.s f%u, f%u, f%u", fd, fs, ft);
27921 calculateFCSR(fs, ft, MAXAS, True, 2);
27922 t1 = newTemp(Ity_F32);
27923 t2 = newTemp(Ity_F32);
27924 t3 = newTemp(Ity_F32);
27925 t4 = newTemp(Ity_I1);
27926 assign(t1, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
27927 getFReg(fs))));
27928 assign(t2, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
27929 getFReg(ft))));
27930 assign(t3, binop(Iop_MaxNumF32, mkexpr(t1), mkexpr(t2)));
27931 assign(t4, binop(Iop_CmpEQ32,
27932 binop(Iop_CmpF32, mkexpr(t3), mkexpr(t1)),
27933 mkU32(0x40)));
27934 putFReg(fd, IRExpr_ITE(mkexpr(t4),
27935 getFReg(fs), getFReg(ft)));
27936 break;
27939 default:
27940 goto decode_failure;
27942 /* missing in documentation */
27943 } else {
27944 ILLEGAL_INSTRUCTON;
27946 break;
27948 case 0x1D: /* MINA.fmt */
27949 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
27950 switch (fmt) {
27951 case 0x11: { /* D */
27952 DIP("mina.d f%u, f%u, f%u", fd, fs, ft);
27953 calculateFCSR(fs, ft, MINAD, False, 2);
27954 t1 = newTemp(Ity_F64);
27955 t2 = newTemp(Ity_F64);
27956 t3 = newTemp(Ity_F64);
27957 t4 = newTemp(Ity_I1);
27958 assign(t1, unop(Iop_AbsF64, getFReg(fs)));
27959 assign(t2, unop(Iop_AbsF64, getFReg(ft)));
27960 assign(t3, binop(Iop_MinNumF64, mkexpr(t1), mkexpr(t2)));
27961 assign(t4, binop(Iop_CmpEQ32,
27962 binop(Iop_CmpF64, mkexpr(t3), mkexpr(t1)),
27963 mkU32(0x40)));
27964 putFReg(fd, IRExpr_ITE(mkexpr(t4),
27965 getFReg(fs), getFReg(ft)));
27966 break;
27969 case 0x10: { /* S */
27970 DIP("mina.s f%u, f%u, f%u", fd, fs, ft);
27971 calculateFCSR(fs, ft, MINAS, True, 2);
27972 t1 = newTemp(Ity_F32);
27973 t2 = newTemp(Ity_F32);
27974 t3 = newTemp(Ity_F32);
27975 t4 = newTemp(Ity_I1);
27976 assign(t1, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
27977 getFReg(fs))));
27978 assign(t2, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
27979 getFReg(ft))));
27980 assign(t3, binop(Iop_MinNumF32, mkexpr(t1), mkexpr(t2)));
27981 assign(t4, binop(Iop_CmpEQ32,
27982 binop(Iop_CmpF32, mkexpr(t3), mkexpr(t1)),
27983 mkU32(0x40)));
27984 putFReg(fd, IRExpr_ITE(mkexpr(t4),
27985 getFReg(fs), getFReg(ft)));
27986 break;
27989 default:
27990 goto decode_failure;
27992 } else {
27993 ILLEGAL_INSTRUCTON;
27995 break;
27997 case 0x1A: /* RINT.fmt */
27998 if (ft == 0) {
27999 switch (fmt) {
28000 case 0x11: { /* D */
28001 DIP("rint.d f%u, f%u", fd, fs);
28002 calculateFCSR(fs, 0, RINTS, True, 1);
28003 IRExpr *rm = get_IR_roundingmode();
28004 putDReg(fd, binop(Iop_RoundF64toInt, rm, getDReg(fs)));
28005 break;
28008 case 0x10: { /* S */
28009 DIP("rint.s f%u, f%u", fd, fs);
28010 calculateFCSR(fs, 0, RINTD, True, 1);
28011 IRExpr *rm = get_IR_roundingmode();
28012 putFReg(fd,
28013 mkWidenFromF32(tyF,
28014 binop(Iop_RoundF32toInt, rm,
28015 getLoFromF64(tyF,
28016 getFReg(fs)))));
28017 break;
28020 default:
28021 goto decode_failure;
28025 break;
28027 case 0x10: /* SEL.fmt */
28028 switch (fmt) {
28029 case 0x11: { /* D */
28030 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
28031 DIP("sel.d f%u, f%u, f%u", fd, fs, ft);
28032 t1 = newTemp(Ity_I1);
28033 if (mode64) {
28034 assign(t1,binop(Iop_CmpNE64,
28035 binop(Iop_And64,
28036 unop(Iop_ReinterpF64asI64,
28037 getDReg(fd)),
28038 mkU64(1)),
28039 mkU64(0)));
28040 } else {
28041 assign(t1,binop(Iop_CmpNE32,
28042 binop(Iop_And32,
28043 unop(Iop_64to32,
28044 unop(Iop_ReinterpF64asI64,
28045 getDReg(fd))),
28046 mkU32(1)),
28047 mkU32(0)));
28049 putDReg(fd, IRExpr_ITE(mkexpr(t1),
28050 getDReg(ft), getDReg(fs)));
28051 break;
28052 } else {
28053 ILLEGAL_INSTRUCTON;
28058 case 0x10: { /* S */
28059 DIP("sel.s f%u, f%u, f%u", fd, fs, ft);
28060 t1 = newTemp(Ity_I1);
28061 assign(t1,binop(Iop_CmpNE32,
28062 binop(Iop_And32,
28063 unop(Iop_ReinterpF32asI32,
28064 getLoFromF64(tyF, getFReg(fd))),
28065 mkU32(1)),
28066 mkU32(0)));
28067 putFReg(fd, IRExpr_ITE( mkexpr(t1),
28068 getFReg(ft), getFReg(fs)));
28069 break;
28071 default:
28072 goto decode_failure;
28074 break;
28076 case 0x14: /* SELEQZ.fmt */
28077 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
28078 switch (fmt) { /* SELEQZ.df */
28079 case 0x11: { /* D */
28080 DIP("seleqz.d f%u, f%u, f%u", fd, fs, ft);
28081 t1 = newTemp(Ity_I1);
28082 if (mode64) {
28083 assign(t1, binop(Iop_CmpNE64,
28084 binop(Iop_And64,
28085 unop(Iop_ReinterpF64asI64,
28086 getDReg(ft)),
28087 mkU64(1)),
28088 mkU64(0)));
28089 } else {
28090 assign(t1, binop(Iop_CmpNE32,
28091 binop(Iop_And32,
28092 unop(Iop_64to32,
28093 unop(Iop_ReinterpF64asI64,
28094 getDReg(ft))),
28095 mkU32(1)),
28096 mkU32(0)));
28098 putDReg(fd, IRExpr_ITE( mkexpr(t1),
28099 binop(Iop_I64StoF64,
28100 get_IR_roundingmode(),mkU64(0)),
28101 getDReg(fs)));
28102 break;
28105 case 0x10: { /* S */
28106 DIP("seleqz.s f%u, f%u, f%u", fd, fs, ft);
28107 t1 = newTemp(Ity_I1);
28108 assign(t1, binop(Iop_CmpNE32,
28109 binop(Iop_And32,
28110 unop(Iop_ReinterpF32asI32,
28111 getLoFromF64(tyF, getFReg(ft))),
28112 mkU32(1)),
28113 mkU32(0)));
28114 putFReg(fd, IRExpr_ITE(mkexpr(t1),
28115 mkWidenFromF32(tyF,
28116 binop(Iop_I32StoF32,
28117 get_IR_roundingmode(),
28118 mkU32(0))),
28119 getFReg(fs)));
28120 break;
28123 default:
28124 goto decode_failure;
28126 } else {
28127 ILLEGAL_INSTRUCTON;
28129 break;
28131 case 0x17: /* SELNEZ.fmt */
28132 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
28133 switch (fmt) {
28134 case 0x11: { /* D */
28135 DIP("selnez.d f%u, f%u, f%u", fd, fs, ft);
28136 t1 = newTemp(Ity_I1);
28137 if (mode64) {
28138 assign(t1, binop(Iop_CmpNE64,
28139 binop(Iop_And64,
28140 unop(Iop_ReinterpF64asI64,
28141 getDReg(ft)),
28142 mkU64(1)),
28143 mkU64(0)));
28144 } else {
28145 assign(t1, binop(Iop_CmpNE32,
28146 binop(Iop_And32,
28147 unop(Iop_64to32,
28148 unop(Iop_ReinterpF64asI64,
28149 getDReg(ft))),
28150 mkU32(1)),
28151 mkU32(0)));
28153 putDReg(fd, IRExpr_ITE( mkexpr(t1),
28154 getDReg(fs),
28155 binop(Iop_I64StoF64,
28156 get_IR_roundingmode(),
28157 mkU64(0))));
28158 break;
28161 case 0x10: { /* S */
28162 DIP("selnez.s f%u, f%u, f%u", fd, fs, ft);
28163 t1 = newTemp(Ity_I1);
28164 assign(t1,binop(Iop_CmpNE32,
28165 binop(Iop_And32,
28166 unop(Iop_ReinterpF32asI32,
28167 getLoFromF64(tyF, getFReg(ft))),
28168 mkU32(1)),
28169 mkU32(0)));
28170 putFReg(fd, IRExpr_ITE(mkexpr(t1),
28171 getFReg(fs),
28172 mkWidenFromF32(tyF,
28173 binop(Iop_I32StoF32,
28174 get_IR_roundingmode(),
28175 mkU32(0)))));
28176 break;
28179 default:
28180 goto decode_failure;
28182 } else {
28183 ILLEGAL_INSTRUCTON;
28185 break;
28187 case 0x1B: /* CLASS.fmt */
28188 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
28189 t0 = newTemp(Ity_I1); // exp zero
28190 t1 = newTemp(Ity_I1); // exp max
28191 t2 = newTemp(Ity_I1); // sign
28192 t3 = newTemp(Ity_I1); // first
28193 t4 = newTemp(Ity_I1); // val not zero
28194 t5 = newTemp(Ity_I32);
28195 switch (fmt) {
28196 case 0x11: { /* D */
28197 DIP("class.d f%u, f%u", fd, fs);
28198 assign(t0, binop(Iop_CmpEQ32,
28199 binop(Iop_And32,
28200 unop(Iop_64HIto32,
28201 unop(Iop_ReinterpF64asI64,
28202 getDReg(fs))),
28203 mkU32(0x7ff00000)),
28204 mkU32(0)));
28205 assign(t1, binop(Iop_CmpEQ32,
28206 binop(Iop_And32,
28207 unop(Iop_64HIto32,
28208 unop(Iop_ReinterpF64asI64,
28209 getDReg(fs))),
28210 mkU32(0x7ff00000)),
28211 mkU32(0x7ff00000)));
28212 assign(t2, binop(Iop_CmpEQ32,
28213 binop(Iop_And32,
28214 unop(Iop_64HIto32,
28215 unop(Iop_ReinterpF64asI64,
28216 getDReg(fs))),
28217 mkU32(0x80000000)),
28218 mkU32(0x80000000)));
28219 assign(t3, binop(Iop_CmpEQ32,
28220 binop(Iop_And32,
28221 unop(Iop_64HIto32,
28222 unop(Iop_ReinterpF64asI64,
28223 getDReg(fs))),
28224 mkU32(0x00080000)),
28225 mkU32(0x00080000)));
28226 if (mode64) assign(t4, binop(Iop_CmpNE64,
28227 binop(Iop_And64,
28228 unop(Iop_ReinterpF64asI64,
28229 getDReg(fs)),
28230 mkU64(0x000fffffffffffffULL)),
28231 mkU64(0)));
28232 else assign(t4, binop(Iop_CmpNE32,
28233 binop(Iop_Or32,
28234 binop(Iop_And32,
28235 unop(Iop_64HIto32,
28236 unop(Iop_ReinterpF64asI64,
28237 getDReg(fs))),
28238 mkU32(0x000fffff)),
28239 unop(Iop_64to32,
28240 unop(Iop_ReinterpF64asI64,
28241 getDReg(fs)))),
28242 mkU32(0)));
28243 assign(t5, binop(Iop_Shl32,
28244 IRExpr_ITE(mkexpr(t1),
28245 IRExpr_ITE(mkexpr(t4),
28246 mkU32(0), mkU32(1)),
28247 IRExpr_ITE(mkexpr(t0),
28248 IRExpr_ITE(mkexpr(t4),
28249 mkU32(0x4),
28250 mkU32(0x8)),
28251 mkU32(2))),
28252 IRExpr_ITE(mkexpr(t2), mkU8(2), mkU8(6))));
28253 putDReg(fd, unop(Iop_ReinterpI64asF64,
28254 unop(Iop_32Uto64,
28255 IRExpr_ITE(binop(Iop_CmpNE32,
28256 mkexpr(t5), mkU32(0)),
28257 mkexpr(t5),
28258 IRExpr_ITE(mkexpr(t3),
28259 mkU32(2),
28260 mkU32(1))))));
28261 break;
28263 case 0x10: { /* S */
28264 DIP("class.s f%u, f%u", fd, fs);
28265 assign(t0, binop(Iop_CmpEQ32,
28266 binop(Iop_And32,
28267 unop(Iop_ReinterpF32asI32,
28268 getLoFromF64(tyF, getFReg(fs))),
28269 mkU32(0x7f800000)),
28270 mkU32(0)));
28271 assign(t1, binop(Iop_CmpEQ32,
28272 binop(Iop_And32,
28273 unop(Iop_ReinterpF32asI32,
28274 getLoFromF64(tyF, getFReg(fs))),
28275 mkU32(0x7f800000)),
28276 mkU32(0x7f800000)));
28277 assign(t2, binop(Iop_CmpEQ32,
28278 binop(Iop_And32,
28279 unop(Iop_ReinterpF32asI32,
28280 getLoFromF64(tyF, getFReg(fs))),
28281 mkU32(0x80000000)),
28282 mkU32(0x80000000)));
28283 assign(t3, binop(Iop_CmpEQ32,
28284 binop(Iop_And32,
28285 unop(Iop_ReinterpF32asI32,
28286 getLoFromF64(tyF, getFReg(fs))),
28287 mkU32(0x00400000)),
28288 mkU32(0x00400000)));
28289 assign(t4, binop(Iop_CmpNE32,
28290 binop(Iop_And32,
28291 unop(Iop_ReinterpF32asI32,
28292 getLoFromF64(tyF, getFReg(fs))),
28293 mkU32(0x007fffff)),
28294 mkU32(0)));
28295 assign(t5, binop(Iop_Shl32,
28296 IRExpr_ITE(mkexpr(t1),
28297 IRExpr_ITE(mkexpr(t4),
28298 mkU32(0), mkU32(1)),
28299 IRExpr_ITE(mkexpr(t0),
28300 IRExpr_ITE(mkexpr(t4),
28301 mkU32(0x4),
28302 mkU32(0x8)), //zero or subnorm
28303 mkU32(2))),
28304 IRExpr_ITE(mkexpr(t2), mkU8(2), mkU8(6))));
28305 putDReg(fd, unop(Iop_ReinterpI64asF64,
28306 unop(Iop_32Uto64,
28307 IRExpr_ITE(binop(Iop_CmpNE32,
28308 mkexpr(t5), mkU32(0)),
28309 mkexpr(t5),
28310 IRExpr_ITE(mkexpr(t3),
28311 mkU32(2),
28312 mkU32(1))))));
28313 break;
28315 default:
28316 goto decode_failure;
28318 } else {
28319 ILLEGAL_INSTRUCTON;
28321 break;
28323 default:
28324 if (dis_instr_CCondFmt(cins))
28325 break;
28326 goto decode_failure;
28332 break; /* COP1 */
28334 case 0x31: /* LWC1 */
28335 /* Load Word to Floating Point - LWC1 (MIPS32) */
28336 DIP("lwc1 f%u, %u(r%u)", ft, imm, rs);
28337 LOAD_STORE_PATTERN;
28338 if (fp_mode64) {
28339 t0 = newTemp(Ity_F32);
28340 t2 = newTemp(Ity_I64);
28341 assign(t0, load(Ity_F32, mkexpr(t1)));
28342 assign(t2, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
28343 mkexpr(t0)), True));
28344 putDReg(ft, unop(Iop_ReinterpI64asF64, mkexpr(t2)));
28345 } else {
28346 putFReg(ft, load(Ity_F32, mkexpr(t1)));
28348 break;
28350 case 0x39: /* SWC1 */
28351 DIP("swc1 f%u, %u(r%u)", ft, imm, rs);
28352 if (fp_mode64) {
28353 t0 = newTemp(Ity_I64);
28354 t2 = newTemp(Ity_I32);
28355 LOAD_STORE_PATTERN;
28356 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(ft)));
28357 assign(t2, unop(Iop_64to32, mkexpr(t0)));
28358 store(mkexpr(t1), unop(Iop_ReinterpI32asF32, mkexpr(t2)));
28359 } else {
28360 LOAD_STORE_PATTERN;
28361 store(mkexpr(t1), getFReg(ft));
28363 break;
28365 case 0x33: /* PREF */
28366 DIP("pref");
28367 break;
28369 case 0x35:
28370 /* Load Doubleword to Floating Point - LDC1 (MIPS32) */
28371 DIP("ldc1 f%u, %u(%u)", rt, imm, rs);
28372 LOAD_STORE_PATTERN;
28373 putDReg(ft, load(Ity_F64, mkexpr(t1)));
28374 break;
28376 case 0x3D:
28377 /* Store Doubleword from Floating Point - SDC1 */
28378 DIP("sdc1 f%u, %u(%u)", ft, imm, rs);
28379 LOAD_STORE_PATTERN;
28380 store(mkexpr(t1), getDReg(ft));
28381 break;
28383 case 0x23: /* LW */
28384 DIP("lw r%u, %u(r%u)", rt, imm, rs);
28385 LOAD_STORE_PATTERN;
28386 putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
28387 break;
28389 case 0x20: /* LB */
28390 DIP("lb r%u, %u(r%u)", rt, imm, rs);
28391 LOAD_STORE_PATTERN;
28392 if (mode64)
28393 putIReg(rt, unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
28394 else
28395 putIReg(rt, unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
28396 break;
28398 case 0x24: /* LBU */
28399 DIP("lbu r%u, %u(r%u)", rt, imm, rs);
28400 LOAD_STORE_PATTERN;
28401 if (mode64)
28402 putIReg(rt, unop(Iop_8Uto64, load(Ity_I8, mkexpr(t1))));
28403 else
28404 putIReg(rt, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t1))));
28405 break;
28407 case 0x21: /* LH */
28408 DIP("lh r%u, %u(r%u)", rt, imm, rs);
28409 LOAD_STORE_PATTERN;
28410 if (mode64)
28411 putIReg(rt, unop(Iop_16Sto64, load(Ity_I16, mkexpr(t1))));
28412 else
28413 putIReg(rt, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t1))));
28414 break;
28416 case 0x25: /* LHU */
28417 DIP("lhu r%u, %u(r%u)", rt, imm, rs);
28418 LOAD_STORE_PATTERN;
28419 if (mode64)
28420 putIReg(rt, unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
28421 else
28422 putIReg(rt, unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
28423 break;
28425 case 0x0F: /* LUI */
28426 if (rs == 0) {
28427 p = (imm << 16);
28428 DIP("lui r%u, imm: 0x%x", rt, imm);
28429 if (mode64)
28430 putIReg(rt, mkU64(extend_s_32to64(p)));
28431 else
28432 putIReg(rt, mkU32(p));
28433 break;
28434 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) { /* AUI */
28435 DIP("aui r%u, imm: 0x%x", rt, imm);
28436 if (mode64) {
28437 putIReg(rt, unop(Iop_32Sto64,
28438 unop(Iop_64to32,
28439 binop(Iop_Add64,
28440 getIReg(rs),
28441 mkU64(extend_s_32to64(imm << 16))))));
28442 } else {
28443 putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(imm << 16)));
28445 } else {
28446 ILLEGAL_INSTRUCTON;
28448 break;
28450 case 0x13: /* COP1X */
28451 switch (function) {
28452 case 0x0: { /* LWXC1 */
28453 /* Load Word Indexed to Floating Point - LWXC1 (MIPS32r2) */
28454 DIP("lwxc1 f%u, r%u(r%u)", fd, rt, rs);
28455 t2 = newTemp(ty);
28456 assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
28457 getIReg(rt)));
28458 if (fp_mode64) {
28459 t0 = newTemp(Ity_I64);
28460 t1 = newTemp(Ity_I32);
28461 t3 = newTemp(Ity_F32);
28462 t4 = newTemp(Ity_I64);
28463 assign(t3, load(Ity_F32, mkexpr(t2)));
28465 assign(t4, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
28466 mkexpr(t3)), True));
28468 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t4)));
28469 } else {
28470 putFReg(fd, load(Ity_F32, mkexpr(t2)));
28472 break;
28475 case 0x1: { /* LDXC1 */
28476 /* Load Doubleword Indexed to Floating Point
28477 LDXC1 (MIPS32r2 and MIPS64) */
28478 DIP("ldxc1 f%u, r%u(r%u)", fd, rt, rs);
28479 t0 = newTemp(ty);
28480 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
28481 getIReg(rt)));
28482 putDReg(fd, load(Ity_F64, mkexpr(t0)));
28483 break;
28486 case 0x5: /* Load Doubleword Indexed Unaligned to Floating Point - LUXC1;
28487 MIPS32r2 and MIPS64 */
28488 DIP("luxc1 f%u, r%u(r%u)", fd, rt, rs);
28489 if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps))
28490 && fp_mode64) {
28491 t0 = newTemp(ty);
28492 t1 = newTemp(ty);
28493 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32,
28494 getIReg(rs), getIReg(rt)));
28495 assign(t1, binop(mode64 ? Iop_And64 : Iop_And32,
28496 mkexpr(t0),
28497 mode64 ? mkU64(0xfffffffffffffff8ULL)
28498 : mkU32(0xfffffff8ULL)));
28499 putFReg(fd, load(Ity_F64, mkexpr(t1)));
28500 } else {
28501 ILLEGAL_INSTRUCTON;
28503 break;
28505 case 0x8: { /* Store Word Indexed from Floating Point - SWXC1 */
28506 DIP("swxc1 f%u, r%u(r%u)", ft, rt, rs);
28507 t0 = newTemp(ty);
28508 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
28509 getIReg(rt)));
28510 if (fp_mode64) {
28511 store(mkexpr(t0), getLoFromF64(tyF, getFReg(fs)));
28512 } else {
28513 store(mkexpr(t0), getFReg(fs));
28515 break;
28517 case 0x9: { /* Store Doubleword Indexed from Floating Point - SDXC1 */
28518 DIP("sdxc1 f%u, r%u(r%u)", fs, rt, rs);
28519 t0 = newTemp(ty);
28520 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
28521 getIReg(rt)));
28522 store(mkexpr(t0), getDReg(fs));
28523 break;
28525 case 0xD: /* Store Doubleword Indexed Unaligned from Floating Point -
28526 SUXC1; MIPS64 MIPS32r2 */
28527 DIP("suxc1 f%u, r%u(r%u)", fd, rt, rs);
28528 if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps))
28529 && fp_mode64) {
28530 t0 = newTemp(ty);
28531 t1 = newTemp(ty);
28532 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32,
28533 getIReg(rs), getIReg(rt)));
28534 assign(t1, binop(mode64 ? Iop_And64 : Iop_And32,
28535 mkexpr(t0),
28536 mode64 ? mkU64(0xfffffffffffffff8ULL)
28537 : mkU32(0xfffffff8ULL)));
28538 store(mkexpr(t1), getFReg(fs));
28539 } else {
28540 ILLEGAL_INSTRUCTON;
28542 break;
28544 case 0x0F: {
28545 DIP("prefx");
28546 break;
28548 case 0x20: { /* MADD.S */
28549 DIP("madd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
28550 IRExpr *rm = get_IR_roundingmode();
28551 t1 = newTemp(Ity_F32);
28552 assign(t1, triop(Iop_AddF32, rm, getLoFromF64(tyF, getFReg(fmt)),
28553 triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
28554 getLoFromF64(tyF, getFReg(ft)))));
28555 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
28556 break; /* MADD.S */
28558 case 0x21: { /* MADD.D */
28559 DIP("madd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
28560 IRExpr *rm = get_IR_roundingmode();
28561 putDReg(fd, triop(Iop_AddF64, rm, getDReg(fmt),
28562 triop(Iop_MulF64, rm, getDReg(fs),
28563 getDReg(ft))));
28564 break; /* MADD.D */
28566 case 0x28: { /* MSUB.S */
28567 DIP("msub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
28568 IRExpr *rm = get_IR_roundingmode();
28569 t1 = newTemp(Ity_F32);
28570 assign(t1, triop(Iop_SubF32, rm,
28571 triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
28572 getLoFromF64(tyF, getFReg(ft))),
28573 getLoFromF64(tyF, getFReg(fmt))));
28574 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
28575 break; /* MSUB.S */
28577 case 0x29: { /* MSUB.D */
28578 DIP("msub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
28579 IRExpr *rm = get_IR_roundingmode();
28580 putDReg(fd, triop(Iop_SubF64, rm, triop(Iop_MulF64, rm, getDReg(fs),
28581 getDReg(ft)), getDReg(fmt)));
28582 break; /* MSUB.D */
28584 case 0x30: { /* NMADD.S */
28585 DIP("nmadd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
28586 IRExpr *rm = get_IR_roundingmode();
28587 t1 = newTemp(Ity_F32);
28588 assign(t1, triop(Iop_AddF32, rm, getLoFromF64(tyF, getFReg(fmt)),
28589 triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
28590 getLoFromF64(tyF, getFReg(ft)))));
28591 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
28592 break; /* NMADD.S */
28594 case 0x31: { /* NMADD.D */
28595 DIP("nmadd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
28596 IRExpr *rm = get_IR_roundingmode();
28597 t1 = newTemp(Ity_F64);
28598 assign(t1, triop(Iop_AddF64, rm, getDReg(fmt),
28599 triop(Iop_MulF64, rm, getDReg(fs),
28600 getDReg(ft))));
28601 putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
28602 break; /* NMADD.D */
28604 case 0x38: { /* NMSUBB.S */
28605 DIP("nmsub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
28606 IRExpr *rm = get_IR_roundingmode();
28607 t1 = newTemp(Ity_F32);
28608 assign(t1, triop(Iop_SubF32, rm,
28609 triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
28610 getLoFromF64(tyF, getFReg(ft))),
28611 getLoFromF64(tyF, getFReg(fmt))));
28612 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
28613 break; /* NMSUBB.S */
28615 case 0x39: { /* NMSUBB.D */
28616 DIP("nmsub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
28617 IRExpr *rm = get_IR_roundingmode();
28618 t1 = newTemp(Ity_F64);
28619 assign(t1, triop(Iop_SubF64, rm, triop(Iop_MulF64, rm, getDReg(fs),
28620 getDReg(ft)), getDReg(fmt)));
28621 putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
28622 break; /* NMSUBB.D */
28625 default:
28626 goto decode_failure;
28628 break;
28630 case 0x22: /* LWL */
28631 DIP("lwl r%u, %u(r%u)", rt, imm, rs);
28632 if (mode64) {
28633 /* t1 = addr */
28634 t1 = newTemp(Ity_I64);
28635 #if defined (_MIPSEL)
28636 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
28637 #elif defined (_MIPSEB)
28638 assign(t1, binop(Iop_Xor64,
28639 mkU64(0x03),
28640 binop(Iop_Add64,
28641 getIReg(rs),
28642 mkU64(extend_s_16to64(imm)))));
28643 #endif
28644 /* t2 = word addr */
28645 /* t4 = addr mod 4 */
28646 LWX_SWX_PATTERN64;
28648 /* t3 = word content - shifted */
28649 t3 = newTemp(Ity_I32);
28650 assign(t3, binop(Iop_Shl32,
28651 load(Ity_I32, mkexpr(t2)),
28652 narrowTo(Ity_I8,
28653 binop(Iop_Shl32,
28654 binop(Iop_Sub32,
28655 mkU32(0x03),
28656 mkexpr(t4)),
28657 mkU8(3)))));
28659 /* rt content - adjusted */
28660 t5 = newTemp(Ity_I32);
28661 assign(t5, binop(Iop_And32,
28662 mkNarrowTo32(ty, getIReg(rt)),
28663 binop(Iop_Shr32,
28664 mkU32(0x00FFFFFF),
28665 narrowTo(Ity_I8, binop(Iop_Mul32,
28666 mkU32(0x08),
28667 mkexpr(t4))))));
28669 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
28670 mkexpr(t3)), True));
28671 } else {
28672 /* t1 = addr */
28673 t1 = newTemp(Ity_I32);
28674 #if defined (_MIPSEL)
28675 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
28676 #elif defined (_MIPSEB)
28677 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
28678 mkU32(extend_s_16to32(imm)))));
28679 #endif
28681 /* t2 = word addr */
28682 /* t4 = addr mod 4 */
28683 LWX_SWX_PATTERN;
28685 /* t3 = word content - shifted */
28686 t3 = newTemp(Ity_I32);
28687 assign(t3, binop(Iop_Shl32, load(Ity_I32, mkexpr(t2)), narrowTo(Ity_I8,
28688 binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)),
28689 mkU8(3)))));
28691 /* rt content - adjusted */
28692 t5 = newTemp(Ity_I32);
28693 assign(t5, binop(Iop_And32,
28694 getIReg(rt),
28695 binop(Iop_Shr32,
28696 mkU32(0x00FFFFFF),
28697 narrowTo(Ity_I8, binop(Iop_Mul32,
28698 mkU32(0x08),
28699 mkexpr(t4))))));
28701 putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
28703 break;
28705 case 0x26: /* LWR */
28706 DIP("lwr r%u, %u(r%u)", rt, imm, rs);
28707 if (mode64) {
28708 /* t1 = addr */
28709 t1 = newTemp(Ity_I64);
28710 #if defined (_MIPSEL)
28711 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
28712 #elif defined (_MIPSEB)
28713 assign(t1, binop(Iop_Xor64,
28714 mkU64(0x3),
28715 binop(Iop_Add64,
28716 getIReg(rs),
28717 mkU64(extend_s_16to64(imm)))));
28718 #endif
28719 /* t2 = word addr */
28720 /* t4 = addr mod 4 */
28721 LWX_SWX_PATTERN64;
28723 /* t3 = word content - shifted */
28724 t3 = newTemp(Ity_I32);
28725 assign(t3, binop(Iop_Shr32,
28726 load(Ity_I32, mkexpr(t2)),
28727 narrowTo(Ity_I8,
28728 binop(Iop_Shl32, mkexpr(t4), mkU8(0x03)))));
28730 /* rt content - adjusted */
28731 t5 = newTemp(Ity_I32);
28732 assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
28733 unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF),
28734 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
28736 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
28737 mkexpr(t3)), True));
28739 } else {
28740 /* t1 = addr */
28741 t1 = newTemp(Ity_I32);
28742 #if defined (_MIPSEL)
28743 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
28744 #elif defined (_MIPSEB)
28745 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
28746 mkU32(extend_s_16to32(imm)))));
28747 #endif
28749 /* t2 = word addr */
28750 /* t4 = addr mod 4 */
28751 LWX_SWX_PATTERN;
28753 /* t3 = word content - shifted */
28754 t3 = newTemp(Ity_I32);
28755 assign(t3, binop(Iop_Shr32, load(Ity_I32, mkexpr(t2)),
28756 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4),
28757 mkU8(3)))));
28759 /* rt content - adjusted */
28760 t5 = newTemp(Ity_I32);
28761 assign(t5, binop(Iop_And32, getIReg(rt), unop(Iop_Not32,
28762 binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
28763 binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
28765 putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
28767 break;
28769 case 0x2B: /* SW */
28770 DIP("sw r%u, %u(r%u)", rt, imm, rs);
28771 LOAD_STORE_PATTERN;
28772 store(mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)));
28773 break;
28775 case 0x2C: { /* SDL rt, offset(base) MIPS64 */
28776 DIP("sdl r%u, %u(r%u)", rt, imm, rs);
28777 vassert(mode64);
28778 IRTemp A_byte = newTemp(Ity_I8);
28779 IRTemp B_byte = newTemp(Ity_I8);
28780 IRTemp C_byte = newTemp(Ity_I8);
28781 IRTemp D_byte = newTemp(Ity_I8);
28782 IRTemp E_byte = newTemp(Ity_I8);
28783 IRTemp F_byte = newTemp(Ity_I8);
28784 IRTemp G_byte = newTemp(Ity_I8);
28785 IRTemp H_byte = newTemp(Ity_I8);
28786 IRTemp B_pos = newTemp(Ity_I64);
28787 IRTemp C_pos = newTemp(Ity_I64);
28788 IRTemp D_pos = newTemp(Ity_I64);
28789 IRTemp E_pos = newTemp(Ity_I64);
28790 IRTemp F_pos = newTemp(Ity_I64);
28791 IRTemp G_pos = newTemp(Ity_I64);
28793 /* H byte */
28794 assign(H_byte, getByteFromReg(rt, 0));
28795 /* G byte */
28796 assign(G_byte, getByteFromReg(rt, 1));
28797 /* F byte */
28798 assign(F_byte, getByteFromReg(rt, 2));
28799 /* E byte */
28800 assign(E_byte, getByteFromReg(rt, 3));
28801 /* D byte */
28802 assign(D_byte, getByteFromReg(rt, 4));
28803 /* C byte */
28804 assign(C_byte, getByteFromReg(rt, 5));
28805 /* B byte */
28806 assign(B_byte, getByteFromReg(rt, 6));
28807 /* A byte */
28808 assign(A_byte, getByteFromReg(rt, 7));
28810 /* t1 = addr */
28811 t1 = newTemp(Ity_I64);
28812 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
28814 /* t2 = word addr */
28815 t2 = newTemp(Ity_I64);
28816 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
28818 /* t3 = addr mod 7 */
28819 t3 = newTemp(Ity_I64);
28820 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
28822 #if defined (_MIPSEL)
28823 /* Calculate X_byte position. */
28824 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x1)),
28825 mkU64(0x0),
28826 mkU64(0x1)));
28828 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x2)),
28829 mkU64(0x0),
28830 mkU64(0x2)));
28832 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
28833 mkU64(0x0),
28834 mkU64(0x3)));
28836 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
28837 mkU64(0x0),
28838 mkU64(0x4)));
28840 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
28841 mkU64(0x0),
28842 mkU64(0x5)));
28844 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
28845 mkU64(0x1),
28846 mkU64(0x0)));
28848 /* Store X_byte on the right place. */
28849 store(mkexpr(t2), mkexpr(H_byte));
28850 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
28851 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
28852 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
28853 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
28854 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
28855 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
28856 store(mkexpr(t1), mkexpr(A_byte));
28858 #else /* _MIPSEB */
28859 /* Calculate X_byte position. */
28860 assign(B_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
28861 mkU64(0x0),
28862 mkU64(0x1)));
28864 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x6)),
28865 mkU64(0x2),
28866 mkU64(0x0)));
28868 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
28869 mkU64(0x3),
28870 mkU64(0x0)));
28872 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
28873 mkU64(0x4),
28874 mkU64(0x0)));
28876 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
28877 mkU64(0x5),
28878 mkU64(0x0)));
28880 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
28881 mkU64(0x6),
28882 mkU64(0x7)));
28884 /* Store X_byte on the right place. */
28885 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(H_byte));
28886 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
28887 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
28888 store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
28889 store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
28890 store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
28891 store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
28892 store(mkexpr(t1), mkexpr(A_byte));
28893 #endif
28895 break;
28898 case 0x2D: {
28899 /* SDR rt, offset(base) - MIPS64 */
28900 vassert(mode64);
28901 DIP("sdr r%u, %u(r%u)", rt, imm, rs);
28902 IRTemp A_byte = newTemp(Ity_I8);
28903 IRTemp B_byte = newTemp(Ity_I8);
28904 IRTemp C_byte = newTemp(Ity_I8);
28905 IRTemp D_byte = newTemp(Ity_I8);
28906 IRTemp E_byte = newTemp(Ity_I8);
28907 IRTemp F_byte = newTemp(Ity_I8);
28908 IRTemp G_byte = newTemp(Ity_I8);
28909 IRTemp H_byte = newTemp(Ity_I8);
28910 IRTemp B_pos = newTemp(Ity_I64);
28911 IRTemp C_pos = newTemp(Ity_I64);
28912 IRTemp D_pos = newTemp(Ity_I64);
28913 IRTemp E_pos = newTemp(Ity_I64);
28914 IRTemp F_pos = newTemp(Ity_I64);
28915 IRTemp G_pos = newTemp(Ity_I64);
28917 /* H byte */
28918 assign(H_byte, getByteFromReg(rt, 0));
28919 /* G byte */
28920 assign(G_byte, getByteFromReg(rt, 1));
28921 /* F byte */
28922 assign(F_byte, getByteFromReg(rt, 2));
28923 /* E byte */
28924 assign(E_byte, getByteFromReg(rt, 3));
28925 /* D byte */
28926 assign(D_byte, getByteFromReg(rt, 4));
28927 /* C byte */
28928 assign(C_byte, getByteFromReg(rt, 5));
28929 /* B byte */
28930 assign(B_byte, getByteFromReg(rt, 6));
28931 /* A byte */
28932 assign(A_byte, getByteFromReg(rt, 7));
28934 /* t1 = addr */
28935 t1 = newTemp(Ity_I64);
28936 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
28938 /* t2 = word addr */
28939 t2 = newTemp(Ity_I64);
28940 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
28942 /* t3 = addr mod 7 */
28943 t3 = newTemp(Ity_I64);
28944 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
28946 #if defined (_MIPSEL)
28947 /* Calculate X_byte position. */
28948 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
28949 mkU64(0x0),
28950 mkU64(0x6)));
28952 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
28953 mkU64(0x0),
28954 mkU64(0x5)));
28956 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
28957 mkU64(0x0),
28958 mkU64(0x4)));
28960 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
28961 mkU64(0x0),
28962 mkU64(0x3)));
28964 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
28965 mkU64(0x0),
28966 mkU64(0x2)));
28968 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
28969 mkU64(0x0),
28970 mkU64(0x1)));
28972 /* Store X_byte on the right place. */
28973 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(A_byte));
28974 store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
28975 store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
28976 store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
28977 store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
28978 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
28979 store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
28980 store(mkexpr(t1), mkexpr(H_byte));
28982 #else /* _MIPSEB */
28983 /* Calculate X_byte position. */
28984 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
28985 mkU64(0x6),
28986 mkU64(0x0)));
28988 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
28989 mkU64(0x5),
28990 mkU64(0x0)));
28992 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
28993 mkU64(0x4),
28994 mkU64(0x0)));
28996 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
28997 mkU64(0x3),
28998 mkU64(0x0)));
29000 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
29001 mkU64(0x2),
29002 mkU64(0x0)));
29004 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
29005 mkU64(0x0),
29006 mkU64(0x1)));
29008 /* Store X_byte on the right place. */
29009 store(mkexpr(t2), mkexpr(A_byte));
29010 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
29011 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
29012 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
29013 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
29014 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
29015 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
29016 store(mkexpr(t1), mkexpr(H_byte));
29017 #endif
29018 break;
29021 case 0x28: /* SB */
29022 DIP("sb r%u, %u(r%u)", rt, imm, rs);
29023 LOAD_STORE_PATTERN;
29024 store(mkexpr(t1), narrowTo(Ity_I8, getIReg(rt)));
29025 break;
29027 case 0x29: /* SH */
29028 DIP("sh r%u, %u(r%u)", rt, imm, rs);
29029 LOAD_STORE_PATTERN;
29030 store(mkexpr(t1), narrowTo(Ity_I16, getIReg(rt)));
29031 break;
29033 case 0x2A: /* SWL */
29034 DIP("swl r%u, %u(r%u)", rt, imm, rs);
29035 if (mode64) {
29036 IRTemp E_byte = newTemp(Ity_I8);
29037 IRTemp F_byte = newTemp(Ity_I8);
29038 IRTemp G_byte = newTemp(Ity_I8);
29039 IRTemp H_byte = newTemp(Ity_I8);
29040 IRTemp F_pos = newTemp(Ity_I64);
29041 IRTemp G_pos = newTemp(Ity_I64);
29043 /* H byte */
29044 assign(H_byte, getByteFromReg(rt, 0));
29045 /* G byte */
29046 assign(G_byte, getByteFromReg(rt, 1));
29047 /* F byte */
29048 assign(F_byte, getByteFromReg(rt, 2));
29049 /* E byte */
29050 assign(E_byte, getByteFromReg(rt, 3));
29052 /* t1 = addr */
29053 t1 = newTemp(Ity_I64);
29054 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
29056 /* t2 = word addr */
29057 t2 = newTemp(Ity_I64);
29058 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
29060 /* t3 = addr mod 4 */
29061 t3 = newTemp(Ity_I64);
29062 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
29064 #if defined (_MIPSEL)
29065 /* Calculate X_byte position. */
29066 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
29067 mkU64(0x0),
29068 mkU64(0x1)));
29070 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
29071 mkU64(0x1),
29072 mkU64(0x0)));
29074 /* Store X_byte on the right place. */
29075 store(mkexpr(t2), mkexpr(H_byte));
29076 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
29077 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
29078 store(mkexpr(t1), mkexpr(E_byte));
29080 #else /* _MIPSEB */
29081 /* Calculate X_byte position. */
29082 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
29083 mkU64(0x0),
29084 mkU64(0x1)));
29086 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
29087 mkU64(0x2),
29088 mkU64(0x3)));
29090 store(binop(Iop_Add64, mkexpr(t2), mkU64(3)), mkexpr(H_byte));
29091 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
29092 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
29093 store(mkexpr(t1), mkexpr(E_byte));
29095 #endif
29096 } else {
29097 IRTemp E_byte = newTemp(Ity_I8);
29098 IRTemp F_byte = newTemp(Ity_I8);
29099 IRTemp G_byte = newTemp(Ity_I8);
29100 IRTemp H_byte = newTemp(Ity_I8);
29101 IRTemp F_pos = newTemp(Ity_I32);
29102 IRTemp G_pos = newTemp(Ity_I32);
29104 /* H byte */
29105 assign(H_byte, getByteFromReg(rt, 0));
29106 /* G byte */
29107 assign(G_byte, getByteFromReg(rt, 1));
29108 /* F byte */
29109 assign(F_byte, getByteFromReg(rt, 2));
29110 /* E byte */
29111 assign(E_byte, getByteFromReg(rt, 3));
29113 /* t1 = addr */
29114 t1 = newTemp(Ity_I32);
29115 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
29117 /* t2 = word addr */
29118 t2 = newTemp(Ity_I32);
29119 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
29121 /* t3 = addr mod 4 */
29122 t3 = newTemp(Ity_I32);
29123 assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
29125 #if defined (_MIPSEL)
29126 /* Calculate X_byte position. */
29127 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
29128 mkU32(0x0),
29129 mkU32(0x1)));
29131 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
29132 mkU32(0x1),
29133 mkU32(0x0)));
29135 /* Store X_byte on the right place. */
29136 store(mkexpr(t2), mkexpr(H_byte));
29137 store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
29138 store(binop(Iop_Sub32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
29139 store(mkexpr(t1), mkexpr(E_byte));
29141 #else /* _MIPSEB */
29142 /* Calculate X_byte position. */
29143 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
29144 mkU32(0x0),
29145 mkU32(0x1)));
29147 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
29148 mkU32(0x2),
29149 mkU32(0x3)));
29151 store(binop(Iop_Add32, mkexpr(t2), mkU32(3)), mkexpr(H_byte));
29152 store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
29153 store(binop(Iop_Add32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
29154 store(mkexpr(t1), mkexpr(E_byte));
29156 #endif
29158 break;
29160 case 0x2E: /* SWR */
29161 DIP("swr r%u, %u(r%u)", rt, imm, rs);
29162 if (mode64) {
29163 IRTemp E_byte = newTemp(Ity_I8);
29164 IRTemp F_byte = newTemp(Ity_I8);
29165 IRTemp G_byte = newTemp(Ity_I8);
29166 IRTemp H_byte = newTemp(Ity_I8);
29167 IRTemp F_pos = newTemp(Ity_I64);
29168 IRTemp G_pos = newTemp(Ity_I64);
29170 /* H byte */
29171 assign(H_byte, getByteFromReg(rt, 0));
29172 /* G byte */
29173 assign(G_byte, getByteFromReg(rt, 1));
29174 /* F byte */
29175 assign(F_byte, getByteFromReg(rt, 2));
29176 /* E byte */
29177 assign(E_byte, getByteFromReg(rt, 3));
29179 /* t1 = addr */
29180 t1 = newTemp(Ity_I64);
29181 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
29183 /* t2 = word addr */
29184 t2 = newTemp(Ity_I64);
29185 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
29187 /* t3 = addr mod 4 */
29188 t3 = newTemp(Ity_I64);
29189 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
29191 #if defined (_MIPSEL)
29192 /* Calculate X_byte position. */
29193 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
29194 mkU64(0x2),
29195 mkU64(0x3)));
29197 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
29198 mkU64(0x0),
29199 mkU64(0x1)));
29201 /* Store X_byte on the right place. */
29202 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x3)), mkexpr(E_byte));
29203 store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
29204 store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
29205 store(mkexpr(t1), mkexpr(H_byte));
29207 #else /* _MIPSEB */
29208 /* Calculate X_byte position. */
29209 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
29210 mkU64(0x1),
29211 mkU64(0x0)));
29213 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
29214 mkU64(0x0),
29215 mkU64(0x1)));
29217 /* Store X_byte on the right place. */
29218 store(mkexpr(t2), mkexpr(E_byte));
29219 store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
29220 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
29221 store(mkexpr(t1), mkexpr(H_byte));
29222 #endif
29223 } else {
29224 IRTemp E_byte = newTemp(Ity_I8);
29225 IRTemp F_byte = newTemp(Ity_I8);
29226 IRTemp G_byte = newTemp(Ity_I8);
29227 IRTemp H_byte = newTemp(Ity_I8);
29228 IRTemp F_pos = newTemp(Ity_I32);
29229 IRTemp G_pos = newTemp(Ity_I32);
29231 /* H byte */
29232 assign(H_byte, getByteFromReg(rt, 0));
29233 /* G byte */
29234 assign(G_byte, getByteFromReg(rt, 1));
29235 /* F byte */
29236 assign(F_byte, getByteFromReg(rt, 2));
29237 /* E byte */
29238 assign(E_byte, getByteFromReg(rt, 3));
29240 /* t1 = addr */
29241 t1 = newTemp(Ity_I32);
29242 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
29244 /* t2 = word addr */
29245 t2 = newTemp(Ity_I32);
29246 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
29248 /* t3 = addr mod 4 */
29249 t3 = newTemp(Ity_I32);
29250 assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
29252 #if defined (_MIPSEL)
29253 /* Calculate X_byte position. */
29254 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
29255 mkU32(0x2),
29256 mkU32(0x3)));
29258 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
29259 mkU32(0x0),
29260 mkU32(0x1)));
29262 /* Store X_byte on the right place. */
29263 store(binop(Iop_Add32, mkexpr(t2), mkU32(0x3)), mkexpr(E_byte));
29264 store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
29265 store(binop(Iop_Add32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
29266 store(mkexpr(t1), mkexpr(H_byte));
29268 #else /* _MIPSEB */
29269 /* Calculate X_byte position. */
29270 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
29271 mkU32(0x1),
29272 mkU32(0x0)));
29274 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
29275 mkU32(0x0),
29276 mkU32(0x1)));
29278 /* Store X_byte on the right place. */
29279 store(mkexpr(t2), mkexpr(E_byte));
29280 store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
29281 store(binop(Iop_Sub32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
29282 store(mkexpr(t1), mkexpr(H_byte));
29283 #endif
29285 break;
29287 case 0x1C: /* Special2 */
29288 switch (function) {
29289 /* Cavium Specific instructions */
29290 case 0x03: case 0x32: case 0x33: /* DMUL, CINS , CINS32 */
29291 case 0x3A: case 0x3B: case 0x2B: /* EXT, EXT32, SNE */
29292 /* CVM Compare Instructions */
29293 case 0x2A: case 0x2E: case 0x2F: /* SEQ, SEQI, SNEI */
29294 /* CPU Load, Store, Memory, and Control Instructions */
29295 case 0x18: case 0x19: /* SAA, SAAD */
29296 case 0x1F: /* LAA, LAAD, LAI, LAID */
29297 case 0x28: case 0x2C: case 0x2D: /* BADDU, POP, DPOP */
29298 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
29299 if (dis_instr_CVM(cins))
29300 break;
29301 goto decode_failure;
29302 } else {
29303 goto decode_failure;
29305 break;
29307 case 0x02: { /* MUL */
29308 DIP("mul r%u, r%u, r%u", rd, rs, rt);
29309 if (mode64) {
29310 IRTemp tmpRs32 = newTemp(Ity_I32);
29311 IRTemp tmpRt32 = newTemp(Ity_I32);
29312 IRTemp tmpRes = newTemp(Ity_I32);
29314 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
29315 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
29316 assign(tmpRes, binop(Iop_Mul32,
29317 mkexpr(tmpRs32), mkexpr(tmpRt32)));
29318 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpRes), True));
29319 } else
29320 putIReg(rd, binop(Iop_Mul32, getIReg(rs), getIReg(rt)));
29321 break;
29324 case 0x00: { /* MADD */
29325 if (mode64) {
29326 DIP("madd r%u, r%u", rs, rt);
29327 t1 = newTemp(Ity_I32);
29328 t2 = newTemp(Ity_I32);
29329 t3 = newTemp(Ity_I64);
29330 t4 = newTemp(Ity_I64);
29331 t5 = newTemp(Ity_I64);
29332 t6 = newTemp(Ity_I32);
29334 assign(t1, mkNarrowTo32(ty, getHI()));
29335 assign(t2, mkNarrowTo32(ty, getLO()));
29337 assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
29338 mkNarrowTo32(ty, getIReg(rt))));
29340 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
29341 assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
29343 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
29344 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
29345 } else {
29346 if ( (1 <= ac) && ( 3 >= ac) ) {
29347 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
29348 /* If DSP is present -> DSP ASE MADD */
29349 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
29350 if (0 != retVal ) {
29351 goto decode_failure_dsp;
29353 break;
29354 } else {
29355 goto decode_failure_dsp;
29357 } else {
29358 DIP("madd r%u, r%u", rs, rt);
29359 t1 = newTemp(Ity_I32);
29360 t2 = newTemp(Ity_I32);
29361 t3 = newTemp(Ity_I64);
29362 t4 = newTemp(Ity_I32);
29363 t5 = newTemp(Ity_I32);
29364 t6 = newTemp(Ity_I32);
29366 assign(t1, getHI());
29367 assign(t2, getLO());
29369 assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
29371 assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
29372 mkexpr(t3))));
29374 assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
29375 unop(Iop_64to32, mkexpr(t3)))));
29376 assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
29378 putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
29379 mkexpr(t3))));
29380 putLO(mkexpr(t4));
29381 break;
29384 break;
29387 case 0x01: { /* MADDU */
29388 if (mode64) {
29389 DIP("maddu r%u, r%u", rs, rt);
29390 t1 = newTemp(Ity_I32);
29391 t2 = newTemp(Ity_I32);
29392 t3 = newTemp(Ity_I64);
29393 t4 = newTemp(Ity_I64);
29394 t5 = newTemp(Ity_I64);
29395 t6 = newTemp(Ity_I32);
29397 assign(t1, mkNarrowTo32(ty, getHI()));
29398 assign(t2, mkNarrowTo32(ty, getLO()));
29400 assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
29401 mkNarrowTo32(ty, getIReg(rt))));
29403 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
29404 assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
29406 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
29407 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
29408 } else {
29409 if ( (1 <= ac) && ( 3 >= ac) ) {
29410 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
29411 /* If DSP is present -> DSP ASE MADDU */
29412 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
29413 if (0 != retVal ) {
29414 goto decode_failure_dsp;
29416 break;
29417 } else {
29418 goto decode_failure_dsp;
29420 } else {
29421 DIP("maddu r%u, r%u", rs, rt);
29422 t1 = newTemp(Ity_I32);
29423 t2 = newTemp(Ity_I32);
29424 t3 = newTemp(Ity_I64);
29425 t4 = newTemp(Ity_I32);
29426 t5 = newTemp(Ity_I32);
29427 t6 = newTemp(Ity_I32);
29429 assign(t1, getHI());
29430 assign(t2, getLO());
29432 assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
29434 assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
29435 mkexpr(t3))));
29436 assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
29437 unop(Iop_64to32, mkexpr(t3)))));
29438 assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
29440 putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
29441 mkexpr(t3))));
29442 putLO(mkexpr(t4));
29443 break;
29446 break;
29449 case 0x04: { /* MSUB */
29450 if (mode64) {
29451 DIP("msub r%u, r%u", rs, rt);
29452 t1 = newTemp(Ity_I32);
29453 t2 = newTemp(Ity_I32);
29454 t3 = newTemp(Ity_I64);
29455 t4 = newTemp(Ity_I64);
29456 t5 = newTemp(Ity_I64);
29457 t6 = newTemp(Ity_I32);
29459 assign(t1, mkNarrowTo32(ty, getHI()));
29460 assign(t2, mkNarrowTo32(ty, getLO()));
29462 assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
29463 mkNarrowTo32(ty, getIReg(rt))));
29465 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
29466 assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
29468 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
29469 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
29470 } else {
29471 if ( (1 <= ac) && ( 3 >= ac) ) {
29472 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
29473 /* If DSP is present -> DSP ASE MSUB */
29474 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
29475 if (0 != retVal ) {
29476 goto decode_failure_dsp;
29478 break;
29479 } else {
29480 goto decode_failure_dsp;
29482 } else {
29483 DIP("msub r%u, r%u", rs, rt);
29484 t1 = newTemp(Ity_I32);
29485 t2 = newTemp(Ity_I32);
29486 t3 = newTemp(Ity_I64);
29487 t4 = newTemp(Ity_I32);
29488 t5 = newTemp(Ity_I1);
29489 t6 = newTemp(Ity_I32);
29491 assign(t1, getHI());
29492 assign(t2, getLO());
29494 assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
29495 assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */
29497 /* if lo<lo(mul) hi = hi - 1 */
29498 assign(t5, binop(Iop_CmpLT32U,
29499 mkexpr(t2),
29500 mkexpr(t4)));
29502 assign(t6, IRExpr_ITE(mkexpr(t5),
29503 binop(Iop_Sub32, mkexpr(t1), mkU32(0x1)),
29504 mkexpr(t1)));
29506 putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
29507 mkexpr(t3))));
29508 putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
29509 break;
29512 break;
29515 case 0x05: { /* MSUBU */
29516 if (mode64) {
29517 DIP("msubu r%u, r%u", rs, rt);
29518 t1 = newTemp(Ity_I32);
29519 t2 = newTemp(Ity_I32);
29520 t3 = newTemp(Ity_I64);
29521 t4 = newTemp(Ity_I64);
29522 t5 = newTemp(Ity_I64);
29523 t6 = newTemp(Ity_I32);
29525 assign(t1, mkNarrowTo32(ty, getHI()));
29526 assign(t2, mkNarrowTo32(ty, getLO()));
29528 assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
29529 mkNarrowTo32(ty, getIReg(rt))));
29531 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
29532 assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
29534 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
29535 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
29536 } else {
29537 if ( (1 <= ac) && ( 3 >= ac) ) {
29538 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
29539 /* If DSP is present -> DSP ASE MSUBU */
29540 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
29541 if (0 != retVal ) {
29542 goto decode_failure_dsp;
29544 break;
29545 } else {
29546 goto decode_failure_dsp;
29548 } else {
29549 DIP("msubu r%u, r%u", rs, rt);
29550 t1 = newTemp(Ity_I32);
29551 t2 = newTemp(Ity_I32);
29552 t3 = newTemp(Ity_I64);
29553 t4 = newTemp(Ity_I32);
29554 t5 = newTemp(Ity_I1);
29555 t6 = newTemp(Ity_I32);
29557 assign(t1, getHI());
29558 assign(t2, getLO());
29560 assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
29561 assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */
29563 /* if lo<lo(mul) hi = hi - 1 */
29564 assign(t5, binop(Iop_CmpLT32U,
29565 mkexpr(t2),
29566 mkexpr(t4)));
29568 assign(t6, IRExpr_ITE(mkexpr(t5),
29569 binop(Iop_Sub32,
29570 mkexpr(t1),
29571 mkU32(0x1)),
29572 mkexpr(t1)));
29574 putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
29575 mkexpr(t3))));
29576 putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
29577 break;
29580 break;
29583 case 0x6: /* dmul MIPS64 - Netlogic */
29584 DIP("dmul r%u, r%u, r%u", rd, rs, rt);
29585 t0 = newTemp(Ity_I128);
29587 assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
29589 putIReg(rd, unop(Iop_128to64, mkexpr(t0)));
29590 break;
29592 case 0x10: /* LDADDW - Swap Word - Netlogic */
29593 DIP("ldaddw r%u, r%u", rt, rs);
29594 t0 = newTemp(Ity_I32);
29595 t1 = newTemp(Ity_I32);
29596 t2 = newTemp(Ity_I32);
29597 t3 = newTemp(Ity_I64);
29598 t4 = newTemp(Ity_I32);
29599 t5 = newTemp(Ity_I32);
29600 t6 = newTemp(Ity_I32);
29602 /* v = GPR[rt] */
29603 assign(t0, mkNarrowTo32(ty, getIReg(rt)));
29605 /* GPR[rt] = memory[base]; */
29606 assign(t1, load(Ity_I32, getIReg(rs)));
29607 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
29609 /* memory[base] = memory[base] + v; */
29610 store(getIReg(rs), binop(Iop_Add32, mkexpr(t0), mkexpr(t1)));
29611 break;
29613 case 0x12: /* LDADDD - Swap Word - Netlogic */
29614 DIP("ldaddw r%u, r%u", rt, rs);
29615 t0 = newTemp(Ity_I64);
29616 t1 = newTemp(Ity_I64);
29618 /* v = GPR[rt] */
29619 assign(t0, getIReg(rt));
29621 /* GPR[rt] = memory[base]; */
29622 assign(t1, load(Ity_I64, getIReg(rs)));
29623 putIReg(rt, mkexpr(t1));
29625 /* memory[base] = memory[base] + v; */
29626 store(getIReg(rs), binop(Iop_Add64, mkexpr(t0), mkexpr(t1)));
29627 break;
29629 case 0x14: /* SWAPW - Swap Word - Netlogic */
29630 DIP("swapw r%u, r%u", rt, rs);
29631 t0 = newTemp(Ity_I32);
29632 t1 = newTemp(Ity_I32);
29633 assign(t0, mkNarrowTo32(ty, getIReg(rt)));
29634 assign(t1, load(Ity_I32, getIReg(rs)));
29635 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
29636 store(getIReg(rs), mkexpr(t0));
29637 break;
29639 case 0x16: /* SWAPD - Swap Double - Netlogic */
29640 DIP("swapw r%u, r%u", rt, rs);
29641 t0 = newTemp(Ity_I64);
29642 t1 = newTemp(Ity_I64);
29643 assign(t0, getIReg(rt));
29644 assign(t1, load(Ity_I64, getIReg(rs)));
29645 putIReg(rt, mkexpr(t1));
29646 store(getIReg(rs), mkexpr(t0));
29647 break;
29649 case 0x20: { /* CLZ */
29650 DIP("clz r%u, r%u", rd, rs);
29651 if (mode64) {
29652 IRTemp tmpClz32 = newTemp(Ity_I32);
29653 IRTemp tmpRs32 = newTemp(Ity_I32);
29655 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
29656 assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32)));
29657 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True));
29658 } else {
29659 t1 = newTemp(Ity_I1);
29660 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0)));
29661 putIReg(rd, IRExpr_ITE(mkexpr(t1),
29662 mkU32(0x00000020),
29663 unop(Iop_Clz32, getIReg(rs))));
29665 break;
29668 case 0x21: { /* CLO */
29669 DIP("clo r%u, r%u", rd, rs);
29670 if (mode64) {
29671 IRTemp tmpClo32 = newTemp(Ity_I32);
29672 IRTemp tmpRs32 = newTemp(Ity_I32);
29673 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
29675 t1 = newTemp(Ity_I1);
29676 assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff)));
29677 assign(tmpClo32, IRExpr_ITE(mkexpr(t1),
29678 mkU32(0x00000020),
29679 unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32)))));
29681 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True));
29682 break;
29683 } else {
29684 t1 = newTemp(Ity_I1);
29685 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff)));
29686 putIReg(rd, IRExpr_ITE(mkexpr(t1),
29687 mkU32(0x00000020),
29688 unop(Iop_Clz32,
29689 unop(Iop_Not32, getIReg(rs)))));
29690 break;
29694 case 0x24: /* Count Leading Zeros in Doubleword - DCLZ; MIPS64 */
29695 DIP("dclz r%u, r%u", rd, rs);
29696 t1 = newTemp(Ity_I1);
29697 assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0)));
29698 putIReg(rd, IRExpr_ITE(mkexpr(t1),
29699 mkU64(0x00000040),
29700 unop(Iop_Clz64, getIReg(rs))));
29701 break;
29703 case 0x25: /* Count Leading Ones in Doubleword - DCLO; MIPS64 */
29704 DIP("dclo r%u, r%u", rd, rs);
29705 t1 = newTemp(Ity_I1);
29706 assign(t1, binop(Iop_CmpEQ64, getIReg(rs),
29707 mkU64(0xffffffffffffffffULL)));
29708 putIReg(rd, IRExpr_ITE(mkexpr(t1),
29709 mkU64(0x40),
29710 unop(Iop_Clz64, unop(Iop_Not64,
29711 getIReg(rs)))));
29712 break;
29714 default:
29715 goto decode_failure;
29717 break;
29719 case 0x1F: /* Special3 */
29720 switch (function) {
29721 case 0x01: {
29722 /* Doubleword Extract Bit Field - DEXTM; MIPS64r2 */
29723 msb = get_msb(cins);
29724 lsb = get_lsb(cins);
29725 size = msb + 1;
29726 UInt srcPos = lsb;
29727 UInt dstSz = msb + 33;
29728 t1 = newTemp(Ity_I64);
29729 DIP("dextm r%u, r%u, %u, %u", rt, rs, lsb, msb + 1);
29731 UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */
29732 UChar rsAmt = 64 - dstSz; /* right shift amount; */
29734 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
29735 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
29737 break;
29739 case 0x02: {
29740 /* Doubleword Extract Bit Field Upper - DEXTU; MIPS64r2 */
29741 msb = get_msb(cins);
29742 lsb = get_lsb(cins);
29743 size = msb + 1;
29744 UInt srcPos = lsb + 32;
29745 UInt dstSz = msb + 1;
29746 DIP("dextu r%u, r%u, %u, %u", rt, rs, srcPos, dstSz);
29747 t1 = newTemp(Ity_I64);
29749 vassert(srcPos >= 32 && srcPos < 64);
29750 vassert(dstSz > 0 && dstSz <= 32);
29751 vassert((srcPos + dstSz) > 32 && (srcPos + dstSz) <= 64);
29753 UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */
29754 UChar rsAmt = 64 - dstSz; /* right shift amount; */
29756 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
29757 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
29758 break;
29760 case 0x05: {
29761 /* Doubleword Insert Bit Field Middle - DINSM; MIPS64r2 */
29762 msb = get_msb(cins);
29763 lsb = get_lsb(cins);
29764 size = msb + 1;
29765 UInt dstPos = lsb;
29766 UInt srcSz = msb - lsb + 33;
29767 t1 = newTemp(ty);
29768 t2 = newTemp(ty);
29769 t3 = newTemp(ty);
29770 t4 = newTemp(ty);
29771 IRTemp tmpT1 = newTemp(ty);
29772 IRTemp tmpT2 = newTemp(ty);
29773 IRTemp tmpT3 = newTemp(ty);
29774 IRTemp tmpT4 = newTemp(ty);
29775 IRTemp tmpT5 = newTemp(ty);
29776 IRTemp tmpT6 = newTemp(ty);
29777 IRTemp tmpT7 = newTemp(ty);
29778 IRTemp tmpRs = newTemp(ty);
29779 IRTemp tmpRt = newTemp(ty);
29780 IRTemp tmpRd = newTemp(ty);
29782 assign(tmpRs, getIReg(rs));
29783 assign(tmpRt, getIReg(rt));
29784 DIP("dinsm r%u, r%u, %u, %u", rt, rs, lsb, msb);
29786 UChar lsAmt = dstPos + srcSz - 1; /* left shift amount; */
29787 UChar rsAmt = dstPos + srcSz - 1; /* right shift amount; */
29789 assign(t1, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
29790 assign(tmpT1, binop(Iop_Shr64, mkexpr(t1), mkU8(1)));
29791 assign(t2, binop(Iop_Shl64, mkexpr(tmpT1), mkU8(lsAmt)));
29792 assign(tmpT2, binop(Iop_Shl64, mkexpr(t2), mkU8(1)));
29794 lsAmt = 63 - dstPos; /* left shift amount; */
29795 rsAmt = 63 - dstPos; /* right shift amount; */
29797 assign(t3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
29798 assign(tmpT3, binop(Iop_Shl64, mkexpr(t3), mkU8(1)));
29799 assign(t4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
29800 assign(tmpT4, binop(Iop_Shr64, mkexpr(t4), mkU8(1)));
29802 /* extract size from src register */
29803 lsAmt = 64 - srcSz; /* left shift amount; */
29804 rsAmt = 64 - (lsb + srcSz); /* right shift amount; */
29806 assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
29807 assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(rsAmt)));
29809 assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT4)));
29810 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT7)));
29811 putIReg(rt, mkexpr(tmpRd));
29812 break;
29814 case 0x06: {
29815 /* Doubleword Insert Bit Field Upper - DINSU; MIPS64r2 */
29816 msb = get_msb(cins);
29817 lsb = get_lsb(cins);
29818 size = msb + 1;
29819 UInt dstPos = lsb + 32;
29820 UInt srcSz = msb - lsb + 1;
29821 IRTemp tmpT1 = newTemp(ty);
29822 IRTemp tmpT2 = newTemp(ty);
29823 IRTemp tmpT3 = newTemp(ty);
29824 IRTemp tmpT4 = newTemp(ty);
29825 IRTemp tmpT5 = newTemp(ty);
29826 IRTemp tmpT6 = newTemp(ty);
29827 IRTemp tmpT7 = newTemp(ty);
29828 IRTemp tmpT8 = newTemp(ty);
29829 IRTemp tmpT9 = newTemp(ty);
29830 IRTemp tmpRs = newTemp(ty);
29831 IRTemp tmpRt = newTemp(ty);
29832 IRTemp tmpRd = newTemp(ty);
29834 assign(tmpRs, getIReg(rs));
29835 assign(tmpRt, getIReg(rt));
29836 DIP("dinsu r%u, r%u, %u, %u", rt, rs, lsb, msb);
29838 UChar lsAmt = 64 - srcSz; /* left shift amount; */
29839 UChar rsAmt = 64 - (dstPos + srcSz); /* right shift amount; */
29840 assign(tmpT1, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
29841 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
29843 lsAmt = 64 - dstPos; /* left shift amount; */
29844 rsAmt = 64 - dstPos; /* right shift amount; */
29845 assign(tmpT3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
29846 assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
29848 lsAmt = dstPos; /* left shift amount; */
29849 rsAmt = srcSz; /* right shift amount; */
29850 assign(tmpT5, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
29851 assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(lsAmt)));
29853 assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpT6), mkU8(rsAmt)));
29854 assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(lsAmt)));
29856 assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT4)));
29857 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT9)));
29858 putIReg(rt, mkexpr(tmpRd));
29859 break;
29861 case 0x07: {
29862 /* Doubleword Insert Bit Field - DINS; MIPS64r2 */
29863 IRTemp tmp1 = newTemp(ty);
29864 IRTemp tmpT1 = newTemp(ty);
29865 IRTemp tmpT2 = newTemp(ty);
29866 IRTemp tmpT3 = newTemp(ty);
29867 IRTemp tmpT4 = newTemp(ty);
29868 IRTemp tmpT5 = newTemp(ty);
29869 IRTemp tmpT6 = newTemp(ty);
29870 IRTemp tmpT7 = newTemp(ty);
29871 IRTemp tmpT8 = newTemp(ty);
29872 IRTemp tmpT9 = newTemp(ty);
29873 IRTemp tmp = newTemp(ty);
29874 IRTemp tmpRs = newTemp(ty);
29875 IRTemp tmpRt = newTemp(ty);
29876 IRTemp tmpRd = newTemp(ty);
29878 assign(tmpRs, getIReg(rs));
29879 assign(tmpRt, getIReg(rt));
29881 msb = get_msb(cins);
29882 lsb = get_lsb(cins);
29883 size = msb + 1;
29884 DIP("dins r%u, r%u, %u, %u", rt, rs, lsb,
29885 msb - lsb + 1);
29886 UChar lsAmt = 63 - lsb; /* left shift amount; */
29887 UChar rsAmt = 63 - lsb; /* right shift amount; */
29888 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
29889 assign(tmpT1, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
29890 assign(tmp1, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
29891 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmp1), mkU8(1)));
29893 lsAmt = msb; /* left shift amount; */
29894 rsAmt = 1; /*right shift amount; */
29895 assign(tmpT3, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
29896 assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(lsAmt)));
29897 assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpT4), mkU8(rsAmt)));
29898 assign(tmpT6, binop(Iop_Shl64, mkexpr(tmpT5), mkU8(lsAmt)));
29900 lsAmt = 64 - (msb - lsb + 1); /* left shift amount; */
29901 rsAmt = 64 - (msb + 1); /* right shift amount; */
29902 assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
29903 assign(tmpT8, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(rsAmt)));
29905 assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT8)));
29906 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT9)));
29907 putIReg(rt, mkexpr(tmpRd));
29908 break;
29910 case 0x24: /* DBSHFL */
29911 lsb = get_lsb(cins);
29912 IRTemp tmpRs = newTemp(ty);
29913 IRTemp tmpRt = newTemp(ty);
29914 IRTemp tmpRd = newTemp(ty);
29915 assign(tmpRs, getIReg(rs));
29916 assign(tmpRt, getIReg(rt));
29917 switch (lsb) {
29918 case 0x02: { /* DSBH */
29919 DIP("dsbh r%u, r%u", rd, rt);
29920 IRTemp tmpT1 = newTemp(ty);
29921 IRTemp tmpT2 = newTemp(ty);
29922 IRTemp tmpT3 = newTemp(ty);
29923 IRTemp tmpT4 = newTemp(ty);
29924 IRTemp tmpT5 = newTemp(Ity_I64);
29925 IRTemp tmpT6 = newTemp(ty);
29926 assign(tmpT5, mkU64(0xFF00FF00FF00FF00ULL));
29927 assign(tmpT6, mkU64(0x00FF00FF00FF00FFULL));
29928 assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
29929 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(8)));
29930 assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
29931 assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(8)));
29932 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
29933 putIReg(rd, mkexpr(tmpRd));
29934 break;
29936 case 0x05: { /* DSHD */
29937 DIP("dshd r%u, r%u\n", rd, rt);
29938 IRTemp tmpT1 = newTemp(ty);
29939 IRTemp tmpT2 = newTemp(ty);
29940 IRTemp tmpT3 = newTemp(ty);
29941 IRTemp tmpT4 = newTemp(ty);
29942 IRTemp tmpT5 = newTemp(Ity_I64);
29943 IRTemp tmpT6 = newTemp(ty);
29944 IRTemp tmpT7 = newTemp(ty);
29945 IRTemp tmpT8 = newTemp(ty);
29946 IRTemp tmpT9 = newTemp(ty);
29947 assign(tmpT5, mkU64(0xFFFF0000FFFF0000ULL));
29948 assign(tmpT6, mkU64(0x0000FFFF0000FFFFULL));
29949 assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
29950 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(16)));
29951 assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
29952 assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(16)));
29953 assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
29954 assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(32)));
29955 assign(tmpT9, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(32)));
29956 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT9)));
29957 putIReg(rd, mkexpr(tmpRd));
29958 break;
29960 case 0x08 ... 0x0f: { /* DALIGN */
29961 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
29962 DIP("daling r%u, r%u, r%u, %d", rd, rs, rt, lsb & 0x7);
29963 UInt bp = (lsb & 0x7) << 3;
29964 if (bp) {
29965 putIReg(rd, binop(Iop_Or64,
29966 binop(Iop_Shl64, getIReg(rt), mkU8(bp)),
29967 binop(Iop_Shr64,
29968 getIReg(rs), mkU8(64 - bp))));
29969 } else
29970 putIReg(rd, getIReg(rt));
29971 } else {
29972 ILLEGAL_INSTRUCTON;
29974 break;
29977 case 0: /* DBITSWAP */
29978 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
29979 DIP("dbitswap r%u, r%u", rd, rt);
29980 putIReg(rd, qop(Iop_Rotx64, getIReg(rt), mkU8(7), mkU8(8), mkU8(1)));
29981 } else {
29982 ILLEGAL_INSTRUCTON;
29984 break;
29985 default:
29986 vex_printf("\nop6o10 = %u", lsb);
29987 goto decode_failure;;
29989 break;
29990 case 0x3B: /* RDHWR */
29991 DIP("rdhwr r%u, r%u", rt, rd);
29992 if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
29993 VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) ||
29994 (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) {
29995 if (rd == 29) {
29996 putIReg(rt, getULR());
29997 } else if (rd <= 3
29998 || (rd == 31
29999 && VEX_MIPS_COMP_ID(archinfo->hwcaps)
30000 == VEX_PRID_COMP_CAVIUM)) {
30001 IRExpr** arg = mkIRExprVec_1(mkU32(rd));
30002 IRTemp val = newTemp(ty);
30003 IRDirty *d = unsafeIRDirty_1_N(val,
30005 "mips_dirtyhelper_rdhwr",
30006 &mips_dirtyhelper_rdhwr,
30007 arg);
30008 stmt(IRStmt_Dirty(d));
30009 putIReg(rt, mkexpr(val));
30010 } else
30011 goto decode_failure;
30012 } else {
30013 ILLEGAL_INSTRUCTON;
30015 break;
30016 case 0x04: /* INS */
30017 msb = get_msb(cins);
30018 lsb = get_lsb(cins);
30019 size = msb - lsb + 1;
30020 DIP("ins size:%u msb:%u lsb:%u", size, msb, lsb);
30022 vassert(lsb + size <= 32);
30023 vassert(lsb + size > 0);
30025 /* put size bits from rs at the pos in temporary */
30026 t0 = newTemp(Ity_I32);
30027 t3 = newTemp(Ity_I32);
30028 /* shift left for 32 - size to clear leading bits and get zeros
30029 at the end */
30030 assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
30031 mkU8(32 - size)));
30032 /* now set it at pos */
30033 t1 = newTemp(Ity_I32);
30034 assign(t1, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size - lsb)));
30036 if (lsb > 0) {
30037 t2 = newTemp(Ity_I32);
30038 /* clear everything but lower pos bits from rt */
30039 assign(t2, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rt)),
30040 mkU8(32 - lsb)));
30041 assign(t3, binop(Iop_Shr32, mkexpr(t2), mkU8(32 - lsb)));
30042 } else
30043 assign(t3, mkU32(0));
30045 if (msb < 31) {
30046 t4 = newTemp(Ity_I32);
30047 /* clear everything but upper msb + 1 bits from rt */
30048 assign(t4, binop(Iop_Shr32, mkNarrowTo32(ty, getIReg(rt)),
30049 mkU8(msb + 1)));
30050 t5 = newTemp(Ity_I32);
30051 assign(t5, binop(Iop_Shl32, mkexpr(t4), mkU8(msb + 1)));
30053 /* now combine these registers */
30054 if (lsb > 0) {
30055 t6 = newTemp(Ity_I32);
30056 assign(t6, binop(Iop_Or32, mkexpr(t5), mkexpr(t1)));
30057 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t6),
30058 mkexpr(t3)), True));
30059 } else {
30060 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
30061 mkexpr(t5)), True));
30063 } else {
30064 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
30065 mkexpr(t3)), True));
30067 break;
30069 case 0x00: /* EXT */
30070 msb = get_msb(cins);
30071 lsb = get_lsb(cins);
30072 size = msb + 1;
30073 DIP("ext size:%u msb:%u lsb:%u", size, msb, lsb);
30074 vassert(lsb + size <= 32);
30075 vassert(lsb + size > 0);
30076 /* put size bits from rs at the top of in temporary */
30077 if (lsb + size < 32) {
30078 t0 = newTemp(Ity_I32);
30079 assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
30080 mkU8(32 - lsb - size)));
30082 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32, mkexpr(t0),
30083 mkU8(32 - size)), True));
30084 } else {
30085 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32,
30086 mkNarrowTo32(ty, getIReg(rs)),
30087 mkU8(32 - size)), True));
30089 break;
30091 case 0x03: /* Doubleword Extract Bit Field - DEXT; MIPS64r2 */
30092 msb = get_msb(cins);
30093 lsb = get_lsb(cins);
30094 size = msb + 1;
30095 DIP("dext r%u, r%u, %u, %u", rt, rs, lsb, msb + 1);
30096 t1 = newTemp(Ity_I64);
30097 vassert(lsb >= 0 && lsb < 32);
30098 vassert(size > 0 && size <= 32);
30099 vassert((lsb + size) > 0 && (lsb + size) <= 63);
30101 UChar lsAmt = 63 - (lsb + msb); /* left shift amount; */
30102 UChar rsAmt = 63 - msb; /* right shift amount; */
30104 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
30105 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
30107 break;
30109 case 0x20: /* BSHFL */
30110 switch (sa) {
30111 case 0x0: /* BITSWAP */
30112 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30113 DIP("bitswap r%u, r%u", rd, rt);
30114 if (mode64) {
30115 putIReg(rd, unop(Iop_32Uto64, qop(Iop_Rotx32, unop(Iop_64to32, getIReg(rt)),
30116 mkU8(7), mkU8(8), mkU8(1))));
30117 } else {
30118 putIReg(rd, qop(Iop_Rotx32, getIReg(rt), mkU8(7),
30119 mkU8(8), mkU8(1)));
30121 } else {
30122 ILLEGAL_INSTRUCTON;
30124 break;
30126 case 0x02: /* WSBH */
30127 DIP("wsbh r%u, r%u", rd, rt);
30128 t0 = newTemp(Ity_I32);
30129 t1 = newTemp(Ity_I32);
30130 t2 = newTemp(Ity_I32);
30131 t3 = newTemp(Ity_I32);
30132 assign(t0, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
30133 getIReg(rt)), mkU32(0x00FF0000)),
30134 mkU8(0x8)));
30135 assign(t1, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
30136 getIReg(rt)), mkU32(0xFF000000)), mkU8(0x8)));
30137 assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
30138 getIReg(rt)), mkU32(0x000000FF)), mkU8(0x8)));
30139 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
30140 getIReg(rt)), mkU32(0x0000FF00)), mkU8(0x8)));
30141 putIReg(rd, mkWidenFrom32(ty, binop(Iop_Or32, binop(Iop_Or32,
30142 mkexpr(t0), mkexpr(t1)),
30143 binop(Iop_Or32, mkexpr(t2),
30144 mkexpr(t3))), True));
30145 break;
30147 case 0x10: /* SEB */
30148 DIP("seb r%u, r%u", rd, rt);
30149 if (mode64)
30150 putIReg(rd, unop(Iop_8Sto64, unop(Iop_64to8, getIReg(rt))));
30151 else
30152 putIReg(rd, unop(Iop_8Sto32, unop(Iop_32to8, getIReg(rt))));
30153 break;
30155 case 0x18: /* SEH */
30156 DIP("seh r%u, r%u", rd, rt);
30157 if (mode64)
30158 putIReg(rd, unop(Iop_16Sto64, unop(Iop_64to16, getIReg(rt))));
30159 else
30160 putIReg(rd, unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
30161 break;
30163 case 0x08 ... 0x0b: /* ALIGN */
30164 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30165 if (mode64) {
30166 UInt bp = (sa & 0x3) << 3;
30167 if (bp) {
30168 putIReg(rd, unop(Iop_32Sto64,
30169 binop(Iop_Or32,
30170 binop(Iop_Shl32,
30171 unop(Iop_64to32,
30172 getIReg(rt)),
30173 mkU8(bp)),
30174 binop(Iop_Shr32,
30175 unop(Iop_64to32,
30176 getIReg(rs)),
30177 mkU8(32 - bp)))));
30178 } else
30179 putIReg(rd, getIReg(rt));
30180 } else {
30181 UInt bp = (sa & 0x3) << 3;
30182 if (bp) {
30183 putIReg(rd, binop(Iop_Or32,
30184 binop(Iop_Shl32,
30185 getIReg(rt), mkU8(bp)),
30186 binop(Iop_Shr32,
30187 getIReg(rs), mkU8(32 - bp))));
30188 } else
30189 putIReg(rd, getIReg(rt));
30191 } else {
30192 ILLEGAL_INSTRUCTON;
30194 break;
30196 default:
30197 goto decode_failure;
30200 break; /* BSHFL */
30202 /* --- MIPS32(r2) DSP ASE(r2) / Cavium Specfic (LX) instructions --- */
30203 case 0xA: /* LX */
30204 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
30205 if (dis_instr_CVM(cins))
30206 break;
30207 goto decode_failure;
30209 case 0xC: /* INSV */
30210 case 0x38: { /* EXTR.W */
30211 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
30212 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
30213 if (0 != retVal ) {
30214 goto decode_failure_dsp;
30216 break;
30217 } else {
30218 goto decode_failure_dsp;
30220 break;
30222 case 0x10: { /* ADDU.QB */
30223 switch(sa) {
30224 case 0xC: /* SUBU_S.PH */
30225 case 0xD: /* ADDU_S.PH */
30226 case 0x1E: { /* MULQ_S.PH */
30227 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
30228 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
30229 if (0 != retVal ) {
30230 goto decode_failure_dsp;
30232 break;
30233 } else {
30234 goto decode_failure_dsp;
30236 break;
30238 default: {
30239 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
30240 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
30241 if (0 != retVal ) {
30242 goto decode_failure_dsp;
30244 break;
30245 } else {
30246 goto decode_failure_dsp;
30248 break;
30251 break;
30253 case 0x11: { /* CMPU.EQ.QB */
30254 switch(sa) {
30255 case 0x18: /* CMPGDU.EQ.QB */
30256 case 0x19: /* CMPGDU.LT.QB */
30257 case 0x1A: /* CMPGDU.LE.QB */
30258 case 0x0D: /* PRECR.QB.PH */
30259 case 0x1E: /* PRECR_SRA.PH.W */
30260 case 0x1F: { /* PRECR_SRA_R.PH.W */
30261 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
30262 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
30263 if (0 != retVal ) {
30264 goto decode_failure_dsp;
30266 break;
30267 } else {
30268 goto decode_failure_dsp;
30270 break;
30272 default: {
30273 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
30274 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
30275 if (0 != retVal ) {
30276 goto decode_failure_dsp;
30278 break;
30279 } else {
30280 goto decode_failure_dsp;
30282 break;
30285 break;
30287 case 0x12: { /* ABSQ_S.PH */
30288 switch(sa){
30289 case 0x1: { /* ABSQ_S.QB */
30290 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
30291 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
30292 if (0 != retVal ) {
30293 goto decode_failure_dsp;
30295 break;
30296 } else {
30297 goto decode_failure_dsp;
30299 break;
30301 default: {
30302 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
30303 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
30304 if (0 != retVal ) {
30305 goto decode_failure_dsp;
30307 break;
30308 } else {
30309 goto decode_failure_dsp;
30311 break;
30314 break;
30316 case 0x13: { /* SHLL.QB */
30317 switch(sa) {
30318 case 0x04: /* SHRA.QB */
30319 case 0x05: /* SHRA_R.QB */
30320 case 0x06: /* SHRAV.QB */
30321 case 0x07: /* SHRAV_R.QB */
30322 case 0x19: /* SHLR.PH */
30323 case 0x1B: { /* SHLRV.PH */
30324 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
30325 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
30326 if (0 != retVal ) {
30327 goto decode_failure_dsp;
30329 break;
30330 } else {
30331 goto decode_failure_dsp;
30333 break;
30335 default: {
30336 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
30337 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
30338 if (0 != retVal ) {
30339 goto decode_failure_dsp;
30341 break;
30342 } else {
30343 goto decode_failure_dsp;
30345 break;
30348 break;
30350 case 0x30: { /* DPAQ.W.PH */
30351 switch(sa) {
30352 case 0x0: /* DPA.W.PH */
30353 case 0x18: /* DPAQX_S.W.PH */
30354 case 0x1A: /* DPAQX_SA.W.PH */
30355 case 0x8: /* DPAX.W.PH */
30356 case 0x1: /* DPS.W.PH */
30357 case 0x19: /* DPSQX_S.W.PH */
30358 case 0x1B: /* DPSQX_SA.W.PH */
30359 case 0x9: /* DPSX.W.PH */
30360 case 0x2: { /* MULSA.W.PH */
30361 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
30362 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
30363 if (0 != retVal ) {
30364 goto decode_failure_dsp;
30366 break;
30367 } else {
30368 goto decode_failure_dsp;
30370 break;
30372 default: {
30373 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
30374 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
30375 if (0 != retVal ) {
30376 goto decode_failure_dsp;
30378 break;
30379 } else {
30380 goto decode_failure_dsp;
30382 break;
30385 break;
30387 case 0x18: /* ADDUH.QB/MUL.PH */
30388 case 0x31: { /* APPEND */
30389 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
30390 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
30391 if (0 != retVal ) {
30392 goto decode_failure_dsp;
30394 break;
30395 } else {
30396 goto decode_failure_dsp;
30399 case 0x35: { /* PREF r6*/
30400 DIP("pref");
30401 break;
30403 case 0x36: { /* LL */
30404 imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
30405 DIP("ll r%u, %u(r%u)", rt, imm, rs);
30406 LOAD_STORE_PATTERN;
30407 t2 = newTemp(ty);
30408 assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
30409 putLLaddr(mkexpr(t1));
30410 putLLdata(mkexpr(t2));
30411 putIReg(rt, mkexpr(t2));
30412 break;
30414 case 0x26: { /* SC */
30415 imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
30416 DIP("sc r%u, %u(r%u)", rt, imm, rs);
30417 LOAD_STORE_PATTERN;
30419 t2 = newTemp(Ity_I1);
30420 t3 = newTemp(Ity_I32);
30421 assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
30422 mkexpr(t1), getLLaddr()));
30423 assign(t3, mkNarrowTo32(ty, getIReg(rt)));
30424 putLLaddr(LLADDR_INVALID);
30425 putIReg(rt, getIReg(0));
30427 mips_next_insn_if(mkexpr(t2));
30429 t4 = newTemp(Ity_I32);
30430 t5 = newTemp(Ity_I32);
30432 assign(t5, mkNarrowTo32(ty, getLLdata()));
30434 stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
30435 MIPS_IEND, mkexpr(t1), /* addr */
30436 NULL, mkexpr(t5), /* expected value */
30437 NULL, mkexpr(t3) /* new value */)));
30439 putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32,
30440 binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5))));
30441 break;
30443 case 0x37: { /* LLD */
30444 imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
30445 DIP("lld r%u, %u(r%u)", rt, imm, rs);
30446 LOAD_STORE_PATTERN;
30448 t2 = newTemp(Ity_I64);
30449 assign(t2, load(Ity_I64, mkexpr(t1)));
30450 putLLaddr(mkexpr(t1));
30451 putLLdata(mkexpr(t2));
30452 putIReg(rt, mkexpr(t2));
30453 break;
30455 case 0x27: { /* SCD */
30456 imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
30457 DIP("sdc r%u, %u(r%u)", rt, imm, rs);
30458 LOAD_STORE_PATTERN;
30460 t2 = newTemp(Ity_I1);
30461 t3 = newTemp(Ity_I64);
30462 assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr()));
30463 assign(t3, getIReg(rt));
30464 putLLaddr(LLADDR_INVALID);
30465 putIReg(rt, getIReg(0));
30467 mips_next_insn_if(mkexpr(t2));
30469 t4 = newTemp(Ity_I64);
30470 t5 = newTemp(Ity_I64);
30472 assign(t5, getLLdata());
30474 stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
30475 MIPS_IEND, mkexpr(t1), /* addr */
30476 NULL, mkexpr(t5), /* expected value */
30477 NULL, mkexpr(t3) /* new value */)));
30479 putIReg(rt, unop(Iop_1Uto64,
30480 binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5))));
30481 break;
30483 default:
30484 goto decode_failure;
30487 break; /* Special3 */
30489 case 0x3B: /* PCREL */
30490 if (rt == 0x1E) { /* AUIPC */
30491 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30492 DIP("auipc r%u, %u", rs, imm);
30493 if (mode64) {
30494 putIReg(rs, mkU64(guest_PC_curr_instr + (imm << 16)));
30495 } else {
30496 putIReg(rs, mkU32(guest_PC_curr_instr + (imm << 16)));
30498 } else {
30499 ILLEGAL_INSTRUCTON;
30501 break;
30502 } else if (rt == 0x1F) { /* ALUIPC */
30503 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30504 DIP("aluipc r%u, %u", rs, imm);
30505 if (mode64) {
30506 putIReg(rs, mkU64((~0x0FFFFULL) &
30507 (guest_PC_curr_instr + extend_s_32to64(imm << 16))));
30508 } else {
30509 putIReg(rs, mkU32((~0x0FFFFULL) &
30510 (guest_PC_curr_instr + (imm << 16))));
30512 } else {
30513 ILLEGAL_INSTRUCTON;
30515 break;
30516 } else if ((rt & 0x18) == 0) { /* ADDIUPC */
30517 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30518 DIP("addiupc r%u, %u", rs, instr_index & 0x7FFFF);
30519 if (mode64) {
30520 putIReg(rs, mkU64(guest_PC_curr_instr +
30521 (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
30522 } else {
30523 putIReg(rs, mkU32(guest_PC_curr_instr +
30524 (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
30526 } else {
30527 ILLEGAL_INSTRUCTON;
30529 break;
30530 } else if ((rt & 0x18) == 8) { /* LWPC */
30531 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30532 DIP("lwpc r%u, %x", rs, instr_index & 0x7FFFF);
30533 if (mode64) {
30534 t1 = newTemp(Ity_I64);
30535 assign(t1, mkU64(guest_PC_curr_instr +
30536 (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
30537 putIReg(rs, unop(Iop_32Sto64, load(Ity_I32, mkexpr(t1))));
30538 } else {
30539 t1 = newTemp(Ity_I32);
30540 assign(t1, mkU32(guest_PC_curr_instr +
30541 (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
30542 putIReg(rs, load(Ity_I32, mkexpr(t1)));
30544 } else {
30545 ILLEGAL_INSTRUCTON;
30547 break;
30548 } else if ((rt & 0x18) == 16) { /* LWUPC */
30549 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30550 DIP("lwupc r%u, %x", rs, instr_index & 0x7FFFF);
30551 if (mode64) {
30552 t1 = newTemp(Ity_I64);
30553 assign(t1, mkU64(guest_PC_curr_instr +
30554 (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
30555 putIReg(rs, unop(Iop_32Uto64, load(Ity_I32, mkexpr(t1))));
30556 } else {
30557 t1 = newTemp(Ity_I32);
30558 assign(t1, mkU32(guest_PC_curr_instr +
30559 (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
30560 putIReg(rs, load(Ity_I32, mkexpr(t1)));
30562 } else {
30563 ILLEGAL_INSTRUCTON;
30565 break;
30566 } else if ((rt & 0x1C) == 0x18) { /* LDPC */
30567 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30568 DIP("ldpc r%u, %x", rs, instr_index & 0x3FFFF);
30569 t1 = newTemp(Ity_I64);
30570 assign(t1, mkU64(guest_PC_curr_instr +
30571 (extend_s_18to64(instr_index & 0x3FFFF) << 3)));
30572 putIReg(rs, load(Ity_I64, mkexpr(t1)));
30573 } else {
30574 ILLEGAL_INSTRUCTON;
30576 break;
30577 } else {
30578 goto decode_failure;
30581 if (0x3B == function &&
30582 (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) {
30583 /*RDHWR*/
30584 DIP("rdhwr r%u, r%u", rt, rd);
30585 if (rd == 29) {
30586 putIReg(rt, getULR());
30587 } else
30588 goto decode_failure;
30589 break;
30590 } else {
30591 goto decode_failure;
30594 case 0x00: /* Special */
30596 switch (function) {
30597 case 0x1: {
30598 UInt mov_cc = get_mov_cc(cins);
30599 if (tf == 0) { /* MOVF */
30600 DIP("movf r%u, r%u, %u", rd, rs, mov_cc);
30601 t1 = newTemp(Ity_I1);
30602 t2 = newTemp(Ity_I32);
30603 t3 = newTemp(Ity_I1);
30605 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
30606 assign(t2, IRExpr_ITE(mkexpr(t1),
30607 binop(Iop_And32,
30608 binop(Iop_Shr32, getFCSR(),
30609 mkU8(23)),
30610 mkU32(0x1)),
30611 binop(Iop_And32,
30612 binop(Iop_Shr32, getFCSR(),
30613 mkU8(24 + mov_cc)),
30614 mkU32(0x1))
30616 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
30617 putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
30618 } else if (tf == 1) { /* MOVT */
30619 DIP("movt r%u, r%u, %u", rd, rs, mov_cc);
30620 t1 = newTemp(Ity_I1);
30621 t2 = newTemp(Ity_I32);
30622 t3 = newTemp(Ity_I1);
30624 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
30625 assign(t2, IRExpr_ITE(mkexpr(t1),
30626 binop(Iop_And32,
30627 binop(Iop_Shr32, getFCSR(),
30628 mkU8(23)),
30629 mkU32(0x1)),
30630 binop(Iop_And32,
30631 binop(Iop_Shr32, getFCSR(),
30632 mkU8(24 + mov_cc)),
30633 mkU32(0x1))
30635 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
30636 putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
30638 break;
30640 case 0x0A: { /* MOVZ */
30641 DIP("movz r%u, r%u, r%u", rd, rs, rt);
30642 t1 = newTemp(ty);
30643 t2 = newTemp(ty);
30644 if (mode64) {
30645 assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
30646 getIReg(rt), mkU64(0x0)))));
30647 assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
30648 getIReg(rt), mkU64(0x0)))));
30649 putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
30650 mkexpr(t1)), binop(Iop_And64, getIReg(rd),mkexpr(t2))));
30651 } else {
30652 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
30653 mkU32(0x0))));
30654 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
30655 mkU32(0x0))));
30656 putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
30657 mkexpr(t1)), binop(Iop_And32, getIReg(rd),
30658 mkexpr(t2))));
30660 break;
30663 case 0x0B: { /* MOVN */
30664 DIP("movn r%u, r%u, r%u", rd, rs, rt);
30665 t1 = newTemp(ty);
30666 t2 = newTemp(ty);
30667 if (mode64) {
30668 assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
30669 getIReg(rt), mkU64(0x0)))));
30670 assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
30671 getIReg(rt), mkU64(0x0)))));
30672 putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
30673 mkexpr(t2)), binop(Iop_And64, getIReg(rd),
30674 mkexpr(t1))));
30675 } else {
30676 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
30677 mkU32(0x0))));
30678 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
30679 mkU32(0x0))));
30680 putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
30681 mkexpr(t2)), binop(Iop_And32, getIReg(rd),
30682 mkexpr(t1))));
30684 break;
30687 case 0x18: { /* MULT */
30688 switch (sa & 0x3) {
30689 case 0: {
30690 if ((1 <= ac) && ( 3 >= ac)) {
30691 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
30692 /* If DSP is present -> DSP ASE MULT */
30693 UInt retVal = disDSPInstr_MIPS_WRK(cins);
30694 if (0 != retVal) {
30695 goto decode_failure_dsp;
30697 break;
30698 } else {
30699 goto decode_failure_dsp;
30701 } else {
30702 DIP("mult r%u, r%u", rs, rt);
30703 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
30704 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
30705 ILLEGAL_INSTRUCTON;
30707 t2 = newTemp(Ity_I64);
30709 assign(t2, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
30710 mkNarrowTo32(ty, getIReg(rt))));
30712 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
30713 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
30714 break;
30717 case 2: { /* MUL R6 */
30718 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30719 DIP("mul r%u, r%u, r%u", rs, rt, rd);
30720 if (mode64) {
30721 putIReg(rd, unop(Iop_32Sto64,
30722 unop(Iop_64to32,
30723 binop(Iop_MullS32,
30724 unop(Iop_64to32, getIReg(rs)),
30725 unop(Iop_64to32, getIReg(rt))))));
30726 } else {
30727 putIReg(rd, unop(Iop_64to32,
30728 binop(Iop_MullS32,
30729 getIReg(rs), getIReg(rt))));
30731 } else {
30732 ILLEGAL_INSTRUCTON;
30734 break;
30737 case 3: { /* MUH R6 */
30738 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30739 DIP("muh r%u, r%u, r%u", rs, rt, rd);
30740 if (mode64) {
30741 putIReg(rd, unop(Iop_32Sto64,
30742 unop(Iop_64HIto32,
30743 binop(Iop_MullS32,
30744 unop(Iop_64to32, getIReg(rs)),
30745 unop(Iop_64to32, getIReg(rt))))));
30746 } else {
30747 putIReg(rd, unop(Iop_64HIto32,
30748 binop(Iop_MullS32,
30749 getIReg(rs), getIReg(rt))));
30751 } else {
30752 ILLEGAL_INSTRUCTON;
30754 break;
30757 break;
30760 case 0x19: { /* MULTU */
30761 switch (sa & 0x3) {
30762 case 0: {
30763 if ((1 <= ac) && ( 3 >= ac)) {
30764 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
30765 /* If DSP is present -> DSP ASE MULTU */
30766 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
30767 if (0 != retVal) {
30768 goto decode_failure_dsp;
30770 break;
30771 } else {
30772 goto decode_failure_dsp;
30774 } else {
30775 DIP("multu r%u, r%u", rs, rt);
30776 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
30777 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
30778 ILLEGAL_INSTRUCTON;
30780 t2 = newTemp(Ity_I64);
30782 assign(t2, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
30783 mkNarrowTo32(ty, getIReg(rt))));
30785 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
30786 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
30787 break;
30790 case 2: { /* MULU R6 */
30791 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30792 DIP("mulu r%u, r%u, r%u", rs, rt, rd);
30793 if (mode64) {
30794 putIReg(rd, unop(Iop_32Uto64,
30795 unop(Iop_64to32,
30796 binop(Iop_MullU32,
30797 unop(Iop_64to32, getIReg(rs)),
30798 unop(Iop_64to32, getIReg(rt))))));
30799 } else {
30800 putIReg(rd, unop(Iop_64to32,
30801 binop(Iop_MullU32,
30802 getIReg(rs), getIReg(rt))));
30804 } else {
30805 ILLEGAL_INSTRUCTON;
30807 break;
30809 case 3: { /* MUHU R6 */
30810 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30811 DIP("muhu r%u, r%u, r%u", rs, rt, rd);
30812 if (mode64) {
30813 putIReg(rd, unop(Iop_32Uto64,
30814 unop(Iop_64HIto32,
30815 binop(Iop_MullU32,
30816 unop(Iop_64to32, getIReg(rs)),
30817 unop(Iop_64to32, getIReg(rt))))));
30818 } else {
30819 putIReg(rd, unop(Iop_64HIto32,
30820 binop(Iop_MullU32,
30821 getIReg(rs), getIReg(rt))));
30823 } else {
30824 ILLEGAL_INSTRUCTON;
30826 break;
30830 break;
30832 case 0x20: { /* ADD */
30833 DIP("add r%u, r%u, r%u", rd, rs, rt);
30834 IRTemp tmpRs32 = newTemp(Ity_I32);
30835 IRTemp tmpRt32 = newTemp(Ity_I32);
30837 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
30838 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
30840 t0 = newTemp(Ity_I32);
30841 t1 = newTemp(Ity_I32);
30842 t2 = newTemp(Ity_I32);
30843 t3 = newTemp(Ity_I32);
30844 t4 = newTemp(Ity_I32);
30845 /* dst = src0 + src1
30846 if (sign(src0 ) != sign(src1 ))
30847 goto no overflow;
30848 if (sign(dst) == sign(src0 ))
30849 goto no overflow;
30850 we have overflow! */
30852 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
30853 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
30854 assign(t2, unop(Iop_1Uto32,
30855 binop(Iop_CmpEQ32,
30856 binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
30857 mkU32(0x80000000))));
30859 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
30860 assign(t4, unop(Iop_1Uto32,
30861 binop(Iop_CmpNE32,
30862 binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
30863 mkU32(0x80000000))));
30865 stmt(IRStmt_Exit(binop(Iop_CmpEQ32,
30866 binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
30867 mkU32(0)),
30868 Ijk_SigFPE_IntOvf,
30869 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
30870 IRConst_U32(guest_PC_curr_instr + 4),
30871 OFFB_PC));
30873 putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True));
30874 break;
30877 case 0x1A: /* DIV */
30878 switch (sa & 0x3) {
30879 case 0:
30880 DIP("div r%u, r%u", rs, rt);
30881 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
30882 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
30883 ILLEGAL_INSTRUCTON;
30885 if (mode64) {
30886 t2 = newTemp(Ity_I64);
30888 assign(t2, binop(Iop_DivModS32to32,
30889 mkNarrowTo32(ty, getIReg(rs)),
30890 mkNarrowTo32(ty, getIReg(rt))));
30892 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
30893 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
30894 } else {
30895 t1 = newTemp(Ity_I64);
30897 assign(t1, binop(Iop_DivModS32to32, getIReg(rs), getIReg(rt)));
30899 putHI(unop(Iop_64HIto32, mkexpr(t1)));
30900 putLO(unop(Iop_64to32, mkexpr(t1)));
30902 break;
30903 case 2:
30904 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30905 DIP("div r%u, r%u, r%u", rs, rt, rd);
30906 if (mode64) {
30907 putIReg(rd, unop(Iop_32Sto64,
30908 binop(Iop_DivS32,
30909 unop(Iop_64to32, getIReg(rs)),
30910 unop(Iop_64to32, getIReg(rt)))));
30911 } else
30912 putIReg(rd, binop(Iop_DivS32, getIReg(rs), getIReg(rt)));
30913 } else {
30914 ILLEGAL_INSTRUCTON;
30916 break;
30917 case 3:
30918 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30919 DIP("mod r%u, r%u, r%u", rs, rt, rd);
30920 if (mode64) {
30921 putIReg(rd, unop(Iop_32Sto64,
30922 unop(Iop_64HIto32,
30923 binop(Iop_DivModS32to32,
30924 unop(Iop_64to32, getIReg(rs)),
30925 unop(Iop_64to32, getIReg(rt))))));
30926 } else {
30927 t1 = newTemp(Ity_I64);
30929 assign(t1, binop(Iop_DivModS32to32, getIReg(rs), getIReg(rt)));
30930 putIReg(rd, unop(Iop_64HIto32, mkexpr(t1)));
30932 } else {
30933 ILLEGAL_INSTRUCTON;
30935 break;
30937 break;
30939 case 0x1B: /* DIVU */
30940 switch (sa & 0x3) {
30941 case 0:
30942 DIP("divu r%u, r%u", rs, rt);
30943 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
30944 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
30945 ILLEGAL_INSTRUCTON;
30947 if (mode64) {
30948 t1 = newTemp(Ity_I64);
30950 assign(t1, binop(Iop_DivModU32to32,
30951 mkNarrowTo32(ty, getIReg(rs)),
30952 mkNarrowTo32(ty, getIReg(rt))));
30954 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t1)), True));
30955 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t1)), True));
30956 } else {
30957 t1 = newTemp(Ity_I64);
30959 assign(t1, binop(Iop_DivModU32to32, getIReg(rs), getIReg(rt)));
30960 putHI(unop(Iop_64HIto32, mkexpr(t1)));
30961 putLO(unop(Iop_64to32, mkexpr(t1)));
30963 break;
30964 case 2:
30965 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30966 DIP("divu r%u, r%u, r%u", rs, rt, rd);
30967 if (mode64) {
30968 putIReg(rd, unop(Iop_32Sto64,
30969 binop(Iop_DivU32,
30970 unop(Iop_64to32, getIReg(rs)),
30971 unop(Iop_64to32, getIReg(rt)))));
30972 } else {
30973 putIReg(rd, binop(Iop_DivU32, getIReg(rs), getIReg(rt)));
30975 break;
30976 } else {
30977 ILLEGAL_INSTRUCTON;
30979 break;
30980 case 3:
30981 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
30982 DIP("modu r%u, r%u, r%u", rs, rt, rd);
30983 if (mode64) {
30984 putIReg(rd, unop(Iop_32Uto64,
30985 unop(Iop_64HIto32,
30986 binop(Iop_DivModU32to32,
30987 unop(Iop_64to32, getIReg(rs)),
30988 unop(Iop_64to32, getIReg(rt))))));
30989 } else {
30990 t1 = newTemp(Ity_I64);
30992 assign(t1, binop(Iop_DivModU32to32, getIReg(rs), getIReg(rt)));
30993 putIReg(rd, unop(Iop_64HIto32, mkexpr(t1)));
30995 } else {
30996 ILLEGAL_INSTRUCTON;
30998 break;
31000 break;
31002 case 0x1C: /* Doubleword Multiply - DMULT; MIPS64 */
31003 switch (sa) {
31004 case 0:
31005 DIP("dmult r%u, r%u", rs, rt);
31006 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
31007 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
31008 ILLEGAL_INSTRUCTON;
31010 t0 = newTemp(Ity_I128);
31012 assign(t0, binop(Iop_MullS64, getIReg(rs), getIReg(rt)));
31014 putHI(unop(Iop_128HIto64, mkexpr(t0)));
31015 putLO(unop(Iop_128to64, mkexpr(t0)));
31016 break;
31017 case 2: /* DMUL */
31018 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
31019 DIP("dmul r%u, r%u, r%u", rd, rs, rt);
31020 putIReg(rd, unop(Iop_128to64,
31021 binop(Iop_MullS64, getIReg(rs), getIReg(rt))));
31022 } else {
31023 ILLEGAL_INSTRUCTON;
31025 /* Value for function in documentation is 111000 */
31026 break;
31027 case 3: /* DMUH */
31028 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
31029 DIP("dmuh r%u, r%u, r%u", rd, rs, rt);
31030 putIReg(rd, unop(Iop_128HIto64,
31031 binop(Iop_MullS64, getIReg(rs), getIReg(rt))));
31032 } else {
31033 ILLEGAL_INSTRUCTON;
31035 break;
31037 break;
31039 case 0x1D: /* Doubleword Multiply Unsigned - DMULTU; MIPS64 */
31040 switch (sa) {
31041 case 0:
31042 DIP("dmultu r%u, r%u", rs, rt);
31043 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
31044 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
31045 ILLEGAL_INSTRUCTON;
31047 t0 = newTemp(Ity_I128);
31049 assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
31051 putHI(unop(Iop_128HIto64, mkexpr(t0)));
31052 putLO(unop(Iop_128to64, mkexpr(t0)));
31053 break;
31054 case 2: /* DMULU */
31055 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
31056 DIP("dmulu r%u, r%u, r%u", rd, rs, rt);
31057 putIReg(rd, unop(Iop_128to64,
31058 binop(Iop_MullU64, getIReg(rs), getIReg(rt))));
31059 } else {
31060 ILLEGAL_INSTRUCTON;
31062 break;
31063 case 3: /* DMUHU */
31064 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
31065 DIP("dmuhu r%u, r%u, r%u", rd, rs, rt);
31066 putIReg(rd, unop(Iop_128HIto64,
31067 binop(Iop_MullU64, getIReg(rs), getIReg(rt))));
31068 } else {
31069 ILLEGAL_INSTRUCTON;
31071 break;
31073 break;
31075 case 0x1E: /* Doubleword Divide DDIV; MIPS64 */
31076 switch (sa) {
31077 case 0:
31078 DIP("ddiv r%u, r%u", rs, rt);
31079 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
31080 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
31081 ILLEGAL_INSTRUCTON;
31083 t1 = newTemp(Ity_I128);
31085 assign(t1, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt)));
31087 putHI(unop(Iop_128HIto64, mkexpr(t1)));
31088 putLO(unop(Iop_128to64, mkexpr(t1)));
31089 break;
31090 case 2: /* DDIV r6 */
31091 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
31092 DIP("ddiv r%u, r%u, r%u", rs, rt, rd);
31093 putIReg(rd, unop(Iop_128to64,
31094 binop(Iop_DivModS64to64,
31095 getIReg(rs), getIReg(rt))));
31096 } else {
31097 ILLEGAL_INSTRUCTON;
31099 break;
31100 case 3: /* DMOD r6 */
31101 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
31102 DIP("dmod r%u, r%u, r%u", rs, rt, rd);
31103 t2 = newTemp(Ity_I128);
31104 assign(t2, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt)));
31105 putIReg(rd, unop(Iop_128HIto64, mkexpr(t2)));
31106 } else {
31107 ILLEGAL_INSTRUCTON;
31109 break;
31111 break;
31113 case 0x1F: /* Doubleword Divide Unsigned DDIVU; MIPS64 check this */
31114 switch (sa) {
31115 case 0:
31116 DIP("ddivu r%u, r%u", rs, rt);
31117 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
31118 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
31119 ILLEGAL_INSTRUCTON;
31121 t1 = newTemp(Ity_I128);
31123 assign(t1, binop(Iop_DivModU64to64, getIReg(rs), getIReg(rt)));
31125 putHI(unop(Iop_128HIto64, mkexpr(t1)));
31126 putLO(unop(Iop_128to64, mkexpr(t1)));
31127 break;
31128 case 2:
31129 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
31130 DIP("ddivu r%u, r%u, r%u", rs, rt, rd);
31131 putIReg(rd, unop(Iop_128to64, binop(Iop_DivModU64to64,
31132 getIReg(rs), getIReg(rt))));
31133 } else {
31134 ILLEGAL_INSTRUCTON;
31136 break;
31137 case 3:
31138 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
31139 DIP("dmodu r%u, r%u, r%u", rs, rt, rd);
31140 putIReg(rd, unop(Iop_128HIto64, binop(Iop_DivModU64to64,
31141 getIReg(rs), getIReg(rt))));
31142 } else {
31143 ILLEGAL_INSTRUCTON;
31145 break;
31147 break;
31149 case 0x10: { /* MFHI, CLZ R6 */
31150 if (((instr_index >> 6) & 0x1f) == 1) { /* CLZ */
31151 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
31152 DIP("clz r%u, r%u", rd, rs);
31153 if (mode64) {
31154 IRTemp tmpClz32 = newTemp(Ity_I32);
31155 IRTemp tmpRs32 = newTemp(Ity_I32);
31157 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
31158 assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32)));
31159 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True));
31160 } else {
31161 t1 = newTemp(Ity_I1);
31162 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0)));
31163 putIReg(rd, IRExpr_ITE(mkexpr(t1),
31164 mkU32(0x00000020),
31165 unop(Iop_Clz32, getIReg(rs))));
31167 } else {
31168 ILLEGAL_INSTRUCTON;
31170 break;
31171 } else if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
31172 /* If DSP is present -> DSP ASE MFHI */
31173 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
31174 if (0 != retVal ) {
31175 goto decode_failure;
31177 break;
31178 } else {
31179 DIP("mfhi r%u", rd);
31180 putIReg(rd, getHI());
31181 break;
31185 case 0x11: { /* MTHI, CLO R6 */
31186 if (((instr_index >> 6) & 0x1f) == 1) { /* CLO */
31187 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
31188 DIP("clo r%u, r%u", rd, rs);
31189 if (mode64) {
31190 IRTemp tmpClo32 = newTemp(Ity_I32);
31191 IRTemp tmpRs32 = newTemp(Ity_I32);
31192 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
31194 t1 = newTemp(Ity_I1);
31195 assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff)));
31196 assign(tmpClo32, IRExpr_ITE(mkexpr(t1),
31197 mkU32(0x00000020),
31198 unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32)))));
31200 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True));
31201 break;
31202 } else {
31203 t1 = newTemp(Ity_I1);
31204 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff)));
31205 putIReg(rd, IRExpr_ITE(mkexpr(t1),
31206 mkU32(0x00000020),
31207 unop(Iop_Clz32,
31208 unop(Iop_Not32, getIReg(rs)))));
31210 } else {
31211 ILLEGAL_INSTRUCTON;
31213 break;
31214 } else if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
31215 /* If DSP is present -> DSP ASE MTHI */
31216 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
31217 if (0 != retVal ) {
31218 goto decode_failure;
31220 break;
31221 } else {
31222 DIP("mthi r%u", rs);
31223 putHI(getIReg(rs));
31224 break;
31228 case 0x12: { /* MFLO */
31229 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
31230 /* If DSP is present -> DSP ASE MFLO */
31231 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
31232 if (0 != retVal ) {
31233 goto decode_failure;
31235 break;
31236 } else {
31237 switch (sa) {
31238 case 0:
31239 DIP("mflo r%u", rd);
31240 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
31241 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
31242 ILLEGAL_INSTRUCTON;
31244 putIReg(rd, getLO());
31245 break;
31246 case 1:
31247 DIP("dclz r%u, r%u", rd, rs);
31248 t1 = newTemp(Ity_I1);
31249 assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0)));
31250 putIReg(rd, IRExpr_ITE(mkexpr(t1),
31251 mkU64(0x00000040),
31252 unop(Iop_Clz64, getIReg(rs))));
31253 break;
31255 break;
31259 case 0x13: { /* MTLO */
31260 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
31261 /* If DSP is present -> DSP ASE MTLO */
31262 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
31263 if (0 != retVal ) {
31264 goto decode_failure;
31266 break;
31267 } else {
31268 switch (sa) {
31269 case 0:
31270 DIP("mtlo r%u", rs);
31271 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
31272 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
31273 ILLEGAL_INSTRUCTON;
31275 putLO(getIReg(rs));
31276 break;
31277 case 1:
31278 DIP("dclo r%u, r%u", rd, rs);
31279 t1 = newTemp(Ity_I1);
31280 assign(t1, binop(Iop_CmpEQ64, getIReg(rs),
31281 mkU64(0xffffffffffffffffULL)));
31282 putIReg(rd, IRExpr_ITE(mkexpr(t1),
31283 mkU64(0x40),
31284 unop(Iop_Clz64, unop(Iop_Not64,
31285 getIReg(rs)))));
31286 break;
31288 break;
31292 case 0x21: /* ADDU */
31293 DIP("addu r%u, r%u, r%u", rd, rs, rt);
31294 if (mode64) {
31295 ALU_PATTERN64(Iop_Add32);
31296 } else {
31297 ALU_PATTERN(Iop_Add32);
31299 break;
31301 case 0x22: { /* SUB */
31302 DIP("sub r%u, r%u, r%u", rd, rs, rt);
31303 IRTemp tmpRs32 = newTemp(Ity_I32);
31304 IRTemp tmpRt32 = newTemp(Ity_I32);
31306 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
31307 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
31308 t0 = newTemp(Ity_I32);
31309 t1 = newTemp(Ity_I32);
31310 t2 = newTemp(Ity_I32);
31311 t3 = newTemp(Ity_I32);
31312 t4 = newTemp(Ity_I32);
31313 t5 = newTemp(Ity_I32);
31314 /* dst = src0 + (-1 * src1)
31315 if(sign(src0 ) != sign((-1 * src1) ))
31316 goto no overflow;
31317 if(sign(dst) == sign(src0 ))
31318 goto no overflow;
31319 we have overflow! */
31321 assign(t5, binop(Iop_Mul32, mkexpr(tmpRt32), mkU32(-1)));
31322 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(t5)));
31323 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(t5)));
31324 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
31325 mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
31327 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
31328 assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
31329 mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
31331 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
31332 mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
31333 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
31334 IRConst_U32(guest_PC_curr_instr + 4),
31335 OFFB_PC));
31337 putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True));
31338 break;
31340 case 0x23: /* SUBU */
31341 DIP("subu r%u, r%u, r%u", rd, rs, rt);
31342 if (mode64) {
31343 ALU_PATTERN64(Iop_Sub32);
31344 } else {
31345 ALU_PATTERN(Iop_Sub32);
31347 break;
31349 case 0x24: /* AND */
31350 DIP("and r%u, r%u, r%u", rd, rs, rt);
31351 if (mode64) {
31352 ALU_PATTERN(Iop_And64);
31353 } else {
31354 ALU_PATTERN(Iop_And32);
31356 break;
31358 case 0x25: /* OR */
31359 DIP("or r%u, r%u, r%u", rd, rs, rt);
31360 if (mode64) {
31361 ALU_PATTERN(Iop_Or64);
31362 } else {
31363 ALU_PATTERN(Iop_Or32);
31365 break;
31367 case 0x26: /* XOR */
31368 DIP("xor r%u, r%u, r%u", rd, rs, rt);
31369 if (mode64) {
31370 ALU_PATTERN(Iop_Xor64);
31371 } else {
31372 ALU_PATTERN(Iop_Xor32);
31374 break;
31376 case 0x27: /* NOR */
31377 DIP("nor r%u, r%u, r%u", rd, rs, rt);
31378 if (mode64)
31379 putIReg(rd, unop(Iop_Not64, binop(Iop_Or64, getIReg(rs),
31380 getIReg(rt))));
31381 else
31382 putIReg(rd, unop(Iop_Not32, binop(Iop_Or32, getIReg(rs),
31383 getIReg(rt))));
31384 break;
31386 case 0x08: /* JR */
31387 DIP("jr r%u", rs);
31388 t0 = newTemp(ty);
31389 assign(t0, getIReg(rs));
31390 lastn = mkexpr(t0);
31391 break;
31393 case 0x09: /* JALR */
31394 DIP("jalr r%u r%u", rd, rs);
31395 if (mode64) {
31396 putIReg(rd, mkU64(guest_PC_curr_instr + 8));
31397 t0 = newTemp(Ity_I64);
31398 assign(t0, getIReg(rs));
31399 lastn = mkexpr(t0);
31400 } else {
31401 putIReg(rd, mkU32(guest_PC_curr_instr + 8));
31402 t0 = newTemp(Ity_I32);
31403 assign(t0, getIReg(rs));
31404 lastn = mkexpr(t0);
31406 break;
31408 case 0x0C: /* SYSCALL */
31409 DIP("syscall");
31410 if (mode64)
31411 putPC(mkU64(guest_PC_curr_instr + 4));
31412 else
31413 putPC(mkU32(guest_PC_curr_instr + 4));
31414 dres.jk_StopHere = Ijk_Sys_syscall;
31415 dres.whatNext = Dis_StopHere;
31416 break;
31418 case 0x2A: /* SLT */
31419 DIP("slt r%u, r%u, r%u", rd, rs, rt);
31420 if (mode64)
31421 putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
31422 getIReg(rt))));
31423 else
31424 putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
31425 getIReg(rt))));
31426 break;
31428 case 0x2B: /* SLTU */
31429 DIP("sltu r%u, r%u, r%u", rd, rs, rt);
31430 if (mode64)
31431 putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
31432 getIReg(rt))));
31433 else
31434 putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
31435 getIReg(rt))));
31436 break;
31438 case 0x00: { /* SLL */
31439 DIP("sll r%u, r%u, %u", rd, rt, sa);
31440 IRTemp tmpRt32 = newTemp(Ity_I32);
31441 IRTemp tmpSh32 = newTemp(Ity_I32);
31442 IRTemp tmpRd = newTemp(Ity_I64);
31443 if (mode64) {
31444 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
31445 assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkU8(sa)));
31446 assign(tmpRd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
31447 putIReg(rd, mkexpr(tmpRd));
31448 } else
31449 SXX_PATTERN(Iop_Shl32);
31450 break;
31453 case 0x04: { /* SLLV */
31454 DIP("sllv r%u, r%u, r%u", rd, rt, rs);
31455 if (mode64) {
31456 IRTemp tmpRs8 = newTemp(Ity_I8);
31457 IRTemp tmpRt32 = newTemp(Ity_I32);
31458 IRTemp tmpSh32 = newTemp(Ity_I32);
31459 IRTemp tmp = newTemp(ty);
31460 assign(tmp, binop(mkSzOp(ty, Iop_And8), getIReg(rs),
31461 mkSzImm(ty, 31)));
31462 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
31463 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
31464 assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkexpr(tmpRs8)));
31465 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
31466 } else {
31467 SXXV_PATTERN(Iop_Shl32);
31469 break;
31472 case 0x03: /* SRA */
31473 DIP("sra r%u, r%u, %u", rd, rt, sa);
31474 if (mode64) {
31475 IRTemp tmpRt32 = newTemp(Ity_I32);
31476 IRTemp tmpSh32 = newTemp(Ity_I32);
31478 t1 = newTemp(Ity_I64);
31479 t2 = newTemp(Ity_I64);
31480 t3 = newTemp(Ity_I64);
31482 assign(t1, binop(Iop_And64, getIReg(rt), /* hi */
31483 mkU64(0xFFFFFFFF00000000ULL)));
31485 assign(t2, binop(Iop_Sar64, mkexpr(t1), mkU8(sa)));
31487 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
31488 assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkU8(sa)));
31490 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
31491 } else {
31492 SXX_PATTERN(Iop_Sar32);
31494 break;
31496 case 0x07: /* SRAV */
31497 DIP("srav r%u, r%u, r%u", rd, rt, rs);
31498 if (mode64) {
31499 IRTemp tmpRt32 = newTemp(Ity_I32);
31500 IRTemp tmpSh32 = newTemp(Ity_I32);
31502 t1 = newTemp(Ity_I64);
31503 t2 = newTemp(Ity_I64);
31504 t3 = newTemp(Ity_I64);
31505 t4 = newTemp(Ity_I8);
31507 assign(t4, unop(Iop_32to8, binop(Iop_And32,
31508 mkNarrowTo32(ty, getIReg(rs)), mkU32(0x0000001F))));
31510 assign(t1, binop(Iop_And64, getIReg(rt), /* hi */
31511 mkU64(0xFFFFFFFF00000000ULL)));
31513 assign(t2, binop(Iop_Sar64, mkexpr(t1), mkexpr(t4)));
31515 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
31516 assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkexpr(t4)));
31518 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
31519 } else {
31520 SXXV_PATTERN(Iop_Sar32);
31522 break;
31524 case 0x02: { /* SRL */
31525 rot = get_rot(cins);
31526 if (rot) {
31527 DIP("rotr r%u, r%u, %u", rd, rt, sa);
31528 putIReg(rd, mkWidenFrom32(ty, genROR32(mkNarrowTo32(ty,
31529 getIReg(rt)), sa), True));
31530 } else {
31531 DIP("srl r%u, r%u, %u", rd, rt, sa);
31532 if (mode64) {
31533 IRTemp tmpSh32 = newTemp(Ity_I32);
31534 IRTemp tmpRt32 = newTemp(Ity_I32);
31536 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
31537 assign(tmpSh32, binop(Iop_Shr32, mkexpr(tmpRt32), mkU8(sa)));
31538 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
31539 } else {
31540 SXX_PATTERN(Iop_Shr32);
31543 break;
31546 case 0x06: {
31547 rot = get_rotv(cins);
31548 if (rot) {
31549 DIP("rotrv r%u, r%u, r%u", rd, rt, rs);
31550 putIReg(rd, mkWidenFrom32(ty, genRORV32(mkNarrowTo32(ty,
31551 getIReg(rt)), mkNarrowTo32(ty, getIReg(rs))), True));
31552 break;
31553 } else { /* SRLV */
31554 DIP("srlv r%u, r%u, r%u", rd, rt, rs);
31555 if (mode64) {
31556 SXXV_PATTERN64(Iop_Shr32);
31557 } else {
31558 SXXV_PATTERN(Iop_Shr32);
31560 break;
31563 case 0x05: { /* LSA */
31564 UInt imm2 = (imm & 0xC0) >> 6;
31565 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) || has_msa) {
31566 DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
31567 if (mode64) {
31568 DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
31569 putIReg(rd, unop(Iop_32Sto64,
31570 binop(Iop_Add32,
31571 binop(Iop_Shl32,
31572 unop(Iop_64to32, getIReg(rs)),
31573 mkU8(imm2 + 1)),
31574 unop(Iop_64to32, getIReg(rt)))));
31575 break;
31576 } else {
31577 DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
31578 putIReg(rd, binop(Iop_Add32,
31579 binop(Iop_Shl32,
31580 getIReg(rs), mkU8(imm2 + 1)), getIReg(rt)));
31581 break;
31583 } else {
31584 ILLEGAL_INSTRUCTON;
31588 case 0x15:{ /* DLSA */
31589 UInt imm2 = (imm & 0xC0) >> 6;
31590 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) || has_msa) {
31591 DIP("dlsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
31592 putIReg(rd, binop(Iop_Add64,
31593 binop(Iop_Shl64, getIReg(rs), mkU8(imm2 + 1)),
31594 getIReg(rt)));
31595 } else {
31596 ILLEGAL_INSTRUCTON;
31598 break;
31601 case 0x0D: /* BREAK */
31602 DIP("break 0x%x", trap_code);
31603 if (mode64)
31604 jmp_lit64(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
31605 else
31606 jmp_lit32(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
31607 vassert(dres.whatNext == Dis_StopHere);
31608 break;
31610 case 0x30: { /* TGE */
31611 DIP("tge r%u, r%u %u", rs, rt, trap_code);
31612 if (mode64) {
31613 if (trap_code == 7)
31614 stmt (IRStmt_Exit (unop (Iop_Not1,
31615 binop (Iop_CmpLT64S,
31616 getIReg (rs),
31617 getIReg (rt))),
31618 Ijk_SigFPE_IntDiv,
31619 IRConst_U64(guest_PC_curr_instr + 4),
31620 OFFB_PC));
31621 else if (trap_code == 6)
31622 stmt (IRStmt_Exit (unop (Iop_Not1,
31623 binop (Iop_CmpLT64S,
31624 getIReg (rs),
31625 getIReg (rt))),
31626 Ijk_SigFPE_IntOvf,
31627 IRConst_U64(guest_PC_curr_instr + 4),
31628 OFFB_PC));
31629 else
31630 stmt (IRStmt_Exit (unop (Iop_Not1,
31631 binop (Iop_CmpLT64S,
31632 getIReg (rs),
31633 getIReg (rt))),
31634 Ijk_SigTRAP,
31635 IRConst_U64(guest_PC_curr_instr + 4),
31636 OFFB_PC));
31637 } else {
31638 if (trap_code == 7)
31639 stmt (IRStmt_Exit (unop (Iop_Not1,
31640 binop (Iop_CmpLT32S,
31641 getIReg (rs),
31642 getIReg (rt))),
31643 Ijk_SigFPE_IntDiv,
31644 IRConst_U32(guest_PC_curr_instr + 4),
31645 OFFB_PC));
31646 else if (trap_code == 6)
31647 stmt (IRStmt_Exit (unop (Iop_Not1,
31648 binop (Iop_CmpLT32S,
31649 getIReg (rs),
31650 getIReg (rt))),
31651 Ijk_SigFPE_IntOvf,
31652 IRConst_U32(guest_PC_curr_instr + 4),
31653 OFFB_PC));
31654 else
31655 stmt (IRStmt_Exit (unop (Iop_Not1,
31656 binop (Iop_CmpLT32S,
31657 getIReg (rs),
31658 getIReg (rt))),
31659 Ijk_SigTRAP,
31660 IRConst_U32(guest_PC_curr_instr + 4),
31661 OFFB_PC));
31663 break;
31665 case 0x31: { /* TGEU */
31666 DIP("tgeu r%u, r%u %u", rs, rt, trap_code);
31667 if (mode64) {
31668 if (trap_code == 7)
31669 stmt (IRStmt_Exit (unop (Iop_Not1,
31670 binop (Iop_CmpLT64U,
31671 getIReg (rs),
31672 getIReg (rt))),
31673 Ijk_SigFPE_IntDiv,
31674 IRConst_U64(guest_PC_curr_instr + 4),
31675 OFFB_PC));
31676 else if (trap_code == 6)
31677 stmt (IRStmt_Exit (unop (Iop_Not1,
31678 binop (Iop_CmpLT64U,
31679 getIReg (rs),
31680 getIReg (rt))),
31681 Ijk_SigFPE_IntOvf,
31682 IRConst_U64(guest_PC_curr_instr + 4),
31683 OFFB_PC));
31684 else
31685 stmt (IRStmt_Exit (unop (Iop_Not1,
31686 binop (Iop_CmpLT64U,
31687 getIReg (rs),
31688 getIReg (rt))),
31689 Ijk_SigTRAP,
31690 IRConst_U64(guest_PC_curr_instr + 4),
31691 OFFB_PC));
31692 } else {
31693 if (trap_code == 7)
31694 stmt (IRStmt_Exit (unop (Iop_Not1,
31695 binop (Iop_CmpLT32U,
31696 getIReg (rs),
31697 getIReg (rt))),
31698 Ijk_SigFPE_IntDiv,
31699 IRConst_U32(guest_PC_curr_instr + 4),
31700 OFFB_PC));
31701 else if (trap_code == 6)
31702 stmt (IRStmt_Exit (unop (Iop_Not1,
31703 binop (Iop_CmpLT32U,
31704 getIReg (rs),
31705 getIReg (rt))),
31706 Ijk_SigFPE_IntOvf,
31707 IRConst_U32(guest_PC_curr_instr + 4),
31708 OFFB_PC));
31709 else
31710 stmt (IRStmt_Exit (unop (Iop_Not1,
31711 binop (Iop_CmpLT32U,
31712 getIReg (rs),
31713 getIReg (rt))),
31714 Ijk_SigTRAP,
31715 IRConst_U32(guest_PC_curr_instr + 4),
31716 OFFB_PC));
31718 break;
31720 case 0x32: { /* TLT */
31721 DIP("tlt r%u, r%u %u", rs, rt, trap_code);
31722 if (mode64) {
31723 if (trap_code == 7)
31724 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
31725 getIReg(rt)), Ijk_SigFPE_IntDiv,
31726 IRConst_U64(guest_PC_curr_instr + 4),
31727 OFFB_PC));
31728 else if (trap_code == 6)
31729 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
31730 getIReg(rt)), Ijk_SigFPE_IntOvf,
31731 IRConst_U64(guest_PC_curr_instr + 4),
31732 OFFB_PC));
31733 else
31734 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
31735 getIReg(rt)), Ijk_SigTRAP,
31736 IRConst_U64(guest_PC_curr_instr + 4),
31737 OFFB_PC));
31738 } else {
31739 if (trap_code == 7)
31740 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
31741 getIReg(rt)), Ijk_SigFPE_IntDiv,
31742 IRConst_U32(guest_PC_curr_instr + 4),
31743 OFFB_PC));
31744 else if (trap_code == 6)
31745 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
31746 getIReg(rt)), Ijk_SigFPE_IntOvf,
31747 IRConst_U32(guest_PC_curr_instr + 4),
31748 OFFB_PC));
31749 else
31750 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
31751 getIReg(rt)), Ijk_SigTRAP,
31752 IRConst_U32(guest_PC_curr_instr + 4),
31753 OFFB_PC));
31755 break;
31757 case 0x33: { /* TLTU */
31758 DIP("tltu r%u, r%u %u", rs, rt, trap_code);
31759 if (mode64) {
31760 if (trap_code == 7)
31761 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
31762 getIReg(rt)), Ijk_SigFPE_IntDiv,
31763 IRConst_U64(guest_PC_curr_instr + 4),
31764 OFFB_PC));
31765 else if (trap_code == 6)
31766 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
31767 getIReg(rt)), Ijk_SigFPE_IntOvf,
31768 IRConst_U64(guest_PC_curr_instr + 4),
31769 OFFB_PC));
31770 else
31771 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
31772 getIReg(rt)), Ijk_SigTRAP,
31773 IRConst_U64(guest_PC_curr_instr + 4),
31774 OFFB_PC));
31775 } else {
31776 if (trap_code == 7)
31777 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
31778 getIReg(rt)), Ijk_SigFPE_IntDiv,
31779 IRConst_U32(guest_PC_curr_instr + 4),
31780 OFFB_PC));
31781 else if (trap_code == 6)
31782 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
31783 getIReg(rt)), Ijk_SigFPE_IntOvf,
31784 IRConst_U32(guest_PC_curr_instr + 4),
31785 OFFB_PC));
31786 else
31787 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
31788 getIReg (rt)), Ijk_SigTRAP,
31789 IRConst_U32(guest_PC_curr_instr + 4),
31790 OFFB_PC));
31792 break;
31794 case 0x34: { /* TEQ */
31795 DIP("teq r%u, r%u, %u", rs, rt, trap_code);
31796 if (mode64) {
31797 if (trap_code == 7)
31798 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
31799 getIReg(rt)), Ijk_SigFPE_IntDiv,
31800 IRConst_U64(guest_PC_curr_instr + 4),
31801 OFFB_PC));
31802 else if (trap_code == 6)
31803 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
31804 getIReg(rt)), Ijk_SigFPE_IntOvf,
31805 IRConst_U64(guest_PC_curr_instr + 4),
31806 OFFB_PC));
31807 else
31808 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
31809 getIReg(rt)), Ijk_SigTRAP,
31810 IRConst_U64(guest_PC_curr_instr + 4),
31811 OFFB_PC));
31812 } else {
31813 if (trap_code == 7)
31814 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
31815 getIReg(rt)), Ijk_SigFPE_IntDiv,
31816 IRConst_U32(guest_PC_curr_instr + 4),
31817 OFFB_PC));
31818 else if (trap_code == 6)
31819 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
31820 getIReg(rt)), Ijk_SigFPE_IntOvf,
31821 IRConst_U32(guest_PC_curr_instr + 4),
31822 OFFB_PC));
31823 else
31824 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
31825 getIReg(rt)), Ijk_SigTRAP,
31826 IRConst_U32(guest_PC_curr_instr + 4),
31827 OFFB_PC));
31829 break;
31831 case 0x35: { /* SELEQZ */
31832 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
31833 DIP("seleqz r%u, r%u, r%u", rd, rs, rt);
31834 if (mode64) {
31835 putIReg(rd, binop(Iop_And64,
31836 unop(Iop_Not64,
31837 unop(Iop_CmpwNEZ64, getIReg(rt))),
31838 getIReg(rs)));
31839 } else {
31840 putIReg(rd, binop(Iop_And32,
31841 unop(Iop_Not32,
31842 unop(Iop_CmpwNEZ32, getIReg(rt))),
31843 getIReg(rs)));
31845 } else {
31846 ILLEGAL_INSTRUCTON;
31848 break;
31851 case 0x36: { /* TNE */
31852 DIP("tne r%u, r%u %u", rs, rt, trap_code);
31853 if (mode64) {
31854 if (trap_code == 7)
31855 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
31856 getIReg(rt)), Ijk_SigFPE_IntDiv,
31857 IRConst_U64(guest_PC_curr_instr + 4),
31858 OFFB_PC));
31859 else if (trap_code == 6)
31860 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
31861 getIReg(rt)), Ijk_SigFPE_IntOvf,
31862 IRConst_U64(guest_PC_curr_instr + 4),
31863 OFFB_PC));
31864 else
31865 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
31866 getIReg(rt)), Ijk_SigTRAP,
31867 IRConst_U64(guest_PC_curr_instr + 4),
31868 OFFB_PC));
31869 } else {
31870 if (trap_code == 7)
31871 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
31872 getIReg(rt)), Ijk_SigFPE_IntDiv,
31873 IRConst_U32(guest_PC_curr_instr + 4),
31874 OFFB_PC));
31875 else if (trap_code == 6)
31876 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
31877 getIReg(rt)), Ijk_SigFPE_IntOvf,
31878 IRConst_U32(guest_PC_curr_instr + 4),
31879 OFFB_PC));
31880 else
31881 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
31882 getIReg(rt)), Ijk_SigTRAP,
31883 IRConst_U32(guest_PC_curr_instr + 4),
31884 OFFB_PC));
31886 break;
31888 case 0x37: { /* SELNEZ */
31889 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
31890 DIP("selnez r%u, r%u, r%u", rd, rs, rt);
31891 if (mode64) {
31892 putIReg(rd, binop(Iop_And64,
31893 unop(Iop_CmpwNEZ64, getIReg(rt)), getIReg(rs)));
31894 } else {
31895 putIReg(rd, binop(Iop_And32,
31896 unop(Iop_CmpwNEZ32, getIReg(rt)), getIReg(rs)));
31898 } else {
31899 ILLEGAL_INSTRUCTON;
31901 break;
31903 case 0x14:
31904 case 0x16:
31905 case 0x17: /* DSLLV, DROTRV:DSRLV, DSRAV */
31906 case 0x38:
31907 case 0x3A:
31908 case 0x3B: /* DSLL, DROTL:DSRL, DSRA */
31909 case 0x3C:
31910 case 0x3E:
31911 case 0x3F: /* DSLL32, DROTR32:DSRL32, DSRA32 */
31912 if (dis_instr_shrt(cins))
31913 break;
31914 goto decode_failure;
31916 case 0x0F: /* SYNC */
31917 DIP("sync 0x%x", sel);
31918 /* Just ignore it. */
31919 break;
31921 case 0x2C: { /* Doubleword Add - DADD; MIPS64 */
31922 DIP("dadd r%u, r%u, r%u", rd, rs, rt);
31923 IRTemp tmpRs64 = newTemp(Ity_I64);
31924 IRTemp tmpRt64 = newTemp(Ity_I64);
31926 assign(tmpRs64, getIReg(rs));
31927 assign(tmpRt64, getIReg(rt));
31929 t0 = newTemp(Ity_I64);
31930 t1 = newTemp(Ity_I64);
31931 t2 = newTemp(Ity_I64);
31932 t3 = newTemp(Ity_I64);
31933 t4 = newTemp(Ity_I64);
31934 /* dst = src0 + src1
31935 if(sign(src0 ) != sign(src1 ))
31936 goto no overflow;
31937 if(sign(dst) == sign(src0 ))
31938 goto no overflow;
31939 we have overflow! */
31941 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
31942 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
31943 assign(t2, unop(Iop_1Uto64,
31944 binop(Iop_CmpEQ64,
31945 binop(Iop_And64, mkexpr(t1),
31946 mkU64(0x8000000000000000ULL)),
31947 mkU64(0x8000000000000000ULL))));
31949 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
31950 assign(t4, unop(Iop_1Uto64,
31951 binop(Iop_CmpNE64,
31952 binop(Iop_And64, mkexpr(t3),
31953 mkU64(0x8000000000000000ULL)),
31954 mkU64(0x8000000000000000ULL))));
31956 stmt(IRStmt_Exit(binop(Iop_CmpEQ64,
31957 binop(Iop_Or64, mkexpr(t2), mkexpr(t4)),
31958 mkU64(0)),
31959 Ijk_SigFPE_IntOvf,
31960 IRConst_U64(guest_PC_curr_instr + 4),
31961 OFFB_PC));
31963 putIReg(rd, mkexpr(t0));
31964 break;
31967 case 0x2D: /* Doubleword Add Unsigned - DADDU; MIPS64 */
31968 DIP("daddu r%u, r%u, r%u", rd, rs, rt);
31969 ALU_PATTERN(Iop_Add64);
31970 break;
31972 case 0x2E: { /* Doubleword Subtract - DSUB; MIPS64 */
31973 DIP("dsub r%u, r%u, r%u", rd, rs, rt);
31974 IRTemp tmpRs64 = newTemp(Ity_I64);
31975 IRTemp tmpRt64 = newTemp(Ity_I64);
31977 assign(tmpRs64, getIReg(rs));
31978 assign(tmpRt64, getIReg(rt));
31979 t0 = newTemp(Ity_I64);
31980 t1 = newTemp(Ity_I64);
31981 t2 = newTemp(Ity_I64);
31982 t3 = newTemp(Ity_I64);
31983 t4 = newTemp(Ity_I64);
31984 t5 = newTemp(Ity_I64);
31985 /* dst = src0 + (-1 * src1)
31986 if(sign(src0 ) != sign((-1 * src1) ))
31987 goto no overflow;
31988 if(sign(dst) == sign(src0 ))
31989 goto no overflow;
31990 we have overflow! */
31992 assign(t5, binop(Iop_Mul64,
31993 mkexpr(tmpRt64),
31994 mkU64(0xffffffffffffffffULL)));
31995 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(t5)));
31996 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(t5)));
31997 assign(t2, unop(Iop_1Sto64,
31998 binop(Iop_CmpEQ64,
31999 binop(Iop_And64,
32000 mkexpr(t1),
32001 mkU64(0x8000000000000000ULL)),
32002 mkU64(0x8000000000000000ULL))));
32004 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
32005 assign(t4, unop(Iop_1Sto64,
32006 binop(Iop_CmpNE64,
32007 binop(Iop_And64,
32008 mkexpr(t3),
32009 mkU64(0x8000000000000000ULL)),
32010 mkU64(0x8000000000000000ULL))));
32012 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
32013 mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
32014 IRConst_U64(guest_PC_curr_instr + 4),
32015 OFFB_PC));
32017 putIReg(rd, binop(Iop_Sub64, getIReg(rs), getIReg(rt)));
32018 break;
32021 case 0x2F: /* Doubleword Subtract Unsigned - DSUBU; MIPS64 */
32022 DIP("dsub r%u, r%u,r%u", rd, rt, rt);
32023 ALU_PATTERN(Iop_Sub64);
32024 break;
32026 default:
32027 goto decode_failure;
32029 break;
32031 case 0x01: /* Regimm */
32033 switch (rt) {
32034 case 0x00: /* BLTZ */
32035 DIP("bltz r%u, %u", rs, imm);
32036 if (mode64) {
32037 if (!dis_instr_branch(cins, &dres, resteerOkFn,
32038 callback_opaque, &bstmt))
32039 goto decode_failure;
32040 } else
32041 dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
32042 mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
32043 break;
32045 case 0x01: /* BGEZ */
32046 DIP("bgez r%u, %u", rs, imm);
32047 if (mode64) {
32048 if (!dis_instr_branch(cins, &dres, resteerOkFn,
32049 callback_opaque, &bstmt))
32050 goto decode_failure;
32051 } else
32052 dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
32053 mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
32054 break;
32056 case 0x02: /* BLTZL */
32057 DIP("bltzl r%u, %u", rs, imm);
32058 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
32059 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
32060 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
32061 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
32062 imm);
32063 break;
32065 case 0x03: /* BGEZL */
32066 DIP("bgezl r%u, %u", rs, imm);
32067 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
32068 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
32069 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
32070 mode64 ? mkU64(0x0) : mkU32(0x0)), imm);
32071 break;
32073 case 0x10: /* BLTZAL */
32074 DIP("bltzal r%u, %u", rs, imm);
32075 if (mode64) {
32076 if (!dis_instr_branch(cins, &dres, resteerOkFn,
32077 callback_opaque, &bstmt))
32078 goto decode_failure;
32079 } else
32080 dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
32081 mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
32082 break;
32084 case 0x12: /* BLTZALL */
32085 DIP("bltzall r%u, %u", rs, imm);
32086 putIReg(31, mode64 ? mkU64(guest_PC_curr_instr + 8) :
32087 mkU32(guest_PC_curr_instr + 8));
32088 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
32089 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
32090 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
32091 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
32092 imm);
32093 break;
32095 case 0x11: /* BGEZAL */
32096 DIP("bgezal r%u, %u", rs, imm);
32097 if (mode64) {
32098 if (!dis_instr_branch(cins, &dres, resteerOkFn,
32099 callback_opaque, &bstmt))
32100 goto decode_failure;
32101 } else
32102 dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
32103 mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
32104 break;
32106 case 0x13: /* BGEZALL */
32107 DIP("bgezall r%u, %u", rs, imm);
32108 if (mode64) {
32109 putIReg(31, mkU64(guest_PC_curr_instr + 8));
32110 lastn = dis_branch_likely(binop(Iop_CmpNE64,
32111 binop(Iop_And64,
32112 getIReg(rs),
32113 mkU64(0x8000000000000000ULL)),
32114 mkU64(0x0)),
32115 imm);
32116 } else {
32117 putIReg(31, mkU32(guest_PC_curr_instr + 8));
32118 lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
32119 getIReg(rs), mkU32(0x80000000)),
32120 mkU32(0x0)), imm);
32122 break;
32124 case 0x08: /* TGEI */
32125 DIP("tgei r%u, %u %u", rs, imm, trap_code);
32126 if (mode64) {
32127 stmt (IRStmt_Exit(unop(Iop_Not1,
32128 binop(Iop_CmpLT64S,
32129 getIReg(rs),
32130 mkU64(extend_s_16to64 (imm)))),
32131 Ijk_SigTRAP,
32132 IRConst_U64(guest_PC_curr_instr + 4),
32133 OFFB_PC));
32134 } else {
32135 stmt (IRStmt_Exit(unop(Iop_Not1,
32136 binop(Iop_CmpLT32S,
32137 getIReg(rs),
32138 mkU32(extend_s_16to32 (imm)))),
32139 Ijk_SigTRAP,
32140 IRConst_U32(guest_PC_curr_instr + 4),
32141 OFFB_PC));
32143 break;
32145 case 0x09: { /* TGEIU */
32146 DIP("tgeiu r%u, %u %u", rs, imm, trap_code);
32147 if (mode64) {
32148 stmt (IRStmt_Exit (unop (Iop_Not1,
32149 binop (Iop_CmpLT64U,
32150 getIReg (rs),
32151 mkU64 (extend_s_16to64 (imm)))),
32152 Ijk_SigTRAP,
32153 IRConst_U64(guest_PC_curr_instr + 4),
32154 OFFB_PC));
32155 } else {
32156 stmt (IRStmt_Exit (unop (Iop_Not1,
32157 binop (Iop_CmpLT32U,
32158 getIReg (rs),
32159 mkU32 (extend_s_16to32 (imm)))),
32160 Ijk_SigTRAP,
32161 IRConst_U32(guest_PC_curr_instr + 4),
32162 OFFB_PC));
32164 break;
32166 case 0x0A: { /* TLTI */
32167 DIP("tlti r%u, %u %u", rs, imm, trap_code);
32168 if (mode64) {
32169 stmt (IRStmt_Exit (binop (Iop_CmpLT64S, getIReg (rs),
32170 mkU64 (extend_s_16to64 (imm))),
32171 Ijk_SigTRAP,
32172 IRConst_U64(guest_PC_curr_instr + 4),
32173 OFFB_PC));
32174 } else {
32175 stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs),
32176 mkU32 (extend_s_16to32 (imm))),
32177 Ijk_SigTRAP,
32178 IRConst_U32(guest_PC_curr_instr + 4),
32179 OFFB_PC));
32181 break;
32183 case 0x0B: { /* TLTIU */
32184 DIP("tltiu r%u, %u %u", rs, imm, trap_code);
32185 if (mode64) {
32186 stmt (IRStmt_Exit (binop (Iop_CmpLT64U, getIReg (rs),
32187 mkU64 (extend_s_16to64 (imm))),
32188 Ijk_SigTRAP,
32189 IRConst_U64(guest_PC_curr_instr + 4),
32190 OFFB_PC));
32191 } else {
32192 stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs),
32193 mkU32 (extend_s_16to32 (imm))),
32194 Ijk_SigTRAP,
32195 IRConst_U32(guest_PC_curr_instr + 4),
32196 OFFB_PC));
32198 break;
32200 case 0x0C: { /* TEQI */
32201 DIP("teqi r%u, %u %u", rs, imm, trap_code);
32202 if (mode64) {
32203 stmt (IRStmt_Exit (binop (Iop_CmpEQ64, getIReg (rs),
32204 mkU64 (extend_s_16to64 (imm))),
32205 Ijk_SigTRAP,
32206 IRConst_U64(guest_PC_curr_instr + 4),
32207 OFFB_PC));
32208 } else {
32209 stmt (IRStmt_Exit (binop (Iop_CmpEQ32, getIReg (rs),
32210 mkU32 (extend_s_16to32 (imm))),
32211 Ijk_SigTRAP,
32212 IRConst_U32(guest_PC_curr_instr + 4),
32213 OFFB_PC));
32215 break;
32217 case 0x0E: { /* TNEI */
32218 DIP("tnei r%u, %u %u", rs, imm, trap_code);
32219 if (mode64) {
32220 stmt (IRStmt_Exit (binop (Iop_CmpNE64, getIReg (rs),
32221 mkU64 (extend_s_16to64 (imm))),
32222 Ijk_SigTRAP,
32223 IRConst_U64(guest_PC_curr_instr + 4),
32224 OFFB_PC));
32225 } else {
32226 stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs),
32227 mkU32 (extend_s_16to32 (imm))),
32228 Ijk_SigTRAP,
32229 IRConst_U32(guest_PC_curr_instr + 4),
32230 OFFB_PC));
32232 break;
32234 case 0x1C: { /* BPOSGE32 */
32235 DIP("bposge32 %u", imm);
32236 vassert(!mode64);
32237 t0 = newTemp(Ity_I32);
32238 /* Get pos field from DSPControl register. */
32239 assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
32240 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLT32U, mkexpr(t0),
32241 mkU32(32))), imm, &bstmt);
32243 case 0x1F:
32244 /* SYNCI */
32245 /* Just ignore it */
32246 break;
32248 case 0x06: { /* DAHI */
32249 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
32250 DIP("dahi r%u, %x", rs, imm);
32251 putIReg(rs, binop(Iop_Add64,
32252 getIReg(rs), mkU64(extend_s_16to64 (imm) << 32)));
32253 } else {
32254 ILLEGAL_INSTRUCTON;
32256 break;
32259 case 0x1E: { /* DATI */
32260 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
32261 DIP("dati r%u, %x", rs, imm);
32262 putIReg(rs, binop(Iop_Add64,
32263 getIReg(rs), mkU64((long long)imm << 48)));
32264 } else {
32265 ILLEGAL_INSTRUCTON;
32267 break;
32270 default:
32271 goto decode_failure;
32273 break;
32275 case 0x04:
32276 DIP("beq r%u, r%u, %u", rs, rt, imm);
32277 if (mode64)
32278 dis_branch(False, binop(Iop_CmpEQ64, getIReg(rs), getIReg(rt)),
32279 imm, &bstmt);
32280 else
32281 dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)),
32282 imm, &bstmt);
32283 break;
32285 case 0x14:
32286 DIP("beql r%u, r%u, %u", rs, rt, imm);
32287 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
32288 getIReg(rs), getIReg(rt)), imm);
32289 break;
32291 case 0x05:
32292 DIP("bne r%u, r%u, %u", rs, rt, imm);
32293 if (mode64)
32294 dis_branch(False, binop(Iop_CmpNE64, getIReg(rs), getIReg(rt)),
32295 imm, &bstmt);
32296 else
32297 dis_branch(False, binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)),
32298 imm, &bstmt);
32299 break;
32301 case 0x15:
32302 DIP("bnel r%u, r%u, %u", rs, rt, imm);
32303 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpEQ64 : Iop_CmpEQ32,
32304 getIReg(rs), getIReg(rt)), imm);
32305 break;
32307 case 0x07: /* BGTZ, BGTZALC, BLTZALC, BLTUC */
32308 if (rt == 0) { /* BGTZ */
32309 DIP("bgtz r%u, %u", rs, imm);
32310 if (mode64)
32311 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE64S, getIReg(rs),
32312 mkU64(0x00))), imm, &bstmt);
32313 else
32314 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE32S, getIReg(rs),
32315 mkU32(0x00))), imm, &bstmt);
32316 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
32317 if (rs == 0) { /* BGTZALC */
32318 DIP("bgtzalc r%u, %u", rt, imm);
32319 if (mode64) {
32320 dis_branch_compact(True,
32321 unop(Iop_Not1,
32322 binop(Iop_CmpLE64S,
32323 getIReg(rt), mkU64(0x0))),
32324 imm, &dres);
32325 } else {
32326 dis_branch_compact(True,
32327 unop(Iop_Not1,
32328 binop(Iop_CmpLE32S,
32329 getIReg(rt), mkU32(0x0))),
32330 imm, &dres);
32332 } else if (rs == rt) { /* BLTZALC */
32333 DIP("bltzalc r%u, %u", rt, imm);
32334 if (mode64) {
32335 dis_branch_compact(True,
32336 unop(Iop_Not1,
32337 binop(Iop_CmpLE64S,
32338 mkU64(0x0), getIReg(rt))),
32339 imm, &dres);
32340 } else {
32341 dis_branch_compact(True,
32342 unop(Iop_Not1,
32343 binop(Iop_CmpLE32S,
32344 mkU32(0x0), getIReg(rt))),
32345 imm, &dres);
32347 } else { /* BLTUC */
32348 DIP("bltuc r%u, r%u, %u", rt, rs, imm);
32349 if (mode64) {
32350 dis_branch_compact(False,
32351 binop(Iop_CmpLT64U, getIReg(rs), getIReg(rt)),
32352 imm, &dres);
32353 } else {
32354 dis_branch_compact(False,
32355 binop(Iop_CmpLT32U, getIReg(rs), getIReg(rt)),
32356 imm, &dres);
32359 } else {
32360 ILLEGAL_INSTRUCTON;
32362 break;
32364 case 0x17: /* BGTZL, BGTZC, BLTZC, BLTC */
32365 if (rt == 0) { /* BGTZL */
32366 DIP("bgtzl r%u, %u", rs, imm);
32367 if (mode64)
32368 lastn = dis_branch_likely(binop(Iop_CmpLE64S, getIReg(rs),
32369 mkU64(0x00)), imm);
32370 else
32371 lastn = dis_branch_likely(binop(Iop_CmpLE32S, getIReg(rs),
32372 mkU32(0x00)), imm);
32373 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
32374 if (rs == 0) { /* BGTZC */
32375 DIP("bgtzc r%u, %u", rt, imm);
32376 if (mode64) {
32377 dis_branch_compact(False,
32378 unop(Iop_Not1,
32379 binop(Iop_CmpLE64S,
32380 getIReg(rt), mkU64(0x0))),
32381 imm, &dres);
32382 } else {
32383 dis_branch_compact(False,
32384 unop(Iop_Not1,
32385 binop(Iop_CmpLE32S,
32386 getIReg(rt), mkU32(0x0))),
32387 imm, &dres);
32389 } else if (rs == rt) { /* BLTZC */
32390 DIP("bltzc r%u, %u", rt, imm);
32391 if (mode64) {
32392 dis_branch_compact(False,
32393 unop(Iop_Not1,
32394 binop(Iop_CmpLE64S,
32395 mkU64(0x0), getIReg(rt))),
32396 imm, &dres);
32397 } else {
32398 dis_branch_compact(False,
32399 unop(Iop_Not1,
32400 binop(Iop_CmpLE32S,
32401 mkU32(0x0), getIReg(rt))),
32402 imm, &dres);
32404 } else { /* BLTC */
32405 DIP("bltc r%u, r%u, %u", rs, rt, imm);
32406 if (mode64) {
32407 dis_branch_compact(False,
32408 unop(Iop_Not1,
32409 binop(Iop_CmpLE64S,
32410 getIReg(rt), getIReg(rs))),
32411 imm, &dres);
32412 } else {
32413 dis_branch_compact(False,
32414 unop(Iop_Not1,
32415 binop(Iop_CmpLE32S,
32416 getIReg(rt), getIReg(rs))),
32417 imm, &dres);
32420 } else {
32421 ILLEGAL_INSTRUCTON;
32423 break;
32425 case 0x06: /* BLEZ, BLEZALC, BGEZALC, BGEUC */
32426 if (rt == 0) { /* BLEZ */
32427 DIP("blez r%u, %u", rs, imm);
32428 if (mode64)
32429 dis_branch(False, binop(Iop_CmpLE64S, getIReg(rs), mkU64(0x0)),
32430 imm, &bstmt);
32431 else
32432 dis_branch(False, binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x0)), imm,
32433 &bstmt);
32434 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
32435 if (rs == 0) { /* BLEZALC */
32436 DIP("blezalc r%u, %u", rt, imm);
32437 if (mode64)
32438 dis_branch_compact(True,
32439 binop(Iop_CmpLE64S, getIReg(rt), mkU64(0x0)),
32440 imm, &dres);
32441 else
32442 dis_branch_compact(True,
32443 binop(Iop_CmpLE32S, getIReg(rt), mkU32(0x0)),
32444 imm, &dres);
32445 } else if (rt == rs) {/* BGEZALC */
32446 DIP("bgezalc r%u, %u", rt, imm);
32447 if (mode64)
32448 dis_branch_compact(True,
32449 binop(Iop_CmpLE64S, mkU64(0x0), getIReg(rt)),
32450 imm, &dres);
32451 else
32452 dis_branch_compact(True,
32453 binop(Iop_CmpLE32S, mkU32(0x0), getIReg(rt)),
32454 imm, &dres);
32455 } else { /* BGEUC */
32456 DIP("bgeuc r%u, r%u, %u", rt, rs, imm);
32457 if (mode64)
32458 dis_branch_compact(False,
32459 unop(Iop_Not1,
32460 binop(Iop_CmpLT64U,
32461 getIReg(rs), getIReg(rt))),
32462 imm, &dres);
32463 else
32464 dis_branch_compact(False,
32465 unop(Iop_Not1,
32466 binop(Iop_CmpLT32U,
32467 getIReg(rs), getIReg(rt))),
32468 imm, &dres);
32470 } else {
32471 ILLEGAL_INSTRUCTON;
32473 break;
32475 case 0x16: /* BLEZL, BLEZC, BGEZC, BGEC */
32476 if (rt == 0) { /* BLEZL */
32477 DIP("blezl r%u, %u", rs, imm);
32478 lastn = dis_branch_likely(unop(Iop_Not1, (binop(mode64 ? Iop_CmpLE64S :
32479 Iop_CmpLE32S, getIReg(rs), mode64 ?
32480 mkU64(0x0) : mkU32(0x0)))), imm);
32481 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
32482 if (rs == 0) { /* BLEZC */
32483 DIP("blezc r%u, %u", rt, imm);
32484 if (mode64) {
32485 dis_branch_compact(False,
32486 binop(Iop_CmpLE64S, getIReg(rt), mkU64(0x0)),
32487 imm, &dres);
32488 } else {
32489 dis_branch_compact(False,
32490 binop(Iop_CmpLE32S, getIReg(rt), mkU32(0x0)),
32491 imm, &dres);
32493 } else if (rt == rs) { /* BGEZC */
32494 DIP("bgezc r%u, %u", rt, imm);
32495 if (mode64) {
32496 dis_branch_compact(False,
32497 binop(Iop_CmpLE64S, mkU64(0x0), getIReg(rt)),
32498 imm, &dres);
32499 } else {
32500 dis_branch_compact(False,
32501 binop(Iop_CmpLE32S, mkU32(0x0), getIReg(rt)),
32502 imm, &dres);
32504 } else { /* BGEC */
32505 DIP("bgec r%u, r%u, %u", rs, rt, imm);
32506 if (mode64) {
32507 dis_branch_compact(False,
32508 binop(Iop_CmpLE64S, getIReg(rt), getIReg(rs)),
32509 imm, &dres);
32510 } else {
32511 dis_branch_compact(False,
32512 binop(Iop_CmpLE32S, getIReg(rt), getIReg(rs)),
32513 imm, &dres);
32516 } else {
32517 ILLEGAL_INSTRUCTON;
32519 break;
32521 #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev < 6))
32522 case 0x08: { /* ADDI */
32523 DIP("addi r%u, r%u, %u", rt, rs, imm);
32524 IRTemp tmpRs32 = newTemp(Ity_I32);
32525 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
32527 t0 = newTemp(Ity_I32);
32528 t1 = newTemp(Ity_I32);
32529 t2 = newTemp(Ity_I32);
32530 t3 = newTemp(Ity_I32);
32531 t4 = newTemp(Ity_I32);
32532 /* dst = src0 + sign(imm)
32533 if(sign(src0 ) != sign(imm ))
32534 goto no overflow;
32535 if(sign(dst) == sign(src0 ))
32536 goto no overflow;
32537 we have overflow! */
32539 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32),
32540 mkU32(extend_s_16to32(imm))));
32541 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32),
32542 mkU32(extend_s_16to32(imm))));
32543 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
32544 mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
32546 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
32547 assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
32548 mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
32550 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
32551 mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
32552 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
32553 IRConst_U32(guest_PC_curr_instr + 4),
32554 OFFB_PC));
32556 putIReg(rt, mkWidenFrom32(ty, mkexpr(t0), True));
32557 break;
32559 #elif defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
32560 case 0x08: { /* BEQZALC, BEQC, BOVC */
32561 if (rs == 0) { /* BEQZALC */
32562 DIP("beqzalc r%u, %u", rt, imm);
32563 if (mode64) {
32564 dis_branch_compact(True,
32565 binop(Iop_CmpEQ64, getIReg(rt), mkU64(0x0)),
32566 imm, &dres);
32567 } else {
32568 dis_branch_compact(True,
32569 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x0)),
32570 imm, &dres);
32572 } else if (rs < rt) { /* BEQC */
32573 DIP("beqc r%u, r%u, %u",rs, rt, imm);
32574 if (mode64) {
32575 dis_branch_compact(False,
32576 binop(Iop_CmpEQ64, getIReg(rt), getIReg(rs)),
32577 imm, &dres);
32578 } else {
32579 dis_branch_compact(False,
32580 binop(Iop_CmpEQ32, getIReg(rt), getIReg(rs)),
32581 imm, &dres);
32583 } else { /* BOVC */
32584 DIP("bovc r%u, r%u, %u",rs, rt, imm);
32585 if (mode64) {
32586 t0 = newTemp(Ity_I32);
32587 t1 = newTemp(Ity_I32);
32588 t2 = newTemp(Ity_I32);
32589 t3 = newTemp(Ity_I32);
32590 assign(t0, IRExpr_ITE(binop(Iop_CmpLT64S,
32591 getIReg(rt),
32592 mkU64(0xffffffff80000000ULL)),
32593 mkU32(1),
32594 IRExpr_ITE(binop(Iop_CmpLT64S,
32595 getIReg(rt),
32596 mkU64(0x7FFFFFFFULL)),
32597 mkU32(0),mkU32(1))));
32598 assign(t1, IRExpr_ITE(binop(Iop_CmpLT64S,
32599 getIReg(rs),
32600 mkU64(0xffffffff80000000ULL)),
32601 mkU32(1),
32602 IRExpr_ITE(binop(Iop_CmpLT64S,
32603 getIReg(rs),
32604 mkU64(0x7FFFFFFFULL)),
32605 mkU32(0), mkU32(1))));
32606 assign(t2, IRExpr_ITE(binop(Iop_CmpLT64S,
32607 binop(Iop_Add64,
32608 getIReg(rt), getIReg(rs)),
32609 mkU64(0xffffffff80000000ULL)),
32610 mkU32(1),
32611 IRExpr_ITE(binop(Iop_CmpLT64S,
32612 binop(Iop_Add64,
32613 getIReg(rt),
32614 getIReg(rs)),
32615 mkU64(0x7FFFFFFFULL)),
32616 mkU32(0), mkU32(1))));
32617 assign(t3, binop(Iop_Add32,
32618 mkexpr(t0),
32619 binop(Iop_Add32, mkexpr(t1), mkexpr(t2))));
32620 dis_branch_compact(False,
32621 binop(Iop_CmpNE32, mkexpr(t3), mkU32(0)),
32622 imm, &dres);
32623 } else {
32624 IRTemp tmpRs32 = newTemp(Ity_I32);
32625 IRTemp tmpRt32 = newTemp(Ity_I32);
32626 assign(tmpRs32, getIReg(rs));
32627 assign(tmpRt32, getIReg(rt));
32629 t0 = newTemp(Ity_I32);
32630 t1 = newTemp(Ity_I32);
32631 t2 = newTemp(Ity_I32);
32632 t3 = newTemp(Ity_I32);
32633 t4 = newTemp(Ity_I32);
32634 /* dst = src0 + src1
32635 if (sign(src0 ) != sign(src1 ))
32636 goto no overflow;
32637 if (sign(dst) == sign(src0 ))
32638 goto no overflow;
32639 we have overflow! */
32641 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
32642 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
32643 assign(t2, unop(Iop_1Uto32,
32644 binop(Iop_CmpEQ32,
32645 binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
32646 mkU32(0x80000000))));
32648 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
32649 assign(t4, unop(Iop_1Uto32,
32650 binop(Iop_CmpNE32,
32651 binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
32652 mkU32(0x80000000))));
32654 dis_branch_compact(False, binop(Iop_CmpEQ32,
32655 binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
32656 mkU32(0)), imm, &dres);
32659 break;
32660 /* In documentation for BEQC stands rs > rt and for BOVC stands rs >= rt! */
32662 #endif
32664 case 0x09: /* ADDIU */
32665 DIP("addiu r%u, r%u, %u", rt, rs, imm);
32666 if (mode64) {
32667 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Add32,
32668 mkNarrowTo32(ty, getIReg(rs)),mkU32(extend_s_16to32(imm))),
32669 True));
32670 } else
32671 putIReg(rt, binop(Iop_Add32, getIReg(rs),mkU32(extend_s_16to32(imm))));
32672 break;
32673 case 0x0C: /* ANDI */
32674 DIP("andi r%u, r%u, %u", rt, rs, imm);
32675 if (mode64) {
32676 ALUI_PATTERN64(Iop_And64);
32677 } else {
32678 ALUI_PATTERN(Iop_And32);
32680 break;
32682 case 0x0E: /* XORI */
32683 DIP("xori r%u, r%u, %u", rt, rs, imm);
32684 if (mode64) {
32685 ALUI_PATTERN64(Iop_Xor64);
32686 } else {
32687 ALUI_PATTERN(Iop_Xor32);
32689 break;
32691 case 0x0D: /* ORI */
32692 DIP("ori r%u, r%u, %u", rt, rs, imm);
32693 if (mode64) {
32694 ALUI_PATTERN64(Iop_Or64);
32695 } else {
32696 ALUI_PATTERN(Iop_Or32);
32698 break;
32700 case 0x0A: /* SLTI */
32701 DIP("slti r%u, r%u, %u", rt, rs, imm);
32702 if (mode64)
32703 putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
32704 mkU64(extend_s_16to64(imm)))));
32705 else
32706 putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
32707 mkU32(extend_s_16to32(imm)))));
32708 break;
32710 case 0x0B: /* SLTIU */
32711 DIP("sltiu r%u, r%u, %u", rt, rs, imm);
32712 if (mode64)
32713 putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
32714 mkU64(extend_s_16to64(imm)))));
32715 else
32716 putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
32717 mkU32(extend_s_16to32(imm)))));
32718 break;
32720 #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev < 6))
32721 case 0x18: { /* Doubleword Add Immidiate - DADDI; MIPS64 */
32722 DIP("daddi r%u, r%u, %u", rt, rs, imm);
32723 IRTemp tmpRs64 = newTemp(Ity_I64);
32724 assign(tmpRs64, getIReg(rs));
32726 t0 = newTemp(Ity_I64);
32727 t1 = newTemp(Ity_I64);
32728 t2 = newTemp(Ity_I64);
32729 t3 = newTemp(Ity_I64);
32730 t4 = newTemp(Ity_I64);
32731 /* dst = src0 + sign(imm)
32732 if(sign(src0 ) != sign(imm ))
32733 goto no overflow;
32734 if(sign(dst) == sign(src0 ))
32735 goto no overflow;
32736 we have overflow! */
32738 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64),
32739 mkU64(extend_s_16to64(imm))));
32740 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64),
32741 mkU64(extend_s_16to64(imm))));
32742 assign(t2, unop(Iop_1Sto64, binop(Iop_CmpEQ64, binop(Iop_And64,
32743 mkexpr(t1), mkU64(0x8000000000000000ULL)),
32744 mkU64(0x8000000000000000ULL))));
32746 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
32747 assign(t4, unop(Iop_1Sto64, binop(Iop_CmpNE64, binop(Iop_And64,
32748 mkexpr(t3), mkU64(0x8000000000000000ULL)),
32749 mkU64(0x8000000000000000ULL))));
32751 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
32752 mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
32753 IRConst_U64(guest_PC_curr_instr + 4),
32754 OFFB_PC));
32756 putIReg(rt, mkexpr(t0));
32757 break;
32759 #elif defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
32760 case 0x18: { /* BNEZALC, BNEC, BNVC */
32761 if (rs == 0) { /* BNEZALC */
32762 DIP("bnezalc r%u, %u", rt, imm);
32763 if (mode64) {
32764 dis_branch_compact(True,
32765 unop(Iop_Not1,
32766 binop(Iop_CmpEQ64, getIReg(rt), mkU64(0x0))),
32767 imm, &dres);
32768 } else {
32769 dis_branch_compact(True,
32770 unop(Iop_Not1,
32771 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x0))),
32772 imm, &dres);
32774 } else if (rs < rt) { /* BNEC */
32775 DIP("bnec r%u, %u", rt, imm);
32776 if (mode64) {
32777 dis_branch_compact(False,
32778 unop(Iop_Not1,
32779 binop(Iop_CmpEQ64,
32780 getIReg(rt), getIReg(rs))),
32781 imm, &dres);
32782 } else {
32783 dis_branch_compact(False,
32784 unop(Iop_Not1,
32785 binop(Iop_CmpEQ32,
32786 getIReg(rt), getIReg(rs))),
32787 imm, &dres);
32789 } else { /* BNVC */
32790 DIP("bnvc r%u, r%u, %u", rs, rt, imm);
32791 if (mode64) {
32792 t0 = newTemp(Ity_I32);
32793 t1 = newTemp(Ity_I32);
32794 t2 = newTemp(Ity_I32);
32795 t3 = newTemp(Ity_I32);
32796 assign(t0, IRExpr_ITE(binop(Iop_CmpLT64S,
32797 getIReg(rt),
32798 mkU64(0xffffffff80000000ULL)),
32799 mkU32(1),
32800 IRExpr_ITE(binop(Iop_CmpLT64S,
32801 getIReg(rt),
32802 mkU64(0x7FFFFFFFULL)),
32803 mkU32(0),mkU32(1))));
32804 assign(t1, IRExpr_ITE(binop(Iop_CmpLT64S,
32805 getIReg(rs),
32806 mkU64(0xffffffff80000000ULL)),
32807 mkU32(1),
32808 IRExpr_ITE(binop(Iop_CmpLT64S,
32809 getIReg(rs),
32810 mkU64(0x7FFFFFFFULL)),
32811 mkU32(0),mkU32(1))));
32812 assign(t2, IRExpr_ITE(binop(Iop_CmpLT64S,
32813 binop(Iop_Add64,
32814 getIReg(rt), getIReg(rs)),
32815 mkU64(0xffffffff80000000ULL)),
32816 mkU32(1),
32817 IRExpr_ITE(binop(Iop_CmpLT64S,
32818 binop(Iop_Add64,
32819 getIReg(rt),
32820 getIReg(rs)),
32821 mkU64(0x7FFFFFFFULL)),
32822 mkU32(0),mkU32(1))));
32823 assign(t3, binop(Iop_Add32,
32824 mkexpr(t0),
32825 binop(Iop_Add32, mkexpr(t1), mkexpr(t2))));
32826 dis_branch_compact(False,
32827 binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0)),
32828 imm, &dres);
32829 } else {
32830 IRTemp tmpRs32 = newTemp(Ity_I32);
32831 IRTemp tmpRt32 = newTemp(Ity_I32);
32833 assign(tmpRs32, getIReg(rs));
32834 assign(tmpRt32, getIReg(rt));
32835 t0 = newTemp(Ity_I32);
32836 t1 = newTemp(Ity_I32);
32837 t2 = newTemp(Ity_I32);
32838 t3 = newTemp(Ity_I32);
32839 t4 = newTemp(Ity_I32);
32840 /* dst = src0 + src1
32841 if (sign(src0 ) != sign(src1 ))
32842 goto no overflow;
32843 if (sign(dst) == sign(src0 ))
32844 goto no overflow;
32845 we have overflow! */
32847 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
32848 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
32849 assign(t2, unop(Iop_1Uto32,
32850 binop(Iop_CmpEQ32,
32851 binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
32852 mkU32(0x80000000))));
32854 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
32855 assign(t4, unop(Iop_1Uto32,
32856 binop(Iop_CmpNE32,
32857 binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
32858 mkU32(0x80000000))));
32860 dis_branch_compact(False, binop(Iop_CmpNE32 ,
32861 binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
32862 mkU32(0)), imm, &dres);
32865 break;
32867 #endif
32869 case 0x19: /* Doubleword Add Immidiate Unsigned - DADDIU; MIPS64 */
32870 DIP("daddiu r%u, r%u, %u", rt, rs, imm);
32871 putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
32872 break;
32874 case 0x1A: {
32875 /* Load Doubleword Left - LDL; MIPS64 */
32876 vassert(mode64);
32877 DIP("ldl r%u, %u(r%u)", rt, imm, rs);
32878 /* t1 = addr */
32879 #if defined (_MIPSEL)
32880 t1 = newTemp(Ity_I64);
32881 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
32882 #elif defined (_MIPSEB)
32883 t1 = newTemp(Ity_I64);
32884 assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
32885 mkU64(extend_s_16to64(imm)))));
32886 #endif
32887 /* t2 = word addr */
32888 /* t4 = addr mod 8 */
32889 LWX_SWX_PATTERN64_1;
32891 /* t3 = word content - shifted */
32892 t3 = newTemp(Ity_I64);
32893 assign(t3, binop(Iop_Shl64, load(Ity_I64, mkexpr(t2)),
32894 narrowTo(Ity_I8, binop(Iop_Shl64, binop(Iop_Sub64, mkU64(0x07),
32895 mkexpr(t4)), mkU8(3)))));
32897 /* rt content - adjusted */
32898 t5 = newTemp(Ity_I64);
32899 t6 = newTemp(Ity_I64);
32900 t7 = newTemp(Ity_I64);
32902 assign(t5, binop(Iop_Mul64, mkexpr(t4), mkU64(0x8)));
32904 assign(t6, binop(Iop_Shr64, mkU64(0x00FFFFFFFFFFFFFFULL),
32905 narrowTo(Ity_I8, mkexpr(t5))));
32907 assign(t7, binop(Iop_And64, getIReg(rt), mkexpr(t6)));
32909 putIReg(rt, binop(Iop_Or64, mkexpr(t7), mkexpr(t3)));
32910 break;
32913 case 0x1B: {
32914 /* Load Doubleword Right - LDR; MIPS64 */
32915 vassert(mode64);
32916 DIP("ldr r%u,%u(r%u)", rt, imm, rs);
32917 /* t1 = addr */
32918 #if defined (_MIPSEL)
32919 t1 = newTemp(Ity_I64);
32920 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
32921 #elif defined (_MIPSEB)
32922 t1 = newTemp(Ity_I64);
32923 assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
32924 mkU64(extend_s_16to64(imm)))));
32925 #endif
32926 /* t2 = word addr */
32927 /* t4 = addr mod 8 */
32928 LWX_SWX_PATTERN64_1;
32930 /* t3 = word content - shifted */
32931 t3 = newTemp(Ity_I64);
32932 assign(t3, binop(Iop_Shr64, load(Ity_I64, mkexpr(t2)),
32933 narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(3)))));
32935 /* rt content - adjusted */
32936 t5 = newTemp(Ity_I64);
32937 assign(t5, binop(Iop_And64, getIReg(rt), unop(Iop_Not64,
32938 binop(Iop_Shr64, mkU64(0xFFFFFFFFFFFFFFFFULL),
32939 narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(0x3)))))));
32941 putIReg(rt, binop(Iop_Or64, mkexpr(t5), mkexpr(t3)));
32942 break;
32945 case 0x27: /* Load Word unsigned - LWU; MIPS64 */
32946 DIP("lwu r%u,%u(r%u)", rt, imm, rs);
32947 LOAD_STORE_PATTERN;
32949 putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), False));
32950 break;
32952 case 0x30: /* LL */
32953 DIP("ll r%u, %u(r%u)", rt, imm, rs);
32954 LOAD_STORE_PATTERN;
32955 if (abiinfo->guest__use_fallback_LLSC) {
32956 t2 = newTemp(ty);
32957 assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
32958 putLLaddr(mkexpr(t1));
32959 putLLdata(mkexpr(t2));
32960 putIReg(rt, mkexpr(t2));
32961 } else {
32962 t2 = newTemp(Ity_I32);
32963 stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
32964 putIReg(rt, mkWidenFrom32(ty, mkexpr(t2), True));
32966 break;
32968 case 0x34: /* Load Linked Doubleword - LLD; MIPS64 */
32969 DIP("lld r%u, %u(r%u)", rt, imm, rs);
32970 if (mode64) {
32971 LOAD_STORE_PATTERN;
32972 t2 = newTemp(Ity_I64);
32973 if (abiinfo->guest__use_fallback_LLSC) {
32974 assign(t2, load(Ity_I64, mkexpr(t1)));
32975 putLLaddr(mkexpr(t1));
32976 putLLdata(mkexpr(t2));
32977 } else {
32978 stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
32980 putIReg(rt, mkexpr(t2));
32981 } else {
32982 ILLEGAL_INSTRUCTON;
32984 break;
32986 case 0x38: /* SC */
32987 DIP("sc r%u, %u(r%u)", rt, imm, rs);
32988 t2 = newTemp(Ity_I1);
32989 LOAD_STORE_PATTERN;
32990 if (abiinfo->guest__use_fallback_LLSC) {
32991 t3 = newTemp(Ity_I32);
32992 assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
32993 mkexpr(t1), getLLaddr()));
32994 assign(t3, mkNarrowTo32(ty, getIReg(rt)));
32995 putLLaddr(LLADDR_INVALID);
32996 putIReg(rt, getIReg(0));
32998 mips_next_insn_if(mkexpr(t2));
33000 t4 = newTemp(Ity_I32);
33001 t5 = newTemp(Ity_I32);
33003 assign(t5, mkNarrowTo32(ty, getLLdata()));
33005 stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
33006 MIPS_IEND, mkexpr(t1), /* addr */
33007 NULL, mkexpr(t5), /* expected value */
33008 NULL, mkexpr(t3) /* new value */)));
33010 putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32,
33011 binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5))));
33012 } else {
33013 stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1),
33014 mkNarrowTo32(ty, getIReg(rt))));
33015 putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32, mkexpr(t2)));
33017 break;
33019 case 0x3C: /* Store Conditional Doubleword - SCD; MIPS64 */
33020 DIP("scd r%u, %u(r%u)", rt, imm, rs);
33021 if (mode64) {
33022 t2 = newTemp(Ity_I1);
33023 LOAD_STORE_PATTERN;
33024 if (abiinfo->guest__use_fallback_LLSC) {
33025 t3 = newTemp(Ity_I64);
33026 assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr()));
33027 assign(t3, getIReg(rt));
33028 putLLaddr(LLADDR_INVALID);
33029 putIReg(rt, getIReg(0));
33031 mips_next_insn_if(mkexpr(t2));
33033 t4 = newTemp(Ity_I64);
33034 t5 = newTemp(Ity_I64);
33036 assign(t5, getLLdata());
33038 stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
33039 MIPS_IEND, mkexpr(t1), /* addr */
33040 NULL, mkexpr(t5), /* expected value */
33041 NULL, mkexpr(t3) /* new value */)));
33043 putIReg(rt, unop(Iop_1Uto64,
33044 binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5))));
33045 } else {
33046 stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), getIReg(rt)));
33047 putIReg(rt, unop(Iop_1Uto64, mkexpr(t2)));
33049 } else {
33050 ILLEGAL_INSTRUCTON;
33052 break;
33054 case 0x37: /* Load Doubleword - LD; MIPS64 */
33055 DIP("ld r%u, %u(r%u)", rt, imm, rs);
33056 LOAD_STORE_PATTERN;
33057 putIReg(rt, load(Ity_I64, mkexpr(t1)));
33058 break;
33060 case 0x3F: /* Store Doubleword - SD; MIPS64 */
33061 DIP("sd r%u, %u(r%u)", rt, imm, rs);
33062 LOAD_STORE_PATTERN;
33063 store(mkexpr(t1), getIReg(rt));
33064 break;
33066 case 0x32: /* Branch on Bit Clear - BBIT0; Cavium OCTEON */
33067 /* Cavium Specific instructions. */
33068 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
33069 DIP("bbit0 r%u, 0x%x, %x", rs, rt, imm);
33070 t0 = newTemp(Ity_I32);
33071 t1 = newTemp(Ity_I32);
33072 assign(t0, mkU32(0x1));
33073 assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
33074 dis_branch(False, binop(Iop_CmpEQ32,
33075 binop(Iop_And32,
33076 mkexpr(t1),
33077 mkNarrowTo32(ty, getIReg(rs))),
33078 mkU32(0x0)),
33079 imm, &bstmt);
33080 } else if (archinfo->hwcaps & VEX_MIPS_CPU_ISA_M32R6) { /* BC */
33081 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
33082 DIP("bc %x", instr_index & 0x3FFFFFF);
33083 if (mode64) {
33084 t0 = newTemp(Ity_I64);
33085 assign(t0, mkU64(guest_PC_curr_instr +
33086 ((extend_s_26to64(instr_index & 0x3FFFFFF) + 1 ) << 2)));
33087 } else {
33088 t0 = newTemp(Ity_I32);
33089 assign(t0, mkU32(guest_PC_curr_instr +
33090 ((extend_s_26to32(instr_index & 0x3FFFFFF) + 1) << 2)));
33092 putPC(mkexpr(t0));
33093 dres.whatNext = Dis_StopHere;
33094 dres.jk_StopHere = Ijk_Boring;
33095 } else {
33096 ILLEGAL_INSTRUCTON;
33098 } else {
33099 goto decode_failure;
33101 break;
33102 case 0x36: /* Branch on Bit Clear Plus 32 - BBIT032; Cavium OCTEON */
33103 /* Cavium Specific instructions. */
33104 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
33105 DIP("bbit032 r%u, 0x%x, %x", rs, rt, imm);
33106 t0 = newTemp(Ity_I64);
33107 t1 = newTemp(Ity_I8); /* Shift. */
33108 t2 = newTemp(Ity_I64);
33109 assign(t0, mkU64(0x1));
33110 assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
33111 assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
33112 dis_branch(False, binop(Iop_CmpEQ64,
33113 binop(Iop_And64,
33114 mkexpr(t2),
33115 getIReg(rs)),
33116 mkU64(0x0)),
33117 imm, &bstmt);
33118 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
33119 if (rs == 0) { /* JIC */
33120 DIP("jic r%u, %u", rt, instr_index & 0xFFFF);
33121 if (mode64) {
33122 t0 = newTemp(Ity_I64);
33123 assign(t0, binop(Iop_Add64, getIReg(rt),
33124 mkU64(extend_s_16to64((instr_index & 0xFFFF)))));
33125 } else {
33126 t0 = newTemp(Ity_I32);
33127 assign(t0, binop(Iop_Add32, getIReg(rt),
33128 mkU32(extend_s_16to32((instr_index & 0xFFFF)))));
33130 putPC(mkexpr(t0));
33131 dres.whatNext = Dis_StopHere;
33132 dres.jk_StopHere = Ijk_Boring;
33133 } else { /* BEQZC */
33134 DIP("beqzc r%u, %u", rs, imm);
33135 dres.jk_StopHere = Ijk_Boring;
33136 dres.whatNext = Dis_StopHere;
33137 ULong branch_offset;
33138 t0 = newTemp(Ity_I1);
33139 if (mode64) {
33140 branch_offset = extend_s_23to64((instr_index& 0x1fffff) << 2);
33141 assign(t0, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0x0)));
33142 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
33143 IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
33144 OFFB_PC));
33145 putPC(mkU64(guest_PC_curr_instr + 4));
33146 } else {
33147 branch_offset = extend_s_23to32((instr_index& 0x1fffff) << 2);
33148 assign(t0, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x0)));
33149 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
33150 IRConst_U32(guest_PC_curr_instr + 4 +
33151 (UInt) branch_offset), OFFB_PC));
33152 putPC(mkU32(guest_PC_curr_instr + 4));
33155 } else {
33156 ILLEGAL_INSTRUCTON;
33158 break;
33159 case 0x3A: /* Branch on Bit Set - BBIT1; Cavium OCTEON */
33160 /* Cavium Specific instructions. */
33161 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
33162 DIP("bbit1 r%u, 0x%x, %x", rs, rt, imm);
33163 t0 = newTemp(Ity_I32);
33164 t1 = newTemp(Ity_I32);
33165 assign(t0, mkU32(0x1));
33166 assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
33167 dis_branch(False, binop(Iop_CmpNE32,
33168 binop(Iop_And32,
33169 mkexpr(t1),
33170 mkNarrowTo32(ty, getIReg(rs))),
33171 mkU32(0x0)),
33172 imm, &bstmt);
33173 } else if (archinfo->hwcaps & VEX_MIPS_CPU_ISA_M32R6) {/* BALC */
33174 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
33175 DIP("balc %x", instr_index & 0x3FFFFFF);
33176 if (mode64) {
33177 t0 = newTemp(Ity_I64);
33178 assign(t0, mkU64(guest_PC_curr_instr + ((extend_s_26to64(instr_index & 0x3FFFFFF)+1)<<2)));
33179 putIReg(31, mkU64(guest_PC_curr_instr + 4));
33180 } else {
33181 t0 = newTemp(Ity_I32);
33182 assign(t0, mkU32(guest_PC_curr_instr+((extend_s_26to32(instr_index & 0x3FFFFFF)+1)<<2)));
33183 putIReg(31, mkU32(guest_PC_curr_instr + 4));
33185 putPC(mkexpr(t0));
33186 dres.whatNext = Dis_StopHere;
33187 dres.jk_StopHere = Ijk_Call;
33188 } else {
33189 ILLEGAL_INSTRUCTON;
33191 } else {
33192 goto decode_failure;
33194 break;
33195 case 0x3E: /* Branch on Bit Set Plus 32 - BBIT132; Cavium OCTEON */
33196 /* Cavium Specific instructions. */
33197 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
33198 DIP("bbit132 r%u, 0x%x, %x", rs, rt, imm);
33199 t0 = newTemp(Ity_I64);
33200 t1 = newTemp(Ity_I8); /* Shift. */
33201 t2 = newTemp(Ity_I64);
33202 assign(t0, mkU64(0x1));
33203 assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
33204 assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
33205 dis_branch(False, binop(Iop_CmpNE64,
33206 binop(Iop_And64,
33207 mkexpr(t2),
33208 getIReg(rs)),
33209 mkU64(0x0)),
33210 imm, &bstmt);
33211 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
33212 if (rs == 0) {/* JIALC */
33213 DIP("jialc r%u, %u", rt, instr_index & 0xFFFF);
33214 if (rs) goto decode_failure;
33215 if (mode64) {
33216 t0 = newTemp(Ity_I64);
33217 assign(t0, binop(Iop_Add64, getIReg(rt),
33218 mkU64(extend_s_16to64((instr_index & 0xFFFF)))));
33219 putIReg(31, mkU64(guest_PC_curr_instr + 4));
33220 } else {
33221 t0 = newTemp(Ity_I32);
33222 assign(t0, binop(Iop_Add32, getIReg(rt),
33223 mkU32(extend_s_16to32((instr_index & 0xFFFF)))));
33224 putIReg(31, mkU32(guest_PC_curr_instr + 4));
33226 putPC(mkexpr(t0));
33227 dres.whatNext = Dis_StopHere;
33228 dres.jk_StopHere = Ijk_Call;
33229 } else { /* BNEZC */
33230 DIP("bnezc r%u, %u", rs, imm);
33231 dres.jk_StopHere = Ijk_Boring;
33232 dres.whatNext = Dis_StopHere;
33233 ULong branch_offset;
33234 t0 = newTemp(Ity_I1);
33235 if (mode64) {
33236 branch_offset = extend_s_23to64((instr_index& 0x1fffff) << 2);
33237 assign(t0, unop(Iop_Not1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0x0))));
33238 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
33239 IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
33240 OFFB_PC));
33241 putPC(mkU64(guest_PC_curr_instr + 4));
33242 } else {
33243 branch_offset = extend_s_23to32((instr_index& 0x1fffff) << 2);
33244 assign(t0, unop(Iop_Not1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x0))));
33245 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
33246 IRConst_U32(guest_PC_curr_instr + 4 +
33247 (UInt) branch_offset), OFFB_PC));
33248 putPC(mkU32(guest_PC_curr_instr + 4));
33251 } else {
33252 goto decode_failure;
33254 break;
33256 case 0x1D: /* DAUI */
33257 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
33258 DIP("daui r%u, r%u, %x", rt, rs, imm);
33259 putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_32to64(imm << 16))));
33260 } else {
33261 ILLEGAL_INSTRUCTON;
33263 break;
33265 case 0x1E: /* MIPS MSA (SIMD) */
33266 if (has_msa) {
33267 Int retVal = disMSAInstr_MIPS_WRK(cins);
33268 if (retVal == 0) {
33269 break;
33270 } else if (retVal == -2) {
33271 ILLEGAL_INSTRUCTON
33272 break;
33275 vex_printf("Error occured while trying to decode MIPS MSA "
33276 "instruction.\nYour platform probably doesn't support "
33277 "MIPS MSA (SIMD) ASE.\n");
33279 default:
33280 goto decode_failure;
33282 decode_failure_dsp:
33283 vex_printf("Error occured while trying to decode MIPS32 DSP "
33284 "instruction.\nYour platform probably doesn't support "
33285 "MIPS32 DSP ASE.\n");
33286 decode_failure:
33287 /* All decode failures end up here. */
33288 if (sigill_diag)
33289 vex_printf("vex mips->IR: unhandled instruction bytes: "
33290 "0x%x 0x%x 0x%x 0x%x\n",
33291 (UInt) getIByte(delta_start + 0),
33292 (UInt) getIByte(delta_start + 1),
33293 (UInt) getIByte(delta_start + 2),
33294 (UInt) getIByte(delta_start + 3));
33296 /* Tell the dispatcher that this insn cannot be decoded, and so has
33297 not been executed, and (is currently) the next to be executed.
33298 EIP should be up-to-date since it made so at the start bnezof each
33299 insn, but nevertheless be paranoid and update it again right
33300 now. */
33301 if (mode64) {
33302 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_PC),
33303 mkU64(guest_PC_curr_instr)));
33304 jmp_lit64(&dres, Ijk_NoDecode, guest_PC_curr_instr);
33305 } else {
33306 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_PC),
33307 mkU32(guest_PC_curr_instr)));
33308 jmp_lit32(&dres, Ijk_NoDecode, guest_PC_curr_instr);
33310 dres.whatNext = Dis_StopHere;
33311 dres.len = 0;
33312 return dres;
33313 } /* switch (opc) for the main (primary) opcode switch. */
33315 /* All MIPS insn have 4 bytes */
33317 if (delay_slot_branch) {
33318 delay_slot_branch = False;
33319 stmt(bstmt);
33320 bstmt = NULL;
33321 if (mode64)
33322 putPC(mkU64(guest_PC_curr_instr + 4));
33323 else
33324 putPC(mkU32(guest_PC_curr_instr + 4));
33325 dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
33326 Ijk_Call : Ijk_Boring;
33329 if (likely_delay_slot) {
33330 dres.jk_StopHere = Ijk_Boring;
33331 dres.whatNext = Dis_StopHere;
33332 putPC(lastn);
33333 lastn = NULL;
33335 if (delay_slot_jump) {
33336 putPC(lastn);
33337 lastn = NULL;
33338 dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
33339 Ijk_Call : Ijk_Boring;
33342 decode_success:
33343 /* All decode successes end up here. */
33344 switch (dres.whatNext) {
33345 case Dis_Continue:
33346 if (mode64)
33347 putPC(mkU64(guest_PC_curr_instr + 4));
33348 else
33349 putPC(mkU32(guest_PC_curr_instr + 4));
33350 break;
33351 case Dis_ResteerU:
33352 case Dis_ResteerC:
33353 if (mode64)
33354 putPC(mkU64(dres.continueAt));
33355 else
33356 putPC(mkU32(dres.continueAt));
33357 break;
33358 case Dis_StopHere:
33359 break;
33360 default:
33361 vassert(0);
33362 break;
33365 /* On MIPS we need to check if the last instruction in block is branch or
33366 jump. */
33367 if (((vex_control.guest_max_insns - 1) == (delta + 4) / 4)
33368 && (dres.whatNext != Dis_StopHere))
33369 if (branch_or_jump(guest_code + delta + 4)) {
33370 dres.whatNext = Dis_StopHere;
33371 dres.jk_StopHere = Ijk_Boring;
33372 if (mode64)
33373 putPC(mkU64(guest_PC_curr_instr + 4));
33374 else
33375 putPC(mkU32(guest_PC_curr_instr + 4));
33377 dres.len = 4;
33379 DIP("\n");
33381 return dres;
33385 /*------------------------------------------------------------*/
33386 /*--- Top-level fn ---*/
33387 /*------------------------------------------------------------*/
33389 /* Disassemble a single instruction into IR. The instruction
33390 is located in host memory at &guest_code[delta]. */
33391 DisResult disInstr_MIPS( IRSB* irsb_IN,
33392 Bool (*resteerOkFn) ( void *, Addr ),
33393 Bool resteerCisOk,
33394 void* callback_opaque,
33395 const UChar* guest_code_IN,
33396 Long delta,
33397 Addr guest_IP,
33398 VexArch guest_arch,
33399 const VexArchInfo* archinfo,
33400 const VexAbiInfo* abiinfo,
33401 VexEndness host_endness_IN,
33402 Bool sigill_diag_IN )
33404 DisResult dres;
33405 /* Set globals (see top of this file) */
33406 vassert(guest_arch == VexArchMIPS32 || guest_arch == VexArchMIPS64);
33408 mode64 = guest_arch != VexArchMIPS32;
33409 fp_mode64 = abiinfo->guest_mips_fp_mode & 1;
33410 fp_mode64_fre = abiinfo->guest_mips_fp_mode & 2;
33411 has_msa = VEX_MIPS_PROC_MSA(archinfo->hwcaps);
33413 vassert(VEX_MIPS_HOST_FP_MODE(archinfo->hwcaps) >= fp_mode64);
33415 guest_code = guest_code_IN;
33416 irsb = irsb_IN;
33417 host_endness = host_endness_IN;
33418 #if defined(VGP_mips32_linux)
33419 guest_PC_curr_instr = (Addr32)guest_IP;
33420 #elif defined(VGP_mips64_linux)
33421 guest_PC_curr_instr = (Addr64)guest_IP;
33422 #endif
33424 dres = disInstr_MIPS_WRK(resteerOkFn, resteerCisOk, callback_opaque,
33425 delta, archinfo, abiinfo, sigill_diag_IN);
33427 return dres;
33430 /*--------------------------------------------------------------------*/
33431 /*--- end guest_mips_toIR.c ---*/
33432 /*--------------------------------------------------------------------*/